wesal/lib/services/notification_service.dart
2025-07-17 10:20:19 +03:00

163 lines
5.0 KiB
Dart

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<String> topics = [
'all',
'newposts',
'newinvites',
'invitesfollowup',
'appnews',
];
Future<void> initialize() async {
if (!kIsWeb) {
print('Notifications are only supported on web platform');
return;
}
_messaging = FirebaseMessaging.instance;
await _requestPermission();
await _subscribeToTopics();
await _setupMessageHandlers();
}
Future<void> _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<void> _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<void> _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<void> 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<void> 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<String?> getToken() async {
if (_messaging == null) return null;
return await _messaging!.getToken(vapidKey: vapidKey);
}
}
// Background message handler must be a top-level function
Future<void> _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}');
}
}