diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt index 9ce35483a4..6c8580df05 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt @@ -14,6 +14,7 @@ sealed class MainScreen( class ButtonScanCard : MainScreen("Button - Scan Card") class ButtonMyWallets : MainScreen("Button - My Wallets") + class ButtonBuy : MainScreen("Button - Buy") class EnableBiometrics(state: AnalyticsParam.OnOffState) : MainScreen( event = "Enable Biometric", diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt index 0b203bab27..c0d61c52d1 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt @@ -68,16 +68,24 @@ sealed class Onboarding( } class PinScreenOpened : Onboarding("Onboarding", "PIN screen opened") - class PinCodeSet : Onboarding("Onboarding", "PIN code set") + class ButtonSetPinCode : Onboarding("Onboarding", "Button - Set PIN Code") + class CardConnectionScreenOpened : Onboarding("Onboarding", "Card Connection Screen Opened") class ButtonConnect : Onboarding("Onboarding", "Button - Connect") + class PinCodeSet : Onboarding("Onboarding", "PIN code set") + class KYCScreenOpened : Onboarding("Onboarding", "KYC screen opened") class KYCStarted : Onboarding("Onboarding", "KYC started") class KYCInProgress : Onboarding("Onboarding", "KYC in progress") class KYCRejected : Onboarding("Onboarding", "KYC rejected") + class ClaimScreenOpened : Onboarding("Onboarding", "Claim screen opened") class ButtonClaim : Onboarding("Onboarding", "Button - Claim") class ClaimWasSuccessfully : Onboarding("Onboarding", "Claim was successfully") - class ButtonChat: Onboarding("Onboarding", "Button - Chat") + + class ButtonChat : Onboarding("Onboarding", "Button - Chat") + + class NotEnoughGasError : Onboarding("Onboarding", "Not Enough Gas Error") + class CardNotPassedError : Onboarding("Onboarding", "Card Not Passed Error") class EnableBiometrics(state: AnalyticsParam.OnOffState) : Onboarding( category = "Onboarding / Biometric", diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt index 99c231e1e4..e723fb4a9e 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt @@ -6,6 +6,8 @@ import com.tangem.domain.common.ProductType import com.tangem.domain.common.ScanResponse import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter import com.tangem.tap.common.analytics.events.AnalyticsParam +import com.tangem.tap.common.analytics.events.IntroductionProcess +import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.features.demo.DemoHelper /** @@ -17,7 +19,12 @@ class CardContextInterceptor( override fun id(): String = CardContextInterceptor.id() - override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = true + override fun canBeAppliedTo(event: AnalyticsEvent): Boolean { + return when (event) { + is IntroductionProcess.ButtonScanCard, is MainScreen.ButtonScanCard -> false + else -> true + } + } override fun intercept(params: MutableMap) { scanResponse ?: return diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt index 21c1cd221a..3317a70315 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt @@ -201,7 +201,7 @@ object ScanCardProcessor { onWalletNotCreated() store.dispatch(GlobalAction.Onboarding.Start(scanResponse, canSkipBackup = false)) store.dispatch(OnboardingSaltPayAction.SetDependencies(manager)) - store.dispatch(OnboardingSaltPayAction.Update) + store.dispatch(OnboardingSaltPayAction.Update(withAnalytics = false)) navigateTo(AppScreen.OnboardingWallet) { onProgressStateChange(it) } } else { delay(DELAY_SDK_DIALOG_CLOSE) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 009ede0c8d..42848b47b9 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -63,7 +63,11 @@ sealed class BackupAction : Action { data class PrepareToWriteBackupCard(val cardNumber: Int) : BackupAction() data class WriteBackupCard(val cardNumber: Int) : BackupAction() - object FinishBackup : BackupAction() + /** + * It always calls for the SaltPay cards when resuming the activation process. + */ + data class FinishBackup(val withAnalytics: Boolean = true) : BackupAction() + object DiscardBackup : BackupAction() object DiscardSavedBackup : BackupAction() object ResumeFoundUnfinishedBackup : BackupAction() 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 143ad4d35f..3397e56980 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 @@ -86,10 +86,11 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: scanResponse.isSaltPay() -> { store.dispatch(OnboardingWalletAction.GetToSaltPayStep) - store.dispatch(BackupAction.FinishBackup) + store.dispatch(BackupAction.FinishBackup(withAnalytics = false)) + store.dispatch(OnboardingSaltPayAction.OnSwitchedToSaltPayProcess) } - else -> store.dispatch(BackupAction.FinishBackup) + else -> store.dispatch(BackupAction.FinishBackup()) } } else -> { @@ -314,7 +315,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) is CompletionResult.Success -> { if (backupService.currentState == BackupService.State.Finished) { initSaltPayOnBackupFinishedIfNeeded(scanResponse, onboardingWalletState) - store.dispatchOnMain(BackupAction.FinishBackup) + store.dispatchOnMain(BackupAction.FinishBackup()) } else { store.dispatchOnMain(BackupAction.PrepareToWriteBackupCard(action.cardNumber + 1)) } @@ -325,7 +326,9 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } } is BackupAction.FinishBackup -> { - Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber)) + if (action.withAnalytics) { + Analytics.send(Onboarding.Backup.Finished(backupState.backupCardsNumber)) + } if (!onboardingWalletState.isSaltPay) { Analytics.send(Onboarding.Finished()) finishCardActivation(backupState, card) @@ -357,7 +360,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) is BackupAction.DismissBackup -> { Analytics.send(Onboarding.Backup.Skipped()) if (onboardingWalletState.isSaltPay) throw UnsupportedOperationException() - store.dispatch(BackupAction.FinishBackup) + store.dispatch(BackupAction.FinishBackup()) } } } @@ -405,7 +408,7 @@ private fun initSaltPayOnBackupFinishedIfNeeded( card = scanResponse.card, ).create() store.dispatchOnMain(OnboardingSaltPayAction.SetDependencies(manager)) - store.dispatchOnMain(OnboardingSaltPayAction.Update) + store.dispatchOnMain(OnboardingSaltPayAction.Update(false)) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt index 8a6403aa27..85a64112cb 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/GnosisRegistrator.kt @@ -50,6 +50,7 @@ class GnosisRegistrator( private val atomicNonce = AtomicLong() suspend fun checkHasGas(): Result { + // return Result.Success(true) // test val wallet = walletManager.safeUpdate().successOr { return Result.Failure(BlockchainSdkError.WrappedThrowable(it.error)) } @@ -148,6 +149,7 @@ class GnosisRegistrator( } suspend fun getAllowance(): Result { + // return Result.Success(Amount(BigDecimal(0.1), walletManager.wallet.blockchain)) // test return walletManager.getAllowance(addressTreasureSafe, token) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt index 0f0b207431..e215cbfe92 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayExceptionHandler.kt @@ -2,6 +2,8 @@ package com.tangem.tap.features.onboarding.products.wallet.saltPay import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.common.core.TangemSdkError +import com.tangem.core.analytics.Analytics +import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.redux.AppDialog import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog @@ -17,8 +19,15 @@ class SaltPayExceptionHandler { when (throwable) { is SaltPayActivationError -> { val dialog = when (throwable) { - is SaltPayActivationError.NoGas -> SaltPayDialog.Activation.NoGas + is SaltPayActivationError.NoGas -> { + Analytics.send(Onboarding.NotEnoughGasError()) + SaltPayDialog.Activation.NoGas + } is SaltPayActivationError.PutVisaCard -> SaltPayDialog.Activation.PutVisaCard + is SaltPayActivationError.CardNotPassed -> { + Analytics.send(Onboarding.CardNotPassedError()) + SaltPayDialog.Activation.OnError(throwable) + } else -> SaltPayDialog.Activation.OnError(throwable) } store.dispatchDialogShow(dialog) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt index 73c1700fc6..1fbb284524 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayAction.kt @@ -11,6 +11,11 @@ import java.math.BigDecimal sealed class OnboardingSaltPayAction : Action { object Init : OnboardingSaltPayAction() + /** + * Notification about the switching from the Wallet view to the SaltPay view. + */ + object OnSwitchedToSaltPayProcess : OnboardingSaltPayAction() + data class SetDependencies( val registrationManager: SaltPayActivationManager, ) : OnboardingSaltPayAction() @@ -20,7 +25,7 @@ sealed class OnboardingSaltPayAction : Action { data class SetAccessCode(val accessCode: String?) : OnboardingSaltPayAction() - object Update : OnboardingSaltPayAction() + data class Update(val withAnalytics: Boolean = true) : OnboardingSaltPayAction() object RegisterCard : OnboardingSaltPayAction() object OpenUtorgKYC : OnboardingSaltPayAction() object UtorgKYCRedirectSuccess : OnboardingSaltPayAction() @@ -31,7 +36,11 @@ sealed class OnboardingSaltPayAction : Action { data class TrySetPin(val pin: String) : OnboardingSaltPayAction() data class SetPin(val pin: String) : OnboardingSaltPayAction() - data class SetStep(val newStep: SaltPayActivationStep) : OnboardingSaltPayAction() + data class SetStep( + val newStep: SaltPayActivationStep, + val withAnalytics: Boolean = true, + ) : OnboardingSaltPayAction() + data class SetAmountToClaim(val amount: Amount?) : OnboardingSaltPayAction() data class SetTokenBalance(val balanceValue: BigDecimal) : OnboardingSaltPayAction() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt index ad903e6dd1..33e9d7fa1b 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/redux/OnboardingSaltPayMiddleware.kt @@ -79,6 +79,9 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App onboardingManager.activationStarted(card.cardId) } } + is OnboardingSaltPayAction.OnSwitchedToSaltPayProcess -> { + sendAnalyticsScreenOpened(getState().step, newStep = SaltPayActivationStep.None) + } is OnboardingSaltPayAction.Update -> { handleInProgress = true @@ -90,7 +93,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App } handleInProgress = false - dispatchOnMain(OnboardingSaltPayAction.SetStep(updateStep)) + dispatchOnMain(OnboardingSaltPayAction.SetStep(updateStep, action.withAnalytics)) if (updateStep == SaltPayActivationStep.Claim) { handleClaimRefreshInProgress = true @@ -148,6 +151,7 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App return@launch } + Analytics.send(Onboarding.PinCodeSet()) handleInProgress = false dispatchOnMain(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.KycIntro)) } @@ -171,13 +175,13 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App } handleInProgress = false - dispatchOnMain(OnboardingSaltPayAction.Update) + dispatchOnMain(OnboardingSaltPayAction.Update()) } } is OnboardingSaltPayAction.TrySetPin -> { try { assertPinValid(action.pin, getState().pinLength) - Analytics.send(Onboarding.PinCodeSet()) + Analytics.send(Onboarding.ButtonSetPinCode()) store.dispatch(OnboardingSaltPayAction.SetPin(action.pin)) store.dispatch(OnboardingSaltPayAction.SetStep(SaltPayActivationStep.CardRegistration)) } catch (error: SaltPayActivationError) { @@ -257,24 +261,22 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App } } is OnboardingSaltPayAction.SetStep -> { - when (action.newStep) { - SaltPayActivationStep.NeedPin -> Analytics.send(Onboarding.PinScreenOpened()) - SaltPayActivationStep.KycIntro -> Analytics.send(Onboarding.KYCScreenOpened()) - 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) + if (action.withAnalytics) { + sendAnalyticsScreenOpened(getState().step, action.newStep) + } + if (action.newStep == SaltPayActivationStep.ClaimSuccess || + action.newStep == SaltPayActivationStep.Success + ) { + 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 } - else -> {} + finishCardActivation( + getOnboardingWalletState().backupState, + onboardingManager.scanResponse.card, + ) } } else -> { @@ -283,6 +285,22 @@ private fun handleOnboardingSaltPayAction(anyAction: Action, appState: () -> App } } +private fun sendAnalyticsScreenOpened(currentStep: SaltPayActivationStep, newStep: SaltPayActivationStep) { + if (currentStep == newStep) return + + when (newStep) { + SaltPayActivationStep.NeedPin -> Analytics.send(Onboarding.PinScreenOpened()) + SaltPayActivationStep.CardRegistration -> Analytics.send(Onboarding.CardConnectionScreenOpened()) + SaltPayActivationStep.KycIntro -> Analytics.send(Onboarding.KYCScreenOpened()) + 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()) + else -> {} + } +} + suspend fun SaltPayActivationManager.update( currentStep: SaltPayActivationStep, currentAmountToClaim: Amount?, @@ -369,6 +387,7 @@ private suspend fun getAmountToClaimIfNeeded( return amountToClaim } + // return Amount(BigDecimal(0.1), Blockchain.SaltPay) return when (val result = saltPayManager.getAmountToClaim()) { is Result.Success -> { Timber.d("getAmountToClaimIfNeeded: success: %s", result.data) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt index 84e012cad9..9ed2b65b03 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/ui/OnboardingSaltPayView.kt @@ -80,6 +80,7 @@ internal class OnboardingSaltPayView( if (state.backupState.backupStep == BackupStep.Finished) { // if backup finished -> switch OnboardingWalletStep to the SaltPay store.dispatch(OnboardingWalletAction.GetToSaltPayStep) + store.dispatch(OnboardingSaltPayAction.OnSwitchedToSaltPayProcess) } else { // if not -> back to the standard backup process walletFragment.handleOnboardingStep(state) @@ -228,7 +229,7 @@ internal class OnboardingSaltPayView( btnKycAction.text = getText(R.string.onboarding_button_kyc_waiting) btnKycAction.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.Update) + store.dispatch(OnboardingSaltPayAction.Update()) } progressButton = SaltPayProgressButton(root) } @@ -244,7 +245,7 @@ internal class OnboardingSaltPayView( btnOpenSupportChat.hide() btnKycAction.text = getText(R.string.onboarding_button_kyc_start) btnKycAction.setOnClickListener { - store.dispatch(OnboardingSaltPayAction.Update) + store.dispatch(OnboardingSaltPayAction.Update()) } progressButton = SaltPayProgressButton(root) } diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt index f029d4fa9b..3e7e7b824e 100644 --- a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.sprinklr.ui +import android.os.Bundle import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.systemBarsPadding @@ -8,11 +9,18 @@ import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.fragment.app.viewModels +import com.tangem.core.analytics.Analytics import com.tangem.core.ui.fragments.ComposeFragment +import com.tangem.tap.common.analytics.events.Chat internal class SprinklrFragment : ComposeFragment() { private val viewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Analytics.send(Chat.ScreenOpened()) + } + @Composable override fun provideState(): State { return viewModel.state.collectAsState() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt index b1d18042d6..8d43ff1316 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt @@ -3,10 +3,12 @@ package com.tangem.tap.features.wallet.ui.wallet.saltPay import android.view.LayoutInflater import android.view.ViewGroup import com.skydoves.androidveil.VeilLayout +import com.tangem.core.analytics.Analytics import com.tangem.domain.common.extensions.debounce import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.ShimmerData import com.tangem.tap.common.ShimmerRecyclerAdapter +import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.extensions.animateVisibility import com.tangem.tap.common.extensions.formatAmountAsSpannedString import com.tangem.tap.common.extensions.hide @@ -144,6 +146,7 @@ class SaltPayWalletView : WalletView() { btnBuy.show(tokenData.isAvailableToBuy) btnBuy.setOnClickListener { + Analytics.send(MainScreen.ButtonBuy()) store.dispatch(WalletAction.TradeCryptoAction.Buy(false)) } }