Updated on 2026-08-14

This commit is contained in:
Tangem 2022-10-28 12:27:15 +05:00
parent f5bad31618
commit 2c19b748b0
17 changed files with 127 additions and 59 deletions

View file

@ -166,7 +166,7 @@ private fun onScanSuccess(scanResponse: ScanResponse) {
val isOnboardingCase = result.data val isOnboardingCase = result.data
if (isOnboardingCase) { if (isOnboardingCase) {
store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false)) store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false))
store.dispatch(OnboardingSaltPayAction.Init.SetDependencies(manager, config)) store.dispatch(OnboardingSaltPayAction.SetDependencies(manager, config))
store.dispatch(OnboardingSaltPayAction.Update) store.dispatch(OnboardingSaltPayAction.Update)
navigateTo(AppScreen.OnboardingWallet) navigateTo(AppScreen.OnboardingWallet)
} else { } else {

View file

@ -19,10 +19,10 @@ class OnboardingHelper {
if (!response.twinsIsTwinned()) { if (!response.twinsIsTwinned()) {
true true
} else { } else {
cardInfoStorage.activationIsStarted(response.card.cardId) cardInfoStorage.isActivationStarted(response.card.cardId)
} }
} }
response.card.hasWallets() -> cardInfoStorage.activationIsStarted(response.card.cardId) response.card.hasWallets() -> cardInfoStorage.isActivationStarted(response.card.cardId)
else -> true else -> true
} }
} }

View file

@ -67,8 +67,10 @@ class OnboardingManager(
} }
} }
return balance.copy(currency = Currency.Blockchain( return balance.copy(
walletManager.wallet.blockchain, walletManager.wallet.publicKey.derivationPath?.rawPath) currency = Currency.Blockchain(
walletManager.wallet.blockchain, walletManager.wallet.publicKey.derivationPath?.rawPath,
),
) )
} }
@ -79,6 +81,14 @@ class OnboardingManager(
fun activationFinished(cardId: String) { fun activationFinished(cardId: String) {
usedCardsPrefStorage.activationFinished(cardId) usedCardsPrefStorage.activationFinished(cardId)
} }
fun isActivationFinished(cardId: String): Boolean {
return usedCardsPrefStorage.isActivationFinished(cardId)
}
fun isActivationStarted(cardId: String): Boolean {
return usedCardsPrefStorage.isActivationStarted(cardId)
}
} }
data class OnboardingWalletBalance( data class OnboardingWalletBalance(
@ -98,23 +108,23 @@ data class OnboardingWalletBalance(
companion object { companion object {
fun error(error: TapError): OnboardingWalletBalance = OnboardingWalletBalance( fun error(error: TapError): OnboardingWalletBalance = OnboardingWalletBalance(
state = ProgressState.Error, state = ProgressState.Error,
error = error error = error,
) )
fun criticalError(error: TapError): OnboardingWalletBalance = OnboardingWalletBalance( fun criticalError(error: TapError): OnboardingWalletBalance = OnboardingWalletBalance(
state = ProgressState.Error, state = ProgressState.Error,
criticalError = error criticalError = error,
) )
fun loading(value: BigDecimal = BigDecimal.ZERO): OnboardingWalletBalance = OnboardingWalletBalance( fun loading(value: BigDecimal = BigDecimal.ZERO): OnboardingWalletBalance = OnboardingWalletBalance(
value, value,
state = ProgressState.Loading state = ProgressState.Loading,
) )
fun done(value: BigDecimal, hasTransactions: Boolean): OnboardingWalletBalance = OnboardingWalletBalance( fun done(value: BigDecimal, hasTransactions: Boolean): OnboardingWalletBalance = OnboardingWalletBalance(
value, value,
hasIncomingTransaction = hasTransactions, hasIncomingTransaction = hasTransactions,
state = ProgressState.Done state = ProgressState.Done,
) )
} }
} }

View file

@ -41,6 +41,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
binding.toolbar.setTitle(R.string.onboarding_title) binding.toolbar.setTitle(R.string.onboarding_title)
btnRefreshBalanceWidget = RefreshBalanceWidget(mainBinding.onboardingTopContainer.onboardingWalletContainer) btnRefreshBalanceWidget = RefreshBalanceWidget(mainBinding.onboardingTopContainer.onboardingWalletContainer)
store.dispatch(OnboardingNoteAction.Init)
store.dispatch(OnboardingNoteAction.LoadCardArtwork) store.dispatch(OnboardingNoteAction.LoadCardArtwork)
store.dispatch(OnboardingNoteAction.DetermineStepOfScreen) store.dispatch(OnboardingNoteAction.DetermineStepOfScreen)
} }

View file

@ -10,6 +10,7 @@ import org.rekotlin.Action
*/ */
sealed class OnboardingNoteAction : Action { sealed class OnboardingNoteAction : Action {
// from user, ui // from user, ui
object Init : OnboardingNoteAction()
object LoadCardArtwork : OnboardingNoteAction() object LoadCardArtwork : OnboardingNoteAction()
object CreateWallet : OnboardingNoteAction() object CreateWallet : OnboardingNoteAction()
object TopUp : OnboardingNoteAction() object TopUp : OnboardingNoteAction()

View file

@ -4,6 +4,8 @@ import com.tangem.common.CompletionResult
import com.tangem.common.extensions.guard import com.tangem.common.extensions.guard
import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.extensions.withMainContext
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchErrorNotification import com.tangem.tap.common.extensions.dispatchErrorNotification
import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.dispatchOpenUrl
@ -58,6 +60,11 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
val noteState = store.state.onboardingNoteState val noteState = store.state.onboardingNoteState
when (action) { when (action) {
is OnboardingNoteAction.Init -> {
if (!onboardingManager.isActivationStarted(card.cardId)) {
Analytics.send(Onboarding.Started())
}
}
is OnboardingNoteAction.LoadCardArtwork -> { is OnboardingNoteAction.LoadCardArtwork -> {
scope.launch { scope.launch {
val artworkUrl = onboardingManager.loadArtworkUrl() val artworkUrl = onboardingManager.loadArtworkUrl()
@ -78,6 +85,7 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch
store.dispatch(OnboardingNoteAction.Balance.Update) store.dispatch(OnboardingNoteAction.Balance.Update)
} }
OnboardingNoteStep.Done -> { OnboardingNoteStep.Done -> {
Analytics.send(Onboarding.Finished())
onboardingManager.activationFinished(card.cardId) onboardingManager.activationFinished(card.cardId)
postUi(DELAY_SDK_DIALOG_CLOSE) { store.dispatch(OnboardingNoteAction.Confetti.Show) } postUi(DELAY_SDK_DIALOG_CLOSE) { store.dispatch(OnboardingNoteAction.Confetti.Show) }
} }

View file

@ -33,6 +33,7 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
mainBinding.onboardingTopContainer.imvFrontCard.transitionName = ShareElement.imvFrontCard mainBinding.onboardingTopContainer.imvFrontCard.transitionName = ShareElement.imvFrontCard
binding.toolbar.setTitle(R.string.onboarding_title) binding.toolbar.setTitle(R.string.onboarding_title)
store.dispatch(OnboardingOtherCardsAction.Init)
store.dispatch(OnboardingOtherCardsAction.LoadCardArtwork) store.dispatch(OnboardingOtherCardsAction.LoadCardArtwork)
store.dispatch(OnboardingOtherCardsAction.DetermineStepOfScreen) store.dispatch(OnboardingOtherCardsAction.DetermineStepOfScreen)
} }

View file

@ -7,6 +7,7 @@ import org.rekotlin.Action
*/ */
sealed class OnboardingOtherCardsAction : Action { sealed class OnboardingOtherCardsAction : Action {
// from user, ui // from user, ui
object Init : OnboardingOtherCardsAction()
object LoadCardArtwork : OnboardingOtherCardsAction() object LoadCardArtwork : OnboardingOtherCardsAction()
object CreateWallet : OnboardingOtherCardsAction() object CreateWallet : OnboardingOtherCardsAction()

View file

@ -4,6 +4,8 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult import com.tangem.common.CompletionResult
import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.extensions.withMainContext
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.onCardScanned import com.tangem.tap.common.extensions.onCardScanned
import com.tangem.tap.common.postUi import com.tangem.tap.common.postUi
import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.AppState
@ -45,6 +47,11 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
val card = onboardingManager.scanResponse.card val card = onboardingManager.scanResponse.card
when (action) { when (action) {
is OnboardingOtherCardsAction.Init -> {
if (!onboardingManager.isActivationStarted(card.cardId)) {
Analytics.send(Onboarding.Started())
}
}
is OnboardingOtherCardsAction.LoadCardArtwork -> { is OnboardingOtherCardsAction.LoadCardArtwork -> {
scope.launch { scope.launch {
val artworkUrl = onboardingManager.loadArtworkUrl() val artworkUrl = onboardingManager.loadArtworkUrl()
@ -60,6 +67,7 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
} }
is OnboardingOtherCardsAction.SetStepOfScreen -> { is OnboardingOtherCardsAction.SetStepOfScreen -> {
if (action.step == OnboardingOtherCardsStep.Done) { if (action.step == OnboardingOtherCardsStep.Done) {
Analytics.send(Onboarding.Finished())
onboardingManager.activationFinished(card.cardId) onboardingManager.activationFinished(card.cardId)
postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) } postUi(200) { store.dispatch(OnboardingOtherCardsAction.Confetti.Show) }
} }
@ -71,7 +79,7 @@ private fun handleOtherCardsAction(action: Action, dispatch: DispatchFunction) {
when (result) { when (result) {
is CompletionResult.Success -> { is CompletionResult.Success -> {
val updatedResponse = onboardingManager.scanResponse.copy( val updatedResponse = onboardingManager.scanResponse.copy(
card = result.data.card card = result.data.card,
) )
onboardingManager.scanResponse = updatedResponse onboardingManager.scanResponse = updatedResponse
onboardingManager.activationStarted(updatedResponse.card.cardId) onboardingManager.activationStarted(updatedResponse.card.cardId)

View file

@ -6,6 +6,8 @@ import com.tangem.common.extensions.guard
import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.extensions.withMainContext
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchErrorNotification import com.tangem.tap.common.extensions.dispatchErrorNotification
import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.dispatchOpenUrl
@ -76,6 +78,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
fun finishCardActivation() { fun finishCardActivation() {
if (twinCardsState.mode == CreateTwinWalletMode.CreateWallet) { if (twinCardsState.mode == CreateTwinWalletMode.CreateWallet) {
Analytics.send(Onboarding.Finished())
onboardingManager?.activationFinished(getScanResponse().card.cardId) onboardingManager?.activationFinished(getScanResponse().card.cardId)
twinCardsState.pairCardId?.let { onboardingManager?.activationFinished(it) } twinCardsState.pairCardId?.let { onboardingManager?.activationFinished(it) }
} }
@ -85,11 +88,18 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
is TwinCardsAction.Init -> { is TwinCardsAction.Init -> {
if (twinCardsState.currentStep == TwinCardsStep.WelcomeOnly) return if (twinCardsState.currentStep == TwinCardsStep.WelcomeOnly) return
val scanResponse = getScanResponse()
onboardingManager?.apply {
if (!isActivationStarted(scanResponse.card.cardId)) {
Analytics.send(Onboarding.Started())
}
}
when (twinCardsState.mode) { when (twinCardsState.mode) {
CreateTwinWalletMode.CreateWallet -> { CreateTwinWalletMode.CreateWallet -> {
if (preferencesStorage.wasTwinsOnboardingShown()) { if (preferencesStorage.wasTwinsOnboardingShown()) {
val step = when { val step = when {
!getScanResponse().twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet !scanResponse.twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet
twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done
else -> TwinCardsStep.TopUpWallet else -> TwinCardsStep.TopUpWallet
} }
@ -105,8 +115,8 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
} }
is TwinCardsAction.Wallet.HandleOnBackPressed -> { is TwinCardsAction.Wallet.HandleOnBackPressed -> {
val shouldReturnCardBack = twinCardsState.mode == CreateTwinWalletMode.CreateWallet val shouldReturnCardBack = twinCardsState.mode == CreateTwinWalletMode.CreateWallet
&& twinCardsState.currentStep != TwinCardsStep.TopUpWallet && twinCardsState.currentStep != TwinCardsStep.TopUpWallet
&& twinCardsState.currentStep != TwinCardsStep.Done && twinCardsState.currentStep != TwinCardsStep.Done
if (twinCardsState.showAlert) { if (twinCardsState.showAlert) {
val onInterruptPrompt = { val onInterruptPrompt = {
@ -163,7 +173,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
val result = manager.createSecondWallet( val result = manager.createSecondWallet(
action.initialMessage, action.initialMessage,
action.preparingMessage, action.preparingMessage,
action.creatingWalletMessage action.creatingWalletMessage,
) )
when (result) { when (result) {
is CompletionResult.Success -> { is CompletionResult.Success -> {
@ -221,11 +231,11 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
val balanceIsLoading = twinCardsState.walletBalance.copy( val balanceIsLoading = twinCardsState.walletBalance.copy(
currency = Currency.Blockchain( currency = Currency.Blockchain(
walletManager.wallet.blockchain, walletManager.wallet.blockchain,
walletManager.wallet.publicKey.derivationPath?.rawPath walletManager.wallet.publicKey.derivationPath?.rawPath,
), ),
state = ProgressState.Loading, state = ProgressState.Loading,
error = null, error = null,
criticalError = null criticalError = null,
) )
store.dispatch(TwinCardsAction.Balance.Set(balanceIsLoading)) store.dispatch(TwinCardsAction.Balance.Set(balanceIsLoading))
@ -239,7 +249,6 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
store.dispatch(TwinCardsAction.Balance.SetNonCriticalError(loadedBalance.error)) store.dispatch(TwinCardsAction.Balance.SetNonCriticalError(loadedBalance.error))
} }
} }
} }
is TwinCardsAction.Balance.Set -> { is TwinCardsAction.Balance.Set -> {
if (action.balance.balanceIsToppedUp()) { if (action.balance.balanceIsToppedUp()) {

View file

@ -7,7 +7,6 @@ import org.rekotlin.Action
sealed class OnboardingWalletAction : Action { sealed class OnboardingWalletAction : Action {
object Init : OnboardingWalletAction() object Init : OnboardingWalletAction()
object StartSaltPayCardActivation : OnboardingWalletAction()
object GetToCreateWalletStep : OnboardingWalletAction() object GetToCreateWalletStep : OnboardingWalletAction()
object GetToSaltPayStep : OnboardingWalletAction() object GetToSaltPayStep : OnboardingWalletAction()
object CreateWallet : OnboardingWalletAction() object CreateWallet : OnboardingWalletAction()

View file

@ -3,10 +3,14 @@ package com.tangem.tap.features.onboarding.products.wallet.redux
import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult import com.tangem.common.CompletionResult
import com.tangem.common.card.Card import com.tangem.common.card.Card
import com.tangem.common.extensions.ifNotNull
import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.TapWorkarounds.isSaltPay
import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.extensions.withMainContext
import com.tangem.operations.backup.BackupService import com.tangem.operations.backup.BackupService
import com.tangem.tap.backupService import com.tangem.tap.backupService
import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.primaryCardIsSaltPay import com.tangem.tap.common.extensions.primaryCardIsSaltPay
@ -61,6 +65,12 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
when (action) { when (action) {
OnboardingWalletAction.Init -> { OnboardingWalletAction.Init -> {
ifNotNull(onboardingManager, card) { manager, card ->
if (!card.isSaltPay && !manager.isActivationStarted(card.cardId)) {
Analytics.send(Onboarding.Started())
}
}
when { when {
card == null -> { card == null -> {
// it's possible when found unfinished backup for standard Wallet cards // it's possible when found unfinished backup for standard Wallet cards
@ -87,13 +97,6 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
} }
} }
} }
is OnboardingWalletAction.StartSaltPayCardActivation -> {
// we need to do this because the standard activation happens in the OnboardingWalletAction.CreateWallet
// step which is omitted for SaltPay cards
if (onboardingWalletState.isSaltPay && scanResponse != null) {
startCardActivation(scanResponse)
}
}
is OnboardingWalletAction.LoadArtwork -> { is OnboardingWalletAction.LoadArtwork -> {
scope.launch { scope.launch {
val artwork = onboardingManager?.loadArtworkUrl() val artwork = onboardingManager?.loadArtworkUrl()
@ -148,9 +151,6 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch:
} else { } else {
val backupState = store.state.onboardingWalletState.backupState val backupState = store.state.onboardingWalletState.backupState
val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState) val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState)
if (onboardingWalletState.isSaltPay) {
finishCardActivation(backupState, scanResponse.card)
}
scope.launch { globalState.tapWalletManager.onCardScanned(updatedScanResponse) } scope.launch { globalState.tapWalletManager.onCardScanned(updatedScanResponse) }
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet)) store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet))
} }
@ -313,6 +313,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
} }
is BackupAction.FinishBackup -> { is BackupAction.FinishBackup -> {
if (!onboardingWalletState.isSaltPay) { if (!onboardingWalletState.isSaltPay) {
Analytics.send(Onboarding.Finished())
finishCardActivation(backupState, card) finishCardActivation(backupState, card)
} }
} }
@ -320,7 +321,10 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
backupService.discardSavedBackup() backupService.discardSavedBackup()
} }
is BackupAction.DiscardSavedBackup -> { is BackupAction.DiscardSavedBackup -> {
backupService.primaryCardId?.let { finishCardsActivationForDiscardedUnfinishedBackup(it) } backupService.primaryCardId?.let {
Analytics.send(Onboarding.Finished())
finishCardsActivationForDiscardedUnfinishedBackup(it)
}
backupService.discardSavedBackup() backupService.discardSavedBackup()
} }
is BackupAction.CheckForUnfinishedBackup -> { is BackupAction.CheckForUnfinishedBackup -> {
@ -351,7 +355,7 @@ private fun startCardActivation(scanResponse: ScanResponse) {
* Standard Wallet cards finish activation at BackupAction.FinishBackup * Standard Wallet cards finish activation at BackupAction.FinishBackup
* SaltPay cards finish activation at OnboardingWalletAction.FinishOnboarding * SaltPay cards finish activation at OnboardingWalletAction.FinishOnboarding
*/ */
private fun finishCardActivation(backupState: BackupState, card: Card?) { internal fun finishCardActivation(backupState: BackupState, card: Card?) {
(listOf(backupState.primaryCardId, card?.cardId) + backupState.backupCardIds) (listOf(backupState.primaryCardId, card?.cardId) + backupState.backupCardIds)
.distinct().filterNotNull() .distinct().filterNotNull()
.forEach { cardId -> .forEach { cardId ->
@ -377,7 +381,7 @@ private fun initSaltPayOnBackupFinishedIfNeeded(
if (scanResponse == null) throw IllegalArgumentException() if (scanResponse == null) throw IllegalArgumentException()
val (manager, config) = OnboardingSaltPayState.initDependency(scanResponse) val (manager, config) = OnboardingSaltPayState.initDependency(scanResponse)
store.dispatchOnMain(OnboardingSaltPayAction.Init.SetDependencies(manager, config)) store.dispatchOnMain(OnboardingSaltPayAction.SetDependencies(manager, config))
store.dispatchOnMain(OnboardingSaltPayAction.Update) store.dispatchOnMain(OnboardingSaltPayAction.Update)
} }
} }

View file

@ -10,12 +10,12 @@ import java.math.BigDecimal
[REDACTED_AUTHOR] [REDACTED_AUTHOR]
*/ */
sealed class OnboardingSaltPayAction : Action { sealed class OnboardingSaltPayAction : Action {
sealed class Init : OnboardingSaltPayAction() { object Init : OnboardingSaltPayAction()
data class SetDependencies(
val registrationManager: SaltPayActivationManager, data class SetDependencies(
val saltPayConfig: SaltPayConfig, val registrationManager: SaltPayActivationManager,
) : Init() val saltPayConfig: SaltPayConfig,
} ) : OnboardingSaltPayAction()
data class SetInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction() data class SetInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction()
data class SetClaimRefreshInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction() data class SetClaimRefreshInProgress(val isInProgress: Boolean) : OnboardingSaltPayAction()

View file

@ -12,13 +12,16 @@ import com.tangem.network.api.paymentology.KYCStatus
import com.tangem.network.api.paymentology.RegistrationResponse import com.tangem.network.api.paymentology.RegistrationResponse
import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.Analytics
import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.analytics.events.Onboarding
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.isPositive import com.tangem.tap.common.extensions.isPositive
import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.domain.TangemSigner import com.tangem.tap.domain.TangemSigner
import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.onboarding.OnboardingManager
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
import com.tangem.tap.features.onboarding.products.wallet.redux.finishCardActivation
import com.tangem.tap.features.onboarding.products.wallet.saltPay.AllSymbolsTheSameFilter import com.tangem.tap.features.onboarding.products.wallet.saltPay.AllSymbolsTheSameFilter
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayActivationManager
import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler import com.tangem.tap.features.onboarding.products.wallet.saltPay.SaltPayExceptionHandler
@ -58,9 +61,23 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
fun getAppState(): AppState = appState()!! fun getAppState(): AppState = appState()!!
fun getOnboardingWalletState(): OnboardingWalletState = getAppState().onboardingWalletState fun getOnboardingWalletState(): OnboardingWalletState = getAppState().onboardingWalletState
fun getOnboardingManager(): OnboardingManager? = getAppState().globalState.onboardingState.onboardingManager
fun getState(): OnboardingSaltPayState = getOnboardingWalletState().onboardingSaltPayState!! fun getState(): OnboardingSaltPayState = getOnboardingWalletState().onboardingSaltPayState!!
when (action) { when (action) {
is OnboardingSaltPayAction.Init -> {
if (getOnboardingWalletState().isSaltPay) return
val onboardingManager = getOnboardingManager().guard {
// onboardingManager may be null if it's started from standard Wallet unfinished backup
return
}
val card = onboardingManager.scanResponse.card
if (!onboardingManager.isActivationStarted(card.cardId)) {
Analytics.send(Onboarding.Started())
onboardingManager.activationStarted(card.cardId)
}
}
is OnboardingSaltPayAction.Update -> { is OnboardingSaltPayAction.Update -> {
handleInProgress = true handleInProgress = true
@ -232,23 +249,31 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App
} }
} }
} }
is OnboardingSaltPayAction.SetStep -> handleAnalytics(action.newStep) is OnboardingSaltPayAction.SetStep -> {
when (action.newStep) {
SaltPayActivationStep.KycStart -> Analytics.send(Onboarding.KYCStarted())
SaltPayActivationStep.KycWaiting -> Analytics.send(Onboarding.KYCInProgress())
SaltPayActivationStep.KycReject -> Analytics.send(Onboarding.KYCRejected())
SaltPayActivationStep.Claim -> Analytics.send(Onboarding.ClaimScreenOpened())
SaltPayActivationStep.ClaimSuccess, SaltPayActivationStep.Success -> {
Analytics.send(Onboarding.Finished())
val onboardingManager = getOnboardingManager().guard {
// Null is possible if it is started from a standard pending backup and in this case
// it is impossible to get here
store.dispatchDebugErrorNotification("OnboardingManager can't be NULL")
return
}
finishCardActivation(getOnboardingWalletState().backupState, onboardingManager.scanResponse.card)
}
else -> {}
}
}
else -> { else -> {
/* do nothing, only reduce */ /* do nothing, only reduce */
} }
} }
} }
private fun handleAnalytics(step: SaltPayActivationStep) {
when (step) {
SaltPayActivationStep.KycStart -> Analytics.send(Onboarding.KYCStarted())
SaltPayActivationStep.KycWaiting -> Analytics.send(Onboarding.KYCInProgress())
SaltPayActivationStep.KycReject -> Analytics.send(Onboarding.KYCRejected())
SaltPayActivationStep.Claim -> Analytics.send(Onboarding.ClaimScreenOpened())
else -> {}
}
}
suspend fun SaltPayActivationManager.update( suspend fun SaltPayActivationManager.update(
currentStep: SaltPayActivationStep, currentStep: SaltPayActivationStep,
currentAmountToClaim: Amount?, currentAmountToClaim: Amount?,

View file

@ -17,7 +17,7 @@ class OnboardingSaltPayReducer {
private fun internalReduce(anyAction: Action, onboardingWalletState: OnboardingWalletState): OnboardingWalletState { private fun internalReduce(anyAction: Action, onboardingWalletState: OnboardingWalletState): OnboardingWalletState {
val action = anyAction as? OnboardingSaltPayAction ?: return onboardingWalletState val action = anyAction as? OnboardingSaltPayAction ?: return onboardingWalletState
if (onboardingWalletState.onboardingSaltPayState == null && action is OnboardingSaltPayAction.Init.SetDependencies) { if (onboardingWalletState.onboardingSaltPayState == null && action is OnboardingSaltPayAction.SetDependencies) {
return onboardingWalletState.copy( return onboardingWalletState.copy(
onboardingSaltPayState = OnboardingSaltPayState( onboardingSaltPayState = OnboardingSaltPayState(
saltPayManager = action.registrationManager, saltPayManager = action.registrationManager,

View file

@ -32,6 +32,7 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayAction
import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayView import com.tangem.tap.features.onboarding.products.wallet.saltPay.ui.OnboardingSaltPayView
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog
import com.tangem.tap.store import com.tangem.tap.store
@ -81,7 +82,7 @@ class OnboardingWalletFragment : BaseFragment(R.layout.fragment_onboarding_walle
addBackPressHandler(this) addBackPressHandler(this)
store.dispatch(OnboardingWalletAction.Init) store.dispatch(OnboardingWalletAction.Init)
store.dispatch(OnboardingWalletAction.StartSaltPayCardActivation) store.dispatch(OnboardingSaltPayAction.Init)
store.dispatch(OnboardingWalletAction.LoadArtwork) store.dispatch(OnboardingWalletAction.LoadArtwork)
} }

View file

@ -11,7 +11,7 @@ import timber.log.Timber
*/ */
class UsedCardsPrefStorage( class UsedCardsPrefStorage(
private val preferences: SharedPreferences, private val preferences: SharedPreferences,
private val jsonConverter: MoshiJsonConverter private val jsonConverter: MoshiJsonConverter,
) { ) {
internal fun migrate() { internal fun migrate() {
@ -43,14 +43,6 @@ class UsedCardsPrefStorage(
save(foundItem, restoredList) save(foundItem, restoredList)
} }
fun isActivationFinished(cardId: String): Boolean {
return !(findCardInfo(cardId)?.isActivationStarted ?: true)
}
fun activationIsStarted(cardId: String): Boolean {
return findCardInfo(cardId)?.isActivationStarted ?: false
}
fun activationFinished(cardId: String) { fun activationFinished(cardId: String) {
val restoredList = restore() val restoredList = restore()
val foundItem = findCardInfo(cardId, restoredList)?.copy(isActivationStarted = false) val foundItem = findCardInfo(cardId, restoredList)?.copy(isActivationStarted = false)
@ -59,6 +51,14 @@ class UsedCardsPrefStorage(
save(foundItem, restoredList) save(foundItem, restoredList)
} }
fun isActivationFinished(cardId: String): Boolean {
return !(findCardInfo(cardId)?.isActivationStarted ?: true)
}
fun isActivationStarted(cardId: String): Boolean {
return findCardInfo(cardId)?.isActivationStarted ?: false
}
private fun findCardInfo(cardId: String, list: MutableList<UsedCardInfo>? = null): UsedCardInfo? { private fun findCardInfo(cardId: String, list: MutableList<UsedCardInfo>? = null): UsedCardInfo? {
val findInList = list ?: restore() val findInList = list ?: restore()
return findInList.firstOrNull { it.cardId == cardId } return findInList.firstOrNull { it.cardId == cardId }