fix: register device push token with backend on permission grant#1669
fix: register device push token with backend on permission grant#1669
Conversation
Add useAddTokenMutation to NotificationsProvider and register the native device push token whenever notification permission is granted. Triggers on every app state change so tokens are re-registered after permission is granted while the app is backgrounded. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Registers the native device push token with the backend from within the existing notifications permission state provider, so the backend can associate the device for push delivery once permission is granted.
Changes:
- Add
useAddTokenMutationtoNotificationsProvider. - On
appStatechanges, if notification permission is granted, fetch the native device push token and send it to the backend with the platform OS.
| Notifications.getPermissionsAsync().then(({ status }) => { | ||
| if (status === "granted") { | ||
| Notifications.getDevicePushTokenAsync() | ||
| .then(({ data: token }) => { | ||
| addToken({ variables: { token, os: Platform.OS } }); | ||
| }) | ||
| .catch(() => undefined); |
There was a problem hiding this comment.
addToken(...) returns a Promise; if the mutation fails (e.g., auth/network error) this can create an unhandled rejection because the returned Promise is not awaited/handled. Handle the Promise (e.g., await in an async IIFE or .catch(...)) and consider handling errors from getPermissionsAsync() as well to avoid unhandled rejections in this effect.
| // Register device token with backend whenever permission is granted | ||
| useEffect(() => { | ||
| Notifications.getPermissionsAsync().then(({ status }) => { | ||
| if (status === "granted") { | ||
| Notifications.getDevicePushTokenAsync() | ||
| .then(({ data: token }) => { | ||
| addToken({ variables: { token, os: Platform.OS } }); | ||
| }) | ||
| .catch(() => undefined); | ||
| } | ||
| }); | ||
| }, [appState, addToken]); |
There was a problem hiding this comment.
This effect runs on every appState change, including transitions to inactive/background. Consider gating the registration logic to only run when the app is active (or on foreground) to avoid doing network/token work while backgrounded, which can be unreliable and is more expensive than needed for the stated goal.
| // Register device token with backend whenever permission is granted | ||
| useEffect(() => { | ||
| Notifications.getPermissionsAsync().then(({ status }) => { | ||
| if (status === "granted") { | ||
| Notifications.getDevicePushTokenAsync() |
There was a problem hiding this comment.
Notifications.getPermissionsAsync() is now called in two separate useEffects that both depend on appState (this one and the alreadyDenied effect below). Consider consolidating into a single permission check per app-state change (and then branching into both behaviors) to reduce duplicated work and keep the permission/token flow easier to follow.
Updated the push token retrieval logic in the DevScreen component to use promise chaining instead of an async IIFE. This improves readability and maintains the same functionality for obtaining Expo and device push tokens.
…handling in DevScreen
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ted hooks - Create usePermissionStatus hook: gates getPermissionsAsync to active state only, eliminates duplicate permission checks - Create useDeviceTokenRegistration hook: caches last token in useRef, handles addToken errors with .catch(), only fires when permission is granted - Refactor NotificationsProvider to use new hooks, removing 3 effects and consolidating permission logic - Remove dead alreadyDenied state (not exposed in context interface) - Add unit tests for both hooks (14 test cases) Fixes: unhandled promise on addToken, duplicate getPermissionsAsync calls, unnecessary background/inactive state network calls, no token caching Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- PUSH_NOTIFICATIONS.md: Main feature doc (1140 lines, 12 Mermaid diagrams) Covers architecture, permissions, token registration, categories, deep-link routing, settings, UI components, file structure, config, testing - PUSH_NOTIFICATION_ROUTING.md: Deep-dive routing doc (993 lines, 13 Mermaid diagrams) Covers type system, native push taps, URL scheme handling, routing logic, navigation strategies, E2E testing, web URL deep links Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add useAddTokenMutation to NotificationsProvider and register the native device push token whenever notification permission is granted. Triggers on every app state change so tokens are re-registered after permission is granted while the app is backgrounded.