Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131import { lazy, Show, Suspense, type ParentProps } from "solid-js"import { createStore } from "solid-js/store"import { createMediaQuery } from "@solid-primitives/media"import { ResizeHandle } from "@opencode/ui/resize-handle"import { Titlebar, type TitlebarUpdate } from "@/shell/titlebar/titlebar"import { usePlatform } from "@/runtime/platform/platform"import { ToastRegion } from "@/shell/notifications/toast"import { UploadToastHost } from "@/composer/attachments/uploads"import { TitlebarRightProvider } from "@/shell/titlebar/right-slot"import { useSettingsSurface } from "@/settings/surface"import { useSettings } from "@/settings/model"import { SshAuthentication } from "@/servers/ssh/authentication"import { useUpdaterInstall } from "@/shell/updates/download"import { useCommand } from "@/shell/commands/command"import { useLanguage } from "@/runtime/i18n/language"
const DebugBar = lazy(() => import("@/shell/debug/debug-bar").then((module) => ({ default: module.DebugBar })))
export default function Layout(props: ParentProps) { const platform = usePlatform() const settings = useSettingsSurface() const preferences = useSettings() const installUpdate = useUpdaterInstall() const command = useCommand() const language = useLanguage() const mobile = createMediaQuery("(max-width: 767px)") const [state, setState] = createStore({ debugTools: false, tabsWidth: 260, tabsMount: undefined as HTMLElement | undefined, }) const verticalTabs = () => preferences.appearance.tabLayout() === "vertical" && !mobile() const bottomTitlebar = () => mobile() && preferences.general.mobileTitlebarPosition() === "bottom"
const update: TitlebarUpdate = { get state() { return platform.updater?.state() }, install: installUpdate, } // A plain object avoids the compiler's conditional-prop memo, which leaks when read from event handlers. const debugTools = { get visible() { return state.debugTools }, toggle: () => setState("debugTools", (value) => !value), }
command.register("debug-bar", () => [ { id: "debugBar.toggle", title: language.t("command.debugBar.toggle"), category: language.t("command.category.view"), onSelect: debugTools.toggle, }, ])
return ( <TitlebarRightProvider> <div class="relative bg-v2-background-bg-deep flex-1 min-h-0 min-w-0 flex flex-col select-none [&_input]:select-text [&_textarea]:select-text [&_[contenteditable]]:select-text" style={{ // Native Windows chrome supplies the gap; retain paint clearance for the panels' outer outlines. "--shell-top-inset": bottomTitlebar() ? "max(0px, calc(8px - env(safe-area-inset-top, 0px)))" : platform.platform === "desktop" && platform.os === "windows" ? "1px" : "8px", "--shell-bottom-inset": bottomTitlebar() ? "8px" : "max(0px, calc(8px - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))))", }} > <Titlebar update={update} verticalTabs={verticalTabs() ? { mount: state.tabsMount } : undefined} debugTools={debugTools} /> <div class="flex flex-1 min-h-0 min-w-0 flex-row"> <Show when={verticalTabs()}> <aside ref={(element) => setState("tabsMount", element)} data-slot="vertical-tabs-sidebar" class="relative flex h-full min-h-0 shrink-0 flex-col bg-v2-background-bg-deep pe-0.5 ps-2.5 pb-[var(--shell-bottom-inset,8px)] pt-[var(--shell-top-inset,8px)]" style={{ width: `${state.tabsWidth}px`, "padding-bottom": "max(10px, var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)))", }} > <ResizeHandle class="-end-2" direction="horizontal" size={state.tabsWidth} min={140} max={520} onResize={(width) => setState("tabsWidth", width)} /> </aside> </Show> {/* Size containment collapses percentage-height descendants in WebKit. */} <main class="flex-1 min-h-0 min-w-0 overflow-x-hidden flex flex-col items-start contain-content" style={{ "padding-top": bottomTitlebar() ? "env(safe-area-inset-top, 0px)" : "0px", "padding-bottom": bottomTitlebar() || settings.active() ? "0px" : "var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))", "--settings-bottom-inset": bottomTitlebar() ? "40px" : "var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))", "--settings-top-inset": mobile() && !bottomTitlebar() ? "0px" : "var(--shell-top-inset, 8px)", }} > <SshAuthentication> <Suspense>{props.children}</Suspense> </SshAuthentication> </main> </div> <Show when={state.debugTools}> <Suspense> <DebugBar diagnostics={import.meta.env.DEV} inline /> </Suspense> </Show> <ToastRegion /> <UploadToastHost /> </div> </TitlebarRightProvider> )}