diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/TotalBalance.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/TotalBalance.kt index fdabcb075d..5d63e8b816 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/TotalBalance.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/TotalBalance.kt @@ -1,16 +1,11 @@ package com.tangem.tap.features.wallet.models import com.tangem.tap.common.entities.FiatCurrency +import com.tangem.tap.features.wallet.redux.ProgressState import java.math.BigDecimal data class TotalBalance( - val state: State, + val state: ProgressState, val fiatAmount: BigDecimal, val fiatCurrency: FiatCurrency, -) { - enum class State { - Loading, - SomeTokensFailed, - Success, - } -} \ No newline at end of file +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 6ca5098dd8..769d28a8cd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -1,7 +1,11 @@ package com.tangem.tap.features.wallet.redux import android.content.Context -import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.Token +import com.tangem.blockchain.common.Wallet +import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType import com.tangem.common.card.Card import com.tangem.tap.common.entities.FiatCurrency @@ -11,8 +15,8 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.wallet.R -import org.rekotlin.Action import java.math.BigDecimal +import org.rekotlin.Action sealed class WalletAction : Action { @@ -21,6 +25,7 @@ sealed class WalletAction : Action { data class SetIfTestnetCard(val isTestnet: Boolean) : WalletAction() object LoadData : WalletAction() { + object Refresh : WalletAction() data class Failure(val error: TapError) : WalletAction() } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index e8cecdb127..e8b093c5ab 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -33,7 +33,7 @@ import com.tangem.tap.features.wallet.models.hasPendingTransactions import com.tangem.tap.features.wallet.models.hasSendableAmounts import com.tangem.tap.features.wallet.models.isSendableAmount import com.tangem.tap.features.wallet.redux.reducers.calculateTotalFiatAmount -import com.tangem.tap.features.wallet.redux.reducers.findTotalBalanceState +import com.tangem.tap.features.wallet.redux.reducers.findProgressState import com.tangem.tap.features.wallet.ui.BalanceStatus import com.tangem.tap.features.wallet.ui.BalanceWidgetData import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager @@ -203,6 +203,7 @@ data class WalletState( fun updateWalletStore(walletStore: WalletStore?): WalletState { return copy(wallets = replaceWalletInWallets(walletStore)) .updateTotalBalance() + .updateProgressState() } private fun updateWalletStores(walletStores: List): WalletState { @@ -220,6 +221,7 @@ data class WalletState( } return copy(wallets = updatedWallets + walletStoresMutable) .updateTotalBalance() + .updateProgressState() } fun removeWallet(walletData: WalletData?): WalletState { @@ -282,9 +284,9 @@ data class WalletState( } private fun updateTotalBalance(): WalletState { - return if (wallets.isNotEmpty()) { + return if (this.wallets.isNotEmpty()) { val globalState = store.state.globalState - val walletsData = wallets + val walletsData = this.wallets .flatMap(WalletStore::walletsData) .filterNot { wallet -> wallet.currency.isCustomCurrency( @@ -297,7 +299,7 @@ data class WalletState( this.copy( totalBalance = TotalBalance( - state = walletsData.findTotalBalanceState(), + state = walletsData.findProgressState(), fiatAmount = walletsData.calculateTotalFiatAmount(), fiatCurrency = globalState.appCurrency ) @@ -306,6 +308,19 @@ data class WalletState( totalBalance = null ) } + + private fun updateProgressState(): WalletState { + return if (this.wallets.isNotEmpty()) { + val walletsData = this.wallets + .flatMap(WalletStore::walletsData) + val newProgressState = walletsData.findProgressState() + + this.copy( + state = walletsData.findProgressState(), + error = this.error.takeIf { newProgressState == ProgressState.Error } + ) + } else this + } } sealed interface WalletDialog : StateDialog { @@ -318,7 +333,7 @@ sealed interface WalletDialog : StateDialog { ) : WalletDialog } -enum class ProgressState : WidgetState { Loading, Done, Error } +enum class ProgressState : WidgetState { Loading, Refreshing, Done, Error } enum class ErrorType { NoInternetConnection } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index a4862b21b8..e4f7b6f659 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -15,7 +15,12 @@ import com.tangem.domain.common.extensions.withMainContext import com.tangem.operations.attestation.Attestation import com.tangem.operations.attestation.OnlineCardVerifier import com.tangem.tap.common.analytics.Analytics -import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.extensions.copyToClipboard +import com.tangem.tap.common.extensions.dispatchDebugErrorNotification +import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.extensions.onCardScanned +import com.tangem.tap.common.extensions.shareText +import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen @@ -28,12 +33,17 @@ import com.tangem.tap.features.send.redux.PrepareSendScreen import com.tangem.tap.features.wallet.models.PendingTransactionType import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.getSendableAmounts -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.Currency +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.features.wallet.redux.WalletState +import com.tangem.tap.features.wallet.redux.WalletStore import com.tangem.tap.network.NetworkStateChanged import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager +import java.math.BigDecimal import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch @@ -41,7 +51,6 @@ import org.rekotlin.Action import org.rekotlin.DispatchFunction import org.rekotlin.Middleware import timber.log.Timber -import java.math.BigDecimal class WalletMiddleware { private val tradeCryptoMiddleware = TradeCryptoMiddleware() @@ -198,7 +207,8 @@ class WalletMiddleware { store.dispatchOnMain(WalletAction.Warnings.CheckIfNeeded) } } - is WalletAction.LoadData -> { + is WalletAction.LoadData, + is WalletAction.LoadData.Refresh -> { scope.launch { val scanNoteResponse = globalState.scanResponse ?: return@launch if (walletState.walletsData.isNotEmpty()) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index 28a7675472..41f297af89 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -11,7 +11,6 @@ import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.filterByToken import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.removeUnknownTransactions -import com.tangem.tap.features.wallet.models.toPendingTransactions import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletData @@ -41,8 +40,8 @@ class MultiWalletReducer { } val walletData = WalletData( currencyData = BalanceWidgetData( - BalanceStatus.Loading, - blockchain.blockchain.fullName, + status = BalanceStatus.Loading, + currency = blockchain.blockchain.fullName, currencySymbol = blockchain.blockchain.currency, token = cardToken ), @@ -77,8 +76,8 @@ class MultiWalletReducer { val walletData = WalletData( currencyData = BalanceWidgetData( - BalanceStatus.Loading, - action.blockchain.blockchain.fullName, + status = BalanceStatus.Loading, + currency = action.blockchain.blockchain.fullName, currencySymbol = action.blockchain.blockchain.currency, ), walletAddresses = createAddressList(wallet), @@ -184,7 +183,7 @@ fun Token.toWallet(state: WalletState, blockchain: BlockchainNetwork): WalletDat return WalletData( currencyData = BalanceWidgetData( - BalanceStatus.Loading, + status = BalanceStatus.Loading, currency = this.name, currencySymbol = this.symbol ), diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt index 442cbf46ec..ffbe3cce5d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/OnWalletLoadedReducer.kt @@ -12,7 +12,6 @@ import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.filterByToken import com.tangem.tap.features.wallet.models.getPendingTransactions import com.tangem.tap.features.wallet.models.removeUnknownTransactions -import com.tangem.tap.features.wallet.models.toPendingTransactions import com.tangem.tap.features.wallet.redux.Currency import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.TradeCryptoState @@ -61,7 +60,8 @@ class OnWalletLoadedReducer { val fiatAmount = walletData.fiatRate?.let { coinAmountValue?.toFiatValue(it) } val newWalletData = walletData.copy( currencyData = walletData.currencyData.copy( - status = balanceStatus, currency = wallet.blockchain.fullName, + status = balanceStatus, + currency = wallet.blockchain.fullName, currencySymbol = wallet.blockchain.currency, blockchainAmount = coinAmountValue, amount = coinAmountValue, @@ -110,17 +110,8 @@ class OnWalletLoadedReducer { val newWallets = tokens + newWalletData val wallets = walletState.replaceSomeWallets((newWallets)) - val state = if (wallets.any { it.currencyData.status == BalanceStatus.Loading }) { - ProgressState.Loading - } else { - ProgressState.Done - } return walletState .updateWalletsData(wallets) - .copy( - state = state, - error = null - ) } private fun onSingleWalletLoaded(wallet: Wallet, walletState: WalletState): WalletState { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt index 054f2626d4..c0ead34d52 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TotalBalanceOperations.kt @@ -1,14 +1,14 @@ package com.tangem.tap.features.wallet.redux.reducers -import com.tangem.tap.features.wallet.models.TotalBalance +import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletData import com.tangem.tap.features.wallet.ui.BalanceStatus import java.math.BigDecimal -fun List.findTotalBalanceState(): TotalBalance.State { +fun List.findProgressState(): ProgressState { return this - .mapToTotalBalanceState() - .reduce(TotalBalance.State::or) + .mapToProgressState() + .reduce(ProgressState::or) } fun List.calculateTotalFiatAmount(): BigDecimal { @@ -17,34 +17,43 @@ fun List.calculateTotalFiatAmount(): BigDecimal { .reduce(BigDecimal::plus) } -private fun List.mapToTotalBalanceState(): List { +private fun List.mapToProgressState(): List { return this.map { when (it.currencyData.status) { + BalanceStatus.Refreshing -> ProgressState.Refreshing BalanceStatus.VerifiedOnline, BalanceStatus.SameCurrencyTransactionInProgress, BalanceStatus.TransactionInProgress, - BalanceStatus.NoAccount -> TotalBalance.State.Success + BalanceStatus.NoAccount -> ProgressState.Done BalanceStatus.Unreachable, BalanceStatus.EmptyCard, - BalanceStatus.UnknownBlockchain -> TotalBalance.State.SomeTokensFailed + BalanceStatus.UnknownBlockchain -> ProgressState.Error BalanceStatus.Loading, - null -> TotalBalance.State.Loading + null -> ProgressState.Loading } } } -private infix fun TotalBalance.State.or(newState: TotalBalance.State): TotalBalance.State { +private infix fun ProgressState.or(newState: ProgressState): ProgressState { return when (this) { - TotalBalance.State.Loading -> when (newState) { - TotalBalance.State.Loading, - TotalBalance.State.SomeTokensFailed, - TotalBalance.State.Success -> this + ProgressState.Loading -> when (newState) { + ProgressState.Loading, + ProgressState.Refreshing, + ProgressState.Error, + ProgressState.Done -> this } - TotalBalance.State.Success, - TotalBalance.State.SomeTokensFailed -> when (newState) { - TotalBalance.State.Loading, - TotalBalance.State.SomeTokensFailed -> newState - TotalBalance.State.Success -> this + ProgressState.Done, + ProgressState.Error -> when (newState) { + ProgressState.Loading, + ProgressState.Refreshing, + ProgressState.Error -> newState + ProgressState.Done -> this + } + ProgressState.Refreshing -> when (newState) { + ProgressState.Loading -> this + ProgressState.Refreshing, + ProgressState.Error, + ProgressState.Done -> newState } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt index 11ea7236c0..426fb74e2b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt @@ -25,7 +25,6 @@ import com.tangem.tap.features.wallet.redux.TradeCryptoState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletAddresses import com.tangem.tap.features.wallet.redux.WalletData -import com.tangem.tap.features.wallet.redux.WalletDialog import com.tangem.tap.features.wallet.redux.WalletMainButton import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletStore @@ -135,14 +134,25 @@ private fun internalReduce(action: Action, state: AppState): WalletState { error = null, ) } + is WalletAction.LoadData.Refresh -> { + newState = newState.copy( + state = ProgressState.Refreshing, + error = null, + ) + } is WalletAction.LoadWallet -> { + val balanceStatus = if (newState.state == ProgressState.Refreshing) { + BalanceStatus.Refreshing + } else { + BalanceStatus.Loading + } if (action.blockchain == null) { val wallets = newState.wallets.map { it.copy( walletsData = it.walletsData.map { walletData -> walletData.copy( currencyData = walletData.currencyData.copy( - status = BalanceStatus.Loading, + status = balanceStatus, currency = walletData.currencyData.currency, currencySymbol = walletData.currencyData.currencySymbol, ), @@ -169,7 +179,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState { .map { wallet -> wallet.copy( currencyData = wallet.currencyData.copy( - status = BalanceStatus.Loading, + status = balanceStatus, currency = wallet.currencyData.currency, currencySymbol = wallet.currencyData.currencySymbol, ), diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt index 6f666e8601..2be2f19145 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/BalanceWidget.kt @@ -13,6 +13,7 @@ enum class BalanceStatus { SameCurrencyTransactionInProgress, Unreachable, Loading, + Refreshing, NoAccount, EmptyCard, UnknownBlockchain diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index 24473568ef..6a113fb7a8 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -135,15 +135,14 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber) { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index a19f17d5a3..b7604317f3 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -64,6 +64,9 @@ class WalletAdapter fun bind(wallet: WalletData) = with(binding) { val status = wallet.currencyData.status + // Skip changes when on refreshing status + if (status == BalanceStatus.Refreshing) return@with + val isCustomCurrency = wallet.currency.isCustomCurrency( derivationStyle = store.state.globalState .scanResponse @@ -83,6 +86,7 @@ class WalletAdapter BalanceStatus.EmptyCard, BalanceStatus.UnknownBlockchain, BalanceStatus.Loading, + BalanceStatus.Refreshing, null -> null } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt index b777d3ef00..e228e737bd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt @@ -14,6 +14,7 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.currenciesRepository import com.tangem.tap.features.tokens.redux.TokensAction import com.tangem.tap.features.wallet.models.TotalBalance +import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.ui.BalanceStatus @@ -125,16 +126,19 @@ class MultiWalletView : WalletView { ) = with(binding.lCardTotalBalance) { root.isVisible = totalBalance != null if (totalBalance != null) { - if (totalBalance.state == TotalBalance.State.Loading) { + // Skip changes when on refreshing state + if (totalBalance.state == ProgressState.Refreshing) return@with + + if (totalBalance.state == ProgressState.Loading) { veilBalance.veil() } else { veilBalance.unVeil() } tvProcessing.animateVisibility( - show = totalBalance.state == TotalBalance.State.SomeTokensFailed + show = totalBalance.state == ProgressState.Error ) - tvBalance.text = if (totalBalance.state == TotalBalance.State.SomeTokensFailed) "—" + tvBalance.text = if (totalBalance.state == ProgressState.Error) "—" else totalBalance.fiatAmount.formatAmountAsSpannedString( currencySymbol = totalBalance.fiatCurrency.symbol )