Updated on 2026-08-14

This commit is contained in:
Tangem 2022-12-10 16:42:01 +03:00
parent 87c43ab20f
commit 27b0d0f461
6 changed files with 92 additions and 46 deletions

View file

@ -5,10 +5,30 @@ import com.tangem.tap.domain.model.WalletStoreModel
import java.math.BigDecimal
interface TotalFiatBalanceCalculator {
/**
* Calculate total fiat balance for list of [WalletStoreModel]
* @param prevAmount Previous amount, used in [TotalFiatBalance.Refreshing]
* @param walletStores List of [WalletStoreModel] to calculate fiat amount
* @param initial Initial [TotalFiatBalance] state, used when list of [WalletStoreModel] is empty
* @return [TotalFiatBalance] with state found with the [WalletStoreModel] list
* */
suspend fun calculate(
prevAmount: BigDecimal,
prevAmount: BigDecimal?,
walletStores: List<WalletStoreModel>,
initial: TotalFiatBalance,
): TotalFiatBalance
/**
* Same as [TotalFiatBalanceCalculator.calculate] but returns null if list of [WalletStoreModel] is empty
* @param prevAmount Previous amount, used in [TotalFiatBalance.Refreshing]
* @param walletStores List of [WalletStoreModel] to calculate fiat amount
* @return [TotalFiatBalance] with state found with the [WalletStoreModel] list
* */
suspend fun calculateOrNull(
prevAmount: BigDecimal?,
walletStores: List<WalletStoreModel>,
): TotalFiatBalance?
companion object
}

View file

@ -11,11 +11,19 @@ import java.math.BigDecimal
internal class DefaultTotalFiatBalanceCalculator : TotalFiatBalanceCalculator {
override suspend fun calculate(
prevAmount: BigDecimal,
prevAmount: BigDecimal?,
walletStores: List<WalletStoreModel>,
initial: TotalFiatBalance,
): TotalFiatBalance {
return calculateOrNull(prevAmount, walletStores) ?: initial
}
override suspend fun calculateOrNull(
prevAmount: BigDecimal?,
walletStores: List<WalletStoreModel>,
): TotalFiatBalance? {
return if (walletStores.isEmpty()) {
TotalFiatBalance.Loading
null
} else {
withContext(Dispatchers.Default) {
val walletsData = walletStores
@ -25,7 +33,9 @@ internal class DefaultTotalFiatBalanceCalculator : TotalFiatBalanceCalculator {
when (walletsData.findStatus()) {
TotalFiatBalanceStatus.Loading -> TotalFiatBalance.Loading
TotalFiatBalanceStatus.Refreshing -> TotalFiatBalance.Refreshing(prevAmount)
TotalFiatBalanceStatus.Refreshing -> TotalFiatBalance.Refreshing(
amount = prevAmount ?: BigDecimal.ZERO,
)
TotalFiatBalanceStatus.Error -> TotalFiatBalance.Error(calculateAmount())
TotalFiatBalanceStatus.Loaded -> TotalFiatBalance.Loaded(calculateAmount())
}

View file

@ -294,28 +294,29 @@ class WalletMiddleware {
}
is WalletAction.UserWalletChanged -> Unit
is WalletAction.WalletStoresChanged -> {
scope.launch(Dispatchers.Default) {
fetchTotalFiatBalance(action.walletStores, walletState)
findMissedDerivations(action.walletStores)
tryToShowAppRatingWarning(action.walletStores)
}
fetchTotalFiatBalance(action.walletStores, walletState)
findMissedDerivations(action.walletStores)
tryToShowAppRatingWarning(action.walletStores)
}
is WalletAction.TotalFiatBalanceChanged -> Unit
}
}
private fun fetchTotalFiatBalance(walletStores: List<WalletStoreModel>, state: WalletState) {
scope.launch {
val totalFiatBalance = totalFiatBalanceCalculator.calculate(
prevAmount = state.totalBalance?.fiatAmount ?: BigDecimal.ZERO,
scope.launch(Dispatchers.Default) {
val totalFiatBalance = totalFiatBalanceCalculator.calculateOrNull(
prevAmount = state.totalBalance?.fiatAmount,
walletStores = walletStores,
)
store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance))
if (totalFiatBalance != null) {
store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance))
}
}
}
private fun findMissedDerivations(wallStores: List<WalletStoreModel>) {
scope.launch {
scope.launch(Dispatchers.Default) {
val missedDerivations = wallStores
.filter { store ->
store.walletsData.any { it.status is WalletDataModel.MissedDerivation }
@ -327,11 +328,13 @@ class WalletMiddleware {
}
private fun tryToShowAppRatingWarning(walletStores: List<WalletStoreModel>) {
warningsMiddleware.tryToShowAppRatingWarning(
hasNonZeroWallets = walletStores
.flatMap { it.walletsData }
.any { it.status.amount.isGreaterThan(BigDecimal.ZERO) },
)
scope.launch(Dispatchers.Default) {
warningsMiddleware.tryToShowAppRatingWarning(
hasNonZeroWallets = walletStores
.flatMap { it.walletsData }
.any { it.status.amount.isGreaterThan(BigDecimal.ZERO) },
)
}
}
private fun showSaveWalletIfNeeded() {

View file

@ -9,7 +9,11 @@ import com.tangem.domain.common.TapWorkarounds.isTestCard
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.MainScreen
import com.tangem.tap.common.analytics.events.Portfolio
import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.extensions.animateVisibility
import com.tangem.tap.common.extensions.formatAmountAsSpannedString
import com.tangem.tap.common.extensions.getQuantityString
import com.tangem.tap.common.extensions.hide
import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.domain.tokens.CurrenciesRepository
@ -43,6 +47,7 @@ class MultiWalletView : WalletView() {
lAddress.root.hide()
rowButtons.hide()
lSingleWalletBalance.root.hide()
lCardTotalBalance.root.show()
rvMultiwallet.show()
btnAddToken.show()
setupWalletCardNumber(binding)
@ -134,21 +139,20 @@ class MultiWalletView : WalletView() {
totalBalance: TotalBalance?,
progressState: ProgressState,
) = with(binding.lCardTotalBalance) {
root.isVisible = totalBalance != null
if (totalBalance != null) {
// Skip changes when on refreshing state
if (totalBalance.state == ProgressState.Refreshing ||
progressState == ProgressState.Refreshing
) return@with
if (totalBalance == null) {
veilBalance.animateVisibility(show = true)
root.isVisible = progressState == ProgressState.Loading
} else {
root.isVisible = true
if (totalBalance.state == ProgressState.Loading) {
veilBalance.veil()
} else {
veilBalance.unVeil()
// Skip changes when on refreshing state
if (totalBalance.state == ProgressState.Refreshing || progressState == ProgressState.Refreshing) {
return@with
}
tvProcessing.animateVisibility(
show = totalBalance.state == ProgressState.Error,
)
veilBalance.animateVisibility(show = totalBalance.state == ProgressState.Loading)
tvBalance.animateVisibility(show = totalBalance.state != ProgressState.Loading)
tvProcessing.animateVisibility(show = totalBalance.state == ProgressState.Error)
tvBalance.text = totalBalance.fiatAmount.formatAmountAsSpannedString(
currencySymbol = totalBalance.fiatCurrency.symbol,

View file

@ -12,6 +12,7 @@ import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.domain.model.TotalFiatBalance
import com.tangem.tap.domain.model.UserWallet
import com.tangem.tap.domain.model.WalletStoreModel
import com.tangem.tap.domain.model.builders.UserWalletBuilder
@ -26,6 +27,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import org.rekotlin.Middleware
import timber.log.Timber
import java.math.BigDecimal
internal class WalletSelectorMiddleware {
val middleware: Middleware<AppState> = { _, appStateProvider ->
@ -221,7 +223,6 @@ internal class WalletSelectorMiddleware {
is UserWalletModel.Type.MultiCurrency -> type.copy(
tokensCount = walletStores.flatMap { it.walletsData }.size,
)
is UserWalletModel.Type.SingleCurrency -> type.copy(
blockchainName = walletStores
.firstOrNull()
@ -233,6 +234,7 @@ internal class WalletSelectorMiddleware {
fiatBalance = totalFiatBalanceCalculator.calculate(
prevAmount = fiatBalance.amount,
walletStores = walletStores,
initial = TotalFiatBalance.Loaded(BigDecimal.ZERO),
),
)
}