Updated on 2026-08-14
This commit is contained in:
parent
022c4bcfcd
commit
d71d29b72b
30 changed files with 295 additions and 104 deletions
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.feedback.GetCardInfoUseCase
|
|||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.repository.OnboardingRepository
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -119,6 +120,8 @@ interface ApplicationEntryPoint {
|
|||
|
||||
fun getOnboardingV2FeatureToggles(): OnboardingV2FeatureToggles
|
||||
|
||||
fun getOnboardingRepository(): OnboardingRepository
|
||||
|
||||
fun getCoroutineDispatcherProvider(): CoroutineDispatcherProvider
|
||||
|
||||
fun getExcludedBlockchains(): ExcludedBlockchains
|
||||
|
|
|
|||
|
|
@ -586,7 +586,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
}
|
||||
}
|
||||
|
||||
// TODO add onboarding v2 handling
|
||||
store.dispatch(BackupAction.CheckForUnfinishedBackup)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import com.tangem.domain.feedback.GetCardInfoUseCase
|
|||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.repository.OnboardingRepository
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -188,6 +189,9 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles
|
||||
get() = entryPoint.getOnboardingV2FeatureToggles()
|
||||
|
||||
private val onboardingRepository: OnboardingRepository
|
||||
get() = entryPoint.getOnboardingRepository()
|
||||
|
||||
private val dispatchers: CoroutineDispatcherProvider
|
||||
get() = entryPoint.getCoroutineDispatcherProvider()
|
||||
|
||||
|
|
@ -273,6 +277,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory {
|
|||
onrampFeatureToggles = onrampFeatureToggles,
|
||||
environmentConfigStorage = environmentConfigStorage,
|
||||
onboardingV2FeatureToggles = onboardingV2FeatureToggles,
|
||||
onboardingRepository = onboardingRepository,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -148,8 +148,14 @@ class DialogManager : StoreSubscriber<GlobalState> {
|
|||
is BackupDialog.AttestationFailed -> AttestationFailedDialog.create(context)
|
||||
is BackupDialog.AddMoreBackupCards -> AddMoreBackupCardsDialog.create(context)
|
||||
is BackupDialog.BackupInProgress -> BackupInProgressDialog.create(context)
|
||||
is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(context)
|
||||
is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(context)
|
||||
is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(
|
||||
context = context,
|
||||
scanResponse = state.dialog.scanResponse,
|
||||
)
|
||||
is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(
|
||||
context = context,
|
||||
unfinishedBackupScanResponse = state.dialog.scanResponse,
|
||||
)
|
||||
is BackupDialog.ResetBackupCard -> ResetBackupCardDialog.create(
|
||||
context = context,
|
||||
cardId = state.dialog.cardId,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
|
|||
import android.net.Uri
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
|
||||
|
|
@ -98,7 +99,10 @@ sealed class BackupAction : Action {
|
|||
|
||||
data object DiscardBackup : BackupAction()
|
||||
data object DiscardSavedBackup : BackupAction()
|
||||
data object ResumeFoundUnfinishedBackup : BackupAction()
|
||||
|
||||
data class ResumeFoundUnfinishedBackup(
|
||||
val unfinishedBackupScanResponse: ScanResponse?,
|
||||
) : BackupAction()
|
||||
|
||||
data class ResetBackupCard(val cardId: String) : BackupAction()
|
||||
}
|
||||
|
|
@ -581,14 +581,42 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
store.state.globalState.onboardingState.onboardingManager?.finishActivation(it)
|
||||
}
|
||||
backupService.discardSavedBackup()
|
||||
|
||||
val isOnboardingV2Enabled = store.inject(DaggerGraphState::onboardingV2FeatureToggles)
|
||||
.isOnboardingV2Enabled
|
||||
|
||||
if (isOnboardingV2Enabled) {
|
||||
val onboardingRepository = store.inject(DaggerGraphState::onboardingRepository)
|
||||
onboardingRepository.clearUnfinishedFinalizeOnboarding()
|
||||
}
|
||||
}
|
||||
}
|
||||
is BackupAction.CheckForUnfinishedBackup -> {
|
||||
if (backupService.hasIncompletedBackup) {
|
||||
store.dispatch(GlobalAction.ShowDialog(BackupDialog.UnfinishedBackupFound))
|
||||
val isOnboardingV2Enabled = store.inject(DaggerGraphState::onboardingV2FeatureToggles).isOnboardingV2Enabled
|
||||
|
||||
if (isOnboardingV2Enabled) {
|
||||
val onboardingRepository = store.inject(DaggerGraphState::onboardingRepository)
|
||||
|
||||
mainScope.launch {
|
||||
val onboardingScanResponse = onboardingRepository.getUnfinishedFinalizeOnboarding() ?: return@launch
|
||||
store.dispatch(GlobalAction.ShowDialog(BackupDialog.UnfinishedBackupFound(onboardingScanResponse)))
|
||||
}
|
||||
} else if (backupService.hasIncompletedBackup) {
|
||||
store.dispatch(GlobalAction.ShowDialog(BackupDialog.UnfinishedBackupFound()))
|
||||
}
|
||||
}
|
||||
is BackupAction.ResumeFoundUnfinishedBackup -> {
|
||||
if (action.unfinishedBackupScanResponse != null) {
|
||||
// onboarding V2
|
||||
store.dispatchNavigationAction {
|
||||
push(
|
||||
AppRoute.Onboarding(
|
||||
scanResponse = action.unfinishedBackupScanResponse,
|
||||
startFromBackup = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
store.dispatch(
|
||||
GlobalAction.Onboarding.StartForUnfinishedBackup(
|
||||
addedBackupCardsCount = backupService.addedBackupCardsCount,
|
||||
|
|
@ -597,6 +625,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
|
|||
|
||||
store.dispatchNavigationAction { push(AppRoute.OnboardingWallet()) }
|
||||
}
|
||||
}
|
||||
is BackupAction.SkipBackup -> {
|
||||
Analytics.send(Onboarding.Backup.Skipped())
|
||||
Analytics.send(Onboarding.Finished())
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
|
|||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.redux.StateDialog
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import org.rekotlin.StateType
|
||||
|
|
@ -99,22 +100,29 @@ enum class AccessCodeError {
|
|||
typealias CardId = String
|
||||
|
||||
sealed class BackupStep {
|
||||
object InitBackup : BackupStep()
|
||||
object ScanOriginCard : BackupStep()
|
||||
object AddBackupCards : BackupStep()
|
||||
object SetAccessCode : BackupStep()
|
||||
object EnterAccessCode : BackupStep()
|
||||
object ReenterAccessCode : BackupStep()
|
||||
object WritePrimaryCard : 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()
|
||||
object Finished : BackupStep()
|
||||
data object Finished : BackupStep()
|
||||
}
|
||||
|
||||
sealed class BackupDialog : StateDialog {
|
||||
object AttestationFailed : BackupDialog()
|
||||
object AddMoreBackupCards : BackupDialog()
|
||||
object BackupInProgress : BackupDialog()
|
||||
object UnfinishedBackupFound : BackupDialog()
|
||||
object ConfirmDiscardingBackup : BackupDialog()
|
||||
data object AttestationFailed : BackupDialog()
|
||||
data object AddMoreBackupCards : BackupDialog()
|
||||
data object BackupInProgress : BackupDialog()
|
||||
|
||||
data class UnfinishedBackupFound(
|
||||
val scanResponse: ScanResponse? = null,
|
||||
) : BackupDialog()
|
||||
|
||||
data class ConfirmDiscardingBackup(
|
||||
val scanResponse: ScanResponse? = null,
|
||||
) : BackupDialog()
|
||||
|
||||
data class ResetBackupCard(val cardId: String) : BackupDialog()
|
||||
}
|
||||
|
|
@ -3,18 +3,19 @@ package com.tangem.tap.features.onboarding.products.wallet.ui.dialogs
|
|||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
||||
object ConfirmDiscardingBackupDialog {
|
||||
fun create(context: Context): AlertDialog {
|
||||
fun create(context: Context, unfinishedBackupScanResponse: ScanResponse? = null): AlertDialog {
|
||||
return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
|
||||
setTitle(R.string.welcome_interrupted_backup_discard_title)
|
||||
setMessage(R.string.welcome_interrupted_backup_discard_message)
|
||||
setPositiveButton(R.string.welcome_interrupted_backup_discard_resume) { _, _ ->
|
||||
store.dispatch(BackupAction.ResumeFoundUnfinishedBackup)
|
||||
store.dispatch(BackupAction.ResumeFoundUnfinishedBackup(unfinishedBackupScanResponse))
|
||||
}
|
||||
setNegativeButton(R.string.welcome_interrupted_backup_discard_discard) { _, _ ->
|
||||
store.dispatch(BackupAction.DiscardSavedBackup)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.onboarding.products.wallet.ui.dialogs
|
|||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog
|
||||
|
|
@ -10,17 +11,17 @@ import com.tangem.tap.store
|
|||
import com.tangem.wallet.R
|
||||
|
||||
object UnfinishedBackupFoundDialog {
|
||||
fun create(context: Context): AlertDialog {
|
||||
fun create(context: Context, scanResponse: ScanResponse? = null): AlertDialog {
|
||||
return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
|
||||
setTitle(R.string.common_warning)
|
||||
setMessage(R.string.welcome_interrupted_backup_alert_message)
|
||||
setPositiveButton(R.string.welcome_interrupted_backup_alert_resume) { _, _ ->
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(BackupAction.ResumeFoundUnfinishedBackup)
|
||||
store.dispatch(BackupAction.ResumeFoundUnfinishedBackup(scanResponse))
|
||||
}
|
||||
setNegativeButton(R.string.welcome_interrupted_backup_alert_discard) { _, _ ->
|
||||
store.dispatch(GlobalAction.HideDialog)
|
||||
store.dispatch(GlobalAction.ShowDialog(BackupDialog.ConfirmDiscardingBackup))
|
||||
store.dispatch(GlobalAction.ShowDialog(BackupDialog.ConfirmDiscardingBackup(scanResponse)))
|
||||
}
|
||||
setCancelable(false)
|
||||
}.create()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.domain.feedback.GetCardInfoUseCase
|
|||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.repository.OnboardingRepository
|
||||
import com.tangem.domain.settings.repositories.SettingsRepository
|
||||
import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
|
|
@ -72,5 +73,6 @@ data class DaggerGraphState(
|
|||
val onrampFeatureToggles: OnrampFeatureToggles? = null,
|
||||
val environmentConfigStorage: EnvironmentConfigStorage? = null,
|
||||
val onboardingV2FeatureToggles: OnboardingV2FeatureToggles? = null,
|
||||
val onboardingRepository: OnboardingRepository? = null,
|
||||
val excludedBlockchains: ExcludedBlockchains? = null,
|
||||
) : StateType
|
||||
|
|
@ -28,6 +28,7 @@ dependencies {
|
|||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.staking.models)
|
||||
implementation(projects.domain.onramp.models)
|
||||
implementation(projects.domain.models)
|
||||
|
||||
/** Tangem libraries */
|
||||
implementation(deps.tangem.blockchain)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.datasource.api.common.adapter.DateTimeAdapter
|
|||
import com.tangem.datasource.api.common.adapter.LocalDateAdapter
|
||||
import com.tangem.datasource.api.common.adapter.addStakeKitEnumFallbackAdapters
|
||||
import com.tangem.datasource.local.config.providers.models.ProviderModel
|
||||
import com.tangem.domain.models.scan.serialization.*
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -49,7 +50,16 @@ class MoshiModule {
|
|||
@Singleton
|
||||
fun provideSdkMoshiConverter(): MoshiJsonConverter {
|
||||
return MoshiJsonConverter(
|
||||
adapters = listOf(BigDecimalAdapter()) + MoshiJsonConverter.getTangemSdkAdapters(),
|
||||
adapters = MoshiJsonConverter.getTangemSdkAdapters() +
|
||||
listOf(
|
||||
BigDecimalAdapter(),
|
||||
WalletDerivedKeysMapAdapter(),
|
||||
ScanResponseDerivedKeysMapAdapter(),
|
||||
ByteArrayKeyAdapter(),
|
||||
ExtendedPublicKeysMapAdapter(),
|
||||
CardBackupStatusAdapter(),
|
||||
DerivationPathAdapterWithMigration(),
|
||||
),
|
||||
typedAdapters = MoshiJsonConverter.getTangemSdkTypedAdapters(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ object PreferencesKeys {
|
|||
|
||||
val ONRAMP_TRANSACTIONS_STATUSES_KEY by lazy { stringPreferencesKey(name = "onrampTransactionsStatuses") }
|
||||
|
||||
val ONBOARDING_FINALIZE_SCAN_RESPONSE_KEY by lazy { stringPreferencesKey(name = "onboardingFinalizeScanResponse") }
|
||||
|
||||
val IS_GOOGLE_SERVICES_AVAILABLE_KEY by lazy { booleanPreferencesKey(name = "isGoogleServicesAvailable") }
|
||||
|
||||
val IS_GOOGLE_PAY_AVAILABLE_KEY by lazy { booleanPreferencesKey(name = "isGooglePayAvailable") }
|
||||
|
|
|
|||
|
|
@ -26,5 +26,6 @@ dependencies {
|
|||
|
||||
// region Domain modules
|
||||
implementation(projects.domain.onboarding)
|
||||
implementation(projects.domain.models)
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -2,9 +2,8 @@ package com.tangem.data.onboarding
|
|||
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.datasource.local.preferences.utils.get
|
||||
import com.tangem.datasource.local.preferences.utils.getSyncOrDefault
|
||||
import com.tangem.datasource.local.preferences.utils.store
|
||||
import com.tangem.datasource.local.preferences.utils.*
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.onboarding.repository.OnboardingRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
|
@ -30,4 +29,23 @@ internal class DefaultOnboardingRepository(
|
|||
override suspend fun saveTwinsOnboardingShown() {
|
||||
appPreferencesStore.store(key = PreferencesKeys.WAS_TWINS_ONBOARDING_SHOWN, value = true)
|
||||
}
|
||||
|
||||
override suspend fun getUnfinishedFinalizeOnboarding(): ScanResponse? {
|
||||
return appPreferencesStore
|
||||
.getObjectSyncOrNull<ScanResponse>(PreferencesKeys.ONBOARDING_FINALIZE_SCAN_RESPONSE_KEY)
|
||||
}
|
||||
|
||||
override suspend fun saveUnfinishedFinalizeOnboarding(scanResponse: ScanResponse) {
|
||||
appPreferencesStore
|
||||
.storeObject<ScanResponse>(
|
||||
PreferencesKeys.ONBOARDING_FINALIZE_SCAN_RESPONSE_KEY,
|
||||
scanResponse,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun clearUnfinishedFinalizeOnboarding() {
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
mutablePreferences.remove(PreferencesKeys.ONBOARDING_FINALIZE_SCAN_RESPONSE_KEY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,4 +6,6 @@ plugins {
|
|||
dependencies {
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.kotlin.coroutines)
|
||||
|
||||
implementation(projects.domain.models)
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.onboarding.repository
|
||||
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
|
|
@ -15,4 +16,10 @@ interface OnboardingRepository {
|
|||
suspend fun wasTwinsOnboardingShownSync(): Boolean
|
||||
|
||||
suspend fun saveTwinsOnboardingShown()
|
||||
|
||||
suspend fun getUnfinishedFinalizeOnboarding(): ScanResponse?
|
||||
|
||||
suspend fun saveUnfinishedFinalizeOnboarding(scanResponse: ScanResponse)
|
||||
|
||||
suspend fun clearUnfinishedFinalizeOnboarding()
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ dependencies {
|
|||
implementation(projects.core.res)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.navigation)
|
||||
implementation(projects.core.datasource)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
@ -39,6 +40,7 @@ dependencies {
|
|||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.onboarding)
|
||||
|
||||
/** Tangem libraries */
|
||||
implementation(projects.libs.tangemSdkApi)
|
||||
|
|
@ -62,6 +64,7 @@ dependencies {
|
|||
implementation(deps.lottie.compose)
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.androidx.activity.compose)
|
||||
implementation(deps.androidx.datastore)
|
||||
|
||||
/** Other libraries */
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ internal class OnboardingEntryModel @Inject constructor(
|
|||
}
|
||||
|
||||
return when (scanResponse.productType) {
|
||||
ProductType.Note -> TODO()
|
||||
ProductType.Twins -> TODO()
|
||||
ProductType.Wallet -> OnboardingRoute.MultiWallet(
|
||||
scanResponse = scanResponse,
|
||||
withSeedPhraseFlow = false,
|
||||
|
|
@ -71,8 +69,7 @@ internal class OnboardingEntryModel @Inject constructor(
|
|||
onDone = ::onMultiWalletOnboardingDone,
|
||||
mode = multiWalletNavigationMode,
|
||||
)
|
||||
ProductType.Start2Coin -> TODO()
|
||||
ProductType.Visa -> TODO()
|
||||
else -> error("Unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ internal class MultiWalletAccessCodeModel @Inject constructor(
|
|||
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))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model
|
||||
|
||||
// TODO maybe delete some fields in the future
|
||||
data class BackupState(
|
||||
val backupCardsNumber: Int = 0,
|
||||
val numberOfBackupCards: Int = 0,
|
||||
)
|
||||
|
|
@ -15,9 +15,9 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEv
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWalletBackupComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.backupCardAttestationFailedDialog
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.onlyOneBackupDeviceDialog
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.resetBackupCardDialog
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUM
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.BackupServiceHolder
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -70,9 +70,7 @@ class MultiWalletBackupModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getInitState(): MultiWalletBackupUM {
|
||||
return when (backupService.currentState) {
|
||||
BackupService.State.Preparing -> {
|
||||
MultiWalletBackupUM(
|
||||
return MultiWalletBackupUM(
|
||||
title = resourceReference(R.string.onboarding_title_no_backup_cards),
|
||||
bodyText = resourceReference(R.string.onboarding_subtitle_no_backup_cards),
|
||||
finalizeButtonEnabled = false,
|
||||
|
|
@ -80,20 +78,11 @@ class MultiWalletBackupModel @Inject constructor(
|
|||
addBackupButtonLoading = false,
|
||||
onAddBackupClick = ::startBackupWallet,
|
||||
onFinalizeButtonClick = ::onFinalizeClick,
|
||||
onSkipButtonClick = {
|
||||
// eventFlow.tryEmit(Unit)
|
||||
},
|
||||
)
|
||||
}
|
||||
// TODO
|
||||
is BackupService.State.FinalizingBackupCard -> TODO()
|
||||
BackupService.State.FinalizingPrimaryCard -> TODO()
|
||||
BackupService.State.Finished -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startBackupWallet() {
|
||||
if (state.value.backupCardsNumber == 0) {
|
||||
if (state.value.numberOfBackupCards == 0) {
|
||||
backupService.discardSavedBackup()
|
||||
}
|
||||
val primaryCard = scanResponse.primaryCard
|
||||
|
|
@ -144,19 +133,35 @@ class MultiWalletBackupModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onFinalizeClick() {
|
||||
when (state.value.backupCardsNumber) {
|
||||
private fun onFinalizeClick(fromDialog: Boolean = false) {
|
||||
when (state.value.numberOfBackupCards) {
|
||||
1 -> {
|
||||
// TODO show dialog
|
||||
params.multiWalletState.update { it.copy(isThreeCards = false) }
|
||||
|
||||
if (fromDialog.not()) {
|
||||
showOnlyOneBackupWarningDialog()
|
||||
return
|
||||
}
|
||||
}
|
||||
2 -> {
|
||||
params.multiWalletState.update { it.copy(isThreeCards = true) }
|
||||
}
|
||||
}
|
||||
|
||||
modelScope.launch { eventFlow.emit(MultiWalletBackupComponent.Event.Done) }
|
||||
|
||||
analyticsHandler.send(OnboardingEvent.Backup.Finished(cardsCount = state.value.backupCardsNumber + 1))
|
||||
analyticsHandler.send(OnboardingEvent.Backup.Finished(cardsCount = state.value.numberOfBackupCards + 1))
|
||||
}
|
||||
|
||||
private fun showOnlyOneBackupWarningDialog() {
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
dialog = onlyOneBackupDeviceDialog(
|
||||
onDismiss = { _uiState.update { it.copy(dialog = null) } },
|
||||
onConfirm = { onFinalizeClick(fromDialog = true) },
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addBackupCardWithService() {
|
||||
|
|
@ -176,7 +181,7 @@ class MultiWalletBackupModel @Inject constructor(
|
|||
is CompletionResult.Success -> {
|
||||
state.update {
|
||||
it.copy(
|
||||
backupCardsNumber = it.backupCardsNumber + 1,
|
||||
numberOfBackupCards = it.numberOfBackupCards + 1,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -186,12 +191,12 @@ class MultiWalletBackupModel @Inject constructor(
|
|||
)
|
||||
params.backups.update {
|
||||
it.copy(
|
||||
card2 = if (state.value.backupCardsNumber == 1) backupCardInfo else it.card2,
|
||||
card3 = if (state.value.backupCardsNumber == 2) backupCardInfo else it.card3,
|
||||
card2 = if (state.value.numberOfBackupCards == 1) backupCardInfo else it.card2,
|
||||
card3 = if (state.value.numberOfBackupCards == 2) backupCardInfo else it.card3,
|
||||
)
|
||||
}
|
||||
|
||||
setNumberOfBackupCards(state.value.backupCardsNumber)
|
||||
setNumberOfBackupCards(state.value.numberOfBackupCards)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
when (val error = result.error) {
|
||||
|
|
|
|||
|
|
@ -29,3 +29,17 @@ internal fun backupCardAttestationFailedDialog(onDismiss: () -> Unit) = MultiWal
|
|||
onConfirm = onDismiss,
|
||||
onCancel = null,
|
||||
)
|
||||
|
||||
internal fun onlyOneBackupDeviceDialog(onDismiss: () -> Unit, onConfirm: () -> Unit) = MultiWalletBackupUMDialog(
|
||||
title = resourceReference(R.string.common_warning),
|
||||
bodyText = resourceReference(R.string.onboarding_alert_message_not_max_backup_cards_added),
|
||||
confirmText = resourceReference(R.string.common_continue),
|
||||
cancelText = resourceReference(R.string.common_cancel),
|
||||
warningCancelColor = false,
|
||||
onDismiss = onDismiss,
|
||||
onConfirm = {
|
||||
onDismiss()
|
||||
onConfirm()
|
||||
},
|
||||
onCancel = onDismiss,
|
||||
)
|
||||
|
|
@ -13,7 +13,6 @@ data class MultiWalletBackupUM(
|
|||
val finalizeButtonEnabled: Boolean = false,
|
||||
val onAddBackupClick: () -> Unit = {},
|
||||
val onFinalizeButtonClick: () -> Unit = {},
|
||||
val onSkipButtonClick: () -> Unit = {},
|
||||
val dialog: MultiWalletBackupUMDialog? = null,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@ internal class Wallet1ChooseOptionModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onSkipClick() {
|
||||
// TODO show confirmation dialog
|
||||
|
||||
if (skipClicked) return
|
||||
skipClicked = true
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ 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.onboarding.repository.OnboardingRepository
|
||||
import com.tangem.domain.wallets.builder.UserWalletBuilder
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -22,6 +23,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChild
|
|||
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.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.FinalizeStage.*
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.BackupServiceHolder
|
||||
import com.tangem.sdk.api.TangemSdkManager
|
||||
|
|
@ -46,23 +48,66 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
private val generateWalletNameUseCase: GenerateWalletNameUseCase,
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val cardRepository: CardRepository,
|
||||
private val onboardingRepository: OnboardingRepository,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<MultiWalletChildParams>()
|
||||
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
|
||||
private val _uiState = MutableStateFlow(getInitialState())
|
||||
|
||||
private val backupCardIds = backupServiceHolder.backupService.get()?.backupCardIds.orEmpty()
|
||||
|
||||
private var walletHasBackupError = false
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
val onEvent = MutableSharedFlow<MultiWalletFinalizeComponent.Event>()
|
||||
|
||||
init {
|
||||
// save scan response to preferences to be able
|
||||
// to continue finalize process after app restart
|
||||
modelScope.launch {
|
||||
onboardingRepository.saveUnfinishedFinalizeOnboarding(
|
||||
scanResponse = multiWalletState.value.currentScanResponse,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInitialState(): MultiWalletFinalizeUM {
|
||||
val backupService = backupServiceHolder.backupService.get() ?: return MultiWalletFinalizeUM()
|
||||
val initialStep = getInitialStep()
|
||||
|
||||
val batchId = when (initialStep) {
|
||||
MultiWalletFinalizeUM.Step.Primary -> backupService.primaryCardBatchId
|
||||
MultiWalletFinalizeUM.Step.BackupDevice1 -> backupService.backupCardsBatchIds.getOrNull(0)
|
||||
MultiWalletFinalizeUM.Step.BackupDevice2 -> backupService.backupCardsBatchIds.getOrNull(1)
|
||||
}
|
||||
|
||||
val cardId = when (initialStep) {
|
||||
MultiWalletFinalizeUM.Step.Primary -> backupService.primaryCardId
|
||||
MultiWalletFinalizeUM.Step.BackupDevice1 -> backupService.backupCardIds.getOrNull(0)
|
||||
MultiWalletFinalizeUM.Step.BackupDevice2 -> backupService.backupCardIds.getOrNull(1)
|
||||
}
|
||||
|
||||
return MultiWalletFinalizeUM(
|
||||
isRing = batchId?.let { isRing(it) } ?: false,
|
||||
onScanClick = ::onLinkClick,
|
||||
scanPrimary = initialStep == MultiWalletFinalizeUM.Step.Primary,
|
||||
cardNumber = cardId?.lastMasked().orEmpty(),
|
||||
step = getInitialStep(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getInitialStep(): MultiWalletFinalizeUM.Step {
|
||||
val startFromFinalize =
|
||||
params.multiWalletState.value.startFromFinalize ?: return MultiWalletFinalizeUM.Step.Primary
|
||||
|
||||
return when (startFromFinalize) {
|
||||
ScanPrimaryCard -> MultiWalletFinalizeUM.Step.Primary
|
||||
ScanBackupFirstCard -> MultiWalletFinalizeUM.Step.BackupDevice1
|
||||
ScanBackupSecondCard -> MultiWalletFinalizeUM.Step.BackupDevice2
|
||||
}
|
||||
}
|
||||
|
||||
private fun onLinkClick() {
|
||||
when (_uiState.value.step) {
|
||||
MultiWalletFinalizeUM.Step.Primary -> {
|
||||
|
|
@ -79,8 +124,6 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
|
||||
private fun writePrimaryCard() {
|
||||
val backupService = backupServiceHolder.backupService.get() ?: return
|
||||
// TODO 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
|
||||
|
|
@ -107,9 +150,6 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
|
||||
private fun writeBackupCard(cardIndex: Int) {
|
||||
val backupService = backupServiceHolder.backupService.get() ?: return
|
||||
|
||||
// TODO 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
|
||||
|
|
@ -151,8 +191,6 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun finishBackup() {
|
||||
// TODO Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber))
|
||||
|
||||
modelScope.launch {
|
||||
val scanResponse = params.multiWalletState.value.currentScanResponse
|
||||
val userWallet = createUserWallet(scanResponse)
|
||||
|
|
@ -183,8 +221,12 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
it.copy(resultUserWallet = userWallet)
|
||||
}
|
||||
|
||||
cardRepository.finishCardActivation(scanResponse.card.cardId)
|
||||
// user wallet is fully created and saved, remove scan response from preferences
|
||||
// to prevent showing finalize screen dialog on next app start
|
||||
onboardingRepository.clearUnfinishedFinalizeOnboarding()
|
||||
|
||||
cardRepository.finishCardActivation(scanResponse.card.cardId)
|
||||
backupServiceHolder.backupService.get()?.discardSavedBackup()
|
||||
onEvent.emit(MultiWalletFinalizeComponent.Event.ThreeBackupCardsAdded)
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +243,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
|
||||
@Suppress("MagicNumber")
|
||||
private fun ScanResponse.updateScanResponseAfterBackup(): ScanResponse {
|
||||
val cardsCount = if (params.multiWalletState.value.isThreeCards) 3 else 2
|
||||
val cardsCount = if (params.multiWalletState.value.isThreeCards) 2 else 1
|
||||
|
||||
val card = card.copy(
|
||||
backupStatus = CardDTO.BackupStatus.Active(cardCount = cardsCount),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.ui
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
|
|||
|
|
@ -135,8 +135,6 @@ internal class MultiWalletSeedPhraseModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun openGeneratedSeedPhrase() {
|
||||
// TODO analytics SeedPhraseEvents.ButtonGenerateSeedPhrase
|
||||
|
||||
val words12 = state.value.generatedWords12 ?: return
|
||||
val words24 = state.value.generatedWords24 ?: return
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,18 @@ import com.tangem.core.decompose.di.ComponentScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.analytics.OnboardingEvent
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.common.ui.interruptBackupDialog
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.FinalizeStage
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.BackupServiceHolder
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -23,6 +28,8 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val analyticsHandler: AnalyticsEventHandler,
|
||||
private val backupServiceHolder: BackupServiceHolder,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
) : Model() {
|
||||
private val params = paramsContainer.require<OnboardingMultiWalletComponent.Params>()
|
||||
private val getCardImageUseCase = GetCardImageUseCase()
|
||||
|
|
@ -35,6 +42,7 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
accessCode = null,
|
||||
isThreeCards = true,
|
||||
resultUserWallet = null,
|
||||
startFromFinalize = getInitialStartFromFinalize(),
|
||||
),
|
||||
)
|
||||
val backups = MutableStateFlow(MultiWalletChildParams.Backup())
|
||||
|
|
@ -48,10 +56,11 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onBack() {
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
_uiState.update { st ->
|
||||
st.copy(
|
||||
dialog = interruptBackupDialog(
|
||||
onConfirm = {
|
||||
removeFinalizeScanResponseState()
|
||||
router.pop()
|
||||
},
|
||||
dismiss = { _uiState.update { it.copy(dialog = null) } },
|
||||
|
|
@ -60,20 +69,30 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun removeFinalizeScanResponseState() {
|
||||
// discarding onboarding means we have to remove scan response from preferences
|
||||
// to prevent showing finalize screen dialog on next app start
|
||||
modelScope.launch {
|
||||
appPreferencesStore.editData { mutablePreferences ->
|
||||
mutablePreferences.remove(PreferencesKeys.ONBOARDING_FINALIZE_SCAN_RESPONSE_KEY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeToBackups() {
|
||||
modelScope.launch {
|
||||
backups.collectLatest { bst ->
|
||||
backups.collectLatest { backup ->
|
||||
when {
|
||||
_uiState.value.artwork2Url == null && bst.card2 != null -> {
|
||||
_uiState.value.artwork2Url == null && backup.card2 != null -> {
|
||||
val artwork =
|
||||
getCardImageUseCase.invoke(bst.card2.cardId, bst.card2.cardPublicKey)
|
||||
getCardImageUseCase.invoke(backup.card2.cardId, backup.card2.cardPublicKey)
|
||||
_uiState.update {
|
||||
it.copy(artwork2Url = artwork)
|
||||
}
|
||||
}
|
||||
_uiState.value.artwork3Url == null && bst.card3 != null -> {
|
||||
_uiState.value.artwork3Url == null && backup.card3 != null -> {
|
||||
val artwork =
|
||||
getCardImageUseCase.invoke(bst.card3.cardId, bst.card3.cardPublicKey)
|
||||
getCardImageUseCase.invoke(backup.card3.cardId, backup.card3.cardPublicKey)
|
||||
_uiState.update {
|
||||
it.copy(artwork3Url = artwork)
|
||||
}
|
||||
|
|
@ -85,9 +104,10 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
|
||||
private fun getInitialStep(): OnboardingMultiWalletState.Step {
|
||||
val card = params.scanResponse.card
|
||||
val backupService = backupServiceHolder.backupService.get()!!
|
||||
|
||||
// todo check local storage for scan response
|
||||
return when {
|
||||
backupService.hasIncompletedBackup -> OnboardingMultiWalletState.Step.Finalize
|
||||
card.wallets.isNotEmpty() && card.backupStatus == CardDTO.BackupStatus.NoBackup ->
|
||||
OnboardingMultiWalletState.Step.AddBackupDevice
|
||||
card.wallets.isNotEmpty() && card.backupStatus?.isActive == true ->
|
||||
|
|
@ -97,6 +117,19 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getInitialStartFromFinalize(): FinalizeStage? {
|
||||
val backupService = backupServiceHolder.backupService.get() ?: return null
|
||||
return when (val state = backupService.currentState) {
|
||||
BackupService.State.FinalizingPrimaryCard -> FinalizeStage.ScanPrimaryCard
|
||||
is BackupService.State.FinalizingBackupCard -> if (state.index == 1) {
|
||||
FinalizeStage.ScanBackupFirstCard
|
||||
} else {
|
||||
FinalizeStage.ScanBackupSecondCard
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun initScreenTitle() {
|
||||
val title = screenTitleByStep(getInitialStep())
|
||||
params.titleProvider.changeTitle(title)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,13 @@ data class OnboardingMultiWalletState(
|
|||
val accessCode: AccessCode?,
|
||||
val isThreeCards: Boolean,
|
||||
val currentScanResponse: ScanResponse,
|
||||
val resultUserWallet: UserWallet?, // TODO make callback instead
|
||||
val startFromFinalize: FinalizeStage?,
|
||||
val resultUserWallet: UserWallet?,
|
||||
) {
|
||||
enum class FinalizeStage {
|
||||
ScanPrimaryCard, ScanBackupFirstCard, ScanBackupSecondCard
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallet1
|
||||
* CreateWallet -> ChooseBackupOption -> AddBackupDevice -> Finalize -> [Done]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue