1.修改了设置页面的展示顺序。
2.在设置页面新增了软件特性和使用帮助。 3.设置页面中,静音和只读合并。
This commit is contained in:
@@ -427,13 +427,8 @@ struct Index {
|
||||
}
|
||||
|
||||
private openEvent(e: DisplayEvent): void {
|
||||
// 只读日历本或系统日历日程:无法保存修改,直接显示详情
|
||||
if (e.isSystem || !e.writable) {
|
||||
// 所有日程点击都弹出详情(只读/可写/系统一致);可写日程在详情中可点"编辑"进入编辑页
|
||||
this.showEventDetail(e);
|
||||
return;
|
||||
}
|
||||
AppStorage.setOrCreate<number>('pendingEventId', e.id);
|
||||
router.pushUrl({ url: 'pages/EventEditPage' });
|
||||
}
|
||||
|
||||
/** 只读日程详情:改为卡片式半屏弹层(与编辑页风格一致) */
|
||||
@@ -729,6 +724,25 @@ struct Index {
|
||||
.align(Alignment.Top)
|
||||
.layoutWeight(1)
|
||||
}
|
||||
// 可写日程:详情底部提供"编辑"入口(系统/只读日程无此按钮)
|
||||
if (this.detailEvent !== null && !this.detailEvent.isSystem && this.detailEvent.writable) {
|
||||
Button('编辑日程')
|
||||
.width('100%')
|
||||
.height(44)
|
||||
.fontSize(15)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor($r('app.color.button_text'))
|
||||
.backgroundColor($r('app.color.brand'))
|
||||
.borderRadius(12)
|
||||
.onClick(() => {
|
||||
const id: number = this.detailEvent !== null ? this.detailEvent.id : 0;
|
||||
this.detailShow = false;
|
||||
if (id > 0) {
|
||||
AppStorage.setOrCreate<number>('pendingEventId', id);
|
||||
router.pushUrl({ url: 'pages/EventEditPage' });
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
@@ -1739,6 +1753,19 @@ struct Index {
|
||||
.backgroundColor($r('app.color.chip_off_bg'))
|
||||
}
|
||||
}
|
||||
if (e.location !== '') {
|
||||
Row({ space: 4 }) {
|
||||
Text('📍')
|
||||
.fontSize(11)
|
||||
.fontColor($r('app.color.text_hint'))
|
||||
Text(e.location)
|
||||
.fontSize(12)
|
||||
.fontColor($r('app.color.text_hint'))
|
||||
.maxLines(1)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.layoutWeight(1)
|
||||
|
||||
@@ -2,17 +2,15 @@
|
||||
// 设置页:系统日历模式(仅显示/备份到 CalDAV)+ 混合显示开关 + 自动同步间隔 + 后台同步
|
||||
import { router } from '@kit.ArkUI';
|
||||
import { common } from '@kit.AbilityKit';
|
||||
import { pasteboard } from '@kit.BasicServicesKit';
|
||||
import { notificationManager } from '@kit.NotificationKit';
|
||||
import { AppSettings } from '../common/AppSettings';
|
||||
import { BackgroundSyncService } from '../common/BackgroundSyncService';
|
||||
import { AccountStore, DavAccount } from '../common/AccountStore';
|
||||
import { ReminderService } from '../common/ReminderService';
|
||||
import { LogUtil } from '../common/LogUtil';
|
||||
|
||||
const INTERVAL_OPTIONS: number[] = [1, 5, 15, 30, 60];
|
||||
|
||||
/** 日历本选项(备份目标 / 只读标记共用) */
|
||||
/** 日历本选项(备份目标 / 只读标记 / 静音标记共用) */
|
||||
class BackupTarget {
|
||||
calKey: string = '';
|
||||
label: string = '';
|
||||
@@ -28,13 +26,12 @@ struct SettingsPage {
|
||||
@State sysMode: string = 'display'; // display | backup
|
||||
@State backupKey: string = '';
|
||||
@State backupTargets: BackupTarget[] = [];
|
||||
@State allBooks: BackupTarget[] = []; // 全部 DAV 日历本(只读标记管理用)
|
||||
@State allBooks: BackupTarget[] = []; // 全部 DAV 日历本(只读/静音标记管理用)
|
||||
@State manualKeys: string[] = []; // 手动标记只读的 calKey
|
||||
@State mutedKeys: string[] = []; // 提醒静音的 calKey
|
||||
@State showLogSheet: boolean = false; // 同步日志查看弹层
|
||||
@State logText: string = '';
|
||||
@State notifyEnabled: boolean = true; // 通知权限状态(提醒依赖)
|
||||
@State lastTestResult: string = '';
|
||||
@State showFeatures: boolean = false; // 软件特性弹层
|
||||
@State showHelp: boolean = false; // 使用帮助弹层
|
||||
private context?: common.Context;
|
||||
|
||||
aboutToAppear(): void {
|
||||
@@ -43,7 +40,6 @@ struct SettingsPage {
|
||||
return;
|
||||
}
|
||||
this.context = ctx;
|
||||
LogUtil.init(ctx);
|
||||
AppSettings.getShowSystemCalendar(ctx).then((v: boolean): void => {
|
||||
this.showSystem = v;
|
||||
});
|
||||
@@ -62,6 +58,13 @@ struct SettingsPage {
|
||||
AppSettings.getMutedReminderKeys(ctx).then((v: string[]): void => {
|
||||
this.mutedKeys = v;
|
||||
});
|
||||
this.refreshNotifyState();
|
||||
this.loadBackupSettings();
|
||||
this.loadAllBooks();
|
||||
}
|
||||
|
||||
/** 重新检测通知权限状态 */
|
||||
private refreshNotifyState(): void {
|
||||
notificationManager.isNotificationEnabled()
|
||||
.then((v: boolean): void => {
|
||||
this.notifyEnabled = v;
|
||||
@@ -69,11 +72,9 @@ struct SettingsPage {
|
||||
.catch((): void => {
|
||||
this.notifyEnabled = false;
|
||||
});
|
||||
this.loadBackupSettings();
|
||||
this.loadAllBooks();
|
||||
}
|
||||
|
||||
/** 加载全部 DAV 日历本(含探测到的写权限,只读标记管理用) */
|
||||
/** 加载全部 DAV 日历本(含探测到的写权限,只读/静音标记管理用) */
|
||||
private async loadAllBooks(): Promise<void> {
|
||||
if (this.context === undefined) {
|
||||
return;
|
||||
@@ -116,14 +117,6 @@ struct SettingsPage {
|
||||
});
|
||||
}
|
||||
|
||||
/** 日历本当前只读状态文案 */
|
||||
private bookStateLabel(b: BackupTarget): string {
|
||||
if (this.manualKeys.includes(b.calKey)) {
|
||||
return '只读(手动)';
|
||||
}
|
||||
return b.serverWritable ? '可写' : '只读';
|
||||
}
|
||||
|
||||
/** 切换日历本提醒静音:静音后该本所有日程不再发布系统提醒 */
|
||||
private async toggleMuteBook(b: BackupTarget): Promise<void> {
|
||||
if (this.context === undefined) {
|
||||
@@ -179,7 +172,6 @@ struct SettingsPage {
|
||||
// 手动标记只读的本不可作为备份目标
|
||||
const manual: string[] = await AppSettings.getManualReadonlyKeys(this.context);
|
||||
this.backupTargets = targets.filter((t: BackupTarget): boolean => !manual.includes(t.calKey));
|
||||
this.backupTargets = targets;
|
||||
const saved: string = await AppSettings.getBackupCalKey(this.context);
|
||||
this.backupKey = targets.some((t: BackupTarget): boolean => t.calKey === saved) ? saved : '';
|
||||
}
|
||||
@@ -191,7 +183,6 @@ struct SettingsPage {
|
||||
this.sysMode = mode;
|
||||
await AppSettings.setSysCalMode(this.context, mode);
|
||||
if (mode === 'backup' && this.backupKey === '') {
|
||||
// 自动选中第一个可写日历本
|
||||
if (this.backupTargets.length > 0) {
|
||||
this.backupKey = this.backupTargets[0].calKey;
|
||||
await AppSettings.setBackupCalKey(this.context, this.backupKey);
|
||||
@@ -287,63 +278,30 @@ struct SettingsPage {
|
||||
});
|
||||
}
|
||||
|
||||
/** 打开同步日志查看弹层 */
|
||||
private openLogSheet(): void {
|
||||
if (this.context === undefined) {
|
||||
return;
|
||||
}
|
||||
this.logText = LogUtil.readAll(this.context);
|
||||
this.showLogSheet = true;
|
||||
}
|
||||
|
||||
/** 复制全部日志到剪贴板(方便粘贴给我诊断) */
|
||||
private copyLog(): void {
|
||||
/** 去系统设置开启本应用通知 */
|
||||
private async openNotifySettings(): Promise<void> {
|
||||
if (this.context === undefined) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data: pasteboard.PasteData = pasteboard.createData(
|
||||
pasteboard.MIMETYPE_TEXT_PLAIN, LogUtil.readAll(this.context));
|
||||
pasteboard.getSystemPasteboard().setData(data)
|
||||
.then((): void => {
|
||||
this.getUIContext().getPromptAction().showToast({ message: '日志已复制到剪贴板' });
|
||||
})
|
||||
.catch((): void => {
|
||||
this.getUIContext().getPromptAction().showToast({ message: '复制失败' });
|
||||
});
|
||||
await notificationManager.requestEnableNotification(this.context as common.UIAbilityContext);
|
||||
this.refreshNotifyState(); // 返回后重新检测状态
|
||||
} catch (err) {
|
||||
this.getUIContext().getPromptAction().showToast({ message: '复制失败' });
|
||||
// 用户取消或未跳转,状态保持原样
|
||||
}
|
||||
}
|
||||
|
||||
private clearLog(): void {
|
||||
if (this.context === undefined) {
|
||||
/** 打开外部链接(如开源仓库) */
|
||||
private async openUrl(url: string): Promise<void> {
|
||||
const context = this.getUIContext().getHostContext();
|
||||
if (context === undefined) {
|
||||
return;
|
||||
}
|
||||
LogUtil.clear(this.context);
|
||||
this.logText = '(日志已清空)';
|
||||
this.getUIContext().getPromptAction().showToast({ message: '日志已清空' });
|
||||
try {
|
||||
await (context as common.UIAbilityContext).openLink(url);
|
||||
} catch (err) {
|
||||
this.getUIContext().getPromptAction().showToast({ message: '无法打开链接' });
|
||||
}
|
||||
|
||||
/** 发布 1 分钟后的测试提醒,验证提醒链路 */
|
||||
private async testReminder(): Promise<void> {
|
||||
if (this.context === undefined) {
|
||||
return;
|
||||
}
|
||||
this.lastTestResult = await ReminderService.publishTestReminder(
|
||||
this.context as common.UIAbilityContext);
|
||||
}
|
||||
|
||||
/** 按当前数据立即重建提醒,显示发布条数 */
|
||||
private async refreshNow(): Promise<void> {
|
||||
if (this.context === undefined) {
|
||||
return;
|
||||
}
|
||||
const n: number = await ReminderService.refreshReminders(
|
||||
this.context as common.UIAbilityContext);
|
||||
this.getUIContext().getPromptAction().showToast({
|
||||
message: n > 0 ? `已发布 ${n} 个提醒` : '没有发布任何提醒(可能都过了提醒时间、被静音或通知未开启,详见日志)'
|
||||
});
|
||||
}
|
||||
|
||||
build() {
|
||||
@@ -432,113 +390,8 @@ struct SettingsPage {
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
|
||||
// 日历本只读标记(部分服务器不在 CalDAV 层拒绝写入,自动探测无法区分时手动标记)
|
||||
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.bookStateLabel(b))
|
||||
.fontSize(11)
|
||||
.fontColor(this.bookStateLabel(b) === '可写'
|
||||
? $r('app.color.success') : $r('app.color.error'))
|
||||
.padding({ left: 8, right: 8, top: 3, bottom: 3 })
|
||||
.borderRadius(10)
|
||||
.backgroundColor(this.bookStateLabel(b) === '可写'
|
||||
? $r('app.color.success_bg') : $r('app.color.error_bg'))
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ top: 6, bottom: 6 })
|
||||
.onClick(() => {
|
||||
this.toggleManualBook(b);
|
||||
})
|
||||
}, (b: BackupTarget) => `${b.calKey}_${this.manualKeys.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') })
|
||||
|
||||
// 日历本提醒静音(如别人分享的日历本,静音后其中所有日程不再提醒)
|
||||
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') })
|
||||
|
||||
// 数据修复:手动触发一次性全量重拉(重建提醒等本地残缺字段)
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 10 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text('重建日程数据')
|
||||
@@ -559,12 +412,16 @@ struct SettingsPage {
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
|
||||
// 混合显示系统日历
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 10 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text('混合显示系统日历')
|
||||
@@ -587,12 +444,16 @@ struct SettingsPage {
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
|
||||
// 自动同步间隔
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 10 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text('自动同步间隔')
|
||||
@@ -621,12 +482,16 @@ struct SettingsPage {
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
|
||||
// 后台持续同步(长时任务)
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 10 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text('后台持续同步')
|
||||
@@ -649,20 +514,24 @@ struct SettingsPage {
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
// 提醒诊断:通知权限状态 + 测试提醒 + 立即刷新
|
||||
|
||||
// 通知权限:仅检测是否开启,未开启则引导去设置
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 10 }) {
|
||||
Column({ space: 2 }) {
|
||||
Row({ space: 6 }) {
|
||||
Text('提醒诊断')
|
||||
Text('通知权限')
|
||||
.fontSize(15)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
Text(this.notifyEnabled ? '通知已开启' : '通知未开启!')
|
||||
Text(this.notifyEnabled ? '已开启' : '未开启')
|
||||
.fontSize(11)
|
||||
.fontColor(this.notifyEnabled ? $r('app.color.success') : $r('app.color.error'))
|
||||
.padding({ left: 8, right: 8, top: 3, bottom: 3 })
|
||||
@@ -670,8 +539,8 @@ struct SettingsPage {
|
||||
.backgroundColor(this.notifyEnabled ? $r('app.color.success_bg') : $r('app.color.error_bg'))
|
||||
}
|
||||
Text(this.notifyEnabled
|
||||
? '点"测试提醒"验证链路:1 分钟后应收到通知'
|
||||
: '系统设置 → 通知管理 → 找到本应用 → 允许通知,日程提醒才能弹出')
|
||||
? '日程提醒将正常以系统通知弹出'
|
||||
: '未开启系统通知,日程提醒无法弹出')
|
||||
.fontSize(12)
|
||||
.fontColor($r('app.color.text_secondary'))
|
||||
}
|
||||
@@ -679,25 +548,13 @@ struct SettingsPage {
|
||||
.layoutWeight(1)
|
||||
}
|
||||
.width('100%')
|
||||
Row({ space: 10 }) {
|
||||
Button('测试提醒')
|
||||
if (!this.notifyEnabled) {
|
||||
Button('去开启通知')
|
||||
.fontSize(13)
|
||||
.backgroundColor($r('app.color.brand'))
|
||||
.onClick(() => {
|
||||
this.testReminder();
|
||||
this.openNotifySettings();
|
||||
})
|
||||
Button('立即刷新提醒')
|
||||
.fontSize(13)
|
||||
.backgroundColor($r('app.color.text_secondary'))
|
||||
.onClick(() => {
|
||||
this.refreshNow();
|
||||
})
|
||||
}
|
||||
if (this.lastTestResult !== '') {
|
||||
Text(this.lastTestResult)
|
||||
.fontSize(12)
|
||||
.fontColor($r('app.color.text_secondary'))
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
@@ -707,27 +564,143 @@ struct SettingsPage {
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
|
||||
// 同步日志:查看/复制/清空(真机测试诊断用)
|
||||
// 软件特性(点击弹层;bindSheet 挂在本卡片上,避免与其它弹层冲突)
|
||||
Column({ space: 8 }) {
|
||||
Row({ space: 10 }) {
|
||||
Column({ space: 2 }) {
|
||||
Text('同步日志')
|
||||
Text('软件特性')
|
||||
.fontSize(15)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
Text('记录每次同步/推送/提醒的详细过程,测试出问题时复制日志用于分析')
|
||||
Text('了解这个应用的特点与隐私理念')
|
||||
.fontSize(12)
|
||||
.fontColor($r('app.color.text_secondary'))
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.layoutWeight(1)
|
||||
Button('查看')
|
||||
.fontSize(13)
|
||||
.backgroundColor($r('app.color.brand'))
|
||||
Text('›')
|
||||
.fontSize(18)
|
||||
.fontColor($r('app.color.text_hint'))
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
.onClick(() => {
|
||||
this.openLogSheet();
|
||||
this.showFeatures = true;
|
||||
})
|
||||
.bindSheet($$this.showFeatures, this.featureSheet(), {
|
||||
height: 560,
|
||||
dragBar: true,
|
||||
showClose: true,
|
||||
title: { title: '软件特性' }
|
||||
})
|
||||
|
||||
// 使用帮助(点击弹层;bindSheet 挂在本卡片上)
|
||||
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)
|
||||
Text('›')
|
||||
.fontSize(18)
|
||||
.fontColor($r('app.color.text_hint'))
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
.border({ width: 1, color: $r('app.color.shadow_color') })
|
||||
.onClick(() => {
|
||||
this.showHelp = true;
|
||||
})
|
||||
.bindSheet($$this.showHelp, this.helpSheet(), {
|
||||
height: 560,
|
||||
dragBar: true,
|
||||
showClose: true,
|
||||
title: { title: '使用帮助' }
|
||||
})
|
||||
|
||||
// 日历本只读 / 静音(放在最下方;本多时列表较长)
|
||||
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)
|
||||
Button(this.manualKeys.includes(b.calKey) ? '已只读' : '只读')
|
||||
.fontSize(11)
|
||||
.height(28)
|
||||
.fontColor(this.manualKeys.includes(b.calKey)
|
||||
? $r('app.color.button_text') : $r('app.color.text_secondary'))
|
||||
.backgroundColor(this.manualKeys.includes(b.calKey)
|
||||
? $r('app.color.brand') : $r('app.color.card_bg'))
|
||||
.border({
|
||||
width: this.manualKeys.includes(b.calKey) ? 0 : 1,
|
||||
color: $r('app.color.shadow_color')
|
||||
})
|
||||
.onClick(() => {
|
||||
this.toggleManualBook(b);
|
||||
})
|
||||
Button(this.mutedKeys.includes(b.calKey) ? '已静音' : '静音')
|
||||
.fontSize(11)
|
||||
.height(28)
|
||||
.fontColor(this.mutedKeys.includes(b.calKey)
|
||||
? $r('app.color.button_text') : $r('app.color.text_secondary'))
|
||||
.backgroundColor(this.mutedKeys.includes(b.calKey)
|
||||
? $r('app.color.error') : $r('app.color.card_bg'))
|
||||
.border({
|
||||
width: this.mutedKeys.includes(b.calKey) ? 0 : 1,
|
||||
color: $r('app.color.shadow_color')
|
||||
})
|
||||
.onClick(() => {
|
||||
this.toggleMuteBook(b);
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ top: 6, bottom: 6 })
|
||||
}, (b: BackupTarget) => `book_${b.calKey}_r${this.manualKeys.includes(b.calKey) ? 1 : 0}_m${this.mutedKeys.includes(b.calKey) ? 1 : 0}`)
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width('100%')
|
||||
.padding(14)
|
||||
.borderRadius(12)
|
||||
.backgroundColor($r('app.color.card_bg'))
|
||||
@@ -739,11 +712,6 @@ struct SettingsPage {
|
||||
.layoutWeight(1)
|
||||
.align(Alignment.Top)
|
||||
.scrollBar(BarState.Off)
|
||||
.bindSheet($$this.showLogSheet, this.logSheetBuilder(), {
|
||||
height: 560,
|
||||
dragBar: true,
|
||||
title: { title: '同步日志' }
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
@@ -751,41 +719,151 @@ struct SettingsPage {
|
||||
}
|
||||
|
||||
@Builder
|
||||
logSheetBuilder() {
|
||||
Column({ space: 10 }) {
|
||||
Row({ space: 10 }) {
|
||||
Button('复制全部')
|
||||
featureSheet() {
|
||||
Scroll() {
|
||||
Column({ space: 12 }) {
|
||||
Text('隐私与数据')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 数据自持:你的所有日程、待办只存放在你自己(或所在机构)的 CalDAV 服务器上,我们(开发者)不保存你的任何日程或账户数据。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 账户加密:CalDAV 账号的密码在本地以 AES-256-GCM 加密保存,只有发起同步时才临时解密使用,不会以明文留存。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 开源透明:本项目完全开源,代码可自行查看与审计,不藏任何后台上传逻辑。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Button('打开开源仓库')
|
||||
.fontSize(13)
|
||||
.backgroundColor($r('app.color.brand'))
|
||||
.onClick(() => {
|
||||
this.copyLog();
|
||||
this.openUrl('https://gitee.com/dryangyq/SyncCalendar');
|
||||
})
|
||||
Button('清空')
|
||||
.fontSize(13)
|
||||
.backgroundColor($r('app.color.error'))
|
||||
.onClick(() => {
|
||||
this.clearLog();
|
||||
})
|
||||
Button('刷新')
|
||||
.fontSize(13)
|
||||
.backgroundColor($r('app.color.text_secondary'))
|
||||
.onClick(() => {
|
||||
this.openLogSheet();
|
||||
})
|
||||
}
|
||||
Scroll() {
|
||||
Text(this.logText === '' ? '(日志为空)' : this.logText)
|
||||
.fontSize(11)
|
||||
Text('同步能力')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
.margin({ top: 4 })
|
||||
Text('• 双向同步:本地新建/修改会自动推送到服务器,服务器上的变更也会自动拉取,多设备保持一致。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 多账号多日历本统一管理,并可与手机系统日历混合展示。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 完整重复规则(RRULE)与多种提前提醒(可多选:5/10/15/30/60 分钟/1 天等)。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 只读日历本标记、他人分享日历本一键静音免打扰。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 后台持续同步(长时任务),退到后台也按设定间隔继续同步。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 日程地址一键拉起高德地图导航(系统地理编码定位,无需额外配置)。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('• 提醒走系统本地通知,不依赖厂商云推送;在系统无代理提醒配额时自动降级为应用内通知(需 App 在前台或开启后台同步)。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.width('100%')
|
||||
.align(Alignment.Top)
|
||||
.scrollBar(BarState.On)
|
||||
.padding(16)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor($r('app.color.page_bg'))
|
||||
}
|
||||
|
||||
@Builder
|
||||
helpSheet() {
|
||||
Scroll() {
|
||||
Column({ space: 12 }) {
|
||||
Text('一、添加账号')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
Text('在「账号」页填写你的 CalDAV 服务器地址(如群晖 https://域名:5006)、用户名与密码。账号信息在本地加密保存,不会上传给开发者。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
|
||||
Text('二、查看与新建日程')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
.margin({ top: 4 })
|
||||
Text('首页支持月 / 周 / 日 / 列表视图。点「+」新建日程:选择所属日历本、开始/结束时间、重复规则、提醒(可多选),并可填写地址用于导航。点列表中任意日程都会弹出详情;详情中若有地址,点「导航 ›」即可拉起高德地图;可写日程还能点「编辑日程」修改。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
|
||||
Text('三、同步')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
.margin({ top: 4 })
|
||||
Text('App 处于打开状态时按设定间隔自动同步。开启「后台持续同步」后,退到后台也会继续同步(通知栏有常驻通知)。同步期间会保持屏幕常亮,避免熄屏中断。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
|
||||
Text('四、只读与静音')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
.margin({ top: 4 })
|
||||
Text('把某个日历本标记为「只读」后,其中日程只能查看、不再可新建(适用于他人共享给你、或服务器侧不让改的本)。把分享来的日历本「静音」,其中所有日程都不再弹提醒,避免被打扰。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
|
||||
Text('五、提醒')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
.margin({ top: 4 })
|
||||
Text('日程会在开始前按设定提前量弹出系统通知。请在系统设置中开启本应用「通知」权限(设置页可检测并一键前往开启)。提醒依赖系统代理提醒配额;若系统额度为 0,将自动改用应用内通知。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
|
||||
Text('六、系统日历与数据修复')
|
||||
.fontSize(16)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
.margin({ top: 4 })
|
||||
Text('可开启「混合显示系统日历」,把手机自带日历也一并展示;或开启「备份到 CalDAV」,把系统本地日程导入所选日历本,换机/丢失也有备份。若发现提醒丢失等异常,可点「重建日程数据」让下次同步重新拉取完整数据。')
|
||||
.fontSize(14)
|
||||
.fontColor($r('app.color.text_primary'))
|
||||
.width('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.align(Alignment.Top)
|
||||
.padding(16)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor($r('app.color.page_bg'))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user