mirror of
https://github.com/panatgithub/AnkiHeadingSync.git
synced 2026-07-22 17:10:28 +00:00
Introduced two new management commands: 'Clear currently synced cards' to reset sync state for the current file, and 'Cleanup empty decks' to remove unused decks from Anki. Both commands improve plugin maintenance and synchronization flow. 新增两个管理命令:'清空当前文件已同步卡片'用于重置当前文件的同步状态,'清理空牌组'用于从 Anki 中移除未使用的牌组。这两个命令改进了插件的维护和同步流程。
4.2 KiB
4.2 KiB
Cleanup / Reset Decisions
1. 命令边界
两个能力都作为显式管理命令实现,不接入 ManualSyncService 的普通同步主链路:
清空当前文件已同步卡片清理空牌组
这样可以直接满足“普通 sync / rebuild / orphan 语义不变”的硬约束。
2. AnkiGateway 扩展
新增接口:
deleteNotes(noteIds: number[]): Promise<void>listDeckNames(): Promise<string[]>getDeckStats(deckNames: string[]): Promise<Array<{ deckName: string; noteCount: number }>>deleteDecks(deckNames: string[]): Promise<void>
实现策略:
- 上层只看“列 deck / 判空 / 删除 deck”语义
- AnkiConnect action 的兼容细节全部封装在
AnkiConnectGateway getDeckStats只要求足够判断空 deck;如果底层返回的是 card 统计而不是 note 统计,网关内部统一映射为noteCount风格字段供上层使用
3. Current-file reset 编排
新增独立 use case:ClearCurrentFileSyncedCardsUseCase。
固定执行顺序:
- 读取
pluginState - 找出当前文件对应 card records
- 收集有
noteId的 noteIds - 先调用
deleteNotes - 再尝试删除该文件内对应 marker
- 最后保存清理后的本地 state
保存规则:
- marker 删除成功时:删除对应
pluginState.cards、pluginState.files[filePath].cardIds、相关pendingWriteBack - marker 删除失败时:不回滚已删除的 Anki notes;保留失败文件对应 card record,但清空其
noteId,并清理相关pendingWriteBack
另外,无论 marker 删除成功还是失败,都删除该文件的 FileState 记录,强制下一次普通同步重新读取正文,而不是复用“当前文件没有卡片变更”的旧索引结论。
这样做的原因:
- 文件内容仍带旧 marker 时,完全删除本地 state 会让后续索引误把旧 marker 的
noteId当成仍可更新的 note - 保留 cardId 但清空
noteId,能让下一次普通同步把它当作“正文仍在、需要重新创建”的卡片,而不是对已删除 note 做 update
这是一项为满足“失败时保持内部一致”而做的最小兼容调整,不扩展成长期 tombstone 状态。
4. Marker removal 实现
不把删除逻辑塞进现有 MarkdownWriteBackService。
新增两层:
- 纯内容变换:marker removal service
- 文件改写编排:Markdown marker removal application service
删除原则:
- 仅删除匹配的 AHS marker 行
- 不改正文
- 不调整其他 card block 顺序
5. Empty deck cleanup 编排
新增独立 use case:CleanupEmptyDecksUseCase。
分两步:
listCandidates():列 deck、取统计、筛空 deckexecute(selectedDeckNames):删除用户确认的 deck,并把“已不存在/已非空”归入 skipped
UI 选择发生在 presentation 层 modal 中,不下沉到 application 层。
6. Presentation 交互
新增两个 plugin 入口方法与两个命令注册项。
空 deck 清理使用一个小型多选 modal:
- 先展示候选空 deck
- 用户勾选
- 确认删除后才调用 use case
如果没有候选 deck,则直接提示,不进入确认流程。
7. 结果类型与 notice
新增独立结果类型:
ClearCurrentFileSyncedCardsResultCleanupEmptyDecksResult
不扩展 ManualSyncResult。
NoticeService 新增两组摘要:
- reset:deleted notes、removed markers、deleted local records、failed/conflict files
- empty decks:candidate count、selected count、deleted count、skipped count
8. 索引兼容修正
当 marker 中有 cardId,且本地 CardState 已存在但 noteId 被清空时,索引恢复身份时应优先信任本地 state 的“无 noteId”结果,而不是回退到 marker 里的旧 noteId。
该修正只服务于 reset 命令的失败恢复,不改变普通同步的删除语义。
9. 测试范围
至少覆盖:
- current-file reset 的全成功路径
- current-file reset 的无
noteId路径 - current-file reset 的 marker 写回失败路径
- reset 后普通同步可重建
- empty deck 候选识别
- empty deck 手选删除
- 已非空/已不存在 deck 的 skip 汇总
- 普通 sync / rebuild / orphan 行为不变