@@ -3,10 +3,14 @@ import { App as CapApp } from "@capacitor/app"
33import { useServerConfig } from "./hooks/useServerConfig"
44import { useServerData } from "./hooks/useServerData"
55import { useChat } from "./hooks/useChat"
6+ import ProjectsScreen from "./screens/ProjectsScreen"
67import SessionsScreen from "./screens/SessionsScreen"
78import ChatScreen from "./screens/ChatScreen"
89import SettingsScreen from "./screens/SettingsScreen"
910import HelpScreen from "./screens/HelpScreen"
11+ import type { Project } from "./types"
12+
13+ type Screen = "projects" | "sessions" | "chat" | "settings" | "help"
1014
1115function App ( ) {
1216 const sv = useServerConfig ( )
@@ -32,45 +36,50 @@ function App() {
3236 prefs : sv . prefs ,
3337 } )
3438
35- const [ tab , setTab ] = useState < "sessions" | "settings" > ( ( ) =>
36- sv . hasConfiguredServer ? "sessions " : "settings" ,
39+ const [ screen , setScreen ] = useState < Screen > ( ( ) =>
40+ sv . hasConfiguredServer ? "projects " : "settings"
3741 )
38- const [ chatOpen , setChatOpen ] = useState ( false )
39- const [ helpOpen , setHelpOpen ] = useState ( false )
42+ const [ selectedProject , setSelectedProject ] = useState < Project | null > ( null )
4043
4144 const connected = sv . connectedVersion !== ""
4245
4346 const isWorking = Boolean (
4447 sd . selectedSession && [ "busy" , "retry" , "ask" , "question" , "permission" ] . includes ( sd . selectedSession . status ) ,
4548 )
4649
50+ function openProject ( project : Project ) {
51+ setSelectedProject ( project )
52+ setScreen ( "sessions" )
53+ }
54+
4755 function openSession ( id : string , dir : string ) {
4856 sd . setSelectedID ( id )
4957 sd . loadSelected ( id , dir ) . catch ( ( ) => undefined )
50- setChatOpen ( true )
58+ setScreen ( "chat" )
59+ }
60+
61+ async function handleCreateSession ( directory ?: string ) {
62+ await sd . createSession ( directory )
63+ setScreen ( "chat" )
5164 }
5265
5366 function handleSaveConfig ( ) {
5467 sv . saveConfig ( )
5568 sd . setRuntimeError ( null )
56- setTab ( "sessions ")
69+ setScreen ( "projects ")
5770 }
5871
59- async function handleCreateSession ( ) {
60- await sd . createSession ( )
61- setChatOpen ( true )
62- }
63-
64- // ── Android back button ──────────────────────────────────────────
72+ // Android back button
6573 useEffect ( ( ) => {
6674 let listener : { remove : ( ) => void } | null = null
6775
6876 const onBack = ( ) => {
69- if ( helpOpen ) {
70- setHelpOpen ( false )
71- } else if ( chatOpen ) {
72- setChatOpen ( false )
73- setTab ( "sessions" )
77+ if ( screen === "help" ) {
78+ setScreen ( "settings" )
79+ } else if ( screen === "chat" ) {
80+ setScreen ( "sessions" )
81+ } else if ( screen === "sessions" ) {
82+ setScreen ( "projects" )
7483 }
7584 // else: default system behaviour
7685 }
@@ -82,20 +91,11 @@ function App() {
8291 return ( ) => {
8392 if ( listener ) listener . remove ( )
8493 }
85- } , [ helpOpen , chatOpen ] )
94+ } , [ screen ] )
8695
87- return (
88- < div className = "app-shell" >
89- { sd . toast && (
90- < div
91- className = { `toast toast-${ sd . toast . type } fade-in` }
92- onClick = { ( ) => sd . setToast ( null ) }
93- >
94- { sd . toast . text }
95- </ div >
96- ) }
97-
98- { chatOpen ? (
96+ const renderScreen = ( ) => {
97+ if ( screen === "chat" ) {
98+ return (
9999 < ChatScreen
100100 selectedSession = { sd . selectedSession }
101101 renderedMessages = { sd . renderedMessages }
@@ -106,10 +106,8 @@ function App() {
106106 setTodosExpanded = { sd . setTodosExpanded }
107107 sessionInfo = { sd . sessionInfo }
108108 runtimeError = { sd . runtimeError }
109- onBack = { ( ) => {
110- setChatOpen ( false )
111- setTab ( "sessions" )
112- } }
109+ diff = { sd . diff }
110+ onBack = { ( ) => setScreen ( "sessions" ) }
113111 isWorking = { isWorking }
114112 abortSession = { chat . abortSession }
115113 composer = { chat . composer }
@@ -134,51 +132,91 @@ function App() {
134132 currentAgent = { sd . currentAgent }
135133 primaryAgents = { sd . primaryAgents }
136134 cycleAgent = { chat . cycleAgent }
135+ questions = { sd . questions }
137136 replyPermission = { chat . replyPermission }
137+ replyQuestion = { chat . replyQuestion }
138+ rejectQuestion = { chat . rejectQuestion }
139+ forkSession = { sd . forkSession }
140+ renameSession = { sd . renameSession }
141+ onSessionForked = { ( ) => setScreen ( "sessions" ) }
138142 />
139- ) : helpOpen ? (
143+ )
144+ }
145+
146+ if ( screen === "help" ) {
147+ return (
140148 < HelpScreen
141- onBack = { ( ) => setHelpOpen ( false ) }
149+ onBack = { ( ) => setScreen ( "settings" ) }
142150 commands = { sd . commands }
143151 />
144- ) : (
145- < >
146- { tab === "sessions" && (
147- < SessionsScreen
148- config = { { host : sv . config . host } }
149- connected = { connected }
150- filteredSessions = { sd . filteredSessions }
151- selectedID = { sd . selectedID }
152- onOpenSession = { openSession }
153- query = { sd . query }
154- setQuery = { sd . setQuery }
155- createSession = { handleCreateSession }
156- serverDirectory = { sd . serverDirectory }
157- runtimeError = { sd . runtimeError }
158- refreshSessions = { sd . refreshSessions }
159- onOpenSettings = { ( ) => setTab ( "settings" ) }
160- deleteSession = { sd . deleteSession }
161- />
162- ) }
163- { tab === "settings" && (
164- < SettingsScreen
165- theme = { sv . theme }
166- setTheme = { sv . setTheme }
167- draftConfig = { sv . draftConfig }
168- setDraftConfig = { sv . setDraftConfig }
169- connectedVersion = { sv . connectedVersion }
170- settingsNotice = { sv . settingsNotice }
171- testingConnection = { sv . testingConnection }
172- prefs = { sv . prefs }
173- setPrefs = { sv . setPrefs }
174- saveConfig = { handleSaveConfig }
175- testConnection = { sv . testConnection }
176- onOpenHelp = { ( ) => setHelpOpen ( true ) }
177- onBack = { ( ) => setTab ( "sessions" ) }
178- />
179- ) }
180- </ >
152+ )
153+ }
154+
155+ if ( screen === "settings" ) {
156+ return (
157+ < SettingsScreen
158+ theme = { sv . theme }
159+ setTheme = { sv . setTheme }
160+ draftConfig = { sv . draftConfig }
161+ setDraftConfig = { sv . setDraftConfig }
162+ connectedVersion = { sv . connectedVersion }
163+ settingsNotice = { sv . settingsNotice }
164+ testingConnection = { sv . testingConnection }
165+ prefs = { sv . prefs }
166+ setPrefs = { sv . setPrefs }
167+ saveConfig = { handleSaveConfig }
168+ testConnection = { sv . testConnection }
169+ onOpenHelp = { ( ) => setScreen ( "help" ) }
170+ onBack = { ( ) => setScreen ( sv . hasConfiguredServer ? "projects" : "settings" ) }
171+ mcpServers = { sd . mcpServers }
172+ />
173+ )
174+ }
175+
176+ if ( screen === "sessions" && selectedProject ) {
177+ return (
178+ < SessionsScreen
179+ project = { selectedProject }
180+ sessions = { sd . sessions }
181+ selectedID = { sd . selectedID }
182+ onOpenSession = { openSession }
183+ onBack = { ( ) => setScreen ( "projects" ) }
184+ query = { sd . query }
185+ setQuery = { sd . setQuery }
186+ createSession = { handleCreateSession }
187+ runtimeError = { sd . runtimeError }
188+ refreshSessions = { sd . refreshSessions }
189+ deleteSession = { sd . deleteSession }
190+ />
191+ )
192+ }
193+
194+ // Default: projects
195+ return (
196+ < ProjectsScreen
197+ config = { { host : sv . config . host } }
198+ connected = { connected }
199+ projects = { sd . projects }
200+ sessions = { sd . sessions }
201+ onOpenProject = { openProject }
202+ onOpenSettings = { ( ) => setScreen ( "settings" ) }
203+ refreshSessions = { sd . refreshSessions }
204+ runtimeError = { sd . runtimeError }
205+ />
206+ )
207+ }
208+
209+ return (
210+ < div className = "app-shell" >
211+ { sd . toast && (
212+ < div
213+ className = { `toast toast-${ sd . toast . type } fade-in` }
214+ onClick = { ( ) => sd . setToast ( null ) }
215+ >
216+ { sd . toast . text }
217+ </ div >
181218 ) }
219+ { renderScreen ( ) }
182220 </ div >
183221 )
184222}
0 commit comments