Updated on 2026-08-14
This commit is contained in:
parent
86139d5f45
commit
480f66e8b2
4 changed files with 70 additions and 41 deletions
|
|
@ -61,6 +61,10 @@ internal class DefaultWalletCurrenciesManager(
|
|||
userWallet: UserWallet,
|
||||
currenciesToAdd: List<Currency>,
|
||||
): CompletionResult<Unit> = withContext(Dispatchers.Default) {
|
||||
if (currenciesToAdd.isEmpty()) {
|
||||
return@withContext CompletionResult.Success(Unit)
|
||||
}
|
||||
|
||||
val card = userWallet.scanResponse.card
|
||||
val currenciesToAddWithMissingBlockchains = currenciesToAdd.addMissingBlockchainsIfNeeded(card)
|
||||
listeners.forEach { it.willCurrenciesAdd(userWallet, currenciesToAddWithMissingBlockchains) }
|
||||
|
|
@ -86,6 +90,10 @@ internal class DefaultWalletCurrenciesManager(
|
|||
userWallet: UserWallet,
|
||||
currenciesToRemove: List<Currency>,
|
||||
): CompletionResult<Unit> = withContext(Dispatchers.Default) {
|
||||
if (currenciesToRemove.isEmpty()) {
|
||||
return@withContext CompletionResult.Success(Unit)
|
||||
}
|
||||
|
||||
listeners.forEach { it.willCurrenciesRemove(userWallet, currenciesToRemove) }
|
||||
val card = userWallet.scanResponse.card
|
||||
val remainingCurrencies = getSavedCurrencies(userWallet.walletId)
|
||||
|
|
|
|||
|
|
@ -42,8 +42,10 @@ import com.tangem.tap.store
|
|||
import com.tangem.tap.tangemSdkManager
|
||||
import com.tangem.tap.totalFiatBalanceCalculator
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import com.tangem.utils.coroutines.ifActive
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.rekotlin.Action
|
||||
|
|
@ -70,6 +72,12 @@ class WalletMiddleware {
|
|||
private val networkConnectionManager: NetworkConnectionManager
|
||||
get() = store.state.daggerGraphState.get(DaggerGraphState::networkConnectionManager)
|
||||
|
||||
private var updateWalletStoresJob: Job? = null
|
||||
set(value) {
|
||||
field?.cancel()
|
||||
field = value
|
||||
}
|
||||
|
||||
val walletMiddleware: Middleware<AppState> = { _, state ->
|
||||
{ next ->
|
||||
{ action ->
|
||||
|
|
@ -176,11 +184,14 @@ class WalletMiddleware {
|
|||
}
|
||||
is WalletAction.UserWalletChanged -> Unit
|
||||
is WalletAction.WalletStoresChanged -> {
|
||||
store.state.globalState.topUpController?.walletStoresChanged(action.walletStores)
|
||||
updateWalletStores(action.walletStores, walletState)
|
||||
fetchTotalFiatBalance(action.walletStores)
|
||||
findMissedDerivations(action.walletStores)
|
||||
tryToShowAppRatingWarning(action.walletStores)
|
||||
// Cancel update job when new wallet stores received
|
||||
updateWalletStoresJob = scope.launch(Dispatchers.Default) {
|
||||
ifActive { updateWalletStores(action.walletStores, walletState) }
|
||||
ifActive { fetchTotalFiatBalance(action.walletStores) }
|
||||
ifActive { findMissedDerivations(action.walletStores) }
|
||||
ifActive { tryToShowAppRatingWarning(action.walletStores) }
|
||||
ifActive { store.state.globalState.topUpController?.walletStoresChanged(action.walletStores) }
|
||||
}
|
||||
}
|
||||
is WalletAction.TotalFiatBalanceChanged -> Unit
|
||||
is WalletAction.PopBackToInitialScreen -> {
|
||||
|
|
@ -197,55 +208,47 @@ class WalletMiddleware {
|
|||
}
|
||||
|
||||
private fun updateWalletStores(walletsStores: List<WalletStoreModel>, state: WalletState) {
|
||||
scope.launch(Dispatchers.Default) {
|
||||
val reduxWalletStores = walletsStores.mapToReduxModels()
|
||||
if (!state.isMultiwalletAllowed) {
|
||||
findSelectedCurrency(
|
||||
walletsStores = reduxWalletStores,
|
||||
currentSelectedCurrency = null,
|
||||
isMultiWalletAllowed = false,
|
||||
)?.let {
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.SetSingleWalletCurrency(it))
|
||||
}
|
||||
val reduxWalletStores = walletsStores.mapToReduxModels()
|
||||
if (!state.isMultiwalletAllowed) {
|
||||
findSelectedCurrency(
|
||||
walletsStores = reduxWalletStores,
|
||||
currentSelectedCurrency = null,
|
||||
isMultiWalletAllowed = false,
|
||||
)?.let {
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.SetSingleWalletCurrency(it))
|
||||
}
|
||||
store.dispatchOnMain(
|
||||
WalletAction.WalletStoresChanged.UpdateWalletStores(
|
||||
reduxWalletStores = reduxWalletStores,
|
||||
),
|
||||
)
|
||||
}
|
||||
store.dispatchOnMain(
|
||||
WalletAction.WalletStoresChanged.UpdateWalletStores(
|
||||
reduxWalletStores = reduxWalletStores,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun fetchTotalFiatBalance(walletStores: List<WalletStoreModel>) {
|
||||
scope.launch(Dispatchers.Default) {
|
||||
val totalFiatBalance = totalFiatBalanceCalculator.calculateOrNull(walletStores)?.mapToReduxModel()
|
||||
private suspend fun fetchTotalFiatBalance(walletStores: List<WalletStoreModel>) {
|
||||
val totalFiatBalance = totalFiatBalanceCalculator.calculateOrNull(walletStores)?.mapToReduxModel()
|
||||
|
||||
if (totalFiatBalance != null) {
|
||||
store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance))
|
||||
}
|
||||
if (totalFiatBalance != null) {
|
||||
store.dispatchOnMain(WalletAction.TotalFiatBalanceChanged(totalFiatBalance))
|
||||
}
|
||||
}
|
||||
|
||||
private fun findMissedDerivations(wallStores: List<WalletStoreModel>) {
|
||||
scope.launch(Dispatchers.Default) {
|
||||
val missedDerivations = wallStores
|
||||
.filter { store ->
|
||||
store.walletsData.any { it.status is WalletDataModel.MissedDerivation }
|
||||
}
|
||||
.map(WalletStoreModel::blockchainNetwork)
|
||||
val missedDerivations = wallStores
|
||||
.filter { store ->
|
||||
store.walletsData.any { it.status is WalletDataModel.MissedDerivation }
|
||||
}
|
||||
.map(WalletStoreModel::blockchainNetwork)
|
||||
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(missedDerivations))
|
||||
}
|
||||
store.dispatchOnMain(WalletAction.MultiWallet.AddMissingDerivations(missedDerivations))
|
||||
}
|
||||
|
||||
private fun tryToShowAppRatingWarning(walletStores: List<WalletStoreModel>) {
|
||||
scope.launch(Dispatchers.Default) {
|
||||
warningsMiddleware.tryToShowAppRatingWarning(
|
||||
hasNonZeroWallets = walletStores
|
||||
.flatMap { it.walletsData }
|
||||
.any { it.status.amount.isGreaterThan(BigDecimal.ZERO) },
|
||||
)
|
||||
}
|
||||
warningsMiddleware.tryToShowAppRatingWarning(
|
||||
hasNonZeroWallets = walletStores
|
||||
.flatMap { it.walletsData }
|
||||
.any { it.status.amount.isGreaterThan(BigDecimal.ZERO) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun showSaveWalletIfNeeded() {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ import com.tangem.tap.store
|
|||
import com.tangem.tap.walletStoresManager
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -98,12 +100,16 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
private fun bootstrapSelectedWalletStoresChanges(manager: UserWalletsListManager) {
|
||||
observeWalletStoresUpdatesJob = manager.selectedUserWallet
|
||||
.map { it.walletId }
|
||||
.flatMapLatest { selectedUserWalletId ->
|
||||
walletStoresManager.get(selectedUserWalletId)
|
||||
}
|
||||
.debounce { walletStores ->
|
||||
if (walletStores.isNotEmpty()) WALLET_STORES_DEBOUNCE_TIMEOUT else 0
|
||||
}
|
||||
.onEach { walletStores ->
|
||||
store.dispatch(WalletAction.WalletStoresChanged(walletStores))
|
||||
}
|
||||
|
|
@ -126,4 +132,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
.select { it.globalState.userWalletsListManager }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val WALLET_STORES_DEBOUNCE_TIMEOUT = 100L
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@ package com.tangem.utils.coroutines
|
|||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
|
@ -13,6 +15,12 @@ suspend fun <R> runCatching(dispatcher: CoroutineDispatcher, block: suspend () -
|
|||
}
|
||||
}
|
||||
|
||||
suspend inline fun ifActive(crossinline block: suspend () -> Unit) = coroutineScope {
|
||||
if (isActive) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
class Debouncer {
|
||||
|
||||
private var debounceJob: Job? = null
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue