0.0.8 提醒修复(补):已镜像的本由系统日历全权负责,且判据改为"镜像真实存在"
用户要求:如果用户已把自己的日历同步到系统日历里,那么本应用就**完全不再提醒**了 —— 因为那必然是重复提醒。 采纳。同时修正上一版实现的一个**会漏提醒的弱点**: 问题:上一版按"**用户勾选了要镜像的本**"来跳过 App 提醒。但"勾选"只是**意图**, 本可能还没真正写进系统日历(如刚勾选未点「立即执行镜像」、系统日历里还没有对应账户) → 按意图跳过会导致**两边都不提醒(漏提醒)**。 改法:判据改为「**镜像账户真实存在**」,新增 `SystemCalendarMirror.mirroredCalKeys(context)`: 1. 镜像开关未开 / 无系统日历权限 → 直接返回**空集**(不跳过任何本); 2. 读系统日历全部账户,取出 name 以 `synccalendar.mirror.` 开头者的 **bookId**; 3. 与 `listBooks()` 的 `bookId → calKey` 对照 → 只有**账户真实存在**的本才计入。 安全阀:任何异常 → 空集 → 不跳过 → **宁可多提醒,绝不漏提醒**。 `ReminderService.mirroredKeys()` 改为委托给它(保留 30 秒缓存与 `invalidateMirrorCache()`); `refreshReminders` / `tickReminders` 两处仍照旧跳过这些本(跳过即"App 完全不再提醒")。 交互完整性(不变):镜像开关开启/关闭、勾选本变化、权限被回收 四处 均 `invalidateMirrorCache()` + 立即 `refreshReminders()`, 确保**关闭镜像后这些本立刻恢复由 App 提醒**。 验证:编译通过(BUILD SUCCESSFUL);手机未连接 → 未装机。
This commit is contained in:
@@ -12,7 +12,7 @@ import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { EventDb, LocalEvent } from './EventDb';
|
||||
import { AppSettings } from './AppSettings';
|
||||
import { AccountStore } from './AccountStore';
|
||||
import { SystemCalendarMirror, BookRef } from './SystemCalendarMirror';
|
||||
import { SystemCalendarMirror } from './SystemCalendarMirror';
|
||||
import { LogUtil } from './LogUtil';
|
||||
|
||||
export class ReminderService {
|
||||
@@ -34,32 +34,21 @@ export class ReminderService {
|
||||
/**
|
||||
* ⭐⭐ 取"已镜像到系统日历"的日历本 calKey 集合(0.0.8 修复双通道重复提醒)。
|
||||
*
|
||||
* 背景:镜像到系统日历后,**系统日历自己会提醒**(条目的 reminderTime)。
|
||||
* 镜像到系统日历后,**系统日历自己会提醒**(条目的 reminderTime);
|
||||
* 若 App 再为同一个本排代理提醒 → 同一条日程提醒两次。
|
||||
* 因此这里返回"该由系统日历负责提醒"的本,App 侧跳过它们。
|
||||
* 因此这里返回"该由系统日历负责提醒"的本,App 侧**完全不再提醒**它们。
|
||||
*
|
||||
* ⚠️ 判据是"**镜像账户真实存在**"(`SystemCalendarMirror.mirroredCalKeys`),
|
||||
* 而不是"用户勾选了要镜像"—— 后者只是意图,本可能还没被真正写进系统日历;
|
||||
* 按意图跳过会导致"两边都不提醒"(漏提醒)。
|
||||
* ⚠️ 返回空集 = 不跳过任何本(保守:宁可多提醒,不可漏提醒)。
|
||||
* 仅在「镜像开关已开 + 有系统日历权限 + 有选中本」时才真正跳过。
|
||||
*/
|
||||
private static async mirroredKeys(context: common.Context): Promise<Set<string>> {
|
||||
if (Date.now() - ReminderService.mirroredLoadedAt < 30000
|
||||
&& ReminderService.mirroredCalKeys.size > 0) {
|
||||
return ReminderService.mirroredCalKeys;
|
||||
}
|
||||
const out: Set<string> = new Set<string>();
|
||||
try {
|
||||
const on: boolean = await AppSettings.getMirrorEnabled(context);
|
||||
if (on && await SystemCalendarMirror.hasPermission()) {
|
||||
const refs: BookRef[] = await SystemCalendarMirror.selectedBookRefs(context);
|
||||
for (const r of refs) {
|
||||
if (r.calKey !== '') {
|
||||
out.add(r.calKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// 判定失败 → 返回空集(不跳过,避免漏提醒)
|
||||
}
|
||||
const out: Set<string> = await SystemCalendarMirror.mirroredCalKeys(context);
|
||||
ReminderService.mirroredCalKeys = out;
|
||||
ReminderService.mirroredLoadedAt = Date.now();
|
||||
return out;
|
||||
|
||||
@@ -239,6 +239,56 @@ export class SystemCalendarMirror {
|
||||
return name.startsWith(SystemCalendarMirror.ACCOUNT_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* ⭐⭐ 取"**确实已经镜像到系统日历**"的日历本 calKey 集合(按镜像账户的**真实存在性**判定)。
|
||||
*
|
||||
* 与"用户勾选了要镜像的本"不同 —— 后者只是**意图**,本可能还没被真正写进系统日历
|
||||
* (如刚勾选但没点「立即执行镜像」、或根本没开镜像开关)。
|
||||
* 若按"意图"跳过 App 提醒,而系统日历里其实还没有 → **两边都不提醒 = 漏提醒**。
|
||||
* 故这里只认**镜像账户真实存在**这一条。
|
||||
*
|
||||
* ⚠️ 返回**空集**=不跳过任何本(读不到账户时保守处理,宁可多提醒)。
|
||||
* ⚠️ 未开启镜像开关时直接返回空集(省一次系统查询)。
|
||||
*/
|
||||
static async mirroredCalKeys(context: common.Context): Promise<Set<string>> {
|
||||
const out: Set<string> = new Set<string>();
|
||||
try {
|
||||
if (!await AppSettings.getMirrorEnabled(context)) {
|
||||
return out; // 未开启镜像 → 没有任何本由系统日历负责
|
||||
}
|
||||
if (!await SystemCalendarMirror.hasPermission()) {
|
||||
return out; // 无权限 → 系统日历里不可能有我们的条目
|
||||
}
|
||||
const cm: calendarManager.CalendarManager = calendarManager.getCalendarManager(context);
|
||||
const all: calendarManager.Calendar[] = [];
|
||||
const cals: calendarManager.Calendar[] = await cm.getAllCalendars();
|
||||
for (const c of cals) {
|
||||
all.push(c);
|
||||
}
|
||||
// 存在镜像账户 → 其 bookId 对应的本由系统日历负责
|
||||
const presentBookIds: Set<string> = new Set<string>();
|
||||
for (const c of all) {
|
||||
const name: string = c.getAccount().name;
|
||||
if (name.startsWith(SystemCalendarMirror.ACCOUNT_PREFIX)) {
|
||||
presentBookIds.add(name.substring(SystemCalendarMirror.ACCOUNT_PREFIX.length));
|
||||
}
|
||||
}
|
||||
if (presentBookIds.size === 0) {
|
||||
return out;
|
||||
}
|
||||
// bookId → calKey(从当前账号配置解析)
|
||||
const refs: BookRef[] = await SystemCalendarMirror.listBooks(context);
|
||||
for (const r of refs) {
|
||||
if (presentBookIds.has(r.bookId) && r.calKey !== '') {
|
||||
out.add(r.calKey);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
LogUtil.write(`判定"已镜像本"失败(按未镜像处理): ${(err as BusinessError).message}`);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* ==================== 账户身份判定(0.0.8) ==================== */
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user