git.iko.soy/opencode-android
on master help sign in
Fix expand/collapse state loss on rotation and stale error snackbars re-showing after navigation
commit2db74cbd43924e5b9ef162e4046bf4b636536742 authoriko <mail@iko.soy> dateTue 30 Jun 2026, 10:51 (3 months ago) parentc6a343e
5 files changed+26−14
app/src/main/java/soy/iko/opencode/ui/chat/ChatScreen.kt+9−6 app/src/main/java/soy/iko/opencode/ui/chat/PartRenderer.kt+3−2 app/src/main/java/soy/iko/opencode/ui/file/FileBrowserScreen.kt+5−2 app/src/main/java/soy/iko/opencode/ui/server/ServerListScreen.kt+4−2 app/src/main/java/soy/iko/opencode/ui/session/SessionListScreen.kt+5−2
app/src/main/java/soy/iko/opencode/ui/chat/ChatScreen.kt+9−6
@@ -200,13 +200,16 @@ fun ChatScreen(
200200 val retryLabel = stringResource(R.string.retry)
201201 LaunchedEffect(error) {
202202 val msg = error ?: return@LaunchedEffect
203− val result = if (failedDraft != null) {
204− snackbar.showSnackbar(message = msg, actionLabel = retryLabel)
205− } else {
206− snackbar.showSnackbar(msg)
203+ try {
204+ val result = if (failedDraft != null) {
205+ snackbar.showSnackbar(message = msg, actionLabel = retryLabel)
206+ } else {
207+ snackbar.showSnackbar(msg)
208+ }
209+ if (result == androidx.compose.material3.SnackbarResult.ActionPerformed) vm.retryFailed()
210+ } finally {
211+ vm.clearError()
207212 }
208− if (result == androidx.compose.material3.SnackbarResult.ActionPerformed) vm.retryFailed()
209− vm.clearError()
210213 }
211214
212215 fun doSend() {
app/src/main/java/soy/iko/opencode/ui/chat/PartRenderer.kt+3−2
@@ -29,6 +29,7 @@ import androidx.compose.runtime.Composable
2929import androidx.compose.runtime.getValue
3030import androidx.compose.runtime.mutableStateOf
3131import androidx.compose.runtime.remember
32+import androidx.compose.runtime.saveable.rememberSaveable
3233import androidx.compose.runtime.setValue
3334import androidx.compose.ui.Alignment
3435import androidx.compose.ui.Modifier
@@ -94,7 +95,7 @@ fun PartView(part: Part, modifier: Modifier = Modifier, isRunning: Boolean = fal
9495private fun ReasoningBlock(text: String, streaming: Boolean, modifier: Modifier) {
9596 if (text.isBlank()) return
9697 val context = LocalContext.current
97− var expanded by remember { mutableStateOf(false) }
98+ var expanded by rememberSaveable { mutableStateOf(false) }
9899 val expandedState = stringResource(R.string.state_expanded)
99100 val collapsedState = stringResource(R.string.state_collapsed)
100101 Column(modifier = modifier.fillMaxWidth()) {
@@ -177,7 +178,7 @@ private fun ToolCallView(part: ToolPart, modifier: Modifier) {
177178 }
178179 if (detail != null) {
179180 val collapsed = remember(detail) { detail.take(COLLAPSED_LIMIT) }
180− var expanded by remember(detail) { mutableStateOf(false) }
181+ var expanded by rememberSaveable(detail) { mutableStateOf(false) }
181182 val expandedState = stringResource(R.string.state_expanded)
182183 val collapsedState = stringResource(R.string.state_collapsed)
183184 val display = if (expanded || detail.length <= COLLAPSED_LIMIT) detail else collapsed
app/src/main/java/soy/iko/opencode/ui/file/FileBrowserScreen.kt+5−2
@@ -70,8 +70,11 @@ fun FileBrowserScreen(
7070
7171 LaunchedEffect(transientError) {
7272 val msg = transientError ?: return@LaunchedEffect
73− snackbar.showSnackbar(msg)
74− vm.clearTransientError()
73+ try {
74+ snackbar.showSnackbar(msg)
75+ } finally {
76+ vm.clearTransientError()
77+ }
7578 }
7679
7780 Scaffold(
app/src/main/java/soy/iko/opencode/ui/server/ServerListScreen.kt+4−2
@@ -77,8 +77,10 @@ fun ServerListScreen(
7777 val connectedId = activeConnection?.profile?.id
7878
7979 LaunchedEffect(error) {
80− error?.let {
81− snackbar.showSnackbar(it)
80+ val msg = error ?: return@LaunchedEffect
81+ try {
82+ snackbar.showSnackbar(msg)
83+ } finally {
8284 vm.clearError()
8385 }
8486 }
app/src/main/java/soy/iko/opencode/ui/session/SessionListScreen.kt+5−2
@@ -109,8 +109,11 @@ fun SessionListScreen(
109109
110110 LaunchedEffect(transientError) {
111111 val msg = transientError ?: return@LaunchedEffect
112− snackbar.showSnackbar(msg)
113− vm.clearTransientError()
112+ try {
113+ snackbar.showSnackbar(msg)
114+ } finally {
115+ vm.clearTransientError()
116+ }
114117 }
115118
116119 Scaffold(