Updated on 2026-08-14
This commit is contained in:
parent
2336cb6aaa
commit
beceddf1fb
13 changed files with 89 additions and 0 deletions
|
|
@ -17,6 +17,7 @@ dependencies {
|
|||
/* Project - Core */
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.analytics.models)
|
||||
|
||||
/* Compose */
|
||||
implementation(deps.compose.runtime)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ interface ChooseManagedTokensComponent : ComposableContentComponent {
|
|||
val source: Source,
|
||||
val showSendViaSwapNotification: Boolean,
|
||||
val callback: ModelCallback? = null,
|
||||
val analyticsCategoryName: String,
|
||||
)
|
||||
|
||||
enum class Source {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.features.managetokens.component.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.CHOSEN_TOKEN
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
|
||||
sealed class CommonManageTokensAnalyticEvents(
|
||||
category: String,
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category = category, event = event, params = params) {
|
||||
|
||||
data class TokenSearchClicked(
|
||||
val categoryName: String,
|
||||
) : CommonManageTokensAnalyticEvents(category = categoryName, event = "Token Search Clicked")
|
||||
|
||||
/** Searched token chosen event */
|
||||
data class TokenSearched(
|
||||
val categoryName: String,
|
||||
val token: String?,
|
||||
val blockchain: String?,
|
||||
val isTokenChosen: Boolean,
|
||||
) : CommonManageTokensAnalyticEvents(
|
||||
category = categoryName,
|
||||
event = "Token Searched",
|
||||
params = buildMap {
|
||||
put(CHOSEN_TOKEN, if (isTokenChosen) "Yes" else "No")
|
||||
token?.let { put(TOKEN_PARAM, token) }
|
||||
blockchain?.let { put(BLOCKCHAIN, blockchain) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -59,9 +59,11 @@ internal class DefaultChooseManagedTokensComponent @AssistedInject constructor(
|
|||
context = childByContext(componentContext),
|
||||
params = SwapChooseTokenNetworkComponent.Params(
|
||||
userWalletId = config.userWalletId,
|
||||
analyticsCategoryName = params.analyticsCategoryName,
|
||||
initialCurrency = config.initialCurrency,
|
||||
selectedCurrency = config.selectedCurrency,
|
||||
token = config.token,
|
||||
isSearchedToken = config.isSearchedToken,
|
||||
onDismiss = model.bottomSheetNavigation::dismiss,
|
||||
onResult = { swapCurrencies, cryptoCurrency ->
|
||||
componentScope.launch {
|
||||
|
|
|
|||
|
|
@ -14,5 +14,6 @@ internal sealed class ChooseManageTokensBottomSheetConfig {
|
|||
val initialCurrency: CryptoCurrency,
|
||||
val selectedCurrency: CryptoCurrency?,
|
||||
val token: ManagedCryptoCurrency.Token,
|
||||
val isSearchedToken: Boolean,
|
||||
) : ChooseManageTokensBottomSheetConfig()
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import com.arkivanov.decompose.router.slot.SlotNavigation
|
|||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.tangem.common.ui.notifications.NotificationId
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -22,6 +23,7 @@ import com.tangem.features.managetokens.choosetoken.entity.ChooseManagedTokenUM
|
|||
import com.tangem.features.managetokens.component.ChooseManagedTokensComponent
|
||||
import com.tangem.features.managetokens.component.ChooseManagedTokensComponent.Source
|
||||
import com.tangem.features.managetokens.component.ManageTokensSource
|
||||
import com.tangem.features.managetokens.component.analytics.CommonManageTokensAnalyticEvents
|
||||
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensTopBarUM
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensUM
|
||||
|
|
@ -40,12 +42,14 @@ import timber.log.Timber
|
|||
import javax.inject.Inject
|
||||
import kotlin.collections.isNotEmpty
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class ChooseManagedTokensModel @Inject constructor(
|
||||
private val router: Router,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val setShouldShowNotificationUseCase: SetShouldShowNotificationUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
paramsContainer: ParamsContainer,
|
||||
manageTokensListManagerFactory: ManageTokensListManager.Factory,
|
||||
) : Model() {
|
||||
|
|
@ -60,6 +64,7 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
initialCurrency = params.initialCurrency,
|
||||
selectedCurrency = params.selectedCurrency,
|
||||
token = token,
|
||||
isSearchedToken = uiState.value.readContent.search.isActive,
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
@ -132,6 +137,17 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
private fun observeSearchQueryChanges() {
|
||||
uiState
|
||||
.distinctUntilChanged { old, new ->
|
||||
if (!new.readContent.search.isActive && old.readContent.search.isActive) {
|
||||
analyticsEventHandler.send(
|
||||
CommonManageTokensAnalyticEvents.TokenSearched(
|
||||
params.analyticsCategoryName,
|
||||
token = null,
|
||||
blockchain = null,
|
||||
isTokenChosen = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// It's also used to skip search activation to avoid searching an empty query
|
||||
old.readContent.search.query == new.readContent.search.query && new.readContent.search.isActive
|
||||
}
|
||||
|
|
@ -251,6 +267,11 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun toggleSearchBar(isActive: Boolean) {
|
||||
if (isActive) {
|
||||
analyticsEventHandler.send(
|
||||
CommonManageTokensAnalyticEvents.TokenSearchClicked(params.analyticsCategoryName),
|
||||
)
|
||||
}
|
||||
uiState.update { state ->
|
||||
@StringRes val placeholderTextRes = if (isActive) {
|
||||
R.string.manage_tokens_search_placeholder
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
import com.tangem.features.managetokens.component.ChooseManagedTokensComponent
|
||||
import com.tangem.features.send.v2.api.SendComponent
|
||||
import com.tangem.features.send.v2.api.SendEntryPointComponent
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.send.v2.entrypoint.model.SendEntryPointModel
|
||||
import com.tangem.features.swap.v2.api.SendWithSwapComponent
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -126,6 +127,7 @@ internal class DefaultSendEntryPointComponent @AssistedInject constructor(
|
|||
selectedCurrency = null,
|
||||
showSendViaSwapNotification = showSendViaSwapNotification,
|
||||
callback = model,
|
||||
analyticsCategoryName = CommonSendAnalyticEvents.SEND_CATEGORY,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ interface SwapChooseTokenNetworkComponent : ComposableBottomSheetComponent {
|
|||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
val initialCurrency: CryptoCurrency,
|
||||
val analyticsCategoryName: String,
|
||||
val selectedCurrency: CryptoCurrency?,
|
||||
val token: ManagedCryptoCurrency.Token,
|
||||
val isSearchedToken: Boolean,
|
||||
val onDismiss: () -> Unit,
|
||||
val onResult: (SwapCurrencies, CryptoCurrency) -> Unit,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ internal class SwapAmountModel @Inject constructor(
|
|||
selectedCurrency = selectedCurrency.takeIf { isEditMode },
|
||||
source = AppRoute.ChooseManagedTokens.Source.SendViaSwap,
|
||||
showSendViaSwapNotification = showSendViaSwapNotification,
|
||||
analyticsCategoryName = params.analyticsCategoryName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.swap.v2.impl.choosetoken.fromSupported.model
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -10,6 +11,8 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.swap.models.SwapCurrencies
|
||||
import com.tangem.domain.swap.usecase.GetSwapSupportedPairsUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.managetokens.component.analytics.CommonManageTokensAnalyticEvents
|
||||
import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents
|
||||
import com.tangem.features.swap.v2.api.choosetoken.SwapChooseTokenNetworkComponent
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.entity.SwapChooseTokenNetworkContentUM
|
||||
import com.tangem.features.swap.v2.impl.choosetoken.fromSupported.entity.SwapChooseTokenNetworkUM
|
||||
|
|
@ -26,6 +29,7 @@ import kotlinx.coroutines.launch
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class SwapChooseTokenNetworkModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -34,6 +38,7 @@ internal class SwapChooseTokenNetworkModel @Inject constructor(
|
|||
private val createCryptoCurrencyUseCase: CreateCryptoCurrencyUseCase,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val swapChooseTokenAlertFactory: SwapChooseTokenAlertFactory,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model() {
|
||||
|
||||
private val params: SwapChooseTokenNetworkComponent.Params = paramsContainer.require()
|
||||
|
|
@ -103,6 +108,23 @@ internal class SwapChooseTokenNetworkModel @Inject constructor(
|
|||
|
||||
private fun onSwapTokenClick(swapCurrencies: SwapCurrencies, cryptoCurrency: CryptoCurrency) {
|
||||
val prevSelectedCurrency = params.selectedCurrency?.network
|
||||
analyticsEventHandler.send(
|
||||
CommonSendAnalyticEvents.TokenChosen(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
token = cryptoCurrency.symbol,
|
||||
blockchain = cryptoCurrency.network.name,
|
||||
),
|
||||
)
|
||||
if (params.isSearchedToken) {
|
||||
analyticsEventHandler.send(
|
||||
CommonManageTokensAnalyticEvents.TokenSearched(
|
||||
categoryName = params.analyticsCategoryName,
|
||||
token = cryptoCurrency.symbol,
|
||||
blockchain = cryptoCurrency.network.name,
|
||||
isTokenChosen = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (prevSelectedCurrency == null || cryptoCurrency.network == prevSelectedCurrency) {
|
||||
params.onResult(swapCurrencies, cryptoCurrency)
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue