Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-02 14:57:55 +03:00
parent 683525570c
commit c9be7fa5c5
5 changed files with 86 additions and 50 deletions

View file

@ -14,7 +14,6 @@ object RoutingTransitionAnimationFactory {
@Suppress("MagicNumber") @Suppress("MagicNumber")
fun create(appRoute: AppRoute): StackAnimator { fun create(appRoute: AppRoute): StackAnimator {
return when (appRoute) { return when (appRoute) {
is AppRoute.Onboarding,
is AppRoute.Welcome, is AppRoute.Welcome,
is AppRoute.Home, is AppRoute.Home,
-> fade(tween(400)).plus(scale(tween(400))) -> fade(tween(400)).plus(scale(tween(400)))

View file

@ -465,6 +465,7 @@ internal class WalletModel @Inject constructor(
when (action) { when (action) {
is WalletsUpdateActionResolver.Action.InitializeWallets -> initializeWallets(action) is WalletsUpdateActionResolver.Action.InitializeWallets -> initializeWallets(action)
is WalletsUpdateActionResolver.Action.ReinitializeWallet -> reinitializeWallet(action) is WalletsUpdateActionResolver.Action.ReinitializeWallet -> reinitializeWallet(action)
is WalletsUpdateActionResolver.Action.ReinitializeWallets -> reinitializeWallets(action)
is WalletsUpdateActionResolver.Action.AddWallet -> addWallet(action) is WalletsUpdateActionResolver.Action.AddWallet -> addWallet(action)
is WalletsUpdateActionResolver.Action.DeleteWallet -> deleteWallet(action) is WalletsUpdateActionResolver.Action.DeleteWallet -> deleteWallet(action)
is WalletsUpdateActionResolver.Action.UnlockWallet -> unlockWallet(action) is WalletsUpdateActionResolver.Action.UnlockWallet -> unlockWallet(action)
@ -569,6 +570,32 @@ internal class WalletModel @Inject constructor(
) )
} }
private fun reinitializeWallets(action: WalletsUpdateActionResolver.Action.ReinitializeWallets) {
action.wallets.forEach { userWallet ->
walletScreenContentLoader.cancel(userWallet.walletId)
tokenListStore.remove(userWallet.walletId)
walletScreenContentLoader.load(
userWallet = userWallet,
clickIntents = clickIntents,
coroutineScope = modelScope,
)
modelScope.launch(dispatchers.main) {
fetchWalletContent(userWallet = userWallet)
}
stateHolder.update(
ReinitializeWalletTransformer(
prevWalletId = userWallet.walletId,
newUserWallet = userWallet,
clickIntents = clickIntents,
walletImageResolver = walletImageResolver,
),
)
}
}
private suspend fun addWallet(action: WalletsUpdateActionResolver.Action.AddWallet) { private suspend fun addWallet(action: WalletsUpdateActionResolver.Action.AddWallet) {
if (accountsFeatureToggles.isFeatureEnabled) { if (accountsFeatureToggles.isFeatureEnabled) {
fetchWalletContent(userWallet = action.selectedWallet) fetchWalletContent(userWallet = action.selectedWallet)

View file

@ -64,8 +64,11 @@ internal class WalletsUpdateActionResolver @Inject constructor(
selectedWallet: UserWallet, selectedWallet: UserWallet,
): Action { ): Action {
return when { return when {
isHotWalletUpgraded(state, wallets) -> { isAnyHotWalletUpgraded(state, wallets) -> {
getHotWalletsUpgradedAction(state, wallets) getHotWalletsUpgradedAction(state, wallets, selectedWallet)
}
isAnyHotWalletBackedUpChange(state, wallets) -> {
getHotWalletsBackedUpAction(state, wallets)
} }
isWalletsCountChanged(state, wallets) -> { isWalletsCountChanged(state, wallets) -> {
getChangeWalletsListAction(state, wallets, selectedWallet) getChangeWalletsListAction(state, wallets, selectedWallet)
@ -79,31 +82,35 @@ internal class WalletsUpdateActionResolver @Inject constructor(
isAnyWalletNameChanged(state, wallets) -> { isAnyWalletNameChanged(state, wallets) -> {
getRenameWalletsAction(state, wallets) getRenameWalletsAction(state, wallets)
} }
isAnyHotWalletBackedUpChange(state, wallets) -> { isAnyWalletUnlocked(state, wallets) -> {
getHotWalletsBackedUpAction(state, wallets) Action.UnlockWallet(
selectedWallet = selectedWallet,
unlockedWallets = wallets.filterNot(UserWallet::isLocked),
)
} }
else -> getUpdateSelectedWalletAction(state, wallets, selectedWallet) isSelectedWalletCardsCountChanged(state, selectedWallet) -> {
Action.UpdateWalletCardCount(selectedWallet)
}
else -> Action.Unknown
} }
} }
private fun isAnyHotWalletBackedUpChange(state: WalletScreenState, wallets: List<UserWallet>): Boolean { private fun isAnyHotWalletBackedUpChange(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
val incompleteActivationWalletIds = state.incompleteActivationWalletIds() val incompleteActivationWalletIds = state.incompleteActivationWalletIds()
val walletsToUpdate = wallets.filter { return wallets.any {
it is UserWallet.Hot && it.backedUp == incompleteActivationWalletIds.contains(it.walletId) it is UserWallet.Hot && it.backedUp && incompleteActivationWalletIds.contains(it.walletId)
} }
return walletsToUpdate.isNotEmpty()
} }
private fun isHotWalletUpgraded(state: WalletScreenState, wallets: List<UserWallet>): Boolean { private fun isAnyHotWalletUpgraded(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
val previousWallet = state return state.wallets.any { walletState ->
.wallets when (walletState) {
.getOrNull(state.selectedWalletIndex) is WalletState.MultiCurrency -> {
return when (previousWallet) { val wallet = wallets.firstOrNull { it.walletId == walletState.walletCardState.id }
is WalletState.MultiCurrency -> { walletState.type == WalletState.MultiCurrency.WalletType.Hot && wallet is UserWallet.Cold
val wallet = wallets.firstOrNull { it.walletId == previousWallet.walletCardState.id } }
previousWallet.type == WalletState.MultiCurrency.WalletType.Hot && wallet is UserWallet.Cold else -> false
} }
else -> false
} }
} }
@ -189,9 +196,15 @@ internal class WalletsUpdateActionResolver @Inject constructor(
private fun getHotWalletsUpgradedAction( private fun getHotWalletsUpgradedAction(
state: WalletScreenState, state: WalletScreenState,
wallets: List<UserWallet>, wallets: List<UserWallet>,
): Action.ReloadWallets { selectedWallet: UserWallet,
val walletsToUpdate = wallets.filter { it.walletId == state.getPrevSelectedWallet().id } ): Action.ReinitializeWallets {
return Action.ReloadWallets(walletsToUpdate) val walletsToUpdate = wallets.filter { wallet ->
val previousState = state.wallets.firstOrNull { it.walletCardState.id == wallet.walletId }
?: return@filter false
wallet is UserWallet.Cold && previousState is WalletState.MultiCurrency &&
previousState.type == WalletState.MultiCurrency.WalletType.Hot
}
return Action.ReinitializeWallets(selectedWallet, walletsToUpdate)
} }
private fun getRenameWalletsAction(state: WalletScreenState, wallets: List<UserWallet>): Action.RenameWallets { private fun getRenameWalletsAction(state: WalletScreenState, wallets: List<UserWallet>): Action.RenameWallets {
@ -205,29 +218,14 @@ internal class WalletsUpdateActionResolver @Inject constructor(
) )
} }
private fun getUpdateSelectedWalletAction( private fun isAnyWalletUnlocked(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
state: WalletScreenState, return state.wallets.any { walletState ->
wallets: List<UserWallet>, val wallet = wallets.firstOrNull { it.walletId == walletState.walletCardState.id } ?: return@any false
selectedWallet: UserWallet, !wallet.isLocked &&
): Action { (walletState is WalletState.MultiCurrency.Locked || walletState is WalletState.SingleCurrency.Locked)
return when {
isSelectedWalletUnlocked(state, selectedWallet) -> {
Action.UnlockWallet(
selectedWallet = selectedWallet,
unlockedWallets = wallets.filterNot(UserWallet::isLocked),
)
}
isSelectedWalletCardsCountChanged(state, selectedWallet) -> {
Action.UpdateWalletCardCount(selectedWallet)
}
else -> Action.Unknown
} }
} }
private fun isSelectedWalletUnlocked(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
return state.isSelectedWalletLocked() && !selectedWallet.isLocked
}
private fun isSelectedWalletCardsCountChanged(state: WalletScreenState, selectedWallet: UserWallet): Boolean { private fun isSelectedWalletCardsCountChanged(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
if (selectedWallet !is UserWallet.Cold) return false if (selectedWallet !is UserWallet.Cold) return false
val prevSelectedWallet = state.getPrevSelectedWallet() val prevSelectedWallet = state.getPrevSelectedWallet()
@ -235,12 +233,6 @@ internal class WalletsUpdateActionResolver @Inject constructor(
prevSelectedWallet.cardCount != selectedWallet.getCardsCount() prevSelectedWallet.cardCount != selectedWallet.getCardsCount()
} }
private fun WalletScreenState.isSelectedWalletLocked(): Boolean {
val selectedWalletState = wallets.getOrNull(selectedWalletIndex) ?: error("Selected wallet is not found")
return selectedWalletState is WalletState.MultiCurrency.Locked ||
selectedWalletState is WalletState.SingleCurrency.Locked
}
private fun WalletScreenState.getPrevSelectedWallet(): WalletCardState { private fun WalletScreenState.getPrevSelectedWallet(): WalletCardState {
return wallets return wallets
.map(WalletState::walletCardState) .map(WalletState::walletCardState)
@ -249,9 +241,12 @@ internal class WalletsUpdateActionResolver @Inject constructor(
} }
private fun WalletScreenState.incompleteActivationWalletIds(): List<UserWalletId> { private fun WalletScreenState.incompleteActivationWalletIds(): List<UserWalletId> {
return wallets.mapNotNull { return wallets.mapNotNull { wallet ->
if (it.warnings.any { it is WalletNotification.FinishWalletActivation }) { if (wallet.warnings.any { it is WalletNotification.FinishWalletActivation } ||
it.walletCardState.id wallet.walletCardState is WalletState.MultiCurrency &&
wallet.walletCardState.additionalInfo?.isHotBackedUp == false
) {
wallet.walletCardState.id
} else { } else {
null null
} }
@ -306,6 +301,19 @@ internal class WalletsUpdateActionResolver @Inject constructor(
} }
} }
/**
* Reinitialize wallets
*/
data class ReinitializeWallets(
val selectedWallet: UserWallet,
val wallets: List<UserWallet>,
) : Action() {
override fun toString(): String {
return "ReinitializeWallets(wallets = ${wallets.joinToString { it.walletId.toString() }}"
}
}
/** /**
* Rename wallets * Rename wallets
* *

View file

@ -50,6 +50,7 @@ internal object WalletAdditionalInfoFactory {
backedUp.not() -> DIVIDER + TextReference.Res(R.string.hw_backup_no_backup) backedUp.not() -> DIVIDER + TextReference.Res(R.string.hw_backup_no_backup)
else -> TextReference.Str("") else -> TextReference.Str("")
}, },
isHotBackedUp = backedUp,
) )
} }

View file

@ -7,4 +7,5 @@ import com.tangem.core.ui.extensions.TextReference
data class WalletAdditionalInfo( data class WalletAdditionalInfo(
val hideable: Boolean, val hideable: Boolean,
val content: TextReference, val content: TextReference,
val isHotBackedUp: Boolean = false,
) )