Updated on 2026-08-14

This commit is contained in:
Tangem 2024-12-05 10:35:27 +03:00
parent 022c4bcfcd
commit d71d29b72b
30 changed files with 295 additions and 104 deletions

View file

@ -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

View file

@ -586,7 +586,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
}
}
// TODO add onboarding v2 handling
store.dispatch(BackupAction.CheckForUnfinishedBackup)
}

View file

@ -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,
),
),

View file

@ -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,

View file

@ -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()
}

View file

@ -581,21 +581,50 @@ 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 -> {
store.dispatch(
GlobalAction.Onboarding.StartForUnfinishedBackup(
addedBackupCardsCount = backupService.addedBackupCardsCount,
),
)
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,
),
)
store.dispatchNavigationAction { push(AppRoute.OnboardingWallet()) }
store.dispatchNavigationAction { push(AppRoute.OnboardingWallet()) }
}
}
is BackupAction.SkipBackup -> {
Analytics.send(Onboarding.Backup.Skipped())

View file

@ -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()
}

View file

@ -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)

View file

@ -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()

View file

@ -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