Skip to content

Integrated Firebase Analitycs #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/lib/components/card/select_lang_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'package:mq_ci_keys/mq_ci_keys.dart';
import 'package:my_quran/app/app.dart';
import 'package:my_quran/core/core.dart';
import 'package:my_quran/l10n/l10.dart';

class SelectLangFromListViewBuilder extends StatelessWidget {
Expand All @@ -22,6 +23,10 @@ class SelectLangFromListViewBuilder extends StatelessWidget {
key: Key(MqKeys.languageCode(locale.languageCode)),
title: Text(langName, locale: locale),
onTap: () async {
MqAnalytic.track(
AnalyticKey.selectLanguage,
params: {'language': locale.languageCode},
);
context.loaderOverlay.show();
await context.read<AuthCubit>().saveLocale(locale.languageCode);
if (context.mounted) context.loaderOverlay.hide();
Expand Down
34 changes: 34 additions & 0 deletions app/lib/core/analytics/mq_analytic.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:developer';

import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flutter/foundation.dart';
import 'package:my_quran/core/core.dart';

part 'mq_analytic_keys.dart';

@immutable
final class MqAnalytic {
const MqAnalytic._();

static Future<void> setUserProperty(String userName) async {
try {
if (kDebugMode) return;
await _analytics.setUserProperty(name: userName, value: null);
} catch (error, stackTrace) {
MqCrashlytics.report(error, stackTrace);
log('MqAnalytics setUserProperty error: $error, stackTrace: $stackTrace');
}
}

static void track(String event, {Map<String, dynamic>? params}) {
try {
if (kDebugMode) return;
_analytics.logEvent(name: event, parameters: params);
} catch (error, stackTrace) {
MqCrashlytics.report(error, stackTrace);
log('MqAnalytics track error: $error, stackTrace: $stackTrace');
}
}

static FirebaseAnalytics get _analytics => FirebaseAnalytics.instance;
}
39 changes: 39 additions & 0 deletions app/lib/core/analytics/mq_analytic_keys.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
part of 'mq_analytic.dart';

@immutable
final class AnalyticKey {
const AnalyticKey._();

// go - back
static const goGenderPage = 'go_gender_page';
static const goThemePage = 'go_theme_page';
static const goAboutUsPage = 'go_about_us_page';
static const goContactUsPage = 'go_contact_us_page';
static const goDevelopersPage = 'go_developers_page';
static const goDevMode = 'go_dev_mode';
static const goHatim = 'go_hatim';
static const goHatimReadPage = 'go_hatim_read_page';
static const goQuranReadByJuz = 'go_quran_read_by_juz';
static const goQuranReadBySurah = 'go_quran_read_by_surah';

// select - unselect
static const selectLanguage = 'select_language';
static const selectGender = 'select_gender';
static const selectThemeMode = 'select_theme_mode';
static const selectThemeColor = 'select_theme_color';
static const selectDevMode = 'select_dev_mode';
static const selectPage = 'select_page';
static const unselectPage = 'unselect_page';
static const selectHatimJuz = 'select_hatim_juz';
static const selectQuranAudioBySurah = 'select_quran_audio_by_surah';

// action
static const tapLogout = 'tap_logout';
static const tapLoginWithSoccial = 'tap_login_with_soccial';
static const tapPrivacyPolicy = 'tap_privacy_policy';
static const tapQuranReadSettings = 'tap_quran_read_settings';
static const showAmin = 'show_amin';

// refresh
static const refreshHomePage = 'refresh_home';
}
1 change: 1 addition & 0 deletions app/lib/core/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export 'exceptions/auth_exception.dart';
export 'exceptions/convert_exception.dart';
export 'launch/app_launch.dart';
export 'enums/fetch_status.dart';
export 'analytics/mq_analytic.dart';
10 changes: 7 additions & 3 deletions app/lib/core/crashlytics/mq_crashlytics.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';

@immutable
final class MqCrashlytics {
Expand All @@ -13,6 +13,7 @@ final class MqCrashlytics {
bool? printDetails,
bool fatal = false,
}) {
if (kDebugMode) return;
crashlytics.recordError(
exception,
stack,
Expand All @@ -27,14 +28,17 @@ final class MqCrashlytics {
FlutterErrorDetails flutterErrorDetails, {
bool fatal = false,
}) {
if (kDebugMode) return;
crashlytics.recordFlutterError(flutterErrorDetails, fatal: fatal);
}

static Future<void> setUserIdentifier(String identifier) {
static Future<void> setUserIdentifier(String identifier) async {
if (kDebugMode) return;
return crashlytics.setUserIdentifier(identifier);
}

static Future<void> setCrashlyticsCollectionEnabled({required bool enabled}) {
static Future<void> setCrashlyticsCollectionEnabled({required bool enabled}) async {
if (kDebugMode) return;
return crashlytics.setCrashlyticsCollectionEnabled(enabled);
}

Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "يرجى تحديد لغة.",
"male": "ذكر",
"next": "التالي",
"orSignInWith": "---أو تسجيل الدخول باستخدام---",
"signInWith": "---تسجيل الدخول ب---",
"pleaseWait": "يرجى الانتظار",
"privacyPolicy": " سياسة الخصوصية ",
"profileChangeTheme": "تثبيت موضوع",
Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "Please select a language.",
"male": "Male",
"next": "Next",
"orSignInWith": "---Or sign in with---",
"signInWith": "---Sign in with---",
"pleaseWait": "Please waiting",
"privacyPolicy": "Privacy Policy",
"profileChangeTheme": "Theme Installation",
Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_id.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "Pilih bahasa.",
"male": "Pria",
"next": "Lanjut",
"orSignInWith": "---Atau masuk dengan---",
"signInWith": "---Masuk dengan---",
"pleaseWait": "Silakan tunggu",
"privacyPolicy": " Kebijakan Privasi",
"profileChangeTheme": "Instalasi Tema",
Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_kk.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "Тілді таңдаңыз",
"male": "Eркек",
"next": "Келесі",
"orSignInWith": " ---Немесе кіруге мүмкіндік береді---",
"signInWith": " ---Жүйеге кіру---",
"pleaseWait": "Өтінемін, Күте тұрыңыз",
"privacyPolicy": " Құпиялылық саясаты",
"profileChangeTheme": "Тақырыпты орнату",
Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_ky.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "Сураныч тилди тандаңыз.",
"male": "Эркек",
"next": "Кийинки",
"orSignInWith": "---Же экинчи ыкма аркылуу кириңиз---",
"signInWith": "---Кирүү---",
"pleaseWait": "Сураныч, күтө туруңуз",
"privacyPolicy": "Конфиденциалдык саясат",
"profileChangeTheme": "Теманы орнотуу",
Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_ru.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "Пожалуйста, выберите язык",
"male": "Мужчина",
"next": "Следующий",
"orSignInWith": "---Или войти с помощью---",
"signInWith": "---Войти с помощью---",
"pleaseWait": "Пожалуйста, подождите",
"privacyPolicy": "Политика Конфиденциальности",
"profileChangeTheme": "Установка темы",
Expand Down
2 changes: 1 addition & 1 deletion app/lib/l10n/arb/app_tr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"loginPleaseSelectLang": "Lütfen bir dil seçin.",
"male": "Erkek",
"next": "Sonraki",
"orSignInWith": "---Veya ile giriş yap---",
"signInWith": "---Şununla giriş yap---",
"pleaseWait": "Lütfen bekleyin",
"privacyPolicy": "Gizlilik Politikası",
"profileChangeTheme": "Tema Kurulumu",
Expand Down
2 changes: 2 additions & 0 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:developer';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand All @@ -23,6 +24,7 @@ Future<void> main({AppConfig? appConfig}) async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);

await MqCrashlytics.setCrashlyticsCollectionEnabled(enabled: kDebugMode);

Expand Down
8 changes: 8 additions & 0 deletions app/lib/modules/dev_mode/presentation/dev_mode_view.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:my_quran/config/app_config.dart';
import 'package:my_quran/core/core.dart';
import 'package:my_quran/utils/show/alerts.dart';

class DevModeView extends StatefulWidget {
Expand Down Expand Up @@ -47,6 +48,13 @@ class _DevModeViewState extends State<DevModeView> {
const SizedBox(height: 40),
ElevatedButton(
onPressed: () async {
MqAnalytic.track(
AnalyticKey.selectDevMode,
params: {
'devDomain': _controller.text,
'isDevMode': isDevMode,
},
);
final appConfig = context.read<AppConfig>();
await appConfig.setDevMode(
devDomain: _controller.text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
import 'package:mq_ci_keys/mq_ci_keys.dart';

import 'package:my_quran/components/components.dart';
import 'package:my_quran/core/core.dart';
import 'package:my_quran/l10n/l10.dart';
import 'package:my_quran/modules/hatim/hatim.dart';
import 'package:my_quran/modules/modules.dart';
Expand Down Expand Up @@ -31,7 +32,7 @@ class HatimJusBottomSheet extends StatelessWidget {
return switch (juzPagesState) {
HatimJuzPagesInitial() => const Center(child: CircularProgressIndicator()),
HatimJuzPagesLoading() => const Center(child: CircularProgressIndicator()),
HatimJuzPagesFetched() => HatimPageGridLisrBuilder(juzPagesState.data),
HatimJuzPagesFetched() => HatimPageGridListBuilder(juzPagesState.data),
HatimJuzPagesFailed() => Center(child: Text('${juzPagesState.exception}')),
};
},
Expand Down Expand Up @@ -79,8 +80,8 @@ class HatimJusBottomSheet extends StatelessWidget {
}
}

class HatimPageGridLisrBuilder extends StatelessWidget {
const HatimPageGridLisrBuilder(this.items, {super.key});
class HatimPageGridListBuilder extends StatelessWidget {
const HatimPageGridListBuilder(this.items, {super.key});

final List<HatimPagesEntity> items;

Expand All @@ -100,8 +101,16 @@ class HatimPageGridLisrBuilder extends StatelessWidget {
? () {
final bloc = context.read<HatimBloc>();
if (e.status == HatimPageStatus.todo) {
MqAnalytic.track(
AnalyticKey.selectPage,
params: {'page': e.id},
);
bloc.add(SelectPageEvent(e.id));
} else if (e.mine) {
MqAnalytic.track(
AnalyticKey.unselectPage,
params: {'page': e.id},
);
bloc.add(UnSelectPageEvent(e.id));
}
}
Expand Down
4 changes: 4 additions & 0 deletions app/lib/modules/hatim/presentation/view/hatim_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class _HatimUIState extends State<HatimUI> {
final pageIds = pages.map((e) => e.id).toList();
final pageNumbers = pages.map((e) => e.number).toList();
context.read<HatimBloc>().add(SetInProgressPagesEvent(pageIds));
MqAnalytic.track(
AnalyticKey.goHatimReadPage,
params: {'pages': pageIds},
);
final value = await context.pushNamed<bool>(
AppRouter.hatimRead,
pathParameters: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mq_ci_keys/mq_ci_keys.dart';
import 'package:my_quran/core/core.dart';
import 'package:my_quran/l10n/l10.dart';
import 'package:my_quran/modules/modules.dart';
import 'package:my_quran/utils/urils.dart';
Expand Down Expand Up @@ -34,6 +35,10 @@ class HatimJuzListBuilder extends StatelessWidget {
],
),
onTap: () async {
MqAnalytic.track(
AnalyticKey.selectHatimJuz,
params: {'juzId': item.id},
);
final bloc = context.read<HatimBloc>();
await AppBottomSheet.showBottomSheet<void>(
context,
Expand Down
13 changes: 10 additions & 3 deletions app/lib/modules/home/presentation/view/home_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ class _HomeViewState extends State<HomeView> {
void initState() {
final homeCubit = context.read<HomeCubit>();
final authCubit = context.read<AuthCubit>();
final user = authCubit.state.user;
final validName = user?.username.replaceAll(RegExp(r'\W+'), '_');
if (homeCubit.state.status != FetchStatus.success && authCubit.state.user != null) {
MqCrashlytics.setUserIdentifier(
authCubit.state.user?.username ?? authCubit.state.user!.accessToken,
validName ?? user!.accessToken,
);
homeCubit.getData(authCubit.state.user!.accessToken);
MqAnalytic.setUserProperty(validName ?? user!.accessToken);
homeCubit.getData(user!.accessToken);
}
super.initState();
}
Expand Down Expand Up @@ -61,6 +64,7 @@ class HomeBody extends StatelessWidget {
final colorScheme = Theme.of(context).colorScheme;
return RefreshIndicator(
onRefresh: () async {
MqAnalytic.track(AnalyticKey.refreshHomePage);
if (context.read<AuthCubit>().state.user != null) {
await context.read<HomeCubit>().getData(context.read<AuthCubit>().state.user!.accessToken);
}
Expand Down Expand Up @@ -98,7 +102,10 @@ class HomeBody extends StatelessWidget {
child: CustomButton(
key: const Key(MqKeys.participantToHatim),
text: l10n.homeGoHatim,
onPressed: () => context.goNamed(AppRouter.hatim),
onPressed: () {
MqAnalytic.track(AnalyticKey.goHatim);
context.goNamed(AppRouter.hatim);
},
),
),
const SizedBox(height: 20),
Expand Down
6 changes: 5 additions & 1 deletion app/lib/modules/login/presentation/view/login_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:mq_ci_keys/mq_ci_keys.dart';

import 'package:my_quran/components/components.dart';
import 'package:my_quran/config/config.dart';
import 'package:my_quran/core/core.dart';
import 'package:my_quran/l10n/l10.dart';
import 'package:my_quran/modules/modules.dart';

Expand Down Expand Up @@ -50,7 +51,10 @@ class LoginBody extends StatelessWidget {
),
const SizedBox(height: 20),
InkWell(
onLongPress: () => context.pushNamed(AppRouter.devModeView),
onLongPress: () {
MqAnalytic.track(AnalyticKey.goDevMode);
context.pushNamed(AppRouter.devModeView);
},
child: DotsIndicator(
controller: controller,
itemCount: 2,
Expand Down
Loading
Loading