新增了提醒静音功能,可以在设置中关闭某个日历本的提醒。
This commit is contained in:
@@ -13,6 +13,7 @@ export class AppSettings {
|
|||||||
private static readonly KEY_SYS_MODE: string = 'sys_cal_mode'; // 'display' | 'backup'
|
private static readonly KEY_SYS_MODE: string = 'sys_cal_mode'; // 'display' | 'backup'
|
||||||
private static readonly KEY_BACKUP_KEY: string = 'sys_backup_cal_key'; // 备份目标 DAV 日历本
|
private static readonly KEY_BACKUP_KEY: string = 'sys_backup_cal_key'; // 备份目标 DAV 日历本
|
||||||
private static readonly KEY_MANUAL_READONLY: string = 'manual_readonly_keys'; // 手动标记只读的 calKey
|
private static readonly KEY_MANUAL_READONLY: string = 'manual_readonly_keys'; // 手动标记只读的 calKey
|
||||||
|
private static readonly KEY_MUTED_REMINDER: string = 'muted_reminder_keys'; // 提醒静音的 calKey
|
||||||
private static readonly KEY_FULL_REFETCH: string = 'full_refetch_done'; // 一次性全量重拉已完成
|
private static readonly KEY_FULL_REFETCH: string = 'full_refetch_done'; // 一次性全量重拉已完成
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,6 +87,33 @@ export class AppSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提醒静音的日历本 calKey 列表。
|
||||||
|
* 适用于别人分享的日历本:静音后其中所有日程都不再发布系统提醒(日程本身仍正常显示)。
|
||||||
|
*/
|
||||||
|
static async getMutedReminderKeys(context: common.Context): Promise<string[]> {
|
||||||
|
try {
|
||||||
|
const store: preferences.Preferences =
|
||||||
|
await preferences.getPreferences(context, AppSettings.STORE);
|
||||||
|
const raw: string = await store.get(AppSettings.KEY_MUTED_REMINDER, '') as string;
|
||||||
|
return raw === '' ? [] : raw.split(';');
|
||||||
|
} catch (err) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async setMutedReminderKeys(context: common.Context, keys: string[]): Promise<void> {
|
||||||
|
try {
|
||||||
|
const store: preferences.Preferences =
|
||||||
|
await preferences.getPreferences(context, AppSettings.STORE);
|
||||||
|
await store.put(AppSettings.KEY_MUTED_REMINDER, keys.join(';'));
|
||||||
|
await store.flush();
|
||||||
|
} catch (err) {
|
||||||
|
const e = err as BusinessError;
|
||||||
|
console.error(`保存提醒静音标记失败: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 系统日历模式:display = 仅混合显示;backup = 本地系统日程备份到选定 CalDAV 日历本 */
|
/** 系统日历模式:display = 仅混合显示;backup = 本地系统日程备份到选定 CalDAV 日历本 */
|
||||||
static async getSysCalMode(context: common.Context): Promise<string> {
|
static async getSysCalMode(context: common.Context): Promise<string> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { reminderAgentManager } from '@kit.BackgroundTasksKit';
|
|||||||
import { common } from '@kit.AbilityKit';
|
import { common } from '@kit.AbilityKit';
|
||||||
import { BusinessError } from '@kit.BasicServicesKit';
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
import { EventDb, LocalEvent } from './EventDb';
|
import { EventDb, LocalEvent } from './EventDb';
|
||||||
|
import { AppSettings } from './AppSettings';
|
||||||
import { LogUtil } from './LogUtil';
|
import { LogUtil } from './LogUtil';
|
||||||
|
|
||||||
export class ReminderService {
|
export class ReminderService {
|
||||||
@@ -18,8 +19,13 @@ export class ReminderService {
|
|||||||
const now: number = Date.now();
|
const now: number = Date.now();
|
||||||
const rows: LocalEvent[] =
|
const rows: LocalEvent[] =
|
||||||
await EventDb.queryRemindable(context, now, now + ReminderService.WINDOW);
|
await EventDb.queryRemindable(context, now, now + ReminderService.WINDOW);
|
||||||
|
// 提醒静音的日历本(如别人分享的本):其中所有日程都不再提醒
|
||||||
|
const muted: string[] = await AppSettings.getMutedReminderKeys(context);
|
||||||
let published: number = 0;
|
let published: number = 0;
|
||||||
for (const e of rows) {
|
for (const e of rows) {
|
||||||
|
if (muted.includes(e.calKey)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (published >= ReminderService.MAX_REMINDERS) {
|
if (published >= ReminderService.MAX_REMINDERS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -50,7 +56,7 @@ export class ReminderService {
|
|||||||
await reminderAgentManager.publishReminder(request);
|
await reminderAgentManager.publishReminder(request);
|
||||||
published++;
|
published++;
|
||||||
}
|
}
|
||||||
LogUtil.write(`提醒刷新完成:发布 ${published} 个提醒(窗口 7 天)`);
|
LogUtil.write(`提醒刷新完成:发布 ${published} 个提醒(窗口 7 天,静音日历本 ${muted.length} 个)`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = err as BusinessError;
|
const e = err as BusinessError;
|
||||||
LogUtil.write(`提醒刷新失败: ${e.code} - ${e.message}`);
|
LogUtil.write(`提醒刷新失败: ${e.code} - ${e.message}`);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { common } from '@kit.AbilityKit';
|
|||||||
import { AppSettings } from '../common/AppSettings';
|
import { AppSettings } from '../common/AppSettings';
|
||||||
import { BackgroundSyncService } from '../common/BackgroundSyncService';
|
import { BackgroundSyncService } from '../common/BackgroundSyncService';
|
||||||
import { AccountStore, DavAccount } from '../common/AccountStore';
|
import { AccountStore, DavAccount } from '../common/AccountStore';
|
||||||
|
import { ReminderService } from '../common/ReminderService';
|
||||||
import { LogUtil } from '../common/LogUtil';
|
import { LogUtil } from '../common/LogUtil';
|
||||||
|
|
||||||
const INTERVAL_OPTIONS: number[] = [1, 5, 15, 30, 60];
|
const INTERVAL_OPTIONS: number[] = [1, 5, 15, 30, 60];
|
||||||
@@ -27,6 +28,7 @@ struct SettingsPage {
|
|||||||
@State backupTargets: BackupTarget[] = [];
|
@State backupTargets: BackupTarget[] = [];
|
||||||
@State allBooks: BackupTarget[] = []; // 全部 DAV 日历本(只读标记管理用)
|
@State allBooks: BackupTarget[] = []; // 全部 DAV 日历本(只读标记管理用)
|
||||||
@State manualKeys: string[] = []; // 手动标记只读的 calKey
|
@State manualKeys: string[] = []; // 手动标记只读的 calKey
|
||||||
|
@State mutedKeys: string[] = []; // 提醒静音的 calKey
|
||||||
private context?: common.Context;
|
private context?: common.Context;
|
||||||
|
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
@@ -51,6 +53,9 @@ struct SettingsPage {
|
|||||||
AppSettings.getManualReadonlyKeys(ctx).then((v: string[]): void => {
|
AppSettings.getManualReadonlyKeys(ctx).then((v: string[]): void => {
|
||||||
this.manualKeys = v;
|
this.manualKeys = v;
|
||||||
});
|
});
|
||||||
|
AppSettings.getMutedReminderKeys(ctx).then((v: string[]): void => {
|
||||||
|
this.mutedKeys = v;
|
||||||
|
});
|
||||||
this.loadBackupSettings();
|
this.loadBackupSettings();
|
||||||
this.loadAllBooks();
|
this.loadAllBooks();
|
||||||
}
|
}
|
||||||
@@ -106,6 +111,33 @@ struct SettingsPage {
|
|||||||
return b.serverWritable ? '可写' : '只读';
|
return b.serverWritable ? '可写' : '只读';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 切换日历本提醒静音:静音后该本所有日程不再发布系统提醒 */
|
||||||
|
private async toggleMuteBook(b: BackupTarget): Promise<void> {
|
||||||
|
if (this.context === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list: string[] = [...this.mutedKeys];
|
||||||
|
const idx: number = list.indexOf(b.calKey);
|
||||||
|
if (idx >= 0) {
|
||||||
|
list.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
list.push(b.calKey);
|
||||||
|
}
|
||||||
|
this.mutedKeys = list;
|
||||||
|
await AppSettings.setMutedReminderKeys(this.context, list);
|
||||||
|
// 立即重建提醒(全量取消后按新静音规则重发),无需等下次同步
|
||||||
|
try {
|
||||||
|
await ReminderService.refreshReminders(this.context as common.UIAbilityContext);
|
||||||
|
} catch (err) {
|
||||||
|
// 重建失败不影响设置保存,下次同步时会再刷新
|
||||||
|
}
|
||||||
|
this.getUIContext().getPromptAction().showToast({
|
||||||
|
message: idx >= 0
|
||||||
|
? '已恢复提醒'
|
||||||
|
: '已静音:该日历本的所有日程不再提醒'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** 加载备份目标候选(可写 DAV 日历本)+ 当前选择 */
|
/** 加载备份目标候选(可写 DAV 日历本)+ 当前选择 */
|
||||||
private async loadBackupSettings(): Promise<void> {
|
private async loadBackupSettings(): Promise<void> {
|
||||||
if (this.context === undefined) {
|
if (this.context === undefined) {
|
||||||
@@ -379,6 +411,59 @@ struct SettingsPage {
|
|||||||
.backgroundColor($r('app.color.card_bg'))
|
.backgroundColor($r('app.color.card_bg'))
|
||||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||||
|
|
||||||
|
// 日历本提醒静音(如别人分享的日历本,静音后其中所有日程不再提醒)
|
||||||
|
Column({ space: 8 }) {
|
||||||
|
Row({ space: 10 }) {
|
||||||
|
Column({ space: 2 }) {
|
||||||
|
Text('日历本提醒静音')
|
||||||
|
.fontSize(15)
|
||||||
|
.fontWeight(FontWeight.Medium)
|
||||||
|
.fontColor($r('app.color.text_primary'))
|
||||||
|
Text('点击日历本切换静音:静音后该日历本的所有日程都不再提醒(日程仍正常显示)')
|
||||||
|
.fontSize(12)
|
||||||
|
.fontColor($r('app.color.text_secondary'))
|
||||||
|
}
|
||||||
|
.alignItems(HorizontalAlign.Start)
|
||||||
|
.layoutWeight(1)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
if (this.allBooks.length === 0) {
|
||||||
|
Text('暂无 CalDAV 日历本')
|
||||||
|
.fontSize(12)
|
||||||
|
.fontColor($r('app.color.text_hint'))
|
||||||
|
.width('100%')
|
||||||
|
}
|
||||||
|
ForEach(this.allBooks, (b: BackupTarget) => {
|
||||||
|
Row({ space: 8 }) {
|
||||||
|
Text(b.label)
|
||||||
|
.fontSize(13)
|
||||||
|
.fontColor($r('app.color.text_primary'))
|
||||||
|
.maxLines(1)
|
||||||
|
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||||
|
.layoutWeight(1)
|
||||||
|
Text(this.mutedKeys.includes(b.calKey) ? '已静音' : '提醒中')
|
||||||
|
.fontSize(11)
|
||||||
|
.fontColor(this.mutedKeys.includes(b.calKey)
|
||||||
|
? $r('app.color.error') : $r('app.color.success'))
|
||||||
|
.padding({ left: 8, right: 8, top: 3, bottom: 3 })
|
||||||
|
.borderRadius(10)
|
||||||
|
.backgroundColor(this.mutedKeys.includes(b.calKey)
|
||||||
|
? $r('app.color.error_bg') : $r('app.color.success_bg'))
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.padding({ top: 6, bottom: 6 })
|
||||||
|
.onClick(() => {
|
||||||
|
this.toggleMuteBook(b);
|
||||||
|
})
|
||||||
|
}, (b: BackupTarget) => `mute_${b.calKey}_${this.mutedKeys.includes(b.calKey) ? 1 : 0}`)
|
||||||
|
}
|
||||||
|
.alignItems(HorizontalAlign.Start)
|
||||||
|
.width('100%')
|
||||||
|
.padding(14)
|
||||||
|
.borderRadius(12)
|
||||||
|
.backgroundColor($r('app.color.card_bg'))
|
||||||
|
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||||
|
|
||||||
// 数据修复:手动触发一次性全量重拉(重建提醒等本地残缺字段)
|
// 数据修复:手动触发一次性全量重拉(重建提醒等本地残缺字段)
|
||||||
Row({ space: 10 }) {
|
Row({ space: 10 }) {
|
||||||
Column({ space: 2 }) {
|
Column({ space: 2 }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user