import 'dart:async'; import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import 'package:model/firebase/firebase_dto.dart'; import 'package:rxdart/rxdart.dart'; import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart'; import 'package:tmail_ui_user/firebase_options.dart'; import 'notification_strings.dart'; final StreamController selectNotificationStream = StreamController.broadcast(); @pragma('vm:entry-point') Future firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await NotificationService.displayPushNotification(message); } @pragma('vm:entry-point') void notificationTapBackground(NotificationResponse notificationResponse) { //handle action } void onDidReceiveNotificationResponse( NotificationResponse details, ) { selectNotificationStream.add(details); } class NotificationService { factory NotificationService() => _instance; NotificationService._internal(); static final NotificationService _instance = NotificationService._internal(); static get _firebaseMessaging => FirebaseMessaging.instance; static get _flutterLocalNotificationsPlugin => FlutterLocalNotificationsPlugin(); static final BehaviorSubject _notificationActionStream = BehaviorSubject.seeded(null); static Stream get notificationActionStream => _notificationActionStream.stream; static Stream get onTokenRefresh => _firebaseMessaging.onTokenRefresh; static bool _isFlutterLocalNotificationsInitialized = false; static Future initializeNotificationService( Function(NotificationResponse)? onDidReceiveNotificationResponse, ) async { if (_isFlutterLocalNotificationsInitialized) return; final _saveFirebaseCacheInteractor = Get.find(); final token = await _firebaseMessaging.getToken(); _saveFirebaseCacheInteractor.execute(FirebaseDto(token)); await _initFirebaseMessaging(); await _flutterLocalNotificationsPlugin.initialize( InitializationSettings( android: androidInitializationSettings, iOS: iosInitializationSettings, ), onDidReceiveNotificationResponse: onDidReceiveNotificationResponse, onDidReceiveBackgroundNotificationResponse: notificationTapBackground, ); await _requestPermissions(); await _createNotificationChannels(); _listenNotificationActionStream(); _isFlutterLocalNotificationsInitialized = true; } static Future displayPushNotification( RemoteMessage notification, ) async { try { await _flutterLocalNotificationsPlugin.show( createUniqueId, channelName, notification.data.toString(), pushNotificationDetails, ); } catch (e) { debugPrint(e.toString()); } } static Future cancelAllNotifications() async { await _flutterLocalNotificationsPlugin.cancelAll(); } static Future _initFirebaseMessaging() async { FirebaseMessaging.onMessage.listen(_handleIncomingForegroundNotification); FirebaseMessaging.onMessageOpenedApp.listen(_handleOpenedAppNotification); } static Future _handleIncomingForegroundNotification( RemoteMessage remoteMessage, ) async { await displayPushNotification(remoteMessage); } static void _handleOpenedAppNotification(RemoteMessage remoteMessage) {} static Future _requestPermissions() async { if (Platform.isAndroid) { await _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.requestPermission(); } else { await _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin>() ?.requestPermissions( alert: true, badge: true, sound: true, ); } } static Future _listenNotificationActionStream() async { selectNotificationStream.stream .listen((event) => event) .onData((data) async { _notificationActionStream.add(data); switch (data?.notificationResponseType) { case NotificationResponseType.selectedNotification: break; case NotificationResponseType.selectedNotificationAction: break; default: } }); } static Future _createNotificationChannels() async { await _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(androidChannel); } static Future deleteToken() async => _firebaseMessaging.deleteToken(); } int get createUniqueId => DateTime.now().millisecondsSinceEpoch.remainder(100000);