Updated on 2026-08-14
This commit is contained in:
parent
411a591509
commit
94a4486443
28 changed files with 393 additions and 178 deletions
|
|
@ -10,6 +10,7 @@ import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
|
|
@ -35,6 +36,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
|
|
@ -58,7 +60,7 @@ internal class WalletModel @Inject constructor(
|
|||
private val walletScreenContentLoader: WalletScreenContentLoader,
|
||||
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
private val getWalletsUseCase: GetWalletsUseCase,
|
||||
private val shouldShowSaveWalletScreenUseCase: ShouldShowSaveWalletScreenUseCase,
|
||||
private val shouldShowAskBiometryUseCase: ShouldShowAskBiometryUseCase,
|
||||
private val shouldShowMarketsTooltipUseCase: ShouldShowMarketsTooltipUseCase,
|
||||
private val setWalletFirstTimeUsageUseCase: SetWalletFirstTimeUsageUseCase,
|
||||
private val canUseBiometryUseCase: CanUseBiometryUseCase,
|
||||
|
|
@ -80,6 +82,8 @@ internal class WalletModel @Inject constructor(
|
|||
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
|
||||
private val shouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase,
|
||||
private val getIsHuaweiDeviceWithoutGoogleServicesUseCase: GetIsHuaweiDeviceWithoutGoogleServicesUseCase,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
) : Model() {
|
||||
|
|
@ -137,7 +141,7 @@ internal class WalletModel @Inject constructor(
|
|||
modelScope.launch(dispatchers.main) {
|
||||
withContext(dispatchers.io) { delay(timeMillis = 1_800) }
|
||||
|
||||
if (isShowSaveWalletScreenEnabled()) {
|
||||
if (shouldShowAskBiometryBottomSheet()) {
|
||||
innerWalletRouter.dialogNavigation.activate(
|
||||
configuration = WalletDialogConfig.AskForBiometry,
|
||||
)
|
||||
|
|
@ -159,8 +163,15 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun isShowSaveWalletScreenEnabled(): Boolean {
|
||||
return innerWalletRouter.isWalletLastScreen() && shouldShowSaveWalletScreenUseCase() && canUseBiometryUseCase()
|
||||
private suspend fun shouldShowAskBiometryBottomSheet(): Boolean {
|
||||
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
userWalletsListRepository.userWalletsSync().any { it is UserWallet.Cold } &&
|
||||
innerWalletRouter.isWalletLastScreen() &&
|
||||
shouldShowAskBiometryUseCase() &&
|
||||
canUseBiometryUseCase()
|
||||
} else {
|
||||
innerWalletRouter.isWalletLastScreen() && shouldShowAskBiometryUseCase() && canUseBiometryUseCase()
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeToUserWalletsUpdates() = channelFlow<Unit> {
|
||||
|
|
|
|||
|
|
@ -76,18 +76,19 @@ internal class WalletsUpdateActionResolver @Inject constructor(
|
|||
isAnyWalletNameChanged(state, wallets) -> {
|
||||
getRenameWalletsAction(state, wallets)
|
||||
}
|
||||
isAnyHotWalletBackedUp(state, wallets) -> {
|
||||
isAnyHotWalletBackedUpChange(state, wallets) -> {
|
||||
getHotWalletsBackedUpAction(state, wallets)
|
||||
}
|
||||
else -> getUpdateSelectedWalletAction(state, wallets, selectedWallet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAnyHotWalletBackedUp(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
|
||||
private fun isAnyHotWalletBackedUpChange(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
|
||||
val incompleteActivationWalletIds = state.incompleteActivationWalletIds()
|
||||
return incompleteActivationWalletIds.mapNotNull { walletId ->
|
||||
wallets.firstOrNull { it.walletId == walletId && it is UserWallet.Hot && it.backedUp }
|
||||
}.isNotEmpty()
|
||||
val walletsToUpdate = wallets.filter {
|
||||
it is UserWallet.Hot && it.backedUp == incompleteActivationWalletIds.contains(it.walletId)
|
||||
}
|
||||
return walletsToUpdate.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun isWalletsCountChanged(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
|
||||
|
|
@ -163,8 +164,7 @@ internal class WalletsUpdateActionResolver @Inject constructor(
|
|||
val incompleteActivationWalletIds = state.incompleteActivationWalletIds()
|
||||
|
||||
val walletsToUpdate = wallets.filter {
|
||||
it is UserWallet.Hot && it.backedUp &&
|
||||
incompleteActivationWalletIds.contains(it.walletId)
|
||||
it is UserWallet.Hot && it.backedUp == incompleteActivationWalletIds.contains(it.walletId)
|
||||
}
|
||||
|
||||
return Action.ReloadWarningsForWallets(walletsToUpdate)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
internal class MultiWalletWarningsSubscriber(
|
||||
|
|
@ -31,6 +32,11 @@ internal class MultiWalletWarningsSubscriber(
|
|||
.onEach { warnings ->
|
||||
val displayedState = stateHolder.getWalletState(userWallet.walletId)
|
||||
|
||||
// Wait until the wallet appears in the list
|
||||
stateHolder.uiState.first {
|
||||
it.wallets.any { walletState -> walletState.walletCardState.id == userWallet.walletId }
|
||||
}
|
||||
|
||||
stateHolder.update(SetWarningsTransformer(userWallet.walletId, warnings))
|
||||
walletWarningsAnalyticsSender.send(displayedState, warnings)
|
||||
walletWarningsSingleEventSender.send(
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
@Assisted private val onWalletClick: (UserWalletId) -> Unit,
|
||||
@Assisted private val messageSender: UiMessageSender,
|
||||
@Assisted("onlyMultiCurrency") private val onlyMultiCurrency: Boolean,
|
||||
@Assisted("authMode") private val authMode: Boolean,
|
||||
@Assisted("isAuthMode") private val isAuthMode: Boolean,
|
||||
private val userWalletImageFetcher: UserWalletImageFetcher,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
) : UserWalletsFetcher {
|
||||
|
|
@ -55,7 +55,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
override val userWallets: Flow<ImmutableList<UserWalletItemUM>> = walletsFlow.transformLatest { wallets ->
|
||||
val uiModels = UserWalletItemUMConverter(
|
||||
onClick = onWalletClick,
|
||||
authMode = authMode,
|
||||
isAuthMode = isAuthMode,
|
||||
).convertList(wallets)
|
||||
.toImmutableList()
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
combine(
|
||||
flow = getSelectedAppCurrencyUseCase().distinctUntilChanged(),
|
||||
flow2 = getBalanceHidingSettingsUseCase().distinctUntilChanged(),
|
||||
flow3 = getWalletTotalBalanceUseCase(wallets.map(UserWallet::walletId)).distinctUntilChanged(),
|
||||
flow3 = getTotalBalanceFlow(wallets),
|
||||
flow4 = userWalletImageFetcher.walletsImage(wallets, ArtworkSize.SMALL),
|
||||
) { maybeAppCurrency, balanceHidingSettings, maybeBalances, artworks ->
|
||||
createUiModels(
|
||||
|
|
@ -88,6 +88,19 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
}
|
||||
.flowOn(dispatchers.default)
|
||||
|
||||
private fun getTotalBalanceFlow(
|
||||
wallets: List<UserWallet>,
|
||||
): Flow<Lce<TokenListError, Map<UserWalletId, TotalFiatBalance>>> {
|
||||
val walletIds = wallets.map(UserWallet::walletId)
|
||||
|
||||
return if (isAuthMode) {
|
||||
// We should not load balances in auth mode
|
||||
flowOf(Lce.Loading(walletIds.associateWith { TotalFiatBalance.Loading }))
|
||||
} else {
|
||||
getWalletTotalBalanceUseCase(walletIds).distinctUntilChanged()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUiModels(
|
||||
wallets: List<UserWallet>,
|
||||
maybeAppCurrency: Either<SelectedAppCurrencyError, AppCurrency>,
|
||||
|
|
@ -117,7 +130,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
balance = balance,
|
||||
isBalanceHidden = balanceHidingSettings.isBalanceHidden,
|
||||
artwork = artworks[userWallet.walletId],
|
||||
authMode = authMode,
|
||||
isAuthMode = isAuthMode,
|
||||
)
|
||||
.convert(userWallet)
|
||||
}
|
||||
|
|
@ -136,7 +149,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
|
|||
override fun create(
|
||||
messageSender: UiMessageSender,
|
||||
@Assisted("onlyMultiCurrency") onlyMultiCurrency: Boolean,
|
||||
@Assisted("authMode") authMode: Boolean,
|
||||
@Assisted("isAuthMode") isAuthMode: Boolean,
|
||||
onWalletClick: (UserWalletId) -> Unit,
|
||||
): DefaultUserWalletsFetcher
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue