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
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,
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?,
33 private val _state = MutableStateFlow(ServerEditState(id = profileId))
34 val state: StateFlow<ServerEditState> = _state.asStateFlow()
37 viewModelScope.launch {
38 if (profileId != null) {
39 val existing = withTimeoutOrNull(5_000) {
40 container.profileStore.profiles.first().firstOrNull { it.id == profileId }
42 if (existing != null) {
43 _state.value = ServerEditState(
45 label = existing.label,
46 baseUrl = existing.baseUrl,
47 username = existing.username.orEmpty(),
48 password = existing.password.orEmpty(),
54 _state.value = _state.value.copy(loaded = true)
58 fun update(transform: (ServerEditState) -> ServerEditState) {
59 _state.value = transform(_state.value)
62 fun save(onDone: () -> Unit) {
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
73 container.profileStore.save(
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,
84 result.onSuccess { onDone() }
85 .onFailure { _state.value = _state.value.copy(error = it.message ?: "Failed to save") }
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list