diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index 3f80bcbc71..bea3f669ff 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -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, diff --git a/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt b/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt index db128105fb..2350350cd0 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/utils/BigDecimalFormatter.kt @@ -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 diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index 2e38ce1e26..0671449433 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -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"), ), ), ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt index 7e0fd572df..4c1514a7f0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/TokenItem.kt @@ -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( 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, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenCryptoAmount.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenCryptoAmount.kt index 700dfdc58c..74d1cf836f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenCryptoAmount.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenCryptoAmount.kt @@ -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) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenFiatAmount.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenFiatAmount.kt index f4ed36c1c8..6aff7c7e1c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenFiatAmount.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenFiatAmount.kt @@ -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) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenPriceChange.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenPriceChange.kt index 1981bb5b17..002357512e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenPriceChange.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenPriceChange.kt @@ -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) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenTitle.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenTitle.kt index 37106e707c..50cea114b0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenTitle.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/TokenTitle.kt @@ -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( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/ContentIcon.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/ContentIcon.kt index 49e3b3f183..9f29cbd72b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/ContentIcon.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/ContentIcon.kt @@ -53,6 +53,9 @@ internal fun ContentIcon( background = icon.background, alpha = alpha, ) + TokenItemState.IconState.Loading, + TokenItemState.IconState.Locked, + -> Unit } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/TokenIcon.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/TokenIcon.kt index be02ad2229..9a5cd1bee0 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/TokenIcon.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/component/token/icon/TokenIcon.kt @@ -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) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt index ca960f320f..d61fbbbba4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/state/TokenItemState.kt @@ -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 = "—" diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenItemHiddenStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenItemHiddenStateConverter.kt index 91e8124c43..5a98aa841d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenItemHiddenStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenItemHiddenStateConverter.kt @@ -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 } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt index a6c36995b0..aa518deba2 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt @@ -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)) }, ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt index f434ec4117..89ce3ee6b1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/CryptoCurrencyStatusToTokenItemConverter.kt @@ -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 } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/HiddenStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/HiddenStateConverter.kt index a5f5ea9808..ae1528ddaf 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/HiddenStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/HiddenStateConverter.kt @@ -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, ), ),