You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Notification-Behavior.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,7 @@ This document describes the current notification behavior in OnTime across push
6
6
7
7
- App startup checks current notification permission first.
8
8
-`NotificationService.initialize()` runs at startup only when permission is already `AuthorizationStatus.authorized`.
9
+
-`NotificationService.initialize()` is service-level idempotent: repeated sequential or concurrent calls share the same completed or in-flight setup and do not register duplicate FCM listeners.
9
10
- If startup permission is not authorized, the app does not initialize notification handlers/tokens from `main.dart`.
10
11
- During authenticated redirects from sign-in/onboarding entry routes, router logic checks permission and redirects to `/allowNotification` when permission is not authorized.
11
12
- Permission can later be requested from:
@@ -21,20 +22,20 @@ Implementation notes:
21
22
22
23
### Foreground
23
24
24
-
-`FirebaseMessaging.onMessage` listener is registered in `NotificationService._setupMessageHandlers()`.
25
+
-`FirebaseMessaging.onMessage` listener is registered once per `NotificationService` lifecycle.
25
26
- Incoming push messages are converted into in-app local notifications through `showNotification(message)`.
26
27
- Title/body resolution supports both `message.notification` and `message.data` keys (e.g., `title`, `content`, `body`, plus case variants).
27
28
28
29
### Background (App in background, opened from notification)
-`FirebaseMessaging.onMessageOpenedApp`listener is registered once per `NotificationService` lifecycle and triggers `_handleBackgroundMessage(message)`.
31
32
- Navigation is decided from payload fields:
32
33
-`type` contains `5min` -> push `/scheduleStart` with `extra: {'isFiveMinutesBefore': true}`
33
34
-`type` starts with `schedule_` or `preparation_`, or `scheduleId` exists -> push `/alarmScreen`
34
35
35
36
### Terminated (Cold start from notification tap)
36
37
37
-
-`FirebaseMessaging.getInitialMessage()` is read on initialization.
38
+
-`FirebaseMessaging.getInitialMessage()` is read once during notification service initialization.
38
39
- If present, it is passed through the same `_handleBackgroundMessage(message)` routing logic as background open.
39
40
40
41
### Background isolate handler
@@ -78,7 +79,7 @@ Implementation notes:
78
79
-`FirebaseMessaging.getToken()` is called.
79
80
- If token exists, app posts to backend endpoint `/firebase-token` with payload `{ "firebaseToken": "<token>" }`.
80
81
- On token refresh:
81
-
-`FirebaseMessaging.onTokenRefresh.listen(...)` posts refreshed token to the same endpoint.
82
+
-A single `FirebaseMessaging.onTokenRefresh` subscription posts refreshed token to the same endpoint.
0 commit comments