fix: 处理 Copilot 二轮 review 的 10 条评论

- BrowserView: 即使 host 在白名单,GUI 自身 origin 永不给 allow-same-origin(裸 host 条目覆盖所有端口时可提权)
- intercept: revealInExplorer 相对路径经 resolveSidebarPath 解析后再 revealPaths(交付物路径是相对的)
- intercept: ctx.betterSidebar 改为 ctx.get(#357 纤维链读取约定)
- FileTree/EditorHost/TreePanel/tabs: 把 revealed 贯通到树行渲染 + 高亮类 + scrollIntoView(此前高亮永不渲染)
- state.revealPaths: 重建祖先目录时保留前导分隔符(POSIX/UNC 此前目录永远折叠)
- state.schedulePersist: 仅活动会话写入全局宽度(targeted open 不再用非活动会话的过期宽度覆盖拖拽值)
- browser.probe: GET 回退显式取消 body(否则流式/大响应挂住 socket)
- terminal-font: leading generic 前只放 symbols-only 字体;fully-patched 放 generic 后(避免 hijack 度量字体)
- sidebar.module.css: 恢复拖拽反馈(#130 的 silent resize 与 PR 描述冲突,取 HEAD)
- Sidebar: 剩余 4 处 ctx.betterSidebar 改 ctx.get
- tests: 补 revealPaths/iframeSandboxFor/terminal-font 回归测试 + EditorHost/FileTree 测试补 revealed prop
This commit is contained in:
HuanLinOTO
2026-08-24 18:40:04 +08:00
parent 9048dbe42d
commit 699ce448a1
19 changed files with 171 additions and 27 deletions
+28 -1
View File
@@ -4,7 +4,7 @@ import {
dockFloat, FLOAT_MIN_H, FLOAT_MIN_W, floatTab, floatWithTab, insertLeafAt, makeDefaultState,
migrateBottomTabs, moveFloat, moveTab, moveTabToEdge, openDiffTab,
openTabInActivePane, patchTab, raiseFloat, reconcileAgentTerminals, resizeFloat, resizeSplit,
resizeSplitIn, sanitizeState, setBottomHeight,
resizeSplitIn, revealPaths, sanitizeState, setBottomHeight,
splitPane, tabOpenIn, toggleBottomPanel, toggleExpanded, togglePanel,
type SidebarLeaf, type SidebarState, type SidebarTab, type SplitNode,
} from '../src/client/state.ts'
@@ -1084,6 +1084,33 @@ describe('free windows (v0.16.0)', () => {
expect(allLeaves(after.splits).flatMap(leaf => leaf.tabs).some(tab => tab.id === 'agent:u2')).toBe(true)
})
describe('revealPaths (show in folder)', () => {
it('expands ancestors with their ABSOLUTE path (leading separator preserved)', () => {
// POSIX: the root (/w/src) is not itself expanded, but the subdirs
// below it must be recorded as ABSOLUTE paths so FileTree's
// `expanded.includes(entry.path)` matches.
const base = makeDefaultState()
const next = revealPaths(base, '/w/src', ['/w/src/sub/deep/a.ts'])
expect(next.revealed).toEqual(['/w/src/sub/deep/a.ts'])
expect(next.expanded).toContain('/w/src/sub')
expect(next.expanded).toContain('/w/src/sub/deep')
expect(next.expanded).not.toContain('w/src/sub')
expect(next.expanded).not.toContain('/w/src')
})
it('keeps a Windows drive-letter root and a UNC prefix', () => {
const drive = revealPaths(makeDefaultState(), 'C:\\work', ['C:\\work\\src\\a.ts'])
expect(drive.expanded).toContain('C:\\work\\src')
const unc = revealPaths(makeDefaultState(), '\\\\server\\share', ['\\\\server\\share\\sub\\a.ts'])
expect(unc.expanded).toContain('\\\\server\\share\\sub')
})
it('resolves nothing to the same reference (no churn)', () => {
const base = makeDefaultState()
expect(revealPaths(base, '/w', [])).toBe(base)
})
})
describe('sanitizeState (floats)', () => {
const g = globalThis as Record<string, unknown>
beforeEach(() => {