From e10ff4c65165bbba21edcdcc69fbaffbb691fd52 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 14 Nov 2024 16:27:13 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../analytics/TokenScreenAnalyticsEvent.kt | 40 +++++++++++ .../viewmodels/TokenDetailsViewModel.kt | 70 +++++++++++++++++-- 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt index c661b761bd..d42f2f31b5 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt @@ -1,6 +1,7 @@ package com.tangem.domain.tokens.model.analytics import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason /** [REDACTED_AUTHOR] @@ -77,4 +78,43 @@ sealed class TokenScreenAnalyticsEvent( event = "Staking Clicked", params = mapOf("Token" to token), ) + + class NoticeActionInactive(token: String, tokenAction: TokenAction, reason: String) : TokenScreenAnalyticsEvent( + "Notice - Action Inactive", + params = buildMap { + put("Token", token) + put("Action", tokenAction.action) + if (reason.isNotEmpty()) { + put("Reason", reason) + } + }, + ) { + sealed class TokenAction(val action: String) { + data object BuyAction : TokenAction("Buy") + data object SellAction : TokenAction("Sell") + data object SwapAction : TokenAction("Swap") + data object SendAction : TokenAction("Send") + data object ReceiveAction : TokenAction("Receive") + } + } + + companion object { + private const val UNAVAILABLE = "Unavailable" + private const val EMPTY = "Empty" + private const val PENDING = "Pending" + + fun ScenarioUnavailabilityReason.toReasonAnalyticsText(): String { + return when (this) { + is ScenarioUnavailabilityReason.BuyUnavailable -> UNAVAILABLE + is ScenarioUnavailabilityReason.EmptyBalance -> EMPTY + ScenarioUnavailabilityReason.None -> "" + is ScenarioUnavailabilityReason.NotExchangeable -> UNAVAILABLE + is ScenarioUnavailabilityReason.NotSupportedBySellService -> UNAVAILABLE + is ScenarioUnavailabilityReason.PendingTransaction -> PENDING + is ScenarioUnavailabilityReason.StakingUnavailable -> UNAVAILABLE + ScenarioUnavailabilityReason.UnassociatedAsset -> UNAVAILABLE + ScenarioUnavailabilityReason.Unreachable -> "" + } + } + } } \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index 34c9d9f591..8130b96926 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -48,6 +48,7 @@ import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.analytics.TokenExchangeAnalyticsEvent import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent +import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent import com.tangem.domain.tokens.repository.QuotesRepository import com.tangem.domain.transaction.error.AssociateAssetError @@ -446,7 +447,14 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onBuyClick(unavailabilityReason: ScenarioUnavailabilityReason) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonBuy(cryptoCurrency.symbol)) - if (handleUnavailabilityReason(unavailabilityReason)) return + if (handleUnavailabilityReason( + unavailabilityReason = unavailabilityReason, + tokenSymbol = cryptoCurrency.symbol, + tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.BuyAction, + ) + ) { + return + } showErrorIfDemoModeOrElse { val status = cryptoCurrencyStatus ?: return@showErrorIfDemoModeOrElse @@ -482,7 +490,14 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onSendClick(unavailabilityReason: ScenarioUnavailabilityReason) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonSend(cryptoCurrency.symbol)) - if (handleUnavailabilityReason(unavailabilityReason)) return + if (handleUnavailabilityReason( + unavailabilityReason = unavailabilityReason, + tokenSymbol = cryptoCurrency.symbol, + tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.SendAction, + ) + ) { + return + } sendCurrency(status = cryptoCurrencyStatus ?: return) } @@ -551,7 +566,14 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onReceiveClick(unavailabilityReason: ScenarioUnavailabilityReason) { val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return - if (handleUnavailabilityReason(unavailabilityReason)) return + if (handleUnavailabilityReason( + unavailabilityReason = unavailabilityReason, + tokenSymbol = cryptoCurrency.symbol, + tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.ReceiveAction, + ) + ) { + return + } viewModelScope.launch(dispatchers.main) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrency.symbol)) @@ -571,7 +593,14 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onStakeClick(unavailabilityReason: ScenarioUnavailabilityReason) { - if (handleUnavailabilityReason(unavailabilityReason)) return + if (handleUnavailabilityReason( + unavailabilityReason = unavailabilityReason, + tokenSymbol = cryptoCurrency.symbol, + tokenAction = null, + ) + ) { + return + } openStaking() } @@ -603,7 +632,14 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onSellClick(unavailabilityReason: ScenarioUnavailabilityReason) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonSell(cryptoCurrency.symbol)) - if (handleUnavailabilityReason(unavailabilityReason)) return + if (handleUnavailabilityReason( + unavailabilityReason = unavailabilityReason, + tokenSymbol = cryptoCurrency.symbol, + tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.SellAction, + ) + ) { + return + } showErrorIfDemoModeOrElse { val status = cryptoCurrencyStatus ?: return@showErrorIfDemoModeOrElse @@ -620,7 +656,14 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onSwapClick(unavailabilityReason: ScenarioUnavailabilityReason) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonExchange(cryptoCurrency.symbol)) - if (handleUnavailabilityReason(unavailabilityReason)) return + if (handleUnavailabilityReason( + unavailabilityReason = unavailabilityReason, + tokenSymbol = cryptoCurrency.symbol, + tokenAction = TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction.SwapAction, + ) + ) { + return + } appRouter.push(AppRoute.Swap(currency = cryptoCurrency, userWalletId = userWalletId)) } @@ -854,8 +897,21 @@ internal class TokenDetailsViewModel @Inject constructor( internalUiState.value = stateFactory.getStateWithUpdatedBalanceSegmentedButtonConfig(config) } - private fun handleUnavailabilityReason(unavailabilityReason: ScenarioUnavailabilityReason): Boolean { + private fun handleUnavailabilityReason( + unavailabilityReason: ScenarioUnavailabilityReason, + tokenSymbol: String, + tokenAction: TokenScreenAnalyticsEvent.NoticeActionInactive.TokenAction?, + ): Boolean { if (unavailabilityReason == ScenarioUnavailabilityReason.None) return false + if (tokenAction != null) { + analyticsEventsHandler.send( + TokenScreenAnalyticsEvent.NoticeActionInactive( + token = tokenSymbol, + tokenAction = tokenAction, + reason = unavailabilityReason.toReasonAnalyticsText(), + ), + ) + } internalUiState.value = stateFactory.getStateWithActionButtonErrorDialog(unavailabilityReason)