Updated on 2026-08-14
This commit is contained in:
parent
b91efa6730
commit
d36d3f5427
13 changed files with 173 additions and 18 deletions
|
|
@ -5,6 +5,8 @@ import com.tangem.domain.card.repository.CardRepository
|
|||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.tap.domain.TangemSdkManager
|
||||
import com.tangem.tap.domain.card.DefaultDerivePublicKeysUseCase
|
||||
import dagger.Module
|
||||
|
|
@ -62,4 +64,10 @@ internal object CardDomainModule {
|
|||
fun provideDerivePublicKeysUseCase(tangemSdkManager: TangemSdkManager): DerivePublicKeysUseCase {
|
||||
return DefaultDerivePublicKeysUseCase(tangemSdkManager = tangemSdkManager)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideIsNeedToBackupUseCase(walletStateHolder: WalletsStateHolder): IsNeedToBackupUseCase {
|
||||
return IsNeedToBackupUseCase(walletStateHolder)
|
||||
}
|
||||
}
|
||||
|
|
@ -450,6 +450,23 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber))
|
||||
}
|
||||
|
||||
userWalletsListManager.selectedUserWalletSync?.walletId?.let {
|
||||
scope.launch {
|
||||
userWalletsListManager.update(
|
||||
userWalletId = it,
|
||||
update = { wallet ->
|
||||
wallet.copy(
|
||||
scanResponse = updateScanResponseAfterBackup(
|
||||
scanResponse = wallet.scanResponse,
|
||||
backupState = backupState,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
store.dispatchOnMain(GlobalAction.UpdateUserWalletsListManager(userWalletsListManager))
|
||||
}
|
||||
}
|
||||
|
||||
val notActivatedCardIds = gatherCardIds(backupState, card)
|
||||
.mapNotNull { if (cardActivationIsFinished(it)) null else it }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.domain.wallets.usecase
|
||||
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
/**
|
||||
* Use case that checks if wallet need backup cards
|
||||
*/
|
||||
class IsNeedToBackupUseCase(private val walletsStateHolder: WalletsStateHolder) {
|
||||
|
||||
operator fun invoke(id: UserWalletId): Flow<Boolean> {
|
||||
val userWalletsListManager = requireNotNull(walletsStateHolder.userWalletsListManager)
|
||||
|
||||
return userWalletsListManager.userWallets
|
||||
.map { wallets ->
|
||||
val wallet = wallets.firstOrNull { it.walletId == id }
|
||||
if (wallet == null) {
|
||||
false
|
||||
} else {
|
||||
wallet.scanResponse.card.backupStatus is CardDTO.BackupStatus.NoBackup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ internal object WalletPreviewData {
|
|||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onRenameClick = { _, _ -> },
|
||||
onDeleteClick = {},
|
||||
cardCount = 1,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ internal object WalletPreviewData {
|
|||
onDeleteClick = {},
|
||||
balance = "8923,05 $",
|
||||
additionalInfo = TextReference.Str("3 cards • Seed phrase"),
|
||||
cardCount = 1,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ internal sealed interface WalletCardState {
|
|||
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property cardCount number of cards in the wallet
|
||||
* @property balance wallet balance
|
||||
*/
|
||||
data class Content(
|
||||
|
|
@ -43,6 +44,7 @@ internal sealed interface WalletCardState {
|
|||
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||
val additionalInfo: TextReference,
|
||||
val cardCount: Int?,
|
||||
val balance: String,
|
||||
) : WalletCardState
|
||||
|
||||
|
|
@ -55,6 +57,7 @@ internal sealed interface WalletCardState {
|
|||
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property cardCount number of cards in the wallet
|
||||
* @property balance wallet balance
|
||||
*/
|
||||
data class HiddenContent(
|
||||
|
|
@ -65,6 +68,7 @@ internal sealed interface WalletCardState {
|
|||
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||
val additionalInfo: TextReference,
|
||||
val balance: String,
|
||||
val cardCount: Int?,
|
||||
) : WalletCardState
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.domain.tokens.error.CurrencyStatusError
|
|||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.getCardsCount
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
|
|
@ -96,6 +97,7 @@ internal class WalletSingleCurrencyLoadedBalanceConverter(
|
|||
onRenameClick = selectedWallet.onRenameClick,
|
||||
onDeleteClick = selectedWallet.onDeleteClick,
|
||||
balance = formatFiatAmount(status = status, appCurrency = appCurrencyProvider()),
|
||||
cardCount = currentWalletProvider().getCardsCount(),
|
||||
)
|
||||
}
|
||||
is CryptoCurrencyStatus.Loading -> {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ internal class WalletStateFactory(
|
|||
|
||||
private val hiddenStateConverter by lazy { HiddenStateConverter(currentStateProvider) }
|
||||
|
||||
private val walletUpdateCardCountConverter by lazy {
|
||||
WalletUpdateCardCountConverter(
|
||||
currentStateProvider,
|
||||
currentWalletProvider,
|
||||
)
|
||||
}
|
||||
|
||||
private val tokenListErrorConverter by lazy {
|
||||
TokenListErrorConverter(currentStateProvider)
|
||||
}
|
||||
|
|
@ -134,6 +141,8 @@ internal class WalletStateFactory(
|
|||
|
||||
fun getStateWithUpdatedWalletName(name: String): WalletState = walletRenameStateConverter.convert(value = name)
|
||||
|
||||
fun getStateWithUpdatedWalletCardCount(): WalletState = walletUpdateCardCountConverter.convert(Unit)
|
||||
|
||||
fun getUnlockedState(action: WalletsUpdateActionResolver.Action.UnlockWallet): WalletState {
|
||||
return walletsUnlockStateConverter.convert(value = action)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.getCardsCount
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletsListConfig
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class WalletUpdateCardCountConverter(
|
||||
private val currentStateProvider: Provider<WalletState>,
|
||||
private val currentWalletProvider: Provider<UserWallet>,
|
||||
) : Converter<Unit, WalletState> {
|
||||
|
||||
override fun convert(value: Unit): WalletState {
|
||||
return when (val state = currentStateProvider()) {
|
||||
is WalletState.ContentState -> {
|
||||
state.copySealed(
|
||||
walletsListConfig = state.walletsListConfig.refreshCardCount(),
|
||||
)
|
||||
}
|
||||
is WalletState.Initial -> state
|
||||
}
|
||||
}
|
||||
|
||||
private fun WalletsListConfig.refreshCardCount(): WalletsListConfig {
|
||||
return copy(
|
||||
wallets = wallets
|
||||
.mapIndexed { index, walletCard ->
|
||||
if (index == selectedWalletIndex) {
|
||||
when (walletCard) {
|
||||
is WalletCardState.Content -> walletCard.copy(
|
||||
additionalInfo = WalletAdditionalInfoFactory.resolve(
|
||||
wallet = currentWalletProvider(),
|
||||
),
|
||||
cardCount = currentWalletProvider().getCardsCount(),
|
||||
)
|
||||
is WalletCardState.HiddenContent -> walletCard.copy(
|
||||
additionalInfo = WalletAdditionalInfoFactory.resolve(
|
||||
wallet = currentWalletProvider(),
|
||||
),
|
||||
cardCount = currentWalletProvider().getCardsCount(),
|
||||
)
|
||||
else -> walletCard
|
||||
}
|
||||
} else {
|
||||
walletCard
|
||||
}
|
||||
}
|
||||
.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.tokens.model.TokenList.FiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.getCardsCount
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
|
|
@ -54,6 +55,7 @@ internal class FiatBalanceToWalletCardConverter(
|
|||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
),
|
||||
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = currentWalletProvider()),
|
||||
cardCount = currentWalletProvider().getCardsCount(),
|
||||
)
|
||||
} else {
|
||||
WalletCardState.Content(
|
||||
|
|
@ -68,6 +70,7 @@ internal class FiatBalanceToWalletCardConverter(
|
|||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
),
|
||||
cardCount = currentWalletProvider().getCardsCount(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ internal class WalletHiddenBalanceStateConverter {
|
|||
onRenameClick = content.onRenameClick,
|
||||
onDeleteClick = content.onDeleteClick,
|
||||
balance = content.balance,
|
||||
cardCount = content.cardCount,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -37,6 +38,7 @@ internal class WalletHiddenBalanceStateConverter {
|
|||
onRenameClick = hiddenContent.onRenameClick,
|
||||
onDeleteClick = hiddenContent.onDeleteClick,
|
||||
balance = hiddenContent.balance,
|
||||
cardCount = hiddenContent.cardCount,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import com.tangem.domain.demo.IsDemoCardUseCase
|
|||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletNotification
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -16,9 +18,10 @@ import kotlin.collections.count
|
|||
/**
|
||||
* Wallet notifications list factory
|
||||
*
|
||||
* @property isDemoCardUseCase use case that check if card is demo
|
||||
* @property isReadyToShowRateAppUseCase use case that check if card is user already rate app
|
||||
* @property wasCardScannedUseCase use case that check if card was scanned
|
||||
* @property isDemoCardUseCase use case that checks if card is demo
|
||||
* @property isReadyToShowRateAppUseCase use case that checks if card is user already rate app
|
||||
* @property wasCardScannedUseCase use case that checks if card was scanned
|
||||
* @property isNeedToBackupUseCase use case that checks if wallet need backup cards
|
||||
* @property clickIntents screen click intents
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -27,17 +30,20 @@ internal class WalletNotificationsListFactory(
|
|||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val wasCardScannedUseCase: WasCardScannedUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) {
|
||||
|
||||
fun create(
|
||||
selectedWalletId: UserWalletId,
|
||||
cardTypesResolver: CardTypesResolver,
|
||||
cryptoCurrencyList: List<CryptoCurrencyStatus>,
|
||||
): Flow<ImmutableList<WalletNotification>> {
|
||||
return combine(
|
||||
flow = wasCardScannedUseCase(cardTypesResolver.getCardId()),
|
||||
flow2 = isReadyToShowRateAppUseCase(),
|
||||
) { wasCardScanned, isReadyToShowRating ->
|
||||
flow3 = isNeedToBackupUseCase(selectedWalletId),
|
||||
) { wasCardScanned, isReadyToShowRating, isNeedToBackup ->
|
||||
buildList {
|
||||
addCriticalNotifications(cardTypesResolver)
|
||||
|
||||
|
|
@ -45,7 +51,7 @@ internal class WalletNotificationsListFactory(
|
|||
|
||||
addRateTheAppNotification(isReadyToShowRating)
|
||||
|
||||
addWarningNotifications(cardTypesResolver, cryptoCurrencyList, wasCardScanned)
|
||||
addWarningNotifications(cardTypesResolver, cryptoCurrencyList, wasCardScanned, isNeedToBackup)
|
||||
}.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
|
@ -116,12 +122,13 @@ internal class WalletNotificationsListFactory(
|
|||
cardTypesResolver: CardTypesResolver,
|
||||
cryptoCurrencyList: List<CryptoCurrencyStatus>,
|
||||
wasCardScanned: Boolean,
|
||||
isNeedToBackup: Boolean,
|
||||
) {
|
||||
addIf(
|
||||
element = WalletNotification.Warning.MissingBackup(
|
||||
onStartBackupClick = clickIntents::onBackupCardClick,
|
||||
),
|
||||
condition = !cardTypesResolver.isBackupForbidden() && !cardTypesResolver.hasBackup(),
|
||||
condition = isNeedToBackup,
|
||||
)
|
||||
|
||||
val isDemo = isDemoCardUseCase(cardId = cardTypesResolver.getCardId())
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
wasCardScannedUseCase: WasCardScannedUseCase,
|
||||
isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
isDemoCardUseCase: IsDemoCardUseCase,
|
||||
isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
// endregion Parameters
|
||||
) : ViewModel(), DefaultLifecycleObserver, WalletClickIntents {
|
||||
|
||||
|
|
@ -135,6 +136,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
wasCardScannedUseCase = wasCardScannedUseCase,
|
||||
isReadyToShowRateAppUseCase = isReadyToShowRateAppUseCase,
|
||||
isDemoCardUseCase = isDemoCardUseCase,
|
||||
isNeedToBackupUseCase = isNeedToBackupUseCase,
|
||||
clickIntents = this,
|
||||
)
|
||||
|
||||
|
|
@ -227,6 +229,9 @@ internal class WalletViewModel @Inject constructor(
|
|||
is WalletsUpdateActionResolver.Action.AddWallet -> {
|
||||
scrollAndUpdateState(action.selectedWalletIndex)
|
||||
}
|
||||
is WalletsUpdateActionResolver.Action.UpdateWalletCardCount -> {
|
||||
uiState = stateFactory.getStateWithUpdatedWalletCardCount()
|
||||
}
|
||||
is WalletsUpdateActionResolver.Action.Unknown -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -983,6 +988,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
private fun updateNotifications(index: Int, tokenList: TokenList? = null) {
|
||||
notificationsListFactory.create(
|
||||
selectedWalletId = getWallet(index).walletId,
|
||||
cardTypesResolver = getCardTypeResolver(index = index),
|
||||
cryptoCurrencyList = if (tokenList != null) {
|
||||
when (tokenList) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.common.Provider
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.getCardsCount
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletLockedState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
|
||||
|
|
@ -110,20 +111,29 @@ internal class WalletsUpdateActionResolver(
|
|||
selectedWallet: UserWallet,
|
||||
): Action {
|
||||
val selectedWalletName = selectedWallet.name
|
||||
val previousWalletState = state.getPrevSelectedWallet()
|
||||
return when {
|
||||
previousWalletState.title != selectedWalletName -> {
|
||||
Action.UpdateWalletName(selectedWalletName)
|
||||
}
|
||||
|
||||
if (state.getPrevSelectedWallet().title != selectedWalletName) {
|
||||
return Action.UpdateWalletName(selectedWalletName)
|
||||
state is WalletLockedState && !selectedWallet.isLocked -> {
|
||||
Action.UnlockWallet(
|
||||
selectedWalletIndex = wallets.indexOfWallet(id = selectedWallet.walletId),
|
||||
selectedWallet = selectedWallet,
|
||||
unlockedWallets = wallets.filterNot(UserWallet::isLocked),
|
||||
)
|
||||
}
|
||||
|
||||
previousWalletState is WalletCardState.Content &&
|
||||
previousWalletState.cardCount != selectedWallet.getCardsCount() ||
|
||||
previousWalletState is WalletCardState.HiddenContent &&
|
||||
previousWalletState.cardCount != selectedWallet.getCardsCount() -> {
|
||||
Action.UpdateWalletCardCount
|
||||
}
|
||||
|
||||
else -> Action.Unknown
|
||||
}
|
||||
|
||||
if (state is WalletLockedState && !selectedWallet.isLocked) {
|
||||
return Action.UnlockWallet(
|
||||
selectedWalletIndex = wallets.indexOfWallet(id = selectedWallet.walletId),
|
||||
selectedWallet = selectedWallet,
|
||||
unlockedWallets = wallets.filterNot(UserWallet::isLocked),
|
||||
)
|
||||
}
|
||||
|
||||
return Action.Unknown
|
||||
}
|
||||
|
||||
private fun WalletState.ContentState.getPrevSelectedWallet(): WalletCardState {
|
||||
|
|
@ -163,6 +173,8 @@ internal class WalletsUpdateActionResolver(
|
|||
|
||||
data class AddWallet(val selectedWalletIndex: Int) : Action()
|
||||
|
||||
object UpdateWalletCardCount : Action()
|
||||
|
||||
object Unknown : Action()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue