Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-04 13:21:10 +05:00
parent d53f4d0346
commit d09f2d3bc5
3 changed files with 230 additions and 22 deletions

View file

@ -1,12 +1,57 @@
package com.tangem.features.nft.details.ui
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.FabPosition
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.nft.details.entity.NFTDetailsUM
import com.tangem.features.nft.impl.R
@Suppress("UnusedPrivateMember")
@Composable
internal fun NFTDetails(state: NFTDetailsUM, modifier: Modifier = Modifier) {
BackHandler(onBack = state.onBackClick)
Scaffold(
modifier = modifier,
containerColor = TangemTheme.colors.background.secondary,
topBar = {
TangemTopAppBar(
modifier = Modifier.statusBarsPadding(),
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_back_24,
onIconClicked = state.onBackClick,
),
title = state.nftAsset.name,
)
},
content = { innerPadding ->
NFTDetailsAsset(
state = state.nftAsset,
onReadMoreClick = state.onReadMoreClick,
onSeeAllClick = state.onSeeAllClick,
onExploreClick = state.onExploreClick,
modifier = Modifier
.padding(innerPadding),
)
},
floatingActionButtonPosition = FabPosition.Center,
floatingActionButton = {
PrimaryButton(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
.fillMaxWidth(),
text = stringResourceSafe(id = R.string.common_send),
onClick = state.onSendClick,
)
},
)
}

View file

@ -0,0 +1,178 @@
package com.tangem.features.nft.details.ui
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.atoms.text.TextEllipsis
import com.tangem.core.ui.components.bottomFade
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.details.entity.NFTAssetUM
import com.tangem.features.nft.impl.R
import kotlinx.collections.immutable.persistentListOf
@Composable
internal fun NFTDetailsAsset(
state: NFTAssetUM,
onReadMoreClick: () -> Unit,
onSeeAllClick: () -> Unit,
onExploreClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val scrollState = rememberScrollState()
val bottomBarHeight = with(LocalDensity.current) {
WindowInsets.systemBars.getBottom(density = this).toDp()
}
val bottomPadding = TangemTheme.dimens.spacing76 + bottomBarHeight
Box(
modifier = Modifier
.fillMaxSize()
.bottomFade(),
) {
Column(
modifier = modifier
.verticalScroll(scrollState)
.padding(
start = TangemTheme.dimens.spacing16,
top = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = bottomPadding,
)
.fillMaxSize(),
) {
NFTDetailsLogo(
state = state.media,
modifier = Modifier
.aspectRatio(1f),
)
NFTDetailsInfoGroup(
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing12),
state = state.topInfo,
onReadMoreClick = onReadMoreClick,
)
NFTDetailsBlocksGroup(
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing12),
items = state.traits,
title = resourceReference(R.string.nft_details_traits),
action = {
NFTBlocksGroupAction(
text = resourceReference(R.string.common_see_all),
startIcon = { },
onClick = onSeeAllClick,
)
},
)
NFTDetailsBlocksGroup(
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing12),
items = state.baseInfoItems,
title = resourceReference(R.string.nft_details_base_information),
action = {
NFTBlocksGroupAction(
text = resourceReference(R.string.common_explore),
startIcon = {
NFTBlocksGroupActionIcon(iconRes = R.drawable.ic_compass_24)
},
onClick = onExploreClick,
)
},
)
}
}
}
@Preview(widthDp = 360, heightDp = 1000, showBackground = true)
@Preview(widthDp = 360, heightDp = 1000, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun Preview_NFTDetailsAssetAsset(@PreviewParameter(NFTAssetProvider::class) state: NFTAssetUM) {
TangemThemePreview {
NFTDetailsAsset(
state = state,
onReadMoreClick = { },
onSeeAllClick = { },
onExploreClick = { },
)
}
}
@Suppress("MagicNumber")
private class NFTAssetProvider : CollectionPreviewParameterProvider<NFTAssetUM>(
collection = listOf(
NFTAssetUM(
name = "Nethers #9744",
media = NFTAssetUM.Media.Content(
url = "img1",
mimetype = "image/jpeg",
),
topInfo = NFTAssetUM.TopInfo.Content(
title = resourceReference(R.string.nft_details_last_sale_price),
salePrice = NFTAssetUM.SalePrice.Content(value = "0,012 ETH", fiatValue = "32.34$"),
description = "Base edition by Piux. An illustration of Crypto Robot #7804".repeat(3),
rarity = NFTAssetUM.Rarity.Content(
rank = "Top 1% rarity",
label = "115.28",
showDivider = true,
),
),
traits = persistentListOf(
NFTAssetUM.BlockItem(
title = stringReference("Tier"),
value = "Infinite",
),
NFTAssetUM.BlockItem(
title = stringReference("Phygital Toy"),
value = "None",
),
NFTAssetUM.BlockItem(
title = stringReference("Class"),
value = "CYBER",
),
NFTAssetUM.BlockItem(
title = stringReference("Accessory"),
value = "No accessory",
),
NFTAssetUM.BlockItem(
title = stringReference("Sneakers"),
value = "Boots",
),
NFTAssetUM.BlockItem(
title = stringReference("Artist"),
value = "DJ Dragoon",
),
),
baseInfoItems = persistentListOf(
NFTAssetUM.BlockItem(
title = resourceReference(R.string.nft_details_token_standard),
value = "ERC-721",
),
NFTAssetUM.BlockItem(
title = resourceReference(R.string.nft_details_contract_address),
value = "0x6811f2fgd892ac83f719",
valueTextEllipsis = TextEllipsis.Middle,
),
NFTAssetUM.BlockItem(
title = resourceReference(R.string.nft_details_token_id),
value = "100200273",
),
NFTAssetUM.BlockItem(
title = resourceReference(R.string.nft_details_chain),
value = "Ethereum",
),
),
),
),
)

View file

@ -2,12 +2,11 @@ package com.tangem.features.nft.details.ui
import android.content.res.Configuration
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -140,8 +139,11 @@ private fun Rarity(state: NFTAssetUM.Rarity, modifier: Modifier = Modifier) {
is NFTAssetUM.Rarity.Empty -> Unit
is NFTAssetUM.Rarity.Content -> {
if (state.showDivider) {
Divider(
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing12),
HorizontalDivider(
modifier = Modifier.padding(
horizontal = TangemTheme.dimens.spacing12,
),
color = TangemTheme.colors.stroke.primary,
)
}
Row(
@ -177,23 +179,6 @@ private fun Rarity(state: NFTAssetUM.Rarity, modifier: Modifier = Modifier) {
}
}
@Composable
private fun Divider(modifier: Modifier = Modifier) {
Box(
modifier = modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size8),
contentAlignment = Alignment.Center,
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(TangemTheme.dimens.size1)
.background(TangemTheme.colors.stroke.primary),
)
}
}
@Preview(widthDp = 360)
@Preview(widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable