feat: add local reminders and owned calendar synchronization

This commit is contained in:
Codex
2026-10-13 00:11:48 +08:00
parent ffd3920c0d
commit 2c4256b880
13 changed files with 978 additions and 8 deletions
+48 -6
View File
@@ -140,21 +140,33 @@ class AppController extends ChangeNotifier {
});
Future<void> clearCourses() => _run(() async {
// Preserve ownership mapping until cleanup has actually succeeded.
await _save(snapshot.copyWith(courses: [], clearMetadata: true));
await _save(
snapshot.copyWith(
courses: [],
clearMetadata: true,
calendarCleanupPending: true,
),
);
isDemo = false;
await notifications.cancelOwned();
await calendar.deleteOwned(snapshot.calendarEventIds);
await _save(snapshot.copyWith(calendarEventIds: {}));
try {
await notifications.cancelOwned();
} catch (_) {
reminderResult = const ReminderResult(
ReminderStatus.error,
message: '提醒清理失败,可重试',
);
}
await _cleanupCalendar();
});
Future<void> disableCalendar({required bool deleteEvents}) => _run(() async {
await _save(
snapshot.copyWith(
settings: snapshot.settings.copyWith(calendarEnabled: false),
calendarCleanupPending: deleteEvents || snapshot.calendarCleanupPending,
),
);
if (deleteEvents) {
await calendar.deleteOwned(snapshot.calendarEventIds);
await _save(snapshot.copyWith(calendarEventIds: {}));
await _cleanupCalendar();
}
calendarSyncError = null;
});
@@ -166,6 +178,9 @@ class AppController extends ChangeNotifier {
calendarSyncError = '日历权限未获允许';
return;
}
if (snapshot.calendarCleanupPending) {
await _cleanupCalendar();
}
final calendars = await calendar.listWritableCalendars();
if (!calendars.any((c) => c.id == calendarId)) {
calendarSyncError = '请选择可写入的日历';
@@ -200,6 +215,26 @@ class AppController extends ChangeNotifier {
await _reconcile();
});
Future<void> refreshServices() => _run(_reconcile);
Future<void> retryCalendarCleanup() => _run(() async {
if (await calendar.requestAccess()) {
await _cleanupCalendar();
} else {
calendarSyncError = '日历权限未获允许,课程日程尚未清理';
}
});
Future<void> _cleanupCalendar() async {
try {
await calendar.deleteOwned(snapshot.calendarEventIds);
await _save(
snapshot.copyWith(calendarEventIds: {}, calendarCleanupPending: false),
);
calendarSyncError = null;
} catch (_) {
calendarSyncError = '课程日程尚未清理,请允许日历访问后重试';
rethrow;
}
}
Future<void> _reconcile() async {
if (!storageReady) {
return;
@@ -220,6 +255,13 @@ class AppController extends ChangeNotifier {
message: '提醒设置未完成,可重试',
);
}
if (snapshot.calendarCleanupPending) {
try {
await _cleanupCalendar();
} catch (_) {
return;
}
}
if (settings.calendarEnabled && settings.calendarId != null) {
try {
final ids = await calendar.sync(