import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/timezone.dart' as tz; import 'package:timezone/data/latest_all.dart' as tz; class NotificationService { static final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin(); /// Initialisation (à appeler dans main()) static Future initialize() async { tz.initializeTimeZones(); const AndroidInitializationSettings androidInitSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initSettings = InitializationSettings( android: androidInitSettings, iOS: DarwinInitializationSettings(), ); await _notificationsPlugin.initialize(initSettings); // Demande les permissions au lancement await requestPermissions(); } /// Demander les permissions (Android 13+ et iOS) static Future requestPermissions() async { // Android 13+ final androidImplementation = _notificationsPlugin.resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>(); await androidImplementation?.requestNotificationsPermission(); // iOS final iosImplementation = _notificationsPlugin.resolvePlatformSpecificImplementation< IOSFlutterLocalNotificationsPlugin>(); await iosImplementation?.requestPermissions( alert: true, badge: true, sound: true, ); } /// Planifie une notification 1h avant l’évènement static Future scheduleEventNotification({ required String eventId, required String title, required String body, required DateTime eventDate, }) async { final scheduledDate = eventDate.subtract(const Duration(hours: 1)); if (scheduledDate.isBefore(DateTime.now())) { // Trop tard pour notifier return; } await _notificationsPlugin.zonedSchedule( eventId.hashCode, // identifiant unique pour l’évènement title, body, tz.TZDateTime.from(scheduledDate, tz.local), const NotificationDetails( android: AndroidNotificationDetails( 'events_channel', 'Évènements', channelDescription: 'Notifications des évènements favoris', importance: Importance.high, priority: Priority.high, ), iOS: DarwinNotificationDetails(), ), androidScheduleMode: AndroidScheduleMode .inexactAllowWhileIdle, // évite l'erreur Exact Alarm uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, matchDateTimeComponents: DateTimeComponents.dateAndTime, ); } /// Notification immédiate (debug) static Future showTestNotification() async { await _notificationsPlugin.show( 0, "Test Notification", "Ceci est une notification de debug", const NotificationDetails( android: AndroidNotificationDetails( 'debug_channel', 'Debug Notifications', channelDescription: 'Notifications de test pour debug', importance: Importance.max, priority: Priority.high, ), iOS: DarwinNotificationDetails(), ), ); } /// Annule une notification planifiée static Future cancel(String eventId) async { await _notificationsPlugin.cancel(eventId.hashCode); } }