Updated on 2026-08-14
This commit is contained in:
parent
b712e42f44
commit
9315578317
7 changed files with 130 additions and 36 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.common.ui.tokens
|
||||
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
|
|
@ -17,6 +18,7 @@ import com.tangem.utils.StringsSigns.DASH_SIGN
|
|||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -219,7 +221,14 @@ class TokenItemStateConverter(
|
|||
-> {
|
||||
TokenItemState.FiatAmountState.Content(
|
||||
text = status.getFormattedFiatAmount(appCurrency = appCurrency, includeStaking = true),
|
||||
hasStaked = !status.getStakedBalance().isZero(),
|
||||
icons = buildList {
|
||||
if (!status.getStakedBalance().isZero()) {
|
||||
TokenItemState.FiatAmountState.Content.IconUM(
|
||||
iconRes = R.drawable.ic_staking_24,
|
||||
useAccentColor = true,
|
||||
).let(::add)
|
||||
}
|
||||
}.toImmutableList(),
|
||||
)
|
||||
}
|
||||
is CryptoCurrencyStatus.Unreachable,
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@ import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
|||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.components.token.internal.*
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import java.util.UUID
|
||||
import kotlin.math.max
|
||||
|
|
@ -462,11 +464,18 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
text = stringReference(value = "PolygonPolygonPolygonPolygonPolygonPolygon"),
|
||||
hasPending = true,
|
||||
),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "3213123123321312312312312312 $",
|
||||
hasStaked = true,
|
||||
icons = persistentListOf(
|
||||
FiatAmountState.Content.IconUM(R.drawable.ic_error_sync_24, useAccentColor = false),
|
||||
stakingIcon,
|
||||
),
|
||||
isFlickering = true,
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(
|
||||
text = "5,4123123213123123123123123123 MATIC",
|
||||
isFlickering = true,
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,4123123213123123123123123123 MATIC"),
|
||||
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
|
||||
price = "312 USD",
|
||||
priceChangePercent = "42.0%",
|
||||
|
|
@ -511,7 +520,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
id = UUID.randomUUID().toString(),
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = false),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "321 $",
|
||||
icons = persistentListOf(stakingIcon),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,412 MATIC"),
|
||||
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
|
||||
price = "312 USD",
|
||||
|
|
@ -525,7 +537,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
id = UUID.randomUUID().toString(),
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = false),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "321 $",
|
||||
icons = persistentListOf(stakingIcon),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.LabelContent(
|
||||
auditLabelUM = AuditLabelUM(
|
||||
text = TextReference.Str(value = "Trusted"),
|
||||
|
|
@ -565,6 +580,8 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
|
||||
companion object {
|
||||
|
||||
val stakingIcon = FiatAmountState.Content.IconUM(R.drawable.ic_staking_24, useAccentColor = true)
|
||||
|
||||
val coinIconState
|
||||
get() = CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
|
|
@ -599,7 +616,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
text = stringReference(value = "Polygon"),
|
||||
hasPending = true,
|
||||
),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = true),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "321 $",
|
||||
icons = persistentListOf(stakingIcon),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,412 MATIC"),
|
||||
subtitleState = TokenItemState.SubtitleState.Unknown,
|
||||
onItemClick = {},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.audits.AuditLabel
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -25,15 +26,19 @@ internal fun TokenCryptoAmount(
|
|||
when (state) {
|
||||
is TokenCryptoAmountState.TextContent -> {
|
||||
CryptoAmountText(
|
||||
amount = state.text.orMaskWithStars(isBalanceHidden),
|
||||
modifier = modifier,
|
||||
amount = state.text.orMaskWithStars(isBalanceHidden),
|
||||
isFlickering = state.isFlickering,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Subtitle2State.LabelContent -> {
|
||||
AuditLabel(state = state.auditLabelUM, modifier = modifier)
|
||||
}
|
||||
is TokenCryptoAmountState.Unreachable -> {
|
||||
CryptoAmountText(amount = stringResourceSafe(id = R.string.common_unreachable), modifier = modifier)
|
||||
CryptoAmountText(
|
||||
amount = stringResourceSafe(id = R.string.common_unreachable),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is TokenCryptoAmountState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
|
|
@ -46,10 +51,10 @@ internal fun TokenCryptoAmount(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun CryptoAmountText(amount: String, modifier: Modifier = Modifier) {
|
||||
private fun CryptoAmountText(amount: String, modifier: Modifier = Modifier, isFlickering: Boolean = false) {
|
||||
Text(
|
||||
modifier = modifier.flicker(isFlickering),
|
||||
text = amount,
|
||||
modifier = modifier,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.core.ui.components.token.internal
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -14,9 +15,10 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.tangem.core.ui.R
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState as TokenFiatAmountState
|
||||
|
|
@ -26,12 +28,13 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool
|
|||
when (state) {
|
||||
is TokenFiatAmountState.Content -> {
|
||||
ContentFiatAmount(
|
||||
text = state.text.orMaskWithStars(isBalanceHidden),
|
||||
hasStaked = state.hasStaked,
|
||||
modifier = modifier,
|
||||
text = state.text.orMaskWithStars(isBalanceHidden),
|
||||
icons = state.icons,
|
||||
isAmountFlickering = state.isFlickering,
|
||||
)
|
||||
}
|
||||
is TokenItemState.FiatAmountState.TextContent -> {
|
||||
is TokenFiatAmountState.TextContent -> {
|
||||
FiatAmountText(
|
||||
text = state.text.orMaskWithStars(isBalanceHidden),
|
||||
modifier = modifier,
|
||||
|
|
@ -39,7 +42,7 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool
|
|||
)
|
||||
}
|
||||
is TokenFiatAmountState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = 4.dp)
|
||||
}
|
||||
is TokenFiatAmountState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
|
|
@ -49,33 +52,53 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentFiatAmount(text: String, hasStaked: Boolean, modifier: Modifier = Modifier) {
|
||||
private fun ContentFiatAmount(
|
||||
text: String,
|
||||
icons: List<TokenFiatAmountState.Content.IconUM>,
|
||||
isAmountFlickering: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = hasStaked,
|
||||
visible = icons.isNotEmpty(),
|
||||
) {
|
||||
Icon(
|
||||
painter = rememberVectorPainter(image = ImageVector.vectorResource(R.drawable.ic_staking_24)),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing4)
|
||||
.size(TangemTheme.dimens.size12),
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
icons.fastForEach { icon ->
|
||||
Icon(
|
||||
modifier = Modifier.size(12.dp),
|
||||
painter = rememberVectorPainter(image = ImageVector.vectorResource(icon.iconRes)),
|
||||
tint = if (icon.useAccentColor) {
|
||||
TangemTheme.colors.icon.accent
|
||||
} else {
|
||||
TangemTheme.colors.icon.inactive
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FiatAmountText(text = text)
|
||||
FiatAmountText(text = text, isFlickering = isAmountFlickering)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FiatAmountText(text: String, modifier: Modifier = Modifier, isAvailable: Boolean = true) {
|
||||
private fun FiatAmountText(
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
isAvailable: Boolean = true,
|
||||
isFlickering: Boolean = false,
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier.flicker(isFlickering),
|
||||
text = text,
|
||||
modifier = modifier,
|
||||
color = if (isAvailable) TangemTheme.colors.text.primary1 else TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -85,6 +108,6 @@ private fun FiatAmountText(text: String, modifier: Modifier = Modifier, isAvaila
|
|||
|
||||
private fun Modifier.placeholderSize(): Modifier = composed {
|
||||
return@composed this
|
||||
.padding(vertical = TangemTheme.dimens.spacing4)
|
||||
.size(width = TangemTheme.dimens.size40, height = TangemTheme.dimens.size12)
|
||||
.padding(vertical = 4.dp)
|
||||
.size(width = 40.dp, height = 12.dp)
|
||||
}
|
||||
|
|
@ -5,6 +5,8 @@ import com.tangem.core.ui.components.audits.AuditLabelUM
|
|||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/** TokenItem component state */
|
||||
@Immutable
|
||||
|
|
@ -192,10 +194,18 @@ sealed class TokenItemState {
|
|||
|
||||
@Immutable
|
||||
sealed class FiatAmountState {
|
||||
|
||||
data class Content(
|
||||
val text: String,
|
||||
val hasStaked: Boolean = false,
|
||||
) : FiatAmountState()
|
||||
val isFlickering: Boolean = false,
|
||||
val icons: ImmutableList<IconUM> = persistentListOf(),
|
||||
) : FiatAmountState() {
|
||||
|
||||
data class IconUM(
|
||||
val iconRes: Int,
|
||||
val useAccentColor: Boolean,
|
||||
)
|
||||
}
|
||||
|
||||
data class TextContent(val text: String, val isAvailable: Boolean = true) : FiatAmountState()
|
||||
|
||||
|
|
@ -207,7 +217,10 @@ sealed class TokenItemState {
|
|||
@Immutable
|
||||
sealed class Subtitle2State {
|
||||
|
||||
data class TextContent(val text: String) : Subtitle2State()
|
||||
data class TextContent(
|
||||
val text: String,
|
||||
val isFlickering: Boolean = false,
|
||||
) : Subtitle2State()
|
||||
|
||||
data class LabelContent(val auditLabelUM: AuditLabelUM) : Subtitle2State()
|
||||
|
||||
|
|
|
|||
15
core/ui/src/main/res/drawable/ic_error_sync_24.xml
Normal file
15
core/ui/src/main/res/drawable/ic_error_sync_24.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M12,4C15.64,4,18.67,6.59,19.35,10.04C21.95,10.22,24,12.36,24,15C24,15.66,23.87,16.31,23.62,16.91C23.37,17.52,23,18.07,22.54,18.54C22.07,19,21.52,19.37,20.91,19.62C20.31,19.87,19.66,20,19,20H15.5V18H19C19.8,18,20.56,17.68,21.12,17.12C21.68,16.56,22,15.8,22,15C22,13.45,20.78,12.14,19.22,12.04L17.69,11.93L17.39,10.43C16.88,7.86,14.62,6,12,6C9.94,6,8.08,7.14,7.13,8.97L6.63,9.92L5.56,10.03C3.53,10.24,2,11.95,2,14C2,15.06,2.42,16.08,3.17,16.83C3.92,17.58,4.94,18,6,18H8.5V20H6C4.41,20,2.88,19.37,1.76,18.24C0.63,17.12,0,15.59,0,14C0,10.91,2.34,8.36,5.35,8.04C6.6,5.64,9.11,4,12,4Z" />
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M11,19V14H13V19Z" />
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M13,21V23H11V21Z" />
|
||||
</vector>
|
||||
|
|
@ -16,9 +16,11 @@ import com.tangem.core.ui.haptic.TangemHapticEffect
|
|||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.features.markets.portfolio.impl.ui.preview.PreviewMyPortfolioUMProvider
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState as TokenFiatAmountState
|
||||
|
||||
@Composable
|
||||
|
|
@ -96,7 +98,14 @@ private class PortfolioTokenUMProvider : CollectionPreviewParameterProvider<Port
|
|||
collection = listOf(
|
||||
tokenUM.copy(
|
||||
tokenItemState = (tokenUM.tokenItemState as TokenItemState.Content).copy(
|
||||
fiatAmountState = contentFiatAmount.copy(hasStaked = true),
|
||||
fiatAmountState = contentFiatAmount.copy(
|
||||
icons = persistentListOf(
|
||||
TokenItemState.FiatAmountState.Content.IconUM(
|
||||
iconRes = R.drawable.ic_staking_24,
|
||||
useAccentColor = true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenUM.copy(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue