From fc329a75d9872c936ee1d92f4c1e5d95870b4898 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 13 Mar 2026 10:54:00 +0100 Subject: [PATCH] Updated on 2026-08-14 --- .../components/TokenMarketInformationBlock.kt | 90 +++++++++++++++++ .../detailed/components/ListedOnBlock.kt | 98 ++++++++++++++++--- .../ui/market/detailed/state/ListedOnUM.kt | 4 + 3 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/TokenMarketInformationBlock.kt diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/TokenMarketInformationBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/TokenMarketInformationBlock.kt new file mode 100644 index 0000000000..ffe3b5771e --- /dev/null +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/components/TokenMarketInformationBlock.kt @@ -0,0 +1,90 @@ +package com.tangem.features.feed.ui.components + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.R +import com.tangem.core.ui.components.SpacerWMax +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreviewRedesign + +@Composable +internal fun TokenMarketInformationBlock( + modifier: Modifier = Modifier, + shape: Shape = RoundedCornerShape(TangemTheme.dimens2.x6), + contentPadding: Dp = TangemTheme.dimens2.x4, + title: (@Composable () -> Unit), + content: (@Composable BoxScope.() -> Unit)? = null, +) { + Column( + modifier = modifier + .clip(shape) + .background(color = TangemTheme.colors2.surface.level3) + .padding(contentPadding), + horizontalAlignment = Alignment.Start, + ) { + title() + + if (content != null) { + Box(modifier = Modifier.fillMaxWidth()) { + content(this) + } + } + } +} + +@Composable +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun TokenMarketInformationBlockPreview() { + TangemThemePreviewRedesign { + TokenMarketInformationBlock( + title = { + Row( + modifier = Modifier.padding(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = "Listed on", + style = TangemTheme.typography2.headingSemibold20, + color = TangemTheme.colors2.text.neutral.primary, + ) + + SpacerWMax() + + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_24), + tint = TangemTheme.colors2.markers.iconGray, + contentDescription = null, + ) + } + }, + content = { + Box( + modifier = Modifier + .fillMaxWidth() + .background(TangemTheme.colors2.surface.level2) + .padding(12.dp), + ) { + Text( + text = "Smth", + color = TangemTheme.colors2.text.neutral.primary, + ) + } + }, + ) + } +} \ No newline at end of file diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt index 7836a63094..3305077d9f 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/ListedOnBlock.kt @@ -2,34 +2,33 @@ package com.tangem.features.feed.ui.market.detailed.components import android.content.res.Configuration import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.material3.Icon import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.testTag +import androidx.compose.ui.unit.dp import com.tangem.common.ui.R +import com.tangem.core.ui.components.SpacerWMax import com.tangem.core.ui.components.TextShimmer import com.tangem.core.ui.components.block.information.InformationBlock import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.res.LocalRedesignEnabled import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.MarketsTestTags +import com.tangem.features.feed.ui.components.TokenMarketInformationBlock import com.tangem.features.feed.ui.market.detailed.state.ListedOnUM import kotlinx.coroutines.delay @@ -42,6 +41,15 @@ import kotlinx.coroutines.delay */ @Composable internal fun ListedOnBlock(state: ListedOnUM, modifier: Modifier = Modifier) { + if (LocalRedesignEnabled.current) { + ListedOnBlockV2(state, modifier) + } else { + ListedOnBlockV1(state, modifier) + } +} + +@Composable +private fun ListedOnBlockV1(state: ListedOnUM, modifier: Modifier = Modifier) { Box(modifier = modifier) { InformationBlock( title = { @@ -78,8 +86,55 @@ internal fun ListedOnBlock(state: ListedOnUM, modifier: Modifier = Modifier) { } } +@Composable +private fun ListedOnBlockV2(state: ListedOnUM, modifier: Modifier = Modifier) { + TokenMarketInformationBlock( + modifier = modifier.clickable(enabled = state is ListedOnUM.Content) { + (state as? ListedOnUM.Content)?.onClick?.invoke() + }, + title = { + Row(verticalAlignment = Alignment.CenterVertically) { + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + Text( + text = state.title.resolveReference(), + style = TangemTheme.typography2.headingSemibold20, + color = TangemTheme.colors2.text.neutral.primary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( + text = state.description.resolveReference(), + style = TangemTheme.typography2.captionSemibold13, + color = TangemTheme.colors2.text.neutral.secondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + + SpacerWMax() + + Icon( + modifier = Modifier.size(20.dp), + imageVector = ImageVector.vectorResource(R.drawable.ic_chevron_small_right_24), + tint = TangemTheme.colors2.markers.iconGray, + contentDescription = null, + ) + } + }, + ) +} + @Composable internal fun ListedOnBlockPlaceholder(modifier: Modifier = Modifier) { + if (LocalRedesignEnabled.current) { + ListedOnBlockPlaceholderV2(modifier) + } else { + ListedOnBlockPlaceholderV1(modifier) + } +} + +@Composable +internal fun ListedOnBlockPlaceholderV1(modifier: Modifier = Modifier) { InformationBlock( title = { TextShimmer( @@ -98,6 +153,27 @@ internal fun ListedOnBlockPlaceholder(modifier: Modifier = Modifier) { } } +@Composable +internal fun ListedOnBlockPlaceholderV2(modifier: Modifier = Modifier) { + TokenMarketInformationBlock( + modifier = modifier, + title = { + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + TextShimmer( + style = TangemTheme.typography2.headingSemibold20, + modifier = Modifier.fillMaxWidth(fraction = 0.5f), + radius = TangemTheme.dimens2.x25, + ) + TextShimmer( + style = TangemTheme.typography2.captionSemibold13, + modifier = Modifier.fillMaxWidth(fraction = 0.5f), + radius = TangemTheme.dimens2.x25, + ) + } + }, + ) +} + @Composable private fun Description(state: ListedOnUM, modifier: Modifier = Modifier) { Text( diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ListedOnUM.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ListedOnUM.kt index 4f4876f07b..0b1dc2b728 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ListedOnUM.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/state/ListedOnUM.kt @@ -1,5 +1,6 @@ package com.tangem.features.feed.ui.market.detailed.state +import androidx.compose.runtime.Immutable import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.pluralReference import com.tangem.core.ui.extensions.resourceReference @@ -11,6 +12,7 @@ import com.tangem.features.feed.impl.R * [REDACTED_AUTHOR] */ +@Immutable internal sealed interface ListedOnUM { /** Title */ @@ -20,6 +22,7 @@ internal sealed interface ListedOnUM { /** Description */ val description: TextReference + @Immutable /** Empty state. No exchanges found */ data object Empty : ListedOnUM { override val description = resourceReference(id = R.string.markets_token_details_empty_exchanges) @@ -31,6 +34,7 @@ internal sealed interface ListedOnUM { * @property onClick lambda be invoked when button is clicked * @property amount amount of exchanges */ + @Immutable data class Content( val onClick: () -> Unit, private val amount: Int,