Updated on 2026-08-14
This commit is contained in:
commit
8cb8795f92
29 changed files with 495 additions and 179 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.common.ui.tokens
|
||||
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
|
|
@ -17,6 +18,7 @@ import com.tangem.utils.StringsSigns.DASH_SIGN
|
|||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -219,7 +221,14 @@ class TokenItemStateConverter(
|
|||
-> {
|
||||
TokenItemState.FiatAmountState.Content(
|
||||
text = status.getFormattedFiatAmount(appCurrency = appCurrency, includeStaking = true),
|
||||
hasStaked = !status.getStakedBalance().isZero(),
|
||||
icons = buildList {
|
||||
if (!status.getStakedBalance().isZero()) {
|
||||
TokenItemState.FiatAmountState.Content.IconUM(
|
||||
iconRes = R.drawable.ic_staking_24,
|
||||
useAccentColor = true,
|
||||
).let(::add)
|
||||
}
|
||||
}.toImmutableList(),
|
||||
)
|
||||
}
|
||||
is CryptoCurrencyStatus.Unreachable,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.common.ui.userwallet
|
|||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.CardColors
|
||||
import androidx.compose.material3.Icon
|
||||
|
|
@ -15,26 +14,32 @@ import androidx.compose.ui.draw.clip
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.coil.RotationTransformation
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.block.BlockCard
|
||||
import com.tangem.core.ui.components.block.TangemBlockCardColors
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.ui.coil.RotationTransformation
|
||||
import com.tangem.core.ui.components.block.TangemBlockCardColors
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.StringsSigns.THREE_STARS
|
||||
|
||||
@Composable
|
||||
fun UserWalletItem(
|
||||
|
|
@ -61,6 +66,7 @@ fun UserWalletItem(
|
|||
modifier = Modifier.weight(1f),
|
||||
name = state.name,
|
||||
information = state.information,
|
||||
balance = state.balance,
|
||||
)
|
||||
|
||||
when (state.endIcon) {
|
||||
|
|
@ -85,7 +91,12 @@ fun UserWalletItem(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun NameAndInfo(name: TextReference, information: TextReference, modifier: Modifier = Modifier) {
|
||||
private fun NameAndInfo(
|
||||
name: TextReference,
|
||||
information: TextReference,
|
||||
balance: UserWalletItemUM.Balance,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.heightIn(min = TangemTheme.dimens.size40),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
|
|
@ -99,17 +110,37 @@ private fun NameAndInfo(name: TextReference, information: TextReference, modifie
|
|||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
AnimatedContent(
|
||||
targetState = information.resolveReference(),
|
||||
label = "User wallet information",
|
||||
) { information ->
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = information,
|
||||
text = information.resolveReference() + " $DOT ",
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
AnimatedContent(
|
||||
targetState = balance,
|
||||
label = "Balance content",
|
||||
) { balance ->
|
||||
val (balanceValue, isFlickering) = getBalanceValueAndFlickerState(balance)
|
||||
|
||||
if (balanceValue == null) {
|
||||
TextShimmer(
|
||||
style = TangemTheme.typography.caption2,
|
||||
text = "aaaaa",
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
modifier = Modifier.flicker(isFlickering),
|
||||
text = balanceValue,
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -150,16 +181,39 @@ private fun CardImage(imageUrl: String, modifier: Modifier = Modifier) {
|
|||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
fun getBalanceValueAndFlickerState(balance: UserWalletItemUM.Balance): Pair<String?, Boolean> {
|
||||
return when (balance) {
|
||||
is UserWalletItemUM.Balance.Failed -> DASH_SIGN to false
|
||||
is UserWalletItemUM.Balance.Hidden -> THREE_STARS to false
|
||||
is UserWalletItemUM.Balance.Loading -> null to false
|
||||
is UserWalletItemUM.Balance.Locked -> stringResource(R.string.common_locked) to false
|
||||
is UserWalletItemUM.Balance.Loaded -> balance.value to balance.isFlickering
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_UserWalletItem(
|
||||
@PreviewParameter(UserWalletItemUMPreviewProvider::class) params: UserWalletItemUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
val list = persistentListOf(
|
||||
UserWalletItem(
|
||||
state = params,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWalletItemUM> {
|
||||
override val values: Sequence<UserWalletItemUM>
|
||||
get() = sequenceOf(
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
name = stringReference("My Wallet"),
|
||||
information = getInformation(3, "4 496,75 $"),
|
||||
information = getInformation(cardCount = 1),
|
||||
balance = UserWalletItemUM.Balance.Locked,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
|
|
@ -167,7 +221,8 @@ private fun Preview() {
|
|||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_2".encodeToByteArray()),
|
||||
name = stringReference("Old wallet"),
|
||||
information = getInformation(3, "4 496,75 $"),
|
||||
information = getInformation(cardCount = 2),
|
||||
balance = UserWalletItemUM.Balance.Hidden,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
|
|
@ -176,7 +231,44 @@ private fun Preview() {
|
|||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = getInformation(3, "4 496,75 $"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Failed,
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Loaded(
|
||||
value = "1.2345 BTC",
|
||||
isFlickering = false,
|
||||
),
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Loaded(
|
||||
value = "1.2345 BTC",
|
||||
isFlickering = true,
|
||||
),
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
|
|
@ -184,30 +276,12 @@ private fun Preview() {
|
|||
),
|
||||
)
|
||||
|
||||
Column(
|
||||
Modifier
|
||||
.background(TangemTheme.colors.background.tertiary)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
list.fastForEach { userWalletItemUM ->
|
||||
UserWalletItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = userWalletItemUM,
|
||||
)
|
||||
}
|
||||
}
|
||||
private fun getInformation(cardCount: Int): TextReference {
|
||||
return TextReference.PluralRes(
|
||||
id = R.plurals.card_label_card_count,
|
||||
count = cardCount,
|
||||
formatArgs = wrappedList(cardCount),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInformation(cardCount: Int, totalBalance: String): TextReference {
|
||||
val t1 = TextReference.PluralRes(
|
||||
id = R.plurals.card_label_card_count,
|
||||
count = cardCount,
|
||||
formatArgs = wrappedList(cardCount),
|
||||
)
|
||||
val divider = stringReference(value = " • ")
|
||||
val t2 = stringReference(totalBalance)
|
||||
|
||||
return TextReference.Combined(wrappedList(t1, divider, t2))
|
||||
}
|
||||
// endregion Preview
|
||||
|
|
@ -2,14 +2,16 @@ package com.tangem.common.ui.userwallet.converter
|
|||
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
|
|
@ -37,12 +39,8 @@ class UserWalletItemUMConverter(
|
|||
UserWalletItemUM(
|
||||
id = walletId,
|
||||
name = stringReference(name),
|
||||
information = getInfo(
|
||||
appCurrency = appCurrency,
|
||||
balance = balance,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
isLoading = isLoading,
|
||||
),
|
||||
information = getInfo(userWallet = this),
|
||||
balance = getBalanceInfo(userWallet = this),
|
||||
imageUrl = artworkUrl,
|
||||
isEnabled = !isLocked,
|
||||
endIcon = endIcon,
|
||||
|
|
@ -51,53 +49,40 @@ class UserWalletItemUMConverter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun UserWallet.getInfo(
|
||||
appCurrency: AppCurrency?,
|
||||
balance: TotalFiatBalance?,
|
||||
isBalanceHidden: Boolean,
|
||||
isLoading: Boolean,
|
||||
): TextReference {
|
||||
val dividerRef = stringReference(value = " $DOT ")
|
||||
|
||||
val cardCount = getCardsCount() ?: 1
|
||||
val cardCountRef = TextReference.PluralRes(
|
||||
private fun getInfo(userWallet: UserWallet): TextReference {
|
||||
val cardCount = userWallet.getCardsCount() ?: 1
|
||||
return TextReference.PluralRes(
|
||||
id = R.plurals.card_label_card_count,
|
||||
count = cardCount,
|
||||
formatArgs = wrappedList(cardCount),
|
||||
)
|
||||
|
||||
return when {
|
||||
isBalanceHidden -> combinedReference(cardCountRef, dividerRef, TextReference.STARS)
|
||||
isLocked -> combinedReference(cardCountRef, dividerRef, resourceReference(R.string.common_locked))
|
||||
isLoading -> cardCountRef
|
||||
else -> getBalanceInfo(balance, appCurrency, cardCountRef, dividerRef)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBalanceInfo(
|
||||
balance: TotalFiatBalance?,
|
||||
appCurrency: AppCurrency?,
|
||||
cardCountRef: TextReference,
|
||||
dividerRef: TextReference,
|
||||
): TextReference {
|
||||
val amount = when (balance) {
|
||||
is TotalFiatBalance.Loaded -> balance.amount
|
||||
is TotalFiatBalance.Failed,
|
||||
is TotalFiatBalance.Loading,
|
||||
null,
|
||||
-> null
|
||||
}
|
||||
private fun getBalanceInfo(userWallet: UserWallet): UserWalletItemUM.Balance {
|
||||
return when {
|
||||
isBalanceHidden -> UserWalletItemUM.Balance.Hidden
|
||||
userWallet.isLocked -> UserWalletItemUM.Balance.Locked
|
||||
balance == null -> UserWalletItemUM.Balance.Loading
|
||||
else -> {
|
||||
when (balance) {
|
||||
is TotalFiatBalance.Loading -> UserWalletItemUM.Balance.Loading
|
||||
is TotalFiatBalance.Failed -> UserWalletItemUM.Balance.Failed
|
||||
is TotalFiatBalance.Loaded -> {
|
||||
if (appCurrency != null) {
|
||||
val formattedAmount = balance.amount.format {
|
||||
fiat(appCurrency.code, appCurrency.symbol)
|
||||
}
|
||||
|
||||
return if (amount != null && appCurrency != null) {
|
||||
val formattedAmount = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = amount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
val amountRef = stringReference(formattedAmount)
|
||||
combinedReference(cardCountRef, dividerRef, amountRef)
|
||||
} else {
|
||||
combinedReference(cardCountRef, dividerRef, stringReference(BigDecimalFormatter.EMPTY_BALANCE_SIGN))
|
||||
UserWalletItemUM.Balance.Loaded(
|
||||
value = formattedAmount,
|
||||
isFlickering = isLoading,
|
||||
)
|
||||
} else {
|
||||
UserWalletItemUM.Balance.Failed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ data class UserWalletItemUM(
|
|||
val id: UserWalletId,
|
||||
val name: TextReference,
|
||||
val information: TextReference,
|
||||
val balance: Balance,
|
||||
val imageUrl: String,
|
||||
val isEnabled: Boolean,
|
||||
val endIcon: EndIcon = EndIcon.None,
|
||||
|
|
@ -19,4 +20,20 @@ data class UserWalletItemUM(
|
|||
Arrow,
|
||||
Checkmark,
|
||||
}
|
||||
|
||||
sealed class Balance {
|
||||
|
||||
data object Hidden : Balance()
|
||||
|
||||
data object Locked : Balance()
|
||||
|
||||
data object Failed : Balance()
|
||||
|
||||
data object Loading : Balance()
|
||||
|
||||
data class Loaded(
|
||||
val value: String,
|
||||
val isFlickering: Boolean,
|
||||
) : Balance()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.tangem.core.ui.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
/**
|
||||
* Modifier that makes content flicker.
|
||||
*
|
||||
* @param isFlickering if `true`, content will flicker.
|
||||
* @param targetTextAlpha target alpha value for flickering.
|
||||
* @param animationDurationMillis duration of flickering animation.
|
||||
* */
|
||||
fun Modifier.flicker(
|
||||
isFlickering: Boolean,
|
||||
targetTextAlpha: Float = 0.4f,
|
||||
animationDurationMillis: Int = 1200,
|
||||
): Modifier = composed {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
val defaultAlpha = remember { mutableFloatStateOf(value = 1f) }
|
||||
|
||||
val alpha: Float by if (isFlickering) {
|
||||
infiniteTransition.animateFloat(
|
||||
initialValue = 1f,
|
||||
targetValue = targetTextAlpha,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(
|
||||
durationMillis = animationDurationMillis,
|
||||
easing = CubicBezierEasing(a = 0.45f, b = 0.0f, c = 0.55f, d = 1.0f),
|
||||
),
|
||||
repeatMode = RepeatMode.Reverse,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
defaultAlpha
|
||||
}
|
||||
|
||||
this.then(alpha(alpha))
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_FlickerText() {
|
||||
TangemThemePreview {
|
||||
var isFlickering by remember {
|
||||
mutableStateOf(value = true)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.primary)
|
||||
.clickable {
|
||||
isFlickering = !isFlickering
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.flicker(isFlickering),
|
||||
text = "Flicker text",
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.body1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// endregion Preview
|
||||
|
|
@ -23,12 +23,14 @@ import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
|||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.components.token.internal.*
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import java.util.UUID
|
||||
import kotlin.math.max
|
||||
|
|
@ -462,11 +464,18 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
text = stringReference(value = "PolygonPolygonPolygonPolygonPolygonPolygon"),
|
||||
hasPending = true,
|
||||
),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "3213123123321312312312312312 $",
|
||||
hasStaked = true,
|
||||
icons = persistentListOf(
|
||||
FiatAmountState.Content.IconUM(R.drawable.ic_error_sync_24, useAccentColor = false),
|
||||
stakingIcon,
|
||||
),
|
||||
isFlickering = true,
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(
|
||||
text = "5,4123123213123123123123123123 MATIC",
|
||||
isFlickering = true,
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,4123123213123123123123123123 MATIC"),
|
||||
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
|
||||
price = "312 USD",
|
||||
priceChangePercent = "42.0%",
|
||||
|
|
@ -511,7 +520,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
id = UUID.randomUUID().toString(),
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = false),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "321 $",
|
||||
icons = persistentListOf(stakingIcon),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,412 MATIC"),
|
||||
subtitleState = TokenItemState.SubtitleState.CryptoPriceContent(
|
||||
price = "312 USD",
|
||||
|
|
@ -525,7 +537,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
id = UUID.randomUUID().toString(),
|
||||
iconState = tokenIconState,
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = false),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "321 $",
|
||||
icons = persistentListOf(stakingIcon),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.LabelContent(
|
||||
auditLabelUM = AuditLabelUM(
|
||||
text = TextReference.Str(value = "Trusted"),
|
||||
|
|
@ -565,6 +580,8 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
|
||||
companion object {
|
||||
|
||||
val stakingIcon = FiatAmountState.Content.IconUM(R.drawable.ic_staking_24, useAccentColor = true)
|
||||
|
||||
val coinIconState
|
||||
get() = CurrencyIconState.CoinIcon(
|
||||
url = null,
|
||||
|
|
@ -599,7 +616,10 @@ private class TokenItemStateProvider : CollectionPreviewParameterProvider<TokenI
|
|||
text = stringReference(value = "Polygon"),
|
||||
hasPending = true,
|
||||
),
|
||||
fiatAmountState = TokenItemState.FiatAmountState.Content(text = "321 $", hasStaked = true),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = "321 $",
|
||||
icons = persistentListOf(stakingIcon),
|
||||
),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "5,412 MATIC"),
|
||||
subtitleState = TokenItemState.SubtitleState.Unknown,
|
||||
onItemClick = {},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.audits.AuditLabel
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -25,15 +26,19 @@ internal fun TokenCryptoAmount(
|
|||
when (state) {
|
||||
is TokenCryptoAmountState.TextContent -> {
|
||||
CryptoAmountText(
|
||||
amount = state.text.orMaskWithStars(isBalanceHidden),
|
||||
modifier = modifier,
|
||||
amount = state.text.orMaskWithStars(isBalanceHidden),
|
||||
isFlickering = state.isFlickering,
|
||||
)
|
||||
}
|
||||
is TokenItemState.Subtitle2State.LabelContent -> {
|
||||
AuditLabel(state = state.auditLabelUM, modifier = modifier)
|
||||
}
|
||||
is TokenCryptoAmountState.Unreachable -> {
|
||||
CryptoAmountText(amount = stringResourceSafe(id = R.string.common_unreachable), modifier = modifier)
|
||||
CryptoAmountText(
|
||||
amount = stringResourceSafe(id = R.string.common_unreachable),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is TokenCryptoAmountState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
|
|
@ -46,10 +51,10 @@ internal fun TokenCryptoAmount(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun CryptoAmountText(amount: String, modifier: Modifier = Modifier) {
|
||||
private fun CryptoAmountText(amount: String, modifier: Modifier = Modifier, isFlickering: Boolean = false) {
|
||||
Text(
|
||||
modifier = modifier.flicker(isFlickering),
|
||||
text = amount,
|
||||
modifier = modifier,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.core.ui.components.token.internal
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -14,9 +15,10 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.tangem.core.ui.R
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState as TokenFiatAmountState
|
||||
|
|
@ -26,12 +28,13 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool
|
|||
when (state) {
|
||||
is TokenFiatAmountState.Content -> {
|
||||
ContentFiatAmount(
|
||||
text = state.text.orMaskWithStars(isBalanceHidden),
|
||||
hasStaked = state.hasStaked,
|
||||
modifier = modifier,
|
||||
text = state.text.orMaskWithStars(isBalanceHidden),
|
||||
icons = state.icons,
|
||||
isAmountFlickering = state.isFlickering,
|
||||
)
|
||||
}
|
||||
is TokenItemState.FiatAmountState.TextContent -> {
|
||||
is TokenFiatAmountState.TextContent -> {
|
||||
FiatAmountText(
|
||||
text = state.text.orMaskWithStars(isBalanceHidden),
|
||||
modifier = modifier,
|
||||
|
|
@ -39,7 +42,7 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool
|
|||
)
|
||||
}
|
||||
is TokenFiatAmountState.Loading -> {
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = TangemTheme.dimens.radius4)
|
||||
RectangleShimmer(modifier = modifier.placeholderSize(), radius = 4.dp)
|
||||
}
|
||||
is TokenFiatAmountState.Locked -> {
|
||||
LockedRectangle(modifier = modifier.placeholderSize())
|
||||
|
|
@ -49,33 +52,53 @@ internal fun TokenFiatAmount(state: TokenFiatAmountState?, isBalanceHidden: Bool
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentFiatAmount(text: String, hasStaked: Boolean, modifier: Modifier = Modifier) {
|
||||
private fun ContentFiatAmount(
|
||||
text: String,
|
||||
icons: List<TokenFiatAmountState.Content.IconUM>,
|
||||
isAmountFlickering: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = hasStaked,
|
||||
visible = icons.isNotEmpty(),
|
||||
) {
|
||||
Icon(
|
||||
painter = rememberVectorPainter(image = ImageVector.vectorResource(R.drawable.ic_staking_24)),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing4)
|
||||
.size(TangemTheme.dimens.size12),
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
icons.fastForEach { icon ->
|
||||
Icon(
|
||||
modifier = Modifier.size(12.dp),
|
||||
painter = rememberVectorPainter(image = ImageVector.vectorResource(icon.iconRes)),
|
||||
tint = if (icon.useAccentColor) {
|
||||
TangemTheme.colors.icon.accent
|
||||
} else {
|
||||
TangemTheme.colors.icon.inactive
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FiatAmountText(text = text)
|
||||
FiatAmountText(text = text, isFlickering = isAmountFlickering)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FiatAmountText(text: String, modifier: Modifier = Modifier, isAvailable: Boolean = true) {
|
||||
private fun FiatAmountText(
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
isAvailable: Boolean = true,
|
||||
isFlickering: Boolean = false,
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier.flicker(isFlickering),
|
||||
text = text,
|
||||
modifier = modifier,
|
||||
color = if (isAvailable) TangemTheme.colors.text.primary1 else TangemTheme.colors.text.tertiary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
|
|
@ -85,6 +108,6 @@ private fun FiatAmountText(text: String, modifier: Modifier = Modifier, isAvaila
|
|||
|
||||
private fun Modifier.placeholderSize(): Modifier = composed {
|
||||
return@composed this
|
||||
.padding(vertical = TangemTheme.dimens.spacing4)
|
||||
.size(width = TangemTheme.dimens.size40, height = TangemTheme.dimens.size12)
|
||||
.padding(vertical = 4.dp)
|
||||
.size(width = 40.dp, height = 12.dp)
|
||||
}
|
||||
|
|
@ -5,6 +5,8 @@ import com.tangem.core.ui.components.audits.AuditLabelUM
|
|||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/** TokenItem component state */
|
||||
@Immutable
|
||||
|
|
@ -192,10 +194,18 @@ sealed class TokenItemState {
|
|||
|
||||
@Immutable
|
||||
sealed class FiatAmountState {
|
||||
|
||||
data class Content(
|
||||
val text: String,
|
||||
val hasStaked: Boolean = false,
|
||||
) : FiatAmountState()
|
||||
val isFlickering: Boolean = false,
|
||||
val icons: ImmutableList<IconUM> = persistentListOf(),
|
||||
) : FiatAmountState() {
|
||||
|
||||
data class IconUM(
|
||||
val iconRes: Int,
|
||||
val useAccentColor: Boolean,
|
||||
)
|
||||
}
|
||||
|
||||
data class TextContent(val text: String, val isAvailable: Boolean = true) : FiatAmountState()
|
||||
|
||||
|
|
@ -207,7 +217,10 @@ sealed class TokenItemState {
|
|||
@Immutable
|
||||
sealed class Subtitle2State {
|
||||
|
||||
data class TextContent(val text: String) : Subtitle2State()
|
||||
data class TextContent(
|
||||
val text: String,
|
||||
val isFlickering: Boolean = false,
|
||||
) : Subtitle2State()
|
||||
|
||||
data class LabelContent(val auditLabelUM: AuditLabelUM) : Subtitle2State()
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.google.zxing.qrcode.QRCodeWriter
|
|||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
|
||||
import com.tangem.core.res.getPluralStringSafe
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.utils.StringsSigns.THREE_STARS
|
||||
import java.util.Hashtable
|
||||
|
||||
/**
|
||||
|
|
@ -79,6 +80,4 @@ fun String.capitalize(): String = replaceFirstChar { if (it.isLowerCase()) it.ti
|
|||
|
||||
fun String.orMaskWithStars(maskWithStars: Boolean): String {
|
||||
return if (maskWithStars) THREE_STARS else this
|
||||
}
|
||||
|
||||
internal const val THREE_STARS = "\u2217\u2217\u2217"
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.text.AnnotatedString.Builder
|
|||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import com.tangem.core.res.getPluralStringSafe
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.utils.StringsSigns.THREE_STARS
|
||||
import org.intellij.markdown.MarkdownElementTypes
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
|
@ -72,9 +73,6 @@ sealed interface TextReference {
|
|||
|
||||
/** Empty string as [TextReference] */
|
||||
val EMPTY: TextReference by lazy(mode = LazyThreadSafetyMode.NONE) { Str(value = "") }
|
||||
|
||||
/** Stars string as [TextReference] */
|
||||
val STARS: TextReference by lazy(mode = LazyThreadSafetyMode.NONE) { Str(value = THREE_STARS) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
15
core/ui/src/main/res/drawable/ic_error_sync_24.xml
Normal file
15
core/ui/src/main/res/drawable/ic_error_sync_24.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M12,4C15.64,4,18.67,6.59,19.35,10.04C21.95,10.22,24,12.36,24,15C24,15.66,23.87,16.31,23.62,16.91C23.37,17.52,23,18.07,22.54,18.54C22.07,19,21.52,19.37,20.91,19.62C20.31,19.87,19.66,20,19,20H15.5V18H19C19.8,18,20.56,17.68,21.12,17.12C21.68,16.56,22,15.8,22,15C22,13.45,20.78,12.14,19.22,12.04L17.69,11.93L17.39,10.43C16.88,7.86,14.62,6,12,6C9.94,6,8.08,7.14,7.13,8.97L6.63,9.92L5.56,10.03C3.53,10.24,2,11.95,2,14C2,15.06,2.42,16.08,3.17,16.83C3.92,17.58,4.94,18,6,18H8.5V20H6C4.41,20,2.88,19.37,1.76,18.24C0.63,17.12,0,15.59,0,14C0,10.91,2.34,8.36,5.35,8.04C6.6,5.64,9.11,4,12,4Z" />
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M11,19V14H13V19Z" />
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M13,21V23H11V21Z" />
|
||||
</vector>
|
||||
|
|
@ -11,4 +11,5 @@ object StringsSigns {
|
|||
const val INFINITY_SIGN = "∞"
|
||||
const val NON_BREAKING_SPACE = '\u00A0'
|
||||
const val PERCENT = "%"
|
||||
const val THREE_STARS = "\u2217\u2217\u2217"
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.features.details.component.preview
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -13,55 +16,75 @@ import com.tangem.features.details.entity.UserWalletListUM
|
|||
import com.tangem.features.details.impl.R
|
||||
import com.tangem.features.details.ui.UserWalletListBlock
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
internal class PreviewUserWalletListComponent : UserWalletListComponent {
|
||||
|
||||
private val previewState = UserWalletListUM(
|
||||
userWallets = persistentListOf(
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
name = stringReference("My Wallet"),
|
||||
information = getInformation(3, "4 496,75 $"),
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_2".encodeToByteArray()),
|
||||
name = stringReference("Old wallet"),
|
||||
information = getInformation(3, "4 496,75 $"),
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = getInformation(3, "4 496,75 $"),
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
onClick = {},
|
||||
private val previewState = mutableStateOf(
|
||||
UserWalletListUM(
|
||||
userWallets = persistentListOf(
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_1".encodeToByteArray()),
|
||||
name = stringReference("My Wallet"),
|
||||
information = getInformation(cardCount = 1),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_2".encodeToByteArray()),
|
||||
name = stringReference("Old wallet"),
|
||||
information = getInformation(cardCount = 2),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
addNewWalletText = resourceReference(R.string.user_wallet_list_add_button),
|
||||
isWalletSavingInProgress = false,
|
||||
onAddNewWalletClick = {},
|
||||
),
|
||||
addNewWalletText = resourceReference(R.string.user_wallet_list_add_button),
|
||||
isWalletSavingInProgress = false,
|
||||
onAddNewWalletClick = {},
|
||||
)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
UserWalletListBlock(state = previewState, modifier = modifier)
|
||||
val state by previewState
|
||||
|
||||
UserWalletListBlock(state = state, modifier = modifier)
|
||||
|
||||
LaunchedEffect(key1 = this) {
|
||||
delay(timeMillis = 2_000)
|
||||
|
||||
previewState.value = state.copy(
|
||||
userWallets = state.userWallets.map {
|
||||
it.copy(
|
||||
balance = UserWalletItemUM.Balance.Loaded(
|
||||
value = "1.000 BTC",
|
||||
isFlickering = true,
|
||||
),
|
||||
)
|
||||
}.toImmutableList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInformation(cardCount: Int, totalBalance: String): TextReference {
|
||||
val t1 = TextReference.PluralRes(
|
||||
private fun getInformation(cardCount: Int): TextReference {
|
||||
return TextReference.PluralRes(
|
||||
id = R.plurals.card_label_card_count,
|
||||
count = cardCount,
|
||||
formatArgs = wrappedList(cardCount),
|
||||
)
|
||||
val divider = stringReference(value = " • ")
|
||||
val t2 = stringReference(totalBalance)
|
||||
|
||||
return TextReference.Combined(wrappedList(t1, divider, t2))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.details.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
|
|
@ -10,11 +11,17 @@ import androidx.compose.runtime.key
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import com.tangem.common.ui.userwallet.UserWalletItem
|
||||
import com.tangem.core.ui.components.block.BlockCard
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.details.component.UserWalletListComponent
|
||||
import com.tangem.features.details.component.preview.PreviewUserWalletListComponent
|
||||
import com.tangem.features.details.entity.UserWalletListUM
|
||||
import com.tangem.features.details.impl.R
|
||||
|
||||
|
|
@ -85,4 +92,24 @@ private fun AddWalletButton(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_UserWalletListBlock(
|
||||
@PreviewParameter(UserWalletListComponentPreviewProvider::class) component: UserWalletListComponent,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
component.Content(Modifier)
|
||||
}
|
||||
}
|
||||
|
||||
private class UserWalletListComponentPreviewProvider : PreviewParameterProvider<UserWalletListComponent> {
|
||||
override val values: Sequence<UserWalletListComponent>
|
||||
get() = sequenceOf(
|
||||
PreviewUserWalletListComponent(),
|
||||
)
|
||||
}
|
||||
// endregion Preview
|
||||
|
|
@ -16,9 +16,11 @@ import com.tangem.core.ui.haptic.TangemHapticEffect
|
|||
import com.tangem.core.ui.res.LocalHapticManager
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.features.markets.portfolio.impl.ui.preview.PreviewMyPortfolioUMProvider
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState as TokenFiatAmountState
|
||||
|
||||
@Composable
|
||||
|
|
@ -96,7 +98,14 @@ private class PortfolioTokenUMProvider : CollectionPreviewParameterProvider<Port
|
|||
collection = listOf(
|
||||
tokenUM.copy(
|
||||
tokenItemState = (tokenUM.tokenItemState as TokenItemState.Content).copy(
|
||||
fiatAmountState = contentFiatAmount.copy(hasStaked = true),
|
||||
fiatAmountState = contentFiatAmount.copy(
|
||||
icons = persistentListOf(
|
||||
TokenItemState.FiatAmountState.Content.IconUM(
|
||||
iconRes = R.drawable.ic_staking_24,
|
||||
useAccentColor = true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
tokenUM.copy(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ internal class PreviewAddToPortfolioBSContentProvider : PreviewParameterProvider
|
|||
val userWallet = UserWalletItemUM(
|
||||
id = UserWalletId("1"),
|
||||
name = stringReference("Wallet 1"),
|
||||
information = stringReference("3 cards, 10,123$"),
|
||||
information = stringReference("3 cards"),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
endIcon = UserWalletItemUM.EndIcon.Arrow,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails
|
|||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.paging.PagingData
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
|
|
@ -11,7 +12,6 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
|
||||
|
|
@ -129,6 +129,7 @@ internal object TokenDetailsPreviewData {
|
|||
displayCryptoBalance = "966,96 XLM",
|
||||
displayFiatBalance = "91,50$",
|
||||
isBalanceSelectorEnabled = true,
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
val balanceError = TokenDetailsBalanceBlockState.Error(
|
||||
actionButtons = actionButtons,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ internal sealed class TokenDetailsBalanceBlockState {
|
|||
val displayCryptoBalance: String,
|
||||
val displayFiatBalance: String,
|
||||
val isBalanceSelectorEnabled: Boolean,
|
||||
val isBalanceFlickering: Boolean,
|
||||
) : TokenDetailsBalanceBlockState()
|
||||
|
||||
data class Error(
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
onBalanceSelect = clickIntents::onBalanceSelect,
|
||||
selectedBalanceType = currentState.selectedBalanceType,
|
||||
isBalanceSelectorEnabled = isBalanceSelectorEnabled,
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
)
|
||||
is CryptoCurrencyStatus.Loading -> TokenDetailsBalanceBlockState.Loading(
|
||||
actionButtons = currentState.actionButtons,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.constraintlayout.compose.ConstraintLayout
|
|||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.buttons.HorizontalActionChips
|
||||
import com.tangem.core.ui.components.buttons.segmentedbutton.SegmentedButtons
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -113,7 +114,7 @@ private fun FiatBalance(
|
|||
),
|
||||
)
|
||||
is TokenDetailsBalanceBlockState.Content -> Text(
|
||||
modifier = modifier,
|
||||
modifier = modifier.flicker(state.isBalanceFlickering),
|
||||
text = state.displayFiatBalance.orMaskWithStars(isBalanceHidden),
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
|
|
@ -141,7 +142,7 @@ private fun CryptoBalance(
|
|||
),
|
||||
)
|
||||
is TokenDetailsBalanceBlockState.Content -> Text(
|
||||
modifier = modifier,
|
||||
modifier = modifier.flicker(state.isBalanceFlickering),
|
||||
text = state.displayCryptoBalance.orMaskWithStars(isBalanceHidden),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
|
|
@ -202,6 +203,7 @@ private class TokenDetailsBalanceBlockStateProvider : CollectionPreviewParameter
|
|||
collection = listOf(
|
||||
TokenDetailsPreviewData.balanceLoading,
|
||||
TokenDetailsPreviewData.balanceContent,
|
||||
TokenDetailsPreviewData.balanceContent.copy(isBalanceFlickering = true),
|
||||
TokenDetailsPreviewData.balanceError,
|
||||
),
|
||||
)
|
||||
|
|
@ -36,6 +36,7 @@ internal object WalletPreviewData {
|
|||
onDeleteClick = {},
|
||||
cardCount = 1,
|
||||
isZeroBalance = false,
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.common.preview
|
||||
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
|
|
@ -7,7 +8,6 @@ import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
|||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData.topBarConfig
|
||||
|
|
@ -105,6 +105,7 @@ internal object WalletScreenPreviewData {
|
|||
onRenameClick = { _ -> },
|
||||
onDeleteClick = {},
|
||||
isZeroBalance = false,
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
}
|
||||
private val multiWalletState by lazy {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ internal sealed interface WalletCardState {
|
|||
override val imageResId: Int?,
|
||||
override val onRenameClick: (UserWalletId) -> Unit,
|
||||
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||
val isBalanceFlickering: Boolean,
|
||||
val cardCount: Int?,
|
||||
val balance: String,
|
||||
val isZeroBalance: Boolean?,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ internal class SetBalancesAndLimitsTransformer(
|
|||
},
|
||||
cardCount = userWallet.getCardsCount(),
|
||||
isZeroBalance = visaCurrency.balances.available.isZero(),
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ internal class SetTokenListErrorTransformer(
|
|||
),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
isZeroBalance = true,
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,7 @@ internal class MultiWalletCardStateConverter(
|
|||
),
|
||||
isZeroBalance = fiatBalance.amount.isZero(),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@ internal class SingleWalletCardStateConverter(
|
|||
balance = formatFiatAmount(status = status, appCurrency = appCurrency),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
isZeroBalance = status.fiatAmount?.isZero(),
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import androidx.constraintlayout.compose.Dimension
|
|||
import com.tangem.core.ui.components.FontSizeRange
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.ResizableText
|
||||
import com.tangem.core.ui.components.flicker
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.orMaskWithStars
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
|
|
@ -289,9 +290,11 @@ private fun Balance(state: WalletCardState, isBalanceHidden: Boolean, modifier:
|
|||
when (walletCardState) {
|
||||
is WalletCardState.Content -> {
|
||||
ResizableText(
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size32)
|
||||
.flicker(isFlickering = walletCardState.isBalanceFlickering),
|
||||
text = walletCardState.balance.orMaskWithStars(isBalanceHidden),
|
||||
fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
|
||||
modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size32),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
|
|
@ -401,6 +404,9 @@ private fun Preview_WalletCard(
|
|||
private class WalletCardStateProvider : CollectionPreviewParameterProvider<WalletCardState>(
|
||||
collection = listOf(
|
||||
WalletPreviewData.walletCardContentState,
|
||||
WalletPreviewData.walletCardContentState.copy(
|
||||
isBalanceFlickering = true,
|
||||
),
|
||||
WalletPreviewData.walletCardLoadingState,
|
||||
WalletPreviewData.walletCardErrorState,
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue