git.iko.soy/opencode-android
on 3e723a1 help sign in
88 lines 3.2 kB history raw
1package soy.iko.opencode.ui.server
3import androidx.lifecycle.ViewModel
4import androidx.lifecycle.viewModelScope
5import soy.iko.opencode.data.model.ServerProfile
6import soy.iko.opencode.di.AppContainer
7import kotlinx.coroutines.flow.MutableStateFlow
8import kotlinx.coroutines.flow.StateFlow
9import kotlinx.coroutines.flow.asStateFlow
10import kotlinx.coroutines.flow.first
11import kotlinx.coroutines.launch
12import kotlinx.coroutines.withTimeoutOrNull
13import java.util.UUID
15data class ServerEditState(
16 val id: String? = null,
17 val label: String = "",
18 val baseUrl: String = "",
19 val username: String = "",
20 val password: String = "",
21 val loaded: Boolean = false,
22 val error: String? = null,
23) {
24 val canSave: Boolean get() = baseUrl.isNotBlank()
25 val isNew: Boolean get() = id == null
28class ServerEditViewModel(
29 private val container: AppContainer,
30 private val profileId: String?,
31) : ViewModel() {
33 private val _state = MutableStateFlow(ServerEditState(id = profileId))
34 val state: StateFlow<ServerEditState> = _state.asStateFlow()
36 init {
37 viewModelScope.launch {
38 if (profileId != null) {
39 val existing = withTimeoutOrNull(5_000) {
40 container.profileStore.profiles.first().firstOrNull { it.id == profileId }
41 }
42 if (existing != null) {
43 _state.value = ServerEditState(
44 id = existing.id,
45 label = existing.label,
46 baseUrl = existing.baseUrl,
47 username = existing.username.orEmpty(),
48 password = existing.password.orEmpty(),
49 loaded = true,
50 )
51 return@launch
52 }
53 }
54 _state.value = _state.value.copy(loaded = true)
55 }
56 }
58 fun update(transform: (ServerEditState) -> ServerEditState) {
59 _state.value = transform(_state.value)
60 }
62 fun save(onDone: () -> Unit) {
63 val s = _state.value
64 if (!s.canSave) return
65 viewModelScope.launch {
66 val result = runCatching {
67 val existingLastUsed = if (s.id != null) {
68 withTimeoutOrNull(5_000) {
69 container.profileStore.profiles.first()
70 .firstOrNull { it.id == s.id }?.lastUsed
71 } ?: 0L
72 } else 0L
73 container.profileStore.save(
74 ServerProfile(
75 id = s.id ?: UUID.randomUUID().toString(),
76 label = s.label.trim(),
77 baseUrl = s.baseUrl.trim(),
78 username = s.username.trim().takeIf { it.isNotBlank() },
79 password = s.password.trim().takeIf { it.isNotEmpty() },
80 lastUsed = existingLastUsed,
81 ),
82 )
83 }
84 result.onSuccess { onDone() }
85 .onFailure { _state.value = _state.value.copy(error = it.message ?: "Failed to save") }
86 }
87 }