镜像到系统日历:新增「全选/全不选」日历本
设置页镜像勾选网格上方加一行「全选(已选 x/N)」: · 整行可点;勾选框半选时显示为关,点按 = 全选,再次点按 = 全不选; · 全选:一次性把全部候选本(已排除"系统日历备份目标本"防回灌)写入 mirror_book_ids —— preferences 只落盘一次、提醒缓存只失效一次, 与逐个 toggle 的关键区别; · 全不选:逐本 removeById 删对应系统日历账户(与取消单个勾选同语义), 逐个独立 try,失败不影响其余; · onChange 加同值守卫,过滤系统重复回调导致的二次翻转。 验证:assembleHap BUILD SUCCESSFUL;已 install -r 到真机。
This commit is contained in:
@@ -293,6 +293,51 @@ struct SettingsPage {
|
|||||||
return this.allBooks.length - this.mirrorCandidates.length;
|
return this.allBooks.length - this.mirrorCandidates.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 已勾选的可镜像本数量(mirrorKeys 里可能残留已不在候选里的 bookId,按候选口径统计) */
|
||||||
|
private mirrorSelectedCount(): number {
|
||||||
|
return this.mirrorCandidates.filter((b: BackupTarget): boolean =>
|
||||||
|
this.mirrorKeys.indexOf(b.bookId) >= 0).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 「全选 / 全不选」要镜像的日历本。
|
||||||
|
* ⭐ 批量落盘只写一次 preferences、缓存只失效一次(与逐个 toggle 的关键区别);
|
||||||
|
* 全不选时逐本删除对应系统日历账户(与取消单个勾选同一语义)。
|
||||||
|
* 半选状态下点按 = 全选。
|
||||||
|
*/
|
||||||
|
private async toggleMirrorAll(): Promise<void> {
|
||||||
|
if (this.context === undefined || this.mirrorCandidates.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectAll: boolean = this.mirrorSelectedCount() < this.mirrorCandidates.length;
|
||||||
|
if (selectAll) {
|
||||||
|
const ids: string[] = this.mirrorCandidates.map((b: BackupTarget): string => b.bookId);
|
||||||
|
this.mirrorKeys = ids;
|
||||||
|
await AppSettings.setMirrorBookIds(this.context, ids);
|
||||||
|
this.getUIContext().getPromptAction().showToast({
|
||||||
|
message: `已全选 ${ids.length} 个日历本,点「立即执行镜像」写入系统日历`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 逐本删除系统日历账户;逐个独立 try,失败不影响其余
|
||||||
|
for (const k of this.mirrorKeys) {
|
||||||
|
try {
|
||||||
|
await SystemCalendarMirror.removeById(this.context, k);
|
||||||
|
} catch (err) {
|
||||||
|
const e = err as BusinessError;
|
||||||
|
console.error(`全不选:删除镜像账户失败 bookId=${k}: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.mirrorKeys = [];
|
||||||
|
await AppSettings.setMirrorBookIds(this.context, []);
|
||||||
|
this.getUIContext().getPromptAction().showToast({
|
||||||
|
message: '已取消全部勾选,并清除对应的系统日历账户'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// ⭐ 勾选本集合变化 → 提醒侧"已镜像本"缓存失效并重排提醒
|
||||||
|
ReminderService.invalidateMirrorCache();
|
||||||
|
await ReminderService.refreshReminders(this.context as common.UIAbilityContext);
|
||||||
|
}
|
||||||
|
|
||||||
/** 该日历本是否只读:服务器无写权限(探测结果)或用户手动标记只读 —— 与首页色块/只读标记同一口径 */
|
/** 该日历本是否只读:服务器无写权限(探测结果)或用户手动标记只读 —— 与首页色块/只读标记同一口径 */
|
||||||
private isBookReadonly(b: BackupTarget): boolean {
|
private isBookReadonly(b: BackupTarget): boolean {
|
||||||
return !b.serverWritable || this.manualKeys.includes(b.calKey);
|
return !b.serverWritable || this.manualKeys.includes(b.calKey);
|
||||||
@@ -978,6 +1023,35 @@ struct SettingsPage {
|
|||||||
.fontColor($r('app.color.text_hint'))
|
.fontColor($r('app.color.text_hint'))
|
||||||
.width('100%')
|
.width('100%')
|
||||||
}
|
}
|
||||||
|
// ⭐ 全选 / 全不选:半选状态下点按 = 全选
|
||||||
|
Row({ space: 6 }) {
|
||||||
|
Text(`全选(已选 ${this.mirrorSelectedCount()}/${this.mirrorCandidates.length})`)
|
||||||
|
.fontSize(13)
|
||||||
|
.fontWeight(FontWeight.Medium)
|
||||||
|
.fontColor($r('app.color.text_primary'))
|
||||||
|
.layoutWeight(1)
|
||||||
|
.maxLines(1)
|
||||||
|
Toggle({
|
||||||
|
type: ToggleType.Checkbox,
|
||||||
|
isOn: this.mirrorCandidates.length > 0
|
||||||
|
&& this.mirrorSelectedCount() === this.mirrorCandidates.length
|
||||||
|
})
|
||||||
|
.selectedColor($r('app.color.brand'))
|
||||||
|
.onChange((on: boolean): void => {
|
||||||
|
// 半选时勾选框显示为关,onChange(on=true) 走全选;全选时取消走全不选
|
||||||
|
if (on === (this.mirrorSelectedCount() === this.mirrorCandidates.length)) {
|
||||||
|
return; // 状态未变化(个别系统会重复回调),忽略
|
||||||
|
}
|
||||||
|
this.toggleMirrorAll();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.padding({ top: 2, bottom: 2 })
|
||||||
|
.onClick(() => {
|
||||||
|
// 整行可点:直接按"是否已全选"翻转,比依赖 Checkbox 的 onChange 更可靠
|
||||||
|
this.toggleMirrorAll();
|
||||||
|
})
|
||||||
|
|
||||||
Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
|
Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {
|
||||||
ForEach(this.mirrorCandidates, (b: BackupTarget): void => {
|
ForEach(this.mirrorCandidates, (b: BackupTarget): void => {
|
||||||
Row({ space: 6 }) {
|
Row({ space: 6 }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user