diff options
| author | Daniel Polito <[email protected]> | 2026-01-16 13:51:02 -0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-16 10:51:02 -0600 |
| commit | 88fd6a294b3ad88d50cb8e1853589ee4e68dc74e (patch) | |
| tree | 1b187dab4b86528430498edc3ec3d3d4a243ea5f /packages/app/src/pages | |
| parent | ea8ef37d50408203d2ef7ebbdb82bbd15bbf8461 (diff) | |
| download | opencode-88fd6a294b3ad88d50cb8e1853589ee4e68dc74e.tar.gz opencode-88fd6a294b3ad88d50cb8e1853589ee4e68dc74e.zip | |
feat(desktop): Terminal Splits (#8767)
Diffstat (limited to 'packages/app/src/pages')
| -rw-r--r-- | packages/app/src/pages/session.tsx | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index ca5e73a9b..585156afa 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -26,6 +26,7 @@ import { useSync } from "@/context/sync" import { useTerminal, type LocalPTY } from "@/context/terminal" import { useLayout } from "@/context/layout" import { Terminal } from "@/components/terminal" +import { TerminalSplit } from "@/components/terminal-split" import { checksum, base64Encode, base64Decode } from "@opencode-ai/util/encode" import { useDialog } from "@opencode-ai/ui/context/dialog" import { DialogSelectFile } from "@/components/dialog-select-file" @@ -170,6 +171,7 @@ export default function Page() { const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) const tabs = createMemo(() => layout.tabs(sessionKey())) const view = createMemo(() => layout.view(sessionKey())) + const activeTerminal = createMemo(() => terminal.active()) if (import.meta.env.DEV) { createEffect( @@ -380,7 +382,7 @@ export default function Page() { createEffect(() => { if (!view().terminal.opened()) return if (!terminal.ready()) return - if (terminal.all().length !== 0) return + if (terminal.tabs().length !== 0) return terminal.new() }) @@ -460,6 +462,30 @@ export default function Page() { onSelect: () => terminal.new(), }, { + id: "terminal.split.vertical", + title: "Split terminal right", + description: "Split the current terminal vertically", + category: "Terminal", + keybind: "mod+d", + disabled: !terminal.active(), + onSelect: () => { + const active = terminal.active() + if (active) terminal.split(active, "vertical") + }, + }, + { + id: "terminal.split.horizontal", + title: "Split terminal down", + description: "Split the current terminal horizontally", + category: "Terminal", + keybind: "mod+shift+d", + disabled: !terminal.active(), + onSelect: () => { + const active = terminal.active() + if (active) terminal.split(active, "horizontal") + }, + }, + { id: "steps.toggle", title: "Toggle steps", description: "Show or hide steps for the current message", @@ -707,7 +733,7 @@ export default function Page() { const handleTerminalDragOver = (event: DragEvent) => { const { draggable, droppable } = event if (draggable && droppable) { - const terminals = terminal.all() + const terminals = terminal.tabs() const fromIndex = terminals.findIndex((t: LocalPTY) => t.id === draggable.id.toString()) const toIndex = terminals.findIndex((t: LocalPTY) => t.id === droppable.id.toString()) if (fromIndex !== -1 && toIndex !== -1 && fromIndex !== toIndex) { @@ -1009,7 +1035,7 @@ export default function Page() { createEffect(() => { if (!terminal.ready()) return - handoff.terminals = terminal.all().map((t) => t.title) + handoff.terminals = terminal.tabs().map((t) => t.title) }) createEffect(() => { @@ -1666,10 +1692,10 @@ export default function Page() { > <DragDropSensors /> <ConstrainDragYAxis /> - <Tabs variant="alt" value={terminal.active()} onChange={terminal.open}> + <Tabs variant="alt" value={activeTerminal()} onChange={terminal.open}> <Tabs.List class="h-10"> - <SortableProvider ids={terminal.all().map((t: LocalPTY) => t.id)}> - <For each={terminal.all()}>{(pty) => <SortableTerminalTab terminal={pty} />}</For> + <SortableProvider ids={terminal.tabs().map((t: LocalPTY) => t.id)}> + <For each={terminal.tabs()}>{(pty) => <SortableTerminalTab terminal={pty} />}</For> </SortableProvider> <div class="h-full flex items-center justify-center"> <TooltipKeybind @@ -1681,10 +1707,10 @@ export default function Page() { </TooltipKeybind> </div> </Tabs.List> - <For each={terminal.all()}> + <For each={terminal.tabs()}> {(pty) => ( - <Tabs.Content value={pty.id}> - <Terminal pty={pty} onCleanup={terminal.update} onConnectError={() => terminal.clone(pty.id)} /> + <Tabs.Content value={pty.id} class="h-[calc(100%-2.5rem)]"> + <TerminalSplit tabId={pty.id} /> </Tabs.Content> )} </For> @@ -1692,7 +1718,7 @@ export default function Page() { <DragOverlay> <Show when={store.activeTerminalDraggable}> {(draggedId) => { - const pty = createMemo(() => terminal.all().find((t: LocalPTY) => t.id === draggedId())) + const pty = createMemo(() => terminal.tabs().find((t: LocalPTY) => t.id === draggedId())) return ( <Show when={pty()}> {(t) => ( |
