0.0.8 修复:系统日历重复提醒 / 已过日程仍提醒
用户反馈:① 日程已开始/已过去,系统日历仍提醒;② 同一提前量(如提前 15 分钟) 提醒两次;③ 怀疑"打开 App 后又写一次系统日历"就多提醒一次。 诊断见《系统日历重复提醒-根因诊断.md》。用户怀疑正确,确为两个 bug。 修复一:消除双通道重复提醒(提醒两次) - 根因:镜像到系统日历后,**系统日历自己会提醒**(条目 reminderTime), 而 ReminderService 为**所有**本地日程排代理提醒、**完全不区分**该本是否已镜像 → 同一条日程、同一提前量被两个应用各弹一次。 - 改法:新增 `ReminderService.mirroredKeys()` —— 取"已镜像到系统日历"的日历本 calKey 集合(仅在「镜像开关已开 + 有系统日历权限 + 有选中本」时才非空), `refreshReminders` 与 `tickReminders` **两处都跳过**这些本,改由系统日历提醒。 - ⚠️ 保守设计:判定失败一律返回**空集**(不跳过任何本)→ 宁可多提醒,绝不漏提醒。 - ⚠️ 交互完整性:镜像开关变化时必须**立即失效缓存并重排提醒**(否则会漏提醒): · 开启镜像 → 交回系统日历负责;· 关闭镜像 → **立刻恢复 App 提醒**; · 勾选本变化、权限被系统回收 → 同样失效缓存并重排。 新增 `ReminderService.invalidateMirrorCache()`。 修复二:消除"已过去的日程仍提醒" - 根因:镜像窗口含**过去 12 个月**(windowStart 往前推 12 月),过去的日程也在系统日历里; 而 `updateEvent` 是**整条覆写**(带 reminderTime),系统在覆写时会**重新计算提醒时刻**, 时刻已过就**立刻补发**一条 → 表现为"过去了还提醒"。 - 改法:`toSystemEvent` 写入时只带**提醒时刻尚未到**的提醒(新增 `futureReminders()`)。 已过期提醒已无意义 → 不写,从根上消除覆写补发。 ⭐ 全天日程按系统口径以**当天 09:00** 为提醒基准(新增 `reminderBaseMs()`)。 - 刻意**不收缩镜像窗口**:保住历史日程在系统日历中的可见性,只去掉提醒。 修复三:让"改了提醒时间"能同步到系统日历(反向 bug) - 根因:`diffOf` 只比较 title/isAllDay/start/end/description/location, **不比较 reminderTime** → 用户改了提醒时间被判"无差异",永不触发 updateEvent → 系统日历侧提醒一直不更新。 - 改法:`diffOf` 纳入 `reminderTime` 比较,用规范化 key(排序去重)避免因顺序/重复误判, 且与修复二同口径(只比"会被写入的"提醒),不会导致每轮都重写。 验证: - 编译通过(BUILD SUCCESSFUL)。 - 离线用例全部通过: · 修复二:已过去/提醒刚过/昨天全天 → 不写提醒;未来日程/明天全天 → 保留; · 修复三:提醒改了/新增 → 触发覆写;相同集合(顺序不同、含重复)→ 不覆写。 - 手机未连接 → 未装机(待用户插线测试)。
This commit is contained in:
@@ -110,6 +110,8 @@ struct SettingsPage {
|
||||
if (!ok && this.context !== undefined) {
|
||||
this.mirrorEnabled = false;
|
||||
AppSettings.setMirrorEnabled(this.context, false);
|
||||
// 权限被回收 → 镜像失效 → 提醒应交回 App 负责
|
||||
ReminderService.invalidateMirrorCache();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -518,13 +520,19 @@ struct SettingsPage {
|
||||
}
|
||||
this.mirrorEnabled = isOn;
|
||||
await AppSettings.setMirrorEnabled(this.context, isOn);
|
||||
// ⭐ 镜像开关变化 → 立即失效提醒侧的"已镜像本"缓存,并重排提醒
|
||||
// (开启:这些本改由系统日历提醒,App 不再重复;关闭:必须立刻恢复 App 提醒,避免漏提醒)
|
||||
ReminderService.invalidateMirrorCache();
|
||||
if (isOn) {
|
||||
this.getUIContext().getPromptAction().showToast({
|
||||
message: '已开启镜像:勾选要同步的日历本后点「立即执行镜像」'
|
||||
});
|
||||
await ReminderService.refreshReminders(this.context as common.UIAbilityContext);
|
||||
return;
|
||||
}
|
||||
const n: number = await SystemCalendarMirror.removeAll(this.context);
|
||||
// 关闭镜像后,这些本的提醒要交回 App 负责
|
||||
await ReminderService.refreshReminders(this.context as common.UIAbilityContext);
|
||||
this.getUIContext().getPromptAction().showToast({
|
||||
message: n > 0 ? `已关闭镜像,并清除系统日历中的 ${n} 个镜像账户` : '已关闭镜像'
|
||||
});
|
||||
@@ -545,6 +553,9 @@ struct SettingsPage {
|
||||
return;
|
||||
}
|
||||
await AppSettings.setMirrorBookIds(this.context, this.mirrorKeys);
|
||||
// ⭐ 勾选本变化 → 提醒侧"已镜像本"集合变化:失效缓存并重排提醒
|
||||
ReminderService.invalidateMirrorCache();
|
||||
await ReminderService.refreshReminders(this.context as common.UIAbilityContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user