git.iko.soy/opencode-android
on master help sign in
Fix file browser search debounce flash, SessionListViewModel indentation, and DiagnosticsScreen dead error handling
commit3996399b03796fc53e83e05c1ff16d26a83c816a authoriko <mail@iko.soy> dateTue 30 Jun 2026, 11:14 (3 months ago) parent50dc098
3 files changed+16−20
app/src/main/java/soy/iko/opencode/ui/file/FileBrowserViewModel.kt+4−2 app/src/main/java/soy/iko/opencode/ui/session/SessionListViewModel.kt+10−10 app/src/main/java/soy/iko/opencode/ui/settings/DiagnosticsScreen.kt+2−8
app/src/main/java/soy/iko/opencode/ui/file/FileBrowserViewModel.kt+4−2
@@ -140,14 +140,16 @@ class FileBrowserViewModel(private val container: AppContainer) : ViewModel() {
140140 }
141141 // The search view replaces the directory listing; clear loading so the spinner
142142 // from a cancelled open() doesn't persist into the search results view.
143− _state.update { it.copy(loading = false) }
143+ // Set searching=true immediately (not after the debounce) so the spinner shows
144+ // during the debounce delay — otherwise the UI briefly renders SearchResults
145+ // with an empty list, flashing "no matches" before the search even starts.
146+ _state.update { it.copy(loading = false, searching = true) }
144147 val client = api ?: run {
145148 _state.update { it.copy(searching = false, error = container.string(R.string.not_connected)) }
146149 return
147150 }
148151 searchJob = viewModelScope.launch {
149152 delay(NetworkConfig.fileSearchDebounceMs) // debounce
150− _state.update { it.copy(searching = true) }
151153 runCatchingCancellable { client.findFiles(query) }
152154 .onSuccess { results -> _state.update { it.copy(results = results, searching = false) } }
153155 .onFailure { e -> _state.update { it.copy(searching = false, error = container.friendlyError(e)) } }
app/src/main/java/soy/iko/opencode/ui/session/SessionListViewModel.kt+10−10
@@ -136,18 +136,18 @@ class SessionListViewModel(private val container: AppContainer) : ViewModel() {
136136 loadPreview(session.id)
137137 }
138138 is SessionDeleted -> {
139− val id = event.properties.info?.id ?: event.properties.sessionID
140− if (id != null) {
141− synchronized(previewLock) { livePreviewJobs.remove(id)?.cancel() }
142− container.draftStore.remove(id)
143− _state.update { s ->
144− s.copy(
145− sessions = s.sessions.filterNot { it.id == id },
146− previews = s.previews - id,
147− )
139+ val id = event.properties.info?.id ?: event.properties.sessionID
140+ if (id != null) {
141+ synchronized(previewLock) { livePreviewJobs.remove(id)?.cancel() }
142+ container.draftStore.remove(id)
143+ _state.update { s ->
144+ s.copy(
145+ sessions = s.sessions.filterNot { it.id == id },
146+ previews = s.previews - id,
147+ )
148+ }
148149 }
149150 }
150− }
151151 else -> {}
152152 }
153153 }
app/src/main/java/soy/iko/opencode/ui/settings/DiagnosticsScreen.kt+2−8
@@ -75,10 +75,7 @@ fun DiagnosticsScreen(onBack: () -> Unit) {
7575 actions = {
7676 if (reports.isNotEmpty()) {
7777 IconButton(onClick = {
78− shareScope.launch(Dispatchers.IO) {
79− runCatching { logger.clearAll() }
80− .onFailure { Log.w("Diagnostics", "Failed to clear crash reports", it) }
81− }
78+ logger.clearAll()
8279 }) {
8380 Icon(Icons.Filled.DeleteSweep, contentDescription = stringResource(R.string.clear_all))
8481 }
@@ -185,10 +182,7 @@ fun DiagnosticsScreen(onBack: () -> Unit) {
185182 }) { Text(stringResource(R.string.share)) }
186183 Spacer(Modifier.size(8.dp))
187184 TextButton(onClick = {
188− shareScope.launch(Dispatchers.IO) {
189− runCatching { logger.deleteReport(reportName) }
190− .onFailure { Log.w("Diagnostics", "Failed to delete crash report", it) }
191− }
185+ logger.deleteReport(reportName)
192186 viewing = null
193187 }) { Text(stringResource(R.string.delete)) }
194188 }