From f3f29813e0ec5597c8f7e5026bcd43838a36ace8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Sep 2023 11:16:22 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../handlers/BuyCurrencyIntentHandler.kt | 4 +- .../tokenreceive/TokenReceiveBottomSheet.kt | 2 + .../TokenReceiveBottomSheetConfig.kt | 2 + domain/tokens/models/build.gradle.kts | 1 + .../analytics/TokenReceiveAnalyticsEvent.kt | 19 ++++++ features/tokendetails/impl/build.gradle.kts | 2 + .../analytics/TokenScreenEvent.kt | 63 +++++++++++++++++++ .../state/factory/TokenDetailsStateFactory.kt | 9 ++- .../viewmodels/TokenDetailsViewModel.kt | 27 +++++++- .../wallet/viewmodels/WalletViewModel.kt | 7 +++ 10 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenReceiveAnalyticsEvent.kt create mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenScreenEvent.kt diff --git a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt index 39dda7cd24..83c294bfb3 100644 --- a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt +++ b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BuyCurrencyIntentHandler.kt @@ -3,8 +3,8 @@ package com.tangem.tap.features.intentHandler.handlers import android.content.Intent import android.net.Uri import com.tangem.core.analytics.Analytics +import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenScreenEvent import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.Token import com.tangem.tap.features.intentHandler.IntentHandler import com.tangem.tap.network.exchangeServices.ExchangeUrlBuilder import com.tangem.tap.store @@ -21,7 +21,7 @@ class BuyCurrencyIntentHandler : IntentHandler { val successUri = Uri.parse(ExchangeUrlBuilder.SUCCESS_URL) return if (data.host == successUri.host && data.authority == successUri.authority) { val currencyType = AnalyticsParam.CurrencyType.Currency(currency) - Analytics.send(Token.Bought(currencyType)) + Analytics.send(TokenScreenEvent.Bought(currencyType.value)) true } else { false diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt index beadf33d24..ee8b8d3581 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt @@ -76,6 +76,7 @@ private fun TokenReceiveBottomSheetContent(content: TokenReceiveBottomSheetConfi text = stringResource(id = R.string.common_copy), iconResId = R.drawable.ic_copy_24, onClick = { + content.onCopyClick.invoke() hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) clipboardManager.setText(AnnotatedString(selectedAddress.value)) }, @@ -85,6 +86,7 @@ private fun TokenReceiveBottomSheetContent(content: TokenReceiveBottomSheetConfi text = stringResource(id = R.string.common_share), iconResId = R.drawable.ic_share_24, onClick = { + content.onShareClick.invoke() hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) context.shareText(selectedAddress.value) }, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt index b1b84dc016..c2531a839d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt @@ -7,4 +7,6 @@ class TokenReceiveBottomSheetConfig( val symbol: String, val network: String, val addresses: List, + val onCopyClick: () -> Unit, + val onShareClick: () -> Unit, ) : TangemBottomSheetConfigContent \ No newline at end of file diff --git a/domain/tokens/models/build.gradle.kts b/domain/tokens/models/build.gradle.kts index 0e4d43a1fc..e9075cefa0 100644 --- a/domain/tokens/models/build.gradle.kts +++ b/domain/tokens/models/build.gradle.kts @@ -11,4 +11,5 @@ android { dependencies { implementation(projects.domain.txhistory.models) + implementation(projects.core.analytics.models) } \ No newline at end of file diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenReceiveAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenReceiveAnalyticsEvent.kt new file mode 100644 index 0000000000..ae658aee6d --- /dev/null +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/models/analytics/TokenReceiveAnalyticsEvent.kt @@ -0,0 +1,19 @@ +package com.tangem.domain.tokens.models.analytics + +import com.tangem.core.analytics.models.AnalyticsEvent + +sealed class TokenReceiveAnalyticsEvent( + event: String, + params: Map = mapOf(), +) : AnalyticsEvent("Token / Receive", event, params, null) { + + class ButtonCopyAddress(token: String) : TokenReceiveAnalyticsEvent( + event = "Button - Copy Address", + params = mapOf("Token" to token), + ) + + class ButtonShareAddress(token: String) : TokenReceiveAnalyticsEvent( + event = "Button - Share Address", + params = mapOf("Token" to token), + ) +} \ No newline at end of file diff --git a/features/tokendetails/impl/build.gradle.kts b/features/tokendetails/impl/build.gradle.kts index 704e1f8bc9..97561c5bb1 100644 --- a/features/tokendetails/impl/build.gradle.kts +++ b/features/tokendetails/impl/build.gradle.kts @@ -47,6 +47,8 @@ dependencies { implementation(projects.core.navigation) implementation(projects.core.ui) implementation(projects.core.utils) + implementation(projects.core.analytics) + implementation(projects.core.analytics.models) /** Domain modules */ implementation(projects.domain.appCurrency) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenScreenEvent.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenScreenEvent.kt new file mode 100644 index 0000000000..758184763f --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/analytics/TokenScreenEvent.kt @@ -0,0 +1,63 @@ +package com.tangem.feature.tokendetails.presentation.tokendetails.analytics + +import com.tangem.core.analytics.models.AnalyticsEvent + +/** +[REDACTED_AUTHOR] + */ +sealed class TokenScreenEvent( + event: String, + params: Map = mapOf(), + error: Throwable? = null, +) : AnalyticsEvent("Token", event, params, error) { + + class Refreshed(token: String) : TokenScreenEvent( + event = "Refreshed", + params = mapOf("Token" to token), + ) + + class ButtonRemoveToken(token: String) : TokenScreenEvent( + "Button - Remove Token", + params = mapOf("Token" to token), + ) + + class ButtonExplore(token: String) : TokenScreenEvent( + event = "Button - Explore", + params = mapOf("Token" to token), + ) + + class ButtonReload(token: String) : TokenScreenEvent( + event = "Button - Reload", + params = mapOf("Token" to token), + ) + + class ButtonBuy(token: String) : TokenScreenEvent( + event = "Button - Buy", + params = mapOf("Token" to token), + ) + + class ButtonSell(token: String) : TokenScreenEvent( + event = "Button - Sell", + params = mapOf("Token" to token), + ) + + class ButtonExchange(token: String) : TokenScreenEvent( + event = "Button - Exchange", + params = mapOf("Token" to token), + ) + + class ButtonSend(token: String) : TokenScreenEvent( + event = "Button - Send", + params = mapOf("Token" to token), + ) + + class ButtonReceive(token: String) : TokenScreenEvent( + event = "Button - Receive", + params = mapOf("Token" to token), + ) + + class Bought(token: String) : TokenScreenEvent( + event = "Token Bought", + params = mapOf("Token" to token), + ) +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index 606c36974f..4a54ef00de 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -144,7 +144,12 @@ internal class TokenDetailsStateFactory( return refreshStateConverter.convert(false) } - fun getStateWithReceiveBottomSheet(currency: CryptoCurrency, addresses: List
): TokenDetailsState { + fun getStateWithReceiveBottomSheet( + currency: CryptoCurrency, + addresses: List
, + sendCopyAnalyticsEvent: () -> Unit, + sendShareAnalyticsEvent: () -> Unit, + ): TokenDetailsState { return currentStateProvider().copy( bottomSheetConfig = TangemBottomSheetConfig( isShow = true, @@ -159,6 +164,8 @@ internal class TokenDetailsStateFactory( type = AddressModel.Type.valueOf(it.type.name), ) }, + onCopyClick = sendCopyAnalyticsEvent, + onShareClick = sendShareAnalyticsEvent, ), ), ) 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 e848594478..4487529033 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 @@ -8,6 +8,7 @@ import androidx.paging.cachedIn import arrow.core.getOrElse import com.tangem.blockchain.common.address.AddressType import com.tangem.common.Provider +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.IsBalanceHiddenUseCase @@ -17,6 +18,7 @@ import com.tangem.domain.tokens.* import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.walletmanager.WalletManagersFacade @@ -25,6 +27,7 @@ import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter +import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenScreenEvent import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory import com.tangem.features.tokendetails.navigation.TokenDetailsArguments @@ -39,7 +42,7 @@ import timber.log.Timber import javax.inject.Inject import kotlin.properties.Delegates -@Suppress("LongParameterList") +@Suppress("LongParameterList", "LargeClass") @HiltViewModel internal class TokenDetailsViewModel @Inject constructor( private val dispatchers: CoroutineDispatcherProvider, @@ -59,6 +62,7 @@ internal class TokenDetailsViewModel @Inject constructor( private val getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase, private val walletManagersFacade: WalletManagersFacade, private val reduxStateHolder: ReduxStateHolder, + private val analyticsEventsHandler: AnalyticsEventHandler, savedStateHandle: SavedStateHandle, ) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents { @@ -208,6 +212,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onBuyClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonBuy(cryptoCurrency.symbol)) val status = cryptoCurrencyStatus ?: return reduxStateHolder.dispatch( @@ -220,10 +225,13 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onReloadClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonReload(cryptoCurrency.symbol)) updateTxHistory() } override fun onSendClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonSend(cryptoCurrency.symbol)) + val cryptoCurrencyStatus = cryptoCurrencyStatus ?: return when (cryptoCurrencyStatus.currency) { @@ -261,6 +269,8 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onReceiveClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonReceive(cryptoCurrency.symbol)) + viewModelScope.launch(dispatchers.io) { val addresses = walletManagersFacade.getAddress( userWalletId = wallet.walletId, @@ -270,11 +280,19 @@ internal class TokenDetailsViewModel @Inject constructor( uiState = stateFactory.getStateWithReceiveBottomSheet( currency = cryptoCurrency, addresses = addresses, + sendCopyAnalyticsEvent = { + analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(cryptoCurrency.symbol)) + }, + sendShareAnalyticsEvent = { + analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonShareAddress(cryptoCurrency.symbol)) + }, ) } } override fun onSellClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonSell(cryptoCurrency.symbol)) + val status = cryptoCurrencyStatus ?: return reduxStateHolder.dispatch( TradeCryptoAction.New.Sell( @@ -285,6 +303,8 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onSwapClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonExchange(cryptoCurrency.symbol)) + reduxStateHolder.dispatch(TradeCryptoAction.New.Swap(cryptoCurrency)) } @@ -293,6 +313,8 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onHideClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonRemoveToken(cryptoCurrency.symbol)) + viewModelScope.launch { val hasLinkedTokens = removeCurrencyUseCase.hasLinkedTokens(wallet.walletId, cryptoCurrency) uiState = if (hasLinkedTokens) { @@ -312,6 +334,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onExploreClick() { + analyticsEventsHandler.send(TokenScreenEvent.ButtonExplore(cryptoCurrency.symbol)) viewModelScope.launch(dispatchers.io) { val addresses = walletManagersFacade.getAddress( userWalletId = wallet.walletId, @@ -345,6 +368,8 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onRefreshSwipe() { + analyticsEventsHandler.send(TokenScreenEvent.Refreshed(cryptoCurrency.symbol)) + uiState = stateFactory.getRefreshingState() viewModelScope.launch(dispatchers.io) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index a76a16ffe8..015c3e99a5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -43,6 +43,7 @@ import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.NetworkGroup import com.tangem.domain.tokens.model.TokenList +import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.userwallets.UserWalletBuilder @@ -639,6 +640,12 @@ internal class WalletViewModel @Inject constructor( type = AddressModel.Type.valueOf(it.type.name), ) }, + onCopyClick = { + analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(currency.symbol)) + }, + onShareClick = { + analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonShareAddress(currency.symbol)) + }, ), ) }