From 5f79c03e8535791e96b21b050c4b914062bd5bc3 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 14 Mar 2025 22:36:14 +0300 Subject: [PATCH 01/11] Updated on 2026-08-14 --- version.properties | 1 + 1 file changed, 1 insertion(+) create mode 100644 version.properties diff --git a/version.properties b/version.properties new file mode 100644 index 0000000000..b3df6e8432 --- /dev/null +++ b/version.properties @@ -0,0 +1 @@ +versionName=5.22.0 \ No newline at end of file From 5936456a0bc28ab80e0f0d4f4ee2e955f93248c4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 15 Mar 2025 22:38:14 +0300 Subject: [PATCH 02/11] Updated on 2026-08-14 --- .../finalize/model/CantLeaveFinalizeDialog.kt | 14 ++++++++++++++ .../finalize/model/MultiWalletFinalizeModel.kt | 4 ++++ 2 files changed, 18 insertions(+) create mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt new file mode 100644 index 0000000000..92e3be5491 --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt @@ -0,0 +1,14 @@ +package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model + +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.message.DialogMessage +import com.tangem.core.ui.message.EventMessageAction +import com.tangem.features.onboarding.v2.impl.R + +internal val CantLeaveFinalizeDialog: DialogMessage = DialogMessage( + message = resourceReference(R.string.onboarding_backup_exit_warning), + firstAction = EventMessageAction( + title = resourceReference(R.string.warning_button_ok), + onClick = {}, + ), +) \ 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 index a84ab61103..dc1dec313a 100644 --- 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 @@ -6,6 +6,7 @@ import com.tangem.common.core.TangemSdkError 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.domain.card.repository.CardRepository import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.feedback.GetCardInfoUseCase @@ -52,6 +53,7 @@ internal class MultiWalletFinalizeModel @Inject constructor( private val cardRepository: CardRepository, private val onboardingRepository: OnboardingRepository, private val walletsRepository: WalletsRepository, + private val uiMessageSender: UiMessageSender, ) : Model() { private val params = paramsContainer.require() @@ -80,6 +82,8 @@ internal class MultiWalletFinalizeModel @Inject constructor( fun onBack() { if (uiState.value.scanPrimary) { modelScope.launch { onBackFlow.emit(Unit) } + } else { + uiMessageSender.send(CantLeaveFinalizeDialog) } } From adb0582bdeba2f9b4767e7a8abe170e91a81b3a1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Mar 2025 10:53:01 +0300 Subject: [PATCH 03/11] Updated on 2026-08-14 --- .../v2/multiwallet/impl/model/OnboardingMultiWalletModel.kt | 4 ---- 1 file changed, 4 deletions(-) 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 8ca4e7faf4..7b11113ad6 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 @@ -106,12 +106,8 @@ internal class OnboardingMultiWalletModel @Inject constructor( private fun getInitialStep(): OnboardingMultiWalletState.Step { val scanResponse = params.scanResponse val card = scanResponse.card - val backupService = backupServiceHolder.backupService.get()!! return when { - // interrupted backup - backupService.hasIncompletedBackup -> OnboardingMultiWalletState.Step.Finalize - // Add backup button // Wallet1 without backup and userwallet's scanResponse doesn't contain primary card. card.wallets.isNotEmpty() && card.backupStatus == CardDTO.BackupStatus.NoBackup && From 779802cabf149cc224e91d1d2d8bc52c396015fe Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Mar 2025 11:00:44 +0300 Subject: [PATCH 04/11] Updated on 2026-08-14 --- .../impl/child/backup/model/MultiWalletBackupModel.kt | 4 ++++ 1 file changed, 4 insertions(+) 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 46f6135d72..6728f170e4 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 @@ -14,6 +14,7 @@ import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.toWrappedList import com.tangem.core.ui.message.dialog.Dialogs +import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType @@ -49,6 +50,7 @@ class MultiWalletBackupModel @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, private val uiMessageSender: UiMessageSender, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, + private val cardRepository: CardRepository, ) : Model() { @Suppress("UnusedPrivateMember") @@ -275,6 +277,8 @@ class MultiWalletBackupModel @Inject constructor( cardId = cardId, allowsRequestAccessCodeFromRepository = false, ) + + cardRepository.finishCardActivation(cardId) } } } \ No newline at end of file From 2ab9227ca02d38d96db3787318c64758410c8044 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Mar 2025 11:58:47 +0300 Subject: [PATCH 05/11] Updated on 2026-08-14 --- .../model/MultiWalletFinalizeModel.kt | 36 +++++++++---------- .../impl/model/OnboardingMultiWalletState.kt | 2 +- 2 files changed, 18 insertions(+), 20 deletions(-) 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 index dc1dec313a..eea8684ef3 100644 --- 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 @@ -64,18 +64,31 @@ internal class MultiWalletFinalizeModel @Inject constructor( private var walletHasBackupError = false private var hasRing = false + val uiState = _uiState.asStateFlow() val onBackFlow = MutableSharedFlow() - val onEvent = MutableSharedFlow() init { - // save scan response to preferences to be able - // to continue finalize process after app restart modelScope.launch { + // save scan response to preferences to be able + // to continue finalize process after app restart onboardingRepository.saveUnfinishedFinalizeOnboarding( scanResponse = multiWalletState.value.currentScanResponse, ) + + // sets proper artwork state for initial step + // (if we start from backup cards, we need to show proper artwork) ([REDACTED_TASK_KEY]) + when (getInitialStep()) { + MultiWalletFinalizeUM.Step.Primary -> { /* state is already set */ } + MultiWalletFinalizeUM.Step.BackupDevice1 -> { + onEvent.emit(MultiWalletFinalizeComponent.Event.OneBackupCardAdded) + } + MultiWalletFinalizeUM.Step.BackupDevice2 -> { + onEvent.emit(MultiWalletFinalizeComponent.Event.OneBackupCardAdded) + onEvent.emit(MultiWalletFinalizeComponent.Event.TwoBackupCardsAdded) + } + } } } @@ -91,21 +104,6 @@ internal class MultiWalletFinalizeModel @Inject constructor( val backupService = backupServiceHolder.backupService.get() ?: return MultiWalletFinalizeUM() val initialStep = getInitialStep() - // sets proper artwork state for initial step - // (if we start from backup cards, we need to show proper artwork) ([REDACTED_TASK_KEY]) - modelScope.launch { - when (initialStep) { - MultiWalletFinalizeUM.Step.Primary -> { /* state is already set */ } - MultiWalletFinalizeUM.Step.BackupDevice1 -> { - onEvent.emit(MultiWalletFinalizeComponent.Event.OneBackupCardAdded) - } - MultiWalletFinalizeUM.Step.BackupDevice2 -> { - onEvent.emit(MultiWalletFinalizeComponent.Event.OneBackupCardAdded) - onEvent.emit(MultiWalletFinalizeComponent.Event.TwoBackupCardsAdded) - } - } - } - val batchId = when (initialStep) { MultiWalletFinalizeUM.Step.Primary -> backupService.primaryCardBatchId MultiWalletFinalizeUM.Step.BackupDevice1 -> backupService.backupCardsBatchIds.getOrNull(0) @@ -123,7 +121,7 @@ internal class MultiWalletFinalizeModel @Inject constructor( onScanClick = ::onLinkClick, scanPrimary = initialStep == MultiWalletFinalizeUM.Step.Primary, cardNumber = cardId?.lastMasked().orEmpty(), - step = getInitialStep(), + step = initialStep, ) } 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 1906d6c2aa..1347a7122b 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 @@ -24,7 +24,7 @@ data class OnboardingMultiWalletState( * -> [Done] * * Wallet2/Ring - * CreateWallet -> SeedPhrase -> AddBackupDevice -> FinishBackup -> [Done] + * CreateWallet -> SeedPhrase -> AddBackupDevice -> Finalize -> [Done] * | * -> AddBackupDevice -> Finalize -> [Done] */ From 995c08286944c84f27e2b4d1432208471f3af257 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Mar 2025 13:25:13 +0300 Subject: [PATCH 06/11] Updated on 2026-08-14 --- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index df9ee2e6b7..6ad91766cb 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -586,7 +586,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } is BackupAction.DiscardSavedBackup -> { mainScope.launch { - backupService.primaryCardId?.let { + backupService.primaryCardId?.let { // always null for onboarding v2 Analytics.send(Onboarding.Finished()) store.state.globalState.onboardingState.onboardingManager?.finishActivation(it) } @@ -597,7 +597,12 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) if (isOnboardingV2Enabled) { val onboardingRepository = store.inject(DaggerGraphState::onboardingRepository) + val cardRepository = store.inject(DaggerGraphState::cardRepository) + val unfinishedBackup = onboardingRepository.getUnfinishedFinalizeOnboarding() ?: return@launch + + cardRepository.finishCardActivation(unfinishedBackup.card.cardId) onboardingRepository.clearUnfinishedFinalizeOnboarding() + Analytics.send(Onboarding.Finished()) } } } From 8990adcc6e63fdca63020a176eef7535f8942209 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 17 Mar 2025 13:33:13 +0300 Subject: [PATCH 07/11] Updated on 2026-08-14 --- .../features/onboarding/OnboardingHelper.kt | 7 +---- .../redux/OnboardingWalletMiddleware.kt | 7 +---- .../tangem/tap/routing/utils/ChildFactory.kt | 2 -- .../com/tangem/common/routing/AppRoute.kt | 4 +-- .../v2/entry/OnboardingEntryComponent.kt | 1 - .../entry/impl/model/OnboardingEntryModel.kt | 14 +++++++--- .../wallet-settings/impl/build.gradle.kts | 1 + .../model/WalletSettingsModel.kt | 26 +++++++++++++------ .../router/DefaultWalletRouter.kt | 1 - 9 files changed, 32 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index 2d53df4f9b..b7642d1a29 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -83,7 +83,6 @@ object OnboardingHelper { return AppRoute.Onboarding( scanResponse = scanResponse, - startFromBackup = false, mode = when (backupState.startedSource) { BackupStartedSource.Onboarding -> AppRoute.Onboarding.Mode.Onboarding BackupStartedSource.CreateBackup -> AppRoute.Onboarding.Mode.AddBackup @@ -93,11 +92,7 @@ object OnboardingHelper { return when (val type = scanResponse.productType) { ProductType.Note -> if (featureToggles.isNoteRefactoringEnabled) { - AppRoute.Onboarding( - scanResponse = scanResponse, - startFromBackup = false, - mode = AppRoute.Onboarding.Mode.Onboarding, - ) + AppRoute.Onboarding(scanResponse = scanResponse) } else { AppRoute.OnboardingNote } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 6ad91766cb..855d95ce35 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -624,12 +624,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) if (action.unfinishedBackupScanResponse != null) { // onboarding V2 store.dispatchNavigationAction { - push( - AppRoute.Onboarding( - scanResponse = action.unfinishedBackupScanResponse, - startFromBackup = false, - ), - ) + push(AppRoute.Onboarding(scanResponse = action.unfinishedBackupScanResponse)) } } else { store.dispatch( diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index a852857c6d..0ff58d9f5f 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -202,7 +202,6 @@ internal class ChildFactory @Inject constructor( contextProvider = contextProvider(route, contextFactory), params = OnboardingEntryComponent.Params( scanResponse = route.scanResponse, - startBackupFlow = route.startFromBackup, multiWalletMode = when (route.mode) { AppRoute.Onboarding.Mode.Onboarding -> OnboardingEntryComponent.MultiWalletMode.Onboarding AppRoute.Onboarding.Mode.AddBackup -> OnboardingEntryComponent.MultiWalletMode.AddBackup @@ -641,7 +640,6 @@ internal class ChildFactory @Inject constructor( contextProvider = contextProvider(route, contextFactory), params = OnboardingEntryComponent.Params( scanResponse = route.scanResponse, - startBackupFlow = route.startFromBackup, multiWalletMode = when (route.mode) { AppRoute.Onboarding.Mode.Onboarding -> OnboardingEntryComponent.MultiWalletMode.Onboarding AppRoute.Onboarding.Mode.AddBackup -> OnboardingEntryComponent.MultiWalletMode.AddBackup diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index ce6d8603f5..f033d76c1e 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -245,15 +245,13 @@ sealed class AppRoute(val path: String) : Route { /** * Onboarding V2 * @property scanResponse scan response, determines onboarding route by the product type - * @property startFromBackup (MultiWallet param, doesn't affect other types) start onboarding from backup * @property mode (MultiWallet param, doesn't affect other types) onboarding mode */ @Serializable data class Onboarding( val scanResponse: ScanResponse, - val startFromBackup: Boolean = false, val mode: Mode = Mode.Onboarding, - ) : AppRoute(path = "/onboarding_v2${if (startFromBackup) "/backup" else ""}") { + ) : AppRoute(path = "/onboarding_v2/${mode.name}") { enum class Mode { Onboarding, // general Mode diff --git a/features/onboarding-v2/api/src/main/kotlin/com/tangem/features/onboarding/v2/entry/OnboardingEntryComponent.kt b/features/onboarding-v2/api/src/main/kotlin/com/tangem/features/onboarding/v2/entry/OnboardingEntryComponent.kt index 1e1bc4d93b..9649b1e0c7 100644 --- a/features/onboarding-v2/api/src/main/kotlin/com/tangem/features/onboarding/v2/entry/OnboardingEntryComponent.kt +++ b/features/onboarding-v2/api/src/main/kotlin/com/tangem/features/onboarding/v2/entry/OnboardingEntryComponent.kt @@ -8,7 +8,6 @@ interface OnboardingEntryComponent : ComposableContentComponent { data class Params( val scanResponse: ScanResponse, - val startBackupFlow: Boolean, val multiWalletMode: MultiWalletMode, ) 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 ef5e1ffa37..75ce0e4bcf 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 @@ -92,10 +92,16 @@ internal class OnboardingEntryModel @Inject constructor( } private fun onMultiWalletOnboardingDone(userWallet: UserWallet) { - if (userWallet.scanResponse.cardTypesResolver.isMultiwalletAllowed()) { - stackNavigation.replaceAll(OnboardingRoute.ManageTokens(userWallet)) - } else { - navigateToFinalScreenFlow() + when { + params.multiWalletMode == OnboardingEntryComponent.MultiWalletMode.AddBackup -> { + stackNavigation.replaceAll(OnboardingRoute.Done(onDone = ::navigateToWalletScreen)) + } + userWallet.scanResponse.cardTypesResolver.isMultiwalletAllowed() -> { + stackNavigation.replaceAll(OnboardingRoute.ManageTokens(userWallet)) + } + else -> { + navigateToFinalScreenFlow() + } } } diff --git a/features/wallet-settings/impl/build.gradle.kts b/features/wallet-settings/impl/build.gradle.kts index ca5f65ffc4..0cfc119783 100644 --- a/features/wallet-settings/impl/build.gradle.kts +++ b/features/wallet-settings/impl/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(projects.features.walletSettings.api) implementation(projects.features.manageTokens.api) implementation(projects.features.nft.api) + implementation(projects.features.onboardingV2.api) /* Project - Core */ implementation(projects.core.decompose) diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt index 764f57f277..52f23e9529 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt @@ -33,6 +33,7 @@ import com.tangem.feature.walletsettings.entity.WalletSettingsUM import com.tangem.feature.walletsettings.impl.R import com.tangem.feature.walletsettings.utils.ItemsBuilder import com.tangem.features.nft.NFTFeatureToggles +import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf @@ -57,6 +58,7 @@ internal class WalletSettingsModel @Inject constructor( private val getShouldSaveUserWalletsSyncUseCase: ShouldSaveUserWalletsSyncUseCase, private val walletsRepository: WalletsRepository, private val nftFeatureToggles: NFTFeatureToggles, + private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles, ) : Model() { val params: WalletSettingsComponent.Params = paramsContainer.require() @@ -156,17 +158,25 @@ internal class WalletSettingsModel @Inject constructor( private fun onLinkMoreCardsClick(scanResponse: ScanResponse) { analyticsEventHandler.send(Settings.ButtonCreateBackup) - analyticsContextProxy.addContext(scanResponse) - reduxStateHolder.dispatch( - LegacyAction.StartOnboardingProcess( - scanResponse = scanResponse, - canSkipBackup = false, - ), - ) + if (onboardingV2FeatureToggles.isOnboardingV2Enabled) { + router.push( + AppRoute.Onboarding( + scanResponse = scanResponse, + mode = AppRoute.Onboarding.Mode.AddBackup, + ), + ) + } else { + reduxStateHolder.dispatch( + LegacyAction.StartOnboardingProcess( + scanResponse = scanResponse, + canSkipBackup = false, + ), + ) - router.push(AppRoute.OnboardingWallet()) + router.push(AppRoute.OnboardingWallet()) + } } private fun onCheckedNFTChange(isChecked: Boolean) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index c32de7180a..967c19ebed 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -53,7 +53,6 @@ internal class DefaultWalletRouter @Inject constructor( router.push( AppRoute.Onboarding( scanResponse = scanResponse, - startFromBackup = true, mode = if (continueBackup) { AppRoute.Onboarding.Mode.AddBackup } else { From 32c24c5cd0047c77b5744b8dea8eb48d1060e1f6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 14 Mar 2025 23:12:10 +0200 Subject: [PATCH 08/11] Updated on 2026-08-14 --- version.properties | 1 - 1 file changed, 1 deletion(-) delete mode 100644 version.properties diff --git a/version.properties b/version.properties deleted file mode 100644 index b3df6e8432..0000000000 --- a/version.properties +++ /dev/null @@ -1 +0,0 @@ -versionName=5.22.0 \ No newline at end of file From c9b3b3f555bacdaa0bf050e5c027aaa8442200b4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Mar 2025 13:42:10 +0300 Subject: [PATCH 09/11] Updated on 2026-08-14 --- .../features/biometry/impl/ui/AskBiometry.kt | 2 +- .../ui/CantLeaveBackupDialog.kt} | 4 ++-- .../impl/DefaultOnboardingEntryComponent.kt | 11 +++++----- .../entry/impl/model/OnboardingEntryModel.kt | 15 +++++++++---- .../model/MultiWalletFinalizeModel.kt | 3 ++- .../impl/model/OnboardingMultiWalletModel.kt | 21 ++++++------------- 6 files changed, 27 insertions(+), 29 deletions(-) rename features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/{multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt => common/ui/CantLeaveBackupDialog.kt} (73%) diff --git a/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/ui/AskBiometry.kt b/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/ui/AskBiometry.kt index 913b028223..cd367b9850 100644 --- a/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/ui/AskBiometry.kt +++ b/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/ui/AskBiometry.kt @@ -17,8 +17,8 @@ import com.tangem.core.ui.components.* import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.features.biometry.impl.ui.state.AskBiometryUM import com.tangem.features.biometry.R +import com.tangem.features.biometry.impl.ui.state.AskBiometryUM @Composable internal fun AskBiometry(state: AskBiometryUM, modifier: Modifier = Modifier) { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/CantLeaveBackupDialog.kt similarity index 73% rename from features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt rename to features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/CantLeaveBackupDialog.kt index 92e3be5491..00b61fe30f 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/finalize/model/CantLeaveFinalizeDialog.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/common/ui/CantLeaveBackupDialog.kt @@ -1,11 +1,11 @@ -package com.tangem.features.onboarding.v2.multiwallet.impl.child.finalize.model +package com.tangem.features.onboarding.v2.common.ui import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.message.DialogMessage import com.tangem.core.ui.message.EventMessageAction import com.tangem.features.onboarding.v2.impl.R -internal val CantLeaveFinalizeDialog: DialogMessage = DialogMessage( +internal val CantLeaveBackupDialog: DialogMessage = DialogMessage( message = resourceReference(R.string.onboarding_backup_exit_warning), firstAction = EventMessageAction( title = resourceReference(R.string.warning_button_ok), 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 05eabc3965..8e6cf0d6c5 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 @@ -53,7 +53,7 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor( popBack = { popInternal { success -> if (success.not()) { - model.stackNavigation.pop() + model.onBack() } } }, @@ -113,15 +113,15 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor( stepperComponent.state.update { it.copy( currentStep = when (stack.active.configuration) { - is OnboardingRoute.AskBiometry -> 7 - is OnboardingRoute.ManageTokens -> 8 + is OnboardingRoute.ManageTokens -> 7 + is OnboardingRoute.AskBiometry -> 8 is OnboardingRoute.Done -> 9 else -> error("Unsupported route") }, steps = 9, title = when (stack.active.configuration) { - is OnboardingRoute.AskBiometry -> resourceReference(R.string.onboarding_navbar_save_wallet) is OnboardingRoute.ManageTokens -> resourceReference(R.string.main_manage_tokens) + is OnboardingRoute.AskBiometry -> resourceReference(R.string.onboarding_navbar_save_wallet) is OnboardingRoute.Done -> resourceReference(R.string.onboarding_done_header) else -> error("Unsupported route") }, @@ -144,8 +144,7 @@ internal class DefaultOnboardingEntryComponent @AssistedInject constructor( override fun Content(modifier: Modifier) { val innerStackState by innerStack.subscribeAsState() - // prevent back navigation - BackHandler { } + BackHandler { model.onBack() } OnboardingEntry( modifier = modifier, 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 75ce0e4bcf..45def47034 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 @@ -8,6 +8,7 @@ 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.navigation.Router +import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.common.util.cardTypesResolver @@ -18,6 +19,7 @@ import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.biometry.AskBiometryComponent import com.tangem.features.biometry.BiometryFeatureToggles import com.tangem.features.onboarding.v2.TitleProvider +import com.tangem.features.onboarding.v2.common.ui.CantLeaveBackupDialog import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent import com.tangem.features.onboarding.v2.entry.impl.analytics.OnboardingEntryEvent import com.tangem.features.onboarding.v2.entry.impl.routing.OnboardingRoute @@ -40,6 +42,7 @@ internal class OnboardingEntryModel @Inject constructor( private val settingsRepository: SettingsRepository, private val askBiometryFeatureToggles: BiometryFeatureToggles, private val analyticsEventHandler: AnalyticsEventHandler, + private val uiMessageSender: UiMessageSender, ) : Model() { private val params = paramsContainer.require() @@ -54,6 +57,14 @@ internal class OnboardingEntryModel @Inject constructor( val startRoute = routeByProductType(params.scanResponse) + fun onManageTokensDone() { + navigateToFinalScreenFlow() + } + + fun onBack() { + uiMessageSender.send(CantLeaveBackupDialog) + } + private fun routeByProductType(scanResponse: ScanResponse): OnboardingRoute { val multiWalletNavigationMode = when (params.multiWalletMode) { OnboardingEntryComponent.MultiWalletMode.Onboarding -> OnboardingMultiWalletComponent.Mode.Onboarding @@ -105,10 +116,6 @@ internal class OnboardingEntryModel @Inject constructor( } } - fun onManageTokensDone() { - navigateToFinalScreenFlow() - } - private fun onVisaOnboardingDone() { navigateToFinalScreenFlow() } 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 index eea8684ef3..ebf937ae3d 100644 --- 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 @@ -21,6 +21,7 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.repository.WalletsRepository import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase +import com.tangem.features.onboarding.v2.common.ui.CantLeaveBackupDialog import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams @@ -96,7 +97,7 @@ internal class MultiWalletFinalizeModel @Inject constructor( if (uiState.value.scanPrimary) { modelScope.launch { onBackFlow.emit(Unit) } } else { - uiMessageSender.send(CantLeaveFinalizeDialog) + uiMessageSender.send(CantLeaveBackupDialog) } } 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 7b11113ad6..f1c33ffc66 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 @@ -5,10 +5,9 @@ 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.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.models.scan.ProductType +import com.tangem.domain.onboarding.repository.OnboardingRepository 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 @@ -30,7 +29,7 @@ internal class OnboardingMultiWalletModel @Inject constructor( private val router: Router, private val analyticsHandler: AnalyticsEventHandler, private val backupServiceHolder: BackupServiceHolder, - private val appPreferencesStore: AppPreferencesStore, + private val onboardingRepository: OnboardingRepository, ) : Model() { private val params = paramsContainer.require() private val getCardImageUseCase = GetCardImageUseCase() @@ -61,8 +60,10 @@ internal class OnboardingMultiWalletModel @Inject constructor( st.copy( dialog = interruptBackupDialog( onConfirm = { - removeFinalizeScanResponseState() - router.pop() + modelScope.launch { + onboardingRepository.clearUnfinishedFinalizeOnboarding() + router.pop() + } }, dismiss = { _uiState.update { it.copy(dialog = null) } }, ), @@ -70,16 +71,6 @@ 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 { backup -> From bc93e1bce6dd28063ede344ca86a1b4685c091a1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Mar 2025 13:46:21 +0300 Subject: [PATCH 10/11] Updated on 2026-08-14 --- .../biometry/impl/model/AskBiometryModel.kt | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/model/AskBiometryModel.kt b/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/model/AskBiometryModel.kt index 7de4c4bbd3..505727f1f7 100644 --- a/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/model/AskBiometryModel.kt +++ b/features/biometry/impl/src/main/kotlin/com/tangem/features/biometry/impl/model/AskBiometryModel.kt @@ -66,15 +66,6 @@ internal class AskBiometryModel @Inject constructor( } } - private fun onAllowClick() { - _uiState.update { it.copy(showProgress = true) } - allowToUseBiometrics() - } - - private fun dontAllow() { - params.modelCallbacks.onDenied() - } - fun dismiss() { modelScope.launch { dismissBSFlow.emit(Unit) @@ -83,13 +74,15 @@ internal class AskBiometryModel @Inject constructor( } } - private fun allowToUseBiometrics() { + private fun onAllowClick() { modelScope.launch { if (tangemSdkManager.checkNeedEnrollBiometrics()) { showEnrollBiometricsDialog() return@launch } + _uiState.update { it.copy(showProgress = true) } + /* * because it will be automatically saved on UserWalletsListManager switch @@ -99,6 +92,7 @@ internal class AskBiometryModel @Inject constructor( uiMessageSender.send( SnackbarMessage(stringReference("No selected user wallet")), ) + _uiState.update { it.copy(showProgress = false) } return@launch } @@ -107,6 +101,10 @@ internal class AskBiometryModel @Inject constructor( } } + private fun dontAllow() { + params.modelCallbacks.onDenied() + } + private suspend fun handleSuccessAllowing(userWallet: UserWallet) { walletsRepository.saveShouldSaveUserWallets(item = true) settingsRepository.setShouldSaveAccessCodes(value = true) From 48150bcb5df5d2c635eb7595dc657fe7365dd578 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 18 Mar 2025 10:46:43 +0000 Subject: [PATCH 11/11] Updated on 2026-08-14 --- gradle/tangem_dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/tangem_dependencies.toml b/gradle/tangem_dependencies.toml index c191bacee5..e71e1ff89f 100644 --- a/gradle/tangem_dependencies.toml +++ b/gradle/tangem_dependencies.toml @@ -1,7 +1,7 @@ [versions] -tangemBlockchainSdk = "release-app_5.22-982" +tangemBlockchainSdk = "develop-977" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "release-app_5.22-440" +tangemCardSdk = "develop-441" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem-developments8" #tangemVico = "0.0.1" # Keep it! - used for local builds ^