initFirebaseAndFcm function

Future<bool> initFirebaseAndFcm({
  1. required NotificationService? notificationService,
  2. required void onDeepLink(
    1. String route
    ),
  3. required bool isAllowedRoute(
    1. String route
    ),
})

Boots Firebase + FCM and wires up the deep-link handlers used by push notifications. Returns whether Firebase came up successfully — callers gate downstream work (e.g. token registration) on the result.

The web build replaces this with a no-op (see fcm_setup_stub.dart) so the firebase_core and firebase_messaging packages never reach the JS entry chunk.

Implementation

Future<bool> initFirebaseAndFcm({
  required NotificationService? notificationService,
  required void Function(String route) onDeepLink,
  required bool Function(String route) isAllowedRoute,
}) async {
  try {
    await Firebase.initializeApp();
    dev.log('Firebase ready', name: 'main');

    if (!kIsWeb) {
      // Route framework + uncaught async errors to Crashlytics. Without
      // these handlers, runtime red-screens like the navigator
      // `!keyReservation.contains(key)` assertion are invisible to anyone
      // except the user who hit them. Setting them once here, after
      // Firebase comes up, covers the rest of the app's lifetime.
      // Crashlytics is disabled in debug builds (per FlutterFire defaults)
      // so local crash reports stay out of the production dashboard.
      FlutterError.onError =
          FirebaseCrashlytics.instance.recordFlutterFatalError;
      PlatformDispatcher.instance.onError = (error, stack) {
        FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
        return true;
      };

      FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler);

      if (notificationService != null) {
        FirebaseMessaging.onMessage.listen((RemoteMessage message) {
          final notification = message.notification;
          if (notification != null) {
            notificationService.showFromPush(
              title: notification.title ?? 'DuTaTo',
              body: notification.body ?? '',
              route: message.data['route'] as String?,
            );
          }
        });
      }
    }

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      final route = message.data['route'] as String?;
      if (route != null && isAllowedRoute(route)) onDeepLink(route);
    });

    final initialMessage = await FirebaseMessaging.instance.getInitialMessage();
    if (initialMessage != null) {
      final route = initialMessage.data['route'] as String?;
      if (route != null && isAllowedRoute(route)) onDeepLink(route);
    }
    return true;
  } catch (e) {
    dev.log('Firebase init skipped: $e', name: 'main');
    return false;
  }
}