Updated on 2026-08-14

This commit is contained in:
Tangem 2023-01-23 18:54:12 +03:00
parent b80a3444de
commit ecb01b4652
12 changed files with 49 additions and 50 deletions

View file

@ -7,14 +7,14 @@ sealed class MyWallets(
params: Map<String, String> = mapOf(),
) : AnalyticsEvent("My Wallets", event, params) {
object MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened")
object CardWasScanned : MyWallets(event = "Card Was Scanned")
object WalletUnlockTapped : MyWallets(event = "Wallet Unlock Tapped")
class MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened")
class CardWasScanned : MyWallets(event = "Card Was Scanned")
class WalletUnlockTapped : MyWallets(event = "Wallet Unlock Tapped")
object Button {
object ScanNewCard : MyWallets(event = "Button - Scan New Card")
object UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID")
object EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped")
object DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped")
sealed class Button {
class ScanNewCard : MyWallets(event = "Button - Scan New Card")
class UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID")
class EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped")
class DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped")
}
}

View file

@ -6,13 +6,13 @@ import com.tangem.common.core.TangemSdkError
import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import com.tangem.common.services.Result
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.AnalyticsEvent
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.operations.backup.BackupService
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
import com.tangem.tap.backupService
import com.tangem.core.analytics.Analytics
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor
import com.tangem.tap.common.extensions.dispatchDialogShow
import com.tangem.tap.common.extensions.dispatchOnMain
@ -45,6 +45,7 @@ import kotlinx.coroutines.launch
// TODO: Create repository for that
object ScanCardProcessor {
suspend fun scan(
analyticsEvent: AnalyticsEvent? = null,
additionalBlockchainsToDerive: Collection<Blockchain>? = null,
cardId: String? = null,
onProgressStateChange: suspend (showProgress: Boolean) -> Unit = {},
@ -77,6 +78,8 @@ object ScanCardProcessor {
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
onScanStateChange(false)
sendAnalytics(analyticsEvent, scanResponse.card.batchId)
checkForUnfinishedBackupForSaltPay(
backupService = backupService,
scanResponse = scanResponse,
@ -102,6 +105,14 @@ object ScanCardProcessor {
}
}
private fun sendAnalytics(
analyticsEvent: AnalyticsEvent?,
batchId: String,
) {
Analytics.addParamsInterceptor(BatchIdParamsInterceptor(batchId))
analyticsEvent?.let { Analytics.send(it) }
}
/**
* It checks only the SaltPay cards. To check for unfinished backups for the standard Wallet cards
* see BackupAction.CheckForUnfinishedBackup
@ -173,14 +184,10 @@ object ScanCardProcessor {
crossinline onSuccess: suspend (ScanResponse) -> Unit,
crossinline onFailure: suspend (error: TangemError) -> Unit,
) {
Analytics.send(IntroductionProcess.CardWasScanned())
val globalState = store.state.globalState
val tapWalletManager = globalState.tapWalletManager
tapWalletManager.updateConfigManager(scanResponse)
Analytics.addParamsInterceptor(BatchIdParamsInterceptor(scanResponse.card.batchId))
store.dispatchOnMain(TwinCardsAction.IfTwinsPrepareState(scanResponse))
if (scanResponse.isSaltPay()) {

View file

@ -1,17 +1,16 @@
package com.tangem.tap.features.home.redux
import com.tangem.core.analytics.AnalyticsEvent
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.entities.IndeterminateProgressButton
import com.tangem.tap.common.redux.navigation.AppScreen
import org.rekotlin.Action
sealed class HomeAction : Action {
object Init : HomeAction()
data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction()
// from ui
data class ReadCard(
val fromScreen: AppScreen = AppScreen.Home,
val analyticsEvent: AnalyticsEvent? = IntroductionProcess.CardWasScanned(),
) : HomeAction()
data class ScanInProgress(val scanInProgress: Boolean) : HomeAction()

View file

@ -4,16 +4,13 @@ import com.tangem.common.doOnFailure
import com.tangem.common.doOnResult
import com.tangem.common.doOnSuccess
import com.tangem.core.analytics.Analytics
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.analytics.events.MainScreen
import com.tangem.core.analytics.AnalyticsEvent
import com.tangem.tap.common.analytics.events.Shop
import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor
import com.tangem.tap.common.entities.IndeterminateProgressButton
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.dispatchOpenUrl
import com.tangem.tap.common.extensions.onCardScanned
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.postUiDelayBg
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.navigation.AppScreen
@ -59,13 +56,9 @@ private fun handleHomeAction(action: Action) {
store.dispatch(GlobalAction.ExchangeManager.Init)
store.dispatch(GlobalAction.FetchUserCountry)
}
is HomeAction.ShouldScanCardOnResume -> {
if (action.shouldScanCard) {
store.dispatch(HomeAction.ShouldScanCardOnResume(false))
postUiDelayBg(700) { store.dispatch(HomeAction.ReadCard(AppScreen.Wallet)) }
}
is HomeAction.ReadCard -> {
readCard(action.analyticsEvent)
}
is HomeAction.ReadCard -> readCard(action.fromScreen)
is HomeAction.GoToShop -> {
Analytics.send(Shop.ScreenOpened())
when (action.userCountryCode) {
@ -76,12 +69,13 @@ private fun handleHomeAction(action: Action) {
}
}
private fun readCard(fromScreen: AppScreen) = scope.launch {
private fun readCard(analyticsEvent: AnalyticsEvent?) = scope.launch {
delay(timeMillis = 200)
tangemSdkManager.setAccessCodeRequestPolicy(
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
)
ScanCardProcessor.scan(
analyticsEvent = analyticsEvent,
onProgressStateChange = { showProgress ->
if (showProgress) {
changeButtonState(ButtonState.PROGRESS)
@ -97,10 +91,6 @@ private fun readCard(fromScreen: AppScreen) = scope.launch {
changeButtonState(ButtonState.ENABLED)
},
onSuccess = { scanResponse ->
when (fromScreen) {
AppScreen.Wallet -> Analytics.send(MainScreen.CardWasScanned())
else -> Analytics.send(IntroductionProcess.CardWasScanned())
}
scope.launch {
if (preferencesStorage.shouldSaveUserWallets) {
val userWallet = UserWalletBuilder(scanResponse).build() ?: return@launch

View file

@ -18,9 +18,6 @@ private fun internalReduce(action: Action, state: AppState): HomeState {
is HomeAction.ScanInProgress -> {
state = state.copy(scanInProgress = action.scanInProgress)
}
is HomeAction.ShouldScanCardOnResume -> {
state = state.copy(shouldScanCardOnResume = action.shouldScanCard)
}
is HomeAction.ChangeScanCardButtonState -> {
state = state.copy(btnScanState = action.state)
}

View file

@ -6,7 +6,6 @@ import com.tangem.tap.features.wallet.redux.ProgressState
import org.rekotlin.StateType
data class HomeState(
val shouldScanCardOnResume: Boolean = false,
val scanInProgress: Boolean = false,
val btnScanState: IndeterminateProgressButton = IndeterminateProgressButton(ButtonState.ENABLED),
) : StateType {

View file

@ -7,6 +7,7 @@ import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.address.AddressType
import com.tangem.core.analytics.AnalyticsEvent
import com.tangem.domain.common.CardDTO
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.common.redux.NotificationAction
@ -142,7 +143,7 @@ sealed class WalletAction : Action {
object Failure : WalletAction()
}
object Scan : WalletAction()
data class Scan(val onScanSuccessEvent: AnalyticsEvent?) : WalletAction()
data class Send(val amount: Amount? = null) : WalletAction()

View file

@ -5,8 +5,8 @@ import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.WalletManager
import com.tangem.common.doOnSuccess
import com.tangem.common.extensions.guard
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.extensions.withMainContext
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.MainScreen
import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken
@ -173,7 +173,7 @@ class MultiWalletMiddleware {
if (selectedWallet != null) {
scanAndUpdateCard(selectedWallet, walletState)
} else {
store.dispatch(WalletAction.Scan)
store.dispatch(WalletAction.Scan(onScanSuccessEvent = null))
}
}
}
@ -185,6 +185,7 @@ class MultiWalletMiddleware {
) = scope.launch(Dispatchers.Default) {
Analytics.send(MainScreen.CardWasScanned())
ScanCardProcessor.scan(
analyticsEvent = null,
cardId = selectedUserWallet.cardId,
additionalBlockchainsToDerive = state?.missingDerivations?.map { it.blockchain },
) { scanResponse ->

View file

@ -59,6 +59,7 @@ import com.tangem.wallet.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.rekotlin.Action
import org.rekotlin.DispatchFunction
@ -194,8 +195,11 @@ class WalletMiddleware {
}
}
is WalletAction.Scan -> {
store.dispatch(HomeAction.ShouldScanCardOnResume(true))
store.dispatch(NavigationAction.PopBackTo(AppScreen.Home))
scope.launch {
delay(700)
store.dispatchOnMain(HomeAction.ReadCard(action.onScanSuccessEvent))
}
}
is WalletAction.LoadCardInfo -> {
val attestationFailed = action.card.attestation.status == Attestation.Status.Failed
@ -366,7 +370,7 @@ class WalletMiddleware {
}
else -> {
Analytics.send(MainScreen.ButtonScanCard())
store.dispatch(WalletAction.Scan)
store.dispatch(WalletAction.Scan(MainScreen.CardWasScanned()))
}
}
}

View file

@ -121,7 +121,7 @@ internal class WalletSelectorMiddleware {
}
private fun unlockWalletsWithBiometry() {
Analytics.send(MyWallets.Button.UnlockWithBiometrics)
Analytics.send(MyWallets.Button.UnlockWithBiometrics())
scope.launch {
userWalletsListManager.unlockWithBiometry()
@ -135,7 +135,7 @@ internal class WalletSelectorMiddleware {
}
private fun addWallet() = scope.launch {
Analytics.send(MyWallets.Button.ScanNewCard)
Analytics.send(MyWallets.Button.ScanNewCard())
val prevUseBiometricsForAccessCode = tangemSdkManager.useBiometricsForAccessCode()
@ -145,6 +145,7 @@ internal class WalletSelectorMiddleware {
)
ScanCardProcessor.scan(
analyticsEvent = MyWallets.CardWasScanned(),
onWalletNotCreated = {
// No need to rollback policy, continue with the policy set before the card scan
store.dispatchOnMain(WalletSelectorAction.AddWallet.Success)
@ -175,8 +176,6 @@ internal class WalletSelectorMiddleware {
return userWalletsListManager.save(userWallet)
.doOnSuccess {
Analytics.send(MyWallets.CardWasScanned)
store.dispatchOnMain(WalletSelectorAction.AddWallet.Success)
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
store.onUserWalletSelected(userWallet)
@ -227,7 +226,7 @@ internal class WalletSelectorMiddleware {
}
private fun deleteWallets(userWalletsIds: List<UserWalletId>, state: WalletSelectorState) {
Analytics.send(MyWallets.Button.DeleteWalletTapped)
Analytics.send(MyWallets.Button.DeleteWalletTapped())
scope.launch {
when (userWalletsIds.size) {
@ -244,7 +243,7 @@ internal class WalletSelectorMiddleware {
}
private fun renameWallet(userWalletId: UserWalletId, newName: String) {
Analytics.send(MyWallets.Button.EditWalletTapped)
Analytics.send(MyWallets.Button.EditWalletTapped())
scope.launch {
userWalletsListManager.update(userWalletId) { it.copy(name = newName) }

View file

@ -20,9 +20,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
import androidx.fragment.app.viewModels
import com.tangem.core.analytics.Analytics
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.analytics.Analytics
import com.tangem.tap.common.analytics.events.MyWallets
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
import com.tangem.tap.features.walletSelector.ui.components.RenameWalletDialogContent
@ -33,7 +33,7 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<Wa
private val viewModel by viewModels<WalletSelectorViewModel>()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
Analytics.send(MyWallets.MyWalletsScreenOpened)
Analytics.send(MyWallets.MyWalletsScreenOpened())
return super.onCreateDialog(savedInstanceState)
}

View file

@ -4,6 +4,7 @@ import android.content.Intent
import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess
import com.tangem.domain.common.ScanResponse
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.onUserWalletSelected
import com.tangem.tap.common.redux.AppState
@ -98,6 +99,7 @@ internal class WelcomeMiddleware {
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
)
ScanCardProcessor.scan(
analyticsEvent = IntroductionProcess.CardWasScanned(),
onSuccess = { scanResponse ->
scope.launch { onCardScanned(scanResponse) }
},