git.iko.soy/opencode-android
on 0bc1eda help sign in
48 lines 1.9 kB history raw
1package soy.iko.opencode.ui.file
3import androidx.lifecycle.ViewModel
4import androidx.lifecycle.viewModelScope
5import soy.iko.opencode.data.model.FileContent
6import soy.iko.opencode.di.AppContainer
7import soy.iko.opencode.R
8import kotlinx.coroutines.ExperimentalCoroutinesApi
9import kotlinx.coroutines.flow.MutableStateFlow
10import kotlinx.coroutines.flow.StateFlow
11import kotlinx.coroutines.flow.asStateFlow
12import kotlinx.coroutines.flow.collectLatest
13import kotlinx.coroutines.launch
15data class FileViewState(
16 val loading: Boolean = true,
17 val content: FileContent? = null,
18 val error: String? = null,
21@OptIn(ExperimentalCoroutinesApi::class)
22class FileViewModel(
23 private val container: AppContainer,
24 private val path: String,
25) : ViewModel() {
27 private val _state = MutableStateFlow(FileViewState())
28 val state: StateFlow<FileViewState> = _state.asStateFlow()
30 init {
31 // Observe the active connection so the file loads (or reloads) when a connection
32 // becomes available — including when the view opens during a reconnect window
33 // where activeConnection.value was momentarily null. collectLatest cancels the
34 // in-flight load if the connection is replaced mid-read.
35 viewModelScope.launch {
36 container.activeConnection.collectLatest { conn ->
37 if (conn == null) {
38 _state.value = FileViewState(loading = false, error = container.string(R.string.not_connected))
39 return@collectLatest
40 }
41 _state.value = FileViewState(loading = true)
42 runCatching { conn.api.readFile(path) }
43 .onSuccess { _state.value = FileViewState(loading = false, content = it) }
44 .onFailure { _state.value = FileViewState(loading = false, error = container.friendlyError(it)) }
45 }
46 }
47 }