git.iko.soy/opencode-android
on master help sign in
Fix untruncated bulk previews, stale file-search error, switch-server error clobber, and generic send-failure message, and log swallowed SSE parse errors
commitf2ce9a122c69e85ff04b5c02bd18dbf06df67f78 authoriko <mail@iko.soy> dateMon 29 Jun 2026, 20:19 (3 months ago) parent78252a2
4 files changed+8−9
app/src/main/java/soy/iko/opencode/data/network/EventStreamClient.kt+1 app/src/main/java/soy/iko/opencode/ui/chat/ChatViewModel.kt+5−6 app/src/main/java/soy/iko/opencode/ui/file/FileBrowserViewModel.kt+1−1 app/src/main/java/soy/iko/opencode/ui/session/SessionListViewModel.kt+1−2
app/src/main/java/soy/iko/opencode/data/network/EventStreamClient.kt+1
@@ -104,6 +104,7 @@ class EventStreamClient(
104104 val event = try {
105105 OpencodeJson.decodeFromString(BusEvent.serializer(), data)
106106 } catch (e: kotlinx.serialization.SerializationException) {
107+ Log.d("EventStream", "Skipping unparseable SSE event", e)
107108 continue
108109 }
109110 // Any successfully decoded event means the stream is live;
app/src/main/java/soy/iko/opencode/ui/chat/ChatViewModel.kt+5−6
@@ -209,24 +209,23 @@ class ChatViewModel(
209209 // would be lost forever. The persisted draft is cleared only on success.
210210 _draft.value = ""
211211 viewModelScope.launch {
212− val ok = runCatching {
212+ runCatching {
213213 conn.repository.sendPrompt(
214214 sessionId,
215215 trimmed,
216216 model = _selectedModel.value?.ref,
217217 agent = _selectedAgent.value,
218218 )
219− }.isSuccess
220− _running.value = false
221− if (!ok) {
219+ }.onFailure {
222220 _failedDraft.value = trimmed
223221 // Only restore the draft if the user hasn't typed anything new since.
224222 if (_draft.value.isBlank()) updateDraft(trimmed)
225− _error.value = container.string(R.string.error_failed_to_send)
226− } else {
223+ _error.value = container.friendlyError(it)
224+ }.onSuccess {
227225 // Send succeeded — now it's safe to persist the empty draft.
228226 container.draftStore.set(sessionId, "")
229227 }
228+ _running.value = false
230229 }
231230 return true
232231 }
app/src/main/java/soy/iko/opencode/ui/file/FileBrowserViewModel.kt+1−1
@@ -88,7 +88,7 @@ class FileBrowserViewModel(private val container: AppContainer) : ViewModel() {
8888 }
8989
9090 fun setQuery(query: String) {
91− _state.value = _state.value.copy(query = query)
91+ _state.value = _state.value.copy(query = query, error = null)
9292 searchJob?.cancel()
9393 if (query.isBlank()) {
9494 _state.value = _state.value.copy(results = emptyList(), searching = false)
app/src/main/java/soy/iko/opencode/ui/session/SessionListViewModel.kt+1−2
@@ -216,7 +216,7 @@ class SessionListViewModel(private val container: AppContainer) : ViewModel() {
216216 api.listMessages(session.id).lastOrNull()?.let { msg ->
217217 msg.parts.filterIsInstance<TextPart>().lastOrNull()?.text
218218 }
219− }.getOrNull()?.takeIf { it.isNotBlank() } ?: return@withPermit
219+ }.getOrNull()?.takeIf { it.isNotBlank() }?.take(NetworkConfig.previewTextMaxLength) ?: return@withPermit
220220 _state.update { s -> s.copy(previews = s.previews + (session.id to preview)) }
221221 }
222222 }
@@ -281,7 +281,6 @@ class SessionListViewModel(private val container: AppContainer) : ViewModel() {
281281 .onFailure {
282282 container.disconnect()
283283 _state.value = SessionListState(loading = false, error = container.friendlyError(it))
284− refresh()
285284 }
286285 }
287286 }