From af3edb1d301f7c6da57f6d809af67d047e75231d Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Sun, 29 Sep 2024 15:52:12 +0800 Subject: [PATCH] Refactor(ToolViewScreenViewModel): Save tool detail in cache --- .../ui/view/ToolViewScreenViewModel.kt | 75 ++++++++++++------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/view/ToolViewScreenViewModel.kt b/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/view/ToolViewScreenViewModel.kt index 9da58c4..d245b50 100644 --- a/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/view/ToolViewScreenViewModel.kt +++ b/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/view/ToolViewScreenViewModel.kt @@ -5,6 +5,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine @@ -13,6 +15,7 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn import timber.log.Timber import top.fatweb.oxygen.toolbox.model.Result +import top.fatweb.oxygen.toolbox.model.tool.ToolEntity import top.fatweb.oxygen.toolbox.navigation.ToolViewArgs import top.fatweb.oxygen.toolbox.repository.tool.StoreRepository import top.fatweb.oxygen.toolbox.repository.tool.ToolRepository @@ -35,6 +38,8 @@ class ToolViewScreenViewModel @Inject constructor( private val toolId = toolViewArgs.toolId private val preview = toolViewArgs.preview + private val storeDetailCache = MutableStateFlow?>(null) + val toolViewUiState: StateFlow = toolViewUiState( savedStateHandle = savedStateHandle, @@ -42,7 +47,8 @@ class ToolViewScreenViewModel @Inject constructor( toolId = toolId, preview = preview, storeRepository = storeRepository, - toolRepository = toolRepository + toolRepository = toolRepository, + storeDetailCache = storeDetailCache ) .stateIn( scope = viewModelScope, @@ -57,7 +63,8 @@ private fun toolViewUiState( toolId: String, preview: Boolean, storeRepository: StoreRepository, - toolRepository: ToolRepository + toolRepository: ToolRepository, + storeDetailCache: MutableStateFlow?> ): Flow { val toolViewTemplate = toolRepository.toolViewTemplate val entityFlow = @@ -67,32 +74,14 @@ private fun toolViewUiState( combine(entityFlow, toolViewTemplate, ::Pair).collect { (entityFlow, toolViewTemplate) -> if (entityFlow == null) { savedStateHandle[IS_PREVIEW] = true - storeRepository.detail(username, toolId).collect { - emit( - when (it) { - is Result.Success -> { - val dist = it.data.dist!! - val base = it.data.base!! - ToolViewUiState.Success( - it.data.name, - processHtml( - toolViewTemplate = toolViewTemplate, - distBase64 = dist, - baseBase64 = base - ) - ) - } - - is Result.Loading -> ToolViewUiState.Loading - is Result.Error -> { - Timber.e("Can not load tool", it.exception) - - ToolViewUiState.Error - } - - is Result.Fail -> ToolViewUiState.Error - } - ) + val cachedDetail = storeDetailCache.value + if (cachedDetail != null) { + emitResult(result = cachedDetail, toolViewTemplate = toolViewTemplate) + } else { + storeRepository.detail(username, toolId).collect { result -> + storeDetailCache.value = result + emitResult(result = result, toolViewTemplate = toolViewTemplate) + } } } else { savedStateHandle[IS_PREVIEW] = false @@ -111,6 +100,36 @@ private fun toolViewUiState( } } +private suspend fun FlowCollector.emitResult( + result: Result, + toolViewTemplate: String +) { + emit( + when (result) { + is Result.Success -> { + val dist = result.data.dist!! + val base = result.data.base!! + ToolViewUiState.Success( + result.data.name, + processHtml( + toolViewTemplate = toolViewTemplate, + distBase64 = dist, + baseBase64 = base + ) + ) + } + + is Result.Loading -> ToolViewUiState.Loading + is Result.Error -> { + Timber.e("Can not load tool", result.exception) + ToolViewUiState.Error + } + + is Result.Fail -> ToolViewUiState.Error + } + ) +} + sealed interface ToolViewUiState { data class Success( val toolName: String,