mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 06:51:43 +00:00
- 设置页在有缓存时立即显示缓存摘要,并在打开时只做一次轻量 note type freshness 检查 - 手动读取仍负责完整模板与字段刷新,不会在页面打开时读取所有字段 - Add tests and docs for cache summary, stale-cache warning, and failed background checks
108 lines
No EOL
3.8 KiB
Markdown
108 lines
No EOL
3.8 KiB
Markdown
# 设置页 Anki 模板缓存状态实现决策
|
||
|
||
本文锁定本轮“设置页模板缓存状态 + 后台轻量 freshness 检测”的仓库兼容实现方案。
|
||
|
||
## 1. 作用域决策
|
||
|
||
- 只改设置页 card 1 的状态显示与轻量检测。
|
||
- 不改同步主线。
|
||
- 不新增按需字段读取。
|
||
- 保留现有 manual full refresh 行为。
|
||
|
||
## 2. 缓存状态模型决策
|
||
|
||
- 在 `PluginSettingTab` 中新增实例级状态:
|
||
- `noteTypeCacheCheckStatus: "idle" | "checking" | "same" | "changed" | "failed"`
|
||
- `noteTypeCacheCheckPromise: Promise<void> | null`
|
||
- `detectedAnkiNoteTypeCache: string[] | null`
|
||
- 另增:
|
||
- `cardTypeStatusOverride: UserFacingMessage | null`
|
||
|
||
## 3. 统一状态计算决策
|
||
|
||
- 不再直接渲染原来的 `cardTypeStatus` 字段。
|
||
- 改为通过 `getCardTypeStatusMessage()` 统一计算。
|
||
- 优先级固定为:
|
||
1. `ankiConfigLoading === true`
|
||
2. `cardTypeStatusOverride`
|
||
3. 缓存状态:
|
||
- 无缓存 -> `cacheEmpty`
|
||
- 缓存 + changed -> `cacheChanged`
|
||
- 缓存 + failed -> `cacheCheckFailed`
|
||
- 缓存 + idle/checking/same -> `cacheSummary`
|
||
|
||
## 4. 后台检测启动决策
|
||
|
||
- `renderCardTypesCard()` 每次渲染时调用 `maybeStartNoteTypeCacheCheck()`。
|
||
- 但该方法必须短路以下情况:
|
||
- `ankiConfigLoading === true`
|
||
- `ankiNoteTypeCache.length === 0`
|
||
- `noteTypeCacheCheckPromise !== null`
|
||
- `noteTypeCacheCheckStatus !== "idle"`
|
||
- 这样同一 settings tab 生命周期只会发起一次后台检测。
|
||
|
||
## 5. 轻量检测语义决策
|
||
|
||
- 后台检测只调用 `listNoteModels()`。
|
||
- 不调用:
|
||
- `getModelFieldNamesByModelNames()`
|
||
- `getNoteModelDetails()`
|
||
- `modelTemplates`
|
||
- 比较逻辑使用规范化后的名称列表:
|
||
- trim
|
||
- 过滤空字符串
|
||
- 去重
|
||
- 排序
|
||
- 比较相等 -> `same`
|
||
- 比较不等 -> `changed`
|
||
- 调用失败 -> `failed`
|
||
- 检测结果不写入 `data.json`。
|
||
|
||
## 6. override 与缓存状态交互决策
|
||
|
||
- 手动 full refresh 成功时:
|
||
- `cardTypeStatusOverride = loadedSummary`
|
||
- `noteTypeCacheCheckStatus = "same"`
|
||
- `detectedAnkiNoteTypeCache = 最新 modelNames`
|
||
- 手动 full refresh 失败时:
|
||
- `cardTypeStatusOverride = failedLoad`
|
||
- 保留已有缓存和字段映射
|
||
- 本地 validation/save 失败时:
|
||
- `cardTypeStatusOverride = failedSave` 或具体错误
|
||
- 普通自动保存成功时:
|
||
- 清空 `cardTypeStatusOverride`
|
||
|
||
## 7. 生命周期重置决策
|
||
|
||
- `hide()` 时重置:
|
||
- `noteTypeCacheCheckStatus = "idle"`
|
||
- `noteTypeCacheCheckPromise = null`
|
||
- `detectedAnkiNoteTypeCache = null`
|
||
- `cardTypeStatusOverride = null`
|
||
- 这样每次重新打开设置页都允许重新做一次轻量检测。
|
||
|
||
## 8. manual full refresh 决策
|
||
|
||
- 保持当前完整流程:
|
||
- `listNoteModels()`
|
||
- `getModelFieldNamesByModelNames()`
|
||
- `updateSettings({ ankiNoteTypeCache, ankiModelFieldCache })`
|
||
- `hydrateVisibleCardTypeCaches()`
|
||
- `syncQaGroupMappingFromCache()`
|
||
- 成功后 card 1 继续局部刷新。
|
||
- 失败后继续用缓存渲染下拉和字段。
|
||
|
||
## 9. 受控偏离
|
||
|
||
- 偏离 1:当前仓库的“保存失败”有两类。
|
||
- 设置页内可见的 validate 失败,仍会进入 `cardTypeStatusOverride`
|
||
- `plugin.updateSettings()` 内部持久化失败只通过 NoticeService 通知,当前设置页拿不到错误回传
|
||
- 因此本轮只能稳定覆盖“校验失败”和“手动刷新失败”的 override,不额外改 plugin 层错误合同。
|
||
|
||
- 偏离 2:后台检测中的 `checking` 不单独显示 loading 文案。
|
||
- 仍显示 `cacheSummary`
|
||
- 原因:计划要求检测不阻塞 UI,且 checking 与 same 的用户文案相同
|
||
|
||
- 偏离 3:`detectedAnkiNoteTypeCache` 仅作为实例内调试/状态记录,不参与渲染计数。
|
||
- 渲染中的数量仍来自持久缓存 `ankiNoteTypeCache`
|
||
- 原因:目标文案强调“当前使用缓存的 x 个模板” |