Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-14 17:17:49 +04:00
parent b139e9ff97
commit 32887fb26d
4 changed files with 43 additions and 28 deletions

View file

@ -146,4 +146,10 @@ sealed class Lce<out E : Any, out C : Any> {
ifContent = { predicate(it) },
ifError = { false },
)
fun onError(action: (error: E) -> Unit): Lce<E, C> {
if (this is Error) action(this.error)
return this
}
}

View file

@ -30,7 +30,7 @@ import com.tangem.utils.extensions.addOrReplace
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
@Suppress("LongParameterList")
@Suppress("LongParameterList", "LargeClass")
class CachedCurrenciesStatusesOperations(
private val currenciesRepository: CurrenciesRepository,
private val quotesRepository: QuotesRepository,
@ -67,8 +67,6 @@ class CachedCurrenciesStatusesOperations(
): LceFlow<TokenListError, List<CryptoCurrencyStatus>> = lceFlow {
val prevStatuses = MutableStateFlow(value = emptyList<CryptoCurrencyStatus>())
val isUpdating = MutableStateFlow(value = true)
val nonEmptyCurrencies = currenciesFlow.mapNotNull { it.getOrNull() }.firstOrNull()?.toNonEmptyListOrNull()
if (!isFetchingStarted(userWalletId) && nonEmptyCurrencies != null) {
@ -78,7 +76,7 @@ class CachedCurrenciesStatusesOperations(
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
fetchComponents(userWalletId, networks, currenciesIds, nonEmptyCurrencies)
}
.invokeOnCompletion { isUpdating.value = false }
.invokeOnCompletion { setFetchFinished(userWalletId) }
}
currenciesFlow.flatMapLatest { maybeCurrencies ->
@ -137,14 +135,18 @@ class CachedCurrenciesStatusesOperations(
fetchComponents(userWalletId, networks, currenciesIds, currencies)
}
.invokeOnCompletion { isUpdating.value = false }
.invokeOnCompletion { setFetchFinished(userWalletId) }
}
combine(
flow = getQuotes(currenciesIds),
flow2 = getNetworksStatuses(userWalletId, networks),
flow3 = getYieldBalances(userWalletId, currencies),
flow4 = isUpdating,
flow4 = fetchingState.map {
val state = it[userWalletId] ?: return@map false
!state.isFinished()
},
transform = ::createCurrenciesStatuses,
)
.distinctUntilChanged()
@ -362,20 +364,35 @@ class CachedCurrenciesStatusesOperations(
}
private fun isFetchingStarted(userWalletId: UserWalletId): Boolean {
return fetchingState.value[userWalletId] ?: false
return fetchingState.value[userWalletId]?.let { it.isStarted() || it.isFinished() } ?: false
}
private fun setFetchStarted(userWalletId: UserWalletId) {
fetchingState.update {
it.toMutableMap().apply {
put(key = userWalletId, value = true)
put(key = userWalletId, value = FetchingState.STARTED)
}
}
}
private fun setFetchFinished(userWalletId: UserWalletId) {
fetchingState.update {
it.toMutableMap().apply {
put(key = userWalletId, value = FetchingState.FINISHED)
}
}
}
enum class FetchingState {
STARTED, FINISHED;
fun isStarted() = this == STARTED
fun isFinished() = this == FINISHED
}
companion object {
internal const val RETRY_DELAY = 2000L
private val fetchingState = MutableStateFlow(value = emptyMap<UserWalletId, Boolean>())
private val fetchingState = MutableStateFlow(value = emptyMap<UserWalletId, FetchingState>())
}
}

View file

@ -32,8 +32,6 @@ internal class OrganizeTokensComponent(
override fun Content(modifier: Modifier) {
val uiState by model.uiState.collectAsStateWithLifecycle()
OrganizeTokensScreen(
state = uiState,
)
OrganizeTokensScreen(state = uiState)
}
}

View file

@ -10,11 +10,12 @@ import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.core.utils.getOrElse
import com.tangem.domain.core.lce.Lce
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
import com.tangem.domain.tokens.GetTokenListUseCase
import com.tangem.domain.tokens.ToggleTokenListGroupingUseCase
import com.tangem.domain.tokens.ToggleTokenListSortingUseCase
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.model.TokenList
import com.tangem.feature.wallet.child.organizetokens.OrganizeTokensComponent
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensIntents
@ -36,13 +37,13 @@ import javax.inject.Inject
@ModelScoped
internal class OrganizeTokensModel @Inject constructor(
paramsContainer: ParamsContainer,
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
override val dispatchers: CoroutineDispatcherProvider,
private val getTokenListUseCase: GetTokenListUseCase,
private val toggleTokenListGroupingUseCase: ToggleTokenListGroupingUseCase,
private val toggleTokenListSortingUseCase: ToggleTokenListSortingUseCase,
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
private val analyticsEventsHandler: AnalyticsEventHandler,
) : Model(), OrganizeTokensIntents {
@ -167,21 +168,14 @@ internal class OrganizeTokensModel @Inject constructor(
}
private suspend fun getTokenList(): TokenList? {
val tokenList = getTokenListUseCase.launch(userWalletId)
.transform { maybeTokenList ->
val tokenList = maybeTokenList.getOrElse(
ifLoading = { return@transform },
ifError = { error ->
stateHolder.updateStateWithError(error)
val maybeTokenList = getTokenListUseCase.launch(userWalletId)
.filterNot(Lce<TokenListError, TokenList>::isLoading)
.firstOrNull()
?: return null
return@transform
},
)
emit(tokenList)
}
return tokenList.firstOrNull()
return maybeTokenList
.onError(stateHolder::updateStateWithError)
.getOrNull(isPartialContentAccepted = false)
}
private fun bootstrapDragAndDropUpdates() {