Allow OS notifications

This commit is contained in:
2026-02-23 22:19:23 +08:00
parent 98355c3707
commit cc6fda0e79
11 changed files with 398 additions and 4 deletions
+56
View File
@@ -0,0 +1,56 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
/// A thin wrapper around `flutter_local_notifications` that centralizes the
/// plugin instance and provides easy initialization/show helpers.
class NotificationService {
NotificationService._();
static final FlutterLocalNotificationsPlugin _plugin =
FlutterLocalNotificationsPlugin();
/// Call during app startup, after any necessary permissions have been
/// granted. The callback receives a [NotificationResponse] when the user
/// taps the alert.
static Future<void> initialize({
void Function(NotificationResponse)? onDidReceiveNotificationResponse,
}) async {
const androidSettings = AndroidInitializationSettings(
'@mipmap/ic_launcher',
);
const iosSettings = DarwinInitializationSettings();
await _plugin.initialize(
settings: const InitializationSettings(
android: androidSettings,
iOS: iosSettings,
),
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
);
}
/// Show a simple notification immediately.
static Future<void> show({
required int id,
required String title,
required String body,
String? payload,
}) async {
const androidDetails = AndroidNotificationDetails(
'default_channel',
'General',
importance: Importance.high,
priority: Priority.high,
);
const iosDetails = DarwinNotificationDetails();
await _plugin.show(
id: id,
title: title,
body: body,
notificationDetails: const NotificationDetails(
android: androidDetails,
iOS: iosDetails,
),
payload: payload,
);
}
}
+66
View File
@@ -0,0 +1,66 @@
import 'package:permission_handler/permission_handler.dart';
/// Information about a permission that the application cares about.
///
/// Add new entries to [appPermissions] when the app requires additional
/// runtime permissions. The UI that drives the "permissions screen" reads this
/// list and will automatically include new permissions without any further
/// changes.
class PermissionInfo {
const PermissionInfo({
required this.permission,
required this.label,
this.description,
});
final Permission permission;
final String label;
final String? description;
}
/// The set of permissions the app will check/request from the user.
///
/// Currently contains the permissions actually referenced in the codebase, but
/// it should be expanded as new features are added. Declaring a permission
/// here ensures it appears on the permissions screen and is considered when
/// performing bulk checks/requests.
const List<PermissionInfo> appPermissions = [
PermissionInfo(
permission: Permission.notification,
label: 'Notifications',
description: 'Deliver alerts and sounds',
),
PermissionInfo(
permission: Permission.location,
label: 'Location',
description: 'Access your location for geofencing',
),
// add new permissions here as necessary
];
/// Returns the current status for every permission in [appPermissions].
Future<Map<Permission, PermissionStatus>> getAllStatuses() async {
final map = <Permission, PermissionStatus>{};
for (final info in appPermissions) {
map[info.permission] = await info.permission.status;
}
return map;
}
/// Requests [permission] and returns the resulting status.
Future<PermissionStatus> requestPermission(Permission permission) async {
return permission.request();
}
/// Convenience that requests every permission that is currently not granted.
///
/// Returns the full status map after requesting.
Future<Map<Permission, PermissionStatus>> requestAllNeeded() async {
final statuses = await getAllStatuses();
for (final entry in statuses.entries) {
if (!entry.value.isGranted) {
statuses[entry.key] = await entry.key.request();
}
}
return statuses;
}