From 7d017162cbc1409d365ed4f66c872b14444cb816 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 26 Nov 2024 09:21:35 +0300 Subject: [PATCH] Updated on 2026-08-14 --- features/onboarding-v2/impl/build.gradle.kts | 3 + .../impl/DefaultOnboardingEntryComponent.kt | 13 +- .../entry/impl/model/OnboardingEntryModel.kt | 24 +- .../impl/routing/OnboardingChildFactory.kt | 11 + .../v2/entry/impl/routing/OnboardingRoute.kt | 6 + .../v2/entry/impl/ui/OnboardingEntry.kt | 6 + .../api/OnboardingMultiWalletComponent.kt | 2 + .../DefaultOnboardingMultiWalletComponent.kt | 75 +++-- .../model/MultiWalletAccessCodeModel.kt | 6 + .../impl/child/backup/model/BackupState.kt | 44 +-- .../backup/model/MultiWalletBackupModel.kt | 22 +- .../finalize/MultiWalletFinalizeComponent.kt | 31 ++- .../child/finalize/model/BackupValidator.kt | 47 ++++ .../model/MultiWalletFinalizeModel.kt | 257 ++++++++++++++++++ .../finalize/state/MultiWalletFinalizeUM.kt | 10 - .../child/finalize/ui/MultiWalletFinalize.kt | 78 +++++- .../ui/state/MultiWalletFinalizeUM.kt | 16 ++ .../v2/multiwallet/impl/di/ComponentModule.kt | 6 + .../impl/model/OnboardingMultiWalletModel.kt | 2 + .../impl/model/OnboardingMultiWalletState.kt | 3 + .../v2/multiwallet/impl/model/Utils.kt | 2 +- .../impl/DefaultOnboardingStepperComponent.kt | 1 + 22 files changed, 554 insertions(+), 111 deletions(-) create mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/BackupValidator.kt create mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt delete mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/state/MultiWalletFinalizeUM.kt create mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/state/MultiWalletFinalizeUM.kt diff --git a/features/onboarding-v2/impl/build.gradle.kts b/features/onboarding-v2/impl/build.gradle.kts index 5e2dc1d547..2dfbd823dd 100644 --- a/features/onboarding-v2/impl/build.gradle.kts +++ b/features/onboarding-v2/impl/build.gradle.kts @@ -14,6 +14,7 @@ android { dependencies { /** Api */ implementation(projects.features.onboardingV2.api) + implementation(projects.features.manageTokens.api) /** Core modules */ implementation(projects.core.featuretoggles) @@ -34,6 +35,8 @@ dependencies { implementation(projects.domain.core) implementation(projects.domain.card) implementation(projects.domain.wallets) + implementation(projects.domain.wallets.models) + implementation(projects.domain.legacy) /** Tangem libraries */ implementation(projects.libs.tangemSdkApi) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/DefaultOnboardingEntryComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/DefaultOnboardingEntryComponent.kt index 623f315db0..1f95e64368 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/DefaultOnboardingEntryComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/DefaultOnboardingEntryComponent.kt @@ -4,10 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import com.arkivanov.decompose.extensions.compose.jetpack.subscribeAsState -import com.arkivanov.decompose.router.stack.ChildStack -import com.arkivanov.decompose.router.stack.StackNavigation -import com.arkivanov.decompose.router.stack.childStack -import com.arkivanov.decompose.router.stack.pop +import com.arkivanov.decompose.router.stack.* import com.arkivanov.decompose.value.Value import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.child @@ -51,20 +48,18 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor( popBack = { popInternal { success -> if (success.not()) { - stackNavigation.pop() + model.stackNavigation.pop() // TODO } } }, ), ) - private val stackNavigation = StackNavigation() - private val innerStack: Value> = childStack( key = "innerStack", - source = stackNavigation, + source = model.stackNavigation, serializer = null, - initialConfiguration = model.state.value.currentRoute, + initialConfiguration = model.startRoute, handleBackButton = true, childFactory = { configuration, factoryContext -> onboardingChildFactory.createChild( diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt index 07053a7b9e..776e55fd86 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/model/OnboardingEntryModel.kt @@ -1,5 +1,7 @@ package com.tangem.features.onboarding.v2.entry.impl.model +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.navigate import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer @@ -7,9 +9,9 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.models.scan.ProductType import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.onboarding.v2.TitleProvider import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent -import com.tangem.features.onboarding.v2.entry.impl.model.state.OnboardingState import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow @@ -23,6 +25,7 @@ internal class OnboardingEntryModel @Inject constructor( private val params = paramsContainer.require() + val stackNavigation = StackNavigation() val titleProvider = object : TitleProvider { override val currentTitle = MutableStateFlow(stringReference("")) override fun changeTitle(text: TextReference) { @@ -30,11 +33,7 @@ internal class OnboardingEntryModel @Inject constructor( } } - val state = MutableStateFlow( - OnboardingState( - currentRoute = routeByProductType(params.scanResponse), - ), - ) + val startRoute = routeByProductType(params.scanResponse) private fun routeByProductType(scanResponse: ScanResponse): OnboardingRoute { return when (scanResponse.productType) { @@ -44,15 +43,24 @@ internal class OnboardingEntryModel @Inject constructor( scanResponse = scanResponse, withSeedPhraseFlow = false, titleProvider = titleProvider, + onDone = ::onMultiWalletOnboardingDone, ) - ProductType.Wallet2 -> OnboardingRoute.MultiWallet( + ProductType.Ring, + ProductType.Wallet2, + -> OnboardingRoute.MultiWallet( scanResponse = scanResponse, withSeedPhraseFlow = true, titleProvider = titleProvider, + onDone = ::onMultiWalletOnboardingDone, ) ProductType.Start2Coin -> TODO() - ProductType.Ring -> TODO() ProductType.Visa -> TODO() } } + + private fun onMultiWalletOnboardingDone(userWallet: UserWallet) { + stackNavigation.navigate { + listOf(OnboardingRoute.ManageTokens(userWallet)) + } + } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingChildFactory.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingChildFactory.kt index e25190780d..f9586e679c 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingChildFactory.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingChildFactory.kt @@ -1,11 +1,14 @@ package com.tangem.features.onboarding.v2.entry.impl.routing import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.features.managetokens.component.ManageTokensComponent +import com.tangem.features.managetokens.component.ManageTokensSource import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent import javax.inject.Inject internal class OnboardingChildFactory @Inject constructor( private val multiWalletComponentFactory: OnboardingMultiWalletComponent.Factory, + private val manageTokensComponentFactory: ManageTokensComponent.Factory, ) { fun createChild(route: OnboardingRoute, childContext: AppComponentContext): Any { @@ -16,6 +19,14 @@ internal class OnboardingChildFactory @Inject constructor( scanResponse = route.scanResponse, withSeedPhraseFlow = route.withSeedPhraseFlow, titleProvider = route.titleProvider, + onDone = route.onDone, + ), + ) + is OnboardingRoute.ManageTokens -> manageTokensComponentFactory.create( // TODO replace with wrapper + context = childContext, + params = ManageTokensComponent.Params( + userWalletId = route.userWallet.walletId, + source = ManageTokensSource.ONBOARDING, ), ) else -> Unit diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingRoute.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingRoute.kt index b315398e7c..3c611e4dc2 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingRoute.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/routing/OnboardingRoute.kt @@ -2,6 +2,7 @@ package com.tangem.features.onboarding.v2.entry.impl.routing import com.tangem.core.decompose.navigation.Route import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.onboarding.v2.TitleProvider sealed class OnboardingRoute : Route { @@ -12,5 +13,10 @@ sealed class OnboardingRoute : Route { val titleProvider: TitleProvider, val scanResponse: ScanResponse, val withSeedPhraseFlow: Boolean, + val onDone: (UserWallet) -> Unit, + ) : OnboardingRoute() + + data class ManageTokens( + val userWallet: UserWallet, ) : OnboardingRoute() } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/ui/OnboardingEntry.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/ui/OnboardingEntry.kt index 37d5e6acd7..c0a06cbe51 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/ui/OnboardingEntry.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/entry/impl/ui/OnboardingEntry.kt @@ -8,6 +8,7 @@ import com.arkivanov.decompose.extensions.compose.jetpack.stack.Children import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.slide import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.stackAnimation import com.arkivanov.decompose.router.stack.ChildStack +import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.res.TangemTheme import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent @@ -36,6 +37,11 @@ internal inline fun OnboardingEntry( modifier = modifier, ) } + is OnboardingRoute.ManageTokens -> { + (it.instance as ComposableContentComponent).Content( + modifier = modifier, + ) + } OnboardingRoute.None -> {} } } diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/api/OnboardingMultiWalletComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/api/OnboardingMultiWalletComponent.kt index 1dedfd3d41..32ce1ba533 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/api/OnboardingMultiWalletComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/api/OnboardingMultiWalletComponent.kt @@ -4,6 +4,7 @@ import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.decompose.navigation.inner.InnerNavigationHolder import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.onboarding.v2.TitleProvider interface OnboardingMultiWalletComponent : ComposableContentComponent, InnerNavigationHolder { @@ -12,6 +13,7 @@ interface OnboardingMultiWalletComponent : ComposableContentComponent, InnerNavi val titleProvider: TitleProvider, val scanResponse: ScanResponse, val withSeedPhraseFlow: Boolean, + val onDone: (UserWallet) -> Unit, ) interface Factory : ComponentFactory diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt index 5c03bc099f..13ce5f806a 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt @@ -22,13 +22,14 @@ import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.decompose.navigation.inner.InnerNavigation import com.tangem.core.decompose.navigation.inner.InnerNavigationState +import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent -import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams import com.tangem.features.onboarding.v2.multiwallet.impl.child.accesscode.MultiWalletAccessCodeComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWalletBackupComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.chooseoption.Wallet1ChooseOptionComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.MultiWalletCreateWalletComponent +import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.MultiWalletFinalizeComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.MultiWalletSeedPhraseComponent import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState @@ -77,7 +78,7 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor } } - private val childStack: Value> = + private val childStack: Value> = childStack( key = "innerStack", source = stackNavigation, @@ -109,26 +110,23 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor init { componentScope.launch { // access code bs result + // TODO delete and use callback childParams.multiWalletState .map { it.accessCode } .distinctUntilChanged() .filter { it != null } .collectLatest { handleNavigationEvent(Finalize) } } - bottomSheetNavigation.navigate {} } private fun createChild( step: OnboardingMultiWalletState.Step, childContext: AppComponentContext, - ): MultiWalletChildComponent { + ): ComposableContentComponent { return when (step) { CreateWallet -> MultiWalletCreateWalletComponent( context = childContext, - params = MultiWalletChildParams( - multiWalletState = model.state, - parentParams = params, - ), + params = childParams, onNextStep = ::handleNavigationEvent, ) ChooseBackupOption -> Wallet1ChooseOptionComponent( @@ -137,23 +135,21 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor ) SeedPhrase -> MultiWalletSeedPhraseComponent( context = childContext, - params = MultiWalletChildParams( - multiWalletState = model.state, - parentParams = params, - ), + params = childParams, onNextStep = ::handleNavigationEvent, - backButtonClickFlow = MutableSharedFlow(), + backButtonClickFlow = MutableSharedFlow(), // TODO ) AddBackupDevice -> MultiWalletBackupComponent( context = childContext, - params = MultiWalletChildParams( - multiWalletState = model.state, - parentParams = params, - ), + params = childParams, onEvent = ::handleBackupComponentEvent, ) - Finalize -> TODO() - Done -> TODO() + Finalize -> MultiWalletFinalizeComponent( + context = childContext, + params = childParams, + onEvent = ::handleFinalizeComponentEvent, + ) + Done -> error("Unexpected Done state") } } @@ -162,15 +158,17 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor ChooseBackupOption -> { artworksState.value = WalletArtworksState.Fan } - SeedPhrase -> {} AddBackupDevice -> { artworksState.value = WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.First) } Finalize -> { - artworksState.value = WalletArtworksState.Stack() + artworksState.value = WalletArtworksState.Stack(threeCards = model.state.value.isThreeCards) } Done -> { - // TODO + // final step - navigate to parent + val userWallet = childParams.multiWalletState.value.resultUserWallet ?: return + params.onDone(userWallet) + return } else -> return } @@ -179,19 +177,44 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor private fun handleBackupComponentEvent(event: MultiWalletBackupComponent.Event) { when (event) { - MultiWalletBackupComponent.Event.Done -> { - artworksState.value = WalletArtworksState.Stack() - bottomSheetNavigation.navigate { } - } MultiWalletBackupComponent.Event.OneDeviceAdded -> { artworksState.value = WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.Second) } MultiWalletBackupComponent.Event.TwoDeviceAdded -> { artworksState.value = WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.Third) } + MultiWalletBackupComponent.Event.Done -> { + openAccessCodeBottomSheet() + } } } + private fun handleFinalizeComponentEvent(event: MultiWalletFinalizeComponent.Event) { + when (event) { + MultiWalletFinalizeComponent.Event.OneBackupCardAdded -> { + artworksState.value = WalletArtworksState.Leapfrog( + threeCards = model.state.value.isThreeCards, + step = WalletArtworksState.Leapfrog.Step.Second, + ) + } + MultiWalletFinalizeComponent.Event.TwoBackupCardsAdded -> { + if (model.state.value.isThreeCards) { + artworksState.value = WalletArtworksState.Leapfrog( + threeCards = model.state.value.isThreeCards, + step = WalletArtworksState.Leapfrog.Step.Third, + ) + } else { + handleNavigationEvent(Done) + } + } + MultiWalletFinalizeComponent.Event.ThreeBackupCardsAdded -> { + handleNavigationEvent(Done) + } + } + } + + private fun openAccessCodeBottomSheet() { bottomSheetNavigation.navigate { } } + @OptIn(FaultyDecomposeApi::class) @Composable override fun Content(modifier: Modifier) { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt index 2a5fc261bb..5d301c7325 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/accesscode/model/MultiWalletAccessCodeModel.kt @@ -7,6 +7,7 @@ import com.tangem.core.decompose.model.ParamsContainer import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams import com.tangem.features.onboarding.v2.multiwallet.impl.child.accesscode.ui.state.MultiWalletAccessCodeUM import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState +import com.tangem.sdk.api.BackupServiceHolder import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -21,6 +22,7 @@ private const val MINIMUM_ACCESS_CODE_LENGTH = 4 internal class MultiWalletAccessCodeModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, + private val backupServiceHolder: BackupServiceHolder, ) : Model() { private val _uiState = MutableStateFlow(getInitialState()) @@ -112,6 +114,10 @@ internal class MultiWalletAccessCodeModel @Inject constructor( } MultiWalletAccessCodeUM.Step.ConfirmAccessCode -> { if (checkAccessCode()) { + backupServiceHolder.backupService.get()?.setAccessCode(_uiState.value.accessCodeFirst.text) + + // TODO delete access code from state + // make on done params.multiWalletState.update { it.copy(accessCode = OnboardingMultiWalletState.AccessCode(uiState.value.accessCodeFirst.text)) } diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/BackupState.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/BackupState.kt index b1fd1a646c..a87d14ae12 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/BackupState.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/BackupState.kt @@ -1,48 +1,6 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model -import android.graphics.Bitmap -import com.tangem.common.card.Card - // TODO maybe delete some fields in the future data class BackupState( - val primaryCardId: String? = null, - val primaryCardBatchId: String? = null, val backupCardsNumber: Int = 0, - val backupCards: List = emptyList(), - val backupCardIds: List = emptyList(), - val backupCardBatchIds: List = emptyList(), - @Transient - val backupCardsArtworks: Map = emptyMap(), - val accessCode: String = "", - val accessCodeError: AccessCodeError? = null, - val backupStep: BackupStep? = null, - val maxBackupCards: Int = 2, - val canSkipBackup: Boolean = true, - val isInterruptedBackup: Boolean = false, - val showBtnLoading: Boolean = false, - val hasBackupError: Boolean = false, - val startedSource: BackupStartedSource = BackupStartedSource.Onboarding, - val hasRing: Boolean = false, -) - -enum class BackupStartedSource { - Onboarding, CreateBackup -} - -enum class AccessCodeError { - CodeTooShort, CodesDoNotMatch -} - -typealias CardId = String - -sealed class BackupStep { - data object InitBackup : BackupStep() - data object ScanOriginCard : BackupStep() - data object AddBackupCards : BackupStep() - data object SetAccessCode : BackupStep() - data object EnterAccessCode : BackupStep() - data object ReenterAccessCode : BackupStep() - data object WritePrimaryCard : BackupStep() - data class WriteBackupCard(val cardNumber: Int) : BackupStep() - data object Finished : BackupStep() -} \ No newline at end of file +) \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt index 59ea93d2be..1528ccd94d 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt @@ -67,7 +67,7 @@ class MultiWalletBackupModel @Inject constructor( addBackupButtonEnabled = true, addBackupButtonLoading = false, onAddBackupClick = ::startBackupWallet, - onFinalizeButtonClick = {}, + onFinalizeButtonClick = ::onFinalizeClick, onSkipButtonClick = { // eventFlow.tryEmit(Unit) }, @@ -80,7 +80,9 @@ class MultiWalletBackupModel @Inject constructor( } private fun startBackupWallet() { - backupService.discardSavedBackup() + if (state.value.backupCardsNumber == 0) { + backupService.discardSavedBackup() + } val primaryCard = scanResponse.primaryCard if (primaryCard != null) { @@ -107,6 +109,7 @@ class MultiWalletBackupModel @Inject constructor( modelScope.launch { eventFlow.emit(MultiWalletBackupComponent.Event.OneDeviceAdded) } + params.multiWalletState.update { it.copy(isThreeCards = false) } st.copy( title = resourceReference(R.string.onboarding_title_one_backup_card), bodyText = resourceReference(R.string.onboarding_subtitle_one_backup_card), @@ -118,6 +121,7 @@ class MultiWalletBackupModel @Inject constructor( modelScope.launch { eventFlow.emit(MultiWalletBackupComponent.Event.TwoDeviceAdded) } + params.multiWalletState.update { it.copy(isThreeCards = true) } st.copy( title = resourceReference(R.string.onboarding_title_two_backup_cards), bodyText = resourceReference(R.string.onboarding_subtitle_two_backup_cards), @@ -130,6 +134,19 @@ class MultiWalletBackupModel @Inject constructor( } } + private fun onFinalizeClick() { + when (state.value.backupCardsNumber) { + 1 -> { + // TODO show dialog + params.multiWalletState.update { it.copy(isThreeCards = false) } + } + 2 -> { + params.multiWalletState.update { it.copy(isThreeCards = true) } + } + } + modelScope.launch { eventFlow.emit(MultiWalletBackupComponent.Event.Done) } + } + private fun addBackupCardWithService() { _uiState.update { st -> st.copy(addBackupButtonLoading = true) @@ -147,7 +164,6 @@ class MultiWalletBackupModel @Inject constructor( is CompletionResult.Success -> { state.update { it.copy( - backupCards = it.backupCards + result.data, backupCardsNumber = it.backupCardsNumber + 1, ) } diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/MultiWalletFinalizeComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/MultiWalletFinalizeComponent.kt index 17fbfe3699..a28e590923 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/MultiWalletFinalizeComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/MultiWalletFinalizeComponent.kt @@ -1,22 +1,45 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize import androidx.compose.runtime.Composable +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.model.getOrCreateModel import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams -import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState -import kotlinx.coroutines.flow.SharedFlow +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 kotlinx.coroutines.launch @Suppress("UnusedPrivateMember") internal class MultiWalletFinalizeComponent( context: AppComponentContext, params: MultiWalletChildParams, - onNextStep: (OnboardingMultiWalletState.Step) -> Unit, - backButtonClickFlow: SharedFlow, + onEvent: (Event) -> Unit, ) : AppComponentContext by context, MultiWalletChildComponent { + private val model: MultiWalletFinalizeModel = getOrCreateModel(params) + + init { + componentScope.launch { + model.onEvent.collect { + onEvent(it) + } + } + } + @Composable override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + + MultiWalletFinalize( + state = state, + modifier = modifier, + ) + } + + enum class Event { + OneBackupCardAdded, TwoBackupCardsAdded, ThreeBackupCardsAdded } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/BackupValidator.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/BackupValidator.kt new file mode 100644 index 0000000000..1b59b2922d --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/BackupValidator.kt @@ -0,0 +1,47 @@ +package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model + +import com.tangem.common.card.EllipticCurve +import com.tangem.domain.common.configs.CardConfig +import com.tangem.domain.models.scan.CardDTO +import javax.inject.Inject + +class BackupValidator @Inject constructor() { + + fun isValidFull(cardDTO: CardDTO): Boolean { + return validateBackupStatus(cardDTO) && validateCurves(cardDTO) + } + + fun isValidBackupStatus(cardDTO: CardDTO): Boolean { + return validateBackupStatus(cardDTO) + } + + private fun validateCurves(cardDTO: CardDTO): Boolean { + val config = CardConfig.createConfig(cardDTO) + // / Since the curve `bls12381_G2_AUG` was added later into first generation of wallets, + // we cannot determine whether this curve is missing due to an error or because the user + // did not want to recreate the wallet. + val expectedCurves = config.mandatoryCurves + .filterNot { it == EllipticCurve.Bls12381G2Aug } + val curves = cardDTO.wallets.map { it.curve } + for (expectedCurve in expectedCurves) { + val cardCurvesCount = curves.count { it == expectedCurve } + + // missing curve + if (cardCurvesCount == 0) { + return false + } + + // duplicated curve + if (cardCurvesCount > 1) { + return false + } + } + return true + } + + private fun validateBackupStatus(cardDTO: CardDTO): Boolean { + val backupStatus = cardDTO.backupStatus + backupStatus ?: return true // for card with null backup status, validation should always returns true + return backupStatus !is CardDTO.BackupStatus.CardLinked + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt new file mode 100644 index 0000000000..757a4c8753 --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/MultiWalletFinalizeModel.kt @@ -0,0 +1,257 @@ +package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model + +import com.tangem.common.CompletionResult +import com.tangem.common.core.TangemSdkError +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.domain.card.repository.CardRepository +import com.tangem.domain.feedback.GetCardInfoUseCase +import com.tangem.domain.feedback.SendFeedbackEmailUseCase +import com.tangem.domain.feedback.models.FeedbackEmailType +import com.tangem.domain.models.scan.CardDTO +import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.models.scan.isRing +import com.tangem.domain.wallets.builder.UserWalletBuilder +import com.tangem.domain.wallets.legacy.UserWalletsListManager +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase +import com.tangem.features.onboarding.v2.impl.R +import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams +import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.MultiWalletFinalizeComponent +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.operations.backup.BackupService +import com.tangem.sdk.api.BackupServiceHolder +import com.tangem.sdk.api.TangemSdkManager +import com.tangem.utils.StringsSigns +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@Suppress("LongParameterList") +@ComponentScoped +internal class MultiWalletFinalizeModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, + private val backupServiceHolder: BackupServiceHolder, + private val tangemSdkManager: TangemSdkManager, + private val getCardInfoUseCase: GetCardInfoUseCase, + private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val generateWalletNameUseCase: GenerateWalletNameUseCase, + private val userWalletsListManager: UserWalletsListManager, + private val cardRepository: CardRepository, +) : Model() { + + private val params = paramsContainer.require() + private val multiWalletState get() = params.multiWalletState + private val _uiState = MutableStateFlow( + MultiWalletFinalizeUM( + isRing = backupServiceHolder.backupService.get()?.primaryCardBatchId?.let { isRing(it) } ?: false, + onScanClick = ::onLinkClick, + cardNumber = backupServiceHolder.backupService.get()?.primaryCardId?.lastMasked().orEmpty(), + ), + ) + private val backupCardIds = backupServiceHolder.backupService.get()?.backupCardIds.orEmpty() + private var walletHasBackupError = false + + val uiState = _uiState.asStateFlow() + val onEvent = MutableSharedFlow() + + private fun onLinkClick() { + when (_uiState.value.step) { + MultiWalletFinalizeUM.Step.Primary -> { + writePrimaryCard() + } + MultiWalletFinalizeUM.Step.BackupDevice1 -> { + writeBackupCard(cardIndex = 0) + } + MultiWalletFinalizeUM.Step.BackupDevice2 -> { + writeBackupCard(cardIndex = 1) + } + } + } + + private fun writePrimaryCard() { + val backupService = backupServiceHolder.backupService.get() ?: return + // store.dispatchOnMain(BackupAction.SetHasRing(hasRing = isRing)) + + val primaryCardBatchId = backupService.primaryCardBatchId ?: return + val isRing = isRing(primaryCardBatchId) + val iconScanRes = if (isRing) R.drawable.img_hand_scan_ring else null + + tangemSdkManager.changeProductType(isRing) + backupService.proceedBackup(iconScanRes = iconScanRes) { result -> + when (result) { + is CompletionResult.Success -> { + modelScope.launch { onEvent.emit(MultiWalletFinalizeComponent.Event.OneBackupCardAdded) } + _uiState.update { st -> + st.copy( + step = MultiWalletFinalizeUM.Step.BackupDevice1, + isRing = backupService.backupCardsBatchIds.getOrNull(0)?.let { isRing(it) } ?: false, + scanPrimary = false, + cardNumber = backupService.backupCardIds.firstOrNull()?.lastMasked() ?: "", + ) + } + } + is CompletionResult.Failure -> Unit + } + tangemSdkManager.clearProductType() + } + } + + private fun writeBackupCard(cardIndex: Int) { + val backupService = backupServiceHolder.backupService.get() ?: return + + // store.dispatchOnMain(BackupAction.SetHasRing(hasRing = isRing)) + + val backupCardBatchId = backupService.backupCardsBatchIds.getOrNull(cardIndex) ?: return + val isRing = isRing(backupCardBatchId) + val iconScanRes = if (isRing) R.drawable.img_hand_scan_ring else null + + tangemSdkManager.changeProductType(isRing) + backupService.proceedBackup(iconScanRes = iconScanRes) { result -> + when (result) { + is CompletionResult.Success -> { + val backupValidator = BackupValidator() + if (backupValidator.isValidBackupStatus(CardDTO(result.data)).not()) { + // TODO store.dispatchOnMain(BackupAction.ErrorInBackupCard) + walletHasBackupError = true + } + + if (backupService.currentState == BackupService.State.Finished) { + finishBackup() + } else { + modelScope.launch { onEvent.emit(MultiWalletFinalizeComponent.Event.TwoBackupCardsAdded) } + _uiState.update { st -> + st.copy( + step = MultiWalletFinalizeUM.Step.BackupDevice2, + isRing = backupService.backupCardsBatchIds + .getOrNull(cardIndex + 1)?.let { isRing(it) } ?: false, + cardNumber = backupService.backupCardIds.getOrNull(cardIndex + 1) + ?.lastMasked() ?: "", + ) + } + } + } + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.WalletAlreadyCreated) { + // show should reset dialog + handleActivationError() + } + } + } + + tangemSdkManager.clearProductType() + } + } + + private fun finishBackup() { + // TODO Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber)) + + modelScope.launch { + val scanResponse = params.multiWalletState.value.currentScanResponse + + val userWallet = createUserWallet(scanResponse) + userWalletsListManager.save( + userWallet = userWallet.copy( + scanResponse = scanResponse.updateScanResponseAfterBackup(), + ), + canOverride = true, + ) + + // TODO + // BackupStartedSource.CreateBackup -> updateWallet( + // userWalletsListManager = userWalletsListManager, + // userWallet = userWallet, + // backupState = backupState, + // ) + + // TODO maybe here we should check for backup cards activation status + // if (notActivatedCardIds.isEmpty()) { + // delay(1000) + // store.dispatchWithMain(BackupAction.BackupFinished(userWallet?.walletId)) + // return@launch + // } + // + // Analytics.send(Onboarding.Finished()) + // + // store.state.globalState.onboardingState.onboardingManager?.finishActivation(notActivatedCardIds) + // handleFinishBackup(requireNotNull(scanResponse), userWallet) + // delay(1000) + // store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet?.walletId)) + + cardRepository.finishCardActivation(scanResponse.card.cardId) + + // save user wallet for manage tokens screen + params.multiWalletState.update { + it.copy(resultUserWallet = userWallet) + } + + onEvent.emit(MultiWalletFinalizeComponent.Event.ThreeBackupCardsAdded) + } + } + + private suspend fun createUserWallet(scanResponse: ScanResponse): UserWallet { + return requireNotNull( + value = UserWalletBuilder(scanResponse, generateWalletNameUseCase) + .backupCardsIds(backupCardIds.toSet()) + .hasBackupError(walletHasBackupError) + .build(), + lazyMessage = { "User wallet not created" }, + ) + } + + @Suppress("MagicNumber") + private fun ScanResponse.updateScanResponseAfterBackup(): ScanResponse { + val cardsCount = if (params.multiWalletState.value.isThreeCards) 3 else 2 + + val card = card.copy( + backupStatus = CardDTO.BackupStatus.Active(cardCount = cardsCount), + isAccessCodeSet = true, + ) + return copy(card = card) + } + + private fun handleActivationError() { + _uiState.update { + it.copy( + dialog = resetCardDialog( + onConfirm = ::navigateToSupportScreen, + dismiss = { _uiState.update { it.copy(dialog = null) } }, + onDismissButtonClick = ::resetCard, + ), + ) + } + } + + private fun resetCard() { + val scanResponse = params.parentParams.scanResponse + + modelScope.launch { + tangemSdkManager.resetToFactorySettings( + cardId = scanResponse.card.cardId, + allowsRequestAccessCodeFromRepository = true, + ) + } + } + + private fun navigateToSupportScreen() { + modelScope.launch { + val cardInfo = getCardInfoUseCase(multiWalletState.value.currentScanResponse).getOrNull() ?: return@launch + sendFeedbackEmailUseCase(FeedbackEmailType.DirectUserRequest(cardInfo)) + } + } + + private fun String.lastMasked(): String { + val space = StringsSigns.NON_BREAKING_SPACE + fun String.splitBySpace() = reversed().chunked(size = 4).joinToString(separator = "$space").reversed() + val last4 = takeLast(n = 4).splitBySpace() + val mask = "$space*$space*$space*$space" + return mask + last4 + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/state/MultiWalletFinalizeUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/state/MultiWalletFinalizeUM.kt deleted file mode 100644 index 9029c7c231..0000000000 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/state/MultiWalletFinalizeUM.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.state - -data class MultiWalletFinalizeUM( - val step: Step = Step.Device1, - val cardNumber: String = "", -) { - enum class Step { - Device1, Device2, Device3 - } -} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/MultiWalletFinalize.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/MultiWalletFinalize.kt index e9bbecfa82..6d90886eae 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/MultiWalletFinalize.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/MultiWalletFinalize.kt @@ -1,22 +1,86 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.state.MultiWalletFinalizeUM +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.PrimaryButtonIconEnd +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.onboarding.v2.impl.R +import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui.state.MultiWalletFinalizeUM @Suppress("UnusedPrivateMember") @Composable -fun MultiWalletFinalize(state: MultiWalletFinalizeUM, modifier: Modifier = Modifier) { +internal fun MultiWalletFinalize(state: MultiWalletFinalizeUM, modifier: Modifier = Modifier) { Column( modifier = modifier .fillMaxSize() .navigationBarsPadding(), verticalArrangement = Arrangement.Bottom, ) { - // TODO + Column( + Modifier + .fillMaxWidth() + .padding(start = 32.dp, end = 32.dp, bottom = 74.dp) + .weight(1f), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + modifier = Modifier.padding(top = 16.dp), + text = stringResource( + when { + state.scanPrimary && state.isRing -> R.string.common_origin_ring + state.scanPrimary && state.isRing.not() -> R.string.common_origin_card + state.scanPrimary.not() && state.isRing -> R.string.onboarding_title_backup_ring + else -> R.string.onboarding_title_backup_card + }, + ), + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + style = TangemTheme.typography.h2, + ) + + Text( + modifier = Modifier.padding(top = 12.dp), + text = if (state.isRing) { + stringResource(R.string.onboarding_subtitle_scan_ring) + } else { + stringResource( + R.string.onboarding_subtitle_scan_backup_card_format, + state.cardNumber, + ) + }, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + style = TangemTheme.typography.body1, + ) + } + + PrimaryButtonIconEnd( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + text = stringResource( + if (state.isRing) R.string.onboarding_button_backup_ring else R.string.onboarding_button_backup_origin, + ), + iconResId = R.drawable.ic_tangem_24, + onClick = state.onScanClick, + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun Preview() { + TangemThemePreview { + MultiWalletFinalize( + state = MultiWalletFinalizeUM(), + ) } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/state/MultiWalletFinalizeUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/state/MultiWalletFinalizeUM.kt new file mode 100644 index 0000000000..b367e365b4 --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/ui/state/MultiWalletFinalizeUM.kt @@ -0,0 +1,16 @@ +package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui.state + +import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.OnboardingDialogUM + +internal data class MultiWalletFinalizeUM( + val step: Step = Step.Primary, + val isRing: Boolean = false, + val scanPrimary: Boolean = true, + val cardNumber: String = "", + val onScanClick: () -> Unit = {}, + val dialog: OnboardingDialogUM? = null, +) { + enum class Step { + Primary, BackupDevice1, BackupDevice2 + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt index a1cc040ecf..c34467c438 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/di/ComponentModule.kt @@ -7,6 +7,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.DefaultOnboardingMulti import com.tangem.features.onboarding.v2.multiwallet.impl.child.accesscode.model.MultiWalletAccessCodeModel import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model.MultiWalletBackupModel import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.model.MultiWalletCreateWalletModel +import com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model.MultiWalletFinalizeModel import com.tangem.features.onboarding.v2.multiwallet.impl.child.seedphrase.model.MultiWalletSeedPhraseModel import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel import dagger.Binds @@ -54,4 +55,9 @@ internal interface ModelModule { @IntoMap @ClassKey(MultiWalletAccessCodeModel::class) fun provideModel5(model: MultiWalletAccessCodeModel): Model + + @Binds + @IntoMap + @ClassKey(MultiWalletFinalizeModel::class) + fun provideModel6(model: MultiWalletFinalizeModel): Model } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt index 279cd55454..cfd4d2429a 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt @@ -26,6 +26,8 @@ internal class OnboardingMultiWalletModel @Inject constructor( currentStep = getInitialStep(), currentScanResponse = params.scanResponse, accessCode = null, + isThreeCards = true, + resultUserWallet = null, ), ) diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt index 47833e1a76..22298a74b2 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt @@ -1,11 +1,14 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.model import com.tangem.domain.models.scan.ScanResponse +import com.tangem.domain.wallets.models.UserWallet data class OnboardingMultiWalletState( val currentStep: Step, val accessCode: AccessCode?, + val isThreeCards: Boolean, val currentScanResponse: ScanResponse, + val resultUserWallet: UserWallet?, // TODO make callback instead ) { /** * Wallet1 diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt index 77db1fa129..571ce10b03 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt @@ -12,5 +12,5 @@ fun screenTitleByStep(step: OnboardingMultiWalletState.Step): TextReference = wh OnboardingMultiWalletState.Step.AddBackupDevice -> resourceReference(R.string.onboarding_navbar_title_creating_backup) OnboardingMultiWalletState.Step.Finalize -> TODO() - OnboardingMultiWalletState.Step.Done -> TODO() + OnboardingMultiWalletState.Step.Done -> error("No title for Done step") } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt index 0689f4cb86..65a86ac4d1 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/stepper/impl/DefaultOnboardingStepperComponent.kt @@ -31,6 +31,7 @@ internal class DefaultOnboardingStepperComponent @AssistedInject constructor( init { componentScope.launch { state.collect { + // TODO Timber.tag("ASDASD").d("State: $it") } }