Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-18 16:54:01 +04:00
parent 078e8ed336
commit fe6c26624a
9 changed files with 89 additions and 71 deletions

View file

@ -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<CardSettingsComponent.Params>()
@ -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,
),
)
}
}
}
}

View file

@ -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 = {},

View file

@ -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<WarningsToReset>,
val isResetPasswordButtonShown: Boolean,
val isAcceptCondition1Checked: Boolean,
val isAcceptCondition2Checked: Boolean,
val onAcceptCondition1ToggleClick: (Boolean) -> Unit,
val onAcceptCondition2ToggleClick: (Boolean) -> Unit,
val warningsToShow: ImmutableList<WarningUM>,
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
}
}

View file

@ -11,6 +11,7 @@ interface ResetCardComponent : ComposableContentComponent {
val cardId: String,
val isActiveBackupStatus: Boolean,
val backupCardsCount: Int,
val hasTangemPay: Boolean,
)
interface Factory : ComponentFactory<Params, ResetCardComponent>

View file

@ -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<ResetCardScreenState.WarningType, ResetCardScreenState.WarningUM>()
val screenState: MutableStateFlow<ResetCardScreenState> = 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<ResetCardScreenState.WarningUM> {
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 },
)
}
}

View file

@ -424,6 +424,7 @@ internal class ChildFactory @Inject constructor(
cardId = route.cardId,
isActiveBackupStatus = route.isActiveBackupStatus,
backupCardsCount = route.backupCardsCount,
hasTangemPay = route.hasTangemPay,
),
componentFactory = resetCardComponentFactory,
)