Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-06 11:40:31 +02:00
parent 2e857d5e3e
commit 45fa120411
49 changed files with 669 additions and 92 deletions

View file

@ -39,6 +39,7 @@ import com.tangem.core.ui.ds.image.TangemIconUM
import com.tangem.core.ui.ds.row.TangemRowContainer
import com.tangem.core.ui.ds.row.TangemRowLayoutId
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.LocalIsInDarkTheme
import com.tangem.core.ui.res.LocalWindowSize
import com.tangem.core.ui.res.TangemTheme
@ -47,6 +48,7 @@ import com.tangem.core.ui.test.MarketsTestTags
import com.tangem.core.ui.test.TokenElementsTestTags
import com.tangem.core.ui.windowsize.WindowSizeType
import com.tangem.utils.StringsSigns.MINUS
import java.math.BigDecimal
import kotlin.random.Random
@Composable
@ -88,6 +90,8 @@ fun MarketListItemContentV2(model: MarketsListItemUM, modifier: Modifier = Modif
.testTag(tag = TokenElementsTestTags.TOKEN_FIAT_AMOUNT),
price = model.price.text,
priceChangeType = model.price.changeType,
priceAnnotated = model.price.annotated,
priceValue = model.price.fiatPrice,
)
TokenSubtitle(
@ -127,7 +131,7 @@ private fun TokenTitle(name: String, currencySymbol: String, modifier: Modifier
.alignByBaseline(),
text = name,
color = TangemTheme.colors2.text.neutral.primary,
style = TangemTheme.typography2.bodySemibold16,
style = TangemTheme.typography2.bodyMedium16,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
@ -323,12 +327,16 @@ private fun Preview(@PreviewParameter(MarketChartListItemPreviewDataProvider::cl
price = MarketsListItemUM.Price(
text = "0.${prices[0].first}023 $",
changeType = prices[0].second,
fiatPrice = BigDecimal(123123),
annotated = stringReference("0.${prices[0].first}023 $"),
),
)
state2 = state2.copy(
price = MarketsListItemUM.Price(
text = "0.${prices[1].first}023 $",
changeType = prices[1].second,
fiatPrice = BigDecimal(123123),
annotated = stringReference("0.${prices[0].first}023 $"),
),
)
},

View file

@ -0,0 +1,22 @@
package com.tangem.common.ui.markets
import androidx.compose.ui.text.SpanStyle
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.formatStyled
import com.tangem.core.ui.format.bigdecimal.price
import com.tangem.core.ui.res.TangemTheme
import java.math.BigDecimal
/**
* Fiat amount for markets list rows: integer part in primary style, fractional part (from locale separator) in secondary.
*/
fun BigDecimal.toMarketsListItemPriceAnnotated(appCurrencyCode: String, appCurrencySymbol: String): TextReference {
return formatStyled {
fiat(
fiatCurrencyCode = appCurrencyCode,
fiatCurrencySymbol = appCurrencySymbol,
spanStyleReference = { SpanStyle(color = TangemTheme.colors2.text.neutral.secondary) },
).price()
}
}

View file

@ -29,12 +29,14 @@ import com.tangem.core.ui.components.marketprice.PriceChangeInPercent
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.LocalWindowSize
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.MarketsTestTags
import com.tangem.core.ui.windowsize.WindowSizeType
import com.tangem.utils.StringsSigns.MINUS
import java.math.BigDecimal
import kotlin.random.Random
@Composable
@ -85,6 +87,8 @@ private fun MarketsListItemContentV1(model: MarketsListItemUM, modifier: Modifie
modifier = Modifier.alignByBaseline(),
price = model.price.text,
priceChangeType = model.price.changeType,
priceAnnotated = model.price.annotated,
priceValue = model.price.fiatPrice,
)
}
@ -306,12 +310,16 @@ private fun Preview(@PreviewParameter(MarketChartListItemPreviewDataProvider::cl
price = MarketsListItemUM.Price(
text = "0.${prices[0].first}023 $",
changeType = prices[0].second,
fiatPrice = BigDecimal(123123),
annotated = stringReference("0.${prices[0].first}023 $"),
),
)
state2 = state2.copy(
price = MarketsListItemUM.Price(
text = "0.${prices[1].first}023 $",
changeType = prices[1].second,
fiatPrice = BigDecimal(123123),
annotated = stringReference("0.${prices[0].first}023 $"),
),
)
},

View file

@ -6,6 +6,7 @@ import com.tangem.common.ui.charts.state.MarketChartRawData
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.models.currency.CryptoCurrency
import java.math.BigDecimal
@Immutable
data class MarketsListItemUM(
@ -40,7 +41,9 @@ data class MarketsListItemUM(
@Immutable
data class Price(
val text: String,
val annotated: TextReference,
val changeType: PriceChangeType? = null,
val fiatPrice: BigDecimal,
)
@Suppress("NullableToStringCall")

View file

@ -7,6 +7,7 @@ import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.currency.CryptoCurrency
import kotlinx.collections.immutable.persistentListOf
import java.math.BigDecimal
@Suppress("MagicNumber")
class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvider<MarketsListItemUM>(
@ -18,7 +19,11 @@ class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvide
iconUrl = "",
ratingPosition = "1",
marketCap = "$6.233 B",
price = MarketsListItemUM.Price(text = "31 285.72$"),
price = MarketsListItemUM.Price(
text = "31 285.72$",
fiatPrice = BigDecimal(123123),
annotated = stringReference("31 285.72$"),
),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chartData = MarketChartRawData(
@ -35,7 +40,11 @@ class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvide
iconUrl = null,
ratingPosition = "2",
marketCap = "$6.233 B",
price = MarketsListItemUM.Price(text = "31 285.72$"),
price = MarketsListItemUM.Price(
text = "31 285.72$",
fiatPrice = BigDecimal(123123),
annotated = stringReference("31 285.72$"),
),
trendPercentText = "12.43%",
trendType = PriceChangeType.NEUTRAL,
chartData = null,
@ -50,7 +59,11 @@ class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvide
iconUrl = null,
ratingPosition = "10",
marketCap = "$6.23348172384781234 B",
price = MarketsListItemUM.Price(text = "31 285.72$"),
price = MarketsListItemUM.Price(
text = "31 285.72$",
fiatPrice = BigDecimal(123123),
annotated = stringReference("31 285.72$"),
),
trendPercentText = "12.43%",
trendType = PriceChangeType.DOWN,
chartData = MarketChartRawData(
@ -67,7 +80,11 @@ class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvide
iconUrl = null,
ratingPosition = "10",
marketCap = null,
price = MarketsListItemUM.Price(text = "31 285.72$"),
price = MarketsListItemUM.Price(
text = "31 285.72$",
fiatPrice = BigDecimal(123123),
annotated = stringReference("31 285.72$"),
),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chartData = MarketChartRawData(
@ -84,7 +101,11 @@ class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvide
iconUrl = null,
ratingPosition = null,
marketCap = "$6.233 B",
price = MarketsListItemUM.Price(text = "31 285.72$"),
price = MarketsListItemUM.Price(
text = "31 285.72$",
fiatPrice = BigDecimal(123123),
annotated = stringReference("31 285.72$"),
),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chartData = MarketChartRawData(
@ -101,7 +122,11 @@ class MarketChartListItemPreviewDataProvider : CollectionPreviewParameterProvide
iconUrl = null,
ratingPosition = null,
marketCap = null,
price = MarketsListItemUM.Price(text = "31 285.72$"),
price = MarketsListItemUM.Price(
text = "31 285.72$",
fiatPrice = BigDecimal(123123),
annotated = stringReference("31 285.72$"),
),
trendPercentText = "12.43%",
trendType = PriceChangeType.UP,
chartData = MarketChartRawData(

View file

@ -6,25 +6,33 @@ import androidx.compose.animation.core.tween
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resolveAnnotatedReference
import com.tangem.core.ui.res.LocalRedesignEnabled
import com.tangem.core.ui.res.TangemTheme
import java.math.BigDecimal
/**
* Text view for token price.
*
* @param price Price of the token.
* @param price Plain price string (used by V1 and as fallback for V2 when [priceAnnotated] is null).
* @param priceAnnotated Optional styled price (locale-aware decimal separator + secondary fractional color).
* @param priceChangeType Type of the price change.
*/
@Composable
fun TokenPriceText(price: String, modifier: Modifier = Modifier, priceChangeType: PriceChangeType? = null) {
fun TokenPriceText(
priceValue: BigDecimal,
price: String,
priceAnnotated: TextReference,
modifier: Modifier = Modifier,
priceChangeType: PriceChangeType? = null,
) {
if (LocalRedesignEnabled.current) {
TokenPriceTextV2(
price = price,
priceValue = priceValue,
priceAnnotated = priceAnnotated,
modifier = modifier,
priceChangeType = priceChangeType,
)
@ -76,16 +84,20 @@ private fun TokenPriceTextV1(price: String, modifier: Modifier = Modifier, price
}
@Composable
private fun TokenPriceTextV2(price: String, modifier: Modifier = Modifier, priceChangeType: PriceChangeType? = null) {
private fun TokenPriceTextV2(
priceValue: BigDecimal,
priceAnnotated: TextReference,
modifier: Modifier = Modifier,
priceChangeType: PriceChangeType? = null,
) {
val growColor = TangemTheme.colors2.text.status.accent
val fallColor = TangemTheme.colors2.text.status.warning
val generalColor = TangemTheme.colors2.text.neutral.primary
val decimalColor = TangemTheme.colors2.text.neutral.secondary
val color = remember(generalColor) { Animatable(generalColor) }
var isAnimationSkipped by remember { mutableStateOf(false) }
LaunchedEffect(price) {
LaunchedEffect(priceValue) {
if (!isAnimationSkipped) {
isAnimationSkipped = true
return@LaunchedEffect
@ -103,27 +115,9 @@ private fun TokenPriceTextV2(price: String, modifier: Modifier = Modifier, price
}
}
val annotatedText = remember(price) {
buildAnnotatedString {
val dotIndex = price.indexOf(".")
if (dotIndex == -1) {
append(price)
} else {
append(price.take(dotIndex))
withStyle(
style = SpanStyle(color = decimalColor),
) {
append(price.substring(dotIndex))
}
}
}
}
Text(
modifier = modifier,
text = annotatedText,
text = priceAnnotated.resolveAnnotatedReference(),
color = color.value,
maxLines = 1,
style = TangemTheme.typography2.bodySemibold16,