diff --git a/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt b/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt index 4ad10ad879..3106bd1527 100644 --- a/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt +++ b/app/src/main/java/com/tangem/tap/domain/model/UserWallet.kt @@ -13,6 +13,7 @@ import com.tangem.domain.common.util.UserWalletId * TODO: Replace with [com.tangem.domain.common.CardDTO] * @property cardId ID of user's wallet primary card * @property hasAccessCode Indicates if the user's wallet primary card has access code + * @property isLocked Indicates if this primary card has no currency wallets * @property isSaved Indicates if this user wallet is saved * */ data class UserWallet( @@ -28,5 +29,8 @@ data class UserWallet( val hasAccessCode: Boolean get() = scanResponse.card.isAccessCodeSet + val isLocked: Boolean + get() = scanResponse.card.wallets.isEmpty() + internal var isSaved: Boolean = true } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt index a13cd492d0..62f961e418 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManager.kt @@ -62,10 +62,22 @@ internal class BiometricUserWalletsListManager( override suspend fun unlockWithCard(userWallet: UserWallet): CompletionResult { state.update { prevState -> - userWallet.isSaved = false + // If the previous state contains a saved user wallet with the same ID, it is also saved + userWallet.isSaved = prevState.wallets.any { + it.walletId == userWallet.walletId && it.isSaved + } + + val newEncryptionKeys = prevState.encryptionKeys + .plus(UserWalletEncryptionKey(userWallet)) + .distinctBy { it.walletId } + val newUserWallets = prevState.wallets + .plus(userWallet) + .distinctBy { it.walletId } + prevState.copy( - encryptionKeys = listOf(UserWalletEncryptionKey(userWallet)), - wallets = listOf(userWallet), + encryptionKeys = newEncryptionKeys, + wallets = newUserWallets, + selectedWalletId = userWallet.walletId, ) } @@ -73,8 +85,7 @@ internal class BiometricUserWalletsListManager( .map { state.update { prevState -> prevState.copy( - selectedWalletId = userWallet.walletId, - isLocked = prevState.wallets.size != 1, + isLocked = prevState.wallets.any { it.isLocked }, ) } } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/UserWalletModel.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/UserWalletModel.kt index e3a5a613ef..1417914782 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/UserWalletModel.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/UserWalletModel.kt @@ -8,6 +8,7 @@ data class UserWalletModel( val artworkUrl: String, val type: Type, val fiatBalance: TotalFiatBalance, + val isLocked: Boolean, ) { sealed interface Type { data class SingleCurrency( diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorAction.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorAction.kt index d18cf44dec..957661126f 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorAction.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorAction.kt @@ -37,6 +37,10 @@ internal sealed interface WalletSelectorAction : Action { val walletId: String, ) : WalletSelectorAction + data class UnlockWalletWithCard( + val walletId: String, + ) : WalletSelectorAction + data class RenameWallet( val walletId: String, val newName: String, @@ -56,5 +60,6 @@ internal sealed interface WalletSelectorAction : Action { ) : WalletSelectorAction data class HandleError(val error: TangemError) : WalletSelectorAction + object CloseError : WalletSelectorAction } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index 6fcf6665c2..dd4c4ff88b 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -61,6 +61,9 @@ internal class WalletSelectorMiddleware { is WalletSelectorAction.SelectWallet -> { selectWallet(action.walletId) } + is WalletSelectorAction.UnlockWalletWithCard -> { + unlockWalletWithCard(action.walletId) + } is WalletSelectorAction.RemoveWallets -> { removeWallets(action.walletIdsToRemove, state) } @@ -155,6 +158,40 @@ internal class WalletSelectorMiddleware { } } + private fun unlockWalletWithCard(id: String) { + scope.launch { + userWalletsListManager.get(UserWalletId(id)) + .flatMap { userWallet -> + updateUserWalletWithScannedCard(userWallet) + } + .flatMap { updatedUserWallet -> + unlockUserWallet(updatedUserWallet) + } + .doOnFailure { error -> + store.dispatchOnMain(WalletSelectorAction.HandleError(error)) + } + } + } + + private suspend fun updateUserWalletWithScannedCard(userWallet: UserWallet): CompletionResult { + return tangemSdkManager.scanCard(userWallet.cardId) + .map { scannedCard -> + userWallet.copy( + scanResponse = userWallet.scanResponse.copy( + card = scannedCard, + ), + ) + } + } + + private suspend fun unlockUserWallet(userWallet: UserWallet): CompletionResult { + return userWalletsListManager.unlockWithCard(userWallet) + .doOnSuccess { + store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet)) + store.onUserWalletSelected(userWallet) + } + } + private fun removeWallets(walletIdsToRemove: List, state: WalletSelectorState) { Analytics.send(MyWallets.Button.DeleteWalletTapped) diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt index 565f81b165..959c45c8d9 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorReducer.kt @@ -56,6 +56,7 @@ internal object WalletSelectorReducer { ) is WalletSelectorAction.WalletStoresChanged, is WalletSelectorAction.SelectWallet, + is WalletSelectorAction.UnlockWalletWithCard, is WalletSelectorAction.RemoveWallets, is WalletSelectorAction.RenameWallet, -> state @@ -70,6 +71,7 @@ internal object WalletSelectorReducer { it.copy( name = userWallet.name, artworkUrl = userWallet.artworkUrl, + isLocked = userWallet.isLocked, type = userWallet.getType(prevType = it.type), ) } @@ -80,6 +82,7 @@ internal object WalletSelectorReducer { artworkUrl = artworkUrl, type = getType(), fiatBalance = TotalFiatBalance.Loading, + isLocked = isLocked, ) } } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt index 34ce8d3ef9..6694b8b663 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/Mapper.kt @@ -60,6 +60,7 @@ private fun List.toUiModels( name = name, imageUrl = artworkUrl, balance = balance, + isLocked = isLocked, cardsInWallet = type.cardsInWallet, tokensCount = type.tokensCount, ) @@ -68,6 +69,7 @@ private fun List.toUiModels( name = name, imageUrl = artworkUrl, balance = balance, + isLocked = isLocked, tokenName = type.blockchainName ?: "—", ) } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt index ab2608b497..a7eaa3c4f4 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt @@ -37,7 +37,9 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber Unit + isLocked -> { + store.dispatch(WalletSelectorAction.UnlockWalletWithCard(walletId)) + } editingWalletsIds.isNotEmpty() && !editingWalletsIds.contains(walletId) -> { editWallet(walletId) } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/MockData.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/MockData.kt index 383ed51f5d..2fab91adc1 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/MockData.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/MockData.kt @@ -14,6 +14,7 @@ internal object MockData { ), name = "Wallet", imageUrl = "https://app.tangem.com/cards/card_default.png", + isLocked = false, tokensCount = 12, cardsInWallet = 3, ) @@ -26,6 +27,7 @@ internal object MockData { ), name = "Wallet", imageUrl = "https://app.tangem.com/cards/card_default.png", + isLocked = false, tokenName = "Ethereum", ) diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt index 5e972b5dfc..6c57a43f00 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WallectSelectorScreenContent.kt @@ -72,7 +72,6 @@ internal fun WalletSelectorScreenContent( singleCurrencyWallets = state.singleCurrencyWallets, selectedWalletId = state.selectedWalletId, checkedWalletIds = state.editingWalletsIds, - isLocked = state.isLocked, onWalletClick = onWalletClick, onWalletLongClick = onWalletLongClick, ) @@ -141,7 +140,6 @@ private fun WalletsList( singleCurrencyWallets: List, selectedWalletId: String?, checkedWalletIds: List, - isLocked: Boolean, onWalletClick: (walletId: String) -> Unit, onWalletLongClick: (walletId: String) -> Unit, ) { @@ -166,7 +164,6 @@ private fun WalletsList( wallet = wallet, isSelected = wallet.id == selectedWalletId, isChecked = wallet.id in checkedWalletIds, - isLocked = isLocked && wallet.id != selectedWalletId, ) } } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt index ada0168d08..8ad4d7a2fc 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/components/WalletItem.kt @@ -39,7 +39,6 @@ internal fun WalletItem( wallet: UserWalletItem, isSelected: Boolean, isChecked: Boolean, - isLocked: Boolean, ) { Row( modifier = modifier, @@ -59,7 +58,7 @@ internal fun WalletItem( SpacerW6() TokensInfo( modifier = Modifier.weight(weight = .4f), - isLocked = isLocked, + isLocked = wallet.isLocked, balance = wallet.balance, tokensCount = (wallet as? MultiCurrencyUserWalletItem)?.tokensCount, ) diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt index cadbde80db..c546cd131e 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/model/UserWalletItem.kt @@ -1,15 +1,14 @@ package com.tangem.tap.features.walletSelector.ui.model -import androidx.compose.runtime.Immutable import com.tangem.tap.features.details.ui.cardsettings.TextReference import com.tangem.wallet.R -@Immutable internal sealed interface UserWalletItem { val id: String val name: String val imageUrl: String val balance: Balance + val isLocked: Boolean val headerText: TextReference get() = when (this) { @@ -17,7 +16,6 @@ internal sealed interface UserWalletItem { is SingleCurrencyUserWalletItem -> TextReference.Res(R.string.user_wallet_list_single_header) } - @Immutable data class Balance( val amount: String, val isLoading: Boolean, @@ -29,6 +27,7 @@ internal data class MultiCurrencyUserWalletItem( override val name: String, override val imageUrl: String, override val balance: UserWalletItem.Balance, + override val isLocked: Boolean, val tokensCount: Int, val cardsInWallet: Int, ) : UserWalletItem @@ -38,5 +37,6 @@ internal data class SingleCurrencyUserWalletItem( override val name: String, override val imageUrl: String, override val balance: UserWalletItem.Balance, + override val isLocked: Boolean, val tokenName: String, ) : UserWalletItem \ No newline at end of file