import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:timezone/timezone.dart' as tz; class NotificationService { static final _plugin = FlutterLocalNotificationsPlugin(); static bool _initialised = false; static const _channelId = 'daily_reminder'; static const _notificationId = 0; static Future init() async { if (_initialised) return; const android = AndroidInitializationSettings('@mipmap/ic_launcher'); await _plugin.initialize( settings: const InitializationSettings(android: android), ); _initialised = true; } static Future requestPermission() async { final android = _plugin.resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>(); return (await android?.requestNotificationsPermission()) ?? false; } static Future scheduleDaily(TimeOfDay time) async { await _plugin.cancelAll(); const details = NotificationDetails( android: AndroidNotificationDetails( _channelId, 'Daily reminder', channelDescription: 'Reminds you to log your mood', importance: Importance.defaultImportance, priority: Priority.defaultPriority, ), ); await _plugin.zonedSchedule( id: _notificationId, title: 'DailyYou', body: 'Time to log your mood!', scheduledDate: _nextInstanceOfTime(time.hour, time.minute), notificationDetails: details, androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle, matchDateTimeComponents: DateTimeComponents.time, ); } static Future cancelAll() => _plugin.cancelAll(); static tz.TZDateTime _nextInstanceOfTime(int hour, int minute) { final now = tz.TZDateTime.now(tz.UTC); final offset = DateTime.now().timeZoneOffset; var targetMinutes = hour * 60 + minute - offset.inMinutes; // Normalise into [0, 24*60) targetMinutes = ((targetMinutes % (24 * 60)) + 24 * 60) % (24 * 60); final utcHour = targetMinutes ~/ 60; final utcMin = targetMinutes % 60; var scheduled = tz.TZDateTime(tz.UTC, now.year, now.month, now.day, utcHour, utcMin); if (scheduled.isBefore(now)) { scheduled = scheduled.add(const Duration(days: 1)); } return scheduled; } }