Updated on 2026-08-14
This commit is contained in:
parent
7b534690ff
commit
864d524841
10 changed files with 301 additions and 14 deletions
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.*
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.tokens.ToggleTokenListGroupingUseCase
|
|||
import com.tangem.domain.tokens.ToggleTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.analytics.PortfolioOrganizeTokensAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.CryptoCurrenciesIdsResolver
|
||||
|
|
@ -35,9 +36,10 @@ internal class OrganizeTokensViewModel @Inject constructor(
|
|||
private val toggleTokenListSortingUseCase: ToggleTokenListSortingUseCase,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), OrganizeTokensIntents {
|
||||
) : ViewModel(), DefaultLifecycleObserver, OrganizeTokensIntents {
|
||||
|
||||
lateinit var router: InnerWalletRouter
|
||||
|
||||
|
|
@ -68,11 +70,17 @@ internal class OrganizeTokensViewModel @Inject constructor(
|
|||
|
||||
val uiState: StateFlow<OrganizeTokensState> = stateHolder.stateFlow
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.ScreenOpened)
|
||||
}
|
||||
|
||||
override fun onBackClick() {
|
||||
router.popBackStack()
|
||||
}
|
||||
|
||||
override fun onSortClick() {
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.ByBalance)
|
||||
|
||||
viewModelScope.launch(dispatchers.default) {
|
||||
val list = tokenList ?: return@launch
|
||||
|
||||
|
|
@ -87,6 +95,8 @@ internal class OrganizeTokensViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onGroupClick() {
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.Group)
|
||||
|
||||
viewModelScope.launch(dispatchers.default) {
|
||||
val list = tokenList ?: return@launch
|
||||
|
||||
|
|
@ -107,11 +117,19 @@ internal class OrganizeTokensViewModel @Inject constructor(
|
|||
val listState = uiState.value.itemsState
|
||||
val resolver = CryptoCurrenciesIdsResolver()
|
||||
|
||||
val isGroupedByNetwork = listState is OrganizeTokensListState.GroupedByNetwork
|
||||
val isSortedByBalance = uiState.value.header.isSortedByBalance
|
||||
|
||||
sendAnalyticsEvent(
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
val result = applyTokenListSortingUseCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = resolver.resolve(listState, tokenList),
|
||||
isGroupedByNetwork = listState is OrganizeTokensListState.GroupedByNetwork,
|
||||
isSortedByBalance = uiState.value.header.isSortedByBalance,
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
result.fold(
|
||||
|
|
@ -127,6 +145,8 @@ internal class OrganizeTokensViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onCancelClick() {
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.Cancel)
|
||||
|
||||
router.popBackStack()
|
||||
}
|
||||
|
||||
|
|
@ -166,4 +186,21 @@ internal class OrganizeTokensViewModel @Inject constructor(
|
|||
initialValue = AppCurrency.Default,
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendAnalyticsEvent(isGroupedByNetwork: Boolean, isSortedByBalance: Boolean) {
|
||||
analyticsEventsHandler.send(
|
||||
PortfolioOrganizeTokensAnalyticsEvent.Apply(
|
||||
grouping = if (isGroupedByNetwork) {
|
||||
AnalyticsParam.OnOffState.On
|
||||
} else {
|
||||
AnalyticsParam.OnOffState.Off
|
||||
},
|
||||
organizeSortType = if (isSortedByBalance) {
|
||||
AnalyticsParam.OrganizeSortType.ByBalance
|
||||
} else {
|
||||
AnalyticsParam.OrganizeSortType.Manually
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
|
||||
sealed class PortfolioOrganizeTokensAnalyticsEvent(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent("Portfolio / Organize Tokens", event, params) {
|
||||
|
||||
object ScreenOpened : PortfolioOrganizeTokensAnalyticsEvent("Organize Tokens Screen Opened")
|
||||
|
||||
object ByBalance : PortfolioOrganizeTokensAnalyticsEvent("Button - By Balance")
|
||||
|
||||
object Group : PortfolioOrganizeTokensAnalyticsEvent("Button - Group")
|
||||
|
||||
class Apply(
|
||||
grouping: AnalyticsParam.OnOffState,
|
||||
organizeSortType: AnalyticsParam.OrganizeSortType,
|
||||
) : PortfolioOrganizeTokensAnalyticsEvent(
|
||||
"Button - Apply",
|
||||
params = mapOf(
|
||||
"Group" to grouping.value,
|
||||
"Sort" to organizeSortType.value,
|
||||
),
|
||||
)
|
||||
|
||||
object Cancel : PortfolioOrganizeTokensAnalyticsEvent("Button - Cancel")
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
|
||||
sealed class PortfolioEvent(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent("Portfolio", event, params) {
|
||||
|
||||
object Refreshed : PortfolioEvent("Refreshed")
|
||||
|
||||
object ButtonManageTokens : PortfolioEvent("Button - Manage Tokens")
|
||||
|
||||
object TokenTapped : PortfolioEvent("Token is Tapped")
|
||||
|
||||
object OrganizeTokens : PortfolioEvent("Button - Organize Tokens")
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
|
||||
sealed class WalletScreenAnalyticsEvent(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent("Main Screen", event, params) {
|
||||
|
||||
object ScreenOpened : WalletScreenAnalyticsEvent("Screen opened")
|
||||
object WalletSwipe : WalletScreenAnalyticsEvent("Wallet Swipe")
|
||||
|
||||
class EnableBiometrics(state: AnalyticsParam.OnOffState) : WalletScreenAnalyticsEvent(
|
||||
event = "Enable Biometric",
|
||||
params = mapOf("State" to state.value),
|
||||
)
|
||||
|
||||
// TODO [REDACTED_JIRA]
|
||||
class NoticeRateAppButton(result: AnalyticsParam.RateApp) : WalletScreenAnalyticsEvent(
|
||||
event = "Notice - Rate The App Button Tapped",
|
||||
params = mapOf("Result" to result.value),
|
||||
)
|
||||
|
||||
object NoticeBackupYourWalletTapped : WalletScreenAnalyticsEvent("Notice - Backup Your Wallet Tapped")
|
||||
object NoticeScanYourCardTapped : WalletScreenAnalyticsEvent("Notice - Scan Your Card Tapped")
|
||||
object NoticeWalletLocked : WalletScreenAnalyticsEvent("Notice - Wallet Locked")
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import arrow.core.getOrElse
|
|||
import com.tangem.common.Provider
|
||||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel
|
||||
import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig
|
||||
|
|
@ -37,6 +38,8 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.PortfolioEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
|
||||
|
|
@ -93,6 +96,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
// endregion Parameters
|
||||
) : ViewModel(), DefaultLifecycleObserver, WalletClickIntents {
|
||||
|
||||
|
|
@ -141,6 +145,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
)
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.ScreenOpened)
|
||||
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
delay(timeMillis = 1_800)
|
||||
|
||||
|
|
@ -231,6 +237,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onScanCardClick() {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.NoticeScanYourCardTapped)
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
scanCardProcessor.scan()
|
||||
.doOnSuccess {
|
||||
|
|
@ -330,7 +338,10 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
override fun onDetailsClick() = router.openDetailsScreen()
|
||||
|
||||
override fun onBackupCardClick() = router.openOnboardingScreen()
|
||||
override fun onBackupCardClick() {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.NoticeBackupYourWalletTapped)
|
||||
router.openOnboardingScreen()
|
||||
}
|
||||
|
||||
override fun onCriticalWarningAlreadySignedHashesClick() {
|
||||
uiState = stateFactory.getStateWithOpenWalletBottomSheet(
|
||||
|
|
@ -363,6 +374,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onWalletChange(index: Int) {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.WalletSwipe)
|
||||
|
||||
val state = uiState as? WalletState.ContentState ?: return
|
||||
if (state.walletsListConfig.selectedWalletIndex == index) return
|
||||
|
||||
|
|
@ -417,8 +430,14 @@ internal class WalletViewModel @Inject constructor(
|
|||
?: return
|
||||
|
||||
when (uiState) {
|
||||
is WalletMultiCurrencyState.Content -> refreshMultiCurrencyContent(selectedWalletIndex)
|
||||
is WalletSingleCurrencyState.Content -> refreshSingleCurrencyContent(selectedWalletIndex)
|
||||
is WalletMultiCurrencyState.Content -> {
|
||||
analyticsEventsHandler.send(PortfolioEvent.Refreshed)
|
||||
refreshMultiCurrencyContent(selectedWalletIndex)
|
||||
}
|
||||
is WalletSingleCurrencyState.Content -> {
|
||||
analyticsEventsHandler.send(PortfolioEvent.Refreshed)
|
||||
refreshSingleCurrencyContent(selectedWalletIndex)
|
||||
}
|
||||
is WalletState.Initial,
|
||||
is WalletMultiCurrencyState.Locked,
|
||||
is WalletSingleCurrencyState.Locked,
|
||||
|
|
@ -427,6 +446,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onOrganizeTokensClick() {
|
||||
analyticsEventsHandler.send(PortfolioEvent.OrganizeTokens)
|
||||
|
||||
val state = requireNotNull(uiState as? WalletState.ContentState)
|
||||
val index = state.walletsListConfig.selectedWalletIndex
|
||||
val walletId = state.walletsListConfig.wallets[index].id
|
||||
|
|
@ -533,6 +554,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onManageTokensClick() {
|
||||
analyticsEventsHandler.send(PortfolioEvent.ButtonManageTokens)
|
||||
reduxStateHolder.dispatch(action = TokensAction.SetArgs.ManageAccess)
|
||||
router.openManageTokensScreen()
|
||||
}
|
||||
|
|
@ -567,6 +589,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onUnlockWalletClick() {
|
||||
analyticsEventsHandler.send(WalletScreenAnalyticsEvent.NoticeWalletLocked)
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
unlockWalletsUseCase()
|
||||
}
|
||||
|
|
@ -586,6 +610,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onTokenItemClick(currency: CryptoCurrency) {
|
||||
analyticsEventsHandler.send(PortfolioEvent.TokenTapped)
|
||||
router.openTokenDetails(currency = currency)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue