Updated on 2026-08-14
This commit is contained in:
parent
c1302681a4
commit
e1f80e7e41
15 changed files with 356 additions and 297 deletions
|
|
@ -87,6 +87,7 @@ data class TangemDimens internal constructor(
|
|||
val spacing0: Dp = 0.dp,
|
||||
val spacing0_5: Dp = 0.5.dp,
|
||||
val spacing2: Dp = 2.dp,
|
||||
val spacing3: Dp = 3.dp,
|
||||
val spacing4: Dp = 4.dp,
|
||||
val spacing6: Dp = 6.dp,
|
||||
val spacing8: Dp = 8.dp,
|
||||
|
|
|
|||
|
|
@ -40,10 +40,16 @@ object BigDecimalFormatter {
|
|||
.replace(formatterCurrency.getSymbol(locale), fiatCurrencySymbol)
|
||||
}
|
||||
|
||||
fun formatPercent(percent: BigDecimal, useAbsoluteValue: Boolean, locale: Locale = Locale.getDefault()): String {
|
||||
fun formatPercent(
|
||||
percent: BigDecimal,
|
||||
useAbsoluteValue: Boolean,
|
||||
locale: Locale = Locale.getDefault(),
|
||||
maxFractionDigits: Int = 2,
|
||||
minFractionDigits: Int = 2,
|
||||
): String {
|
||||
val formatter = NumberFormat.getPercentInstance(locale).apply {
|
||||
maximumFractionDigits = 2
|
||||
minimumFractionDigits = 2
|
||||
maximumFractionDigits = maxFractionDigits
|
||||
minimumFractionDigits = minFractionDigits
|
||||
roundingMode = RoundingMode.HALF_UP
|
||||
}
|
||||
val value = if (useAbsoluteValue) percent.abs() else percent
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import com.tangem.core.ui.extensions.stringReference
|
|||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
|
|
@ -124,15 +123,12 @@ internal object WalletPreviewData {
|
|||
val tokenItemVisibleState by lazy {
|
||||
TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
icon = coinIconState,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState(
|
||||
fiatAmount = "321 $",
|
||||
priceChangeState = PriceChangeState.Unknown,
|
||||
isBalanceHidden = false,
|
||||
),
|
||||
iconState = coinIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon", hasPending = true),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "5,412 MATIC"),
|
||||
priceChangeState = TokenItemState.PriceChangeState.Unknown,
|
||||
isBalanceHidden = false,
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
|
|
@ -140,26 +136,23 @@ internal object WalletPreviewData {
|
|||
|
||||
val testnetTokenItemVisibleState by lazy {
|
||||
tokenItemVisibleState.copy(
|
||||
name = "Polygon testnet",
|
||||
icon = tokenIconState.copy(isGrayscale = true),
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon testnet"),
|
||||
iconState = tokenIconState.copy(isGrayscale = true),
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemHiddenState by lazy {
|
||||
TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = false,
|
||||
tokenOptions = TokenOptionsState(
|
||||
priceChangeState = PriceChangeState.Content(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
fiatAmount = "321 $",
|
||||
isBalanceHidden = false,
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "5,412 MATIC"),
|
||||
priceChangeState = TokenItemState.PriceChangeState.Content(
|
||||
valueInPercent = "2.0%",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
|
|
@ -168,17 +161,17 @@ internal object WalletPreviewData {
|
|||
val tokenItemDragState by lazy {
|
||||
TokenItemState.Draggable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
info = stringReference(value = "3 172,14 $"),
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = "3 172,14 $"),
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemUnreachableState by lazy {
|
||||
TokenItemState.Unreachable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
|
|
@ -187,16 +180,16 @@ internal object WalletPreviewData {
|
|||
val tokenItemNoAddressState by lazy {
|
||||
TokenItemState.NoAddress(
|
||||
id = UUID.randomUUID().toString(),
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
|
||||
onItemLongClick = {},
|
||||
)
|
||||
}
|
||||
|
||||
val customTokenItemVisibleState by lazy {
|
||||
tokenItemVisibleState.copy(
|
||||
name = "Polygon custom",
|
||||
icon = customTokenIconState.copy(
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
|
||||
iconState = customTokenIconState.copy(
|
||||
tint = TangemColorPalette.White,
|
||||
background = TangemColorPalette.Black,
|
||||
),
|
||||
|
|
@ -205,8 +198,8 @@ internal object WalletPreviewData {
|
|||
|
||||
val customTestnetTokenItemVisibleState by lazy {
|
||||
tokenItemVisibleState.copy(
|
||||
name = "Polygon custom testnet",
|
||||
icon = customTokenIconState.copy(isGrayscale = true),
|
||||
titleState = TokenItemState.TitleState.Content(text = "Polygon"),
|
||||
iconState = customTokenIconState.copy(isGrayscale = true),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +231,9 @@ internal object WalletPreviewData {
|
|||
DraggableItem.Token(
|
||||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
name = "Token $tokenNumber from $networkNumber network",
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = "Token $tokenNumber from $networkNumber network",
|
||||
),
|
||||
),
|
||||
groupId = group.id,
|
||||
roundingMode = when {
|
||||
|
|
@ -348,37 +343,37 @@ internal object WalletPreviewData {
|
|||
TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_1",
|
||||
name = "Ethereum",
|
||||
amount = "1,89340821 ETH",
|
||||
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content("1,89340821 ETH"),
|
||||
),
|
||||
),
|
||||
TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_2",
|
||||
name = "Ethereum",
|
||||
amount = "1,89340821 ETH",
|
||||
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content("1,89340821 ETH"),
|
||||
),
|
||||
),
|
||||
TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_3",
|
||||
name = "Ethereum",
|
||||
amount = "1,89340821 ETH",
|
||||
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content("1,89340821 ETH"),
|
||||
),
|
||||
),
|
||||
TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_4",
|
||||
name = "Ethereum",
|
||||
amount = "1,89340821 ETH",
|
||||
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content("1,89340821 ETH"),
|
||||
),
|
||||
),
|
||||
TokensListItemState.NetworkGroupTitle(id = 1, stringReference("Ethereum")),
|
||||
TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_5",
|
||||
name = "Ethereum",
|
||||
amount = "1,89340821 ETH",
|
||||
titleState = TokenItemState.TitleState.Content(text = "Ethereum"),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content("1,89340821 ETH"),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.constraintlayout.compose.*
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -38,8 +37,10 @@ internal fun TokenItem(
|
|||
) {
|
||||
val (iconRef, titleRef, cryptoAmountRef, fiatAmountRef, priceChangeRef, nonFiatContentRef) = createRefs()
|
||||
|
||||
val isBalanceHidden = (state as? TokenItemState.Content)?.isBalanceHidden ?: false
|
||||
|
||||
TokenIcon(
|
||||
state = state,
|
||||
state = state.iconState,
|
||||
modifier = Modifier.constrainAs(iconRef) {
|
||||
centerVerticallyTo(parent)
|
||||
start.linkTo(parent.start)
|
||||
|
|
@ -52,7 +53,7 @@ internal fun TokenItem(
|
|||
}
|
||||
|
||||
TokenTitle(
|
||||
state = state,
|
||||
state = state.titleState,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing8)
|
||||
.constrainAs(titleRef) {
|
||||
|
|
@ -76,7 +77,8 @@ internal fun TokenItem(
|
|||
)
|
||||
|
||||
TokenFiatAmount(
|
||||
state = state,
|
||||
state = state.fiatAmountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier.constrainAs(fiatAmountRef) {
|
||||
top.linkTo(parent.top)
|
||||
end.linkTo(parent.end)
|
||||
|
|
@ -91,7 +93,8 @@ internal fun TokenItem(
|
|||
|
||||
val marginBetweenRows = TangemTheme.dimens.spacing2
|
||||
TokenCryptoAmount(
|
||||
state = state,
|
||||
state = state.cryptoAmountState,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing8)
|
||||
.constrainAs(cryptoAmountRef) {
|
||||
|
|
@ -117,16 +120,21 @@ internal fun TokenItem(
|
|||
derivedStateOf { with(density) { rootWidth.toDp().times(other = 0.16f) } }
|
||||
}
|
||||
TokenPriceChange(
|
||||
state = state,
|
||||
state = state.priceChangeState,
|
||||
modifier = Modifier.constrainAs(priceChangeRef) {
|
||||
top.linkTo(fiatAmountRef.bottom, marginBetweenRows)
|
||||
end.linkTo(anchor = parent.end)
|
||||
bottom.linkTo(parent.bottom)
|
||||
|
||||
if (state is TokenItemState.ContentState) {
|
||||
start.linkTo(cryptoAmountRef.end)
|
||||
width = Dimension.fillToConstraints
|
||||
.atLeast(priceChangeRequiredMinWidth)
|
||||
when (state.priceChangeState) {
|
||||
is TokenItemState.PriceChangeState.Content,
|
||||
is TokenItemState.PriceChangeState.Unknown,
|
||||
-> {
|
||||
start.linkTo(cryptoAmountRef.end)
|
||||
width = Dimension.fillToConstraints
|
||||
.atLeast(priceChangeRequiredMinWidth)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -202,22 +210,24 @@ private fun Preview_Tokens_DarkTheme(@PreviewParameter(TokenConfigProvider::clas
|
|||
|
||||
private class TokenConfigProvider : CollectionPreviewParameterProvider<TokenItemState>(
|
||||
collection = listOf(
|
||||
WalletPreviewData.tokenItemVisibleState.copy(amount = "5,41221467146712416241274127841274174213421 MATIC"),
|
||||
WalletPreviewData.tokenItemVisibleState.copy(
|
||||
tokenOptions = WalletPreviewData.tokenItemVisibleState.tokenOptions.copy(
|
||||
priceChangeState = PriceChangeState.Content(
|
||||
valueInPercent = "31231231231231231231223123123123212312312312.00%",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content(
|
||||
text = "5,41221467146712416241274127841274174213421 MATIC",
|
||||
),
|
||||
),
|
||||
WalletPreviewData.tokenItemVisibleState.copy(
|
||||
amount = "5,41221467146712416241274127841274174213421 MATIC",
|
||||
tokenOptions = WalletPreviewData.tokenItemVisibleState.tokenOptions.copy(
|
||||
priceChangeState = PriceChangeState.Content(
|
||||
valueInPercent = "31231231231231231231223123123123212312312312.00%",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
priceChangeState = TokenItemState.PriceChangeState.Content(
|
||||
valueInPercent = "31231231231231231231223123123123212312312312.0%",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
),
|
||||
WalletPreviewData.tokenItemVisibleState.copy(
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content(
|
||||
text = "5,41221467146712416241274127841274174213421 MATIC",
|
||||
),
|
||||
priceChangeState = TokenItemState.PriceChangeState.Content(
|
||||
valueInPercent = "31231231231231231231223123123123212312312312.0%",
|
||||
type = PriceChangeType.UP,
|
||||
),
|
||||
),
|
||||
WalletPreviewData.tokenItemVisibleState,
|
||||
|
|
|
|||
|
|
@ -1,51 +1,51 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.tangem.common.Strings
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.CryptoAmountState as TokenCryptoAmountState
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
internal fun TokenCryptoAmount(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(targetState = state, label = "Update crypto amount", modifier = modifier) { animatedState ->
|
||||
when (animatedState) {
|
||||
is TokenItemState.Content -> {
|
||||
CryptoAmountText(
|
||||
amount = if (animatedState.tokenOptions.isBalanceHidden) Strings.STARS else animatedState.amount,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Draggable -> {
|
||||
CryptoAmountText(amount = animatedState.info.resolveReference())
|
||||
}
|
||||
is TokenItemState.Loading -> {
|
||||
RectangleShimmer(modifier = Modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenItemState.Locked -> {
|
||||
LockedRectangle(modifier = Modifier.placeholderSize())
|
||||
}
|
||||
is TokenItemState.Unreachable,
|
||||
is TokenItemState.NoAddress,
|
||||
-> Unit
|
||||
internal fun TokenCryptoAmount(
|
||||
state: TokenCryptoAmountState?,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (state) {
|
||||
is TokenCryptoAmountState.Content -> {
|
||||
CryptoAmountText(
|
||||
amount = if (isBalanceHidden) Strings.STARS else state.text,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is TokenCryptoAmountState.Unreachable -> {
|
||||
CryptoAmountText(amount = stringResource(id = R.string.common_unreachable), modifier = modifier)
|
||||
}
|
||||
is TokenCryptoAmountState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenCryptoAmountState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CryptoAmountText(amount: String) {
|
||||
private fun CryptoAmountText(amount: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = amount,
|
||||
modifier = modifier,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -55,6 +55,6 @@ private fun CryptoAmountText(amount: String) {
|
|||
|
||||
private fun Modifier.placeholderSize(): Modifier = composed {
|
||||
return@composed this
|
||||
.padding(vertical = TangemTheme.dimens.spacing4)
|
||||
.padding(vertical = TangemTheme.dimens.spacing3)
|
||||
.size(width = TangemTheme.dimens.size52, height = TangemTheme.dimens.size12)
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Text
|
||||
|
|
@ -13,40 +11,39 @@ import com.tangem.common.Strings
|
|||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.FiatAmountState as TokenFiatAmountState
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
internal fun TokenFiatAmount(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(targetState = state, label = "Update fiat amount", modifier = modifier) { animatedState ->
|
||||
when (animatedState) {
|
||||
is TokenItemState.Content -> {
|
||||
Text(
|
||||
text = if (animatedState.tokenOptions.isBalanceHidden) {
|
||||
Strings.STARS
|
||||
} else {
|
||||
animatedState.tokenOptions.fiatAmount
|
||||
},
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = TangemTypography.body2,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Loading -> {
|
||||
RectangleShimmer(modifier = Modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenItemState.Locked -> {
|
||||
LockedRectangle(modifier = Modifier.placeholderSize())
|
||||
}
|
||||
is TokenItemState.Unreachable,
|
||||
is TokenItemState.Draggable,
|
||||
is TokenItemState.NoAddress,
|
||||
-> Unit
|
||||
internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is TokenFiatAmountState.Content -> {
|
||||
FiatAmountText(
|
||||
text = if (isBalanceHidden) Strings.STARS else state.text,
|
||||
modifier,
|
||||
)
|
||||
}
|
||||
is TokenFiatAmountState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenFiatAmountState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FiatAmountText(text: String, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = text,
|
||||
modifier,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = TangemTypography.body2,
|
||||
)
|
||||
}
|
||||
|
||||
private fun Modifier.placeholderSize(): Modifier = composed {
|
||||
return@composed this
|
||||
.padding(vertical = TangemTheme.dimens.spacing4)
|
||||
|
|
|
|||
|
|
@ -13,55 +13,49 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerW4
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.PriceChangeState as TokenPriceChangeState
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
internal fun TokenPriceChange(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(targetState = state, label = "Update the price change", modifier = modifier) { animatedState ->
|
||||
when (animatedState) {
|
||||
is TokenItemState.Content -> {
|
||||
PriceChangeBlock(state = animatedState.tokenOptions.priceChangeState)
|
||||
}
|
||||
is TokenItemState.Loading -> {
|
||||
RectangleShimmer(modifier = Modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenItemState.Locked -> {
|
||||
LockedRectangle(modifier = Modifier.placeholderSize())
|
||||
}
|
||||
is TokenItemState.Unreachable,
|
||||
is TokenItemState.Draggable,
|
||||
is TokenItemState.NoAddress,
|
||||
-> Unit
|
||||
internal fun TokenPriceChange(state: TokenPriceChangeState?, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is TokenPriceChangeState.Content -> {
|
||||
PriceChangeBlock(modifier = modifier, type = state.type, text = state.valueInPercent)
|
||||
}
|
||||
is TokenPriceChangeState.Unknown -> {
|
||||
PriceChangeBlock(modifier = modifier)
|
||||
}
|
||||
is TokenPriceChangeState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenPriceChangeState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PriceChangeBlock(state: PriceChangeState) {
|
||||
Row(horizontalArrangement = Arrangement.End) {
|
||||
PriceChangeIcon(
|
||||
type = (state as? PriceChangeState.Content)?.type,
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
)
|
||||
private fun PriceChangeBlock(modifier: Modifier = Modifier, type: PriceChangeType? = null, text: String? = null) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
PriceChangeIcon(type = type)
|
||||
SpacerW4()
|
||||
PriceChangeText(state = state, modifier = Modifier.align(Alignment.CenterVertically))
|
||||
PriceChangeText(type = type, text = text)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
private fun PriceChangeIcon(type: PriceChangeType?, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(
|
||||
targetState = type,
|
||||
label = "Update the price change's arrow",
|
||||
modifier = modifier,
|
||||
) { animatedType ->
|
||||
private fun PriceChangeIcon(type: PriceChangeType?) {
|
||||
AnimatedContent(targetState = type, label = "Update the price change's arrow") { animatedType ->
|
||||
animatedType ?: return@AnimatedContent
|
||||
|
||||
Icon(
|
||||
|
|
@ -82,25 +76,14 @@ private fun PriceChangeIcon(type: PriceChangeType?, modifier: Modifier = Modifie
|
|||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
private fun PriceChangeText(state: PriceChangeState, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(
|
||||
targetState = state,
|
||||
label = "Update the price change's text",
|
||||
modifier = modifier,
|
||||
) { animatedState ->
|
||||
private fun PriceChangeText(type: PriceChangeType?, text: String?) {
|
||||
AnimatedContent(targetState = text, label = "Update the price change's text") { animatedText ->
|
||||
Text(
|
||||
text = when (animatedState) {
|
||||
is PriceChangeState.Content -> animatedState.valueInPercent
|
||||
is PriceChangeState.Unknown -> TokenItemState.UNKNOWN_AMOUNT_SIGN
|
||||
},
|
||||
color = when (animatedState) {
|
||||
is PriceChangeState.Content -> {
|
||||
when (animatedState.type) {
|
||||
PriceChangeType.UP -> TangemTheme.colors.text.accent
|
||||
PriceChangeType.DOWN -> TangemTheme.colors.text.warning
|
||||
}
|
||||
}
|
||||
PriceChangeState.Unknown -> TangemTheme.colors.text.primary1
|
||||
text = animatedText ?: TokenItemState.UNKNOWN_AMOUNT_SIGN,
|
||||
color = when (type) {
|
||||
PriceChangeType.UP -> TangemTheme.colors.text.accent
|
||||
PriceChangeType.DOWN -> TangemTheme.colors.text.warning
|
||||
null -> TangemTheme.colors.text.primary1
|
||||
},
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
|
|
@ -111,6 +94,6 @@ private fun PriceChangeText(state: PriceChangeState, modifier: Modifier = Modifi
|
|||
|
||||
private fun Modifier.placeholderSize(): Modifier = composed {
|
||||
return@composed this
|
||||
.padding(vertical = TangemTheme.dimens.spacing4)
|
||||
.padding(vertical = TangemTheme.dimens.spacing3)
|
||||
.size(width = TangemTheme.dimens.size40, height = TangemTheme.dimens.size12)
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
|
|
@ -16,32 +17,34 @@ import com.tangem.core.ui.components.RectangleShimmer
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TitleState as TokenTitleState
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
internal fun TokenTitle(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
AnimatedContent(targetState = state, label = "Update title", modifier = modifier) { animatedState ->
|
||||
when (animatedState) {
|
||||
is TokenItemState.ContentState -> {
|
||||
ContentTitle(
|
||||
name = animatedState.name,
|
||||
hasPending = (animatedState as? TokenItemState.Content)?.hasPending == true,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Loading -> {
|
||||
RectangleShimmer(modifier = Modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenItemState.Locked -> {
|
||||
LockedRectangle(modifier = Modifier.placeholderSize())
|
||||
}
|
||||
internal fun TokenTitle(state: TokenTitleState?, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is TokenTitleState.Content -> {
|
||||
ContentTitle(name = state.text, hasPending = state.hasPending, modifier = modifier)
|
||||
}
|
||||
is TokenTitleState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
}
|
||||
is TokenTitleState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
}
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentTitle(name: String, hasPending: Boolean) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6)) {
|
||||
private fun ContentTitle(name: String, hasPending: Boolean, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing6),
|
||||
) {
|
||||
/*
|
||||
* If currency name has a long width, then it will completely displace the image.
|
||||
* So we need to use [weight] to avoid displacement.
|
||||
*/
|
||||
CurrencyNameText(name = name, modifier = Modifier.weight(weight = 1f, fill = false))
|
||||
|
||||
PendingTransactionImage(
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ internal fun ContentIcon(
|
|||
background = icon.background,
|
||||
alpha = alpha,
|
||||
)
|
||||
TokenItemState.IconState.Loading,
|
||||
TokenItemState.IconState.Locked,
|
||||
-> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,26 +14,28 @@ import androidx.compose.ui.graphics.ColorFilter
|
|||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.IconState as TokenIconState
|
||||
|
||||
private const val GRAY_SCALE_SATURATION = 0f
|
||||
private const val GRAY_SCALE_ALPHA = 0.4f
|
||||
private const val NORMAL_ALPHA = 1f
|
||||
|
||||
@Composable
|
||||
internal fun TokenIcon(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
internal fun TokenIcon(state: TokenIconState, modifier: Modifier = Modifier) {
|
||||
BaseContainer(modifier = modifier) {
|
||||
val iconModifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.size(TangemTheme.dimens.size36)
|
||||
|
||||
when (state) {
|
||||
is TokenItemState.Loading -> LoadingIcon(modifier = iconModifier)
|
||||
is TokenItemState.Locked -> LockedIcon(modifier = iconModifier)
|
||||
is TokenItemState.ContentState -> ContentIconContainer(
|
||||
modifier = iconModifier,
|
||||
icon = state.icon,
|
||||
)
|
||||
is TokenIconState.Loading -> LoadingIcon(modifier = iconModifier)
|
||||
is TokenIconState.Locked -> LockedIcon(modifier = iconModifier)
|
||||
is TokenIconState.CoinIcon,
|
||||
is TokenIconState.CustomTokenIcon,
|
||||
is TokenIconState.TokenIcon,
|
||||
-> {
|
||||
ContentIconContainer(modifier = iconModifier, icon = state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,7 +60,7 @@ private fun LockedIcon(modifier: Modifier = Modifier) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.ContentIconContainer(icon: TokenItemState.IconState, modifier: Modifier = Modifier) {
|
||||
private fun BoxScope.ContentIconContainer(icon: TokenIconState, modifier: Modifier = Modifier) {
|
||||
val networkBadgeOffset = TangemTheme.dimens.spacing4
|
||||
val (alpha, colorFilter) = remember(icon.isGrayscale) {
|
||||
if (icon.isGrayscale) {
|
||||
|
|
|
|||
|
|
@ -3,99 +3,119 @@ package com.tangem.feature.wallet.presentation.common.state
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
|
||||
/** Token item state */
|
||||
@Immutable
|
||||
internal sealed interface TokenItemState {
|
||||
internal sealed class TokenItemState {
|
||||
|
||||
/** Unique id */
|
||||
val id: String
|
||||
abstract val id: String
|
||||
|
||||
abstract val iconState: IconState
|
||||
|
||||
abstract val titleState: TitleState
|
||||
|
||||
abstract val fiatAmountState: FiatAmountState?
|
||||
|
||||
abstract val cryptoAmountState: CryptoAmountState?
|
||||
|
||||
abstract val priceChangeState: PriceChangeState?
|
||||
|
||||
/** Loading token state */
|
||||
data class Loading(override val id: String) : TokenItemState
|
||||
data class Loading(override val id: String) : TokenItemState() {
|
||||
override val iconState: IconState = IconState.Loading
|
||||
override val titleState: TitleState = TitleState.Loading
|
||||
override val fiatAmountState: FiatAmountState = FiatAmountState.Loading
|
||||
override val cryptoAmountState: CryptoAmountState = CryptoAmountState.Loading
|
||||
override val priceChangeState: PriceChangeState = PriceChangeState.Loading
|
||||
}
|
||||
|
||||
/** Locked token state */
|
||||
data class Locked(override val id: String) : TokenItemState
|
||||
|
||||
/** Content state */
|
||||
@Immutable
|
||||
sealed class ContentState : TokenItemState {
|
||||
|
||||
abstract val icon: IconState
|
||||
abstract val name: String
|
||||
data class Locked(override val id: String) : TokenItemState() {
|
||||
override val iconState: IconState = IconState.Locked
|
||||
override val titleState: TitleState = TitleState.Locked
|
||||
override val fiatAmountState: FiatAmountState = FiatAmountState.Locked
|
||||
override val cryptoAmountState: CryptoAmountState = CryptoAmountState.Locked
|
||||
override val priceChangeState: PriceChangeState = PriceChangeState.Locked
|
||||
}
|
||||
|
||||
/**
|
||||
* Content token state
|
||||
*
|
||||
* @property id unique id
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property amount amount of token
|
||||
* @property hasPending pending tx in blockchain
|
||||
* @property tokenOptions state for token options
|
||||
* @property iconState token icon state
|
||||
* @property titleState token name
|
||||
* @property onItemClick callback which will be called when an item is clicked
|
||||
* @property onItemLongClick callback which will be called when an item is long clicked
|
||||
*/
|
||||
data class Content(
|
||||
override val id: String,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
val amount: String,
|
||||
val hasPending: Boolean,
|
||||
val tokenOptions: TokenOptionsState,
|
||||
override val iconState: IconState,
|
||||
override val titleState: TitleState,
|
||||
override val fiatAmountState: FiatAmountState?,
|
||||
override val cryptoAmountState: CryptoAmountState.Content,
|
||||
override val priceChangeState: PriceChangeState?,
|
||||
val isBalanceHidden: Boolean,
|
||||
val onItemClick: () -> Unit,
|
||||
val onItemLongClick: () -> Unit,
|
||||
) : ContentState()
|
||||
) : TokenItemState()
|
||||
|
||||
/**
|
||||
* Draggable token state
|
||||
*
|
||||
* @property id unique id
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property info token info (e.g. fiat balance or status)
|
||||
* @property iconState token icon state
|
||||
* @property titleState token name
|
||||
*/
|
||||
data class Draggable(
|
||||
override val id: String,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
val info: TextReference,
|
||||
) : ContentState()
|
||||
override val iconState: IconState,
|
||||
override val titleState: TitleState,
|
||||
override val cryptoAmountState: CryptoAmountState,
|
||||
) : TokenItemState() {
|
||||
override val fiatAmountState: FiatAmountState? = null
|
||||
override val priceChangeState: PriceChangeState? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Unreachable token state
|
||||
*
|
||||
* @property id token id
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property iconState token icon state
|
||||
* @property titleState token name
|
||||
* @property onItemClick callback which will be called when an item is clicked
|
||||
* @property onItemLongClick callback which will be called when an item is long clicked
|
||||
*/
|
||||
data class Unreachable(
|
||||
override val id: String,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
override val iconState: IconState,
|
||||
override val titleState: TitleState,
|
||||
val onItemClick: () -> Unit,
|
||||
val onItemLongClick: () -> Unit,
|
||||
) : ContentState()
|
||||
) : TokenItemState() {
|
||||
override val fiatAmountState: FiatAmountState? = null
|
||||
override val cryptoAmountState: CryptoAmountState? = null
|
||||
override val priceChangeState: PriceChangeState? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* No derivation address state
|
||||
*
|
||||
* @property id token id
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property iconState token icon state
|
||||
* @property titleState token name
|
||||
* @property onItemLongClick callback which will be called when an item is long clicked
|
||||
*/
|
||||
data class NoAddress(
|
||||
override val id: String,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
override val iconState: IconState,
|
||||
override val titleState: TitleState,
|
||||
val onItemLongClick: () -> Unit,
|
||||
) : ContentState()
|
||||
) : TokenItemState() {
|
||||
override val fiatAmountState: FiatAmountState? = null
|
||||
override val cryptoAmountState: CryptoAmountState? = null
|
||||
override val priceChangeState: PriceChangeState? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the various states an icon can be in.
|
||||
|
|
@ -161,15 +181,60 @@ internal sealed interface TokenItemState {
|
|||
|
||||
override val isCustom: Boolean = false
|
||||
}
|
||||
|
||||
object Loading : IconState() {
|
||||
override val isGrayscale: Boolean = false
|
||||
override val isCustom: Boolean = false
|
||||
override val networkBadgeIconResId: Int? = null
|
||||
}
|
||||
|
||||
object Locked : IconState() {
|
||||
override val isGrayscale: Boolean = false
|
||||
override val isCustom: Boolean = false
|
||||
override val networkBadgeIconResId: Int? = null
|
||||
}
|
||||
}
|
||||
|
||||
/** Token options state */
|
||||
@Immutable
|
||||
data class TokenOptionsState(
|
||||
val priceChangeState: PriceChangeState,
|
||||
val fiatAmount: String,
|
||||
val isBalanceHidden: Boolean,
|
||||
)
|
||||
sealed class TitleState {
|
||||
|
||||
data class Content(val text: String, val hasPending: Boolean = false) : TitleState()
|
||||
|
||||
object Loading : TitleState()
|
||||
|
||||
object Locked : TitleState()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
sealed class FiatAmountState {
|
||||
data class Content(val text: String) : FiatAmountState()
|
||||
|
||||
object Loading : FiatAmountState()
|
||||
|
||||
object Locked : FiatAmountState()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
sealed class CryptoAmountState {
|
||||
data class Content(val text: String) : CryptoAmountState()
|
||||
|
||||
object Unreachable : CryptoAmountState()
|
||||
|
||||
object Loading : CryptoAmountState()
|
||||
|
||||
object Locked : CryptoAmountState()
|
||||
}
|
||||
|
||||
sealed class PriceChangeState {
|
||||
|
||||
data class Content(val valueInPercent: String, val type: PriceChangeType) : PriceChangeState()
|
||||
|
||||
object Unknown : PriceChangeState()
|
||||
|
||||
object Loading : PriceChangeState()
|
||||
|
||||
object Locked : PriceChangeState()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val UNKNOWN_AMOUNT_SIGN = "—"
|
||||
|
|
|
|||
|
|
@ -1,21 +1,12 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter
|
||||
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
|
||||
internal class TokenItemHiddenStateConverter {
|
||||
|
||||
fun updateHiddenState(
|
||||
optionsState: TokenItemState.TokenOptionsState,
|
||||
isBalanceHidden: Boolean,
|
||||
): TokenItemState.TokenOptionsState {
|
||||
fun updateHiddenState(wasBalanceHidden: Boolean, isBalanceHidden: Boolean): Boolean {
|
||||
return when {
|
||||
!optionsState.isBalanceHidden && isBalanceHidden -> {
|
||||
optionsState.copy(isBalanceHidden = true)
|
||||
}
|
||||
optionsState.isBalanceHidden && !isBalanceHidden -> {
|
||||
optionsState.copy(isBalanceHidden = false)
|
||||
}
|
||||
else -> optionsState
|
||||
!wasBalanceHidden && isBalanceHidden -> true
|
||||
wasBalanceHidden && !isBalanceHidden -> false
|
||||
else -> wasBalanceHidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.utils.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
|
|
@ -48,12 +45,12 @@ internal class CryptoCurrencyToDraggableItemConverter(
|
|||
|
||||
return TokenItemState.Draggable(
|
||||
id = getTokenItemId(currency.id),
|
||||
icon = iconStateConverter.convert(currencyStatus),
|
||||
name = currency.name,
|
||||
info = if (currencyStatus.value.isError) {
|
||||
resourceReference(id = R.string.common_unreachable)
|
||||
iconState = iconStateConverter.convert(currencyStatus),
|
||||
titleState = TokenItemState.TitleState.Content(text = currency.name),
|
||||
cryptoAmountState = if (currencyStatus.value.isError) {
|
||||
TokenItemState.CryptoAmountState.Unreachable
|
||||
} else {
|
||||
stringReference(getFormattedFiatAmount(currencyStatus, appCurrency))
|
||||
TokenItemState.CryptoAmountState.Content(text = getFormattedFiatAmount(currencyStatus, appCurrency))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.utils
|
||||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
|
@ -39,15 +38,17 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
private fun CryptoCurrencyStatus.mapToTokenItemState(): TokenItemState.Content {
|
||||
return TokenItemState.Content(
|
||||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
icon = iconStateConverter.convert(value = this),
|
||||
amount = getFormattedAmount(),
|
||||
hasPending = value.hasCurrentNetworkTransactions,
|
||||
tokenOptions = TokenItemState.TokenOptionsState(
|
||||
fiatAmount = getFormattedFiatAmount(),
|
||||
priceChangeState = getPriceChangeConfig(),
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
iconState = iconStateConverter.convert(value = this),
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = currency.name,
|
||||
hasPending = value.hasCurrentNetworkTransactions,
|
||||
),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(
|
||||
text = getFormattedFiatAmount(),
|
||||
),
|
||||
cryptoAmountState = TokenItemState.CryptoAmountState.Content(text = getFormattedAmount()),
|
||||
priceChangeState = getPriceChangeConfig(),
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
onItemClick = { clickIntents.onTokenItemClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
|
|
@ -68,29 +69,34 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
|
||||
private fun CryptoCurrencyStatus.mapToUnreachableTokenItemState() = TokenItemState.Unreachable(
|
||||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
icon = iconStateConverter.convert(value = this),
|
||||
iconState = iconStateConverter.convert(value = this),
|
||||
titleState = TokenItemState.TitleState.Content(text = currency.name),
|
||||
onItemClick = { clickIntents.onTokenItemClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
|
||||
private fun CryptoCurrencyStatus.mapToNoAddressTokenItemState() = TokenItemState.NoAddress(
|
||||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
icon = iconStateConverter.convert(this),
|
||||
iconState = iconStateConverter.convert(this),
|
||||
titleState = TokenItemState.TitleState.Content(text = currency.name),
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
|
||||
private fun CryptoCurrencyStatus.getPriceChangeConfig(): PriceChangeState {
|
||||
private fun CryptoCurrencyStatus.getPriceChangeConfig(): TokenItemState.PriceChangeState {
|
||||
val priceChange = value.priceChange
|
||||
|
||||
return if (priceChange != null) {
|
||||
PriceChangeState.Content(
|
||||
valueInPercent = BigDecimalFormatter.formatPercent(percent = priceChange, useAbsoluteValue = true),
|
||||
TokenItemState.PriceChangeState.Content(
|
||||
valueInPercent = BigDecimalFormatter.formatPercent(
|
||||
percent = priceChange,
|
||||
useAbsoluteValue = true,
|
||||
maxFractionDigits = 1,
|
||||
minFractionDigits = 1,
|
||||
),
|
||||
type = priceChange.getPriceChangeType(),
|
||||
)
|
||||
} else {
|
||||
PriceChangeState.Unknown
|
||||
TokenItemState.PriceChangeState.Unknown
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ internal class HiddenStateConverter(
|
|||
if (tokenListItemState.state is TokenItemState.Content) {
|
||||
tokenListItemState.copy(
|
||||
state = tokenListItemState.state.copy(
|
||||
tokenOptions = tokenItemHiddenStateConverter.updateHiddenState(
|
||||
optionsState = tokenListItemState.state.tokenOptions,
|
||||
isBalanceHidden = tokenItemHiddenStateConverter.updateHiddenState(
|
||||
wasBalanceHidden = tokenListItemState.state.isBalanceHidden,
|
||||
isBalanceHidden = value,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue