diff options
| author | adamelmore <[email protected]> | 2026-01-26 22:58:29 -0600 |
|---|---|---|
| committer | adamelmore <[email protected]> | 2026-01-27 06:29:18 -0600 |
| commit | 58b9b54600f12ba4ec1d80a2d1b7dee3879a0479 (patch) | |
| tree | 797755369dc2d81ff04c32f0d0b4780e2db84d03 /packages/app/src | |
| parent | c0a5f853497de6778f1430b691e393caa54c59a7 (diff) | |
| download | opencode-58b9b54600f12ba4ec1d80a2d1b7dee3879a0479.tar.gz opencode-58b9b54600f12ba4ec1d80a2d1b7dee3879a0479.zip | |
feat(app): forward and back buttons
Diffstat (limited to 'packages/app/src')
| -rw-r--r-- | packages/app/src/components/titlebar.tsx | 135 | ||||
| -rw-r--r-- | packages/app/src/context/platform.tsx | 6 | ||||
| -rw-r--r-- | packages/app/src/entry.tsx | 6 | ||||
| -rw-r--r-- | packages/app/src/i18n/en.ts | 1 |
4 files changed, 121 insertions, 27 deletions
diff --git a/packages/app/src/components/titlebar.tsx b/packages/app/src/components/titlebar.tsx index 159216a4f..1c8256069 100644 --- a/packages/app/src/components/titlebar.tsx +++ b/packages/app/src/components/titlebar.tsx @@ -1,8 +1,10 @@ -import { createEffect, createMemo, Show } from "solid-js" +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 { TooltipKeybind } from "@opencode-ai/ui/tooltip" +import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { useTheme } from "@opencode-ai/ui/theme" import { useLayout } from "@/context/layout" @@ -16,11 +18,68 @@ export function Titlebar() { 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 [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(() => { + if (!history.stack.length) { + const stack = current === "/" ? ["/"] : ["/", current] + setHistory({ stack, index: stack.length - 1 }) + return + } + + const active = history.stack[history.index] + if (current === active) { + if (history.action) setHistory("action", undefined) + return + } + + if (history.action) { + setHistory("action", undefined) + return + } + + const next = history.stack.slice(0, history.index + 1).concat(current) + setHistory({ stack: next, index: next.length - 1 }) + }) + }) + + const canBack = createMemo(() => history.index > 0) + const canForward = createMemo(() => history.index < history.stack.length - 1) + + const back = () => { + if (!canBack()) return + const index = history.index - 1 + const to = history.stack[index] + if (!to) return + setHistory({ index, action: "back" }) + navigate(to) + } + + const forward = () => { + if (!canForward()) return + const index = history.index + 1 + const to = history.stack[index] + if (!to) return + setHistory({ index, action: "forward" }) + navigate(to) + } + const getWin = () => { if (platform.platform !== "desktop") return @@ -106,34 +165,56 @@ export function Titlebar() { /> </div> </Show> - <TooltipKeybind - class={web() ? "hidden xl:flex shrink-0 ml-14" : "hidden xl:flex shrink-0 ml-2"} - placement="bottom" - title={language.t("command.sidebar.toggle")} - keybind={command.keybind("sidebar.toggle")} - > - <Button - variant="ghost" - class="group/sidebar-toggle size-6 p-0" - onClick={layout.sidebar.toggle} - aria-label={language.t("command.sidebar.toggle")} - aria-expanded={layout.sidebar.opened()} + <div class="flex items-center gap-1 shrink-0"> + <TooltipKeybind + class={web() ? "hidden xl:flex shrink-0 ml-14" : "hidden xl:flex shrink-0 ml-2"} + placement="bottom" + title={language.t("command.sidebar.toggle")} + keybind={command.keybind("sidebar.toggle")} > - <div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0"> - <Icon - size="small" - name={layout.sidebar.opened() ? "layout-left-full" : "layout-left"} - class="group-hover/sidebar-toggle:hidden" + <Button + variant="ghost" + class="group/sidebar-toggle size-6 p-0" + onClick={layout.sidebar.toggle} + aria-label={language.t("command.sidebar.toggle")} + aria-expanded={layout.sidebar.opened()} + > + <div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0"> + <Icon + size="small" + name={layout.sidebar.opened() ? "layout-left-full" : "layout-left"} + class="group-hover/sidebar-toggle:hidden" + /> + <Icon size="small" name="layout-left-partial" class="hidden group-hover/sidebar-toggle:inline-block" /> + <Icon + size="small" + name={layout.sidebar.opened() ? "layout-left" : "layout-left-full"} + class="hidden group-active/sidebar-toggle:inline-block" + /> + </div> + </Button> + </TooltipKeybind> + <div class="hidden xl:flex items-center gap-1 shrink-0"> + <Tooltip placement="bottom" value={language.t("common.goBack")}> + <IconButton + icon="arrow-left" + variant="ghost" + disabled={!canBack()} + onClick={back} + aria-label={language.t("common.goBack")} /> - <Icon size="small" name="layout-left-partial" class="hidden group-hover/sidebar-toggle:inline-block" /> - <Icon - size="small" - name={layout.sidebar.opened() ? "layout-left" : "layout-left-full"} - class="hidden group-active/sidebar-toggle:inline-block" + </Tooltip> + <Tooltip placement="bottom" value={language.t("common.goForward")}> + <IconButton + icon="arrow-right" + variant="ghost" + disabled={!canForward()} + onClick={forward} + aria-label={language.t("common.goForward")} /> - </div> - </Button> - </TooltipKeybind> + </Tooltip> + </div> + </div> <div id="opencode-titlebar-left" class="flex items-center gap-3 min-w-0 px-2" data-tauri-drag-region /> <div class="flex-1 h-full" data-tauri-drag-region /> <div diff --git a/packages/app/src/context/platform.tsx b/packages/app/src/context/platform.tsx index b97f70fea..f6fb157f0 100644 --- a/packages/app/src/context/platform.tsx +++ b/packages/app/src/context/platform.tsx @@ -17,6 +17,12 @@ export type Platform = { /** Restart the app */ restart(): Promise<void> + /** Navigate back in history */ + back(): void + + /** Navigate forward in history */ + forward(): void + /** Send a system notification (optional deep link) */ notify(title: string, description?: string, href?: string): Promise<void> diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx index 7fe03bb6a..aa52fa1e7 100644 --- a/packages/app/src/entry.tsx +++ b/packages/app/src/entry.tsx @@ -31,6 +31,12 @@ const platform: Platform = { openLink(url: string) { window.open(url, "_blank") }, + back() { + window.history.back() + }, + forward() { + window.history.forward() + }, restart: async () => { window.location.reload() }, diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index bca08275f..abbe497dc 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -167,6 +167,7 @@ export const dict = { "common.search.placeholder": "Search", "common.goBack": "Go back", + "common.goForward": "Go forward", "common.loading": "Loading", "common.loading.ellipsis": "...", "common.cancel": "Cancel", |
