Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-10 15:46:42 +05:00
parent 788721e113
commit facd6bb2ca
7 changed files with 76 additions and 37 deletions

View file

@ -16,11 +16,11 @@ sealed class WalletSettingsAnalyticEvents(
params = mapOf(STATUS to enabled.value),
)
object WalletSettingsScreenOpened : WalletSettingsAnalyticEvents(
class WalletSettingsScreenOpened : WalletSettingsAnalyticEvents(
event = "Wallet Settings Screen Opened",
)
object ButtonBackup : WalletSettingsAnalyticEvents(
class ButtonBackup : WalletSettingsAnalyticEvents(
event = "Button - Backup",
)
@ -32,13 +32,13 @@ sealed class WalletSettingsAnalyticEvents(
)
data class BackupScreenOpened(
val isManualBackupEnabled: Boolean,
val isBackedUp: Boolean,
) : WalletSettingsAnalyticEvents(
event = "Backup Screen Opened",
params = mapOf("Manual Backup" to if (isManualBackupEnabled) "Enabled" else "Disabled"),
params = mapOf("Manual Backup" to if (isBackedUp) "Yes" else "No"),
)
object ButtonRecoveryPhrase : WalletSettingsAnalyticEvents(
class ButtonRecoveryPhrase : WalletSettingsAnalyticEvents(
event = "Button - Recovery phrase",
)
@ -59,27 +59,27 @@ sealed class WalletSettingsAnalyticEvents(
}
}
object ButtonHardwareUpdate : WalletSettingsAnalyticEvents(
class ButtonHardwareUpdate : WalletSettingsAnalyticEvents(
event = "Button - Hardware Update",
)
object HardwareUpgradeScreenOpened : WalletSettingsAnalyticEvents(
class HardwareUpgradeScreenOpened : WalletSettingsAnalyticEvents(
event = "Hardware Upgrade Screen Opened",
)
object ButtonCreateNewWallet : WalletSettingsAnalyticEvents(
class ButtonCreateNewWallet : WalletSettingsAnalyticEvents(
event = "Button - Create New Wallet",
)
object ButtonUpgradeCurrent : WalletSettingsAnalyticEvents(
class ButtonUpgradeCurrent : WalletSettingsAnalyticEvents(
event = "Button - Upgrade Current",
)
object CreateWalletScreenOpened : WalletSettingsAnalyticEvents(
class CreateWalletScreenOpened : WalletSettingsAnalyticEvents(
event = "Create Wallet Screen Opened",
)
object HardwareBackupScreenOpened : WalletSettingsAnalyticEvents(
class HardwareBackupScreenOpened : WalletSettingsAnalyticEvents(
event = "Hardware Backup Screen Opened",
)
@ -141,7 +141,7 @@ sealed class WalletSettingsAnalyticEvents(
params = mapOf(AnalyticsParam.Key.SOURCE to source),
)
object ButtonStartUpgrade : WalletSettingsAnalyticEvents(
class ButtonStartUpgrade : WalletSettingsAnalyticEvents(
event = "Button - Start Upgrade",
)

View file

@ -6,6 +6,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.navigation.Router
@ -51,6 +52,7 @@ internal class CreateHardwareWalletModel @Inject constructor(
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
private val saveWalletUseCase: SaveWalletUseCase,
private val userWalletsListRepository: UserWalletsListRepository,
private val trackingContextProxy: TrackingContextProxy,
private val analyticsEventHandler: AnalyticsEventHandler,
) : Model() {
@ -64,10 +66,12 @@ internal class CreateHardwareWalletModel @Inject constructor(
)
init {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.CreateWalletScreenOpened)
trackingContextProxy.addHotWalletContext()
analyticsEventHandler.send(WalletSettingsAnalyticEvents.CreateWalletScreenOpened())
}
override fun onDestroy() {
trackingContextProxy.removeContext()
super.onDestroy()
}

View file

@ -9,6 +9,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -62,6 +63,7 @@ internal class UpgradeWalletModel @Inject constructor(
private val tangemSdkManager: TangemSdkManager,
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
private val trackingContextProxy: TrackingContextProxy,
private val analyticsEventHandler: AnalyticsEventHandler,
) : Model() {
private val params = paramsContainer.require<UpgradeWalletComponent.Params>()
@ -79,10 +81,12 @@ internal class UpgradeWalletModel @Inject constructor(
)
init {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.HardwareUpgradeScreenOpened)
trackingContextProxy.addHotWalletContext()
analyticsEventHandler.send(WalletSettingsAnalyticEvents.HardwareUpgradeScreenOpened())
}
override fun onDestroy() {
trackingContextProxy.removeContext()
clearHotWalletContextualUnlockUseCase.invoke(params.userWalletId)
super.onDestroy()
}
@ -96,7 +100,7 @@ internal class UpgradeWalletModel @Inject constructor(
private fun onContinueClick() {
analyticsEventHandler.send(IntroductionProcess.ButtonScanCard(AnalyticsParam.ScreensSources.Upgrade))
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonStartUpgrade)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonStartUpgrade())
scanCard()
}

View file

@ -70,16 +70,16 @@ internal class WalletActivationModel @Inject constructor(
}
val currentRoute: MutableStateFlow<WalletActivationRoute> = MutableStateFlow(startRoute)
private val source = AnalyticsParam.ScreensSources.Main
private val action = WalletSettingsAnalyticEvents.RecoveryPhraseScreenAction.Backup
private val analyticsSource = AnalyticsParam.ScreensSources.Main
private val analyticsAction = WalletSettingsAnalyticEvents.RecoveryPhraseScreenAction.Backup
init {
trackingContextProxy.addHotWalletContext()
if (startRoute is WalletActivationRoute.ManualBackupStart) {
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.RecoveryPhraseScreenInfo(
source = source.value,
action = action.value,
source = analyticsSource.value,
action = analyticsAction.value,
),
)
}
@ -160,8 +160,8 @@ internal class WalletActivationModel @Inject constructor(
stackNavigation.push(WalletActivationRoute.ManualBackupPhrase)
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.RecoveryPhraseScreen(
source = source.value,
action = action.value,
source = analyticsSource.value,
action = analyticsAction.value,
),
)
}
@ -172,8 +172,8 @@ internal class WalletActivationModel @Inject constructor(
stackNavigation.push(WalletActivationRoute.ManualBackupCheck)
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.RecoveryPhraseCheck(
source = source.value,
action = action.value,
source = analyticsSource.value,
action = analyticsAction.value,
),
)
}
@ -184,8 +184,8 @@ internal class WalletActivationModel @Inject constructor(
stackNavigation.push(WalletActivationRoute.ManualBackupCompleted)
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.BackupCompleteScreen(
source = source.value,
action = action.value,
source = analyticsSource.value,
action = analyticsAction.value,
),
)
}
@ -193,6 +193,9 @@ internal class WalletActivationModel @Inject constructor(
inner class ManualBackupCompletedModelCallbacks : ManualBackupCompletedComponent.ModelCallbacks {
override fun onContinueClick(userWalletId: UserWalletId) {
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.AccessCodeScreenOpened(source = analyticsSource.value),
)
stackNavigation.push(WalletActivationRoute.SetAccessCode)
}
@ -201,6 +204,9 @@ internal class WalletActivationModel @Inject constructor(
inner class AccessCodeModelCallbacks : AccessCodeComponent.ModelCallbacks {
override fun onNewAccessCodeInput(userWalletId: UserWalletId, accessCode: String) {
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.ReEnterAccessCodeScreen(source = analyticsSource.value),
)
stackNavigation.push(WalletActivationRoute.ConfirmAccessCode(accessCode))
}

View file

@ -4,6 +4,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -25,6 +26,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
@Suppress("LongParameterList")
@ -37,11 +39,14 @@ internal class WalletBackupModel @Inject constructor(
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
private val urlOpener: UrlOpener,
private val router: Router,
private val trackingContextProxy: TrackingContextProxy,
private val analyticsEventHandler: AnalyticsEventHandler,
) : Model() {
private val params: WalletBackupComponent.Params = paramsContainer.require()
private val isScreenOpenedEventSent: AtomicBoolean = AtomicBoolean(false)
val uiState: StateFlow<WalletBackupUM>
field = MutableStateFlow(
WalletBackupUM(
@ -68,20 +73,33 @@ internal class WalletBackupModel @Inject constructor(
)
init {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.BackupScreenOpened(isManualBackupEnabled = true))
trackingContextProxy.addHotWalletContext()
getUserWalletUseCase.invokeFlow(params.userWalletId)
.onEach { either ->
either.fold(
ifLeft = {
Timber.e("Error on getting user wallet: $it")
},
ifRight = {
updateBackupStatuses(it)
ifRight = { userWallet ->
if (!isScreenOpenedEventSent.get() && userWallet is UserWallet.Hot) {
analyticsEventHandler.send(
event = WalletSettingsAnalyticEvents.BackupScreenOpened(
isBackedUp = userWallet.backedUp,
),
)
isScreenOpenedEventSent.set(true)
}
updateBackupStatuses(userWallet)
},
)
}.launchIn(modelScope)
}
override fun onDestroy() {
trackingContextProxy.removeContext()
super.onDestroy()
}
private fun updateBackupStatuses(userWallet: UserWallet) {
uiState.update { currentState ->
if (userWallet is UserWallet.Hot) {
@ -119,7 +137,7 @@ internal class WalletBackupModel @Inject constructor(
}
private fun onRecoveryPhraseClick() {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonRecoveryPhrase)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonRecoveryPhrase())
if (uiState.value.backedUp) {
getUserWalletUseCase.invoke(params.userWalletId)
.fold(
@ -162,7 +180,7 @@ internal class WalletBackupModel @Inject constructor(
}
private fun onHardwareWalletClick() {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonHardwareUpdate)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonHardwareUpdate())
router.push(AppRoute.WalletHardwareBackup(params.userWalletId))
}
}

View file

@ -5,6 +5,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.analytics.utils.TrackingContextProxy
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -50,6 +51,7 @@ internal class WalletHardwareBackupModel @Inject constructor(
private val urlOpener: UrlOpener,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val messageSender: UiMessageSender,
private val trackingContextProxy: TrackingContextProxy,
private val analyticsEventHandler: AnalyticsEventHandler,
) : Model() {
@ -115,10 +117,16 @@ internal class WalletHardwareBackupModel @Inject constructor(
)
init {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.HardwareBackupScreenOpened)
trackingContextProxy.addHotWalletContext()
analyticsEventHandler.send(WalletSettingsAnalyticEvents.HardwareBackupScreenOpened())
showPurchaseBlockWithDelay()
}
override fun onDestroy() {
trackingContextProxy.removeContext()
super.onDestroy()
}
private fun showPurchaseBlockWithDelay() {
modelScope.launch {
delay(SHOW_PURCHASE_BLOCK_DELAY)
@ -127,7 +135,7 @@ internal class WalletHardwareBackupModel @Inject constructor(
}
private fun onCreateNewWalletClick() {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonCreateNewWallet)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonCreateNewWallet())
router.push(AppRoute.CreateHardwareWallet)
}
@ -135,7 +143,7 @@ internal class WalletHardwareBackupModel @Inject constructor(
val userWallet = getUserWalletUseCase.invoke(params.userWalletId)
.getOrElse { error("Cannot find user wallet with id: ${params.userWalletId.stringValue}") }
if (userWallet is UserWallet.Hot) {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonUpgradeCurrent)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonUpgradeCurrent())
if (!userWallet.backedUp) {
messageSender.send(makeBackupAtFirstAlertBS)
} else {

View file

@ -115,7 +115,7 @@ internal class WalletSettingsModel @Inject constructor(
init {
getUserWalletUseCase.invoke(params.userWalletId).onRight { wallet ->
trackingContextProxy.addContext(wallet)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.WalletSettingsScreenOpened)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.WalletSettingsScreenOpened())
}
fun combineUI(wallet: UserWallet) = combine(
@ -384,7 +384,6 @@ internal class WalletSettingsModel @Inject constructor(
}
private fun onUpgradeWalletClick() {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonHardwareUpdate)
if (!state.value.isWalletBackedUp) {
showMakeBackupAtFirstAlertBS(
isUpgradeFlow = true,
@ -404,7 +403,7 @@ internal class WalletSettingsModel @Inject constructor(
}
private fun onBackupClick() {
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonBackup)
analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonBackup())
router.push(AppRoute.WalletBackup(params.userWalletId))
}
@ -441,7 +440,7 @@ internal class WalletSettingsModel @Inject constructor(
shouldSetAccessCode = true,
analyticsSource = AnalyticsParam.ScreensSources.WalletSettings.value,
analyticsAction = if (isUpgradeFlow) {
RecoveryPhraseScreenAction.Backup.value
RecoveryPhraseScreenAction.Upgrade.value
} else {
RecoveryPhraseScreenAction.AccessCode.value
},