git.iko.soy/parseable-android
on e7bbc3d help sign in
99 lines 3.6 kB history raw
1package com.parseable.android.ui.screens.settings
3import androidx.lifecycle.ViewModel
4import androidx.lifecycle.viewModelScope
5import com.parseable.android.data.model.AboutInfo
6import com.parseable.android.data.model.ApiResult
7import com.parseable.android.data.repository.ParseableRepository
8import com.parseable.android.data.repository.SettingsRepository
9import dagger.hilt.android.lifecycle.HiltViewModel
10import kotlinx.coroutines.CancellationException
11import kotlinx.coroutines.async
12import kotlinx.coroutines.coroutineScope
13import kotlinx.coroutines.flow.MutableStateFlow
14import kotlinx.coroutines.flow.StateFlow
15import kotlinx.coroutines.flow.asStateFlow
16import kotlinx.coroutines.flow.first
17import kotlinx.coroutines.flow.update
18import kotlinx.coroutines.launch
19import kotlinx.serialization.json.jsonPrimitive
20import javax.inject.Inject
22data class SettingsState(
23 val serverUrl: String = "",
24 val username: String = "",
25 val useTls: Boolean = true,
26 val aboutInfo: AboutInfo? = null,
27 val users: List<String> = emptyList(),
28 val isLoading: Boolean = false,
29 val error: String? = null,
32@HiltViewModel
33class SettingsViewModel @Inject constructor(
34 private val settingsRepository: SettingsRepository,
35 private val repository: ParseableRepository,
36) : ViewModel() {
38 private val _state = MutableStateFlow(SettingsState())
39 val state: StateFlow<SettingsState> = _state.asStateFlow()
41 init {
42 load()
43 }
45 fun load() {
46 viewModelScope.launch {
47 _state.update { it.copy(isLoading = true, error = null) }
49 val config = settingsRepository.serverConfig.first()
51 // Show server info immediately
52 _state.update {
53 it.copy(
54 serverUrl = config?.serverUrl ?: it.serverUrl,
55 username = config?.username ?: it.username,
56 useTls = config?.useTls ?: it.useTls,
57 )
58 }
60 try {
61 val (aboutResult, usersResult) = coroutineScope {
62 val aboutDeferred = async { repository.getAbout() }
63 val usersDeferred = async { repository.listUsers() }
64 aboutDeferred.await() to usersDeferred.await()
65 }
67 val userNames = (usersResult as? ApiResult.Success)?.data?.mapNotNull { obj ->
68 try {
69 obj["id"]?.jsonPrimitive?.content
70 ?: obj["username"]?.jsonPrimitive?.content
71 } catch (_: IllegalStateException) {
72 null
73 }
74 } ?: emptyList()
76 val errors = listOfNotNull(
77 (aboutResult as? ApiResult.Error)?.userMessage,
78 (usersResult as? ApiResult.Error)?.userMessage,
79 ).distinct().joinToString("\n").ifEmpty { null }
81 _state.update {
82 it.copy(
83 aboutInfo = (aboutResult as? ApiResult.Success)?.data,
84 users = userNames,
85 isLoading = false,
86 error = errors,
87 )
88 }
89 } catch (e: CancellationException) {
90 _state.update { it.copy(isLoading = false) }
91 throw e
92 } catch (e: Exception) {
93 _state.update {
94 it.copy(isLoading = false, error = e.message ?: "Failed to load settings")
95 }
96 }
97 }
98 }