diff --git a/src/client/SideCardSection.tsx b/src/client/SideCardSection.tsx index 410cd1a..c0e4950 100644 --- a/src/client/SideCardSection.tsx +++ b/src/client/SideCardSection.tsx @@ -660,17 +660,6 @@ export function SideCardSection({ store, service }: SideCardSectionProps) { onChange={(next) => { applyPref({ interceptOpenPath: next }) }} /> -
- - {t('settingsTitleBarTitle')} - {t('settingsTitleBarDesc')} - - { applyPref({ titleBarCompat: next }) }} - /> -
{/* 侧边栏内容: one small card per registered tab type in a responsive diff --git a/src/client/Sidebar.tsx b/src/client/Sidebar.tsx index d4537e0..8d4cafc 100644 --- a/src/client/Sidebar.tsx +++ b/src/client/Sidebar.tsx @@ -167,21 +167,6 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { return () => { document.body.removeAttribute('data-dsh-sidebar-collapsed') } }, [collapsed]) - // Position compatibility mode (titleBarCompat pref): Windows frameless - // windows draw the native title bar (minimize/maximize/close) at the - // window's top-right corner, OVER the web content. When the user enables - // the pref, the body attribute lets sidebar.module.css drop the toggle - // cluster below the strip and push the right panel's content below it. - // The attribute rides the snapshot's prefs, so flipping the setting - // re-renders and re-applies immediately; the cleanup removes it on - // unmount/boundary swap so a crashed sidebar never leaves it behind. - const titleBarCompat = snapshot.prefs.titleBarCompat - useEffect(() => { - if (titleBarCompat) document.body.setAttribute('data-dsh-title-bar-compat', '') - else document.body.removeAttribute('data-dsh-title-bar-compat') - return () => { document.body.removeAttribute('data-dsh-title-bar-compat') } - }, [titleBarCompat]) - /** * Bottom-panel merge on narrow viewports: whenever a session is current * while narrow (mount, session switch, or a desktop→narrow transition), diff --git a/src/client/locales.ts b/src/client/locales.ts index 5dc6c07..fe66593 100644 --- a/src/client/locales.ts +++ b/src/client/locales.ts @@ -116,8 +116,6 @@ export const zh = { settingsWidthSuffix: '%', settingsOpenPathTitle: '聊天区文件在侧边栏打开', settingsOpenPathDesc: '在聊天里点击文件链接(工具行、产物列表、文件提及)时,在侧边栏编辑器中打开,不再调用系统默认应用', - settingsTitleBarTitle: '位置兼容模式', - settingsTitleBarDesc: '为 Windows 右上角的原生标题栏预留空间:侧边栏按钮与侧边栏内容整体下移,避免被标题栏遮挡', settingsSaveFailed: '保存失败', settingsConflict: '设置已被其他窗口修改,请重试', binaryNoPreview: '此文件类型不支持预览', @@ -335,8 +333,6 @@ export const en: Record = { settingsWidthSuffix: '%', settingsOpenPathTitle: 'Open chat files in the sidebar', settingsOpenPathDesc: 'Open file links in the chat (tool rows, produced files, mentions) in the sidebar editor instead of the system default app', - settingsTitleBarTitle: 'Position compatibility mode', - settingsTitleBarDesc: 'Reserve space for the native Windows title bar at the top-right so the sidebar buttons and content sit below it instead of underneath', settingsSaveFailed: 'Failed to save', settingsConflict: 'The setting changed in another window — please retry', binaryNoPreview: 'This file type cannot be previewed', diff --git a/src/client/prefs.ts b/src/client/prefs.ts index ec92080..2d0895a 100644 --- a/src/client/prefs.ts +++ b/src/client/prefs.ts @@ -59,9 +59,6 @@ export function parsePrefs(value: unknown): SidebarPrefs { interceptOpenPath: typeof record.interceptOpenPath === 'boolean' ? record.interceptOpenPath : SIDEBAR_PREFS_DEFAULTS.interceptOpenPath, - titleBarCompat: typeof record.titleBarCompat === 'boolean' - ? record.titleBarCompat - : SIDEBAR_PREFS_DEFAULTS.titleBarCompat, htmlViewerNoSandbox: typeof record.htmlViewerNoSandbox === 'boolean' ? record.htmlViewerNoSandbox : SIDEBAR_PREFS_DEFAULTS.htmlViewerNoSandbox, diff --git a/src/client/sidebar.module.css b/src/client/sidebar.module.css index 0d765b9..68f709d 100644 --- a/src/client/sidebar.module.css +++ b/src/client/sidebar.module.css @@ -209,28 +209,6 @@ padding-right: 40px; } -/* ── Position compatibility mode (Windows native title bar) ────────────── */ - -/* Windows frameless / hidden-title-bar windows draw the native caption - strip (minimize / maximize / close) at the window's top-right corner, - OVER the web content. When the user enables the "position compatibility" - pref, the sidebar yields the strip: the toggle cluster drops below it and - the right panel's content starts below it — the panel's surface still - spans the full height, so the caption buttons float over empty sidebar - fill (the VSCode hidden-title-bar look). The bottom panel is unaffected: - it sits at the window's bottom, never under the top strip. The Sidebar - shell toggles the body attribute from the prefs. */ -:global(body[data-dsh-title-bar-compat]) .toggleCluster { - top: 43px; /* 40px caption strip + the original 3px inset */ -} - -:global(body[data-dsh-title-bar-compat]) .panel { - /* The caption strip is drawn over the panel's own top edge: keep the - surface full-height and push the content (the tab strip) below the - strip instead. .panelResize is absolutely positioned and unaffected. */ - padding-top: 40px; -} - /* The shared corner (both panels open): the intersection of the right panel's left edge and the bottom panel's top edge. Horizontal drags resize the width, vertical drags the height — the two panels drag diff --git a/src/config.ts b/src/config.ts index 18582fb..5f0d4d3 100644 --- a/src/config.ts +++ b/src/config.ts @@ -91,7 +91,6 @@ export const PrefsSchema: z = z.object({ terminalFontFamily: z.string().default(''), terminalFontSize: z.number().step(1).min(TERMINAL_FONT_SIZE_MIN).max(TERMINAL_FONT_SIZE_MAX).default(TERMINAL_FONT_SIZE_DEFAULT), interceptOpenPath: z.boolean().default(true), - titleBarCompat: z.boolean().default(false), htmlViewerNoSandbox: z.boolean().default(false), htmlViewerDefaultUnsafe: z.boolean().default(false), browserNoSandbox: z.boolean().default(false), diff --git a/src/prefs-shared.ts b/src/prefs-shared.ts index c0f04ed..0cd576d 100644 --- a/src/prefs-shared.ts +++ b/src/prefs-shared.ts @@ -60,14 +60,6 @@ export interface SidebarPrefs { * own enable switch gates it too (both must be on for the takeover). */ interceptOpenPath: boolean - /** - * Position compatibility mode: reserves space at the top for the native - * Windows title bar (drawn at the window's top-right corner over the web - * content in frameless/hidden-title-bar windows). When on, the toggle - * cluster drops below the strip and the right panel's content starts - * below it. Off by default — the sidebar layout is untouched. - */ - titleBarCompat: boolean /** * Whether the HTML previewer drops its sandboxed iframe. Sandbox ON (the * default) renders previewed HTML in an opaque-origin iframe that cannot @@ -167,7 +159,6 @@ export const SIDEBAR_PREFS_DEFAULTS: SidebarPrefs = { terminalFontFamily: '', terminalFontSize: TERMINAL_FONT_SIZE_DEFAULT, interceptOpenPath: true, - titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, diff --git a/tests/plugin-shape.spec.ts b/tests/plugin-shape.spec.ts index 8d0a0a7..c549ae1 100644 --- a/tests/plugin-shape.spec.ts +++ b/tests/plugin-shape.spec.ts @@ -54,8 +54,6 @@ describe('dsh-better-sidebar plugin export shape', () => { // and 13px. expect(resolved.terminalFontFamily).toBe('') expect(resolved.terminalFontSize).toBe(13) - // The position-compat mode defaults OFF (the normal layout is default). - expect(resolved.titleBarCompat).toBe(false) // The enable-switch maps resolve to {} (everything on) for old documents. expect(resolved.tabsEnabled).toEqual({}) expect(resolved.viewersEnabled).toEqual({}) @@ -65,6 +63,6 @@ describe('dsh-better-sidebar plugin export shape', () => { const overridden = (PrefsSchema as unknown as { (input: Record | undefined): Record })({ openByDefault: false, defaultWidthPercent: 45 }) - expect(overridden).toEqual({ openByDefault: false, defaultWidthPercent: 45, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) + expect(overridden).toEqual({ openByDefault: false, defaultWidthPercent: 45, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) }) }) diff --git a/tests/side-card-section.spec.tsx b/tests/side-card-section.spec.tsx index c7f860c..7246561 100644 --- a/tests/side-card-section.spec.tsx +++ b/tests/side-card-section.spec.tsx @@ -151,24 +151,6 @@ describe('SideCardSection declarative inventory', () => { const html = renderSection(store, service) expect(html).not.toContain('Feature settings') }) - - it('renders the position-compat mode general row: off by default, checked when the pref is on', () => { - const { store, service } = mount() - let html = renderSection(store, service) - // The general row renders its title and description. - expect(html).toContain('Position compatibility mode') - expect(html).toContain('Reserve space for the native Windows title bar') - // Three general rows now: openByDefault + interceptOpenPath checked, - // the new titleBarCompat row UNCHECKED (default off) — the checked - // checkbox count stays at 2 while the total checkbox count is 3. - expect(html.match(/type="checkbox"/g)?.length).toBe(3) - expect(html.match(/checked=""/g)?.length).toBe(2) - - // When the pref is on, the new switch is checked too. - store.setPrefs({ ...store.getPrefs(), titleBarCompat: true }) - html = renderSection(store, service) - expect(html.match(/checked=""/g)?.length).toBe(3) - }) }) describe('FeatureSettingsRows (the secondary settings popup body)', () => { diff --git a/tests/smoke.spec.ts b/tests/smoke.spec.ts index bacd3a2..5529fbf 100644 --- a/tests/smoke.spec.ts +++ b/tests/smoke.spec.ts @@ -520,7 +520,6 @@ describe('side card settings routes', () => { terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, - titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, diff --git a/tests/unit.spec.ts b/tests/unit.spec.ts index 4229979..c3a965e 100644 --- a/tests/unit.spec.ts +++ b/tests/unit.spec.ts @@ -1140,7 +1140,6 @@ describe('side card preferences', () => { terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, - titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, @@ -1165,7 +1164,6 @@ describe('side card preferences', () => { terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, - titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, @@ -1190,7 +1188,6 @@ describe('side card preferences', () => { terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, - titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, @@ -1227,16 +1224,6 @@ describe('side card preferences', () => { expect((await loadPrefs(wire({ interceptOpenPath: true }))).interceptOpenPath).toBe(true) }) - it('defaults titleBarCompat to false; only an explicit true turns the position-compat mode on', async () => { - // Absent or malformed → off (the normal layout is the default). - expect((await loadPrefs(wire({}))).titleBarCompat).toBe(false) - expect((await loadPrefs(wire({ titleBarCompat: 'yes' }))).titleBarCompat).toBe(false) - expect((await loadPrefs(wire({ titleBarCompat: 1 }))).titleBarCompat).toBe(false) - // Explicit booleans survive verbatim. - expect((await loadPrefs(wire({ titleBarCompat: false }))).titleBarCompat).toBe(false) - expect((await loadPrefs(wire({ titleBarCompat: true }))).titleBarCompat).toBe(true) - }) - it('defaults the link-takeover protocol flags: http on, https off, master on', async () => { // Absent or malformed → the per-protocol defaults. expect((await loadPrefs(wire({}))).browserInterceptLinks).toBe(true) @@ -1286,9 +1273,9 @@ describe('side card preferences', () => { const store = createSidebarStore() // Node environment: no window → the width falls back to PANEL_DEFAULT, // while the open flag still follows the preference. - store.setPrefs({ openByDefault: false, defaultWidthPercent: 45, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) + store.setPrefs({ openByDefault: false, defaultWidthPercent: 45, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) store.setSession('fresh-session') - expect(store.getPrefs()).toEqual({ openByDefault: false, defaultWidthPercent: 45, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) + expect(store.getPrefs()).toEqual({ openByDefault: false, defaultWidthPercent: 45, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) const snapshot = store.getSnapshot() expect(snapshot.sessionId).toBe('fresh-session') expect(snapshot.state?.panelOpen).toBe(false) @@ -1324,7 +1311,7 @@ describe('side card preferences', () => { it('skips the default explorer tab when the explorer type is disabled', () => { const store = createSidebarStore() - store.setPrefs({ openByDefault: true, defaultWidthPercent: 30, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: { explorer: false }, viewersEnabled: {}, pluginSettings: {} }) + store.setPrefs({ openByDefault: true, defaultWidthPercent: 30, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: { explorer: false }, viewersEnabled: {}, pluginSettings: {} }) store.setSession('no-explorer') const state = store.getSnapshot().state! const tabs = allLeaves(state.splits).flatMap(leaf => leaf.tabs) @@ -1332,7 +1319,7 @@ describe('side card preferences', () => { expect(state.splits.kind).toBe('leaf') // Re-enabling seeds the explorer tab again. const openStore = createSidebarStore() - openStore.setPrefs({ openByDefault: true, defaultWidthPercent: 30, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, titleBarCompat: false, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) + openStore.setPrefs({ openByDefault: true, defaultWidthPercent: 30, autoOpenSubagent: true, autoOpenJobs: true, agentTerminalTools: false, bottomPanelAutoTerminal: true, terminalFontFamily: '', terminalFontSize: 13, interceptOpenPath: true, htmlViewerNoSandbox: false, htmlViewerDefaultUnsafe: false, browserNoSandbox: false, browserInterceptLinks: true, browserInterceptHttp: true, browserInterceptHttps: false, tabsEnabled: {}, viewersEnabled: {}, pluginSettings: {} }) openStore.setSession('with-explorer') const openTabs = allLeaves(openStore.getSnapshot().state!.splits).flatMap(leaf => leaf.tabs) expect(openTabs.map(tab => tab.type)).toEqual(['explorer'])