feat(tabs): 标签页多选——⌘点挑、⇧点连选,⌘W 关掉选中的一批 - #240
Conversation
36e3edf to
da2ee7a
Compare
31a754e to
8585f98
Compare
8585f98 to
26ca8fc
Compare
da2ee7a to
37e4971
Compare
oratis
left a comment
There was a problem hiding this comment.
Review
选择集生命周期表(§4.2)逐行核对代码,八行全部落实且各有测试:任何关闭清空(收在 removeTabs 一处)、Save As 跟着改 id、pinned 进不来、pin 一个已选中的会把它踢出去、普通点击/Esc 清空、右键未选中的先清再弹(Finder 行为)、liveSelection 让「Close N Tabs」的 N 永不撒谎、⌘W 只认可见的选择集。closeSelectedOrActive 放 store 里可测——辩题二那条最危险的路径有直接的单测,三道闸都在。
修了一处(8ec949a)
§4.2 的「strip 隐藏时选择集保留、⌘W 不认」写到了,但 Esc 那条没跟上:清选择集的监听挂在 TabBar 上,showTabBar: false 时 TabBar 整个不渲染、监听不存在;而 App 的 Esc 守卫只看 selectedTabIds.length > 0 就提前 return。于是「先 ⌘ 点选几个标签页,再去设置里关掉标签条」之后,Esc 回读模式永久失灵——隐形选择集清不掉(清空要么靠点击 strip(已隐藏)要么靠一次关闭动作)。
改法:App 的守卫只在 showTabBar && selectedTabIds.length > 0 时让位;strip 隐藏时 Esc 直接回读模式,选择集按 §4.2 继续保留。设计文档同一行已补记。tsc + 89 项相关测试通过;整栈 merge 到当前 main 后 1064 项单测全绿。
另外确认:⇧ 连选的锚点失效回退(fallback 到激活页)、selectTabRange 反向与跳 pinned、closeTabs 空集 no-op 都有测试;USAGE 的表格与实际行为一致。
三个批量动词全是"以某一个为轴心的全有全无","把这五个不相邻的关掉" 没有任何路径,只能点五次悬停才显形的 ×。这一轮把 strip 本身当清单: ⌘点增删、⇧点从锚点连选;选中态是蓝底 + 内描边(不是淡淡的高亮), 挂 data-selected 供测试断言。右键选中项,菜单首条是「Close N Tabs」, N 是真实会关掉的数量;右键未选中项先清空选择集再弹常规菜单。 选择集进 store(selectedTabIds),生命周期逐条钉死:任何关闭清空、 普通点击清空、Esc 清空、Save As 时 id 跟着迁移、固定页进不来——pinned 的契约是"批量手势碰不到我",让它进来计数就会撒谎。 ⌘W(File ▸ Close Tab)改走 closeSelectedOrActive():有选择集关选择集, 否则关当前页。这是设计里风险最高的一条,所以放在 store 里可测,并配 三道闸(显眼标记 / 清空窗口很短 / 批量确认 + ⌘⇧T 逐个找回),外加 标签条被设置关掉时无视选择集——看不见的选择不许指挥破坏性操作。 退路写在 docs/design/10-close-many-tabs.md 辩题二。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
三条 review 发现,全是选择集生命周期没钉死的地方: - ⌘点选中 b → 右键 Pin:b 既带 📌 又带蓝框。按 ⌘W:closeSelectedOrActive 只查"还在不在",不查 pinned → live=[b] → closeTabs 过滤掉固定页 → 一个受害者都没有 → return state,连当前页都不关,选择集也不清,⌘W 从此是死键。两头都堵:toggleTabPinned 固定时把它从选择集里剔掉; closeSelectedOrActive 改用 liveSelection()(在 strip 上且非固定), 空了就退回关当前页。 - 同一根因让「Close N Tabs」的 N 撒谎(选 1 固定 + 2 非固定写 3 关 2)。 标签和 run 都改用 liveSelection(),辩题五要的"计数永远说真话"才真成立。 - Esc 双击:App 的 window keydown 在编辑态下把 Esc 映射成回阅读模式, ⌘点标签页后焦点在 body,按 Esc 清选择集的同时也把编辑器翻回了阅读。 App 那一支看到选择集非空就先让路(TabBar 负责清),下一次 Esc 才回阅读。 TabBar 的监听器则跳过 input/textarea/contenteditable 里的 Esc—— 查找栏里的 Esc 归查找栏。 - ⇧ 连选的锚点被关掉后 `anchorId ?? activeTabId` 不会退回(?? 只认 null),只会选中目标一个。改成点击时核对锚点还在不在。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
showTabBar 关掉时选择集保留但不可见(设计 10 §4.2),清选择集的 监听挂在 TabBar 上——strip 隐藏时它不在场。原守卫只看 selectedTabIds.length,于是隐形选择集会把 Esc 回读模式变成死键, 直到某次关闭动作把选择集清掉为止。改成 strip 可见才让位。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8ec949a to
7dd67dc
Compare
三个叠放 PR 里的 第 3 个,基于 #238 → #239。设计:docs/design/10-close-many-tabs.md §3 辩题一、二、五,§4.1–4.3,以及本 PR 新增的 §9 Review 之后改了什么。用户手册
docs/USAGE.md补了 "Closing tabs" 一节。Summary
opacity: 1(不是"稍微亮一点"——它得显眼到没人会忘了还选着),挂data-selected供测试。liveSelection()(在 strip 上且非固定),所以是真实会关掉的数量;加「Clear Selection」。右键未选中项先清空选择集再弹常规菜单(Finder 的行为,菜单说的和用户看的永远是一回事)。selectedTabIds进 store)逐条钉死:任何关闭清空、普通点击清空、Esc 清空、Save As 时 id 跟着迁移、固定页进不来,固定一个已选中的页会把它剔出去——pinned 的契约是"批量手势碰不到我"。closeSelectedOrActive()——有(真会被关的)选择集关选择集,否则关当前页。Review 抓到的三个 bug(都已修,第 3 个提交)
closeTabs过滤掉固定页后一个受害者都没有 →return state,连当前页都不关、选择集也不清,⌘W 从此是死键toggleTabPinned固定时剔出选择集;closeSelectedOrActive改用liveSelection(),空了退回关当前页liveSelection()外加一个 nit:⇧ 连选的锚点被关掉后
anchorId ?? activeTabId不会退回(??只认 null),改成点击时核对锚点还在不在。How to verify
E进编辑态,⌘点一个标签页,按 Esc → 蓝框消失、还在编辑态;再按 Esc → 回阅读。Checks
pnpm tsc --noEmitcleanpnpm lintcleanpnpm test --rungreen(1064,本 PR +31:store 21、TabBar 10)cd src-tauri && cargo test— 未动 Rustdata-selected+ 实测蓝底/描边 → 右键「Close 2 Tabs」→ 4 变 2;Pin 选中页 → 选择集清空;Esc 先退选择集再退阅读,两步实测)Notes for the reviewer
showTabBar: false)时 ⌘W 无视选择集——看不见的选择不许指挥破坏性操作。退路是降级成"选择集为空才生效",只改closeSelectedOrActive一处。recentlyClosed是路径栈,不记批次;压栈按 strip 顺序,连按 ⌘⇧T 从左到右回来。🤖 Generated with Claude Code