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 = (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 & { worktree: string; expanded: boolean } export type ReviewDiffStyle = "unified" | "split" @@ -115,6 +121,9 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, sessionTabs: {} as Record, sessionView: {} as Record, + 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(