Updated on 2026-08-14

This commit is contained in:
Tangem 2026-03-13 10:54:00 +01:00
parent 473aeee675
commit fc329a75d9
3 changed files with 181 additions and 11 deletions

View file

@ -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,
)
}
},
)
}
}

View file

@ -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(

View file

@ -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,