|
|
@@ -5,7 +5,6 @@ import { IconButton } from "@opencode-ai/ui/icon-button"
|
|
|
import { Icon } from "@opencode-ai/ui/icon"
|
|
|
import { Button } from "@opencode-ai/ui/button"
|
|
|
import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
|
|
|
-import { useTheme } from "@opencode-ai/ui/theme/context"
|
|
|
import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2"
|
|
|
import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
|
|
|
import { KeybindV2 } from "@opencode-ai/ui/v2/keybind-v2"
|
|
|
@@ -30,31 +29,11 @@ import "./titlebar.css"
|
|
|
import { newTabTooltipKeybind } from "./command-tooltip-keybind"
|
|
|
import { normalizeSessionInfo } from "@/utils/session"
|
|
|
|
|
|
-type TauriDesktopWindow = {
|
|
|
- startDragging?: () => Promise<void>
|
|
|
- toggleMaximize?: () => Promise<void>
|
|
|
-}
|
|
|
-
|
|
|
-type TauriThemeWindow = {
|
|
|
- setTheme?: (theme?: "light" | "dark" | null) => Promise<void>
|
|
|
-}
|
|
|
-
|
|
|
-type TauriApi = {
|
|
|
- window?: {
|
|
|
- getCurrentWindow?: () => TauriDesktopWindow
|
|
|
- }
|
|
|
- webviewWindow?: {
|
|
|
- getCurrentWebviewWindow?: () => TauriThemeWindow
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const tauriApi = () => (window as unknown as { __TAURI__?: TauriApi }).__TAURI__
|
|
|
-const currentDesktopWindow = () => tauriApi()?.window?.getCurrentWindow?.()
|
|
|
-const currentThemeWindow = () => tauriApi()?.webviewWindow?.getCurrentWebviewWindow?.()
|
|
|
const legacyTitlebarHeight = 40
|
|
|
const v2TitlebarHeight = 36
|
|
|
const minTitlebarZoom = 0.25
|
|
|
const windowsControlsBaseWidth = 138 // 3 native Windows caption buttons at 46px each.
|
|
|
+const macTrafficLightsBaseWidth = 84
|
|
|
|
|
|
export type TitlebarUpdate = {
|
|
|
version: () => string | undefined
|
|
|
@@ -74,7 +53,6 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
const command = useCommand()
|
|
|
const language = useLanguage()
|
|
|
const settings = useSettings()
|
|
|
- const theme = useTheme()
|
|
|
const server = useServer()
|
|
|
const navigate = useNavigate()
|
|
|
const location = useLocation()
|
|
|
@@ -85,9 +63,9 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
|
|
|
const mac = createMemo(() => platform.platform === "desktop" && platform.os === "macos")
|
|
|
const windows = createMemo(() => platform.platform === "desktop" && platform.os === "windows")
|
|
|
- const electronWindows = createMemo(() => windows() && !tauriApi())
|
|
|
const linux = createMemo(() => platform.platform === "desktop" && platform.os === "linux")
|
|
|
const web = createMemo(() => platform.platform === "web")
|
|
|
+ const macTrafficLights = createMemo(() => mac() && !platform.windowFullscreen?.())
|
|
|
const zoom = () => platform.webviewZoom?.() ?? 1
|
|
|
const titlebarZoom = () => (windows() ? Math.max(zoom(), minTitlebarZoom) : zoom())
|
|
|
const counterZoom = () => (windows() && titlebarZoom() < 1 ? 1 / titlebarZoom() : 1)
|
|
|
@@ -176,56 +154,6 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
},
|
|
|
])
|
|
|
|
|
|
- const getWin = () => {
|
|
|
- if (platform.platform !== "desktop") return
|
|
|
- return currentDesktopWindow()
|
|
|
- }
|
|
|
-
|
|
|
- createEffect(() => {
|
|
|
- if (platform.platform !== "desktop") return
|
|
|
-
|
|
|
- const scheme = theme.colorScheme()
|
|
|
- const value = scheme === "system" ? null : scheme
|
|
|
-
|
|
|
- const win = currentThemeWindow()
|
|
|
- if (!win?.setTheme) return
|
|
|
-
|
|
|
- void win.setTheme(value).catch(() => undefined)
|
|
|
- })
|
|
|
-
|
|
|
- const interactive = (target: EventTarget | null) => {
|
|
|
- if (!(target instanceof Element)) return false
|
|
|
-
|
|
|
- const selector =
|
|
|
- "button, a, input, textarea, select, option, [role='button'], [role='menuitem'], [contenteditable='true'], [contenteditable='']"
|
|
|
-
|
|
|
- return !!target.closest(selector)
|
|
|
- }
|
|
|
-
|
|
|
- const drag = (e: MouseEvent) => {
|
|
|
- if (platform.platform !== "desktop") return
|
|
|
- if (e.buttons !== 1) return
|
|
|
- if (interactive(e.target)) return
|
|
|
-
|
|
|
- const win = getWin()
|
|
|
- if (!win?.startDragging) return
|
|
|
-
|
|
|
- e.preventDefault()
|
|
|
- void win.startDragging().catch(() => undefined)
|
|
|
- }
|
|
|
-
|
|
|
- const maximize = (e: MouseEvent) => {
|
|
|
- if (platform.platform !== "desktop") return
|
|
|
- if (interactive(e.target)) return
|
|
|
- if (e.target instanceof Element && e.target.closest("[data-tauri-decorum-tb]")) return
|
|
|
-
|
|
|
- const win = getWin()
|
|
|
- if (!win?.toggleMaximize) return
|
|
|
-
|
|
|
- e.preventDefault()
|
|
|
- void win.toggleMaximize().catch(() => undefined)
|
|
|
- }
|
|
|
-
|
|
|
return (
|
|
|
<header
|
|
|
data-slot={useV2Titlebar() ? "titlebar-v2" : undefined}
|
|
|
@@ -238,16 +166,12 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
style={{
|
|
|
"min-height": minHeight(),
|
|
|
// Keep native macOS traffic lights clear even when the desktop window is narrow.
|
|
|
- "padding-left": mac() ? `${84 / zoom()}px` : 0,
|
|
|
- width: electronWindows() ? `env(titlebar-area-width, calc(100vw - ${windowsControlsWidth()}))` : undefined,
|
|
|
- "max-width": electronWindows()
|
|
|
- ? `env(titlebar-area-width, calc(100vw - ${windowsControlsWidth()}))`
|
|
|
- : undefined,
|
|
|
- "align-self": electronWindows() ? "flex-start" : undefined,
|
|
|
+ "padding-left": macTrafficLights() ? `${macTrafficLightsBaseWidth / zoom()}px` : 0,
|
|
|
+ width: windows() ? `env(titlebar-area-width, calc(100vw - ${windowsControlsWidth()}))` : undefined,
|
|
|
+ "max-width": windows() ? `env(titlebar-area-width, calc(100vw - ${windowsControlsWidth()}))` : undefined,
|
|
|
+ "align-self": windows() ? "flex-start" : undefined,
|
|
|
}}
|
|
|
data-tauri-drag-region
|
|
|
- onMouseDown={drag}
|
|
|
- onDblClick={maximize}
|
|
|
>
|
|
|
<Switch>
|
|
|
<Match when={useV2Titlebar()}>
|
|
|
@@ -459,8 +383,8 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
classList={{
|
|
|
"pt-2": !bottom(),
|
|
|
"pb-2": bottom(),
|
|
|
- "md:pl-2": mac(),
|
|
|
- "md:pl-4": !mac(),
|
|
|
+ "md:pl-2": macTrafficLights(),
|
|
|
+ "md:pl-4": !macTrafficLights(),
|
|
|
}}
|
|
|
>
|
|
|
<ChannelIndicator debugTools={props.debugTools} />
|
|
|
@@ -528,9 +452,6 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
</Show>
|
|
|
<div class="flex-1" />
|
|
|
<TitlebarV2Right state={v2RightState()} />
|
|
|
- <Show when={windows() && !electronWindows()}>
|
|
|
- <div data-tauri-decorum-tb class="flex flex-row" />
|
|
|
- </Show>
|
|
|
</div>
|
|
|
)
|
|
|
}}
|
|
|
@@ -543,14 +464,13 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
<div
|
|
|
classList={{
|
|
|
"flex items-center min-w-0": true,
|
|
|
- "pl-2": !mac(),
|
|
|
+ "pl-2": !macTrafficLights(),
|
|
|
}}
|
|
|
>
|
|
|
<Show when={windows() || linux()}>
|
|
|
<WindowsAppMenu command={command} platform={platform} />
|
|
|
</Show>
|
|
|
<Show when={mac()}>
|
|
|
- {/*<div class="h-full shrink-0" style={{ width: `${72 / zoom()}px` }} />*/}
|
|
|
<div class="xl:hidden w-10 shrink-0 flex items-center justify-center">
|
|
|
<IconButton
|
|
|
icon="menu"
|
|
|
@@ -680,12 +600,10 @@ export function Titlebar(props: { update?: TitlebarUpdate; debugTools?: { visibl
|
|
|
"pr-2": !windows(),
|
|
|
}}
|
|
|
data-tauri-drag-region
|
|
|
- onMouseDown={drag}
|
|
|
>
|
|
|
<div id="opencode-titlebar-right" class="flex items-center gap-1 shrink-0 justify-end" />
|
|
|
<Show when={windows()}>
|
|
|
- {!tauriApi() && <div class="shrink-0" style={{ width: windowsControlsWidth() }} />}
|
|
|
- <div data-tauri-decorum-tb class="flex flex-row" />
|
|
|
+ <div class="shrink-0" style={{ width: windowsControlsWidth() }} />
|
|
|
</Show>
|
|
|
</div>
|
|
|
</div>
|