perf: optimize data loading across Config, System, Profiles, and Billing tabs (#678)
* perf(model): optimize model tab load speed with two-phase fetch and loadQuick * perf: optimize data loading across Config, System, Profiles, and Billing tabs * chore: remove leftover bottom nav references and unused updatePrimaryScreens * style: fix ktlint violations in Config/Profiles/Billing ViewModels - property/argument-list wrapping for async(...) calls - multiline-expression wrapping for async blocks - remove unused import in ConfigViewModel - break long error-message string literals to stay under 120 cols --------- Co-authored-by: M57 <Hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
f7afbfae85
commit
1cca7764cc
7 files changed
+222
-172
No files matched your search
@@ -9,8 +9,9 @@ import com.m57.hermescontrol.data.remote.ApiClient
|
||||
import com.m57.hermescontrol.data.remote.NetworkResult
|
||||
import com.m57.hermescontrol.data.remote.safeApiCall
|
||||
import com.m57.hermescontrol.ui.common.ToastHost
|
||||
import com.m57.hermescontrol.ui.common.safeLaunchLoad
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
@@ -51,53 +52,55 @@ class ConfigViewModel :
|
||||
}
|
||||
|
||||
fun loadAll() {
|
||||
safeLaunchLoad(
|
||||
apiCall = {
|
||||
safeApiCall { ApiClient.hermesApi.getConfig() }
|
||||
},
|
||||
onStart = { _uiState.update { it.copy(isLoading = true, errorMessage = null) } },
|
||||
onSuccess = { configData ->
|
||||
viewModelScope.launch {
|
||||
val schemaResult =
|
||||
withContext(Dispatchers.IO) {
|
||||
safeApiCall { ApiClient.hermesApi.getConfigSchema() }
|
||||
}
|
||||
val defaultsResult =
|
||||
withContext(Dispatchers.IO) {
|
||||
safeApiCall { ApiClient.hermesApi.getConfigDefaults() }
|
||||
}
|
||||
viewModelScope.launch {
|
||||
_uiState.update { it.copy(isLoading = true, errorMessage = null) }
|
||||
try {
|
||||
coroutineScope {
|
||||
val configDeferred = async(Dispatchers.IO) { safeApiCall { ApiClient.hermesApi.getConfig() } }
|
||||
val schemaDeferred = async(Dispatchers.IO) { safeApiCall { ApiClient.hermesApi.getConfigSchema() } }
|
||||
val defaultsDeferred =
|
||||
async(Dispatchers.IO) { safeApiCall { ApiClient.hermesApi.getConfigDefaults() } }
|
||||
val rawDeferred = async(Dispatchers.IO) { safeApiCall { ApiClient.hermesApi.getRawConfig() } }
|
||||
|
||||
val schema = (schemaResult as? NetworkResult.Success)?.data
|
||||
val defaults = (defaultsResult as? NetworkResult.Success)?.data
|
||||
val rawResult =
|
||||
withContext(Dispatchers.IO) {
|
||||
safeApiCall { ApiClient.hermesApi.getRawConfig() }
|
||||
}
|
||||
val path = (rawResult as? NetworkResult.Success)?.data?.path
|
||||
val configResult = configDeferred.await()
|
||||
val schemaResult = schemaDeferred.await()
|
||||
val defaultsResult = defaultsDeferred.await()
|
||||
val rawResult = rawDeferred.await()
|
||||
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
config = configData,
|
||||
schema = schema,
|
||||
defaults = defaults,
|
||||
path = path,
|
||||
activeCategory =
|
||||
if (schema?.category_order?.isNotEmpty() == true) {
|
||||
schema.category_order.first()
|
||||
} else {
|
||||
""
|
||||
},
|
||||
)
|
||||
if (configResult is NetworkResult.Success) {
|
||||
val configData = configResult.data
|
||||
val schema = (schemaResult as? NetworkResult.Success)?.data
|
||||
val defaults = (defaultsResult as? NetworkResult.Success)?.data
|
||||
val path = (rawResult as? NetworkResult.Success)?.data?.path
|
||||
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
config = configData,
|
||||
schema = schema,
|
||||
defaults = defaults,
|
||||
path = path,
|
||||
activeCategory =
|
||||
if (schema?.category_order?.isNotEmpty() == true) {
|
||||
schema.category_order.first()
|
||||
} else {
|
||||
""
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val errorMsg = (configResult as? NetworkResult.Failure)?.error?.message ?: "Unknown error"
|
||||
_uiState.update {
|
||||
it.copy(isLoading = false, errorMessage = "Failed to load config: $errorMsg")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onError = { errorMsg ->
|
||||
} catch (e: Exception) {
|
||||
_uiState.update {
|
||||
it.copy(isLoading = false, errorMessage = "Failed to load config: $errorMsg")
|
||||
it.copy(isLoading = false, errorMessage = "Failed to load config: ${e.message}")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateField(
|
||||
|
||||
Reference in new issue
Block a user