Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-13 13:43:06 +05:00
parent 4bb7fde041
commit 4341673767
20 changed files with 276 additions and 351 deletions

View file

@ -33,7 +33,6 @@ class AccountPortfolioItemUMConverter(
endIcon = endIcon, endIcon = endIcon,
onClick = { onClick(value.accountId) }, onClick = { onClick(value.accountId) },
imageState = getImageState(value), imageState = getImageState(value),
label = null,
) )
} }
} }

View file

@ -36,9 +36,6 @@ import com.tangem.core.ui.components.TextShimmer
import com.tangem.core.ui.components.account.AccountIconSize import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.components.block.BlockCard import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.block.TangemBlockCardColors import com.tangem.core.ui.components.block.TangemBlockCardColors
import com.tangem.core.ui.components.label.Label
import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.components.text.applyBladeBrush import com.tangem.core.ui.components.text.applyBladeBrush
import com.tangem.core.ui.extensions.* import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
@ -76,8 +73,6 @@ fun UserWalletItem(
balance = state.balance, balance = state.balance,
) )
state.label?.let { Label(it) }
when (state.endIcon) { when (state.endIcon) {
UserWalletItemUM.EndIcon.None -> Unit UserWalletItemUM.EndIcon.None -> Unit
UserWalletItemUM.EndIcon.Arrow -> { UserWalletItemUM.EndIcon.Arrow -> {
@ -94,6 +89,13 @@ fun UserWalletItem(
contentDescription = null, contentDescription = null,
) )
} }
UserWalletItemUM.EndIcon.Warning -> {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_alert_circle_24),
tint = TangemTheme.colors.icon.warning,
contentDescription = null,
)
}
} }
} }
} }
@ -316,10 +318,7 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
name = stringReference("Mobile Wallet"), name = stringReference("Mobile Wallet"),
information = getInformation(cardCount = 1), information = getInformation(cardCount = 1),
balance = UserWalletItemUM.Balance.Locked, balance = UserWalletItemUM.Balance.Locked,
label = LabelUM( endIcon = UserWalletItemUM.EndIcon.Warning,
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
),
isEnabled = true, isEnabled = true,
onClick = {}, onClick = {},
), ),

View file

@ -2,10 +2,7 @@ package com.tangem.common.ui.userwallet.converter
import com.tangem.common.ui.R import com.tangem.common.ui.R
import com.tangem.common.ui.userwallet.state.UserWalletItemUM import com.tangem.common.ui.userwallet.state.UserWalletItemUM
import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.fiat
@ -52,7 +49,6 @@ class UserWalletItemUMConverter(
endIcon = endIcon, endIcon = endIcon,
onClick = { onClick(value.walletId) }, onClick = { onClick(value.walletId) },
imageState = artwork, imageState = artwork,
label = getLabelOrNull(userWallet = this),
) )
} }
} }
@ -61,17 +57,6 @@ class UserWalletItemUMConverter(
return isAuthMode || userWallet.isLocked.not() return isAuthMode || userWallet.isLocked.not()
} }
private fun getLabelOrNull(userWallet: UserWallet): LabelUM? {
return if (isAuthMode.not() && userWallet is UserWallet.Hot && !userWallet.backedUp) {
LabelUM(
text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
)
} else {
null
}
}
private fun getInfo(userWallet: UserWallet): UserWalletItemUM.Information.Loaded { private fun getInfo(userWallet: UserWallet): UserWalletItemUM.Information.Loaded {
val text = when (userWallet) { val text = when (userWallet) {
is UserWallet.Cold -> { is UserWallet.Cold -> {

View file

@ -2,7 +2,6 @@ package com.tangem.common.ui.userwallet.state
import com.tangem.common.ui.account.CryptoPortfolioIconUM import com.tangem.common.ui.account.CryptoPortfolioIconUM
import com.tangem.core.ui.components.artwork.ArtworkUM import com.tangem.core.ui.components.artwork.ArtworkUM
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
import javax.annotation.concurrent.Immutable import javax.annotation.concurrent.Immutable
@ -17,12 +16,13 @@ data class UserWalletItemUM(
val isEnabled: Boolean, val isEnabled: Boolean,
val endIcon: EndIcon = EndIcon.None, val endIcon: EndIcon = EndIcon.None,
val onClick: () -> Unit, val onClick: () -> Unit,
val label: LabelUM? = null,
) { ) {
enum class EndIcon { enum class EndIcon {
None, None,
Arrow, Arrow,
Checkmark, Checkmark,
Warning,
} }
sealed class Balance { sealed class Balance {

View file

@ -51,7 +51,19 @@ fun BlockItem(model: BlockUM, modifier: Modifier = Modifier) {
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
) )
model.label?.let { Label(it) } when (val endContent = model.endContent) {
is BlockUM.EndContent.None -> Unit
is BlockUM.EndContent.Icon -> Icon(
painter = painterResource(id = endContent.resId),
contentDescription = null,
tint = when (endContent.accentType) {
BlockUM.AccentType.NONE -> TangemTheme.colors.text.primary1
BlockUM.AccentType.ACCENT -> TangemTheme.colors.text.accent
BlockUM.AccentType.WARNING -> TangemTheme.colors.text.warning
},
)
is BlockUM.EndContent.Label -> Label(endContent.label)
}
} }
} }
} }

View file

@ -3,15 +3,29 @@ package com.tangem.core.ui.components.block.model
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import com.tangem.core.ui.components.label.entity.LabelUM import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
import javax.annotation.concurrent.Immutable
data class BlockUM( data class BlockUM(
val text: TextReference, val text: TextReference,
@DrawableRes val iconRes: Int, @DrawableRes val iconRes: Int,
val onClick: () -> Unit, val onClick: () -> Unit,
val accentType: AccentType = AccentType.NONE, val accentType: AccentType = AccentType.NONE,
val label: LabelUM? = null, val endContent: EndContent = EndContent.None,
) { ) {
@Immutable
sealed interface EndContent {
data object None : EndContent
data class Label(
val label: LabelUM,
) : EndContent
data class Icon(
val resId: Int,
val accentType: AccentType = AccentType.NONE,
) : EndContent
}
enum class AccentType { enum class AccentType {
NONE, ACCENT, WARNING, NONE, ACCENT, WARNING,
} }

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M11.413,2.426C12.757,2.426 13.43,2.426 13.943,2.688C14.395,2.918 14.762,3.285 14.992,3.736C15.254,4.25 15.253,4.922 15.253,6.266V9.736C15.253,11.079 15.254,11.752 14.992,12.265C14.762,12.716 14.395,13.084 13.943,13.314C13.43,13.575 12.757,13.575 11.413,13.575H4.587C3.243,13.575 2.57,13.575 2.057,13.314C1.605,13.084 1.238,12.716 1.008,12.265C0.746,11.752 0.746,11.079 0.746,9.736V6.266C0.746,4.922 0.746,4.25 1.008,3.736C1.238,3.285 1.605,2.918 2.057,2.688C2.57,2.426 3.243,2.426 4.587,2.426H11.413ZM8,5.063C7.876,5.063 7.814,5.063 7.763,5.073C7.551,5.115 7.386,5.281 7.344,5.492C7.334,5.544 7.333,5.606 7.333,5.729V7.334H5.729C5.606,7.334 5.544,7.334 5.492,7.344C5.281,7.386 5.115,7.551 5.073,7.763C5.063,7.815 5.063,7.877 5.063,8.001C5.063,8.124 5.063,8.186 5.073,8.238C5.115,8.449 5.281,8.615 5.492,8.657C5.544,8.667 5.606,8.667 5.729,8.667H7.333V10.271C7.333,10.394 7.334,10.456 7.344,10.508C7.386,10.719 7.551,10.885 7.763,10.927C7.814,10.937 7.876,10.938 8,10.938C8.124,10.938 8.186,10.937 8.238,10.927C8.449,10.885 8.615,10.719 8.657,10.508C8.667,10.456 8.667,10.394 8.667,10.271V8.667H10.27C10.394,8.667 10.456,8.667 10.508,8.657C10.719,8.615 10.885,8.449 10.927,8.238C10.937,8.186 10.937,8.124 10.937,8.001C10.937,7.877 10.937,7.815 10.927,7.763C10.885,7.551 10.719,7.386 10.508,7.344C10.456,7.333 10.394,7.334 10.27,7.334H8.667V5.729C8.667,5.606 8.667,5.544 8.657,5.492C8.615,5.281 8.449,5.115 8.238,5.073C8.186,5.063 8.124,5.063 8,5.063Z"
android:fillColor="#0099FF"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M12.054,1.505C13.173,1.505 13.733,1.505 14.161,1.723C14.537,1.914 14.843,2.221 15.035,2.597C15.253,3.024 15.253,3.585 15.253,4.705V11.296C15.253,12.416 15.253,12.976 15.035,13.404C14.843,13.781 14.537,14.087 14.161,14.278C13.733,14.496 13.173,14.496 12.054,14.496H3.946C2.827,14.496 2.267,14.496 1.839,14.278C1.463,14.087 1.157,13.78 0.965,13.404C0.747,12.976 0.746,12.416 0.746,11.296V4.705C0.746,3.585 0.747,3.024 0.965,2.597C1.157,2.221 1.463,1.914 1.839,1.723C2.267,1.505 2.827,1.505 3.946,1.505H12.054ZM3.597,10.534C3.21,10.535 2.897,10.848 2.896,11.234C2.896,11.621 3.21,11.934 3.597,11.935H6.563C6.949,11.935 7.263,11.621 7.263,11.234C7.263,10.848 6.949,10.534 6.563,10.534H3.597ZM10.921,6.947C10.535,6.947 10.221,7.261 10.221,7.647V9.544L9.72,9.043C9.446,8.77 9.003,8.77 8.729,9.043C8.456,9.316 8.457,9.76 8.729,10.033L10.426,11.729C10.699,12.002 11.142,12.002 11.415,11.729L13.111,10.034C13.384,9.761 13.384,9.317 13.111,9.044C12.838,8.771 12.394,8.77 12.121,9.043L11.62,9.544V7.647C11.62,7.261 11.307,6.947 10.921,6.947ZM3.597,7.301C3.21,7.301 2.897,7.615 2.896,8.001C2.897,8.387 3.21,8.701 3.597,8.701H6.563C6.949,8.701 7.262,8.387 7.263,8.001C7.263,7.615 6.949,7.301 6.563,7.301H3.597ZM3.597,4.066C3.21,4.067 2.897,4.38 2.896,4.767C2.896,5.153 3.21,5.467 3.597,5.467H6.563C6.949,5.467 7.263,5.153 7.263,4.767C7.263,4.38 6.949,4.066 6.563,4.066H3.597ZM9.438,4.066C9.051,4.067 8.737,4.38 8.737,4.767C8.737,5.153 9.051,5.467 9.438,5.467H12.403C12.79,5.467 13.104,5.153 13.104,4.767C13.103,4.38 12.79,4.067 12.403,4.066H9.438Z"
android:fillColor="#0099FF"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M4.559,7.397C5.105,7.397 5.547,7.839 5.547,8.385V13.432C5.547,13.977 5.105,14.419 4.559,14.419H1.91C1.364,14.419 0.922,13.977 0.922,13.432V8.385C0.922,7.839 1.364,7.397 1.91,7.397H4.559ZM2.773,8.382C2.482,8.382 2.246,8.617 2.246,8.908C2.246,9.199 2.482,9.435 2.773,9.435H3.695C3.986,9.435 4.221,9.199 4.221,8.908C4.221,8.617 3.986,8.382 3.695,8.382H2.773Z"
android:fillColor="#0099FF"
android:fillType="evenOdd"/>
<path
android:pathData="M9.376,1.58C9.887,1.58 10.267,1.58 10.596,1.668C11.485,1.905 12.179,2.598 12.417,3.484C12.473,3.693 12.493,3.923 12.501,4.194C12.597,4.203 12.689,4.213 12.778,4.225C13.375,4.305 13.902,4.479 14.324,4.9C14.746,5.322 14.922,5.848 15.002,6.443C15.078,7.011 15.078,7.727 15.078,8.596V9.971C15.078,10.84 15.078,11.557 15.002,12.124C14.922,12.72 14.746,13.246 14.324,13.667C13.902,14.089 13.375,14.263 12.778,14.343C12.209,14.419 11.491,14.419 10.619,14.419H6.666C6.658,14.419 6.65,14.419 6.642,14.419C6.784,14.12 6.865,13.785 6.865,13.432V8.385C6.865,7.112 5.833,6.08 4.56,6.08H1.91C1.557,6.08 1.221,6.16 0.922,6.302V3.506C0.922,2.442 1.786,1.58 2.852,1.58H9.376ZM12.271,8.29C11.645,8.29 11.138,8.797 11.138,9.423C11.138,10.048 11.645,10.555 12.271,10.555C12.896,10.555 13.404,10.048 13.404,9.423C13.403,8.797 12.896,8.29 12.271,8.29ZM2.852,2.864C2.497,2.864 2.208,3.151 2.208,3.506C2.208,3.86 2.497,4.148 2.852,4.148H10.619C10.825,4.148 11.022,4.148 11.211,4.149C11.205,3.983 11.194,3.892 11.173,3.816C11.054,3.373 10.707,3.026 10.263,2.908C10.12,2.869 9.926,2.864 9.286,2.864H2.852Z"
android:fillColor="#0099FF"
android:fillType="evenOdd"/>
</vector>

View file

@ -125,7 +125,6 @@ internal object PortfolioSelectorPreviewData {
name = accountName, name = accountName,
icon = AccountIconPreviewData.randomAccountIcon(), icon = AccountIconPreviewData.randomAccountIcon(),
), ),
label = null,
) )
private val walletItem: UserWalletItemUM private val walletItem: UserWalletItemUM
@ -137,7 +136,6 @@ internal object PortfolioSelectorPreviewData {
isEnabled = true, isEnabled = true,
onClick = { }, onClick = { },
imageState = ImageState.MobileWallet, imageState = ImageState.MobileWallet,
label = null,
) )
private val lockedWalletItem: UserWalletItemUM private val lockedWalletItem: UserWalletItemUM

View file

@ -1,72 +1,80 @@
package com.tangem.features.createwalletselection package com.tangem.features.createwalletselection
import com.tangem.common.core.TangemError
import com.tangem.common.core.TangemSdkError
import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic.SignedIn
import com.tangem.core.analytics.models.Basic.SignedIn.SignInType
import com.tangem.core.decompose.di.GlobalUiMessageSender
import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.R import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.message.DialogMessage
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.analytics.IntroductionProcess import com.tangem.domain.card.analytics.IntroductionProcess
import com.tangem.domain.card.analytics.ParamCardCurrencyConverter
import com.tangem.domain.card.analytics.Shop import com.tangem.domain.card.analytics.Shop
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.common.wallets.error.SaveWalletError
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.settings.repositories.SettingsRepository
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM
import com.tangem.features.createwalletselection.impl.R
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
private const val HIDE_PROGRESS_DELAY = 400L
@Suppress("LongParameterList") @Suppress("LongParameterList")
@ModelScoped @ModelScoped
internal class CreateWalletSelectionModel @Inject constructor( internal class CreateWalletSelectionModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider, override val dispatchers: CoroutineDispatcherProvider,
private val router: Router, private val router: Router,
private val scanCardProcessor: ScanCardProcessor,
private val cardSdkConfigRepository: CardSdkConfigRepository,
private val settingsRepository: SettingsRepository,
private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsEventHandler: AnalyticsEventHandler,
private val appRouter: AppRouter,
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
private val saveWalletUseCase: SaveWalletUseCase,
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase, private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
private val urlOpener: UrlOpener, private val urlOpener: UrlOpener,
private val userWalletsListRepository: UserWalletsListRepository,
@GlobalUiMessageSender private val uiMessageSender: UiMessageSender,
) : Model() { ) : Model() {
internal val uiState: StateFlow<CreateWalletSelectionUM> internal val uiState: StateFlow<CreateWalletSelectionUM>
field = MutableStateFlow( field = MutableStateFlow(
CreateWalletSelectionUM( CreateWalletSelectionUM(
onBackClick = { router.pop() }, onBackClick = { router.pop() },
onMobileWalletClick = ::onMobileWalletClick, blocks = persistentListOf(
onHardwareWalletClick = ::onHardwareWalletClick, CreateWalletSelectionUM.Block(
onScanClick = ::onScanClick, title = resourceReference(R.string.wallet_create_hardware_title),
titleLabel = LabelUM(
text = resourceReference(R.string.common_recommended),
style = LabelStyle.ACCENT,
),
description = resourceReference(R.string.wallet_add_hardware_description),
features = persistentListOf(
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_add_wallet_16,
title = resourceReference(R.string.wallet_add_hardware_info_create),
),
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_import_seed_16,
title = resourceReference(R.string.wallet_add_import_seed_phrase),
),
),
onClick = ::onHardwareWalletClick,
),
CreateWalletSelectionUM.Block(
title = resourceReference(R.string.wallet_create_mobile_title),
titleLabel = null,
description = resourceReference(R.string.wallet_add_mobile_description),
features = persistentListOf(
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_mobile_wallet_16,
title = resourceReference(R.string.hw_create_title),
),
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_import_seed_16,
title = resourceReference(R.string.wallet_add_import_seed_phrase),
),
),
onClick = ::onMobileWalletClick,
),
),
onBuyClick = ::onBuyClick,
), ),
) )
@ -86,6 +94,10 @@ internal class CreateWalletSelectionModel @Inject constructor(
} }
private fun onHardwareWalletClick() { private fun onHardwareWalletClick() {
// TODO [REDACTED_TASK_KEY]
}
private fun onBuyClick() {
analyticsEventHandler.send(IntroductionProcess.ButtonBuyCards) analyticsEventHandler.send(IntroductionProcess.ButtonBuyCards)
analyticsEventHandler.send(Shop.ScreenOpened) analyticsEventHandler.send(Shop.ScreenOpened)
modelScope.launch { modelScope.launch {
@ -93,113 +105,6 @@ internal class CreateWalletSelectionModel @Inject constructor(
} }
} }
private fun onScanClick() {
analyticsEventHandler.send(IntroductionProcess.ButtonScanCard)
scanCard()
}
private fun scanCard() {
modelScope.launch {
setLoading(true)
val shouldSaveAccessCodes = settingsRepository.shouldSaveAccessCodes()
cardSdkConfigRepository.setAccessCodeRequestPolicy(
isBiometricsRequestPolicy = shouldSaveAccessCodes,
)
val analyticsSource = AnalyticsParam.ScreensSources.Intro
scanCardProcessor.scan(
analyticsSource = analyticsSource,
onProgressStateChange = { showProgress ->
if (!showProgress) {
delay(HIDE_PROGRESS_DELAY)
setLoading(false)
} else {
setLoading(true)
}
},
onFailure = { error ->
handleScanError(error)
delay(HIDE_PROGRESS_DELAY)
setLoading(false)
},
onSuccess = { scanResponse ->
proceedWithScanResponse(scanResponse)
},
)
}
}
private suspend fun proceedWithScanResponse(scanResponse: ScanResponse) {
val userWallet = coldUserWalletBuilderFactory.create(scanResponse = scanResponse).build()
if (userWallet == null) {
Timber.e("User wallet not created")
setLoading(false)
return
}
saveWalletUseCase(userWallet = userWallet).fold(
ifLeft = {
delay(HIDE_PROGRESS_DELAY)
setLoading(false)
when (it) {
is SaveWalletError.DataError -> Timber.e(it.toString(), "Unable to save user wallet")
is SaveWalletError.WalletAlreadySaved -> {
userWalletsListRepository.unlock(
userWalletId = userWallet.walletId,
unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(scanResponse),
).onRight {
appRouter.replaceAll(AppRoute.Wallet)
}
}
}
},
ifRight = {
setLoading(false)
sendSignedInCardAnalyticsEvent(scanResponse)
appRouter.replaceAll(AppRoute.Wallet)
},
)
}
private suspend fun sendSignedInCardAnalyticsEvent(scanResponse: ScanResponse) {
val currency = ParamCardCurrencyConverter().convert(value = scanResponse.cardTypesResolver)
if (currency != null) {
analyticsEventHandler.send(
SignedIn(
currency = currency,
batch = scanResponse.card.batchId,
signInType = SignInType.Card,
walletsCount = userWalletsListRepository.userWalletsSync().size.toString(),
hasBackup = scanResponse.card.backupStatus?.isActive,
),
)
}
}
private fun setLoading(isLoading: Boolean) {
uiState.update { it.copy(isScanInProgress = isLoading) }
}
fun handleScanError(error: TangemError) {
when (error) {
is TangemSdkError.NfcFeatureIsUnavailable -> handleNfcFeatureUnavailable()
is TangemSdkError -> Timber.e(error, "Scan error occurred")
else -> Timber.e(error, "Error happened")
}
}
private fun handleNfcFeatureUnavailable() {
uiMessageSender.send(
message = DialogMessage(
message = resourceReference(R.string.nfc_error_unavailable),
title = resourceReference(id = R.string.common_error),
),
)
}
companion object { companion object {
private const val SHOW_ALREADY_HAVE_WALLET_DELAY = 3000L private const val SHOW_ALREADY_HAVE_WALLET_DELAY = 3000L
} }

View file

@ -1,11 +1,26 @@
package com.tangem.features.createwalletselection.entity package com.tangem.features.createwalletselection.entity
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList
internal data class CreateWalletSelectionUM( internal data class CreateWalletSelectionUM(
val isScanInProgress: Boolean = false, val isScanInProgress: Boolean = false,
val hardwareWalletPrice: String = "$54.90",
val showAlreadyHaveWallet: Boolean = false, val showAlreadyHaveWallet: Boolean = false,
val blocks: ImmutableList<Block>,
val onBackClick: () -> Unit, val onBackClick: () -> Unit,
val onMobileWalletClick: () -> Unit, val onBuyClick: () -> Unit,
val onHardwareWalletClick: () -> Unit, ) {
val onScanClick: () -> Unit, data class Block(
) val title: TextReference,
val titleLabel: LabelUM?,
val description: TextReference,
val features: ImmutableList<Feature>,
val onClick: () -> Unit,
)
data class Feature(
val iconResId: Int,
val title: TextReference,
)
}

View file

@ -10,23 +10,25 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.buttons.common.TangemButton import com.tangem.core.ui.components.SecondaryButton
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
import com.tangem.core.ui.components.buttons.common.TangemButtonSize import com.tangem.core.ui.components.buttons.common.TangemButtonSize
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults import com.tangem.core.ui.components.label.Label
import com.tangem.core.ui.extensions.conditional import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM
import com.tangem.features.createwalletselection.impl.R import com.tangem.features.createwalletselection.impl.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@Suppress("LongMethod") @Suppress("LongMethod")
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -34,7 +36,7 @@ import com.tangem.features.createwalletselection.impl.R
internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifier: Modifier = Modifier) { internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifier: Modifier = Modifier) {
Column( Column(
modifier = modifier modifier = modifier
.background(TangemTheme.colors.background.primary) .background(TangemTheme.colors.background.secondary)
.fillMaxSize() .fillMaxSize()
.systemBarsPadding(), .systemBarsPadding(),
) { ) {
@ -42,7 +44,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi
modifier = Modifier modifier = Modifier
.statusBarsPadding(), .statusBarsPadding(),
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
containerColor = TangemTheme.colors.background.primary, containerColor = TangemTheme.colors.background.secondary,
), ),
navigationIcon = { navigationIcon = {
IconButton(onClick = state.onBackClick) { IconButton(onClick = state.onBackClick) {
@ -58,7 +60,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi
Text( Text(
modifier = Modifier modifier = Modifier
.padding(16.dp), .padding(16.dp),
text = stringResourceSafe(R.string.wallet_create_nav_info_title), text = stringResourceSafe(R.string.wallet_add_support_title),
style = TangemTheme.typography.body1, style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.primary1, color = TangemTheme.colors.text.primary1,
maxLines = 1, maxLines = 1,
@ -78,60 +80,33 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi
Text( Text(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp), .padding(
text = stringResourceSafe(R.string.wallet_create_title), start = 16.dp,
end = 16.dp,
bottom = 24.dp,
),
text = stringResourceSafe(R.string.wallet_add_common_title),
style = TangemTheme.typography.h2, style = TangemTheme.typography.h2,
color = TangemTheme.colors.text.primary1, color = TangemTheme.colors.text.primary1,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
) )
WalletBlock( state.blocks.forEach { block ->
modifier = Modifier WalletBlock(
.padding(top = 24.dp), modifier = Modifier
title = stringResourceSafe(R.string.wallet_create_mobile_title), .padding(top = 8.dp),
description = stringResourceSafe(R.string.wallet_create_mobile_description), title = block.title.resolveReference(),
badge = { description = block.description.resolveReference(),
Box( features = block.features,
modifier = Modifier badge = block.titleLabel?.let {
.background( { Label(it) }
color = TangemTheme.colors.field.focused, },
shape = TangemTheme.shapes.roundedCorners8, onClick = block.onClick,
) )
.padding(horizontal = 8.dp, vertical = 4.dp), }
) {
Text(
text = stringResourceSafe(R.string.common_free),
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.text.secondary,
)
}
},
onClick = state.onMobileWalletClick,
)
WalletBlock(
title = stringResourceSafe(R.string.wallet_create_hardware_title),
description = stringResourceSafe(R.string.wallet_create_hardware_description),
badge = {
Box(
modifier = Modifier
.background(
color = TangemTheme.colors.text.accent.copy(alpha = 0.1f),
shape = TangemTheme.shapes.roundedCorners8,
)
.padding(horizontal = 8.dp, vertical = 4.dp),
) {
Text(
text = stringResourceSafe(R.string.wallet_create_hardware_badge, state.hardwareWalletPrice),
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.text.accent,
)
}
},
onClick = state.onHardwareWalletClick,
)
} }
AnimatedVisibility(state.showAlreadyHaveWallet) { AnimatedVisibility(state.showAlreadyHaveWallet) {
AlreadyHaveTangemWalletBlock( AlreadyHaveTangemWalletBlock(
onScanClick = state.onScanClick, onBuyClick = state.onBuyClick,
isScanInProgress = state.isScanInProgress, isScanInProgress = state.isScanInProgress,
) )
} }
@ -143,8 +118,9 @@ private fun WalletBlock(
title: String, title: String,
description: String, description: String,
onClick: () -> Unit, onClick: () -> Unit,
features: ImmutableList<CreateWalletSelectionUM.Feature>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
badge: @Composable () -> Unit, badge: @Composable (() -> Unit)? = null,
) { ) {
Column( Column(
modifier = modifier modifier = modifier
@ -152,11 +128,14 @@ private fun WalletBlock(
.padding(top = 8.dp) .padding(top = 8.dp)
.clip(TangemTheme.shapes.roundedCornersXMedium) .clip(TangemTheme.shapes.roundedCornersXMedium)
.background( .background(
color = TangemTheme.colors.field.primary, color = TangemTheme.colors.background.primary,
shape = TangemTheme.shapes.roundedCornersXMedium, shape = TangemTheme.shapes.roundedCornersXMedium,
) )
.clickable(onClick = onClick) .clickable(onClick = onClick)
.padding(16.dp), .padding(
horizontal = 16.dp,
vertical = 12.dp,
),
) { ) {
Row { Row {
Text( Text(
@ -167,7 +146,7 @@ private fun WalletBlock(
style = TangemTheme.typography.subtitle1, style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1, color = TangemTheme.colors.text.primary1,
) )
badge() badge?.invoke()
} }
Text( Text(
modifier = Modifier modifier = Modifier
@ -176,24 +155,57 @@ private fun WalletBlock(
style = TangemTheme.typography.body2, style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.tertiary, color = TangemTheme.colors.text.tertiary,
) )
if (features.isNotEmpty()) {
HorizontalDivider(
modifier = Modifier.padding(top = 12.dp),
thickness = 0.5.dp,
color = TangemTheme.colors.stroke.primary,
)
features.forEach {
Feature(
feature = it,
modifier = Modifier
.padding(top = 12.dp),
)
}
}
}
}
@Composable
private fun Feature(feature: CreateWalletSelectionUM.Feature, modifier: Modifier = Modifier) {
Row(
modifier = modifier,
) {
Icon(
modifier = Modifier.size(TangemTheme.dimens.size16),
painter = painterResource(id = feature.iconResId),
contentDescription = null,
tint = TangemTheme.colors.icon.accent,
)
Text(
modifier = Modifier
.weight(1f, fill = false)
.padding(start = 6.dp),
text = feature.title.resolveReference(),
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary,
)
} }
} }
@Composable @Composable
private fun AlreadyHaveTangemWalletBlock( private fun AlreadyHaveTangemWalletBlock(
onScanClick: () -> Unit, onBuyClick: () -> Unit,
isScanInProgress: Boolean, isScanInProgress: Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
var buttonWidth by remember { mutableStateOf(0) }
val density = LocalDensity.current
Row( Row(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(16.dp) .padding(16.dp)
.background( .background(
color = TangemTheme.colors.field.primary, color = TangemTheme.colors.background.primary,
shape = TangemTheme.shapes.roundedCornersXMedium, shape = TangemTheme.shapes.roundedCornersXMedium,
) )
.padding( .padding(
@ -206,30 +218,16 @@ private fun AlreadyHaveTangemWalletBlock(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.padding(end = 16.dp), .padding(end = 16.dp),
text = stringResourceSafe(R.string.wallet_create_scan_question), text = stringResourceSafe(R.string.wallet_add_hardware_purchase),
style = TangemTheme.typography.button, style = TangemTheme.typography.button,
color = TangemTheme.colors.text.primary1, color = TangemTheme.colors.text.primary1,
) )
TangemButton( SecondaryButton(
modifier = Modifier text = stringResourceSafe(R.string.wallet_import_buy_title),
.conditional(buttonWidth > 0) { onClick = onBuyClick,
width(with(density) { buttonWidth.toDp() })
}
.onGloballyPositioned { coordinates ->
if (buttonWidth == 0) {
buttonWidth = coordinates.size.width
}
},
text = stringResourceSafe(R.string.wallet_create_scan_title),
onClick = onScanClick,
icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_tangem_24),
size = TangemButtonSize.RoundedAction, size = TangemButtonSize.RoundedAction,
showProgress = isScanInProgress, showProgress = isScanInProgress,
colors = TangemButtonsDefaults.secondaryButtonColors,
textStyle = TangemTheme.typography.subtitle1,
enabled = true,
animateContentChange = true,
) )
} }
} }
@ -241,11 +239,45 @@ private fun PreviewCreateWalletContent() {
TangemThemePreview { TangemThemePreview {
CreateWalletSelectionContent( CreateWalletSelectionContent(
state = CreateWalletSelectionUM( state = CreateWalletSelectionUM(
showAlreadyHaveWallet = true, onBackClick = { },
onBackClick = {}, blocks = persistentListOf(
onMobileWalletClick = {}, CreateWalletSelectionUM.Block(
onHardwareWalletClick = {}, title = resourceReference(R.string.wallet_create_hardware_title),
onScanClick = {}, titleLabel = LabelUM(
text = resourceReference(R.string.common_recommended),
style = LabelStyle.ACCENT,
),
description = resourceReference(R.string.wallet_add_hardware_description),
features = persistentListOf(
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_add_wallet_16,
title = resourceReference(R.string.wallet_add_hardware_info_create),
),
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_import_seed_16,
title = resourceReference(R.string.wallet_add_import_seed_phrase),
),
),
onClick = { },
),
CreateWalletSelectionUM.Block(
title = resourceReference(R.string.wallet_create_mobile_title),
titleLabel = null,
description = resourceReference(R.string.wallet_add_mobile_description),
features = persistentListOf(
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_mobile_wallet_16,
title = resourceReference(R.string.hw_create_title),
),
CreateWalletSelectionUM.Feature(
iconResId = R.drawable.ic_import_seed_16,
title = resourceReference(R.string.wallet_add_import_seed_phrase),
),
),
onClick = { },
),
),
onBuyClick = { },
), ),
) )
} }

View file

@ -2,7 +2,6 @@ package com.tangem.features.details.entity
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.tangem.common.ui.userwallet.state.UserWalletItemUM import com.tangem.common.ui.userwallet.state.UserWalletItemUM
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@ -12,5 +11,4 @@ internal data class UserWalletListUM(
val isWalletSavingInProgress: Boolean, val isWalletSavingInProgress: Boolean,
val addNewWalletText: TextReference, val addNewWalletText: TextReference,
val onAddNewWalletClick: () -> Unit, val onAddNewWalletClick: () -> Unit,
val addWalletBottomSheet: TangemBottomSheetConfig = TangemBottomSheetConfig.Empty,
) )

View file

@ -6,14 +6,8 @@ import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.navigation.Router import com.tangem.core.decompose.navigation.Router
import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.R.*
import com.tangem.core.ui.components.bottomsheets.BottomSheetOption
import com.tangem.core.ui.components.bottomsheets.OptionsBottomSheetContent
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase
import com.tangem.features.details.entity.UserWalletListUM import com.tangem.features.details.entity.UserWalletListUM
import com.tangem.features.details.impl.R import com.tangem.features.details.impl.R
@ -27,7 +21,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@Suppress("LongParameterList") @Suppress("LongParameterList")
@ -38,8 +31,6 @@ internal class UserWalletListModel @Inject constructor(
private val router: Router, private val router: Router,
private val messageSender: UiMessageSender, private val messageSender: UiMessageSender,
override val dispatchers: CoroutineDispatcherProvider, override val dispatchers: CoroutineDispatcherProvider,
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
private val urlOpener: UrlOpener,
private val userWalletSaver: UserWalletSaver, private val userWalletSaver: UserWalletSaver,
private val hotWalletFeatureToggles: HotWalletFeatureToggles, private val hotWalletFeatureToggles: HotWalletFeatureToggles,
) : Model() { ) : Model() {
@ -58,7 +49,6 @@ internal class UserWalletListModel @Inject constructor(
isWalletSavingInProgress = false, isWalletSavingInProgress = false,
addNewWalletText = TextReference.EMPTY, addNewWalletText = TextReference.EMPTY,
onAddNewWalletClick = ::onAddNewWalletClick, onAddNewWalletClick = ::onAddNewWalletClick,
addWalletBottomSheet = TangemBottomSheetConfig.Empty,
), ),
) )
@ -90,62 +80,11 @@ internal class UserWalletListModel @Inject constructor(
private fun onAddNewWalletClick() { private fun onAddNewWalletClick() {
if (hotWalletFeatureToggles.isHotWalletEnabled) { if (hotWalletFeatureToggles.isHotWalletEnabled) {
state.update { currentState -> router.push(AppRoute.CreateWalletSelection)
currentState.copy(
addWalletBottomSheet = TangemBottomSheetConfig(
isShown = true,
onDismissRequest = ::dismissAddWalletBottomSheet,
content = createAddWalletBottomSheetContent(),
),
)
}
} else { } else {
withProgress(isWalletSavingInProgress) { withProgress(isWalletSavingInProgress) {
userWalletSaver.scanAndSaveUserWallet(modelScope) userWalletSaver.scanAndSaveUserWallet(modelScope)
} }
} }
} }
private fun dismissAddWalletBottomSheet() {
state.update { currentState ->
currentState.copy(
addWalletBottomSheet = currentState.addWalletBottomSheet.copy(isShown = false),
)
}
}
private fun createAddWalletBottomSheetContent(): OptionsBottomSheetContent {
return OptionsBottomSheetContent(
options = persistentListOf(
BottomSheetOption(
key = ADD_WALLET_KEY_CREATE,
label = resourceReference(string.home_button_create_new_wallet),
),
BottomSheetOption(
key = ADD_WALLET_KEY_ADD,
label = resourceReference(string.home_button_add_existing_wallet),
),
BottomSheetOption(
key = ADD_WALLET_KEY_BUY,
label = resourceReference(string.details_buy_wallet),
),
),
onOptionClick = { optionKey ->
dismissAddWalletBottomSheet()
when (optionKey) {
ADD_WALLET_KEY_CREATE -> router.push(AppRoute.CreateWalletSelection)
ADD_WALLET_KEY_ADD -> router.push(AppRoute.AddExistingWallet)
ADD_WALLET_KEY_BUY -> modelScope.launch {
generateBuyTangemCardLinkUseCase.invoke().let { urlOpener.openUrl(it) }
}
}
},
)
}
companion object {
private const val ADD_WALLET_KEY_CREATE = "create"
private const val ADD_WALLET_KEY_ADD = "add"
private const val ADD_WALLET_KEY_BUY = "buy"
}
} }

View file

@ -15,13 +15,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.tangem.common.ui.userwallet.UserWalletItem import com.tangem.common.ui.userwallet.UserWalletItem
import com.tangem.core.ui.R.*
import com.tangem.core.ui.components.block.BlockCard import com.tangem.core.ui.components.block.BlockCard
import com.tangem.core.ui.components.bottomsheets.OptionsBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.details.component.UserWalletListComponent import com.tangem.features.details.component.UserWalletListComponent
@ -48,8 +44,6 @@ internal fun UserWalletListBlock(state: UserWalletListUM, modifier: Modifier = M
onClick = state.onAddNewWalletClick, onClick = state.onAddNewWalletClick,
) )
} }
AddWalletBottomSheet(state.addWalletBottomSheet)
} }
@Composable @Composable
@ -100,15 +94,6 @@ private fun AddWalletButton(
} }
} }
@Composable
private fun AddWalletBottomSheet(config: TangemBottomSheetConfig) {
OptionsBottomSheet(
config = config,
title = resourceReference(string.auth_info_add_wallet_title),
containerColor = TangemTheme.colors.background.tertiary,
)
}
// region Preview // region Preview
@Composable @Composable
@Preview(showBackground = true, widthDp = 360) @Preview(showBackground = true, widthDp = 360)

View file

@ -39,7 +39,6 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
name = accountName, name = accountName,
icon = AccountIconPreviewData.randomAccountIcon(), icon = AccountIconPreviewData.randomAccountIcon(),
), ),
label = null,
) )
private val previewState = WalletSettingsUM( private val previewState = WalletSettingsUM(

View file

@ -197,7 +197,12 @@ internal class WalletSettingsModel @Inject constructor(
onCheckedNFTChange = ::onCheckedNFTChange, onCheckedNFTChange = ::onCheckedNFTChange,
forgetWallet = { forgetWallet = {
val message = DialogMessage( val message = DialogMessage(
message = resourceReference(R.string.user_wallet_list_delete_prompt), message = resourceReference(
id = when (userWallet) {
is UserWallet.Cold -> R.string.user_wallet_list_delete_prompt
is UserWallet.Hot -> R.string.user_wallet_list_delete_hw_prompt
},
),
firstActionBuilder = { firstActionBuilder = {
EventMessageAction( EventMessageAction(
title = resourceReference(R.string.common_delete), title = resourceReference(R.string.common_delete),

View file

@ -191,12 +191,14 @@ internal class ItemsBuilder @Inject constructor(
text = resourceReference(R.string.common_backup), text = resourceReference(R.string.common_backup),
iconRes = R.drawable.ic_more_cards_24, iconRes = R.drawable.ic_more_cards_24,
onClick = { router.push(AppRoute.WalletBackup(userWalletId)) }, onClick = { router.push(AppRoute.WalletBackup(userWalletId)) },
label = if (hasBackup) { endContent = if (hasBackup) {
null BlockUM.EndContent.None
} else { } else {
LabelUM( BlockUM.EndContent.Label(
text = resourceReference(R.string.hw_backup_no_backup), label = LabelUM(
style = LabelStyle.WARNING, text = resourceReference(R.string.hw_backup_no_backup),
style = LabelStyle.WARNING,
),
) )
}, },
).let(::add) ).let(::add)

View file

@ -130,6 +130,11 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
balance = balance, balance = balance,
isBalanceHidden = balanceHidingSettings.isBalanceHidden, isBalanceHidden = balanceHidingSettings.isBalanceHidden,
artwork = artworks[userWallet.walletId], artwork = artworks[userWallet.walletId],
endIcon = if (isAuthMode.not() && userWallet is UserWallet.Hot && !userWallet.backedUp) {
UserWalletItemUM.EndIcon.Warning
} else {
UserWalletItemUM.EndIcon.None
},
isAuthMode = isAuthMode, isAuthMode = isAuthMode,
) )
.convert(userWallet) .convert(userWallet)