From 88fd6a294b3ad88d50cb8e1853589ee4e68dc74e Mon Sep 17 00:00:00 2001 From: Daniel Polito Date: Fri, 16 Jan 2026 13:51:02 -0300 Subject: feat(desktop): Terminal Splits (#8767) --- packages/app/src/pages/session.tsx | 46 +++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'packages/app/src/pages') 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() }) @@ -459,6 +461,30 @@ export default function Page() { keybind: "ctrl+shift+`", 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", @@ -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() { > - + - t.id)}> - {(pty) => } + t.id)}> + {(pty) => }
- + {(pty) => ( - - terminal.clone(pty.id)} /> + + )} @@ -1692,7 +1718,7 @@ export default function Page() { {(draggedId) => { - const pty = createMemo(() => terminal.all().find((t: LocalPTY) => t.id === draggedId())) + const pty = createMemo(() => terminal.tabs().find((t: LocalPTY) => t.id === draggedId())) return ( {(t) => ( -- cgit v1.2.3