@@ -9,7 +9,7 @@ import { Font } from "@opencode-ai/ui/font"
99import { Splash } from "@opencode-ai/ui/logo"
1010import { ThemeProvider } from "@opencode-ai/ui/theme/context"
1111import { MetaProvider } from "@solidjs/meta"
12- import { type BaseRouterProps , Navigate , Route , Router } from "@solidjs/router"
12+ import { type BaseRouterProps , Navigate , Route , Router , useParams , useSearchParams } from "@solidjs/router"
1313import { QueryClient , QueryClientProvider } from "@tanstack/solid-query"
1414import { Effect } from "effect"
1515import {
@@ -43,25 +43,88 @@ import { PromptProvider } from "@/context/prompt"
4343import { ServerConnection , ServerProvider , serverName , useServer } from "@/context/server"
4444import { SettingsProvider , useSettings } from "@/context/settings"
4545import { TerminalProvider } from "@/context/terminal"
46- import { TabsProvider } from "@/context/tabs"
46+ import { TabsProvider , useTabs , type DraftTab } from "@/context/tabs"
47+ import { SDKProvider , useSDK } from "@/context/sdk"
4748import { WslServersProvider } from "@/wsl/context"
48- import DirectoryLayout from "@/pages/directory-layout"
49+ import DirectoryLayout , { DirectoryDataProvider } from "@/pages/directory-layout"
4950import Layout from "@/pages/layout"
5051import { ErrorPage } from "./pages/error"
5152import { useCheckServerHealth } from "./utils/server-health"
5253
5354const HomeRoute = lazy ( ( ) => import ( "@/pages/home" ) )
5455const Session = lazy ( ( ) => import ( "@/pages/session" ) )
56+ const NewSession = lazy ( ( ) => import ( "@/pages/new-session" ) )
5557
5658const SessionRoute = Object . assign (
57- ( ) => (
58- < SessionProviders >
59- < Session />
60- </ SessionProviders >
61- ) ,
59+ ( ) => {
60+ const settings = useSettings ( )
61+ const params = useParams ( )
62+ const [ search ] = useSearchParams < { draftId ?: string ; prompt ?: string } > ( )
63+ const sdk = useSDK ( )
64+ const server = useServer ( )
65+ const tabs = useTabs ( )
66+
67+ // When the new layout is enabled, the legacy new-session route (/:dir/session with no id)
68+ // is replaced by a draft at /new-session?draftId=…
69+ createEffect ( ( ) => {
70+ if ( ! settings . general . newLayoutDesigns ( ) ) return
71+ if ( params . id || search . draftId ) return
72+ if ( ! tabs . ready ( ) || ! sdk . directory ) return
73+ tabs . newDraft ( { server : server . key , directory : sdk . directory } , search . prompt )
74+ } )
75+
76+ return (
77+ < SessionProviders >
78+ < Session />
79+ </ SessionProviders >
80+ )
81+ } ,
6282 { preload : Session . preload } ,
6383)
6484
85+ function DraftRoute ( ) {
86+ const [ search ] = useSearchParams < { draftId ?: string } > ( )
87+ const tabs = useTabs ( )
88+ return (
89+ < Show when = { tabs . ready ( ) } >
90+ < Show when = { search . draftId } keyed fallback = { < Navigate href = "/" /> } >
91+ { ( draftID ) => < ResolvedDraftRoute draftID = { draftID } /> }
92+ </ Show >
93+ </ Show >
94+ )
95+ }
96+
97+ function ResolvedDraftRoute ( props : { draftID : string } ) {
98+ const server = useServer ( )
99+ const tabs = useTabs ( )
100+ const draft = createMemo ( ( ) =>
101+ tabs . store . find ( ( tab ) : tab is DraftTab => tab . type === "draft" && tab . draftID === props . draftID ) ,
102+ )
103+
104+ createEffect ( ( ) => {
105+ const current = draft ( )
106+ if ( current && current . server !== server . key ) server . setActive ( current . server )
107+ } )
108+
109+ // Key on the directory so retargeting the draft's project re-instantiates the
110+ // SDK/data providers for the new directory while keeping the same draft id.
111+ const directory = ( ) => draft ( ) ?. directory
112+
113+ return (
114+ < Show when = { directory ( ) } keyed >
115+ { ( dir ) => (
116+ < SDKProvider directory = { dir } >
117+ < DirectoryDataProvider directory = { dir } draftID = { props . draftID } >
118+ < DraftProviders >
119+ < NewSession />
120+ </ DraftProviders >
121+ </ DirectoryDataProvider >
122+ </ SDKProvider >
123+ ) }
124+ </ Show >
125+ )
126+ }
127+
65128function UiI18nBridge ( props : ParentProps ) {
66129 const language = useLanguage ( )
67130 return < I18nProvider value = { { locale : language . intl , t : language . t } } > { props . children } </ I18nProvider >
@@ -141,6 +204,18 @@ function SessionProviders(props: ParentProps) {
141204 )
142205}
143206
207+ // The draft page only renders the prompt composer, so it drops TerminalProvider.
208+ // FileProvider and CommentsProvider stay because PromptInput uses file search and comment context.
209+ function DraftProviders ( props : ParentProps ) {
210+ return (
211+ < FileProvider >
212+ < PromptProvider >
213+ < CommentsProvider > { props . children } </ CommentsProvider >
214+ </ PromptProvider >
215+ </ FileProvider >
216+ )
217+ }
218+
144219function RouterRoot ( props : ParentProps < { appChildren ?: JSX . Element } > ) {
145220 return (
146221 < AppShellProviders >
@@ -335,6 +410,7 @@ export function AppInterface(props: {
335410 ) }
336411 >
337412 < Route path = "/" component = { HomeRoute } />
413+ < Route path = "/new-session" component = { DraftRoute } />
338414 < Route path = "/:dir" component = { DirectoryLayout } >
339415 < Route path = "/" component = { ( ) => < Navigate href = "session" /> } />
340416 < Route path = "/session/:id?" component = { SessionRoute } />
0 commit comments