diff --git a/TODO.md b/TODO.md index 7ab36ea..69f7673 100644 --- a/TODO.md +++ b/TODO.md @@ -12,7 +12,7 @@ - [x] Test in-house for 1 week - [x] Implement push notifications - [x] Release 0.2.0 -- [ ] Install in test server and test app on iPhone +- [x] Install in test server and test app on iPhone - [ ] Test in-house for 3 days - [ ] Release 0.2.1 (or as many versions as needed) - [ ] Publish website diff --git a/frontend/lib/utils/push_service.dart b/frontend/lib/utils/push_service.dart index 4624aab..66ebf97 100644 --- a/frontend/lib/utils/push_service.dart +++ b/frontend/lib/utils/push_service.dart @@ -99,17 +99,34 @@ final FlutterLocalNotificationsPlugin _localNotifications = // request comes from startup (push already enabled) or from enable() on toggle. bool _foregroundDisplayWired = false; -// Renders push notifications that arrive while the app is in the foreground (the -// OS displays backgrounded/terminated ones itself); taps just open the app, so no +// Ensures push notifications are shown while the app is in the foreground (the OS +// displays backgrounded/terminated ones itself); taps just open the app, so no // tap handler is wired. Idempotent; a no-op on platforms without push. +// +// The two platforms diverge in the foreground: iOS suppresses the incoming push +// banner unless we opt in via setForegroundNotificationPresentationOptions, after +// which the OS presents the original push itself (no re-show needed, which also +// avoids a double notification / UNUserNotificationCenter delegate clash with +// flutter_local_notifications). Android never displays foreground `notification` +// messages itself, so there we render them through a local-notification channel +// from onMessage. Future _ensureForegroundDisplay() async { if (!_pushSupported || _foregroundDisplayWired) return; _foregroundDisplayWired = true; + if (_isIOS) { + await FirebaseMessaging.instance + .setForegroundNotificationPresentationOptions( + alert: true, + badge: true, + sound: true, + ); + return; + } + await _localNotifications.initialize( const InitializationSettings( android: AndroidInitializationSettings('@mipmap/ic_launcher'), - iOS: DarwinInitializationSettings(), ), ); await _localNotifications @@ -133,7 +150,6 @@ Future _ensureForegroundDisplay() async { importance: Importance.high, priority: Priority.high, ), - iOS: const DarwinNotificationDetails(), ), ); });