refactor(calendar): remove deprecated reminder components
This commit is contained in:
@@ -4,7 +4,6 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:timezone/data/latest.dart' as tz_data;
|
||||
import 'package:timezone/timezone.dart' as tz;
|
||||
|
||||
@@ -12,8 +11,6 @@ import 'reminder_notification_callbacks.dart';
|
||||
import '../../features/calendar/data/models/schedule_item_model.dart';
|
||||
import '../../features/calendar/reminders/models/reminder_action.dart';
|
||||
import '../../features/calendar/reminders/models/reminder_payload.dart';
|
||||
import '../../features/calendar/reminders/reminder_action_dedupe_store.dart';
|
||||
import '../../features/calendar/reminders/reminder_overlap_policy.dart';
|
||||
|
||||
typedef ReminderNotificationActionHandler =
|
||||
Future<void> Function({
|
||||
@@ -38,9 +35,7 @@ class LocalNotificationService {
|
||||
static const String _actionSnooze = 'snooze10m';
|
||||
|
||||
final FlutterLocalNotificationsPlugin _plugin;
|
||||
final ReminderOverlapPolicy _overlapPolicy;
|
||||
final ReminderPermissionFallbackTracker? _permissionFallbackTracker;
|
||||
ReminderActionDedupeStore? _dedupeStore;
|
||||
bool _initialized = false;
|
||||
bool _canDeliverSystemNotification = true;
|
||||
ReminderNotificationActionHandler? _actionHandler;
|
||||
@@ -50,12 +45,8 @@ class LocalNotificationService {
|
||||
|
||||
LocalNotificationService({
|
||||
FlutterLocalNotificationsPlugin? plugin,
|
||||
ReminderOverlapPolicy? overlapPolicy,
|
||||
ReminderActionDedupeStore? dedupeStore,
|
||||
ReminderPermissionFallbackTracker? permissionFallbackTracker,
|
||||
}) : _plugin = plugin ?? FlutterLocalNotificationsPlugin(),
|
||||
_overlapPolicy = overlapPolicy ?? const ReminderOverlapPolicy(),
|
||||
_dedupeStore = dedupeStore,
|
||||
_permissionFallbackTracker = permissionFallbackTracker;
|
||||
|
||||
void bindActionHandler(ReminderNotificationActionHandler handler) {
|
||||
@@ -128,19 +119,9 @@ class LocalNotificationService {
|
||||
>();
|
||||
await iosImpl?.requestPermissions(alert: true, badge: true, sound: true);
|
||||
|
||||
await _ensureDedupeStore();
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
Future<void> _ensureDedupeStore() async {
|
||||
if (_dedupeStore != null) {
|
||||
return;
|
||||
}
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_dedupeStore = ReminderActionDedupeStore(prefs);
|
||||
}
|
||||
|
||||
Future<void> _refreshAndroidNotificationAvailability() async {
|
||||
if (defaultTargetPlatform != TargetPlatform.android) {
|
||||
return;
|
||||
@@ -166,8 +147,9 @@ class LocalNotificationService {
|
||||
}
|
||||
|
||||
final now = DateTime.now();
|
||||
final fireAt = _overlapPolicy.resolveFirstFireAt(event, now: now);
|
||||
if (fireAt == null) {
|
||||
final reminderMinutes = event.metadata?.reminderMinutes ?? 0;
|
||||
final fireAt = event.startAt.subtract(Duration(minutes: reminderMinutes));
|
||||
if (fireAt.isBefore(now)) {
|
||||
await cancelEventReminder(event.id);
|
||||
return;
|
||||
}
|
||||
@@ -225,31 +207,21 @@ class LocalNotificationService {
|
||||
) async {
|
||||
await initialize();
|
||||
await _refreshAndroidNotificationAvailability();
|
||||
if (!_canDeliverSystemNotification) {
|
||||
_clearAllInAppFallbackTimers();
|
||||
final now = DateTime.now();
|
||||
final groups = _overlapPolicy.groupByMinute(events, now: now);
|
||||
for (final group in groups) {
|
||||
if (group.isAggregate) {
|
||||
await _scheduleInAppAggregateFallback(group.events, group.fireAt);
|
||||
continue;
|
||||
}
|
||||
await _scheduleInAppFallbackRemindersFrom(
|
||||
event: group.events.first,
|
||||
firstFireAt: group.fireAt,
|
||||
for (final event in events) {
|
||||
if (!_canDeliverSystemNotification) {
|
||||
final reminderMinutes = event.metadata?.reminderMinutes ?? 0;
|
||||
final fireAt = event.startAt.subtract(
|
||||
Duration(minutes: reminderMinutes),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final now = DateTime.now();
|
||||
final groups = _overlapPolicy.groupByMinute(events, now: now);
|
||||
for (final group in groups) {
|
||||
if (group.isAggregate) {
|
||||
await _scheduleAggregateReminder(group.events, group.fireAt);
|
||||
if (fireAt.isAfter(DateTime.now())) {
|
||||
await _scheduleInAppFallbackRemindersFrom(
|
||||
event: event,
|
||||
firstFireAt: fireAt,
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
await upsertEventReminder(group.events.first);
|
||||
await upsertEventReminder(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,21 +665,6 @@ class LocalNotificationService {
|
||||
return;
|
||||
}
|
||||
|
||||
final dedupeStore = _dedupeStore;
|
||||
if (dedupeStore != null) {
|
||||
final notificationId = response.id?.toString() ?? payload.eventId;
|
||||
final fireTimeBucket =
|
||||
payload.fireTimeBucket ??
|
||||
(payload.startAt.millisecondsSinceEpoch ~/
|
||||
const Duration(minutes: 1).inMilliseconds);
|
||||
final actionExecutionId =
|
||||
'$notificationId|${action.value}|$fireTimeBucket';
|
||||
final isNew = await dedupeStore.markIfNew(actionExecutionId);
|
||||
if (!isNew) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await handler(action: action, payload: payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../features/calendar/reminders/reminder_cold_start_queue.dart';
|
||||
|
||||
typedef ReminderNotificationResponseHandler =
|
||||
Future<void> Function(NotificationResponse response);
|
||||
|
||||
@@ -15,8 +13,6 @@ class ReminderNotificationCallbacks {
|
||||
'calendar_reminder_pending_notification_responses_v1';
|
||||
static ReminderNotificationResponseHandler? _responseHandler;
|
||||
static Future<void> _pendingStorageLock = Future<void>.value();
|
||||
static final ReminderColdStartQueue _coldStartQueue =
|
||||
ReminderColdStartQueue();
|
||||
|
||||
@visibleForTesting
|
||||
static Future<void> resetForTest() async {
|
||||
@@ -106,38 +102,35 @@ class ReminderNotificationCallbacks {
|
||||
|
||||
final remaining = <String>[];
|
||||
for (final raw in pending) {
|
||||
_coldStartQueue.enqueue(() async {
|
||||
Map<String, dynamic> parsed;
|
||||
try {
|
||||
parsed = Map<String, dynamic>.from(jsonDecode(raw) as Map);
|
||||
} catch (_) {
|
||||
return;
|
||||
}
|
||||
Map<String, dynamic> parsed;
|
||||
try {
|
||||
parsed = Map<String, dynamic>.from(jsonDecode(raw) as Map);
|
||||
} catch (_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final id = parsed['id'] as int?;
|
||||
final actionId = parsed['actionId'] as String?;
|
||||
final payload = parsed['payload'] as String?;
|
||||
final typeIndex = (parsed['type'] as int?) ?? 0;
|
||||
final input = parsed['input'] as String?;
|
||||
final type = NotificationResponseType.values[typeIndex.clamp(0, 1)];
|
||||
final id = parsed['id'] as int?;
|
||||
final actionId = parsed['actionId'] as String?;
|
||||
final payload = parsed['payload'] as String?;
|
||||
final typeIndex = (parsed['type'] as int?) ?? 0;
|
||||
final input = parsed['input'] as String?;
|
||||
final type = NotificationResponseType.values[typeIndex.clamp(0, 1)];
|
||||
|
||||
try {
|
||||
await handler(
|
||||
NotificationResponse(
|
||||
id: id,
|
||||
actionId: actionId,
|
||||
payload: payload,
|
||||
input: input,
|
||||
notificationResponseType: type,
|
||||
),
|
||||
);
|
||||
} catch (_) {
|
||||
remaining.add(raw);
|
||||
}
|
||||
});
|
||||
try {
|
||||
await handler(
|
||||
NotificationResponse(
|
||||
id: id,
|
||||
actionId: actionId,
|
||||
payload: payload,
|
||||
input: input,
|
||||
notificationResponseType: type,
|
||||
),
|
||||
);
|
||||
} catch (_) {
|
||||
remaining.add(raw);
|
||||
}
|
||||
}
|
||||
|
||||
await _coldStartQueue.replay();
|
||||
if (remaining.isEmpty) {
|
||||
await prefs.remove(_pendingKey);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user