容器内 App 手动排序专题讨论纪要
用户目标
- 用户希望在容器中,每个 App 的位置可以拖动,改变默认显示顺序。
- 本轮要求拉 2 个架构师、1 个代码审核员、1 个 QA 做专题讨论,评估可行性、开发风险和最优方案。
参与视角
- 架构师 A:数据模型、分类方案、导入导出、SmartStart 影响。
- 架构师 B:App Grid / 容器视图 / 拖拽交互。
- 代码审核员:风险、必须避免的实现方式、代码切分。
- QA:验收矩阵、自动化与人工验证边界。
关键结论
- 功能可做,但不能只做 UI 数组重排;必须把容器内 App 顺序持久化到
TagDatabase.Store。
- 当前 App 默认顺序来自扫描后名称排序,
AppIndexer.group() 只负责分组,组内顺序没有用户字段。
- 推荐新增
containerAppOrder: [String: [String]],按稳定容器 ID 保存每个容器内的 app path 顺序。
- 容器 ID 不能使用本地化显示名;建议使用
tag:<tagName>、system:<SmartCategoryID>、__container.uncategorized、__container.appleBuiltIn 等稳定 key。
- 新字段必须纳入分类方案快照、导出、导入、恢复、SmartStart 回滚;否则“分类与布局”导出会丢布局。
- 第一版只支持同一容器内拖动排序;跨容器移动/复制标签、拖到空白移除标签、Apple 内置保护等旧行为保持不变。
- 不建议使用 SwiftUI
onDrag/onDrop。当前 App Grid 是 AppKit NSViewRepresentable + 自定义拖拽,拖拽排序应在 AppGridCollectionView / AppGridGroupCardView / AppGridIconNSView 链路扩展。
推荐开发切分
- 数据层:
Store 增加 containerAppOrder,兼容旧 JSON。
- 增加容器 ID helper 和排序 helper。
CategorySchemeFingerprint 纳入顺序字段。
- 导入、导出、恢复、未分类重置、SmartStart replace、tag rename/delete/relocalize 清理或迁移顺序。
- UI hit-test:
AppGridCollectionView 增加同容器插入位置计算。
- 排序拖拽与现有跨 tag 移动/复制拖拽隔离。
- 先做本地预览,不落盘,不改跨容器行为。
- 集成:
ContentView 增加 reorder callback。
- drop/end 时保存该容器完整顺序。
- 刷新
displayGroups 后顺序保持。
- QA:
- 旧 JSON 兼容、新 JSON roundtrip、导入导出、恢复、重置、SmartStart 数据断言。
- macOS 14 typecheck/build metadata/window logic/Quick Search/SmartStart 现有回归。
- 真实鼠标拖拽、滚动拖拽、显示模式、标签位置、编辑模式必须人工 smoke。
风险评估
- 最小方案风险:中等。
- 若一次性支持跨容器插入、跨机器稳定匹配、复杂拖拽 payload、所有显示模式完整预览,风险升为高。
- 最大风险点:
- 刷新/重启后顺序丢失。
- 导入导出/恢复/SmartStart 漏掉顺序。
- 同容器排序误触发跨容器移动、复制、移除标签确认。
- 用本地化显示名做 key 导致语言切换后顺序错位。
- 编辑模式、tag 拖拽排序、hover bubble、滚动抑制互相冲突。
建议决策
- 先做低风险 spike:只做同容器排序,path-based 顺序持久化,所有 display mode 读取排序,但第一版优先在容器/网格容器拖拽入口验证。
- 暂不改 Quick Search 排名,不改
appTags 语义,不存像素坐标/IndexPath,不把顺序放 UserDefaults。