Files

67 lines
2.3 KiB
Dart
Raw Permalink Normal View History

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<void> init() async {
if (_initialised) return;
const android = AndroidInitializationSettings('@mipmap/ic_launcher');
await _plugin.initialize(
settings: const InitializationSettings(android: android),
);
_initialised = true;
}
static Future<bool> requestPermission() async {
final android = _plugin.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
return (await android?.requestNotificationsPermission()) ?? false;
}
static Future<void> 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<void> 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;
}
}