import { createEffect, createMemo, Show, untrack } from "solid-js" import { createStore } from "solid-js/store" import { useLocation, useNavigate } from "@solidjs/router" 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" import { useLayout } from "@/context/layout" import { usePlatform } from "@/context/platform" import { useCommand } from "@/context/command" import { useLanguage } from "@/context/language" import { applyPath, backPath, forwardPath } from "./titlebar-history" export function Titlebar() { const layout = useLayout() const platform = usePlatform() const command = useCommand() const language = useLanguage() const theme = useTheme() const navigate = useNavigate() const location = useLocation() 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[], index: 0, action: undefined as "back" | "forward" | undefined, }) const path = () => `${location.pathname}${location.search}${location.hash}` createEffect(() => { const current = path() untrack(() => { const next = applyPath(history, current) if (next === history) return setHistory(next) }) }) const canBack = createMemo(() => history.index > 0) const canForward = createMemo(() => history.index < history.stack.length - 1) const back = () => { const next = backPath(history) if (!next) return setHistory(next.state) navigate(next.to) } const forward = () => { const next = forwardPath(history) if (!next) return setHistory(next.state) navigate(next.to) } command.register(() => [ { id: "common.goBack", title: language.t("common.goBack"), category: language.t("command.category.view"), onSelect: back, }, { id: "common.goForward", title: language.t("common.goForward"), category: language.t("command.category.view"), onSelect: forward, }, ]) const getWin = () => { if (platform.platform !== "desktop") return const tauri = ( window as unknown as { __TAURI__?: { window?: { getCurrentWindow?: () => { startDragging?: () => Promise toggleMaximize?: () => Promise } } } } ).__TAURI__ if (!tauri?.window?.getCurrentWindow) return return tauri.window.getCurrentWindow() } createEffect(() => { if (platform.platform !== "desktop") return const scheme = theme.colorScheme() const value = scheme === "system" ? null : scheme const tauri = (window as unknown as { __TAURI__?: { webviewWindow?: { getCurrentWebviewWindow?: () => unknown } } }) .__TAURI__ const get = tauri?.webviewWindow?.getCurrentWebviewWindow if (!get) return const win = get() as { setTheme?: (theme?: "light" | "dark" | null) => Promise } 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 (
) }