import 'package:blind_master/BlindMasterResources/secure_transmissions.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; class FcmService { /// Request permission, fetch the FCM token, and register it with the server. /// Safe to call on every login/session-restore — the server just upserts the value. static Future register() async { debugPrint('FCM: register() called'); try { final messaging = FirebaseMessaging.instance; final settings = await messaging.requestPermission(alert: true, badge: true, sound: true); debugPrint('FCM: authorization status: ${settings.authorizationStatus}'); if (settings.authorizationStatus == AuthorizationStatus.denied) { debugPrint('FCM: notifications denied — enable in Settings > [App] > Notifications'); return; } await messaging.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true, ); // On iOS, APNs token must be available before FCM token can be fetched. // getAPNSToken() can block if iOS hasn't finished APNs registration yet, // so cap it with a timeout and retry once after a short delay. if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) { String? apnsToken = await messaging.getAPNSToken() .timeout(const Duration(seconds: 3), onTimeout: () => null); if (apnsToken == null) { debugPrint('FCM: APNs token not ready, retrying in 5s...'); await Future.delayed(const Duration(seconds: 5)); apnsToken = await messaging.getAPNSToken() .timeout(const Duration(seconds: 5), onTimeout: () => null); } if (apnsToken == null) { debugPrint('FCM: APNs token unavailable — simulator or APNs not configured'); return; } debugPrint('FCM: APNs token acquired'); } final token = await messaging.getToken(); debugPrint('FCM TOKEN: ${token ?? "null — likely running on simulator"}'); if (token == null) return; await securePost({'token': token}, 'register_fcm_token'); } catch (e) { debugPrint('FCM registration failed: $e'); } } }