203 lines
6.5 KiB
Dart
203 lines
6.5 KiB
Dart
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
/// Service de gestion des notifications chat
|
|
///
|
|
/// Gère l'envoi et la réception des notifications pour le module chat
|
|
|
|
class ChatNotificationService {
|
|
static final ChatNotificationService _instance = ChatNotificationService._internal();
|
|
factory ChatNotificationService() => _instance;
|
|
ChatNotificationService._internal();
|
|
|
|
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
|
final FlutterLocalNotificationsPlugin _localNotifications = FlutterLocalNotificationsPlugin();
|
|
|
|
// Callback pour les actions sur les notifications
|
|
Function(String messageId)? onMessageTap;
|
|
Function(Map<String, dynamic>)? onBackgroundMessage;
|
|
|
|
/// Initialise le service de notifications
|
|
Future<void> initialize() async {
|
|
// Demander les permissions
|
|
await _requestPermissions();
|
|
|
|
// Initialiser les notifications locales
|
|
await _initializeLocalNotifications();
|
|
|
|
// Configurer les handlers de messages
|
|
_configureFirebaseHandlers();
|
|
|
|
// Obtenir le token du device
|
|
await _initializeDeviceToken();
|
|
}
|
|
|
|
/// Demande les permissions pour les notifications
|
|
Future<bool> _requestPermissions() async {
|
|
NotificationSettings settings = await _firebaseMessaging.requestPermission(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
provisional: false,
|
|
);
|
|
|
|
return settings.authorizationStatus == AuthorizationStatus.authorized;
|
|
}
|
|
|
|
/// Initialise les notifications locales
|
|
Future<void> _initializeLocalNotifications() async {
|
|
const AndroidInitializationSettings androidSettings =
|
|
AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
|
|
final DarwinInitializationSettings iosSettings = DarwinInitializationSettings(
|
|
requestAlertPermission: true,
|
|
requestBadgePermission: true,
|
|
requestSoundPermission: true,
|
|
onDidReceiveLocalNotification: _onDidReceiveLocalNotification,
|
|
);
|
|
|
|
final InitializationSettings initSettings = InitializationSettings(
|
|
android: androidSettings,
|
|
iOS: iosSettings,
|
|
);
|
|
|
|
await _localNotifications.initialize(
|
|
initSettings,
|
|
onDidReceiveNotificationResponse: _onNotificationTap,
|
|
);
|
|
}
|
|
|
|
/// Configure les handlers Firebase
|
|
void _configureFirebaseHandlers() {
|
|
// Message reçu quand l'app est au premier plan
|
|
FirebaseMessaging.onMessage.listen(_onForegroundMessage);
|
|
|
|
// Message reçu quand l'app est en arrière-plan
|
|
FirebaseMessaging.onMessageOpenedApp.listen(_onBackgroundMessageOpened);
|
|
|
|
// Handler pour les messages en arrière-plan terminé
|
|
FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler);
|
|
}
|
|
|
|
/// Handler pour les messages reçus au premier plan
|
|
Future<void> _onForegroundMessage(RemoteMessage message) async {
|
|
if (message.notification != null) {
|
|
// Afficher une notification locale
|
|
await _showLocalNotification(
|
|
title: message.notification!.title ?? 'Nouveau message',
|
|
body: message.notification!.body ?? '',
|
|
payload: message.data['messageId'] ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Handler pour les messages ouverts depuis l'arrière-plan
|
|
void _onBackgroundMessageOpened(RemoteMessage message) {
|
|
final messageId = message.data['messageId'];
|
|
if (messageId != null) {
|
|
onMessageTap?.call(messageId);
|
|
}
|
|
}
|
|
|
|
/// Affiche une notification locale
|
|
Future<void> _showLocalNotification({
|
|
required String title,
|
|
required String body,
|
|
required String payload,
|
|
}) async {
|
|
const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
|
|
'chat_messages',
|
|
'Messages de chat',
|
|
channelDescription: 'Notifications pour les nouveaux messages de chat',
|
|
importance: Importance.high,
|
|
priority: Priority.high,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
const NotificationDetails notificationDetails = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _localNotifications.show(
|
|
DateTime.now().microsecondsSinceEpoch,
|
|
title,
|
|
body,
|
|
notificationDetails,
|
|
payload: payload,
|
|
);
|
|
}
|
|
|
|
/// Handler pour le clic sur une notification
|
|
void _onNotificationTap(NotificationResponse response) {
|
|
final payload = response.payload;
|
|
if (payload != null) {
|
|
onMessageTap?.call(payload);
|
|
}
|
|
}
|
|
|
|
/// Handler pour les notifications iOS reçues au premier plan
|
|
void _onDidReceiveLocalNotification(int id, String? title, String? body, String? payload) {
|
|
// Traitement spécifique iOS si nécessaire
|
|
}
|
|
|
|
/// Obtient et stocke le token du device
|
|
Future<String?> _initializeDeviceToken() async {
|
|
String? token = await _firebaseMessaging.getToken();
|
|
if (token != null) {
|
|
// Envoyer le token au serveur pour stocker
|
|
await _sendTokenToServer(token);
|
|
}
|
|
|
|
// Écouter les changements de token
|
|
_firebaseMessaging.onTokenRefresh.listen(_sendTokenToServer);
|
|
|
|
return token;
|
|
}
|
|
|
|
/// Envoie le token FCM au serveur
|
|
Future<void> _sendTokenToServer(String token) async {
|
|
try {
|
|
// Appel API pour enregistrer le token
|
|
// await chatApiService.registerDeviceToken(token);
|
|
debugPrint('Device token enregistré : $token');
|
|
} catch (e) {
|
|
debugPrint('Erreur lors de l\'enregistrement du token : $e');
|
|
}
|
|
}
|
|
|
|
/// S'abonner aux notifications pour une conversation
|
|
Future<void> subscribeToConversation(String conversationId) async {
|
|
await _firebaseMessaging.subscribeToTopic('chat_$conversationId');
|
|
}
|
|
|
|
/// Se désabonner des notifications pour une conversation
|
|
Future<void> unsubscribeFromConversation(String conversationId) async {
|
|
await _firebaseMessaging.unsubscribeFromTopic('chat_$conversationId');
|
|
}
|
|
|
|
/// Désactive temporairement les notifications
|
|
Future<void> pauseNotifications() async {
|
|
await _firebaseMessaging.setAutoInitEnabled(false);
|
|
}
|
|
|
|
/// Réactive les notifications
|
|
Future<void> resumeNotifications() async {
|
|
await _firebaseMessaging.setAutoInitEnabled(true);
|
|
}
|
|
}
|
|
|
|
/// Handler pour les messages en arrière-plan
|
|
@pragma('vm:entry-point')
|
|
Future<void> _firebaseBackgroundHandler(RemoteMessage message) async {
|
|
// Traitement des messages en arrière-plan
|
|
debugPrint('Message reçu en arrière-plan : ${message.messageId}');
|
|
}
|