Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-05 14:27:19 +03:00
commit 94a6b98f54
237 changed files with 2879 additions and 1365 deletions

View file

@ -7,6 +7,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.router.slot.childSlot
import com.arkivanov.decompose.router.slot.dismiss
import com.arkivanov.essenty.lifecycle.doOnResume
import com.tangem.common.routing.AppRoute
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.child
@ -48,6 +49,7 @@ internal class WalletComponent @AssistedInject constructor(
init {
lifecycle.subscribe(model.screenLifecycleProvider)
doOnResume { model.onResume() }
componentScope.launch { model.innerWalletRouter.navigateToFlow.collect { navigate(it) } }
}

View file

@ -4,9 +4,11 @@ import androidx.compose.runtime.Stable
import arrow.core.getOrElse
import com.arkivanov.decompose.router.slot.activate
import com.arkivanov.decompose.router.slot.dismiss
import com.squareup.sqldelight.internal.AtomicBoolean
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
@ -95,6 +97,7 @@ internal class WalletModel @Inject constructor(
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val accountsFeatureToggles: AccountsFeatureToggles,
private val tangemPayMainInfoManager: TangemPayMainInfoManager,
private val trackingContextProxy: TrackingContextProxy,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
) : Model() {
@ -110,16 +113,12 @@ internal class WalletModel @Inject constructor(
private val updateTangemPayJobHolder = JobHolder()
private var expressTxStatusTaskScheduler = SingleTaskScheduler<Unit>()
private val hasMainScreenOpenedEventSent = AtomicBoolean(false)
init {
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.ScreenOpened)
screenLifecycleProvider.isBackgroundState
.onEach { isBackground ->
if (isBackground.not()) {
suggestToEnableBiometrics()
}
}.launchIn(modelScope)
if (!hotWalletFeatureToggles.isHotWalletEnabled) {
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.MainScreen.ScreenOpenedLegacy)
}
suggestToOpenMarkets()
@ -137,6 +136,12 @@ internal class WalletModel @Inject constructor(
clickIntents.initialize(innerWalletRouter, modelScope)
}
fun onResume() {
modelScope.launch(dispatchers.main) {
suggestToEnableBiometrics()
}
}
private fun updateYieldSupplyApy() {
if (yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled) {
modelScope.launch(dispatchers.default) {
@ -192,7 +197,6 @@ internal class WalletModel @Inject constructor(
private suspend fun shouldShowAskBiometryBottomSheet(): Boolean {
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
userWalletsListRepository.userWalletsSync().any { it is UserWallet.Cold } &&
innerWalletRouter.isWalletLastScreen() &&
shouldShowAskBiometryUseCase() &&
canUseBiometryUseCase()
} else {
@ -270,11 +274,25 @@ internal class WalletModel @Inject constructor(
// It's okay here because we need to be able to observe the selected wallet changes
@Suppress("DEPRECATION")
private fun subscribeOnSelectedWalletFlow() {
getSelectedWalletUseCase().onRight {
it
getSelectedWalletUseCase().onRight { walletFlow ->
walletFlow
.conflate()
.distinctUntilChanged()
.onEach { selectedWallet ->
trackingContextProxy.setContext(selectedWallet)
if (hotWalletFeatureToggles.isHotWalletEnabled && !hasMainScreenOpenedEventSent.get()) {
// send it here because we need context to be set
modelScope.launch {
val hasMobileWallet = userWalletsListRepository.userWalletsSync()
.any { it is UserWallet.Hot }
analyticsEventsHandler.send(
WalletScreenAnalyticsEvent.MainScreen.ScreenOpened(hasMobileWallet),
)
hasMainScreenOpenedEventSent.set(true)
}
}
if (selectedWallet.isMultiCurrency) {
selectedWalletAnalyticsSender.send(selectedWallet)
}
@ -412,6 +430,7 @@ internal class WalletModel @Inject constructor(
when (action) {
is WalletsUpdateActionResolver.Action.InitializeWallets -> initializeWallets(action)
is WalletsUpdateActionResolver.Action.ReinitializeWallet -> reinitializeWallet(action)
is WalletsUpdateActionResolver.Action.ReinitializeWallets -> reinitializeWallets(action)
is WalletsUpdateActionResolver.Action.AddWallet -> addWallet(action)
is WalletsUpdateActionResolver.Action.DeleteWallet -> deleteWallet(action)
is WalletsUpdateActionResolver.Action.UnlockWallet -> unlockWallet(action)
@ -516,6 +535,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) {
if (accountsFeatureToggles.isFeatureEnabled) {
fetchWalletContent(userWallet = action.selectedWallet)

View file

@ -64,8 +64,11 @@ internal class WalletsUpdateActionResolver @Inject constructor(
selectedWallet: UserWallet,
): Action {
return when {
isHotWalletUpgraded(state, wallets) -> {
getHotWalletsUpgradedAction(state, wallets)
isAnyHotWalletUpgraded(state, wallets) -> {
getHotWalletsUpgradedAction(state, wallets, selectedWallet)
}
isAnyHotWalletBackedUpChange(state, wallets) -> {
getHotWalletsBackedUpAction(state, wallets)
}
isWalletsCountChanged(state, wallets) -> {
getChangeWalletsListAction(state, wallets, selectedWallet)
@ -79,31 +82,35 @@ internal class WalletsUpdateActionResolver @Inject constructor(
isAnyWalletNameChanged(state, wallets) -> {
getRenameWalletsAction(state, wallets)
}
isAnyHotWalletBackedUpChange(state, wallets) -> {
getHotWalletsBackedUpAction(state, wallets)
isAnyWalletUnlocked(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 {
val incompleteActivationWalletIds = state.incompleteActivationWalletIds()
val walletsToUpdate = wallets.filter {
it is UserWallet.Hot && it.backedUp == incompleteActivationWalletIds.contains(it.walletId)
return wallets.any {
it is UserWallet.Hot && it.backedUp && incompleteActivationWalletIds.contains(it.walletId)
}
return walletsToUpdate.isNotEmpty()
}
private fun isHotWalletUpgraded(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
val previousWallet = state
.wallets
.getOrNull(state.selectedWalletIndex)
return when (previousWallet) {
is WalletState.MultiCurrency -> {
val wallet = wallets.firstOrNull { it.walletId == previousWallet.walletCardState.id }
previousWallet.type == WalletState.MultiCurrency.WalletType.Hot && wallet is UserWallet.Cold
private fun isAnyHotWalletUpgraded(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
return state.wallets.any { walletState ->
when (walletState) {
is WalletState.MultiCurrency -> {
val wallet = wallets.firstOrNull { it.walletId == walletState.walletCardState.id }
walletState.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(
state: WalletScreenState,
wallets: List<UserWallet>,
): Action.ReloadWallets {
val walletsToUpdate = wallets.filter { it.walletId == state.getPrevSelectedWallet().id }
return Action.ReloadWallets(walletsToUpdate)
selectedWallet: UserWallet,
): Action.ReinitializeWallets {
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 {
@ -205,29 +218,14 @@ internal class WalletsUpdateActionResolver @Inject constructor(
)
}
private fun getUpdateSelectedWalletAction(
state: WalletScreenState,
wallets: List<UserWallet>,
selectedWallet: UserWallet,
): Action {
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 isAnyWalletUnlocked(state: WalletScreenState, wallets: List<UserWallet>): Boolean {
return state.wallets.any { walletState ->
val wallet = wallets.firstOrNull { it.walletId == walletState.walletCardState.id } ?: return@any false
!wallet.isLocked &&
(walletState is WalletState.MultiCurrency.Locked || walletState is WalletState.SingleCurrency.Locked)
}
}
private fun isSelectedWalletUnlocked(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
return state.isSelectedWalletLocked() && !selectedWallet.isLocked
}
private fun isSelectedWalletCardsCountChanged(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
if (selectedWallet !is UserWallet.Cold) return false
val prevSelectedWallet = state.getPrevSelectedWallet()
@ -235,12 +233,6 @@ internal class WalletsUpdateActionResolver @Inject constructor(
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 {
return wallets
.map(WalletState::walletCardState)
@ -249,9 +241,12 @@ internal class WalletsUpdateActionResolver @Inject constructor(
}
private fun WalletScreenState.incompleteActivationWalletIds(): List<UserWalletId> {
return wallets.mapNotNull {
if (it.warnings.any { it is WalletNotification.FinishWalletActivation }) {
it.walletCardState.id
return wallets.mapNotNull { wallet ->
if (wallet.warnings.any { it is WalletNotification.FinishWalletActivation } ||
wallet.walletCardState is WalletState.MultiCurrency &&
wallet.walletCardState.additionalInfo?.isHotBackedUp == false
) {
wallet.walletCardState.id
} else {
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
*

View file

@ -11,9 +11,7 @@ import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.components.bottomsheets.message.*
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.bottomSheetMessage
import com.tangem.domain.card.SetCardWasScannedUseCase
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
@ -40,7 +38,6 @@ import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.PromotionBan
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
import com.tangem.domain.wallets.models.UnlockWalletsError
import com.tangem.domain.wallets.usecase.*
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
@ -106,7 +103,7 @@ internal interface WalletWarningsClickIntents {
fun onDenyPermissions()
fun onFinishWalletActivationClick(bannerType: WalletActivationBannerType, isBackupExists: Boolean)
fun onFinishWalletActivationClick(isBackupExists: Boolean)
}
@Suppress("LargeClass", "LongParameterList", "TooManyFunctions")
@ -460,40 +457,10 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
}
}
override fun onFinishWalletActivationClick(bannerType: WalletActivationBannerType, isBackupExists: Boolean) {
when (bannerType) {
WalletActivationBannerType.Attention -> {
val userWallet = getSelectedUserWallet() ?: return
appRouter.push(WalletActivation(userWallet.walletId, isBackupExists))
}
WalletActivationBannerType.Warning -> {
val message = bottomSheetMessage {
infoBlock {
icon(R.drawable.img_knight_shield_32) {
type = MessageBottomSheetUMV2.Icon.Type.Warning
backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.SameAsTint
}
title = resourceReference(R.string.hw_activation_need_title)
body = resourceReference(R.string.hw_activation_need_description)
}
secondaryButton {
text = resourceReference(R.string.common_later)
onClick {
closeBs()
}
}
primaryButton {
text = resourceReference(R.string.hw_activation_need_backup)
onClick {
val userWallet = getSelectedUserWallet() ?: return@onClick
appRouter.push(WalletActivation(userWallet.walletId, isBackupExists))
closeBs()
}
}
}
uiMessageSender.send(message)
}
}
override fun onFinishWalletActivationClick(isBackupExists: Boolean) {
analyticsEventHandler.send(MainScreen.ButtonFinalizeActivation)
val userWalletId = stateHolder.getSelectedWalletId()
appRouter.push(WalletActivation(userWalletId, isBackupExists))
}
override fun onAllowPermissions() {

View file

@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.common.preview
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
import com.tangem.core.ui.components.token.AccountItemPreviewData
import com.tangem.core.ui.components.token.state.TokenItemState
@ -14,6 +13,7 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.WalletPreviewData.topBarConfig
import com.tangem.feature.wallet.presentation.wallet.state.model.*
@ -167,11 +167,12 @@ internal object WalletScreenPreviewData {
warnings = persistentListOf(
WalletNotification.Warning.SomeNetworksUnreachable,
WalletNotification.FinishWalletActivation(
iconTint = NotificationConfig.IconTint.Attention,
type = WalletActivationBannerType.Attention,
buttonsState = ButtonsState.SecondaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = { },
),
isBackupExists = false,
),
),
bottomSheetConfig = null,

View file

@ -51,7 +51,30 @@ sealed class WalletScreenAnalyticsEvent {
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(category = "Main Screen", event = event, params = params) {
data object ScreenOpened : MainScreen(event = "Screen opened")
data object ScreenOpenedLegacy : MainScreen(
event = "Screen opened",
)
data class ScreenOpened(
private val hasMobileWallet: Boolean,
) : MainScreen(
event = "Screen opened",
params = mapOf("Mobile Wallet" to if (hasMobileWallet) "Yes" else "No"),
)
data class NoticeFinishActivation(private val activationState: ActivationState) : MainScreen(
event = "Notice - Finish Activation",
params = mapOf("Activation State" to activationState.value),
) {
enum class ActivationState(val value: String) {
NotStarted("Not Started"),
Unfinished("Unfinished"),
}
}
data object ButtonFinalizeActivation : MainScreen(
event = "Button - Finalize Activation",
)
class WalletSelected(val isImported: Boolean) : MainScreen(
event = "Wallet Selected",

View file

@ -70,9 +70,16 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
is WalletNotification.Warning.NetworksUnreachable,
is WalletNotification.UsedOutdatedData,
is WalletNotification.UnlockVisaAccess,
is WalletNotification.FinishWalletActivation,
is WalletNotification.Warning.YeildSupplyApprove, // TODO apply correct event
-> null
is WalletNotification.FinishWalletActivation -> {
val activationState = if (warning.isBackupExists) {
MainScreen.NoticeFinishActivation.ActivationState.Unfinished
} else {
MainScreen.NoticeFinishActivation.ActivationState.NotStarted
}
MainScreen.NoticeFinishActivation(activationState)
}
is WalletNotification.Critical.SeedPhraseNotification -> MainScreen.NoticeSeedPhraseSupport
is WalletNotification.Critical.SeedPhraseSecondNotification -> MainScreen.NoticeSeedPhraseSupportSecond
is WalletNotification.PushNotifications -> WalletScreenAnalyticsEvent.PushBannerPromo.PushBanner

View file

@ -1,8 +1,24 @@
package com.tangem.feature.wallet.presentation.wallet.analytics.utils
import arrow.atomic.AtomicBoolean
import com.tangem.common.routing.AppRoute.WalletActivation
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
import com.tangem.core.ui.components.bottomsheets.message.icon
import com.tangem.core.ui.components.bottomsheets.message.infoBlock
import com.tangem.core.ui.components.bottomsheets.message.onClick
import com.tangem.core.ui.components.bottomsheets.message.primaryButton
import com.tangem.core.ui.components.bottomsheets.message.secondaryButton
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.bottomSheetMessage
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
@ -12,8 +28,13 @@ import javax.inject.Inject
internal class WalletWarningsSingleEventSender @Inject constructor(
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
private val screenLifecycleProvider: ScreenLifecycleProvider,
private val uiMessageSender: UiMessageSender,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val router: Router,
) {
private val isActivationBottomSheetShown: AtomicBoolean = AtomicBoolean(false)
suspend fun send(
userWalletId: UserWalletId,
displayedUiState: WalletState?,
@ -26,9 +47,49 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
val events = newWarnings.filter { it !in displayedUiState.warnings }
events.forEach { event ->
if (event is WalletNotification.Critical.SeedPhraseNotification) {
seedPhraseNotificationUseCase.notified(userWalletId = userWalletId)
when (event) {
is WalletNotification.Critical.SeedPhraseNotification -> {
seedPhraseNotificationUseCase.notified(userWalletId = userWalletId)
}
is WalletNotification.FinishWalletActivation -> {
if (event.type == WalletActivationBannerType.Warning && !isActivationBottomSheetShown.get()) {
showFinishActivationBottomSheet(userWalletId)
isActivationBottomSheetShown.set(true)
}
}
else -> Unit
}
}
}
private fun showFinishActivationBottomSheet(userWalletId: UserWalletId) {
val userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: return
if (userWallet !is UserWallet.Hot) return
val message = bottomSheetMessage {
infoBlock {
icon(R.drawable.img_knight_shield_32) {
type = MessageBottomSheetUMV2.Icon.Type.Warning
backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.SameAsTint
}
title = resourceReference(R.string.hw_activation_need_title)
body = resourceReference(R.string.hw_activation_need_description)
}
secondaryButton {
text = resourceReference(R.string.common_later)
onClick {
closeBs()
}
}
primaryButton {
text = resourceReference(R.string.hw_activation_need_backup)
onClick {
router.push(WalletActivation(userWallet.walletId, userWallet.backedUp))
closeBs()
}
}
}
uiMessageSender.send(message)
}
}

View file

@ -7,7 +7,6 @@ import com.tangem.common.ui.notifications.NotificationId
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
import com.tangem.core.ui.components.notifications.NotificationConfig.IconTint
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
import com.tangem.domain.card.CardTypesResolver
@ -465,24 +464,20 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
ifError = { WalletActivationBannerType.Attention },
)
val tint = when (type) {
WalletActivationBannerType.Attention -> IconTint.Attention
WalletActivationBannerType.Warning -> IconTint.Warning
}
addIf(
element = WalletNotification.FinishWalletActivation(
iconTint = tint,
type = type,
buttonsState = when (type) {
WalletActivationBannerType.Warning -> ButtonsState.PrimaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = { clickIntents.onFinishWalletActivationClick(type, isBackupExists) },
onClick = { clickIntents.onFinishWalletActivationClick(isBackupExists) },
)
else -> ButtonsState.SecondaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = { clickIntents.onFinishWalletActivationClick(type, isBackupExists) },
onClick = { clickIntents.onFinishWalletActivationClick(isBackupExists) },
)
},
isBackupExists = isBackupExists,
),
condition = shouldShowFinishActivation,
)

View file

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

View file

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

View file

@ -10,6 +10,7 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
import com.tangem.feature.wallet.impl.R
import org.joda.time.DateTime
@ -287,14 +288,18 @@ sealed class WalletNotification(val config: NotificationConfig) {
)
data class FinishWalletActivation(
val iconTint: IconTint,
val type: WalletActivationBannerType,
val buttonsState: ButtonsState,
val isBackupExists: Boolean,
) : WalletNotification(
config = NotificationConfig(
title = resourceReference(R.string.hw_activation_need_title),
subtitle = resourceReference(R.string.hw_activation_need_description),
iconResId = R.drawable.img_knight_shield_32,
iconTint = iconTint,
iconTint = when (type) {
WalletActivationBannerType.Attention -> IconTint.Attention
WalletActivationBannerType.Warning -> IconTint.Warning
},
buttonsState = buttonsState,
),
)

View file

@ -49,7 +49,6 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
yieldSupplyApyMap: Map<String, String> = emptyMap(),
stakingApyMap: Map<String, List<Yield.Validator>> = emptyMap(),
) {
val accountFlattenCurrencies = accountList.flattenCurrencies()
val mainAccount = accountList.mainAccount
when {
@ -70,20 +69,8 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
)
}
isAccountMode -> {
val isAllAccountsEmpty = accountFlattenCurrencies.isEmpty()
if (isAllAccountsEmpty) {
stateController.update(
SetTokenListErrorTransformer(
selectedWallet = userWallet,
error = TokenListError.EmptyTokens,
appCurrency = appCurrency,
),
)
} else {
val convertParams = TokenConverterParams.Account(accountList, expandedAccounts)
updateContent(convertParams, appCurrency, yieldSupplyApyMap, stakingApyMap)
}
val convertParams = TokenConverterParams.Account(accountList, expandedAccounts)
updateContent(convertParams, appCurrency, yieldSupplyApyMap, stakingApyMap)
}
}
}