perf: optimize screen load times with progressive un-gating and SWR caching (#1192)

This commit is contained in:
M57 authored and GitHub committed 2026-09-18 23:25:30 +03:00
1 parent abce60ad7a
commit f5eaecbbef
55 files changed
+2494 -401

No files matched your search

@@ -35,6 +35,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.m57.hermescontrol.R
import com.m57.hermescontrol.data.local.AuthManager
import com.m57.hermescontrol.theme.LocalHermesStatusColors
import com.m57.hermescontrol.ui.common.ErrorState
import com.m57.hermescontrol.ui.common.HermesScaffold
@@ -51,9 +52,11 @@ fun GatewayScreen(
viewModel: GatewayViewModel = viewModel { GatewayViewModel() },
) {
val state by viewModel.uiState.collectAsStateWithLifecycle()
val dataScope by AuthManager.dataScopeFlow.collectAsStateWithLifecycle()
val statusColors = LocalHermesStatusColors.current
LaunchedEffect(Unit) {
LaunchedEffect(dataScope) {
viewModel.clearScopeOwnedState()
viewModel.loadStatus()
}
@@ -63,7 +66,7 @@ fun GatewayScreen(
title = { Text(stringResource(R.string.screen_gateway)) },
navigationIcon = onOpenDrawer?.let { NavIcon.Menu(it) },
isRefreshing = state.isLoading,
onRefresh = { viewModel.loadStatus() },
onRefresh = { viewModel.loadStatus(forceRefresh = true) },
) { paddingValues ->
when {
state.isLoading && state.status == null -> {
@@ -2,12 +2,14 @@ package com.m57.hermescontrol.ui.gateway
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.m57.hermescontrol.data.local.SwrCache
import com.m57.hermescontrol.data.model.StatusResponse
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 com.m57.hermescontrol.ui.common.safeLaunchSwrLoad
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -28,8 +30,19 @@ class GatewayViewModel :
private val _uiState = MutableStateFlow(GatewayUiState())
val uiState: StateFlow<GatewayUiState> = _uiState.asStateFlow()
fun loadStatus() {
safeLaunchLoad(
private val statusCache = SwrCache<String, StatusResponse>()
fun clearScopeOwnedState() {
_uiState.update { it.copy(isLoading = false, status = null, errorMessage = null) }
}
fun loadStatus(forceRefresh: Boolean = false) {
safeLaunchSwrLoad(
cache = statusCache,
forceRefresh = forceRefresh,
onCacheHit = { data ->
_uiState.update { it.copy(isLoading = false, status = data, errorMessage = null) }
},
apiCall = { safeApiCall { ApiClient.hermesApi.getStatus() } },
onStart = { _uiState.update { it.copy(isLoading = true, errorMessage = null) } },
onSuccess = { data ->
@@ -73,7 +86,7 @@ class GatewayViewModel :
toastMessage = "Gateway ${actionName}ed successfully",
)
}
loadStatus()
loadStatus(forceRefresh = true)
}
is NetworkResult.Failure -> {