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(
|
data class Metrics(
|
||||||
@Json(name = "market_rating")
|
@Json(name = "market_rating")
|
||||||
val marketRating: Int?,
|
val marketRating: Int?,
|
||||||
|
@Json(name = "market_rating_change_24h")
|
||||||
|
val marketRatingChange24h: Int?,
|
||||||
@Json(name = "circulating_supply")
|
@Json(name = "circulating_supply")
|
||||||
val circulatingSupply: BigDecimal?,
|
val circulatingSupply: BigDecimal?,
|
||||||
@Json(name = "market_cap")
|
@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_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_max_supply_full">Max supply</string>
|
||||||
<string name="markets_token_details_metrics">Metrics</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_official_links">Official links</string>
|
||||||
<string name="markets_token_details_price_performance">Price performance</string>
|
<string name="markets_token_details_price_performance">Price performance</string>
|
||||||
<string name="markets_token_details_repository">Repository</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(
|
val headingRegular20: TextStyle = TextStyle(
|
||||||
fontFamily = fontFamily,
|
fontFamily = fontFamily,
|
||||||
fontSize = 20.sp,
|
fontSize = 20.sp,
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ internal class TokenMarketInfoConverter(
|
||||||
private fun TokenMarketInfoResponse.Metrics.convert(): TokenMarketInfo.Metrics {
|
private fun TokenMarketInfoResponse.Metrics.convert(): TokenMarketInfo.Metrics {
|
||||||
return TokenMarketInfo.Metrics(
|
return TokenMarketInfo.Metrics(
|
||||||
marketRating = marketRating,
|
marketRating = marketRating,
|
||||||
|
marketRatingChange24h = marketRatingChange24h,
|
||||||
circulatingSupply = circulatingSupply,
|
circulatingSupply = circulatingSupply,
|
||||||
marketCap = marketCap,
|
marketCap = marketCap,
|
||||||
volume24h = volume24h,
|
volume24h = volume24h,
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ data class TokenMarketInfo(
|
||||||
|
|
||||||
data class Metrics(
|
data class Metrics(
|
||||||
val marketRating: Int?,
|
val marketRating: Int?,
|
||||||
|
val marketRatingChange24h: Int?,
|
||||||
val circulatingSupply: BigDecimal?,
|
val circulatingSupply: BigDecimal?,
|
||||||
val marketCap: BigDecimal?,
|
val marketCap: BigDecimal?,
|
||||||
val volume24h: BigDecimal?,
|
val volume24h: BigDecimal?,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.features.feed.model.market.details.converter
|
package com.tangem.features.feed.model.market.details.converter
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
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.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
|
|
@ -37,7 +38,7 @@ internal class MetricsConverter(
|
||||||
metrics = persistentListOf(
|
metrics = persistentListOf(
|
||||||
InfoPointUM(
|
InfoPointUM(
|
||||||
title = resourceReference(R.string.markets_token_details_market_capitalization),
|
title = resourceReference(R.string.markets_token_details_market_capitalization),
|
||||||
value = marketCap.formatAmount(),
|
value = marketCap.formatAmount() ?: StringsSigns.DASH_SIGN,
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -65,7 +66,7 @@ internal class MetricsConverter(
|
||||||
),
|
),
|
||||||
InfoPointUM(
|
InfoPointUM(
|
||||||
title = resourceReference(R.string.markets_token_details_trading_volume),
|
title = resourceReference(R.string.markets_token_details_trading_volume),
|
||||||
value = volume24h.formatAmount(),
|
value = volume24h.formatAmount() ?: StringsSigns.DASH_SIGN,
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -79,7 +80,7 @@ internal class MetricsConverter(
|
||||||
),
|
),
|
||||||
InfoPointUM(
|
InfoPointUM(
|
||||||
title = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
|
title = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
|
||||||
value = fullyDilutedValuation.formatAmount(),
|
value = fullyDilutedValuation.formatAmount() ?: StringsSigns.DASH_SIGN,
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -95,7 +96,7 @@ internal class MetricsConverter(
|
||||||
),
|
),
|
||||||
InfoPointUM(
|
InfoPointUM(
|
||||||
title = resourceReference(R.string.markets_token_details_circulating_supply),
|
title = resourceReference(R.string.markets_token_details_circulating_supply),
|
||||||
value = circulatingSupply.formatAmount(crypto = true),
|
value = circulatingSupply.formatAmount(crypto = true) ?: StringsSigns.DASH_SIGN,
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -109,7 +110,7 @@ internal class MetricsConverter(
|
||||||
),
|
),
|
||||||
InfoPointUM(
|
InfoPointUM(
|
||||||
title = resourceReference(R.string.markets_token_details_max_supply),
|
title = resourceReference(R.string.markets_token_details_max_supply),
|
||||||
value = maxSupply.formatMaxSupply(),
|
value = maxSupply.formatMaxSupply() ?: StringsSigns.DASH_SIGN,
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -135,7 +136,7 @@ internal class MetricsConverter(
|
||||||
val liquidity = getLiquidity(value.volume24h, value.marketCap)
|
val liquidity = getLiquidity(value.volume24h, value.marketCap)
|
||||||
persistentListOf(
|
persistentListOf(
|
||||||
InfoPointUMV2.MarketCap(
|
InfoPointUMV2.MarketCap(
|
||||||
capitalizationValue = stringReference(marketCap.formatAmount()),
|
capitalizationValue = marketCap.formatAmount()?.let(::stringReference),
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -150,7 +151,7 @@ internal class MetricsConverter(
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
InfoPointUMV2.TradingVolume(
|
InfoPointUMV2.TradingVolume(
|
||||||
tradingValue = stringReference(volume24h.formatAmount()),
|
tradingValue = volume24h.formatAmount()?.let(::stringReference),
|
||||||
liquidity = liquidity,
|
liquidity = liquidity,
|
||||||
trendingVolumeLiquidityType = getTrendingVolumeLiquidityType(liquidity),
|
trendingVolumeLiquidityType = getTrendingVolumeLiquidityType(liquidity),
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
|
|
@ -165,7 +166,9 @@ internal class MetricsConverter(
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
InfoPointUMV2.MarketPosition(
|
InfoPointUMV2.MarketPosition(
|
||||||
position = marketRating?.toString() ?: StringsSigns.DASH_SIGN,
|
position = marketRating?.let {
|
||||||
|
stringReference(it.toString())
|
||||||
|
},
|
||||||
rangeValue = getMarketRatingRangeValue(marketRating),
|
rangeValue = getMarketRatingRangeValue(marketRating),
|
||||||
marketRatingType = getMarketRatingType(marketRating),
|
marketRatingType = getMarketRatingType(marketRating),
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
|
|
@ -176,12 +179,15 @@ internal class MetricsConverter(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
marketRatingChange24H = getMarketRatingChange(marketRatingChange24h),
|
||||||
),
|
),
|
||||||
InfoPointUMV2.FullyDilutedValuation(
|
InfoPointUMV2.FullyDilutedValuation(
|
||||||
value = resourceReference(
|
value = fullyDilutedValuation?.formatAmount()?.let { formatted ->
|
||||||
R.string.markets_token_details_valuation_value_in_total,
|
resourceReference(
|
||||||
wrappedList(fullyDilutedValuation.formatAmount()),
|
id = R.string.markets_token_details_valuation_value_in_total,
|
||||||
),
|
formatArgs = wrappedList(formatted),
|
||||||
|
)
|
||||||
|
},
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
|
|
@ -196,20 +202,29 @@ internal class MetricsConverter(
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
InfoPointUMV2.CirculatingSupply(
|
InfoPointUMV2.CirculatingSupply(
|
||||||
currentValue = stringReference(circulatingSupply.formatAmount(crypto = true)),
|
currentValue = circulatingSupply?.formatAmount(true)?.let(::stringReference),
|
||||||
maxValue = maxSupply?.let { supply ->
|
maxValue = when (maxSupply) {
|
||||||
if (supply > BigDecimal.ZERO) {
|
null -> null
|
||||||
stringReference(supply.formatMaxSupply())
|
BigDecimal.ZERO -> {
|
||||||
} else {
|
resourceReference(
|
||||||
null
|
R.string
|
||||||
|
.markets_token_details_metrics_no_limited,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
else -> maxSupply.formatAmount(true)?.let(::stringReference)
|
||||||
},
|
},
|
||||||
fillValue = getCirculatingSupplyFillValue(circulatingSupply, maxSupply),
|
fillValue = getCirculatingSupplyFillValue(circulatingSupply, maxSupply),
|
||||||
onInfoClick = {
|
onInfoClick = {
|
||||||
onInfoClick(
|
onInfoClick(
|
||||||
InfoBottomSheetContent(
|
InfoBottomSheetContent(
|
||||||
title = resourceReference(R.string.markets_token_details_max_supply_full),
|
title = resourceReference(
|
||||||
body = resourceReference(R.string.markets_token_details_total_supply_description),
|
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) {
|
when (this) {
|
||||||
null -> return StringsSigns.DASH_SIGN
|
null -> return StringsSigns.DASH_SIGN
|
||||||
BigDecimal.ZERO -> return StringsSigns.INFINITY_SIGN
|
BigDecimal.ZERO -> return StringsSigns.INFINITY_SIGN
|
||||||
|
|
@ -243,8 +258,8 @@ internal class MetricsConverter(
|
||||||
return this.formatAmount(crypto = true)
|
return this.formatAmount(crypto = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BigDecimal?.formatAmount(crypto: Boolean = false): String {
|
private fun BigDecimal?.formatAmount(crypto: Boolean = false): String? {
|
||||||
if (this == null) return StringsSigns.DASH_SIGN
|
if (this == null) return null
|
||||||
|
|
||||||
return if (crypto) {
|
return if (crypto) {
|
||||||
format {
|
format {
|
||||||
|
|
@ -266,9 +281,8 @@ internal class MetricsConverter(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
private fun getLiquidity(volume24h: BigDecimal?, marketCap: BigDecimal?): Float {
|
private fun getLiquidity(volume24h: BigDecimal?, marketCap: BigDecimal?): Float? {
|
||||||
if (volume24h == null || marketCap == null || marketCap == BigDecimal.ZERO) return 0f
|
if (volume24h == null || marketCap == null || marketCap == BigDecimal.ZERO) return null
|
||||||
|
|
||||||
val ratio = volume24h
|
val ratio = volume24h
|
||||||
.divide(marketCap, 6, RoundingMode.HALF_UP)
|
.divide(marketCap, 6, RoundingMode.HALF_UP)
|
||||||
.toFloat()
|
.toFloat()
|
||||||
|
|
@ -277,8 +291,9 @@ internal class MetricsConverter(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
private fun getTrendingVolumeLiquidityType(liquidity: Float): TrendingVolumeLiquidityType {
|
private fun getTrendingVolumeLiquidityType(liquidity: Float?): TrendingVolumeLiquidityType {
|
||||||
return when {
|
return when {
|
||||||
|
liquidity == null -> TrendingVolumeLiquidityType.UNKNOWN
|
||||||
liquidity >= 0.5f -> TrendingVolumeLiquidityType.HIGH
|
liquidity >= 0.5f -> TrendingVolumeLiquidityType.HIGH
|
||||||
liquidity in 0.2f..<0.5f -> TrendingVolumeLiquidityType.MEDIUM
|
liquidity in 0.2f..<0.5f -> TrendingVolumeLiquidityType.MEDIUM
|
||||||
else -> TrendingVolumeLiquidityType.LOW
|
else -> TrendingVolumeLiquidityType.LOW
|
||||||
|
|
@ -296,8 +311,8 @@ internal class MetricsConverter(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
private fun getMarketRatingRangeValue(marketRating: Int?): Float {
|
private fun getMarketRatingRangeValue(marketRating: Int?): Float? {
|
||||||
if (marketRating == null) return 0f
|
if (marketRating == null) return null
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
marketRating <= 20 -> {
|
marketRating <= 20 -> {
|
||||||
|
|
@ -352,4 +367,12 @@ internal class MetricsConverter(
|
||||||
|
|
||||||
return ratio.coerceIn(0f, 1f)
|
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.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.tangem.core.ui.components.SpacerH
|
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.components.progressbar.TangemLinearProgressIndicator
|
||||||
import com.tangem.core.ui.ds.progress.TangemLinearProgressIndicatorWithDot
|
import com.tangem.core.ui.ds.progress.TangemLinearProgressIndicatorWithDot
|
||||||
import com.tangem.core.ui.ds.row.TangemRowContainer
|
import com.tangem.core.ui.ds.row.TangemRowContainer
|
||||||
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
import com.tangem.core.ui.ds.row.TangemRowLayoutId
|
||||||
import com.tangem.core.ui.extensions.resolveReference
|
import com.tangem.core.ui.extensions.*
|
||||||
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.res.LocalIsInDarkTheme
|
import com.tangem.core.ui.res.LocalIsInDarkTheme
|
||||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
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.impl.R
|
||||||
import com.tangem.features.feed.ui.components.MetricsCard
|
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.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.MarketRatingType
|
||||||
import com.tangem.features.feed.ui.market.detailed.state.TrendingVolumeLiquidityType
|
import com.tangem.features.feed.ui.market.detailed.state.TrendingVolumeLiquidityType
|
||||||
|
|
||||||
|
|
@ -45,15 +44,7 @@ internal fun MarketCapCard(item: InfoPointUMV2.MarketCap) {
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.heightIn(120.dp)
|
.heightIn(120.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
title = {
|
title = { MetricValueText(value = item.capitalizationValue) },
|
||||||
Text(
|
|
||||||
text = item.capitalizationValue.resolveReference(),
|
|
||||||
style = TangemTheme.typography2.headingSemibold20,
|
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
content = {
|
content = {
|
||||||
InformationTextBlock(
|
InformationTextBlock(
|
||||||
text = resourceReference(R.string.markets_token_details_market_capitalization),
|
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.HIGH -> TangemTheme.colors2.markers.backgroundSolidGreen
|
||||||
TrendingVolumeLiquidityType.MEDIUM -> TangemTheme.colors2.graphic.status.attention
|
TrendingVolumeLiquidityType.MEDIUM -> TangemTheme.colors2.graphic.status.attention
|
||||||
TrendingVolumeLiquidityType.LOW -> TangemTheme.colors2.graphic.status.warning
|
TrendingVolumeLiquidityType.LOW -> TangemTheme.colors2.graphic.status.warning
|
||||||
|
TrendingVolumeLiquidityType.UNKNOWN -> TangemTheme.colors2.surface.level3
|
||||||
}
|
}
|
||||||
|
val valueColor = metricValueColor(hasData = item.tradingValue != null)
|
||||||
|
|
||||||
MetricsCard(
|
MetricsCard(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.heightIn(120.dp)
|
.heightIn(120.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
title = {
|
title = {
|
||||||
Row {
|
Row {
|
||||||
Text(
|
MetricValueText(item.tradingValue)
|
||||||
text = item.tradingValue.resolveReference(),
|
|
||||||
style = TangemTheme.typography2.headingSemibold20,
|
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(TangemTheme.dimens2.x1),
|
modifier = Modifier.padding(TangemTheme.dimens2.x1),
|
||||||
text = stringResourceSafe(R.string.markets_token_details_trading_interval),
|
text = stringResourceSafe(R.string.markets_token_details_trading_interval),
|
||||||
style = TangemTheme.typography2.captionSemibold11,
|
style = TangemTheme.typography2.captionSemibold11,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = valueColor,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
|
@ -95,14 +83,17 @@ internal fun TradingVolumeCard(item: InfoPointUMV2.TradingVolume) {
|
||||||
},
|
},
|
||||||
content = {
|
content = {
|
||||||
Column(modifier = Modifier.fillMaxWidth()) {
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
TangemLinearProgressIndicator(
|
if (item.liquidity != null) {
|
||||||
modifier = Modifier
|
TangemLinearProgressIndicator(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.height(6.dp),
|
.fillMaxWidth()
|
||||||
progress = { item.liquidity },
|
.height(6.dp),
|
||||||
color = tradingColor,
|
progress = { item.liquidity },
|
||||||
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant.copy(alpha = .1f),
|
color = tradingColor,
|
||||||
)
|
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant
|
||||||
|
.copy(alpha = .1f),
|
||||||
|
)
|
||||||
|
}
|
||||||
SpacerH(12.dp)
|
SpacerH(12.dp)
|
||||||
InformationTextBlock(
|
InformationTextBlock(
|
||||||
text = resourceReference(R.string.markets_token_details_trading_volume),
|
text = resourceReference(R.string.markets_token_details_trading_volume),
|
||||||
|
|
@ -127,37 +118,25 @@ internal fun MarketPositionCard(item: InfoPointUMV2.MarketPosition) {
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
title = {
|
title = {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Icon(
|
MarketPositionValue(position = item.position, ratingColor = ratingColor)
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.ic_big_laurel_left_20),
|
if (item.position != null) {
|
||||||
tint = ratingColor,
|
SpacerW(6.dp)
|
||||||
contentDescription = null,
|
RatingChangeIndicator(change = item.marketRatingChange24H)
|
||||||
)
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
content = {
|
content = {
|
||||||
Column(modifier = Modifier.fillMaxWidth()) {
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
TangemLinearProgressIndicatorWithDot(
|
if (item.rangeValue != null) {
|
||||||
modifier = Modifier
|
TangemLinearProgressIndicatorWithDot(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.height(6.dp),
|
.fillMaxWidth()
|
||||||
progress = { item.rangeValue },
|
.height(6.dp),
|
||||||
dotColor = TangemTheme.colors2.fill.neutral.primaryInvertedConstant,
|
progress = { item.rangeValue },
|
||||||
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant.copy(alpha = .1f),
|
dotColor = TangemTheme.colors2.fill.neutral.primaryInvertedConstant,
|
||||||
)
|
backgroundColor = TangemTheme.colors2.graphic.neutral.primaryInvertedConstant.copy(alpha = .1f),
|
||||||
|
)
|
||||||
|
}
|
||||||
SpacerH(12.dp)
|
SpacerH(12.dp)
|
||||||
InformationTextBlock(
|
InformationTextBlock(
|
||||||
text = resourceReference(R.string.markets_token_details_market_rating),
|
text = resourceReference(R.string.markets_token_details_market_rating),
|
||||||
|
|
@ -177,15 +156,7 @@ internal fun FDVCard(item: InfoPointUMV2.FullyDilutedValuation) {
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.heightIn(120.dp)
|
.heightIn(120.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
title = {
|
title = { MetricValueText(value = item.value) },
|
||||||
Text(
|
|
||||||
text = item.value.resolveReference(),
|
|
||||||
style = TangemTheme.typography2.headingSemibold20,
|
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
content = {
|
content = {
|
||||||
InformationTextBlock(
|
InformationTextBlock(
|
||||||
text = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
|
text = resourceReference(R.string.markets_token_details_fully_diluted_valuation),
|
||||||
|
|
@ -212,15 +183,11 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
MetricValueText(
|
||||||
|
value = item.currentValue,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = 12.dp)
|
.padding(top = 12.dp)
|
||||||
.layoutId(TangemRowLayoutId.START_BOTTOM),
|
.layoutId(TangemRowLayoutId.START_BOTTOM),
|
||||||
text = item.currentValue.resolveReference(),
|
|
||||||
style = TangemTheme.typography2.headingSemibold20,
|
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -238,7 +205,7 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
||||||
.padding(top = 12.dp)
|
.padding(top = 12.dp)
|
||||||
.layoutId(TangemRowLayoutId.END_BOTTOM),
|
.layoutId(TangemRowLayoutId.END_BOTTOM),
|
||||||
text = item.maxValue.resolveReference(),
|
text = item.maxValue.resolveReference(),
|
||||||
style = TangemTheme.typography2.headingSemibold20,
|
style = TangemTheme.typography2.headingSemibold22,
|
||||||
color = TangemTheme.colors2.text.neutral.primary,
|
color = TangemTheme.colors2.text.neutral.primary,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|
@ -253,7 +220,8 @@ internal fun CirculatingSupplyCard(item: InfoPointUMV2.CirculatingSupply) {
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(6.dp),
|
.height(6.dp),
|
||||||
color = TangemTheme.colors2.graphic.status.accent,
|
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 },
|
progress = { item.fillValue },
|
||||||
strokeCap = StrokeCap.Round,
|
strokeCap = StrokeCap.Round,
|
||||||
drawStopIndicator = {},
|
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
|
@Composable
|
||||||
private fun MarketRatingType.baseColor(): Color {
|
private fun MarketRatingType.baseColor(): Color {
|
||||||
val isDarkTheme = LocalIsInDarkTheme.current
|
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_NIGHT = 0xFFFBEE76
|
||||||
private const val GOLD_PLACE_COLOR_LIGHT = 0xFFD9B900
|
private const val GOLD_PLACE_COLOR_LIGHT = 0xFFD9B900
|
||||||
private const val SILVER_PLACE_COLOR_NIGHT = 0xFFAABEF7
|
private const val SILVER_PLACE_COLOR_NIGHT = 0xFFAABEF7
|
||||||
|
|
@ -353,17 +404,19 @@ private fun MetricsCardsPreview() {
|
||||||
|
|
||||||
MarketPositionCard(
|
MarketPositionCard(
|
||||||
item = InfoPointUMV2.MarketPosition(
|
item = InfoPointUMV2.MarketPosition(
|
||||||
position = "1",
|
position = stringReference("1"),
|
||||||
rangeValue = 0.02f,
|
rangeValue = 0.02f,
|
||||||
marketRatingType = MarketRatingType.GOLD,
|
marketRatingType = MarketRatingType.GOLD,
|
||||||
onInfoClick = {},
|
onInfoClick = {},
|
||||||
|
marketRatingChange24H = MarketRatingChange24H.NoChanges,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
MarketPositionCard(
|
MarketPositionCard(
|
||||||
item = InfoPointUMV2.MarketPosition(
|
item = InfoPointUMV2.MarketPosition(
|
||||||
position = "2",
|
position = stringReference("2"),
|
||||||
rangeValue = 0.05f,
|
rangeValue = 0.05f,
|
||||||
|
marketRatingChange24H = MarketRatingChange24H.Up(1),
|
||||||
marketRatingType = MarketRatingType.SILVER,
|
marketRatingType = MarketRatingType.SILVER,
|
||||||
onInfoClick = {},
|
onInfoClick = {},
|
||||||
),
|
),
|
||||||
|
|
@ -371,19 +424,21 @@ private fun MetricsCardsPreview() {
|
||||||
|
|
||||||
MarketPositionCard(
|
MarketPositionCard(
|
||||||
item = InfoPointUMV2.MarketPosition(
|
item = InfoPointUMV2.MarketPosition(
|
||||||
position = "3",
|
position = null,
|
||||||
rangeValue = 0.08f,
|
rangeValue = null,
|
||||||
marketRatingType = MarketRatingType.BRONZE,
|
marketRatingType = MarketRatingType.OTHER,
|
||||||
onInfoClick = {},
|
onInfoClick = {},
|
||||||
|
marketRatingChange24H = MarketRatingChange24H.NoChanges,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
MarketPositionCard(
|
MarketPositionCard(
|
||||||
item = InfoPointUMV2.MarketPosition(
|
item = InfoPointUMV2.MarketPosition(
|
||||||
position = "42",
|
position = stringReference("42"),
|
||||||
rangeValue = 0.42f,
|
rangeValue = 0.42f,
|
||||||
marketRatingType = MarketRatingType.OTHER,
|
marketRatingType = MarketRatingType.OTHER,
|
||||||
onInfoClick = {},
|
onInfoClick = {},
|
||||||
|
marketRatingChange24H = MarketRatingChange24H.Down(15),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,35 +14,36 @@ internal sealed interface InfoPointUMV2 {
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class MarketCap(
|
data class MarketCap(
|
||||||
val capitalizationValue: TextReference,
|
val capitalizationValue: TextReference?,
|
||||||
val onInfoClick: () -> Unit,
|
val onInfoClick: () -> Unit,
|
||||||
) : InfoPointUMV2
|
) : InfoPointUMV2
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class TradingVolume(
|
data class TradingVolume(
|
||||||
val tradingValue: TextReference,
|
val tradingValue: TextReference?,
|
||||||
val liquidity: Float,
|
val liquidity: Float?,
|
||||||
val trendingVolumeLiquidityType: TrendingVolumeLiquidityType,
|
val trendingVolumeLiquidityType: TrendingVolumeLiquidityType,
|
||||||
val onInfoClick: () -> Unit,
|
val onInfoClick: () -> Unit,
|
||||||
) : InfoPointUMV2
|
) : InfoPointUMV2
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class MarketPosition(
|
data class MarketPosition(
|
||||||
val position: String,
|
val position: TextReference?,
|
||||||
val rangeValue: Float,
|
val rangeValue: Float?,
|
||||||
|
val marketRatingChange24H: MarketRatingChange24H,
|
||||||
val marketRatingType: MarketRatingType,
|
val marketRatingType: MarketRatingType,
|
||||||
val onInfoClick: () -> Unit,
|
val onInfoClick: () -> Unit,
|
||||||
) : InfoPointUMV2
|
) : InfoPointUMV2
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class FullyDilutedValuation(
|
data class FullyDilutedValuation(
|
||||||
val value: TextReference,
|
val value: TextReference?,
|
||||||
val onInfoClick: () -> Unit,
|
val onInfoClick: () -> Unit,
|
||||||
) : InfoPointUMV2
|
) : InfoPointUMV2
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class CirculatingSupply(
|
data class CirculatingSupply(
|
||||||
val currentValue: TextReference,
|
val currentValue: TextReference?,
|
||||||
val maxValue: TextReference?,
|
val maxValue: TextReference?,
|
||||||
val fillValue: Float?,
|
val fillValue: Float?,
|
||||||
val onInfoClick: () -> Unit,
|
val onInfoClick: () -> Unit,
|
||||||
|
|
@ -60,9 +61,18 @@ internal data class MetricsV2UM(
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum class TrendingVolumeLiquidityType {
|
internal enum class TrendingVolumeLiquidityType {
|
||||||
HIGH, MEDIUM, LOW,
|
HIGH, MEDIUM, LOW, UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum class MarketRatingType {
|
internal enum class MarketRatingType {
|
||||||
GOLD, SILVER, BRONZE, OTHER
|
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