git.iko.soy/opencode-android
on master help sign in
Fix stuck refresh indicator on disconnect, stale unread badges on server switch, and lost file browser navigation when offline
274bb6aiko
app/src/main/java/soy/iko/opencode/di/AppContainer.kt+1
@@ -259,6 +259,7 @@ class AppContainer(context: Context) {
259 _activeConnection.value?.close()
259 _activeConnection.value?.close()
260 _activeConnection.value = null
260 _activeConnection.value = null
261 activeRuns.clear()
261 activeRuns.clear()
262+ _unread.value = emptySet()
262 val now = System.currentTimeMillis()
263 val now = System.currentTimeMillis()
263 val resolved = profileStore.resolve(profile)
264 val resolved = profileStore.resolve(profile)
264 val needsSave = (now - resolved.lastUsed) > LAST_USED_SAVE_THRESHOLD_MS
265 val needsSave = (now - resolved.lastUsed) > LAST_USED_SAVE_THRESHOLD_MS
app/src/main/java/soy/iko/opencode/ui/chat/ChatViewModel.kt+4−2
@@ -341,8 +341,10 @@ class ChatViewModel(
341
341
342 override fun onCleared() {
342 override fun onCleared() {
343 super.onCleared()
343 super.onCleared()
344− // Flush any pending debounced draft so it survives navigation. Use a synchronous
344+ // Flush any pending debounced draft so it survives navigation. Uses an
345− // commit instead of runBlocking so the main thread isn't held hostage by disk I/O.
345+ // asynchronous apply() (not a synchronous commit) so the main thread isn't
346+ // blocked on disk I/O — Android's SharedPreferences framework guarantees
347+ // pending apply() writes are flushed before the process exits.
346 val pending = _draft.value
348 val pending = _draft.value
347 if (pending.isNotEmpty()) {
349 if (pending.isNotEmpty()) {
348 container.draftStore.flushDraft(sessionId, pending)
350 container.draftStore.flushDraft(sessionId, pending)
app/src/main/java/soy/iko/opencode/ui/file/FileBrowserViewModel.kt+5−1
@@ -88,7 +88,11 @@ class FileBrowserViewModel(private val container: AppContainer) : ViewModel() {
88
88
89 fun open(path: String) {
89 fun open(path: String) {
90 val client = api ?: run {
90 val client = api ?: run {
91+ _state.value = _state.value.copy(
92+ path = path,
93+ loading = false,
91− _state.value = _state.value.copy(loading = false, error = container.string(R.string.not_connected))
94+ error = container.string(R.string.not_connected),
95+ )
92 return
96 return
93 }
97 }
94 _state.value = _state.value.copy(path = path, loading = true, error = null)
98 _state.value = _state.value.copy(path = path, loading = true, error = null)
app/src/main/java/soy/iko/opencode/ui/session/SessionListViewModel.kt+1
@@ -165,6 +165,7 @@ class SessionListViewModel(private val container: AppContainer) : ViewModel() {
165 _state.update { it.copy(loading = false) }
165 _state.update { it.copy(loading = false) }
166 _transientError.value = container.string(R.string.not_connected)
166 _transientError.value = container.string(R.string.not_connected)
167 }
167 }
168+ _refreshing.value = false
168 return
169 return
169 }
170 }
170 _serverLabel.value = conn.profile.displayLabel
171 _serverLabel.value = conn.profile.displayLabel