Files
geo/app/lib/chat/services/notifications/chat_notification_service.dart
pierre 599b9fcda0 feat: Gestion des secteurs et migration v3.0.4+304
- Ajout système complet de gestion des secteurs avec contours géographiques
- Import des contours départementaux depuis GeoJSON
- API REST pour la gestion des secteurs (/api/sectors)
- Service de géolocalisation pour déterminer les secteurs
- Migration base de données avec tables x_departements_contours et sectors_adresses
- Interface Flutter pour visualisation et gestion des secteurs
- Ajout thème sombre dans l'application
- Corrections diverses et optimisations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 11:01:45 +02:00

206 lines
6.4 KiB
Dart
Executable File

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();
// 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}');
}