Updated on 2026-08-14
This commit is contained in:
parent
f5bad31618
commit
2c19b748b0
17 changed files with 127 additions and 59 deletions
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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?,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue