Files
apes-sidebar/src/prefs-shared.ts
T
Menghuan1918 8ad1766390 feat: 位置兼容模式支持自定义下移距离(齿轮弹窗数字输入)
titleBarStripPx 新偏好(0–120px,默认 40):侧边栏按钮与内容的下移量改为
CSS 变量 --dsh-title-bar-strip 驱动,Sidebar shell 随 prefs 写入。设置页
「常规」的位置兼容模式行在开启时显示齿轮小图标,弹窗内用数字行设置下移
距离(复用 FeatureSettingsRows 行控件与提交钳制)。
2026-08-15 15:46:56 +08:00

209 lines
9.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Shared "Side card" preference vocabulary (types + constants), consumed by
* BOTH halves: the host registers the schemastery schema over these values
* (config.ts) and the client reads/writes them through the settings RPC
* (client/prefs.ts, client/SideCardSection.tsx). Kept free of schemastery so
* the browser bundle never pulls the schema runtime in.
*/
/** The user-settings namespace holding the side card preferences. */
export const SIDEBAR_PREFS_NS = 'dsh-better-sidebar'
/** User-facing side card preferences (new-conversation defaults). */
export interface SidebarPrefs {
/** Whether a brand-new conversation opens the side card by default. */
openByDefault: boolean
/** Default panel width as a percent of the window width (20–60). */
defaultWidthPercent: number
/**
* Whether the sidebar auto-activates (opens the panel) and expands the
* Subagent page when the current conversation spawns a new subagent.
*/
autoOpenSubagent: boolean
/**
* Whether the sidebar auto-activates (opens the panel) and expands the
* Jobs page when a NEW background job appears for the current
* conversation (any new job id, not just the first one).
*/
autoOpenJobs: boolean
/**
* Whether the model-facing agent terminal tools (terminal_create / list /
* send / read / wait_for / resize / signal / close) are injected into the
* model's toolset. Off by default: the feature stays dormant until the
* user explicitly enables it in the side card settings.
*/
agentTerminalTools: boolean
/**
* Custom terminal font-family stack (a CSS font-family value, e.g.
* `'JetBrains Mono', monospace`). Empty string follows the app's theme
* monospace font (`--ds-font-family-code`). Applied live to every
* terminal tab; configured under the terminal card's secondary settings.
*/
terminalFontFamily: string
/**
* Custom terminal font size in px (9–32). Applied live to every terminal
* tab; configured under the terminal card's secondary settings.
*/
terminalFontSize: number
/**
* Whether expanding the bottom panel for the FIRST time in a session tries
* to open a fresh terminal tab there (the terminal quota/type still gates
* the attempt). On by default; the switch lives under the terminal tab's
* row in the Side card settings.
*/
bottomPanelAutoTerminal: boolean
/**
* Whether chat-side file opens (tool-row path links, the produced-files
* row, prose file mentions — every path that funnels through the client
* runtime's `ctx.workspaces.openPath`) open in the sidebar editor instead
* of the Host OS's default application. On by default; the editor tab's
* 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
/**
* The reserved top strip height in px when `titleBarCompat` is on
* (0–120, default 40). Drives the `--dsh-title-bar-strip` CSS variable:
* the toggle cluster drops `strip + 3px` and the right panel's content
* starts `strip` px below its top edge.
*/
titleBarStripPx: number
/**
* Whether the HTML previewer drops its sandboxed iframe. Sandbox ON (the
* default) renders previewed HTML in an opaque-origin iframe that cannot
* touch the GUI; turning it OFF runs the previewed page with the GUI's
* own origin — full read/write access to session files and internal
* APIs. Only for trusted local content; the setting copy warns.
*/
htmlViewerNoSandbox: boolean
/**
* Whether a newly opened HTML preview starts UNSANDBOXED (the per-surface
* temporary unlock pre-applied). Off by default: previews open sandboxed
* and the status row offers the one-tap unlock; when on, previews open
* in the red unsandboxed state and the status row offers a one-tap
* restore for the current file.
*/
htmlViewerDefaultUnsafe: boolean
/**
* Whether the browser tab drops its sandboxed iframe. Sandbox ON (the
* default) keeps browsed sites in an opaque origin with no GUI access;
* turning it OFF runs any visited site with the GUI's own origin — it
* can read session data and act as the logged-in GUI. Only for trusted
* sites; the setting copy warns.
*/
browserNoSandbox: boolean
/**
* MASTER switch: whether clicking an EXTERNAL link in the GUI (chat
* messages, tool rows, prose mentions) is taken over into the sidebar at
* all. On by default; the per-protocol granularity lives in
* `browserInterceptHttp` / `browserInterceptHttps` (the protocol flag
* must also be on), and the target tab's own enable switch gates it too.
* Ctrl/Cmd+click always bypasses the takeover. Kept as the master so old
* documents keep their meaning with no migration (an explicit `false`
* stays "never take over").
*/
browserInterceptLinks: boolean
/**
* Whether clicking an http EXTERNAL link in the GUI opens the sidebar
* (the built-in browser tab, or a plugin tab that declares `urlTarget`)
* instead of a new browser tab. On by default; gated on the
* `browserInterceptLinks` master and the target tab's own enable switch.
*/
browserInterceptHttp: boolean
/**
* Whether clicking an https EXTERNAL link in the GUI opens the sidebar
* instead of a new browser tab. OFF by default — most https sites (e.g.
* GitHub) refuse iframe embedding, so the system browser is the smoother
* default; gated on the `browserInterceptLinks` master and the target
* tab's own enable switch.
*/
browserInterceptHttps: boolean
/**
* Per-tab enable switches, keyed by tab descriptor id (`'explorer'`,
* `'my-plugin:db'`). An ABSENT key means enabled — only an explicit
* `false` disables a tab type (hidden from the + menu, `openTab` refuses,
* and derived flows like subagent auto-open / agent-terminal tabs stop).
* Already-open tabs of a disabled type keep rendering (closing one
* prevents reopening), matching the "existing conversations keep their
* own layouts" rule.
*/
tabsEnabled: Record<string, boolean>
/**
* Per-viewer enable switches, keyed by file viewer descriptor id
* (`'image'`, `'my-plugin:csv'`). An ABSENT key means enabled; a disabled
* viewer is skipped by `matchFileViewer` so files fall through to the
* next matching viewer (or the download button when none match).
*/
viewersEnabled: Record<string, boolean>
/**
* Plugin-owned settings blobs (v0.12.0+), keyed by descriptor id: each
* registered tab/viewer that declares `settings.pluginToggles` (or writes
* through `settings.render`'s `updatePluginSetting`) persists its values
* here — an open map, so third-party keys need no host PrefsSchema field.
* Values are JSON-serializable (the row controls produce strings /
* numbers / booleans; custom panels are responsible for their own).
*/
pluginSettings: Record<string, Record<string, unknown>>
}
/** Range contract of {@link SidebarPrefs.defaultWidthPercent}. */
export const WIDTH_PERCENT_MIN = 20
export const WIDTH_PERCENT_MAX = 60
export const WIDTH_PERCENT_DEFAULT = 30
/** Range contract of {@link SidebarPrefs.terminalFontSize}. */
export const TERMINAL_FONT_SIZE_MIN = 9
export const TERMINAL_FONT_SIZE_MAX = 32
export const TERMINAL_FONT_SIZE_DEFAULT = 13
/** Range contract of {@link SidebarPrefs.titleBarStripPx}. */
export const TITLE_BAR_STRIP_MIN = 0
export const TITLE_BAR_STRIP_MAX = 120
export const TITLE_BAR_STRIP_DEFAULT = 40
/** Fallback prefs used whenever the settings document is unreachable or malformed. */
export const SIDEBAR_PREFS_DEFAULTS: SidebarPrefs = {
openByDefault: true,
defaultWidthPercent: WIDTH_PERCENT_DEFAULT,
autoOpenSubagent: true,
autoOpenJobs: true,
agentTerminalTools: false,
bottomPanelAutoTerminal: true,
terminalFontFamily: '',
terminalFontSize: TERMINAL_FONT_SIZE_DEFAULT,
interceptOpenPath: true,
titleBarCompat: false,
titleBarStripPx: TITLE_BAR_STRIP_DEFAULT,
htmlViewerNoSandbox: false,
htmlViewerDefaultUnsafe: false,
browserNoSandbox: false,
browserInterceptLinks: true,
browserInterceptHttp: true,
browserInterceptHttps: false,
tabsEnabled: {},
viewersEnabled: {},
pluginSettings: {},
}
/** Clamp one width percent into the contract range (shared by schema and client reads). */
export function clampWidthPercent(value: number): number {
return Math.min(WIDTH_PERCENT_MAX, Math.max(WIDTH_PERCENT_MIN, Math.round(value)))
}
/** Clamp one terminal font size into the contract range (shared by schema and client reads). */
export function clampTerminalFontSize(value: number): number {
return Math.min(TERMINAL_FONT_SIZE_MAX, Math.max(TERMINAL_FONT_SIZE_MIN, Math.round(value)))
}
/** Clamp one title-bar strip height into the contract range (shared by schema and client reads). */
export function clampTitleBarStrip(value: number): number {
return Math.min(TITLE_BAR_STRIP_MAX, Math.max(TITLE_BAR_STRIP_MIN, Math.round(value)))
}