refactor(apps): 主题系统迁移至 ColorScheme + 扩展架构并支持 Dark Mode
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../core/storage/app_preferences.dart';
|
||||
import '../models/reminder_payload.dart';
|
||||
|
||||
typedef ReminderNotificationResponseHandler =
|
||||
Future<void> Function(NotificationResponse response);
|
||||
|
||||
class ReminderNotificationCallbacks {
|
||||
static ReminderNotificationResponseHandler? _responseHandler;
|
||||
static Future<void> _pendingStorageLock = Future<void>.value();
|
||||
static void Function(ReminderPayload)? onNotificationPayloadReceived;
|
||||
static AppPreferences? _appPreferences;
|
||||
|
||||
static Future<AppPreferences> _resolvePrefs() async {
|
||||
final prefs = _appPreferences;
|
||||
if (prefs != null) {
|
||||
return prefs;
|
||||
}
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
final fallback = AppPreferences(sharedPreferences);
|
||||
_appPreferences = fallback;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static void setAppPreferences(AppPreferences prefs) {
|
||||
_appPreferences = prefs;
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
static Future<void> resetForTest() async {
|
||||
_responseHandler = null;
|
||||
_pendingStorageLock = Future<void>.value();
|
||||
final prefs = await _resolvePrefs();
|
||||
await prefs.clearPendingNotifications();
|
||||
}
|
||||
|
||||
static Future<void> bindResponseHandler(
|
||||
ReminderNotificationResponseHandler handler,
|
||||
) async {
|
||||
_responseHandler = handler;
|
||||
await _drainPendingResponses();
|
||||
}
|
||||
|
||||
static Future<void> onForegroundResponse(
|
||||
NotificationResponse response,
|
||||
) async {
|
||||
final handler = _responseHandler;
|
||||
if (handler == null) {
|
||||
await _enqueuePendingResponse(response);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await handler(response);
|
||||
} catch (_) {
|
||||
await _enqueuePendingResponse(response);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> onBackgroundResponse(
|
||||
NotificationResponse response,
|
||||
) async {
|
||||
final handler = _responseHandler;
|
||||
if (handler == null) {
|
||||
await _enqueuePendingResponse(response);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await handler(response);
|
||||
} catch (_) {
|
||||
await _enqueuePendingResponse(response);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<T> _withPendingStorageLock<T>(Future<T> Function() operation) {
|
||||
final completer = Completer<void>();
|
||||
final waitForTurn = _pendingStorageLock;
|
||||
_pendingStorageLock = waitForTurn.then((_) => completer.future);
|
||||
|
||||
return waitForTurn.then((_) => operation()).whenComplete(() {
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Future<void> _enqueuePendingResponse(
|
||||
NotificationResponse response,
|
||||
) async {
|
||||
final prefs = await _resolvePrefs();
|
||||
await _withPendingStorageLock(() async {
|
||||
final current = prefs.pendingNotifications;
|
||||
await prefs.setPendingNotifications([
|
||||
...current,
|
||||
NotificationResponse(
|
||||
id: response.id,
|
||||
actionId: response.actionId,
|
||||
payload: response.payload,
|
||||
input: response.input,
|
||||
notificationResponseType: response.notificationResponseType,
|
||||
),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
static Future<void> _drainPendingResponses() async {
|
||||
final handler = _responseHandler;
|
||||
if (handler == null) {
|
||||
return;
|
||||
}
|
||||
final prefs = await _resolvePrefs();
|
||||
await _withPendingStorageLock(() async {
|
||||
final pending = prefs.pendingNotifications;
|
||||
if (pending.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final remaining = <NotificationResponse>[];
|
||||
for (final response in pending) {
|
||||
try {
|
||||
await handler(response);
|
||||
} catch (_) {
|
||||
remaining.add(response);
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining.isEmpty) {
|
||||
await prefs.clearPendingNotifications();
|
||||
return;
|
||||
}
|
||||
|
||||
await prefs.setPendingNotifications(remaining);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> reminderNotificationTapBackground(
|
||||
NotificationResponse response,
|
||||
) async {
|
||||
await ReminderNotificationCallbacks.onBackgroundResponse(response);
|
||||
}
|
||||
Reference in New Issue
Block a user