feat(账号/待办): 日历本区分日历与待办类型,待办标签两级判定 #6
用户要求两点:
1. 添加/修改账号时,在颜色前面显示图标区分「日历本 / 待办本」
2. 没勾选任何待办本 → 待办标签不显示;选了待办本但没数据 → 也不显示
## 协议层:supported-calendar-component-set
CalDAV 用这个属性声明集合支持哪些组件:
<C:supported-calendar-component-set>
<C:comp name="VEVENT"/> ← 纯日历本
<C:comp name="VTODO"/> ← 纯待办本
</C:supported-calendar-component-set>
DavClient 改动:
- PROPFIND 请求加该属性(两处:propfindColors / propfindCalendars)
- 新增 `parseComps()` 归一成四类:event / todo / both / **unknown**
- `DavColorEntry` 与 `DavCalendarEntry` 都加 comps 字段
⭐ 为什么保留 unknown:
很多服务器(含自研实现)压根不返回这个属性。若武断判成"不是待办本",
用户原本能用的日历会被错误分类。unknown 一律按**日历**对待,保持兼容。
## 存储
DavAccount 增加 `calendarComps: string[]`,与 calendarHrefs 一一对应。
JSON 存储天然支持;旧数据读出来是空数组 → 全部 unknown → 视为日历。
## 界面
EditCalendarRow 在颜色圆点**前面**加类型图标,用户先看类型再看颜色:
· 待办本 → ✓ 配成功色
· 混合本 → ▦✓
· 日历/unknown → ▦
## 待办标签两级判定
1. `hasTodoBook()`:被选中的日历本里存在 comps 为 todo/both 的
—— 一个都没选 ⇒ 必然没待办,直接不显示
2. `todos.length > 0`
—— 选了待办本但没数据,也不显示
比只看条数更准:没勾待办本时,同步可能拉到残留数据,
只看条数会误显示;第一级在"还没同步"时就能给出确定答案,不会闪一下。
## 待确认(需真机日志)
服务器是否真的返回 supported-calendar-component-set。
诊断日志已加:`日历本组件类型 <名称> → <类型>`。
若全是 unknown,说明服务器没声明 ⇒ 图标会退化成日历图标,
此时需要改用其它判据(如按本内是否含 VTODO 探测)。
This commit is contained in:
@@ -1514,10 +1514,11 @@ struct Index {
|
||||
this.modeTab('month', '月')
|
||||
this.modeTab('week', '周')
|
||||
this.modeTab('agenda', '列表')
|
||||
// ⭐ 待办页签按需显示:**没有待办就不显示**。
|
||||
// ⭐ 待办页签两级判定(用户要求):
|
||||
// ① 没勾选任何待办本(VTODO)→ 必然没待办,直接不显示
|
||||
// ② 选了待办本,但实际待办数为 0 → 也不显示
|
||||
// 否则用户点进去一片空白,会以为功能坏了。
|
||||
// todos 已按"可见日历本"过滤,所以这里判定 = 用户实际能看到的待办数。
|
||||
if (this.todos.length > 0) {
|
||||
if (this.shouldShowTodoTab()) {
|
||||
this.modeTab('todo', '待办')
|
||||
}
|
||||
Blank()
|
||||
@@ -2070,6 +2071,36 @@ struct Index {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ⭐ HAS_TODO_BOOK 是否勾选了"待办本"。
|
||||
*
|
||||
* 判定:该账号的 calendarComps 里,**被选中**的日历本中存在 'todo' 或 'both'。
|
||||
* 一个都没选 ⇒ 必然没有待办,待办标签直接不显示。
|
||||
*
|
||||
* 兼容:calendarComps 为空(旧账号数据没这个字段)或值 'unknown'
|
||||
* 时不判定为待办本,退回由"待办条数>0"来决定,避免误隐藏。
|
||||
*/
|
||||
private hasTodoBook(): boolean {
|
||||
for (const acc of this.accounts) {
|
||||
const comps: string[] = acc.calendarComps;
|
||||
if (comps === undefined || comps.length === 0) {
|
||||
continue; // 旧数据:交给条数判定
|
||||
}
|
||||
for (let i = 0; i < acc.calendarHrefs.length && i < comps.length; i++) {
|
||||
const c: string = comps[i];
|
||||
if (c === 'todo' || c === 'both') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 待办标签是否该显示:必须"选了待办本" **且** "确实有待办数据" */
|
||||
private shouldShowTodoTab(): boolean {
|
||||
return this.hasTodoBook() && this.todos.length > 0;
|
||||
}
|
||||
|
||||
/** 当前选中日是否就是今天(用于「今天」按钮的视觉状态) */
|
||||
private isOnToday(): boolean {
|
||||
return this.selectedDate === this.startOfDay(Date.now());
|
||||
|
||||
Reference in New Issue
Block a user