import 'dart:async'; import 'dart:developer'; import 'package:bloc/bloc.dart'; import 'package:chucker_flutter/chucker_flutter.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/widgets.dart'; import 'package:frontend_eccp_mobile/app/core/config/app_flavor.dart'; import 'package:frontend_eccp_mobile/app/core/di/injection.dart'; import 'package:frontend_eccp_mobile/app/core/navigation/app_resume_once.dart'; import 'package:frontend_eccp_mobile/app/core/navigation/settings_navigator.dart'; import 'package:frontend_eccp_mobile/app/core/notification/fcm_service.dart'; import 'package:frontend_eccp_mobile/app/core/services/bottom_sheet_service.dart'; import 'package:frontend_eccp_mobile/app/core/services/crashlytics_service.dart'; import 'package:frontend_eccp_mobile/app/core/services/location_permission_service.dart'; import 'package:frontend_eccp_mobile/app/core/utils/session_manager.dart'; import 'package:frontend_eccp_mobile/app/core/widgets/bottomsheet/app_bottom_sheet.dart'; import 'package:frontend_eccp_mobile/app/core/widgets/bottomsheet/appbottomsheet_controller.dart'; import 'package:frontend_eccp_mobile/modules/auth/login/data/model/user_session.dart'; class AppBlocObserver extends BlocObserver { const AppBlocObserver(); @override void onChange(BlocBase bloc, Change change) { super.onChange(bloc, change); log('onChange(${bloc.runtimeType}, $change)'); } @override void onError(BlocBase bloc, Object error, StackTrace stackTrace) { log('onError(${bloc.runtimeType}, $error, $stackTrace)'); super.onError(bloc, error, stackTrace); } } Future initSession() async { final session = getIt(); final token = await SessionManager.getToken(); final user = await SessionManager.getUser(); if (token != null && user != null) { session ..token = token ..user = user; } } Future bootstrap(FutureOr Function() builder) async { FlutterError.onError = (details) { log(details.exceptionAsString(), stackTrace: details.stack); }; WidgetsFlutterBinding.ensureInitialized(); await configureDependencies(); await Firebase.initializeApp(); await CrashlyticsService.init(); await FcmService.init(); await initSession(); Bloc.observer = const AppBlocObserver(); log('Running flavor: ${Flavor.name}'); if (!Flavor.isProd) { ChuckerFlutter.showOnRelease = true; ChuckerFlutter.showNotification = false; ChuckerFlutter.isDebugMode = true; } BottomSheetService.configure( noInternetBuilder: (context) => AppBottomSheet( controller: AppBottomSheetController(), icon: 'assets/images/img-no-internet.png', title: 'Eh, jaringannya hilang...', subTitle: 'Harap periksa kembali jaringan internetmu, coba lagi beberapa saat ya!', primaryText: 'Baik, dimengerti', onPrimaryPressed: () { Navigator.pop(context); }, ), serverErrorBuilder: (ctx) => AppBottomSheet( controller: AppBottomSheetController(), title: 'Mohon maaf kami sedang ada gangguan!', primaryText: 'Baik, dimengerti', icon: 'assets/images/img-server-error.png', subTitle: 'Saat ini permintaan kamu belum dapat diproses, coba lagi beberapa saat lagi ya!\nJika berlanjut, hubungi CS.', onPrimaryPressed: () { Navigator.pop(ctx); }, ), notFoundBuilder: (ctx) => AppBottomSheet( controller: AppBottomSheetController(), title: 'Opps, kamu tersesat', primaryText: 'Baik, dimengerti', icon: 'assets/images/img-not-found.png', subTitle: 'Mari kembali ke jalur semula, coba lagi beberapa saat lagi ya!\nJika berlanjut, hubungi CS.', onPrimaryPressed: () { Navigator.pop(ctx); }, ), sessionExpiredBuilder: (ctx) => AppBottomSheet( controller: AppBottomSheetController(), title: 'Sesi Berakhir', primaryText: 'Login Ulang', icon: 'assets/images/img-server-error.png', subTitle: 'Silakan login ulang untuk melanjutkan.', onPrimaryPressed: () { Navigator.pop(ctx); }, ), locationPermissionBuilder: ( ctx, { required onOpenSettings, VoidCallback? onRequestNow, }) { return AppBottomSheet( controller: AppBottomSheetController(), title: 'Permintaan Akses Lokasi', primaryText: 'Buka Pengaturan', icon: 'assets/images/img-location-permission.png', subTitle: 'E-CPP ingin meminta akses lokasi kamu agar paket yang diberikan lebih cocok untukmu!', onPrimaryPressed: () async { final resumeFut = waitRecheckOnNextResume(() async { if (await LocationPermissionService.recheckGranted()) { onOpenSettings(); } }); await SettingsNavigator.openAppSettings(); await resumeFut; if (!ctx.mounted) return; Navigator.pop(ctx); }, // onSecondary: onRequestNow, ); }, ); runApp(await builder()); }