summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-02-04 06:22:55 -0600
committerAdam <[email protected]>2026-02-04 06:22:55 -0600
commita219615fe5aeb6a40898300b17f076072aed5bcc (patch)
tree663a1571f1138ccf96ea85df08de27ed790be131
parentaf06175b1f293ea13d4165cee56db65fbbd56c65 (diff)
downloadopencode-a219615fe5aeb6a40898300b17f076072aed5bcc.tar.gz
opencode-a219615fe5aeb6a40898300b17f076072aed5bcc.zip
fix(app): opened tabs follow created session
-rw-r--r--packages/app/src/components/prompt-input.tsx5
-rw-r--r--packages/app/src/context/layout.tsx19
-rw-r--r--packages/app/src/pages/session.tsx38
3 files changed, 61 insertions, 1 deletions
diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx
index 6b568e916..b897e394a 100644
--- a/packages/app/src/components/prompt-input.tsx
+++ b/packages/app/src/components/prompt-input.tsx
@@ -1220,7 +1220,10 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
})
return undefined
})
- if (session) navigate(`/${base64Encode(sessionDirectory)}/session/${session.id}`)
+ if (session) {
+ layout.handoff.setTabs(base64Encode(sessionDirectory), session.id)
+ navigate(`/${base64Encode(sessionDirectory)}/session/${session.id}`)
+ }
}
if (!session) return
diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx
index 28fe628a8..71f3f6cff 100644
--- a/packages/app/src/context/layout.tsx
+++ b/packages/app/src/context/layout.tsx
@@ -35,6 +35,12 @@ type SessionView = {
reviewOpen?: string[]
}
+type TabHandoff = {
+ dir: string
+ id: string
+ at: number
+}
+
export type LocalProject = Partial<Project> & { worktree: string; expanded: boolean }
export type ReviewDiffStyle = "unified" | "split"
@@ -115,6 +121,9 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
},
sessionTabs: {} as Record<string, SessionTabs>,
sessionView: {} as Record<string, SessionView>,
+ handoff: {
+ tabs: undefined as TabHandoff | undefined,
+ },
}),
)
@@ -411,6 +420,16 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
return {
ready,
+ handoff: {
+ tabs: createMemo(() => store.handoff?.tabs),
+ setTabs(dir: string, id: string) {
+ setStore("handoff", "tabs", { dir, id, at: Date.now() })
+ },
+ clearTabs() {
+ if (!store.handoff?.tabs) return
+ setStore("handoff", "tabs", undefined)
+ },
+ },
projects: {
list,
open(directory: string) {
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index e8c61ee98..e31ab18b9 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -280,9 +280,47 @@ export default function Page() {
.finally(() => setUi("responding", false))
}
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
+ const workspaceKey = createMemo(() => params.dir ?? "")
+ const workspaceTabs = createMemo(() => layout.tabs(workspaceKey))
const tabs = createMemo(() => layout.tabs(sessionKey))
const view = createMemo(() => layout.view(sessionKey))
+ createEffect(
+ on(
+ () => params.id,
+ (id, prev) => {
+ if (!id) return
+ if (prev) return
+
+ const pending = layout.handoff.tabs()
+ if (!pending) return
+ if (Date.now() - pending.at > 60_000) {
+ layout.handoff.clearTabs()
+ return
+ }
+
+ if (pending.id !== id) return
+ layout.handoff.clearTabs()
+ if (pending.dir !== (params.dir ?? "")) return
+
+ const from = workspaceTabs().tabs()
+ if (from.all.length === 0 && !from.active) return
+
+ const current = tabs().tabs()
+ if (current.all.length > 0 || current.active) return
+
+ const all = normalizeTabs(from.all)
+ const active = from.active ? normalizeTab(from.active) : undefined
+ tabs().setAll(all)
+ tabs().setActive(active && all.includes(active) ? active : all[0])
+
+ workspaceTabs().setAll([])
+ workspaceTabs().setActive(undefined)
+ },
+ { defer: true },
+ ),
+ )
+
if (import.meta.env.DEV) {
createEffect(
on(