FCM Token Sync (per-role)
core/network/dio_helper.dart · syncFcmTokenForAllRoles + _checkAndSendFcmToken
Overview
Backend cares which (auth_token, fcm_token) pairs are active — the customer and seller tokens get separate FCM registrations. DioHelper owns this side channel, keyed by the tuple in SharedPreferences so a re-send only fires on actual change.
User Flow
- First-of-session: on the first authenticated request, _checkAndSendFcmToken fires fire-and-forget for that auth token.
- syncFcmTokenForAllRoles is explicitly called after login to register both tokens if dual login succeeded.
- _checkAndSendFcmToken uses a separate raw Dio (not the singleton) to avoid interceptor recursion.
- AuthStorageService.isFcmTokenSent / markFcmTokenSent dedupe by (fcmToken, last20charsOfAuthToken).
Cases & Edge Cases
- _fcmSyncInProgress Set prevents two parallel requests with the same auth token from each sending the FCM token (burst-at-startup race).
- Empty fcmToken is a hard 'skip' — happens before FirebaseMessaging permission resolves.
- Token-tracking keys are never cleared on logout — fine, because clearSession wipes the tokens themselves and the keys become orphaned but harmless.
Code References
- lib/src/core/network/dio_helper.dart:64 // syncFcmTokenForAllRoles
- lib/src/core/network/dio_helper.dart:82 // _checkAndSendFcmToken
- lib/src/core/services/auth_storage.dart:219 // _getFcmTrackingKey
API Calls
- POST
/fcm/tokenno statusRegister the device's FCM token for a given auth scope so the backend can target push to this device + role.
Request{ token: string /* fcmToken */ } + header `Authorization: Bearer <authToken>` + `x-publishable-api-key`Response200 / 201 (no body)
lib/src/core/network/dio_helper.dart:82 // _checkAndSendFcmTokenauth: bearer (per role). Fired via raw Dio (avoids interceptor recursion). Triggered on first authenticated request post-login and on onTokenRefresh. Deduped via 'fcm_sent_<fcmToken>_<authSuffix>' SharedPreferences keys.
Notes
When debugging missing pushes, first verify the right key in SharedPreferences exists ('fcm_sent_<token>_<suffix>') — if missing, the upload never fired.