Files
pantry-flutter/lib/services/local_notifications_service.dart

134 lines
3.8 KiB
Dart

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:pantry/services/deep_link_service.dart';
class LocalNotificationsService {
LocalNotificationsService._();
static final LocalNotificationsService instance =
LocalNotificationsService._();
final _plugin = FlutterLocalNotificationsPlugin();
bool _initialized = false;
static const _channelId = 'pantry_notifications';
static const _channelName = 'Pantry notifications';
static const _channelDescription = 'Household activity from your pantry';
Future<void> init() async {
if (_initialized) return;
const androidSettings = AndroidInitializationSettings(
'@mipmap/ic_launcher',
);
const darwinSettings = DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
);
const settings = InitializationSettings(
android: androidSettings,
iOS: darwinSettings,
macOS: darwinSettings,
);
await _plugin.initialize(
settings,
onDidReceiveNotificationResponse: _onTap,
);
// If the app was launched by tapping a notification (cold start),
// capture that payload so the home view can consume it after startup.
final launchDetails = await _plugin.getNotificationAppLaunchDetails();
if (launchDetails?.didNotificationLaunchApp ?? false) {
final payload = launchDetails?.notificationResponse?.payload;
final link = DeepLink.decode(payload);
if (link != null) DeepLinkService.instance.push(link);
}
// Create the Android channel (no-op on iOS).
final androidPlugin = _plugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin
>();
await androidPlugin?.createNotificationChannel(
const AndroidNotificationChannel(
_channelId,
_channelName,
description: _channelDescription,
importance: Importance.defaultImportance,
),
);
_initialized = true;
}
/// Request runtime notification permission (Android 13+ and iOS).
Future<bool> requestPermission() async {
await init();
final android = _plugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin
>();
final androidGranted =
await android?.requestNotificationsPermission() ?? true;
final ios = _plugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin
>();
final iosGranted =
await ios?.requestPermissions(alert: true, badge: true, sound: true) ??
true;
final macos = _plugin
.resolvePlatformSpecificImplementation<
MacOSFlutterLocalNotificationsPlugin
>();
final macosGranted =
await macos?.requestPermissions(
alert: true,
badge: true,
sound: true,
) ??
true;
return androidGranted && iosGranted && macosGranted;
}
Future<void> show({
required int id,
required String title,
String? body,
String? payload,
}) async {
await init();
await _plugin.show(
id,
title,
body,
const NotificationDetails(
android: AndroidNotificationDetails(
_channelId,
_channelName,
channelDescription: _channelDescription,
importance: Importance.defaultImportance,
priority: Priority.defaultPriority,
),
iOS: DarwinNotificationDetails(),
macOS: DarwinNotificationDetails(),
),
payload: payload,
);
}
static void _onTap(NotificationResponse response) {
final link = DeepLink.decode(response.payload);
if (link != null) DeepLinkService.instance.push(link);
}
Future<void> cancelAll() async {
await init();
await _plugin.cancelAll();
}
}