diff --git a/common/ui/src/main/java/com/tangem/common/ui/account/AccountPortfolioItemUMConverter.kt b/common/ui/src/main/java/com/tangem/common/ui/account/AccountPortfolioItemUMConverter.kt index 276468c38c..0f29f40095 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/account/AccountPortfolioItemUMConverter.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/account/AccountPortfolioItemUMConverter.kt @@ -33,7 +33,6 @@ class AccountPortfolioItemUMConverter( endIcon = endIcon, onClick = { onClick(value.accountId) }, imageState = getImageState(value), - label = null, ) } } diff --git a/common/ui/src/main/java/com/tangem/common/ui/userwallet/UserWalletItem.kt b/common/ui/src/main/java/com/tangem/common/ui/userwallet/UserWalletItem.kt index fedba7d453..44b2fc91e9 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/userwallet/UserWalletItem.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/userwallet/UserWalletItem.kt @@ -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.block.BlockCard 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.extensions.* import com.tangem.core.ui.res.TangemTheme @@ -76,8 +73,6 @@ fun UserWalletItem( balance = state.balance, ) - state.label?.let { Label(it) } - when (state.endIcon) { UserWalletItemUM.EndIcon.None -> Unit UserWalletItemUM.EndIcon.Arrow -> { @@ -94,6 +89,13 @@ fun UserWalletItem( 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 { diff --git a/common/ui/src/main/java/com/tangem/common/ui/userwallet/state/UserWalletItemUM.kt b/common/ui/src/main/java/com/tangem/common/ui/userwallet/state/UserWalletItemUM.kt index ba418cea6b..98c0988741 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/userwallet/state/UserWalletItemUM.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/userwallet/state/UserWalletItemUM.kt @@ -2,7 +2,6 @@ package com.tangem.common.ui.userwallet.state import com.tangem.common.ui.account.CryptoPortfolioIconUM 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.domain.models.wallet.UserWalletId import javax.annotation.concurrent.Immutable @@ -17,12 +16,13 @@ data class UserWalletItemUM( val isEnabled: Boolean, val endIcon: EndIcon = EndIcon.None, val onClick: () -> Unit, - val label: LabelUM? = null, ) { + enum class EndIcon { None, Arrow, Checkmark, + Warning, } sealed class Balance { diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockItem.kt b/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockItem.kt index 8aab6c9598..66cf54df35 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockItem.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/block/BlockItem.kt @@ -51,7 +51,19 @@ fun BlockItem(model: BlockUM, modifier: Modifier = Modifier) { 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) + } } } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/block/model/BlockUM.kt b/core/ui/src/main/java/com/tangem/core/ui/components/block/model/BlockUM.kt index c950b5e4e7..4988f72eff 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/block/model/BlockUM.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/block/model/BlockUM.kt @@ -3,15 +3,29 @@ package com.tangem.core.ui.components.block.model import androidx.annotation.DrawableRes import com.tangem.core.ui.components.label.entity.LabelUM import com.tangem.core.ui.extensions.TextReference +import javax.annotation.concurrent.Immutable data class BlockUM( val text: TextReference, @DrawableRes val iconRes: Int, val onClick: () -> Unit, 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 { NONE, ACCENT, WARNING, } diff --git a/core/ui/src/main/res/drawable/ic_add_wallet_16.xml b/core/ui/src/main/res/drawable/ic_add_wallet_16.xml new file mode 100644 index 0000000000..48e62db467 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_add_wallet_16.xml @@ -0,0 +1,10 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_import_seed_16.xml b/core/ui/src/main/res/drawable/ic_import_seed_16.xml new file mode 100644 index 0000000000..6e96d53e29 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_import_seed_16.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_mobile_wallet_16.xml b/core/ui/src/main/res/drawable/ic_mobile_wallet_16.xml new file mode 100644 index 0000000000..e37da72eac --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_mobile_wallet_16.xml @@ -0,0 +1,14 @@ + + + + diff --git a/features/account/impl/src/main/java/com/tangem/features/account/selector/ui/PortfolioSelectorContent.kt b/features/account/impl/src/main/java/com/tangem/features/account/selector/ui/PortfolioSelectorContent.kt index 2bf56e09c3..a1bc34cd68 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/selector/ui/PortfolioSelectorContent.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/selector/ui/PortfolioSelectorContent.kt @@ -125,7 +125,6 @@ internal object PortfolioSelectorPreviewData { name = accountName, icon = AccountIconPreviewData.randomAccountIcon(), ), - label = null, ) private val walletItem: UserWalletItemUM @@ -137,7 +136,6 @@ internal object PortfolioSelectorPreviewData { isEnabled = true, onClick = { }, imageState = ImageState.MobileWallet, - label = null, ) private val lockedWalletItem: UserWalletItemUM diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt index 1225bd8144..20b64f77ca 100644 --- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt +++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt @@ -1,72 +1,80 @@ 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.AppRouter 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.model.Model 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.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.message.DialogMessage -import com.tangem.domain.card.ScanCardProcessor 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.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.SaveWalletUseCase import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM +import com.tangem.features.createwalletselection.impl.R import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import timber.log.Timber import javax.inject.Inject -private const val HIDE_PROGRESS_DELAY = 400L - @Suppress("LongParameterList") @ModelScoped internal class CreateWalletSelectionModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, - private val scanCardProcessor: ScanCardProcessor, - private val cardSdkConfigRepository: CardSdkConfigRepository, - private val settingsRepository: SettingsRepository, private val analyticsEventHandler: AnalyticsEventHandler, - private val appRouter: AppRouter, - private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory, - private val saveWalletUseCase: SaveWalletUseCase, private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase, private val urlOpener: UrlOpener, - private val userWalletsListRepository: UserWalletsListRepository, - @GlobalUiMessageSender private val uiMessageSender: UiMessageSender, ) : Model() { internal val uiState: StateFlow field = MutableStateFlow( CreateWalletSelectionUM( onBackClick = { router.pop() }, - onMobileWalletClick = ::onMobileWalletClick, - onHardwareWalletClick = ::onHardwareWalletClick, - onScanClick = ::onScanClick, + blocks = persistentListOf( + CreateWalletSelectionUM.Block( + 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() { + // TODO [REDACTED_TASK_KEY] + } + + private fun onBuyClick() { analyticsEventHandler.send(IntroductionProcess.ButtonBuyCards) analyticsEventHandler.send(Shop.ScreenOpened) 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 { private const val SHOW_ALREADY_HAVE_WALLET_DELAY = 3000L } diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt index ef14600b7a..1d76d78bac 100644 --- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt +++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt @@ -1,11 +1,26 @@ 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( val isScanInProgress: Boolean = false, - val hardwareWalletPrice: String = "$54.90", val showAlreadyHaveWallet: Boolean = false, + val blocks: ImmutableList, val onBackClick: () -> Unit, - val onMobileWalletClick: () -> Unit, - val onHardwareWalletClick: () -> Unit, - val onScanClick: () -> Unit, -) \ No newline at end of file + val onBuyClick: () -> Unit, +) { + data class Block( + val title: TextReference, + val titleLabel: LabelUM?, + val description: TextReference, + val features: ImmutableList, + val onClick: () -> Unit, + ) + + data class Feature( + val iconResId: Int, + val title: TextReference, + ) +} \ No newline at end of file diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt index 1df0b5eff7..1a953f008d 100644 --- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt +++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt @@ -10,23 +10,25 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.tangem.core.ui.components.buttons.common.TangemButton -import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition +import com.tangem.core.ui.components.SecondaryButton import com.tangem.core.ui.components.buttons.common.TangemButtonSize -import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults -import com.tangem.core.ui.extensions.conditional +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.extensions.resolveReference +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM import com.tangem.features.createwalletselection.impl.R +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf @Suppress("LongMethod") @OptIn(ExperimentalMaterial3Api::class) @@ -34,7 +36,7 @@ import com.tangem.features.createwalletselection.impl.R internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifier: Modifier = Modifier) { Column( modifier = modifier - .background(TangemTheme.colors.background.primary) + .background(TangemTheme.colors.background.secondary) .fillMaxSize() .systemBarsPadding(), ) { @@ -42,7 +44,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi modifier = Modifier .statusBarsPadding(), colors = TopAppBarDefaults.topAppBarColors( - containerColor = TangemTheme.colors.background.primary, + containerColor = TangemTheme.colors.background.secondary, ), navigationIcon = { IconButton(onClick = state.onBackClick) { @@ -58,7 +60,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi Text( modifier = Modifier .padding(16.dp), - text = stringResourceSafe(R.string.wallet_create_nav_info_title), + text = stringResourceSafe(R.string.wallet_add_support_title), style = TangemTheme.typography.body1, color = TangemTheme.colors.text.primary1, maxLines = 1, @@ -78,60 +80,33 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi Text( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), - text = stringResourceSafe(R.string.wallet_create_title), + .padding( + start = 16.dp, + end = 16.dp, + bottom = 24.dp, + ), + text = stringResourceSafe(R.string.wallet_add_common_title), style = TangemTheme.typography.h2, color = TangemTheme.colors.text.primary1, textAlign = TextAlign.Center, ) - WalletBlock( - modifier = Modifier - .padding(top = 24.dp), - title = stringResourceSafe(R.string.wallet_create_mobile_title), - description = stringResourceSafe(R.string.wallet_create_mobile_description), - badge = { - Box( - modifier = Modifier - .background( - color = TangemTheme.colors.field.focused, - shape = TangemTheme.shapes.roundedCorners8, - ) - .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, - ) + state.blocks.forEach { block -> + WalletBlock( + modifier = Modifier + .padding(top = 8.dp), + title = block.title.resolveReference(), + description = block.description.resolveReference(), + features = block.features, + badge = block.titleLabel?.let { + { Label(it) } + }, + onClick = block.onClick, + ) + } } AnimatedVisibility(state.showAlreadyHaveWallet) { AlreadyHaveTangemWalletBlock( - onScanClick = state.onScanClick, + onBuyClick = state.onBuyClick, isScanInProgress = state.isScanInProgress, ) } @@ -143,8 +118,9 @@ private fun WalletBlock( title: String, description: String, onClick: () -> Unit, + features: ImmutableList, modifier: Modifier = Modifier, - badge: @Composable () -> Unit, + badge: @Composable (() -> Unit)? = null, ) { Column( modifier = modifier @@ -152,11 +128,14 @@ private fun WalletBlock( .padding(top = 8.dp) .clip(TangemTheme.shapes.roundedCornersXMedium) .background( - color = TangemTheme.colors.field.primary, + color = TangemTheme.colors.background.primary, shape = TangemTheme.shapes.roundedCornersXMedium, ) .clickable(onClick = onClick) - .padding(16.dp), + .padding( + horizontal = 16.dp, + vertical = 12.dp, + ), ) { Row { Text( @@ -167,7 +146,7 @@ private fun WalletBlock( style = TangemTheme.typography.subtitle1, color = TangemTheme.colors.text.primary1, ) - badge() + badge?.invoke() } Text( modifier = Modifier @@ -176,24 +155,57 @@ private fun WalletBlock( style = TangemTheme.typography.body2, 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 private fun AlreadyHaveTangemWalletBlock( - onScanClick: () -> Unit, + onBuyClick: () -> Unit, isScanInProgress: Boolean, modifier: Modifier = Modifier, ) { - var buttonWidth by remember { mutableStateOf(0) } - val density = LocalDensity.current - Row( modifier = modifier .fillMaxWidth() .padding(16.dp) .background( - color = TangemTheme.colors.field.primary, + color = TangemTheme.colors.background.primary, shape = TangemTheme.shapes.roundedCornersXMedium, ) .padding( @@ -206,30 +218,16 @@ private fun AlreadyHaveTangemWalletBlock( modifier = Modifier .weight(1f) .padding(end = 16.dp), - text = stringResourceSafe(R.string.wallet_create_scan_question), + text = stringResourceSafe(R.string.wallet_add_hardware_purchase), style = TangemTheme.typography.button, color = TangemTheme.colors.text.primary1, ) - TangemButton( - modifier = Modifier - .conditional(buttonWidth > 0) { - 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), + SecondaryButton( + text = stringResourceSafe(R.string.wallet_import_buy_title), + onClick = onBuyClick, size = TangemButtonSize.RoundedAction, showProgress = isScanInProgress, - colors = TangemButtonsDefaults.secondaryButtonColors, - textStyle = TangemTheme.typography.subtitle1, - enabled = true, - animateContentChange = true, ) } } @@ -241,11 +239,45 @@ private fun PreviewCreateWalletContent() { TangemThemePreview { CreateWalletSelectionContent( state = CreateWalletSelectionUM( - showAlreadyHaveWallet = true, - onBackClick = {}, - onMobileWalletClick = {}, - onHardwareWalletClick = {}, - onScanClick = {}, + onBackClick = { }, + blocks = persistentListOf( + CreateWalletSelectionUM.Block( + 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 = { }, + ), + 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 = { }, ), ) } diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/UserWalletListUM.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/UserWalletListUM.kt index f217f837ce..a8ef5eb141 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/UserWalletListUM.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/entity/UserWalletListUM.kt @@ -2,7 +2,6 @@ package com.tangem.features.details.entity import androidx.compose.runtime.Immutable import com.tangem.common.ui.userwallet.state.UserWalletItemUM -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.extensions.TextReference import kotlinx.collections.immutable.ImmutableList @@ -12,5 +11,4 @@ internal data class UserWalletListUM( val isWalletSavingInProgress: Boolean, val addNewWalletText: TextReference, val onAddNewWalletClick: () -> Unit, - val addWalletBottomSheet: TangemBottomSheetConfig = TangemBottomSheetConfig.Empty, ) \ No newline at end of file diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt index 9ced337ddf..a096f5231d 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/model/UserWalletListModel.kt @@ -6,14 +6,8 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model 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.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.resourceReference -import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.features.details.entity.UserWalletListUM 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.launchIn import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import javax.inject.Inject @Suppress("LongParameterList") @@ -38,8 +31,6 @@ internal class UserWalletListModel @Inject constructor( private val router: Router, private val messageSender: UiMessageSender, override val dispatchers: CoroutineDispatcherProvider, - private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase, - private val urlOpener: UrlOpener, private val userWalletSaver: UserWalletSaver, private val hotWalletFeatureToggles: HotWalletFeatureToggles, ) : Model() { @@ -58,7 +49,6 @@ internal class UserWalletListModel @Inject constructor( isWalletSavingInProgress = false, addNewWalletText = TextReference.EMPTY, onAddNewWalletClick = ::onAddNewWalletClick, - addWalletBottomSheet = TangemBottomSheetConfig.Empty, ), ) @@ -90,62 +80,11 @@ internal class UserWalletListModel @Inject constructor( private fun onAddNewWalletClick() { if (hotWalletFeatureToggles.isHotWalletEnabled) { - state.update { currentState -> - currentState.copy( - addWalletBottomSheet = TangemBottomSheetConfig( - isShown = true, - onDismissRequest = ::dismissAddWalletBottomSheet, - content = createAddWalletBottomSheetContent(), - ), - ) - } + router.push(AppRoute.CreateWalletSelection) } else { withProgress(isWalletSavingInProgress) { 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" - } } \ No newline at end of file diff --git a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/UserWalletListBlock.kt b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/UserWalletListBlock.kt index bea3f8c35d..ec27900868 100644 --- a/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/UserWalletListBlock.kt +++ b/features/details/impl/src/main/kotlin/com/tangem/features/details/ui/UserWalletListBlock.kt @@ -15,13 +15,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider 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.bottomsheets.OptionsBottomSheet -import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.extensions.TextReference 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.TangemThemePreview import com.tangem.features.details.component.UserWalletListComponent @@ -48,8 +44,6 @@ internal fun UserWalletListBlock(state: UserWalletListUM, modifier: Modifier = M onClick = state.onAddNewWalletClick, ) } - - AddWalletBottomSheet(state.addWalletBottomSheet) } @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 @Composable @Preview(showBackground = true, widthDp = 360) diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt index d359b824c4..53d1a92331 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt @@ -39,7 +39,6 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent { name = accountName, icon = AccountIconPreviewData.randomAccountIcon(), ), - label = null, ) private val previewState = WalletSettingsUM( diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt index d0674d5ed0..5453245f07 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt @@ -197,7 +197,12 @@ internal class WalletSettingsModel @Inject constructor( onCheckedNFTChange = ::onCheckedNFTChange, forgetWallet = { 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 = { EventMessageAction( title = resourceReference(R.string.common_delete), diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt index e3caaf89d5..8375ca44c6 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt @@ -191,12 +191,14 @@ internal class ItemsBuilder @Inject constructor( text = resourceReference(R.string.common_backup), iconRes = R.drawable.ic_more_cards_24, onClick = { router.push(AppRoute.WalletBackup(userWalletId)) }, - label = if (hasBackup) { - null + endContent = if (hasBackup) { + BlockUM.EndContent.None } else { - LabelUM( - text = resourceReference(R.string.hw_backup_no_backup), - style = LabelStyle.WARNING, + BlockUM.EndContent.Label( + label = LabelUM( + text = resourceReference(R.string.hw_backup_no_backup), + style = LabelStyle.WARNING, + ), ) }, ).let(::add) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletsFetcher.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletsFetcher.kt index 1b4e9c358f..65c3ffbbe7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletsFetcher.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/utils/DefaultUserWalletsFetcher.kt @@ -130,6 +130,11 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor( balance = balance, isBalanceHidden = balanceHidingSettings.isBalanceHidden, artwork = artworks[userWallet.walletId], + endIcon = if (isAuthMode.not() && userWallet is UserWallet.Hot && !userWallet.backedUp) { + UserWalletItemUM.EndIcon.Warning + } else { + UserWalletItemUM.EndIcon.None + }, isAuthMode = isAuthMode, ) .convert(userWallet)