mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Initialize Firebase at startup so iOS APNs token is captured
Firebase was only initialized lazily when the user toggled push on. On iOS the firebase_messaging plugin installs its APNs swizzling at app launch, but the delivered device token can only be forwarded to FCM if a FirebaseApp is already configured at that point. With lazy init there was none, so getAPNSToken() never resolved and enabling push failed with "Could not enable push". Add initFirebaseForPush() (mobile-only, idempotent) and call it from main() at launch. Extract a shared pushSupportedOnThisPlatform getter so isSupported and the initializer stay in sync; _ensureFirebase() now delegates to it as a safety net. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7d7f0197cd
commit
3d190e847e
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:frontend/theme/catppuccin_mocha_theme.dart';
|
||||
import 'package:frontend/utils/local_network_permission.dart';
|
||||
import 'package:frontend/utils/pref_utils.dart';
|
||||
import 'package:frontend/utils/push_service.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'navigation.dart';
|
||||
import 'theme/gruvbox_theme.dart';
|
||||
@@ -31,6 +32,15 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize Firebase at launch so the firebase_messaging plugin's iOS
|
||||
// APNs swizzling has a configured app to forward the device token to;
|
||||
// without this getAPNSToken() never resolves and enabling push fails.
|
||||
try {
|
||||
await initFirebaseForPush();
|
||||
} catch (e, stack) {
|
||||
debugPrint('Firebase init for push failed, continuing: $e\n$stack');
|
||||
}
|
||||
|
||||
// Settle iOS's local-network permission now, at launch, so it isn't
|
||||
// still being decided when the user first taps "Test" in settings.
|
||||
unawaited(requestLocalNetworkPermission());
|
||||
|
||||
@@ -6,6 +6,25 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import '../firebase_options.dart';
|
||||
import 'oott_api.dart';
|
||||
|
||||
/// Whether push is available on this platform/build (mobile only — FCM/APNs).
|
||||
/// Shared by [FirebasePushService.isSupported] and [initFirebaseForPush] so the
|
||||
/// two never drift.
|
||||
bool get pushSupportedOnThisPlatform =>
|
||||
!kIsWeb &&
|
||||
(defaultTargetPlatform == TargetPlatform.android ||
|
||||
defaultTargetPlatform == TargetPlatform.iOS);
|
||||
|
||||
/// Initializes Firebase at app startup on push-capable platforms. This must run
|
||||
/// at launch — the firebase_messaging plugin wires up iOS APNs swizzling in the
|
||||
/// AppDelegate at launch, and it can only forward the APNs device token to FCM
|
||||
/// if a FirebaseApp is already configured when iOS delivers it. Without this,
|
||||
/// `getAPNSToken()` never resolves and enabling push fails. No-op on web/desktop
|
||||
/// and if Firebase is already initialized.
|
||||
Future<void> initFirebaseForPush() async {
|
||||
if (!pushSupportedOnThisPlatform || Firebase.apps.isNotEmpty) return;
|
||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||
}
|
||||
|
||||
/// Per-device push enable/disable, behind an interface so the settings UI can be
|
||||
/// driven by a fake in tests without pulling in Firebase. Tapping a push only
|
||||
/// opens the app (no deep-link, no identifier); the in-app notification list
|
||||
@@ -47,24 +66,16 @@ class FirebasePushService implements PushService {
|
||||
bool _foregroundDisplayWired = false;
|
||||
|
||||
@override
|
||||
bool get isSupported =>
|
||||
!kIsWeb &&
|
||||
(defaultTargetPlatform == TargetPlatform.android ||
|
||||
defaultTargetPlatform == TargetPlatform.iOS);
|
||||
bool get isSupported => pushSupportedOnThisPlatform;
|
||||
|
||||
String get _platformName =>
|
||||
defaultTargetPlatform == TargetPlatform.iOS ? 'ios' : 'android';
|
||||
|
||||
Future<void> _ensureFirebase() async {
|
||||
// Options come from the committed firebase_options.dart rather than native
|
||||
// config files, so no google-services.json / GoogleService-Info.plist is
|
||||
// needed in the build.
|
||||
if (Firebase.apps.isEmpty) {
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Safety net in case startup init was skipped; normally Firebase is already
|
||||
// initialized at launch by initFirebaseForPush(). Options come from the
|
||||
// committed firebase_options.dart rather than native config files, so no
|
||||
// google-services.json / GoogleService-Info.plist is needed in the build.
|
||||
Future<void> _ensureFirebase() => initFirebaseForPush();
|
||||
|
||||
@override
|
||||
Future<bool> enable() async {
|
||||
|
||||
Reference in New Issue
Block a user