Updated on 2026-08-14
This commit is contained in:
parent
b51b57cf89
commit
1efdecab4a
13 changed files with 119 additions and 33 deletions
|
|
@ -219,5 +219,7 @@ sealed class AnalyticsParam {
|
|||
const val ACTION = "Action"
|
||||
const val COLLECTIONS = "Collections"
|
||||
const val NFT = "Nft"
|
||||
const val STANDARD = "Standard"
|
||||
const val NO_COLLECTION = "No collection"
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ object NFTSdkAssetIdentifierConverter : TwoWayConverter<SdkNFTAsset.Identifier,
|
|||
)
|
||||
is SdkNFTAsset.Identifier.Solana -> NFTAsset.Identifier.Solana(
|
||||
tokenAddress = value.tokenAddress,
|
||||
cnft = value.cnft,
|
||||
tokenStandard = value.tokenStandard,
|
||||
)
|
||||
is SdkNFTAsset.Identifier.Unknown -> NFTAsset.Identifier.Unknown
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ object NFTSdkAssetIdentifierConverter : TwoWayConverter<SdkNFTAsset.Identifier,
|
|||
)
|
||||
is NFTAsset.Identifier.Solana -> SdkNFTAsset.Identifier.Solana(
|
||||
tokenAddress = value.tokenAddress,
|
||||
cnft = value.cnft,
|
||||
tokenStandard = value.tokenStandard,
|
||||
)
|
||||
is NFTAsset.Identifier.Unknown -> SdkNFTAsset.Identifier.Unknown
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ data class NFTAsset(
|
|||
@Serializable
|
||||
data class Solana(
|
||||
val tokenAddress: String,
|
||||
val cnft: Boolean,
|
||||
val tokenStandard: Int?,
|
||||
) : Identifier() {
|
||||
override val stringValue: String = tokenAddress
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ package com.tangem.domain.nft.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.STANDARD
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.COLLECTIONS
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.NFT
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.NO_COLLECTION
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.STATE
|
||||
import kotlin.collections.buildMap
|
||||
|
||||
sealed class NFTAnalyticsEvent(
|
||||
event: String,
|
||||
|
|
@ -17,19 +20,21 @@ sealed class NFTAnalyticsEvent(
|
|||
|
||||
data class NFTListScreenOpened(
|
||||
val state: State,
|
||||
val collectionsCount: Int,
|
||||
val allAssetsCount: Int,
|
||||
val noCollectionAssetsCount: Int,
|
||||
) : NFTAnalyticsEvent(
|
||||
event = "NFT List Screen Opened",
|
||||
params = buildMap {
|
||||
put(STATE, state.value)
|
||||
if (state is State.Full) {
|
||||
put(COLLECTIONS, state.collectionsCount.toString())
|
||||
put(NFT, state.assetsCount.toString())
|
||||
}
|
||||
put(COLLECTIONS, collectionsCount.toString())
|
||||
put(NFT, allAssetsCount.toString())
|
||||
put(NO_COLLECTION, noCollectionAssetsCount.toString())
|
||||
},
|
||||
) {
|
||||
sealed class State(val value: String) {
|
||||
data object Empty : State("Empty")
|
||||
data class Full(val assetsCount: Int, val collectionsCount: Int) : State("Full")
|
||||
enum class State(val value: String) {
|
||||
Empty("Empty"),
|
||||
Full("Full"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +57,16 @@ sealed class NFTAnalyticsEvent(
|
|||
object Details {
|
||||
data class ScreenOpened(
|
||||
private val blockchain: String,
|
||||
) : NFTAnalyticsEvent(event = "NFT Details Screen Opened", params = mapOf(BLOCKCHAIN to blockchain))
|
||||
private val standard: String?,
|
||||
) : NFTAnalyticsEvent(
|
||||
event = "NFT Details Screen Opened",
|
||||
params = buildMap {
|
||||
put(BLOCKCHAIN, blockchain)
|
||||
standard?.let {
|
||||
put(STANDARD, it)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
data object ButtonReadMore : NFTAnalyticsEvent(event = "Button - Read More")
|
||||
data object ButtonSeeAll : NFTAnalyticsEvent(event = "Button - See All")
|
||||
|
|
|
|||
|
|
@ -85,7 +85,17 @@ internal class NFTDetailsModel @Inject constructor(
|
|||
val bottomSheetNavigation: SlotNavigation<NFTDetailsBottomSheetConfig> = SlotNavigation()
|
||||
|
||||
init {
|
||||
analyticsEventHandler.send(NFTAnalyticsEvent.Details.ScreenOpened(params.nftAsset.network.name))
|
||||
analyticsEventHandler.send(
|
||||
NFTAnalyticsEvent.Details.ScreenOpened(
|
||||
blockchain = params.nftAsset.network.name,
|
||||
standard = when (val id = params.nftAsset.id) {
|
||||
is NFTAsset.Identifier.EVM -> id.contractType.name
|
||||
is NFTAsset.Identifier.Solana -> id.tokenStandard?.toString()
|
||||
is NFTAsset.Identifier.TON -> null
|
||||
is NFTAsset.Identifier.Unknown -> null
|
||||
},
|
||||
),
|
||||
)
|
||||
initAppCurrency()
|
||||
subscribeToPriceChanges()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.feature.walletsettings.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.STATUS
|
||||
|
||||
internal sealed class WalletSettingsAnalyticEvents(
|
||||
category: String = "Settings / Wallet",
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent(category, event, params) {
|
||||
|
||||
data class NftToggleSwitch(val enabled: AnalyticsParam.OnOffState) : WalletSettingsAnalyticEvents(
|
||||
event = "NFT toggle switch",
|
||||
params = mapOf(STATUS to enabled.value),
|
||||
)
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import com.arkivanov.decompose.router.slot.SlotNavigation
|
|||
import com.arkivanov.decompose.router.slot.activate
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.OnOffState.Off
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.OnOffState.On
|
||||
import com.tangem.core.analytics.utils.AnalyticsContextProxy
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
|
|
@ -29,6 +31,7 @@ import com.tangem.domain.wallets.models.isMultiCurrency
|
|||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import com.tangem.feature.walletsettings.analytics.Settings
|
||||
import com.tangem.feature.walletsettings.analytics.WalletSettingsAnalyticEvents
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.entity.DialogConfig
|
||||
import com.tangem.feature.walletsettings.entity.NetworksAvailableForNotificationBSConfig
|
||||
|
|
@ -214,6 +217,11 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
} else {
|
||||
disableWalletNFTUseCase.invoke(params.userWalletId)
|
||||
}
|
||||
analyticsEventHandler.send(
|
||||
WalletSettingsAnalyticEvents.NftToggleSwitch(
|
||||
enabled = if (isChecked) On else Off,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -238,19 +238,31 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override fun onNFTClick(userWallet: UserWallet) {
|
||||
val selectedWallet = stateHolder.getSelectedWallet() as? WalletState.MultiCurrency.Content ?: return
|
||||
val analyticsState = when (val nftState = selectedWallet.nftState) {
|
||||
is WalletNFTItemUM.Content -> NFTAnalyticsEvent.NFTListScreenOpened.State.Full(
|
||||
assetsCount = nftState.assetsCount,
|
||||
collectionsCount = nftState.collectionsCount,
|
||||
when (val state = selectedWallet.nftState) {
|
||||
is WalletNFTItemUM.Content -> {
|
||||
analyticsEventHandler.send(
|
||||
NFTAnalyticsEvent.NFTListScreenOpened(
|
||||
state = NFTAnalyticsEvent.NFTListScreenOpened.State.Full,
|
||||
allAssetsCount = state.allAssetsCount,
|
||||
collectionsCount = state.collectionsCount,
|
||||
noCollectionAssetsCount = state.noCollectionAssetsCount,
|
||||
),
|
||||
)
|
||||
is WalletNFTItemUM.Empty -> NFTAnalyticsEvent.NFTListScreenOpened.State.Empty
|
||||
}
|
||||
is WalletNFTItemUM.Empty -> {
|
||||
analyticsEventHandler.send(
|
||||
NFTAnalyticsEvent.NFTListScreenOpened(
|
||||
state = NFTAnalyticsEvent.NFTListScreenOpened.State.Empty,
|
||||
allAssetsCount = 0,
|
||||
collectionsCount = 0,
|
||||
noCollectionAssetsCount = 0,
|
||||
),
|
||||
)
|
||||
}
|
||||
is WalletNFTItemUM.Failed,
|
||||
is WalletNFTItemUM.Hidden,
|
||||
is WalletNFTItemUM.Loading,
|
||||
-> null
|
||||
}
|
||||
analyticsState?.let {
|
||||
analyticsEventHandler.send(NFTAnalyticsEvent.NFTListScreenOpened(analyticsState))
|
||||
-> Unit
|
||||
}
|
||||
|
||||
router.openNFT(userWallet)
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ internal object WalletScreenPreviewData {
|
|||
nftState = WalletNFTItemUM.Content(
|
||||
previews = persistentListOf(WalletNFTItemUM.Content.CollectionPreview.Image("img1")),
|
||||
collectionsCount = 1,
|
||||
assetsCount = 3,
|
||||
allAssetsCount = 3,
|
||||
noCollectionAssetsCount = 0,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ sealed class WalletNFTItemUM {
|
|||
data class Content(
|
||||
val previews: ImmutableList<CollectionPreview>,
|
||||
val collectionsCount: Int,
|
||||
val assetsCount: Int,
|
||||
val allAssetsCount: Int,
|
||||
val noCollectionAssetsCount: Int,
|
||||
val isFlickering: Boolean,
|
||||
val onItemClick: () -> Unit,
|
||||
) : WalletNFTItemUM() {
|
||||
|
|
|
|||
|
|
@ -52,8 +52,24 @@ internal class SetNFTCollectionsTransformer(
|
|||
.toPersistentList()
|
||||
},
|
||||
collectionsCount = collections.size,
|
||||
assetsCount = collections
|
||||
.sumOf { it.count },
|
||||
allAssetsCount = collections.sumOf { it.count },
|
||||
noCollectionAssetsCount = collections.sumOf { collection ->
|
||||
when (val collectionId = collection.id) {
|
||||
is NFTCollection.Identifier.Solana ->
|
||||
collection
|
||||
.count
|
||||
.takeIf { collectionId.collectionAddress == null }
|
||||
?: 0
|
||||
is NFTCollection.Identifier.TON ->
|
||||
collection
|
||||
.count
|
||||
.takeIf { collectionId.contractAddress == null }
|
||||
?: 0
|
||||
is NFTCollection.Identifier.EVM,
|
||||
is NFTCollection.Identifier.Unknown,
|
||||
-> 0
|
||||
}
|
||||
},
|
||||
isFlickering = false,
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () ->
|
|||
Text(
|
||||
text = stringResourceSafe(
|
||||
id = R.string.nft_wallet_count,
|
||||
state.assetsCount,
|
||||
state.allAssetsCount,
|
||||
state.collectionsCount,
|
||||
),
|
||||
style = TangemTheme.typography.caption2.applyBladeBrush(
|
||||
|
|
@ -411,8 +411,9 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
previews = persistentListOf(
|
||||
CollectionPreview.Image("img1"),
|
||||
),
|
||||
assetsCount = 125,
|
||||
allAssetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
noCollectionAssetsCount = 0,
|
||||
isFlickering = true,
|
||||
onItemClick = { },
|
||||
),
|
||||
|
|
@ -421,8 +422,9 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
CollectionPreview.Image("img1"),
|
||||
CollectionPreview.Image("img2"),
|
||||
),
|
||||
assetsCount = 125,
|
||||
allAssetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
noCollectionAssetsCount = 0,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
|
|
@ -432,8 +434,9 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
CollectionPreview.Image("img2"),
|
||||
CollectionPreview.Image("img3"),
|
||||
),
|
||||
assetsCount = 125,
|
||||
allAssetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
noCollectionAssetsCount = 0,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
|
|
@ -444,8 +447,9 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
CollectionPreview.Image("img3"),
|
||||
CollectionPreview.Image("img4"),
|
||||
),
|
||||
assetsCount = 125,
|
||||
allAssetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
noCollectionAssetsCount = 0,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
|
|
@ -456,9 +460,10 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
CollectionPreview.Image("img3"),
|
||||
CollectionPreview.More,
|
||||
),
|
||||
assetsCount = 125,
|
||||
allAssetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
isFlickering = true,
|
||||
noCollectionAssetsCount = 0,
|
||||
onItemClick = { },
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# https://github.com/tangem/tangem-sdk-android/
|
||||
# https://github.com/tangem/vico
|
||||
|
||||
tangemBlockchainSdk = "releases-5.25.0-1094"
|
||||
tangemBlockchainSdk = "releases-5.25.0-1098"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "releases-5.25.0-486"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue