import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; class NotificationService { static final NotificationService _instance = NotificationService._internal(); factory NotificationService() => _instance; NotificationService._internal(); FirebaseMessaging? _messaging; static const String vapidKey = 'BKrFSFm2cb2DNtEpTNmEy3acpi2ziRA5DhzKSyjshqAWANaoydztUTa0Cn3jwh1v7KN6pHUQfsODFXUWrKG6aSU'; static const List topics = [ 'all', 'newposts', 'newinvites', 'invitesfollowup', 'appnews', ]; Future initialize() async { if (!kIsWeb) { print('Notifications are only supported on web platform'); return; } _messaging = FirebaseMessaging.instance; await _requestPermission(); await _subscribeToTopics(); await _setupMessageHandlers(); } Future _requestPermission() async { if (_messaging == null) return; NotificationSettings settings = await _messaging!.requestPermission( alert: true, announcement: false, badge: true, carPlay: false, criticalAlert: false, provisional: false, sound: true, ); print('User granted permission: ${settings.authorizationStatus}'); if (settings.authorizationStatus == AuthorizationStatus.authorized) { print('User granted permission for notifications'); } else if (settings.authorizationStatus == AuthorizationStatus.provisional) { print('User granted provisional permission for notifications'); } else { print('User declined or has not accepted permission for notifications'); } } Future _subscribeToTopics() async { if (_messaging == null) return; for (String topic in topics) { try { await _messaging!.subscribeToTopic(topic); print('Subscribed to topic: $topic'); } catch (e) { print('Error subscribing to topic $topic: $e'); } } } Future _setupMessageHandlers() async { if (_messaging == null) return; // Handle foreground messages FirebaseMessaging.onMessage.listen((RemoteMessage message) { print('Got a message whilst in the foreground!'); print('Message data: ${message.data}'); if (message.notification != null) { print('Message also contained a notification: ${message.notification}'); _showNotification(message.notification!); } }); // Handle background messages FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); // Handle notification taps FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { print('A new onMessageOpenedApp event was published!'); print('Message data: ${message.data}'); _handleNotificationTap(message); }); // Get the initial message if the app was opened from a notification RemoteMessage? initialMessage = await _messaging!.getInitialMessage(); if (initialMessage != null) { print('App opened from notification: ${initialMessage.data}'); _handleNotificationTap(initialMessage); } // Get the FCM token for this device String? token = await _messaging!.getToken(vapidKey: vapidKey); print('FCM Token: $token'); } void _showNotification(RemoteNotification notification) { // For web, we rely on the service worker to show notifications // This is mainly for logging and debugging print('Notification Title: ${notification.title}'); print('Notification Body: ${notification.body}'); } void _handleNotificationTap(RemoteMessage message) { // Handle notification tap actions here print('Notification tapped: ${message.data}'); // You can navigate to specific screens based on the notification data // For example: // if (message.data['type'] == 'newpost') { // // Navigate to posts screen // } else if (message.data['type'] == 'newinvite') { // // Navigate to invitations screen // } } Future unsubscribeFromTopic(String topic) async { if (_messaging == null) return; try { await _messaging!.unsubscribeFromTopic(topic); print('Unsubscribed from topic: $topic'); } catch (e) { print('Error unsubscribing from topic $topic: $e'); } } Future subscribeToTopic(String topic) async { if (_messaging == null) return; try { await _messaging!.subscribeToTopic(topic); print('Subscribed to topic: $topic'); } catch (e) { print('Error subscribing to topic $topic: $e'); } } Future getToken() async { if (_messaging == null) return null; return await _messaging!.getToken(vapidKey: vapidKey); } } // Background message handler must be a top-level function Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { print('Handling a background message: ${message.messageId}'); print('Message data: ${message.data}'); if (message.notification != null) { print('Background message contained a notification: ${message.notification}'); } }