Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-22 16:14:14 +03:00
parent 081128f2cf
commit 63b07cccc3
53 changed files with 614 additions and 464 deletions

View file

@ -65,7 +65,6 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
onNotificationsDescriptionClick = {},
isNotificationsPermissionGranted = false,
onAccessCodeClick = {},
onUpgradeWalletClick = {},
onBackupClick = {},
onCardSettingsClick = {},
accountsUM = previewAccounts(),

View file

@ -31,6 +31,7 @@ internal sealed class WalletSettingsItemUM {
val text: TextReference,
val isEnabled: Boolean,
val imageState: ImageState,
val additionalBlock: BlockUM? = null,
val onClick: () -> Unit,
) : WalletSettingsItemUM()
@ -46,13 +47,6 @@ internal sealed class WalletSettingsItemUM {
val title: TextReference,
val description: TextReference,
) : WalletSettingsItemUM()
data class UpgradeWallet(
override val id: String,
val title: TextReference,
val description: TextReference,
val onClick: () -> Unit,
) : WalletSettingsItemUM()
}
@Immutable

View file

@ -96,7 +96,10 @@ internal class WalletSettingsModel @Inject constructor(
val params: WalletSettingsComponent.Params = paramsContainer.require()
val dialogNavigation = SlotNavigation<DialogConfig>()
val bottomSheetNavigation: SlotNavigation<NetworksAvailableForNotificationBSConfig> = SlotNavigation()
private val walletCardItemDelegate = walletCardItemDelegateFactory.create(dialogNavigation)
private val walletCardItemDelegate = walletCardItemDelegateFactory.create(
dialogNavigation = dialogNavigation,
onUpgradeHotWalletClick = ::onUpgradeWalletClick,
)
val state: MutableStateFlow<WalletSettingsUM> = MutableStateFlow(
value = WalletSettingsUM(
@ -249,7 +252,6 @@ internal class WalletSettingsModel @Inject constructor(
onCheckedNotificationsChanged = ::onCheckedNotificationsChange,
onNotificationsDescriptionClick = ::onNotificationsDescriptionClick,
onAccessCodeClick = { onAccessCodeClick(userWallet) },
onUpgradeWalletClick = { onUpgradeWalletClick() },
onBackupClick = ::onBackupClick,
onCardSettingsClick = ::onCardSettingsClick,
accountsUM = accountList,
@ -374,10 +376,7 @@ internal class WalletSettingsModel @Inject constructor(
val isCodeSet = userWallet.hotWalletId.authType != HotWalletId.AuthType.NoPassword
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonAccessCode(isCodeSet))
if (!state.value.isWalletBackedUp) {
showMakeBackupAtFirstAlertBS(
isUpgradeFlow = false,
action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.AccessCode,
)
showMakeBackupAtFirstAlertBS()
} else {
unlockWalletIfNeedAndProceed { authorizationRequired ->
router.push(
@ -392,35 +391,28 @@ internal class WalletSettingsModel @Inject constructor(
}
private fun onUpgradeWalletClick() {
if (!state.value.isWalletBackedUp) {
showMakeBackupAtFirstAlertBS(
isUpgradeFlow = true,
action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.Upgrade,
)
} else {
unlockWalletIfNeedAndProceed {
router.push(AppRoute.UpgradeWallet(userWalletId = params.userWalletId))
}
}
router.push(AppRoute.WalletHardwareBackup(userWalletId = params.userWalletId))
}
private fun onBackupClick() {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonBackup())
router.push(AppRoute.WalletBackup(params.userWalletId))
router.push(
AppRoute.WalletBackup(
userWalletId = params.userWalletId,
isColdWalletOptionShown = false,
),
)
}
private fun onCardSettingsClick() {
router.push(AppRoute.CardSettings(params.userWalletId))
}
private fun showMakeBackupAtFirstAlertBS(
action: WalletSettingsAnalyticEvents.NoticeBackupFirst.Action,
isUpgradeFlow: Boolean,
) {
private fun showMakeBackupAtFirstAlertBS() {
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.NoticeBackupFirst(
source = AnalyticsParam.ScreensSources.WalletSettings.value,
action = action,
action = WalletSettingsAnalyticEvents.NoticeBackupFirst.Action.AccessCode,
),
)
val message = bottomSheetMessage {
@ -438,14 +430,10 @@ internal class WalletSettingsModel @Inject constructor(
router.push(
AppRoute.CreateWalletBackup(
userWalletId = params.userWalletId,
isUpgradeFlow = isUpgradeFlow,
isUpgradeFlow = false,
shouldSetAccessCode = true,
analyticsSource = AnalyticsParam.ScreensSources.WalletSettings.value,
analyticsAction = if (isUpgradeFlow) {
RecoveryPhraseScreenAction.Upgrade.value
} else {
RecoveryPhraseScreenAction.AccessCode.value
},
analyticsAction = RecoveryPhraseScreenAction.AccessCode.value,
),
)
closeBs()

View file

@ -42,7 +42,6 @@ import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -153,10 +152,6 @@ private fun Content(state: WalletSettingsUM, modifier: Modifier = Modifier) {
modifier = itemModifier,
model = item,
)
is WalletSettingsItemUM.UpgradeWallet -> UpgradeWalletBlock(
modifier = itemModifier,
model = item,
)
is WalletSettingsAccountsUM.Header -> AccountsHeader(item, itemModifier)
is WalletSettingsAccountsUM.Account -> AccountItem(
model = item,
@ -211,35 +206,54 @@ private fun CardBlock(model: WalletSettingsItemUM.CardBlock, modifier: Modifier
enabled = model.isEnabled,
onClick = model.onClick,
) {
Row(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
verticalAlignment = Alignment.CenterVertically,
) {
CardImage(model.imageState)
Column(modifier = Modifier.weight(1f)) {
Text(
text = model.title.resolveReference(),
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption2,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Text(
text = model.text.resolveReference(),
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
Column {
Row(
modifier = Modifier.padding(all = TangemTheme.dimens.spacing12),
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
verticalAlignment = Alignment.CenterVertically,
) {
CardImage(model.imageState)
Column(modifier = Modifier.weight(1f)) {
Text(
text = model.title.resolveReference(),
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.caption2,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
Text(
text = model.text.resolveReference(),
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.subtitle1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
}
SecondarySmallButton(
config = SmallButtonConfig(
isEnabled = model.isEnabled,
text = resourceReference(R.string.common_rename),
onClick = model.onClick,
),
)
}
SecondarySmallButton(
config = SmallButtonConfig(
isEnabled = model.isEnabled,
text = resourceReference(R.string.common_rename),
onClick = model.onClick,
),
)
if (model.additionalBlock != null) {
Column {
HorizontalDivider(
thickness = TangemTheme.dimens.size0_5,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = TangemTheme.dimens.spacing12),
color = TangemTheme.colors.stroke.primary,
)
BlockItem(
modifier = Modifier.fillMaxWidth(),
model = model.additionalBlock,
)
}
}
}
}
}
@ -272,21 +286,6 @@ private fun SwitchBlock(model: WalletSettingsItemUM.WithSwitch, modifier: Modifi
}
}
@Composable
private fun UpgradeWalletBlock(model: WalletSettingsItemUM.UpgradeWallet, modifier: Modifier = Modifier) {
Notification(
config = NotificationConfig(
title = model.title,
subtitle = model.description,
iconResId = R.drawable.ic_hardware_backup_36,
iconSize = 36.dp,
onClick = model.onClick,
shouldShowArrowIcon = false,
),
modifier = modifier,
)
}
@Composable
private fun NotificationAlertBlock(model: WalletSettingsItemUM.NotificationPermission, modifier: Modifier = Modifier) {
Notification(
@ -480,20 +479,4 @@ private fun Preview_WalletSettingsScreen() {
PreviewWalletSettingsComponent().Content(modifier = Modifier.fillMaxSize())
}
}
@Composable
@Preview(showBackground = true, widthDp = 360)
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun Preview_WalletSettingsScreen1() {
TangemThemePreview {
UpgradeWalletBlock(
model = WalletSettingsItemUM.UpgradeWallet(
id = "upgrade_wallet",
title = stringReference("Upgrade wallet with a hardware backup"),
description = stringReference("Keep your crypto safe with Tangems best-in-class hardware wallet."),
onClick = {},
),
)
}
}
// endregion Preview

View file

@ -38,17 +38,10 @@ internal class ItemsBuilder @Inject constructor() {
onReferralClick: () -> Unit,
onManageTokensClick: () -> Unit,
onAccessCodeClick: () -> Unit,
onUpgradeWalletClick: () -> Unit,
onBackupClick: () -> Unit,
onCardSettingsClick: () -> Unit,
): PersistentList<WalletSettingsItemUM> = persistentListOf<WalletSettingsItemUM>()
.add(cardItem)
.addAll(
buildUpgradeWalletItem(
userWallet = userWallet,
onUpgradeWalletClick = onUpgradeWalletClick,
),
)
.addAll(buildAccessCodeItem(userWallet, onAccessCodeClick))
.addAll(accountsUM)
.add(
@ -116,21 +109,6 @@ internal class ItemsBuilder @Inject constructor() {
onCheckedChange = onCheckedNFTChange,
)
private fun buildUpgradeWalletItem(
userWallet: UserWallet,
onUpgradeWalletClick: () -> Unit,
): List<WalletSettingsItemUM> = when (userWallet) {
is UserWallet.Cold -> emptyList()
is UserWallet.Hot -> listOf(
WalletSettingsItemUM.UpgradeWallet(
id = "upgrade_wallet",
title = resourceReference(id = R.string.hw_upgrade_to_cold_banner_title),
description = resourceReference(id = R.string.hw_upgrade_to_cold_banner_description),
onClick = onUpgradeWalletClick,
),
)
}
private fun buildNotificationsPermissionItem() = WalletSettingsItemUM.NotificationPermission(
id = "notifications_permission",
title = resourceReference(id = R.string.transaction_notifications_warning_title),

View file

@ -2,6 +2,7 @@ package com.tangem.feature.walletsettings.utils
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.core.ui.components.block.model.BlockUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.wallet.UserWallet
@ -24,6 +25,7 @@ internal class WalletCardItemDelegate @AssistedInject constructor(
private val getShouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase,
private val walletImageFetcher: UserWalletImageFetcher,
@Assisted private val dialogNavigation: SlotNavigation<DialogConfig>,
@Assisted private val onUpgradeHotWalletClick: () -> Unit,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
) {
@ -43,10 +45,20 @@ internal class WalletCardItemDelegate @AssistedInject constructor(
isEnabled = isRenameAvailable,
onClick = { openRenameWalletDialog(wallet) },
imageState = imageState,
additionalBlock = buildUpgradeToHardwareWalletBlockOrNull(wallet),
)
},
)
private fun buildUpgradeToHardwareWalletBlockOrNull(wallet: UserWallet): BlockUM? {
return BlockUM(
text = resourceReference(R.string.upgrade_to_hardware_wallet_button_title),
iconRes = null,
onClick = onUpgradeHotWalletClick,
accentType = BlockUM.AccentType.ACCENT,
).takeIf { wallet is UserWallet.Hot }
}
private fun openRenameWalletDialog(userWallet: UserWallet) {
val config = DialogConfig.RenameWallet(
userWalletId = userWallet.walletId,
@ -57,6 +69,9 @@ internal class WalletCardItemDelegate @AssistedInject constructor(
@AssistedFactory
interface Factory {
fun create(dialogNavigation: SlotNavigation<DialogConfig>): WalletCardItemDelegate
fun create(
dialogNavigation: SlotNavigation<DialogConfig>,
onUpgradeHotWalletClick: () -> Unit,
): WalletCardItemDelegate
}
}