Updated on 2026-08-14
This commit is contained in:
parent
88f7205293
commit
f9f2ac60d0
8 changed files with 221 additions and 116 deletions
|
|
@ -104,6 +104,8 @@ data class TokenMarketInfoResponse(
|
|||
data class Metrics(
|
||||
@Json(name = "market_rating")
|
||||
val marketRating: Int?,
|
||||
@Json(name = "market_rating_change_24h")
|
||||
val marketRatingChange24h: Int?,
|
||||
@Json(name = "circulating_supply")
|
||||
val circulatingSupply: BigDecimal?,
|
||||
@Json(name = "market_cap")
|
||||
|
|
|
|||
|
|
@ -834,6 +834,7 @@
|
|||
<string name="markets_token_details_max_supply_description">The maximum number of coins or tokens that can ever exist for a particular cryptocurrency</string>
|
||||
<string name="markets_token_details_max_supply_full">Max supply</string>
|
||||
<string name="markets_token_details_metrics">Metrics</string>
|
||||
<string name="markets_token_details_metrics_no_limited">No limited</string>
|
||||
<string name="markets_token_details_official_links">Official links</string>
|
||||
<string name="markets_token_details_price_performance">Price performance</string>
|
||||
<string name="markets_token_details_repository">Repository</string>
|
||||
|
|
|
|||
|
|
@ -114,6 +114,18 @@ class TangemTypography2 internal constructor(
|
|||
),
|
||||
)
|
||||
|
||||
val headingSemibold22: TextStyle = TextStyle(
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 22.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
letterSpacing = TextUnit(value = 0.38f, type = TextUnitType.Sp),
|
||||
lineHeight = TextUnit(value = 28f, type = TextUnitType.Sp),
|
||||
lineHeightStyle = LineHeightStyle(
|
||||
alignment = LineHeightStyle.Alignment.Center,
|
||||
trim = LineHeightStyle.Trim.None,
|
||||
),
|
||||
)
|
||||
|
||||
val headingRegular20: TextStyle = TextStyle(
|
||||
fontFamily = fontFamily,
|
||||
fontSize = 20.sp,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ internal class TokenMarketInfoConverter(
|
|||
private fun TokenMarketInfoResponse.Metrics.convert(): TokenMarketInfo.Metrics {
|
||||
return TokenMarketInfo.Metrics(
|
||||
marketRating = marketRating,
|
||||
marketRatingChange24h = marketRatingChange24h,
|
||||
circulatingSupply = circulatingSupply,
|
||||
marketCap = marketCap,
|
||||
volume24h = volume24h,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ data class TokenMarketInfo(
|
|||
|
||||
data class Metrics(
|
||||
val marketRating: Int?,
|
||||
val marketRatingChange24h: Int?,
|
||||
val circulatingSupply: BigDecimal?,
|
||||
val marketCap: BigDecimal?,
|
||||
val volume24h: BigDecimal?,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.feed.model.market.details.converter
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
|
|
@ -37,7 +38,7 @@ internal class MetricsConverter(
|
|||
metrics = persistentListOf(
|
||||
InfoPointUM(
|
||||
title = resourceReference(R.string.markets_token_details_market_capitalization),
|
||||
value = marketCap.formatAmount(),
|
||||
value = marketCap.formatAmount() ?: StringsSigns.DASH_SIGN,
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -65,7 +66,7 @@ internal class MetricsConverter(
|
|||
),
|
||||
InfoPointUM(
|
||||
title = resourceReference(R.string.markets_token_details_trading_volume),
|
||||
value = volume24h.formatAmount(),
|
||||
value = volume24h.formatAmount() ?: StringsSigns.DASH_SIGN,
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -79,7 +80,7 @@ internal class MetricsConverter(
|
|||
),
|
||||
InfoPointUM(
|
||||
title = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
|
||||
value = fullyDilutedValuation.formatAmount(),
|
||||
value = fullyDilutedValuation.formatAmount() ?: StringsSigns.DASH_SIGN,
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -95,7 +96,7 @@ internal class MetricsConverter(
|
|||
),
|
||||
InfoPointUM(
|
||||
title = resourceReference(R.string.markets_token_details_circulating_supply),
|
||||
value = circulatingSupply.formatAmount(crypto = true),
|
||||
value = circulatingSupply.formatAmount(crypto = true) ?: StringsSigns.DASH_SIGN,
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -109,7 +110,7 @@ internal class MetricsConverter(
|
|||
),
|
||||
InfoPointUM(
|
||||
title = resourceReference(R.string.markets_token_details_max_supply),
|
||||
value = maxSupply.formatMaxSupply(),
|
||||
value = maxSupply.formatMaxSupply() ?: StringsSigns.DASH_SIGN,
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -135,7 +136,7 @@ internal class MetricsConverter(
|
|||
val liquidity = getLiquidity(value.volume24h, value.marketCap)
|
||||
persistentListOf(
|
||||
InfoPointUMV2.MarketCap(
|
||||
capitalizationValue = stringReference(marketCap.formatAmount()),
|
||||
capitalizationValue = marketCap.formatAmount()?.let(::stringReference),
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -150,7 +151,7 @@ internal class MetricsConverter(
|
|||
},
|
||||
),
|
||||
InfoPointUMV2.TradingVolume(
|
||||
tradingValue = stringReference(volume24h.formatAmount()),
|
||||
tradingValue = volume24h.formatAmount()?.let(::stringReference),
|
||||
liquidity = liquidity,
|
||||
trendingVolumeLiquidityType = getTrendingVolumeLiquidityType(liquidity),
|
||||
onInfoClick = {
|
||||
|
|
@ -165,7 +166,9 @@ internal class MetricsConverter(
|
|||
},
|
||||
),
|
||||
InfoPointUMV2.MarketPosition(
|
||||
position = marketRating?.toString() ?: StringsSigns.DASH_SIGN,
|
||||
position = marketRating?.let {
|
||||
stringReference(it.toString())
|
||||
},
|
||||
rangeValue = getMarketRatingRangeValue(marketRating),
|
||||
marketRatingType = getMarketRatingType(marketRating),
|
||||
onInfoClick = {
|
||||
|
|
@ -176,12 +179,15 @@ internal class MetricsConverter(
|
|||
),
|
||||
)
|
||||
},
|
||||
marketRatingChange24H = getMarketRatingChange(marketRatingChange24h),
|
||||
),
|
||||
InfoPointUMV2.FullyDilutedValuation(
|
||||
value = resourceReference(
|
||||
R.string.markets_token_details_valuation_value_in_total,
|
||||
wrappedList(fullyDilutedValuation.formatAmount()),
|
||||
),
|
||||
value = fullyDilutedValuation?.formatAmount()?.let { formatted ->
|
||||
resourceReference(
|
||||
id = R.string.markets_token_details_valuation_value_in_total,
|
||||
formatArgs = wrappedList(formatted),
|
||||
)
|
||||
},
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
|
|
@ -196,20 +202,29 @@ internal class MetricsConverter(
|
|||
},
|
||||
),
|
||||
InfoPointUMV2.CirculatingSupply(
|
||||
currentValue = stringReference(circulatingSupply.formatAmount(crypto = true)),
|
||||
maxValue = maxSupply?.let { supply ->
|
||||
if (supply > BigDecimal.ZERO) {
|
||||
stringReference(supply.formatMaxSupply())
|
||||
} else {
|
||||
null
|
||||
currentValue = circulatingSupply?.formatAmount(true)?.let(::stringReference),
|
||||
maxValue = when (maxSupply) {
|
||||
null -> null
|
||||
BigDecimal.ZERO -> {
|
||||
resourceReference(
|
||||
R.string
|
||||
.markets_token_details_metrics_no_limited,
|
||||
)
|
||||
}
|
||||
else -> maxSupply.formatAmount(true)?.let(::stringReference)
|
||||
},
|
||||
fillValue = getCirculatingSupplyFillValue(circulatingSupply, maxSupply),
|
||||
onInfoClick = {
|
||||
onInfoClick(
|
||||
InfoBottomSheetContent(
|
||||
title = resourceReference(R.string.markets_token_details_max_supply_full),
|
||||
body = resourceReference(R.string.markets_token_details_total_supply_description),
|
||||
title = resourceReference(
|
||||
R.string.markets_token_details_max_supply_and_circulation_full,
|
||||
),
|
||||
body = combinedReference(
|
||||
resourceReference(R.string.markets_token_details_circulating_supply_description),
|
||||
stringReference("\n\n"),
|
||||
resourceReference(R.string.markets_token_details_total_supply_description),
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
@ -234,7 +249,7 @@ internal class MetricsConverter(
|
|||
)
|
||||
}
|
||||
|
||||
private fun BigDecimal?.formatMaxSupply(): String {
|
||||
private fun BigDecimal?.formatMaxSupply(): String? {
|
||||
when (this) {
|
||||
null -> return StringsSigns.DASH_SIGN
|
||||
BigDecimal.ZERO -> return StringsSigns.INFINITY_SIGN
|
||||
|
|
@ -243,8 +258,8 @@ internal class MetricsConverter(
|
|||
return this.formatAmount(crypto = true)
|
||||
}
|
||||
|
||||
private fun BigDecimal?.formatAmount(crypto: Boolean = false): String {
|
||||
if (this == null) return StringsSigns.DASH_SIGN
|
||||
private fun BigDecimal?.formatAmount(crypto: Boolean = false): String? {
|
||||
if (this == null) return null
|
||||
|
||||
return if (crypto) {
|
||||
format {
|
||||
|
|
@ -266,9 +281,8 @@ internal class MetricsConverter(
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun getLiquidity(volume24h: BigDecimal?, marketCap: BigDecimal?): Float {
|
||||
if (volume24h == null || marketCap == null || marketCap == BigDecimal.ZERO) return 0f
|
||||
|
||||
private fun getLiquidity(volume24h: BigDecimal?, marketCap: BigDecimal?): Float? {
|
||||
if (volume24h == null || marketCap == null || marketCap == BigDecimal.ZERO) return null
|
||||
val ratio = volume24h
|
||||
.divide(marketCap, 6, RoundingMode.HALF_UP)
|
||||
.toFloat()
|
||||
|
|
@ -277,8 +291,9 @@ internal class MetricsConverter(
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun getTrendingVolumeLiquidityType(liquidity: Float): TrendingVolumeLiquidityType {
|
||||
private fun getTrendingVolumeLiquidityType(liquidity: Float?): TrendingVolumeLiquidityType {
|
||||
return when {
|
||||
liquidity == null -> TrendingVolumeLiquidityType.UNKNOWN
|
||||
liquidity >= 0.5f -> TrendingVolumeLiquidityType.HIGH
|
||||
liquidity in 0.2f..<0.5f -> TrendingVolumeLiquidityType.MEDIUM
|
||||
else -> TrendingVolumeLiquidityType.LOW
|
||||
|
|
@ -296,8 +311,8 @@ internal class MetricsConverter(
|
|||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun getMarketRatingRangeValue(marketRating: Int?): Float {
|
||||
if (marketRating == null) return 0f
|
||||
private fun getMarketRatingRangeValue(marketRating: Int?): Float? {
|
||||
if (marketRating == null) return null
|
||||
|
||||
return when {
|
||||
marketRating <= 20 -> {
|
||||
|
|
@ -352,4 +367,12 @@ internal class MetricsConverter(
|
|||
|
||||
return ratio.coerceIn(0f, 1f)
|
||||
}
|
||||
|
||||
private fun getMarketRatingChange(change: Int?): MarketRatingChange24H {
|
||||
return when {
|
||||
change == null || change == 0 -> MarketRatingChange24H.NoChanges
|
||||
change < 0 -> MarketRatingChange24H.Down(-change)
|
||||
else -> MarketRatingChange24H.Up(change)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,14 +21,12 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerW
|
||||
import com.tangem.core.ui.components.progressbar.TangemLinearProgressIndicator
|
||||
import com.tangem.core.ui.ds.progress.TangemLinearProgressIndicatorWithDot
|
||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||
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.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.LocalIsInDarkTheme
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -36,6 +34,7 @@ import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
|||
import com.tangem.features.feed.impl.R
|
||||
import com.tangem.features.feed.ui.components.MetricsCard
|
||||
import com.tangem.features.feed.ui.market.detailed.state.InfoPointUMV2
|
||||
import com.tangem.features.feed.ui.market.detailed.state.MarketRatingChange24H
|
||||
import com.tangem.features.feed.ui.market.detailed.state.MarketRatingType
|
||||
import com.tangem.features.feed.ui.market.detailed.state.TrendingVolumeLiquidityType
|
||||
|
||||
|
|
@ -45,15 +44,7 @@ internal fun MarketCapCard(item: InfoPointUMV2.MarketCap) {
|
|||
modifier = Modifier
|
||||
.heightIn(120.dp)
|
||||
.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = item.capitalizationValue.resolveReference(),
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
title = { MetricValueText(value = item.capitalizationValue) },
|
||||
content = {
|
||||
InformationTextBlock(
|
||||
text = resourceReference(R.string.markets_token_details_market_capitalization),
|
||||
|
|
@ -69,25 +60,22 @@ internal fun TradingVolumeCard(item: InfoPointUMV2.TradingVolume) {
|
|||
TrendingVolumeLiquidityType.HIGH -> TangemTheme.colors2.markers.backgroundSolidGreen
|
||||
TrendingVolumeLiquidityType.MEDIUM -> TangemTheme.colors2.graphic.status.attention
|
||||
TrendingVolumeLiquidityType.LOW -> TangemTheme.colors2.graphic.status.warning
|
||||
TrendingVolumeLiquidityType.UNKNOWN -> TangemTheme.colors2.surface.level3
|
||||
}
|
||||
val valueColor = metricValueColor(hasData = item.tradingValue != null)
|
||||
|
||||
MetricsCard(
|
||||
modifier = Modifier
|
||||
.heightIn(120.dp)
|
||||
.fillMaxWidth(),
|
||||
title = {
|
||||
Row {
|
||||
Text(
|
||||
text = item.tradingValue.resolveReference(),
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
MetricValueText(item.tradingValue)
|
||||
Text(
|
||||
modifier = Modifier.padding(TangemTheme.dimens2.x1),
|
||||
text = stringResourceSafe(R.string.markets_token_details_trading_interval),
|
||||
style = TangemTheme.typography2.captionSemibold11,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
color = valueColor,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
|
@ -95,14 +83,17 @@ internal fun TradingVolumeCard(item: InfoPointUMV2.TradingVolume) {
|
|||
},
|
||||
content = {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
if (item.liquidity != null) {
|
||||
TangemLinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(6.dp),
|
||||
progress = { item.liquidity },
|
||||
color = tradingColor,
|
||||
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant.copy(alpha = .1f),
|
||||
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant
|
||||
.copy(alpha = .1f),
|
||||
)
|
||||
}
|
||||
SpacerH(12.dp)
|
||||
InformationTextBlock(
|
||||
text = resourceReference(R.string.markets_token_details_trading_volume),
|
||||
|
|
@ -127,29 +118,16 @@ internal fun MarketPositionCard(item: InfoPointUMV2.MarketPosition) {
|
|||
.fillMaxWidth(),
|
||||
title = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_big_laurel_left_20),
|
||||
tint = ratingColor,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = item.position,
|
||||
color = ratingColor,
|
||||
style = TangemTheme.typography2.headingSemibold20.copy(letterSpacing = 0.sp),
|
||||
maxLines = 1,
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_big_laurel_right_20),
|
||||
tint = ratingColor,
|
||||
contentDescription = null,
|
||||
)
|
||||
MarketPositionValue(position = item.position, ratingColor = ratingColor)
|
||||
if (item.position != null) {
|
||||
SpacerW(6.dp)
|
||||
RatingChangeIndicator(change = item.marketRatingChange24H)
|
||||
}
|
||||
}
|
||||
},
|
||||
content = {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
if (item.rangeValue != null) {
|
||||
TangemLinearProgressIndicatorWithDot(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -158,6 +136,7 @@ internal fun MarketPositionCard(item: InfoPointUMV2.MarketPosition) {
|
|||
dotColor = TangemTheme.colors2.fill.neutral.primaryInvertedConstant,
|
||||
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant.copy(alpha = .1f),
|
||||
)
|
||||
}
|
||||
SpacerH(12.dp)
|
||||
InformationTextBlock(
|
||||
text = resourceReference(R.string.markets_token_details_market_rating),
|
||||
|
|
@ -177,15 +156,7 @@ internal fun FDVCard(item: InfoPointUMV2.FullyDilutedValuation) {
|
|||
modifier = Modifier
|
||||
.heightIn(120.dp)
|
||||
.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = item.value.resolveReference(),
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
title = { MetricValueText(value = item.value) },
|
||||
content = {
|
||||
InformationTextBlock(
|
||||
text = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
|
||||
|
|
@ -212,15 +183,11 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
|||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
MetricValueText(
|
||||
value = item.currentValue,
|
||||
modifier = Modifier
|
||||
.padding(top = 12.dp)
|
||||
.layoutId(TangemRowLayoutId.START_BOTTOM),
|
||||
text = item.currentValue.resolveReference(),
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
|
|
@ -238,7 +205,7 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
|||
.padding(top = 12.dp)
|
||||
.layoutId(TangemRowLayoutId.END_BOTTOM),
|
||||
text = item.maxValue.resolveReference(),
|
||||
style = TangemTheme.typography2.headingSemibold20,
|
||||
style = TangemTheme.typography2.headingSemibold22,
|
||||
color = TangemTheme.colors2.text.neutral.primary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -253,7 +220,8 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
|||
.fillMaxWidth()
|
||||
.height(6.dp),
|
||||
color = TangemTheme.colors2.graphic.status.accent,
|
||||
trackColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant.copy(alpha = .1f),
|
||||
trackColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant
|
||||
.copy(alpha = .1f),
|
||||
progress = { item.fillValue },
|
||||
strokeCap = StrokeCap.Round,
|
||||
drawStopIndicator = {},
|
||||
|
|
@ -265,6 +233,87 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
|||
)
|
||||
}
|
||||
|
||||
// region Private helpers
|
||||
|
||||
@Composable
|
||||
private fun MetricValueText(value: TextReference?, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = value?.resolveReference() ?: stringResourceSafe(R.string.token_market_metrics_no_data),
|
||||
style = TangemTheme.typography2.headingSemibold22,
|
||||
color = metricValueColor(hasData = value != null),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun metricValueColor(hasData: Boolean): Color {
|
||||
return if (hasData) TangemTheme.colors2.text.neutral.primary else TangemTheme.colors2.text.neutral.tertiary
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MarketPositionValue(position: TextReference?, ratingColor: Color) {
|
||||
if (position != null) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_big_laurel_left_20),
|
||||
tint = ratingColor,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = position.resolveReference(),
|
||||
color = ratingColor,
|
||||
style = TangemTheme.typography2.headingSemibold22.copy(letterSpacing = 0.sp),
|
||||
maxLines = 1,
|
||||
)
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_big_laurel_right_20),
|
||||
tint = ratingColor,
|
||||
contentDescription = null,
|
||||
)
|
||||
} else {
|
||||
MetricValueText(value = null)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RatingChangeIndicator(change: MarketRatingChange24H) {
|
||||
when (change) {
|
||||
is MarketRatingChange24H.Up -> RatingChangeContent(
|
||||
iconRes = R.drawable.ic_arrow_up_8,
|
||||
iconTint = TangemTheme.colors2.markers.iconGreen,
|
||||
changeValue = change.changeValue.toString(),
|
||||
textColor = TangemTheme.colors2.text.status.positive,
|
||||
)
|
||||
is MarketRatingChange24H.Down -> RatingChangeContent(
|
||||
iconRes = R.drawable.ic_arrow_down_8,
|
||||
iconTint = TangemTheme.colors2.markers.iconRed,
|
||||
changeValue = change.changeValue.toString(),
|
||||
textColor = TangemTheme.colors2.text.status.warning,
|
||||
)
|
||||
MarketRatingChange24H.NoChanges -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RatingChangeContent(iconRes: Int, iconTint: Color, changeValue: String, textColor: Color) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens2.x3),
|
||||
imageVector = ImageVector.vectorResource(id = iconRes),
|
||||
tint = iconTint,
|
||||
contentDescription = null,
|
||||
)
|
||||
SpacerW(2.dp)
|
||||
Text(
|
||||
text = changeValue,
|
||||
style = TangemTheme.typography2.captionSemibold12,
|
||||
color = textColor,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MarketRatingType.baseColor(): Color {
|
||||
val isDarkTheme = LocalIsInDarkTheme.current
|
||||
|
|
@ -295,6 +344,8 @@ private fun mapRatingToCardColor(marketRatingType: MarketRatingType): Color {
|
|||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
private const val GOLD_PLACE_COLOR_NIGHT = 0xFFFBEE76
|
||||
private const val GOLD_PLACE_COLOR_LIGHT = 0xFFD9B900
|
||||
private const val SILVER_PLACE_COLOR_NIGHT = 0xFFAABEF7
|
||||
|
|
@ -353,17 +404,19 @@ private fun MetricsCardsPreview() {
|
|||
|
||||
MarketPositionCard(
|
||||
item = InfoPointUMV2.MarketPosition(
|
||||
position = "1",
|
||||
position = stringReference("1"),
|
||||
rangeValue = 0.02f,
|
||||
marketRatingType = MarketRatingType.GOLD,
|
||||
onInfoClick = {},
|
||||
marketRatingChange24H = MarketRatingChange24H.NoChanges,
|
||||
),
|
||||
)
|
||||
|
||||
MarketPositionCard(
|
||||
item = InfoPointUMV2.MarketPosition(
|
||||
position = "2",
|
||||
position = stringReference("2"),
|
||||
rangeValue = 0.05f,
|
||||
marketRatingChange24H = MarketRatingChange24H.Up(1),
|
||||
marketRatingType = MarketRatingType.SILVER,
|
||||
onInfoClick = {},
|
||||
),
|
||||
|
|
@ -371,19 +424,21 @@ private fun MetricsCardsPreview() {
|
|||
|
||||
MarketPositionCard(
|
||||
item = InfoPointUMV2.MarketPosition(
|
||||
position = "3",
|
||||
rangeValue = 0.08f,
|
||||
marketRatingType = MarketRatingType.BRONZE,
|
||||
position = null,
|
||||
rangeValue = null,
|
||||
marketRatingType = MarketRatingType.OTHER,
|
||||
onInfoClick = {},
|
||||
marketRatingChange24H = MarketRatingChange24H.NoChanges,
|
||||
),
|
||||
)
|
||||
|
||||
MarketPositionCard(
|
||||
item = InfoPointUMV2.MarketPosition(
|
||||
position = "42",
|
||||
position = stringReference("42"),
|
||||
rangeValue = 0.42f,
|
||||
marketRatingType = MarketRatingType.OTHER,
|
||||
onInfoClick = {},
|
||||
marketRatingChange24H = MarketRatingChange24H.Down(15),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,35 +14,36 @@ internal sealed interface InfoPointUMV2 {
|
|||
|
||||
@Immutable
|
||||
data class MarketCap(
|
||||
val capitalizationValue: TextReference,
|
||||
val capitalizationValue: TextReference?,
|
||||
val onInfoClick: () -> Unit,
|
||||
) : InfoPointUMV2
|
||||
|
||||
@Immutable
|
||||
data class TradingVolume(
|
||||
val tradingValue: TextReference,
|
||||
val liquidity: Float,
|
||||
val tradingValue: TextReference?,
|
||||
val liquidity: Float?,
|
||||
val trendingVolumeLiquidityType: TrendingVolumeLiquidityType,
|
||||
val onInfoClick: () -> Unit,
|
||||
) : InfoPointUMV2
|
||||
|
||||
@Immutable
|
||||
data class MarketPosition(
|
||||
val position: String,
|
||||
val rangeValue: Float,
|
||||
val position: TextReference?,
|
||||
val rangeValue: Float?,
|
||||
val marketRatingChange24H: MarketRatingChange24H,
|
||||
val marketRatingType: MarketRatingType,
|
||||
val onInfoClick: () -> Unit,
|
||||
) : InfoPointUMV2
|
||||
|
||||
@Immutable
|
||||
data class FullyDilutedValuation(
|
||||
val value: TextReference,
|
||||
val value: TextReference?,
|
||||
val onInfoClick: () -> Unit,
|
||||
) : InfoPointUMV2
|
||||
|
||||
@Immutable
|
||||
data class CirculatingSupply(
|
||||
val currentValue: TextReference,
|
||||
val currentValue: TextReference?,
|
||||
val maxValue: TextReference?,
|
||||
val fillValue: Float?,
|
||||
val onInfoClick: () -> Unit,
|
||||
|
|
@ -60,9 +61,18 @@ internal data class MetricsV2UM(
|
|||
}
|
||||
|
||||
internal enum class TrendingVolumeLiquidityType {
|
||||
HIGH, MEDIUM, LOW,
|
||||
HIGH, MEDIUM, LOW, UNKNOWN
|
||||
}
|
||||
|
||||
internal enum class MarketRatingType {
|
||||
GOLD, SILVER, BRONZE, OTHER
|
||||
}
|
||||
|
||||
internal sealed interface MarketRatingChange24H {
|
||||
|
||||
data class Up(val changeValue: Int) : MarketRatingChange24H
|
||||
|
||||
data class Down(val changeValue: Int) : MarketRatingChange24H
|
||||
|
||||
data object NoChanges : MarketRatingChange24H
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue