From c3379c5df97711525d67e600ddecbfae7767c587 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 25 Apr 2025 16:55:31 +0500 Subject: [PATCH] Updated on 2026-08-14 --- core/res/src/main/res/values/strings.xml | 7 ++ .../nft/details/NFTDetailsComponent.kt | 1 + .../features/nft/details/entity/NFTAssetUM.kt | 4 ++ .../entity/NFTDetailsBottomSheetConfig.kt | 1 + .../entity/factory/NFTDetailsUMFactory.kt | 72 +++++++++++++++++++ .../info/DefaultNFTDetailsInfoComponent.kt | 1 + .../details/info/NFTDetailsInfoComponent.kt | 1 + .../nft/details/info/ui/NFTInfoBottomSheet.kt | 10 +-- .../nft/details/model/NFTDetailsModel.kt | 18 ++++- .../nft/details/ui/NFTDetailsAsset.kt | 12 ++++ .../nft/details/ui/NFTDetailsBlocksGroup.kt | 52 +++++++++++--- .../nft/details/ui/NFTDetailsInfoGroup.kt | 22 ++++++ 12 files changed, 188 insertions(+), 13 deletions(-) diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index d374882e15..3d4d6f5d2a 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -538,6 +538,13 @@ Token ID Token Standard Traits + + + + + + + No results. Please try another request. No collection Available diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/NFTDetailsComponent.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/NFTDetailsComponent.kt index 2333a6a0e0..67920ecced 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/NFTDetailsComponent.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/NFTDetailsComponent.kt @@ -53,6 +53,7 @@ internal class NFTDetailsComponent @AssistedInject constructor( is NFTDetailsBottomSheetConfig.Info -> nftDetailsInfoComponentFactory.create( context = childByContext(componentContext), params = NFTDetailsInfoComponent.Params( + title = config.title, text = config.text, onDismiss = { model.bottomSheetNavigation.dismiss() diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTAssetUM.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTAssetUM.kt index ded848d638..88808c889c 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTAssetUM.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTAssetUM.kt @@ -56,6 +56,8 @@ data class NFTAssetUM( val rank: String, val label: String, val showDivider: Boolean, + val onRankClick: () -> Unit, + val onLabelClick: () -> Unit, ) : Rarity() } @@ -64,5 +66,7 @@ data class NFTAssetUM( val titleTextEllipsis: TextEllipsis = TextEllipsis.End, val value: String, val valueTextEllipsis: TextEllipsis = TextEllipsis.End, + val showInfoButton: Boolean, + val onClick: () -> Unit = { }, ) } \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTDetailsBottomSheetConfig.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTDetailsBottomSheetConfig.kt index e8478f38ac..9c5fc52d41 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTDetailsBottomSheetConfig.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/NFTDetailsBottomSheetConfig.kt @@ -7,6 +7,7 @@ import kotlinx.serialization.Serializable internal sealed interface NFTDetailsBottomSheetConfig { @Serializable data class Info( + val title: TextReference, val text: TextReference, ) : NFTDetailsBottomSheetConfig } \ No newline at end of file diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/factory/NFTDetailsUMFactory.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/factory/NFTDetailsUMFactory.kt index 9a8e41a51f..e2e64fdb2b 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/factory/NFTDetailsUMFactory.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/entity/factory/NFTDetailsUMFactory.kt @@ -1,6 +1,7 @@ package com.tangem.features.nft.details.entity.factory import com.tangem.core.ui.components.atoms.text.TextEllipsis +import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.nft.models.NFTAsset @@ -17,6 +18,7 @@ internal class NFTDetailsUMFactory( private val onSeeAllTraitsClick: () -> Unit, private val onExploreClick: () -> Unit, private val onSendClick: () -> Unit, + private val onInfoBlockClick: (title: TextReference, text: TextReference) -> Unit, ) { fun getInitialState(nftAsset: NFTAsset): NFTDetailsUM = NFTDetailsUM( @@ -57,6 +59,18 @@ internal class NFTDetailsUMFactory( rank = rarity.rank, label = rarity.label, showDivider = hasSalePrice || hasDescription, + onLabelClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_rarity_label), + resourceReference(R.string.nft_details_info_rarity_label), + ) + }, + onRankClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_rarity_rank), + resourceReference(R.string.nft_details_info_rarity_rank), + ) + }, ) } else { NFTAssetUM.Rarity.Empty @@ -68,6 +82,7 @@ internal class NFTDetailsUMFactory( NFTAssetUM.BlockItem( title = stringReference(it.name), value = it.value, + showInfoButton = false, ) }.toImmutableList(), showAllTraitsButton = traits.size > MAX_TRAITS_COUNT, @@ -76,24 +91,53 @@ internal class NFTDetailsUMFactory( private fun NFTAsset.hasSalePrice() = salePrice !is NFTSalePrice.Empty && salePrice !is NFTSalePrice.Error + @Suppress("LongMethod") private fun NFTAsset.buildBaseInfoItems() = when (val id = id) { is NFTAsset.Identifier.EVM -> persistentListOf( NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_token_standard), value = contractType, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_token_standard), + resourceReference(R.string.nft_details_info_token_standard), + ) + }, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_contract_address), value = id.tokenAddress, valueTextEllipsis = TextEllipsis.Middle, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_contract_address), + resourceReference(R.string.nft_details_info_contract_address), + ) + }, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_token_id), value = id.tokenId.toString(), + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_token_id), + resourceReference(R.string.nft_details_info_token_id), + ) + }, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_chain), value = network.name, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_chain), + resourceReference(R.string.nft_details_info_chain), + ) + }, ), ) is NFTAsset.Identifier.TON -> persistentListOf( @@ -101,10 +145,24 @@ internal class NFTDetailsUMFactory( title = resourceReference(R.string.nft_details_token_address), value = id.tokenAddress, valueTextEllipsis = TextEllipsis.Middle, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_token_address), + resourceReference(R.string.nft_details_info_token_address), + ) + }, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_chain), value = network.name, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_chain), + resourceReference(R.string.nft_details_info_chain), + ) + }, ), ) is NFTAsset.Identifier.Solana -> persistentListOf( @@ -112,10 +170,24 @@ internal class NFTDetailsUMFactory( title = resourceReference(R.string.nft_details_token_address), value = id.tokenAddress, valueTextEllipsis = TextEllipsis.Middle, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_token_address), + resourceReference(R.string.nft_details_info_token_address), + ) + }, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_chain), value = network.name, + showInfoButton = true, + onClick = { + onInfoBlockClick( + resourceReference(R.string.nft_details_chain), + resourceReference(R.string.nft_details_info_chain), + ) + }, ), ) is NFTAsset.Identifier.Unknown -> persistentListOf() diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/DefaultNFTDetailsInfoComponent.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/DefaultNFTDetailsInfoComponent.kt index 26dc1a1dd6..f5311a1f65 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/DefaultNFTDetailsInfoComponent.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/DefaultNFTDetailsInfoComponent.kt @@ -33,6 +33,7 @@ internal class DefaultNFTDetailsInfoComponent @AssistedInject constructor( ) } NFTInfoBottomSheet( + title = params.title, config = bottomSheetConfig, content = { NFTInfoBottomSheetContent( diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/NFTDetailsInfoComponent.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/NFTDetailsInfoComponent.kt index 90650da63b..eb61128969 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/NFTDetailsInfoComponent.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/NFTDetailsInfoComponent.kt @@ -7,6 +7,7 @@ import com.tangem.core.ui.extensions.TextReference internal interface NFTDetailsInfoComponent : ComposableBottomSheetComponent { data class Params( + val title: TextReference, val text: TextReference, val onDismiss: () -> Unit, ) diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/ui/NFTInfoBottomSheet.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/ui/NFTInfoBottomSheet.kt index b95179836f..875903640f 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/ui/NFTInfoBottomSheet.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/info/ui/NFTInfoBottomSheet.kt @@ -14,17 +14,19 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference -import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview -import com.tangem.features.nft.impl.R @Composable -internal fun NFTInfoBottomSheet(config: TangemBottomSheetConfig, content: @Composable () -> Unit) { +internal fun NFTInfoBottomSheet( + title: TextReference, + config: TangemBottomSheetConfig, + content: @Composable () -> Unit, +) { TangemBottomSheet( config = config, - titleText = resourceReference(R.string.nft_about_title), + titleText = title, content = { content() }, ) } diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt index e81bb43891..dd61ccf4f8 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt @@ -8,15 +8,18 @@ import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router -import com.tangem.domain.nft.analytics.NFTAnalyticsEvent import com.tangem.core.navigation.url.UrlOpener +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.nft.GetNFTExploreUrlUseCase +import com.tangem.domain.nft.analytics.NFTAnalyticsEvent import com.tangem.features.nft.details.NFTDetailsComponent import com.tangem.features.nft.details.entity.NFTAssetUM import com.tangem.features.nft.details.entity.NFTDetailsBottomSheetConfig import com.tangem.features.nft.details.entity.NFTDetailsUM import com.tangem.features.nft.details.entity.factory.NFTDetailsUMFactory +import com.tangem.features.nft.impl.R import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -43,6 +46,7 @@ internal class NFTDetailsModel @Inject constructor( onSeeAllTraitsClick = { params.onAllTraitsClick() }, onExploreClick = ::onExploreClick, onSendClick = ::onSendClick, + onInfoBlockClick = ::onInfoBlockClick, ) private val _state = MutableStateFlow( @@ -50,10 +54,21 @@ internal class NFTDetailsModel @Inject constructor( ) val bottomSheetNavigation: SlotNavigation = SlotNavigation() + init { analyticsEventHandler.send(NFTAnalyticsEvent.Details.ScreenOpened(params.nftAsset.network.name)) } + private fun onInfoBlockClick(title: TextReference, text: TextReference) { + analyticsEventHandler.send(NFTAnalyticsEvent.Details.ButtonReadMore) + bottomSheetNavigation.activate( + NFTDetailsBottomSheetConfig.Info( + title = title, + text = text, + ), + ) + } + private fun onReadMoreClick() { analyticsEventHandler.send(NFTAnalyticsEvent.Details.ButtonReadMore) when (val topInfo = _state.value.nftAsset.topInfo) { @@ -61,6 +76,7 @@ internal class NFTDetailsModel @Inject constructor( is NFTAssetUM.TopInfo.Content -> { bottomSheetNavigation.activate( NFTDetailsBottomSheetConfig.Info( + title = resourceReference(R.string.nft_about_title), text = stringReference(topInfo.description.orEmpty()), ), ) diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsAsset.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsAsset.kt index 3edf28fee7..1f955d7860 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsAsset.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsAsset.kt @@ -138,32 +138,40 @@ private class NFTAssetProvider : CollectionPreviewParameterProvider( rank = "Top 1% rarity", label = "115.28", showDivider = true, + onRankClick = { }, + onLabelClick = { }, ), ), traits = persistentListOf( NFTAssetUM.BlockItem( title = stringReference("Tier"), value = "Infinite", + showInfoButton = false, ), NFTAssetUM.BlockItem( title = stringReference("Phygital Toy"), value = "None", + showInfoButton = false, ), NFTAssetUM.BlockItem( title = stringReference("Class"), value = "CYBER", + showInfoButton = false, ), NFTAssetUM.BlockItem( title = stringReference("Accessory"), value = "No accessory", + showInfoButton = false, ), NFTAssetUM.BlockItem( title = stringReference("Sneakers"), value = "Boots", + showInfoButton = false, ), NFTAssetUM.BlockItem( title = stringReference("Artist"), value = "DJ Dragoon", + showInfoButton = false, ), ), showAllTraitsButton = true, @@ -171,19 +179,23 @@ private class NFTAssetProvider : CollectionPreviewParameterProvider( NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_token_standard), value = "ERC-721", + showInfoButton = true, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_contract_address), value = "0x6811f2fgd892ac83f719", valueTextEllipsis = TextEllipsis.Middle, + showInfoButton = true, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_token_id), value = "100200273", + showInfoButton = true, ), NFTAssetUM.BlockItem( title = resourceReference(R.string.nft_details_chain), value = "Ethereum", + showInfoButton = true, ), ), ), diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsBlocksGroup.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsBlocksGroup.kt index 8df906ff96..cc7726dfd1 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsBlocksGroup.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/ui/NFTDetailsBlocksGroup.kt @@ -30,6 +30,7 @@ import com.tangem.features.nft.impl.R import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +@Suppress("LongMethod") @Composable internal fun NFTDetailsBlocksGroup( title: TextReference, @@ -68,11 +69,17 @@ internal fun NFTDetailsBlocksGroup( NFTDetailsGroupBlock( modifier = Modifier .weight(1f) - .padding(paddingValues), + .padding(paddingValues) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = item1.onClick, + ), title = item1.title, value = stringReference(item1.value), titleEllipsis = item1.titleTextEllipsis, valueEllipsis = item1.valueTextEllipsis, + showInfoButton = item1.showInfoButton, ) if (item2 == null) { Box( @@ -84,11 +91,17 @@ internal fun NFTDetailsBlocksGroup( NFTDetailsGroupBlock( modifier = Modifier .weight(1f) - .padding(paddingValues), + .padding(paddingValues) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = item2.onClick, + ), title = item2.title, value = stringReference(item2.value), titleEllipsis = item2.titleTextEllipsis, valueEllipsis = item2.valueTextEllipsis, + showInfoButton = item2.showInfoButton, ) } } @@ -113,6 +126,7 @@ internal fun NFTDetailsGroupTitle(text: TextReference, modifier: Modifier = Modi internal fun NFTDetailsGroupBlock( title: TextReference, value: TextReference, + showInfoButton: Boolean, modifier: Modifier = Modifier, titleEllipsis: TextEllipsis = TextEllipsis.End, valueEllipsis: TextEllipsis = TextEllipsis.End, @@ -120,12 +134,29 @@ internal fun NFTDetailsGroupBlock( Column( modifier = modifier, ) { - EllipsisText( - text = title.resolveReference(), - style = TangemTheme.typography.caption2, - color = TangemTheme.colors.text.tertiary, - ellipsis = titleEllipsis, - ) + Row( + modifier = Modifier + .fillMaxWidth(), + ) { + EllipsisText( + modifier = Modifier + .weight(1f, fill = false), + text = title.resolveReference(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + ellipsis = titleEllipsis, + ) + if (showInfoButton) { + Icon( + modifier = Modifier + .padding(start = TangemTheme.dimens.spacing4) + .size(TangemTheme.dimens.size16), + painter = painterResource(R.drawable.ic_information_24), + contentDescription = null, + tint = TangemTheme.colors.icon.informative, + ) + } + } EllipsisText( modifier = Modifier .padding(top = TangemTheme.dimens.spacing4), @@ -224,22 +255,27 @@ private class NFTAssetBlocksProvider : CollectionPreviewParameterProvider