From fe6c26624a78e5b53a985b0ca455338dcbf76359 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Dec 2025 16:54:01 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../cardsettings/model/CardSettingsModel.kt | 24 +++--- .../details/ui/resetcard/ResetCardScreen.kt | 36 ++++----- .../ui/resetcard/ResetCardScreenState.kt | 19 +++-- .../ui/resetcard/api/ResetCardComponent.kt | 1 + .../ui/resetcard/model/ResetCardModel.kt | 73 +++++++++++-------- .../tangem/tap/routing/utils/ChildFactory.kt | 1 + .../com/tangem/common/routing/AppRoute.kt | 1 + core/res/src/main/res/values-ru/strings.xml | 2 +- core/res/src/main/res/values/strings.xml | 3 + 9 files changed, 89 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt index 08aa5ef0b0..797ef6c056 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/model/CardSettingsModel.kt @@ -18,6 +18,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.models.wallet.requireColdWallet +import com.tangem.domain.pay.repository.OnboardingRepository import com.tangem.domain.settings.repositories.SettingsRepository import com.tangem.domain.wallets.builder.UserWalletIdBuilder import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -54,6 +55,7 @@ internal class CardSettingsModel @Inject constructor( private val getUserWalletUseCase: GetUserWalletUseCase, private val cardSdkConfigRepository: CardSdkConfigRepository, private val settingsRepository: SettingsRepository, + private val onboardingRepository: OnboardingRepository, ) : Model() { private val params = paramsContainer.require() @@ -218,15 +220,19 @@ internal class CardSettingsModel @Inject constructor( } else { val card = scanResponse.card - store.dispatchNavigationAction { - push( - route = AppRoute.ResetToFactory( - userWalletId = userWalletId, - cardId = card.cardId, - isActiveBackupStatus = card.backupStatus?.isActive == true, - backupCardsCount = scanResponse.getBackupCardsCount() ?: 0, - ), - ) + modelScope.launch { + val hasTangemPay = onboardingRepository.checkCustomerWallet(userWalletId).getOrNull() == true + store.dispatchNavigationAction { + push( + route = AppRoute.ResetToFactory( + userWalletId = userWalletId, + cardId = card.cardId, + isActiveBackupStatus = card.backupStatus?.isActive == true, + backupCardsCount = scanResponse.getBackupCardsCount() ?: 0, + hasTangemPay = hasTangemPay, + ), + ) + } } } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index 3e04e9381b..818620b38f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -22,6 +22,7 @@ import com.tangem.core.ui.extensions.resolveReference import com.tangem.tap.features.details.ui.common.DetailsMainButton import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.wallet.R +import kotlinx.collections.immutable.persistentListOf import com.tangem.tap.features.details.ui.resetcard.ResetCardScreenState.Dialog as ResetCardDialog @Composable @@ -114,22 +115,11 @@ private fun Description(text: TextReference) { @Composable private fun Conditions(state: ResetCardScreenState) { state.warningsToShow.forEach { warning -> - when (warning) { - ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS -> { - ConditionCheckBox( - checkedState = state.isAcceptCondition1Checked, - onCheckedChange = state.onAcceptCondition1ToggleClick, - description = TextReference.Res(R.string.reset_card_to_factory_condition_1), - ) - } - ResetCardScreenState.WarningsToReset.LOST_PASSWORD_RESTORE -> { - ConditionCheckBox( - checkedState = state.isAcceptCondition2Checked, - onCheckedChange = state.onAcceptCondition2ToggleClick, - description = TextReference.Res(R.string.reset_card_to_factory_condition_2), - ) - } - } + ConditionCheckBox( + checkedState = warning.isChecked, + onCheckedChange = { state.onToggleWarning(warning.type) }, + description = warning.description, + ) } } @@ -239,14 +229,16 @@ private fun ResetCardScreenSample(modifier: Modifier = Modifier) { ResetCardScreen( state = ResetCardScreenState( isResetButtonEnabled = true, - isResetPasswordButtonShown = false, - warningsToShow = listOf(ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS), + warningsToShow = persistentListOf( + ResetCardScreenState.WarningUM( + isChecked = false, + type = ResetCardScreenState.WarningType.LOST_WALLET_ACCESS, + description = TextReference.Res(id = R.string.reset_card_to_factory_condition_1), + ), + ), descriptionText = TextReference.Res(R.string.reset_card_with_backup_to_factory_message), - isAcceptCondition1Checked = false, - isAcceptCondition2Checked = false, - onAcceptCondition1ToggleClick = {}, - onAcceptCondition2ToggleClick = {}, onResetButtonClick = {}, + onToggleWarning = {}, dialog = null, ), onBackClick = {}, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt index 68b8585c72..0011e5dcd6 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreenState.kt @@ -3,16 +3,13 @@ package com.tangem.tap.features.details.ui.resetcard import androidx.annotation.StringRes import com.tangem.core.ui.extensions.TextReference import com.tangem.wallet.R +import kotlinx.collections.immutable.ImmutableList internal data class ResetCardScreenState( val isResetButtonEnabled: Boolean, val descriptionText: TextReference, - val warningsToShow: List, - val isResetPasswordButtonShown: Boolean, - val isAcceptCondition1Checked: Boolean, - val isAcceptCondition2Checked: Boolean, - val onAcceptCondition1ToggleClick: (Boolean) -> Unit, - val onAcceptCondition2ToggleClick: (Boolean) -> Unit, + val warningsToShow: ImmutableList, + val onToggleWarning: (WarningType) -> Unit, val onResetButtonClick: () -> Unit, val dialog: Dialog?, ) { @@ -58,7 +55,13 @@ internal data class ResetCardScreenState( } } - internal enum class WarningsToReset { - LOST_WALLET_ACCESS, LOST_PASSWORD_RESTORE + internal data class WarningUM( + val isChecked: Boolean, + val type: WarningType, + val description: TextReference, + ) + + internal enum class WarningType { + LOST_WALLET_ACCESS, LOST_PASSWORD_RESTORE, LOST_TANGEM_PAY } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt index 64dc8b1c5d..9f24f61f9b 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/api/ResetCardComponent.kt @@ -11,6 +11,7 @@ interface ResetCardComponent : ComposableContentComponent { val cardId: String, val isActiveBackupStatus: Boolean, val backupCardsCount: Int, + val hasTangemPay: Boolean, ) interface Factory : ComponentFactory diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt index eaa4ce0a9f..c53ead9529 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/model/ResetCardModel.kt @@ -8,6 +8,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.card.DeleteSavedAccessCodesUseCase import com.tangem.domain.card.ResetCardUseCase import com.tangem.domain.card.ResetCardUserCodeParams @@ -30,6 +31,9 @@ import com.tangem.tap.features.details.ui.resetcard.api.ResetCardComponent import com.tangem.tap.store import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE +import com.tangem.wallet.R +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -82,33 +86,22 @@ internal class ResetCardModel @Inject constructor( // TODO: move logic to separate domain entity private var resetBackupCardCount = 0 + private var warningsMap = emptyMap() + val screenState: MutableStateFlow = MutableStateFlow( value = getInitialState(), ) private fun getInitialState(): ResetCardScreenState { - val shouldShowResetPasswordButton = shouldShowResetPasswordButton() - val warningsToShow = buildList { - add(ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS) - - if (shouldShowResetPasswordButton) { - add(ResetCardScreenState.WarningsToReset.LOST_PASSWORD_RESTORE) - } - } - return ResetCardScreenState( isResetButtonEnabled = false, descriptionText = getResetToFactoryDescription( isActiveBackupStatus = isActiveBackupPrimaryCard, typesResolver = currentCardTypesResolver, ), - warningsToShow = warningsToShow, - isResetPasswordButtonShown = shouldShowResetPasswordButton, - isAcceptCondition1Checked = false, - isAcceptCondition2Checked = false, - onAcceptCondition1ToggleClick = ::toggleFirstCondition, - onAcceptCondition2ToggleClick = ::toggleSecondCondition, + warningsToShow = buildInitialItems(), onResetButtonClick = { showDialog(ResetCardDialog.StartResetDialog) }, + onToggleWarning = ::toggleCondition, dialog = null, ) } @@ -119,28 +112,46 @@ internal class ResetCardModel @Inject constructor( return isTangemWallet && isActiveBackupPrimaryCard } - private fun toggleFirstCondition(isAccepted: Boolean) { - screenState.update { prevState -> - val isResetButtonEnabled = if (prevState.isResetPasswordButtonShown) { - isAccepted && prevState.isAcceptCondition2Checked - } else { - isAccepted - } + private fun buildInitialItems(): ImmutableList { + val shouldShowResetPasswordButton = shouldShowResetPasswordButton() + val shouldShowResetTangemPayButton = params.hasTangemPay - prevState.copy( - isAcceptCondition1Checked = isAccepted, - isResetButtonEnabled = isResetButtonEnabled, - ) + val lostWalletUM = ResetCardScreenState.WarningUM( + isChecked = false, + type = ResetCardScreenState.WarningType.LOST_WALLET_ACCESS, + description = TextReference.Res(id = R.string.reset_card_to_factory_condition_1), + ) + val lostPasswordUM = ResetCardScreenState.WarningUM( + isChecked = false, + type = ResetCardScreenState.WarningType.LOST_PASSWORD_RESTORE, + description = TextReference.Res(R.string.reset_card_to_factory_condition_2), + ) + val lostTangemPayUM = ResetCardScreenState.WarningUM( + isChecked = false, + type = ResetCardScreenState.WarningType.LOST_TANGEM_PAY, + description = TextReference.Res(R.string.reset_card_to_factory_condition_3), + ) + + warningsMap = buildMap { + put(ResetCardScreenState.WarningType.LOST_WALLET_ACCESS, lostWalletUM) + if (shouldShowResetPasswordButton) { + put(ResetCardScreenState.WarningType.LOST_PASSWORD_RESTORE, lostPasswordUM) + } + if (shouldShowResetTangemPayButton) { + put(ResetCardScreenState.WarningType.LOST_TANGEM_PAY, lostTangemPayUM) + } } + return warningsMap.values.toImmutableList() } - private fun toggleSecondCondition(isAccepted: Boolean) { + private fun toggleCondition(type: ResetCardScreenState.WarningType) { screenState.update { prevState -> - val isResetButtonEnabled = prevState.isAcceptCondition1Checked && isAccepted - + warningsMap[type]?.let { current -> + warningsMap = warningsMap + (type to current.copy(isChecked = !current.isChecked)) + } prevState.copy( - isAcceptCondition2Checked = isAccepted, - isResetButtonEnabled = isResetButtonEnabled, + warningsToShow = warningsMap.values.toImmutableList(), + isResetButtonEnabled = warningsMap.values.all { it.isChecked }, ) } } diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 99c8e414b9..2462507a7b 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -424,6 +424,7 @@ internal class ChildFactory @Inject constructor( cardId = route.cardId, isActiveBackupStatus = route.isActiveBackupStatus, backupCardsCount = route.backupCardsCount, + hasTangemPay = route.hasTangemPay, ), componentFactory = resetCardComponentFactory, ) diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 0c771f5609..dbb07560d9 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -113,6 +113,7 @@ sealed class AppRoute(val path: String) : Route { val cardId: String, val isActiveBackupStatus: Boolean, val backupCardsCount: Int, + val hasTangemPay: Boolean, ) : AppRoute( path = "/reset_to_factory" + "/${userWalletId.stringValue}" + diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 0d5eaa197f..03ce372d0f 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -2017,7 +2017,7 @@ %1$s выведено из Aave Режим доходности инициализирован Режим доходности реактивирован - Перевод средств в Aave + Перевод в Aave %1$s отправлено в Aave Вывод из Aave Автоматически diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 524e2ec97f..c6ef91ce1f 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -1083,6 +1083,7 @@ Reset the card I understand that after performing this action, I will no longer have access to the current wallet I realize that I can\'t use this card to recover my access code on the other cards of the current wallet + I understand that I will completely lose access to my Tangem Pay Card and all funds on it without the possibility of recovery Factory Reset will completely delete the wallet from the selected card or ring. You will not be able to restore the current wallet or use the card or ring to recover the access code. Factory Reset will completely delete the wallet from the selected card or ring and remove it from the app. You will not be able to restore the current wallet. All Tangem devices have been reset. @@ -1091,6 +1092,8 @@ Please reset the next device to continue Ring owners get 3 commission-free swaps on Changelly until 15.11! Swap With 0% Fees Now! + Devices with root access are considered less secure. Your data may be exposed to additional risks. + Root access detected Log into the app and check your balance without scanning the card or ring Access the app Allow to use biometrics