diff options
| author | Brendan Allan <[email protected]> | 2026-02-02 15:54:25 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-02-02 07:54:25 +0000 |
| commit | c02dd067b2ae62553c63b087b7b48a0f46628747 (patch) | |
| tree | b152fe0f6e429f317486762b92d366a97f9706a4 | |
| parent | 141fdef5886cc5e161fb9e857b61c5081519d2f6 (diff) | |
| download | opencode-c02dd067b2ae62553c63b087b7b48a0f46628747.tar.gz opencode-c02dd067b2ae62553c63b087b7b48a0f46628747.zip | |
fix(desktop): keep mac titlebar stable under zoom (#11747)
| -rw-r--r-- | packages/app/src/components/titlebar.tsx | 5 | ||||
| -rw-r--r-- | packages/app/src/context/platform.tsx | 4 | ||||
| -rw-r--r-- | packages/desktop/src/index.tsx | 4 | ||||
| -rw-r--r-- | packages/desktop/src/webview-zoom.ts | 38 |
4 files changed, 33 insertions, 18 deletions
diff --git a/packages/app/src/components/titlebar.tsx b/packages/app/src/components/titlebar.tsx index 001f7a567..affb68541 100644 --- a/packages/app/src/components/titlebar.tsx +++ b/packages/app/src/components/titlebar.tsx @@ -24,6 +24,8 @@ export function Titlebar() { const mac = createMemo(() => platform.platform === "desktop" && platform.os === "macos") const windows = createMemo(() => platform.platform === "desktop" && platform.os === "windows") const web = createMemo(() => platform.platform === "web") + const zoom = () => platform.webviewZoom?.() ?? 1 + const minHeight = () => (mac() ? `${40 / zoom()}px` : undefined) const [history, setHistory] = createStore({ stack: [] as string[], @@ -134,6 +136,7 @@ export function Titlebar() { return ( <header class="h-10 shrink-0 bg-background-base relative grid grid-cols-[auto_minmax(0,1fr)_auto] items-center" + style={{ "min-height": minHeight() }} data-tauri-drag-region > <div @@ -145,7 +148,7 @@ export function Titlebar() { data-tauri-drag-region > <Show when={mac()}> - <div class="w-[72px] h-full shrink-0" data-tauri-drag-region /> + <div class="h-full shrink-0" style={{ width: `${72 / zoom()}px` }} data-tauri-drag-region /> <div class="xl:hidden w-10 shrink-0 flex items-center justify-center"> <IconButton icon="menu" diff --git a/packages/app/src/context/platform.tsx b/packages/app/src/context/platform.tsx index f6fb157f0..591bd9c9f 100644 --- a/packages/app/src/context/platform.tsx +++ b/packages/app/src/context/platform.tsx @@ -1,5 +1,6 @@ import { createSimpleContext } from "@opencode-ai/ui/context" import { AsyncStorage, SyncStorage } from "@solid-primitives/storage" +import type { Accessor } from "solid-js" export type Platform = { /** Platform discriminator */ @@ -55,6 +56,9 @@ export type Platform = { /** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */ parseMarkdown?(markdown: string): Promise<string> + + /** Webview zoom level (desktop only) */ + webviewZoom?: Accessor<number> } export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({ diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index 2e7ca136a..505a00b16 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -1,5 +1,5 @@ // @refresh reload -import "./webview-zoom" +import { webviewZoom } from "./webview-zoom" import { render } from "solid-js/web" import { AppBaseProviders, AppInterface, PlatformProvider, Platform } from "@opencode-ai/app" import { open, save } from "@tauri-apps/plugin-dialog" @@ -346,6 +346,8 @@ const createPlatform = (password: Accessor<string | null>): Platform => ({ parseMarkdown: async (markdown: string) => { return invoke<string>("parse_markdown_command", { markdown }) }, + + webviewZoom, }) createMenu() diff --git a/packages/desktop/src/webview-zoom.ts b/packages/desktop/src/webview-zoom.ts index 9fa9bb9ed..06f46a3af 100644 --- a/packages/desktop/src/webview-zoom.ts +++ b/packages/desktop/src/webview-zoom.ts @@ -4,28 +4,34 @@ import { invoke } from "@tauri-apps/api/core" import { type as ostype } from "@tauri-apps/plugin-os" +import { createSignal } from "solid-js" const OS_NAME = ostype() -let zoomLevel = 1 +const [webviewZoom, setWebviewZoom] = createSignal(1) const MAX_ZOOM_LEVEL = 10 const MIN_ZOOM_LEVEL = 0.2 +const clamp = (value: number) => Math.min(Math.max(value, MIN_ZOOM_LEVEL), MAX_ZOOM_LEVEL) + +const applyZoom = (next: number) => { + setWebviewZoom(next) + invoke("plugin:webview|set_webview_zoom", { + value: next, + }) +} + window.addEventListener("keydown", (event) => { - if (OS_NAME === "macos" ? event.metaKey : event.ctrlKey) { - if (event.key === "-") { - zoomLevel -= 0.2 - } else if (event.key === "=" || event.key === "+") { - zoomLevel += 0.2 - } else if (event.key === "0") { - zoomLevel = 1 - } else { - return - } - zoomLevel = Math.min(Math.max(zoomLevel, MIN_ZOOM_LEVEL), MAX_ZOOM_LEVEL) - invoke("plugin:webview|set_webview_zoom", { - value: zoomLevel, - }) - } + if (!(OS_NAME === "macos" ? event.metaKey : event.ctrlKey)) return + + let newZoom = webviewZoom() + + if (event.key === "-") newZoom -= 0.2 + if (event.key === "=" || event.key === "+") newZoom += 0.2 + if (event.key === "0") newZoom = 1 + + applyZoom(clamp(newZoom)) }) + +export { webviewZoom } |
