Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-26 14:36:55 +05:00
parent 1d97ce5203
commit 220a43c1b9
11 changed files with 86 additions and 28 deletions

View file

@ -62,6 +62,7 @@ fun Notification(
NotificationConfig.IconTint.Unspecified -> null
NotificationConfig.IconTint.Accent -> TangemTheme.colors.icon.accent
NotificationConfig.IconTint.Attention -> TangemTheme.colors.icon.attention
NotificationConfig.IconTint.Warning -> TangemTheme.colors.icon.warning
},
isEnabled: Boolean = true,
) {

View file

@ -65,5 +65,6 @@ data class NotificationConfig(
Unspecified,
Accent,
Attention,
Warning,
}
}

View file

@ -74,7 +74,7 @@ internal fun AccessCode(state: AccessCodeUM, modifier: Modifier = Modifier) {
) {
PinTextField(
length = state.accessCodeLength,
isPasswordVisual = !state.isConfirmMode,
isPasswordVisual = state.isConfirmMode,
value = state.accessCode,
pinTextColor = PinTextColor.Primary,
onValueChange = state.onAccessCodeChange,

View file

@ -61,7 +61,7 @@ internal fun OptionBlock(
color = backgroundColor,
shape = TangemTheme.shapes.roundedCornersXMedium,
)
.conditional(onClick != null) {
.conditional(onClick != null && enabled) {
onClick?.let { clickableSingle(onClick = it) } ?: Modifier
}
.padding(16.dp),

View file

@ -4,8 +4,9 @@ import com.tangem.core.ui.components.label.entity.LabelUM
internal data class WalletBackupUM(
val onBackClick: () -> Unit,
val recoveryPhraseStatus: LabelUM?,
val googleDriveStatus: LabelUM?,
val recoveryPhraseOption: LabelUM?,
val googleDriveOption: LabelUM?,
val googleDriveStatus: BackupStatus,
val onRecoveryPhraseClick: () -> Unit,
val onGoogleDriveClick: () -> Unit,
val backedUp: Boolean,

View file

@ -20,6 +20,7 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.common.routing.AppRoute
import com.tangem.features.hotwallet.WalletBackupComponent
import com.tangem.features.hotwallet.walletbackup.entity.BackupStatus
import com.tangem.features.hotwallet.walletbackup.entity.WalletBackupUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.*
@ -40,14 +41,15 @@ internal class WalletBackupModel @Inject constructor(
field = MutableStateFlow(
WalletBackupUM(
onBackClick = { router.pop() },
recoveryPhraseStatus = LabelUM(
recoveryPhraseOption = LabelUM(
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
),
googleDriveStatus = LabelUM(
googleDriveOption = LabelUM(
text = resourceReference(R.string.common_coming_soon),
style = LabelStyle.REGULAR,
),
googleDriveStatus = BackupStatus.ComingSoon,
onRecoveryPhraseClick = ::onRecoveryPhraseClick,
onGoogleDriveClick = { },
backedUp = false,
@ -95,7 +97,7 @@ internal class WalletBackupModel @Inject constructor(
}
private fun WalletBackupUM.updateBackupStatusesHotWallet(userWallet: UserWallet.Hot): WalletBackupUM = copy(
recoveryPhraseStatus = if (userWallet.backedUp) {
recoveryPhraseOption = if (userWallet.backedUp) {
LabelUM(
text = resourceReference(R.string.common_done),
style = LabelStyle.ACCENT,
@ -106,7 +108,7 @@ internal class WalletBackupModel @Inject constructor(
style = LabelStyle.WARNING,
)
},
googleDriveStatus = LabelUM(
googleDriveOption = LabelUM(
text = resourceReference(R.string.common_coming_soon),
style = LabelStyle.REGULAR,
),

View file

@ -51,7 +51,7 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
title = stringResourceSafe(R.string.hw_backup_seed_title),
description = stringResourceSafe(R.string.hw_backup_seed_description),
badge = {
state.recoveryPhraseStatus?.let { Label(it) }
state.recoveryPhraseOption?.let { Label(it) }
},
onClick = state.onRecoveryPhraseClick,
enabled = true,
@ -63,7 +63,7 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
title = stringResourceSafe(R.string.hw_backup_google_drive_title),
description = stringResourceSafe(R.string.hw_backup_google_drive_description),
badge = {
state.googleDriveStatus?.let { Label(it) }
state.googleDriveOption?.let { Label(it) }
},
onClick = state.onGoogleDriveClick,
enabled = state.googleDriveStatus != BackupStatus.ComingSoon,
@ -85,42 +85,45 @@ private fun WalletBackupContentPreview(@PreviewParameter(WalletBackupUMProvider:
private class WalletBackupUMProvider : CollectionPreviewParameterProvider<WalletBackupUM>(
collection = listOf(
WalletBackupUM(
recoveryPhraseStatus = LabelUM(
recoveryPhraseOption = LabelUM(
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
),
googleDriveStatus = LabelUM(
googleDriveOption = LabelUM(
text = resourceReference(R.string.common_coming_soon),
style = LabelStyle.REGULAR,
),
googleDriveStatus = BackupStatus.ComingSoon,
onBackClick = {},
onRecoveryPhraseClick = {},
onGoogleDriveClick = {},
backedUp = false,
),
WalletBackupUM(
recoveryPhraseStatus = LabelUM(
recoveryPhraseOption = LabelUM(
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
),
googleDriveStatus = LabelUM(
googleDriveOption = LabelUM(
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
),
googleDriveStatus = BackupStatus.NoBackup,
onBackClick = {},
onRecoveryPhraseClick = {},
onGoogleDriveClick = {},
backedUp = false,
),
WalletBackupUM(
recoveryPhraseStatus = LabelUM(
recoveryPhraseOption = LabelUM(
text = resourceReference(R.string.common_done),
style = LabelStyle.ACCENT,
),
googleDriveStatus = LabelUM(
googleDriveOption = LabelUM(
text = resourceReference(R.string.common_done),
style = LabelStyle.ACCENT,
),
googleDriveStatus = BackupStatus.Done,
onBackClick = {},
onRecoveryPhraseClick = {},
onGoogleDriveClick = {},

View file

@ -3,10 +3,13 @@ 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.state.TokenItemState
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.event.consumedEvent
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.presentation.wallet.state.model.WalletAdditionalInfo
@ -117,7 +120,13 @@ internal object WalletScreenPreviewData {
buttons = persistentListOf(buyButton),
warnings = persistentListOf(
WalletNotification.Warning.SomeNetworksUnreachable,
WalletNotification.FinishWalletActivation { },
WalletNotification.FinishWalletActivation(
iconTint = NotificationConfig.IconTint.Attention,
buttonsState = ButtonsState.SecondaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = { },
),
),
),
bottomSheetConfig = null,
tokensListState = textContentTokensState,

View file

@ -1,6 +1,9 @@
package com.tangem.feature.wallet.presentation.wallet.domain
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.card.CardTypesResolver
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.core.lce.Lce
@ -19,7 +22,9 @@ import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.utils.extensions.isPositive
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow
@ -54,7 +59,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
addFinishWalletActivationNotification(userWallet, clickIntents)
addFinishWalletActivationNotification(userWallet, maybeTokenList, clickIntents)
addReferralPromoNotification(cardTypesResolver, clickIntents, shouldShowReferralPromo)
@ -256,26 +261,55 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
)
}
private fun MutableList<WalletNotification>.addIf(element: WalletNotification, condition: Boolean) {
if (condition) add(element = element)
}
private fun MutableList<WalletNotification>.addFinishWalletActivationNotification(
userWallet: UserWallet,
maybeTokenList: Lce<TokenListError, TokenList>,
clickIntents: WalletClickIntents,
) {
if (userWallet !is UserWallet.Hot) return
val shouldShowFinishActivation = !userWallet.backedUp
val iconTint = maybeTokenList.fold(
ifLoading = {
if ((it?.totalFiatBalance as? TotalFiatBalance.Loaded)?.amount?.isPositive() == true) {
IconTint.Warning
} else {
IconTint.Attention
}
},
ifContent = {
if ((it.totalFiatBalance as? TotalFiatBalance.Loaded)?.amount?.isPositive() == true) {
IconTint.Warning
} else {
IconTint.Attention
}
},
ifError = { IconTint.Attention },
)
addIf(
element = WalletNotification.FinishWalletActivation(
onFinishClick = clickIntents::onFinishWalletActivationClick,
iconTint = iconTint,
buttonsState = when (iconTint) {
IconTint.Warning -> ButtonsState.PrimaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = clickIntents::onFinishWalletActivationClick,
)
else -> ButtonsState.SecondaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = clickIntents::onFinishWalletActivationClick,
)
},
),
condition = shouldShowFinishActivation,
)
}
private fun MutableList<WalletNotification>.addIf(element: WalletNotification, condition: Boolean) {
if (condition) add(element = element)
}
private companion object {
const val MAX_REMAINING_SIGNATURES_COUNT = 10
}

View file

@ -3,6 +3,8 @@ package com.tangem.feature.wallet.presentation.wallet.state.model
import androidx.compose.runtime.Immutable
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.components.notifications.NotificationConfig.ButtonsState
import com.tangem.core.ui.components.notifications.NotificationConfig.IconTint
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.resourceReference
@ -257,16 +259,15 @@ sealed class WalletNotification(val config: NotificationConfig) {
)
data class FinishWalletActivation(
val onFinishClick: () -> Unit,
val iconTint: IconTint,
val buttonsState: ButtonsState,
) : 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,
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
text = resourceReference(R.string.hw_activation_need_finish),
onClick = onFinishClick,
),
iconTint = iconTint,
buttonsState = buttonsState,
),
)

View file

@ -34,6 +34,12 @@ internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotificati
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
)
}
is WalletNotification.FinishWalletActivation -> {
Notification(
config = it.config,
modifier = modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
)
}
else -> {
Notification(
config = it.config,