@@ -32,6 +32,7 @@ import soy.iko.opencode.ui.screens.SessionsScreen
32fun OpencodeApp(state: UiState, dispatch: (Event) -> Unit) {
32fun OpencodeApp(state: UiState, dispatch: (Event) -> Unit) {
33 val snackbar = remember { SnackbarHostState() }
33 val snackbar = remember { SnackbarHostState() }
34 var showStopConfirm by remember { mutableStateOf(false) }
34 var showStopConfirm by remember { mutableStateOf(false) }
35+ var showDisconnectConfirm by remember { mutableStateOf(false) }
36 LaunchedEffect(state.error) {
37 LaunchedEffect(state.error) {
37 state.error?.let {
38 state.error?.let {
@@ -49,7 +50,8 @@ fun OpencodeApp(state: UiState, dispatch: (Event) -> Unit) {
49 when (state.screen) {
50 when (state.screen) {
50 // Leaving mid-generation would silently drop the reply, so confirm first.
51 // Leaving mid-generation would silently drop the reply, so confirm first.
51 Screen.Chat -> if (state.generating) showStopConfirm = true else dispatch(Event.NavigateToSessions)
52 Screen.Chat -> if (state.generating) showStopConfirm = true else dispatch(Event.NavigateToSessions)
52− Screen.Sessions -> dispatch(Event.NavigateToConnect)
53+ // Disconnecting drops the server session, so guard the back button.
54+ Screen.Sessions -> showDisconnectConfirm = true
53 Screen.Connect -> Unit
55 Screen.Connect -> Unit
@@ -76,6 +78,27 @@ fun OpencodeApp(state: UiState, dispatch: (Event) -> Unit) {
81+ if (showDisconnectConfirm) {
83+ onDismissRequest = { showDisconnectConfirm = false },
84+ title = { Text("Disconnect?") },
85+ text = { Text("You will be disconnected from the server.") },
87+ TextButton(onClick = {
88+ showDisconnectConfirm = false
89+ dispatch(Event.NavigateToConnect)
95+ TextButton(onClick = { showDisconnectConfirm = false }) {
79 Scaffold(snackbarHost = { SnackbarHost(snackbar) }) { padding ->
102 Scaffold(snackbarHost = { SnackbarHost(snackbar) }) { padding ->
80 AnimatedContent(
103 AnimatedContent(
81 targetState = state.screen,
104 targetState = state.screen,