Updated on 2026-08-14
This commit is contained in:
parent
ac01e45371
commit
8db160652c
17 changed files with 421 additions and 1 deletions
|
|
@ -14,6 +14,7 @@ android {
|
|||
dependencies {
|
||||
/** Api */
|
||||
implementation(projects.features.hotWallet.api)
|
||||
implementation(projects.features.onboardingV2.api)
|
||||
implementation(projects.features.pushNotifications.api)
|
||||
|
||||
/** Core modules */
|
||||
|
|
|
|||
|
|
@ -5,21 +5,39 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.child
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.features.hotwallet.UpgradeWalletComponent
|
||||
import com.tangem.features.hotwallet.upgradewallet.ui.UpgradeWalletContent
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class DefaultUpgradeWalletComponent @AssistedInject constructor(
|
||||
@Assisted private val context: AppComponentContext,
|
||||
@Assisted private val params: UpgradeWalletComponent.Params,
|
||||
resetCardsComponentFactory: ResetCardsComponent.Factory,
|
||||
) : UpgradeWalletComponent, AppComponentContext by context {
|
||||
|
||||
private val model: UpgradeWalletModel = getOrCreateModel(params)
|
||||
|
||||
private val resetCardsComponent = resetCardsComponentFactory.create(
|
||||
context = child("ResetCardsComponent"),
|
||||
params = ResetCardsComponent.Params(
|
||||
callbacks = model.resetCardsComponentCallbacks,
|
||||
),
|
||||
)
|
||||
|
||||
init {
|
||||
model.startResetCardsFlow
|
||||
.onEach { resetCardsComponent.startResetCardsFlow(it) }
|
||||
.launchIn(componentScope)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
|
|
|
|||
|
|
@ -16,20 +16,25 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.toWrappedList
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.domain.card.BackupValidator
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
|
||||
import com.tangem.domain.wallets.usecase.ClearHotWalletContextualUnlockUseCase
|
||||
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
|
||||
import com.tangem.features.hotwallet.UpgradeWalletComponent
|
||||
import com.tangem.features.hotwallet.upgradewallet.entity.UpgradeWalletUM
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.sdk.extensions.localizedDescriptionRes
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.DELAY_SDK_DIALOG_CLOSE
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
|
@ -50,9 +55,13 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
private val clearHotWalletContextualUnlockUseCase: ClearHotWalletContextualUnlockUseCase,
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
|
||||
) : Model() {
|
||||
private val params = paramsContainer.require<UpgradeWalletComponent.Params>()
|
||||
|
||||
val resetCardsComponentCallbacks = ResetCardsModelCallbacks()
|
||||
val startResetCardsFlow = MutableSharedFlow<UserWallet.Cold>()
|
||||
|
||||
internal val uiState: StateFlow<UpgradeWalletUM>
|
||||
field = MutableStateFlow(
|
||||
UpgradeWalletUM(
|
||||
|
|
@ -89,6 +98,13 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
tangemSdkManager
|
||||
.scanProduct()
|
||||
.doOnSuccess {
|
||||
// Check if user attempted to upgrade before but something went wrong and a full reset is required
|
||||
val userWallet = coldUserWalletBuilderFactory.create(it).build()
|
||||
if (userWallet?.walletId == params.userWalletId && BackupValidator.isValidFull(it.card).not()) {
|
||||
startResetCardsFlow.emit(userWallet)
|
||||
return@doOnSuccess
|
||||
}
|
||||
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
tangemSdkManager.changeDisplayedCardIdNumbersCount(it)
|
||||
navigateToUpgradeFlow(it)
|
||||
|
|
@ -143,4 +159,14 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
inner class ResetCardsModelCallbacks : ResetCardsComponent.ModelCallbacks {
|
||||
override fun onCancel() {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.features.onboarding.v2.util
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
||||
interface ResetCardsComponent {
|
||||
|
||||
fun startResetCardsFlow(createdUserWallet: UserWallet.Cold)
|
||||
|
||||
data class Params(
|
||||
val callbacks: ModelCallbacks,
|
||||
)
|
||||
|
||||
interface ModelCallbacks {
|
||||
fun onCancel()
|
||||
fun onComplete()
|
||||
}
|
||||
|
||||
interface Factory : ComponentFactory<Params, ResetCardsComponent>
|
||||
}
|
||||
|
|
@ -95,6 +95,7 @@ internal class OnboardingEntryModel @Inject constructor(
|
|||
withSeedPhraseFlow = scanResponse.productType != ProductType.Wallet,
|
||||
titleProvider = titleProvider,
|
||||
onDone = ::onMultiWalletOnboardingDone,
|
||||
onForceExit = ::popOrExitComponentScreen,
|
||||
mode = multiWalletNavigationMode,
|
||||
)
|
||||
}
|
||||
|
|
@ -204,6 +205,14 @@ internal class OnboardingEntryModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun popOrExitComponentScreen() {
|
||||
router.pop(onComplete = { success ->
|
||||
if (!success) {
|
||||
exitComponentScreen()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun exitComponentScreen() {
|
||||
// new flow
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ internal class OnboardingChildFactory @Inject constructor(
|
|||
withSeedPhraseFlow = route.withSeedPhraseFlow,
|
||||
titleProvider = route.titleProvider,
|
||||
onDone = route.onDone,
|
||||
onForceExit = route.onForceExit,
|
||||
mode = route.mode,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ sealed class OnboardingRoute : Route {
|
|||
val withSeedPhraseFlow: Boolean,
|
||||
val mode: OnboardingMultiWalletComponent.Mode,
|
||||
val onDone: (UserWallet.Cold) -> Unit,
|
||||
val onForceExit: () -> Unit,
|
||||
) : OnboardingRoute()
|
||||
|
||||
data class Visa(
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ interface OnboardingMultiWalletComponent : ComposableContentComponent, InnerNavi
|
|||
val withSeedPhraseFlow: Boolean,
|
||||
val mode: Mode,
|
||||
val onDone: (UserWallet.Cold) -> Unit,
|
||||
val onForceExit: () -> Unit,
|
||||
)
|
||||
|
||||
sealed class Mode {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiW
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.Step.*
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.OnboardingMultiWallet
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.WalletArtworksState
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -51,6 +52,7 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
|||
@Assisted private val context: AppComponentContext,
|
||||
@Assisted private val params: OnboardingMultiWalletComponent.Params,
|
||||
private val analyticsHandler: AnalyticsEventHandler,
|
||||
private val resetCardsComponentFactory: ResetCardsComponent.Factory,
|
||||
) : OnboardingMultiWalletComponent, AppComponentContext by context {
|
||||
|
||||
private val model: OnboardingMultiWalletModel = getOrCreateModel(params)
|
||||
|
|
@ -178,6 +180,7 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
|||
)
|
||||
Finalize -> MultiWalletFinalizeComponent(
|
||||
context = childContext,
|
||||
resetCardsComponentFactory = resetCardsComponentFactory,
|
||||
params = childParams,
|
||||
backButtonClickFlow = backButtonClickFlow,
|
||||
onBack = { model.onBack() },
|
||||
|
|
@ -249,6 +252,9 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
|||
MultiWalletFinalizeComponent.Event.ThreeBackupCardsAdded -> {
|
||||
handleNavigationEvent(Done)
|
||||
}
|
||||
MultiWalletFinalizeComponent.Event.ExitFromFlow -> {
|
||||
params.onForceExit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.child
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
|
|
@ -13,13 +14,17 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChild
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model.MultiWalletFinalizeModel
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui.MultiWalletFinalize
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class MultiWalletFinalizeComponent(
|
||||
context: AppComponentContext,
|
||||
resetCardsComponentFactory: ResetCardsComponent.Factory,
|
||||
params: MultiWalletChildParams,
|
||||
backButtonClickFlow: SharedFlow<Unit>,
|
||||
onBack: () -> Unit,
|
||||
|
|
@ -28,6 +33,13 @@ internal class MultiWalletFinalizeComponent(
|
|||
|
||||
private val model: MultiWalletFinalizeModel = getOrCreateModel(params)
|
||||
|
||||
private val resetCardsComponent = resetCardsComponentFactory.create(
|
||||
context = child("ResetCardsComponent"),
|
||||
params = ResetCardsComponent.Params(
|
||||
callbacks = model.resetCardsModelCallbacks,
|
||||
),
|
||||
)
|
||||
|
||||
init {
|
||||
params.innerNavigation.update {
|
||||
it.copy(
|
||||
|
|
@ -51,6 +63,10 @@ internal class MultiWalletFinalizeComponent(
|
|||
componentScope.launch {
|
||||
model.onBackFlow.collect { onBack() }
|
||||
}
|
||||
|
||||
model.startFullResetFlow
|
||||
.onEach { resetCardsComponent.startResetCardsFlow(it) }
|
||||
.launchIn(componentScope)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -66,6 +82,6 @@ internal class MultiWalletFinalizeComponent(
|
|||
}
|
||||
|
||||
enum class Event {
|
||||
OneBackupCardAdded, TwoBackupCardsAdded, ThreeBackupCardsAdded
|
||||
OneBackupCardAdded, TwoBackupCardsAdded, ThreeBackupCardsAdded, ExitFromFlow
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.MultiWa
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui.state.MultiWalletFinalizeUM
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.resetCardDialog
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.FinalizeStage.*
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.BackupServiceHolder
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
|
|
@ -62,6 +63,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
private val onboardingRepository: OnboardingRepository,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val backupValidator: BackupValidator,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<MultiWalletChildParams>()
|
||||
|
|
@ -76,6 +78,8 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
val uiState = _uiState.asStateFlow()
|
||||
val onBackFlow = MutableSharedFlow<Unit>()
|
||||
val onEvent = MutableSharedFlow<MultiWalletFinalizeComponent.Event>()
|
||||
val resetCardsModelCallbacks = ResetCardsModelCallbacks()
|
||||
val startFullResetFlow = MutableSharedFlow<UserWallet.Cold>()
|
||||
|
||||
init {
|
||||
modelScope.launch {
|
||||
|
|
@ -231,9 +235,21 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
|
||||
private fun finishBackup() {
|
||||
modelScope.launch {
|
||||
setLoading(true)
|
||||
val scanResponse = params.multiWalletState.value.currentScanResponse
|
||||
val userWalletCreated = createUserWallet(scanResponse)
|
||||
|
||||
// Validate wallet before saving
|
||||
// If something went wrong - start full reset flow
|
||||
if (walletHasBackupError || !backupValidator.isValidFull(scanResponse.card)) {
|
||||
startFullResetFlow.emit(
|
||||
userWalletCreated.copy(
|
||||
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
||||
),
|
||||
)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val userWallet = when (params.parentParams.mode) {
|
||||
OnboardingMultiWalletComponent.Mode.Onboarding,
|
||||
OnboardingMultiWalletComponent.Mode.ContinueFinalize,
|
||||
|
|
@ -359,4 +375,25 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
val mask = "$space*$space*$space*$space"
|
||||
return mask + last4
|
||||
}
|
||||
|
||||
private fun setLoading(isLoading: Boolean) {
|
||||
_uiState.update { it.copy(isButtonLoading = isLoading) }
|
||||
}
|
||||
|
||||
inner class ResetCardsModelCallbacks : ResetCardsComponent.ModelCallbacks {
|
||||
|
||||
override fun onCancel() {
|
||||
modelScope.launch {
|
||||
onEvent.emit(MultiWalletFinalizeComponent.Event.ExitFromFlow)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
modelScope.launch {
|
||||
onboardingRepository.clearUnfinishedFinalizeOnboarding()
|
||||
backupServiceHolder.backupService.get()?.discardSavedBackup()
|
||||
onEvent.emit(MultiWalletFinalizeComponent.Event.ExitFromFlow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,7 @@ internal fun MultiWalletFinalize(state: MultiWalletFinalizeUM, modifier: Modifie
|
|||
text = stringResourceSafe(
|
||||
if (state.isRing) R.string.onboarding_button_backup_ring else R.string.onboarding_button_backup_origin,
|
||||
),
|
||||
showProgress = state.isButtonLoading,
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
onClick = state.onScanClick,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.features.onboarding.v2.common.ui.OnboardingDialogUM
|
|||
|
||||
internal data class MultiWalletFinalizeUM(
|
||||
val step: Step = Step.Primary,
|
||||
val isButtonLoading: Boolean = false,
|
||||
val isRing: Boolean = false,
|
||||
val scanPrimary: Boolean = true,
|
||||
val cardNumber: String = "",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package com.tangem.features.onboarding.v2.util.impl
|
||||
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import com.tangem.features.onboarding.v2.util.impl.model.ResetCardsModel
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultResetCardsComponent @AssistedInject constructor(
|
||||
@Assisted context: AppComponentContext,
|
||||
@Assisted params: ResetCardsComponent.Params,
|
||||
) : ResetCardsComponent, AppComponentContext by context {
|
||||
|
||||
private val model: ResetCardsModel = getOrCreateModel(params)
|
||||
|
||||
override fun startResetCardsFlow(createdUserWallet: UserWallet.Cold) {
|
||||
model.startResetCardsFlow(createdUserWallet)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : ResetCardsComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: ResetCardsComponent.Params,
|
||||
): DefaultResetCardsComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.features.onboarding.v2.util.impl.di
|
||||
|
||||
import com.tangem.core.decompose.di.ModelComponent
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import com.tangem.features.onboarding.v2.util.impl.DefaultResetCardsComponent
|
||||
import com.tangem.features.onboarding.v2.util.impl.model.ResetCardsModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface ComponentModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindResetCardsComponent(factory: DefaultResetCardsComponent.Factory): ResetCardsComponent.Factory
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(ModelComponent::class)
|
||||
internal interface ModelModule {
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(ResetCardsModel::class)
|
||||
fun provideModel(model: ResetCardsModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
package com.tangem.features.onboarding.v2.util.impl.model
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
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.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.domain.card.common.util.getBackupCardsCount
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import com.tangem.features.onboarding.v2.util.ResetCardsComponent
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
@ModelScoped
|
||||
internal class ResetCardsModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<ResetCardsComponent.Params>()
|
||||
private val callbacks = params.callbacks
|
||||
private val jobHolder = JobHolder()
|
||||
|
||||
fun startResetCardsFlow(wallet: UserWallet.Cold) {
|
||||
modelScope.launch {
|
||||
startFullResetFlow(wallet)
|
||||
}.saveIn(jobHolder)
|
||||
}
|
||||
|
||||
private suspend fun startFullResetFlow(createdUserWallet: UserWallet.Cold) {
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
uiMessageSender.send(
|
||||
DialogMessage.invoke(
|
||||
title = resourceReference(R.string.reset_cards_dialog_first_title),
|
||||
isDismissable = false,
|
||||
message = resourceReference(R.string.reset_cards_dialog_first_description),
|
||||
firstActionBuilder = {
|
||||
cancelAction {
|
||||
callbacks.onCancel()
|
||||
onDismissRequest()
|
||||
continuation.resume(Unit)
|
||||
}
|
||||
},
|
||||
secondActionBuilder = {
|
||||
EventMessageAction(
|
||||
title = resourceReference(R.string.card_settings_action_sheet_reset),
|
||||
isWarning = true,
|
||||
onClick = {
|
||||
modelScope.launch {
|
||||
repeatUntilTrue { resetPrimaryCard(createdUserWallet) }
|
||||
continuation.resume(Unit)
|
||||
onDismissRequest()
|
||||
startResetBackupCardsFlow(createdUserWallet)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
onDismissRequest = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun startResetBackupCardsFlow(createdUserWallet: UserWallet.Cold) {
|
||||
val backupCardsCount = createdUserWallet.scanResponse.getBackupCardsCount() ?: 0
|
||||
|
||||
if (backupCardsCount == 0) {
|
||||
completeResetFlow()
|
||||
return
|
||||
}
|
||||
|
||||
repeat(backupCardsCount) { index ->
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
uiMessageSender.send(
|
||||
DialogMessage.invoke(
|
||||
title = resourceReference(R.string.card_settings_continue_reset_alert_title),
|
||||
isDismissable = false,
|
||||
message = resourceReference(R.string.reset_cards_dialog_next_device_description),
|
||||
firstActionBuilder = {
|
||||
cancelAction {
|
||||
callbacks.onCancel()
|
||||
onDismissRequest()
|
||||
continuation.resume(Unit)
|
||||
}
|
||||
},
|
||||
secondActionBuilder = {
|
||||
EventMessageAction(
|
||||
title = resourceReference(R.string.card_settings_action_sheet_reset),
|
||||
isWarning = true,
|
||||
onClick = {
|
||||
modelScope.launch {
|
||||
repeatUntilTrue { resetBackupCard(index + 1, createdUserWallet.walletId) }
|
||||
onDismissRequest()
|
||||
if (index == backupCardsCount - 1) {
|
||||
completeResetFlow()
|
||||
}
|
||||
continuation.resume(Unit)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
onDismissRequest = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun completeResetFlow() {
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
uiMessageSender.send(
|
||||
DialogMessage.invoke(
|
||||
title = resourceReference(R.string.card_settings_completed_reset_alert_title),
|
||||
isDismissable = false,
|
||||
message = resourceReference(R.string.reset_cards_dialog_complete_description),
|
||||
firstActionBuilder = {
|
||||
EventMessageAction(
|
||||
title = resourceReference(R.string.common_done),
|
||||
onClick = {
|
||||
modelScope.launch {
|
||||
onDismissRequest()
|
||||
callbacks.onComplete()
|
||||
continuation.resume(Unit)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
onDismissRequest = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun resetPrimaryCard(createdUserWallet: UserWallet.Cold): Boolean {
|
||||
val scanResponse = createdUserWallet.scanResponse
|
||||
|
||||
val result = tangemSdkManager.resetToFactorySettings(
|
||||
cardId = scanResponse.card.cardId,
|
||||
allowsRequestAccessCodeFromRepository = true,
|
||||
)
|
||||
|
||||
return when (result) {
|
||||
is CompletionResult.Failure -> false
|
||||
is CompletionResult.Success -> true
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun resetBackupCard(cardIndex: Int, userWalletId: UserWalletId): Boolean {
|
||||
val result = tangemSdkManager.resetBackupCard(cardIndex, userWalletId)
|
||||
return when (result) {
|
||||
is CompletionResult.Failure -> false
|
||||
is CompletionResult.Success -> true
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun repeatUntilTrue(action: () -> Boolean) {
|
||||
while (true) {
|
||||
if (action()) break
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue