fix(tabs): 批量关闭前先问——Close Others / Close to the Right 不再静默丢改动 - #238
Merged
Conversation
This was referenced Aug 23, 2026
ContextMenu 的面板靠 shrink-to-fit 定宽,而 <button> 默认是 inline-block——块级容器的 max-content 对行内级子元素来说是"全排 一行"的宽度,于是面板宽 ≈ 所有菜单项之和:8 条实测 684px,横跨 半个窗口。min-w-[160px] 只管下限,管不住这个。 加 flex flex-col,max-content 退回"最宽的那一条",实测落回 160px。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
两个真缺陷,见 docs/design/10-close-many-tabs.md §1.2: - closeOtherTabs 和 closeTabsToRight 完全不检查脏状态,直接 filter 掉受害者就返回。右键 → Close Others,其余标签页里没保存的改动一声 不响地没了。单个 closeTab 是问的,所以这是漏了,不是风格。 - closeAllTabs 问的是 A,丢的是 A、B、C:confirm 只报第一个脏文件的 名字,用户点确定,后面几个的改动一起没了。比不问更糟——它制造了 "我知道我在丢什么"的错觉。 修法:所有关闭动作共用一个 confirmDiscard(victims)——批次里没有 "有路径且脏"的直接放行;恰好 1 个沿用原文案;2 个以上用新的 tab.confirmCloseMany,把名字都列出来(超过 5 个截断并注明还有几个)。 一次批量只问一次。 顺手把四个 reducer 的移除逻辑收口成 removeTabs():压 recentlyClosed、 落激活页(落到最左被关位置的左邻,和单个关闭一致)、关空回 welcome。 closeTab 仍然不跳过 pinned——显式点名的单个关闭就该关掉你点的那个, 只有批量手势才扫不到固定页。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
现状 review(三个真缺陷 + 三个"不好关")、七道正反方辩论、设计细则、 不在本轮、验证。落地拆成三个叠放的 PR,本 PR 是第一个。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- closeOtherTabs:其余全是固定页时原先直接 return state,连轴心页都不
激活了;改前这个手势永远会把你带到右键的那一页。补回来。
- closeAllTabs 的落点从"第一个固定页"变成"最左被关位置的左邻"(也就是
最后一个固定页)——这是有意的,和所有关闭动作一个规则,补测试钉住。
- i18n t() 用字符串做 replace 的替换值,`$&`、`$'` 会被展开:文件名
x$&y.md 会渲染成 x{1}y.md。换成函数替换值。既有问题,但确认文案现在
会列一串文件名,顺手修。
- 设计文档状态行填上三个 PR 的编号。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
oratis
force-pushed
the
fix/tabs-bulk-close-confirm
branch
from
August 23, 2026 16:47
3ce777d to
db3a417
Compare
oratis
commented
Aug 24, 2026
oratis
left a comment
Owner
Author
There was a problem hiding this comment.
Review
设计 10 的辩论与裁决俱全,代码对得上文档。逐点核过:
removeTabs作为唯一的移除路径是这轮最值钱的改动:激活页落点(min(max(0, firstIdx-1), len-1))与单关规则一致,recentlyClosed按 strip 顺序压栈(辩题六的约定有测试钉住),关空回 welcome。五个公开 API 全部收敛到它,此后不可能再出现"某条路径忘了问"。confirmDiscard的三段式正确修掉缺陷一 + 缺陷二:0 个脏的不打扰、1 个沿用旧文案(单关体验一字不变)、N 个列名并在超过 5 个时截断——截断行自身也走 i18n。closeTab不跳过 pinned 是显式契约,注释写死了理由,和批量手势的"扫不到固定页"分工清楚。t()换函数 replacer:字符串 replacement 会展开文件名里的$&/$',文件名恰好是这里的主要参数——这个补丁本身就值一条测试,也有了。- 右键菜单宽度:
inline-block子元素让 max-content 变成"全排一行"的总宽,flex flex-col一行修掉,量化数据(684px→160px)在文档里。
closeOtherTabs 无事可关时仍落到轴心、closeAllTabs 全 pinned 时 no-op,这些边界都有测试。没有要改的,直接进合并链(rebase 到当前 main 后 tsc + 1064 单测全绿)。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
设计文档:docs/design/10-close-many-tabs.md(本 PR 带入)。这是三个叠放 PR 里的 第 1 个,后两个:#239 Close to the Left + ⌘⌥W → #240 多选 + ⌘W 认选择集。
Summary
closeOtherTabs/closeTabsToRight完全不检查脏状态,直接丢;closeAllTabs只报第一个脏文件的名字就把全部丢掉——比不问更糟,它制造"我知道我在丢什么"的错觉。修法:所有关闭共用confirmDiscard(victims),一次批量问一次,2 个以上把名字都列出来(超过 5 个截断注明还有几个),没有"有路径且脏"的不打扰。removeTabs():压recentlyClosed(按 strip 顺序,所以 ⌘⇧T 从左到右依次回来)、落激活页(最左被关位置的左邻,与单个关闭一致)、关空回 welcome。closeTab仍不跳过 pinned——显式点名就该关掉你点的那个,只有批量手势才扫不到固定页。<button>是 inline-block,块级容器的 max-content 是"全排一行"的宽度。加flex flex-col,实测回到 160px。closeOtherTabs其余全是固定页时仍把轴心页激活(改前行为,重构时丢了);t()用函数做替换值,文件名里的$&不再被展开成{1}(既有 bug,确认文案现在会列一串文件名)。一个有意的行为变化
closeAllTabs之后的落点:改前是第一个固定页,现在是最后一个固定页(= 最左被关位置的左邻)。这是所有关闭动作统一的规则,视线不用跳到 strip 最前面。有测试钉住。How to verify
autosaveMs = 0),在其中两个里各打几个字不保存。Checks
pnpm tsc --noEmitcleanpnpm lintcleanpnpm test --rungreen(1021,本 PR +10)cd src-tauri && cargo test— 未动 RustNotes for the reviewer
wide-tables.spec.ts量到 685 而不是 720,main 的 head(703402d)同一条也红。本地 4 workers 跑 27 次能复现 8 次——根因是pasteMarkdown点编辑区中心放光标,落进列表/引用块就量到容器宽度。另开一个小 PR 修。window.confirm,不造三选一对话框(保存并关闭 / 直接关闭 / 取消)——理由见设计辩题三:autosave 默认 300ms 开着,有路径的文档几乎不存在"脏"这个状态,今天的真问题是"根本不问",先把 ❌ 修成 ✅。git rebase --onto main fix/tabs-bulk-close-confirm feat/tabs-close-left-shortcut再push -f。🤖 Generated with Claude Code