Updated on 2026-08-14
This commit is contained in:
parent
6d95abf3b8
commit
75e2268d10
15 changed files with 522 additions and 271 deletions
|
|
@ -1,45 +1,49 @@
|
|||
package com.tangem.core.ui.extensions
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.core.ui.R
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.core.graphics.toColorInt
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
|
||||
private const val LIGHT_LUMINANCE = 0.5f
|
||||
private const val COLOR_HEX_START_INDEX = 2
|
||||
private const val COLOR_HEX_END_INDEX = 7
|
||||
|
||||
/**
|
||||
* Retrieves the resource ID for the network badge of a [CryptoCurrency].
|
||||
* Retrieves the resource ID for the network of a [CryptoCurrency].
|
||||
*
|
||||
* This property provides a way to fetch the appropriate drawable resource ID
|
||||
* for the network badge of a given cryptocurrency. For coins, this will typically
|
||||
* return null as they do not have network badges, while tokens will fetch the icon
|
||||
* based on their associated network ID.
|
||||
*
|
||||
* @return Drawable resource ID for the network badge or null if the cryptocurrency is a coin.
|
||||
* @return Drawable resource ID for the network.
|
||||
*/
|
||||
@get:DrawableRes
|
||||
val CryptoCurrency.networkBadgeIconResId: Int?
|
||||
get() = when (this) {
|
||||
is CryptoCurrency.Coin -> null
|
||||
is CryptoCurrency.Token -> getActiveIconRes(network.id.value)
|
||||
val CryptoCurrency.networkIconResId: Int
|
||||
get() = getActiveIconRes(network.id.value)
|
||||
|
||||
/**
|
||||
* Tries to extract a background color from the contract address of a token.
|
||||
*
|
||||
* @param fallbackColor The color to use as a fallback.
|
||||
* @return The extracted background color or the fallback color if extraction fails or if it is a test network token.
|
||||
*/
|
||||
fun CryptoCurrency.Token.tryGetBackgroundForTokenIcon(fallbackColor: Color = TangemColorPalette.Black): Color {
|
||||
if (network.isTestnet) return fallbackColor
|
||||
|
||||
return try {
|
||||
val colorHex = "#" + contractAddress.substring(range = COLOR_HEX_START_INDEX..COLOR_HEX_END_INDEX)
|
||||
Color(colorHex.toColorInt())
|
||||
} catch (exception: Exception) {
|
||||
fallbackColor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the resource ID for the icon of a [CryptoCurrency].
|
||||
* Determines the tint color to be used for a token icon based on its background color.
|
||||
* If the icon's background color is light, a dark tint is chosen; otherwise, a light tint is chosen.
|
||||
*
|
||||
* This property provides a way to fetch the appropriate drawable resource ID
|
||||
* for the icon of a given cryptocurrency.
|
||||
*
|
||||
* @return Drawable resource ID for the cryptocurrency icon.
|
||||
* @param iconBackground The background color of the custom token icon.
|
||||
* @return The tint color to be used for the icon.
|
||||
*/
|
||||
@get:DrawableRes
|
||||
val CryptoCurrency.iconResId: Int
|
||||
get() = when (this) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
val rawCoinId = id.rawCurrencyId
|
||||
|
||||
if (rawCoinId != null) {
|
||||
getActiveIconResByCoinId(rawCoinId, network.id.value)
|
||||
} else {
|
||||
R.drawable.ic_alert_24
|
||||
}
|
||||
}
|
||||
is CryptoCurrency.Token -> R.drawable.ic_alert_24
|
||||
}
|
||||
fun getTintForTokenIcon(iconBackground: Color): Color {
|
||||
return if (iconBackground.luminance() > LIGHT_LUMINANCE) TangemColorPalette.Black else TangemColorPalette.White
|
||||
}
|
||||
|
|
@ -88,6 +88,7 @@ private fun materialThemeColors(colors: TangemColors, isDark: Boolean): Colors {
|
|||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun lightThemeColors(): TangemColors {
|
||||
return TangemColors(
|
||||
text = TangemColors.Text(
|
||||
|
|
@ -135,6 +136,7 @@ private fun lightThemeColors(): TangemColors {
|
|||
}
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
private fun darkThemeColors(): TangemColors {
|
||||
return TangemColors(
|
||||
text = TangemColors.Text(
|
||||
|
|
|
|||
10
core/ui/src/main/res/drawable/ic_custom_token_44.xml
Normal file
10
core/ui/src/main/res/drawable/ic_custom_token_44.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="44dp"
|
||||
android:height="44dp"
|
||||
android:viewportWidth="44"
|
||||
android:viewportHeight="44">
|
||||
|
||||
<path
|
||||
android:fillColor="#656565"
|
||||
android:pathData="M22,34L22.69,29.327C23,27.23 23.155,26.182 23.648,25.352C24.065,24.651 24.651,24.065 25.352,23.648C26.182,23.155 27.23,23 29.327,22.69L34,22L29.327,21.31C27.23,21 26.182,20.845 25.352,20.352C24.651,19.935 24.065,19.349 23.648,18.648C23.155,17.818 23,16.77 22.69,14.673L22,10L21.31,14.673C21,16.77 20.845,17.818 20.352,18.648C19.935,19.349 19.349,19.935 18.648,20.352C17.818,20.845 16.77,21 14.673,21.31L10,22L14.673,22.69C16.77,23 17.818,23.155 18.648,23.648C19.349,24.065 19.935,24.651 20.352,25.352C20.845,26.182 21,27.23 21.31,29.327L22,34Z" />
|
||||
</vector>
|
||||
|
|
@ -3,14 +3,10 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory
|
|||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsTopAppBarConfig
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenInfoBlockState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsSkeletonStateConverter.SkeletonModel
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents
|
||||
|
|
@ -38,7 +34,7 @@ internal class TokenDetailsSkeletonStateConverter(
|
|||
is CryptoCurrency.Token -> TokenInfoBlockState.Currency.Token(
|
||||
networkName = currency.network.standardType.name,
|
||||
blockchainName = currency.network.name,
|
||||
networkIcon = currency.iconResId,
|
||||
networkIcon = currency.networkIconResId,
|
||||
)
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -8,13 +8,17 @@ import com.tangem.core.ui.components.transactions.state.TransactionState
|
|||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.event.consumed
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
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
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.TokenActionButtonConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState.TokensListItemState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -87,12 +91,34 @@ internal object WalletPreviewData {
|
|||
)
|
||||
}
|
||||
|
||||
private val coinIconState
|
||||
get() = TokenItemState.IconState.CoinIcon(
|
||||
url = null,
|
||||
fallbackResId = R.drawable.img_polygon_22,
|
||||
isGrayscale = false,
|
||||
)
|
||||
|
||||
private val tokenIconState
|
||||
get() = TokenItemState.IconState.TokenIcon(
|
||||
url = null,
|
||||
networkBadgeIconResId = R.drawable.img_polygon_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
)
|
||||
|
||||
private val customTokenIconState
|
||||
get() = TokenItemState.IconState.CustomTokenIcon(
|
||||
tint = TangemColorPalette.Black,
|
||||
background = TangemColorPalette.Meadow,
|
||||
networkBadgeIconResId = R.drawable.img_polygon_22,
|
||||
isGrayscale = false,
|
||||
)
|
||||
|
||||
val tokenItemVisibleState by lazy {
|
||||
TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkBadgeIconResId = R.drawable.img_polygon_22,
|
||||
icon = coinIconState,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
|
|
@ -103,7 +129,6 @@ internal object WalletPreviewData {
|
|||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
isTestnet = false,
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
|
|
@ -112,16 +137,14 @@ internal object WalletPreviewData {
|
|||
val testnetTokenItemVisibleState by lazy {
|
||||
tokenItemVisibleState.copy(
|
||||
name = "Polygon testnet",
|
||||
isTestnet = true,
|
||||
icon = tokenIconState.copy(isGrayscale = true),
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemHiddenState by lazy {
|
||||
TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkBadgeIconResId = R.drawable.img_polygon_22,
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
|
|
@ -131,7 +154,6 @@ internal object WalletPreviewData {
|
|||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
isTestnet = false,
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
)
|
||||
|
|
@ -140,11 +162,8 @@ internal object WalletPreviewData {
|
|||
val tokenItemDragState by lazy {
|
||||
TokenItemState.Draggable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkBadgeIconResId = R.drawable.img_polygon_22,
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
isTestnet = false,
|
||||
fiatAmount = "3 172,14 $",
|
||||
)
|
||||
}
|
||||
|
|
@ -152,13 +171,28 @@ internal object WalletPreviewData {
|
|||
val tokenItemUnreachableState by lazy {
|
||||
TokenItemState.Unreachable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkBadgeIconResId = R.drawable.img_polygon_22,
|
||||
icon = tokenIconState,
|
||||
name = "Polygon",
|
||||
)
|
||||
}
|
||||
|
||||
val customTokenItemVisibleState by lazy {
|
||||
tokenItemVisibleState.copy(
|
||||
name = "Polygon custom",
|
||||
icon = customTokenIconState.copy(
|
||||
tint = TangemColorPalette.White,
|
||||
background = TangemColorPalette.Black,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val customTestnetTokenItemVisibleState by lazy {
|
||||
tokenItemVisibleState.copy(
|
||||
name = "Polygon custom testnet",
|
||||
icon = customTokenIconState.copy(isGrayscale = true),
|
||||
)
|
||||
}
|
||||
|
||||
val loadingTokenItemState by lazy { TokenItemState.Loading(id = "Loading#1") }
|
||||
|
||||
private const val networksSize = 10
|
||||
|
|
@ -188,7 +222,6 @@ internal object WalletPreviewData {
|
|||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
name = "Token $tokenNumber from $networkNumber network",
|
||||
networkBadgeIconResId = R.drawable.img_eth_22.takeIf { i != 0 },
|
||||
),
|
||||
groupId = group.id,
|
||||
roundingMode = when {
|
||||
|
|
@ -299,8 +332,6 @@ internal object WalletPreviewData {
|
|||
tokenItemVisibleState.copy(
|
||||
id = "token_1",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkBadgeIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
|
|
@ -308,8 +339,6 @@ internal object WalletPreviewData {
|
|||
tokenItemVisibleState.copy(
|
||||
id = "token_2",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkBadgeIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
|
|
@ -317,8 +346,6 @@ internal object WalletPreviewData {
|
|||
tokenItemVisibleState.copy(
|
||||
id = "token_3",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkBadgeIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
|
|
@ -326,8 +353,6 @@ internal object WalletPreviewData {
|
|||
tokenItemVisibleState.copy(
|
||||
id = "token_4",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkBadgeIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
|
|
@ -336,8 +361,6 @@ internal object WalletPreviewData {
|
|||
tokenItemVisibleState.copy(
|
||||
id = "token_5",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkBadgeIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -17,16 +17,14 @@ import androidx.constraintlayout.compose.ConstrainedLayoutReference
|
|||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.ConstraintLayoutScope
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.common.component.token.TokenCryptoInfoBlock
|
||||
import com.tangem.feature.wallet.presentation.common.component.token.TokenFiatInfoBlock
|
||||
import com.tangem.feature.wallet.presentation.common.component.token.TokenIcon
|
||||
import com.tangem.feature.wallet.presentation.common.component.token.icon.TokenIcon
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
|
||||
// TODO: Add custom token state: [REDACTED_JIRA]
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
internal fun TokenItem(
|
||||
|
|
@ -90,7 +88,7 @@ private inline fun BaseContainer(
|
|||
) {
|
||||
ConstraintLayout(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
horizontal = TangemTheme.dimens.spacing14,
|
||||
vertical = TangemTheme.dimens.spacing14,
|
||||
|
|
@ -111,7 +109,6 @@ private fun Modifier.constrainAsOptionsItem(scope: ConstraintLayoutScope, ref: C
|
|||
}
|
||||
|
||||
// region preview
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_Tokens_LightTheme(@PreviewParameter(TokenConfigProvider::class) state: TokenItemState) {
|
||||
|
|
@ -136,6 +133,8 @@ private class TokenConfigProvider : CollectionPreviewParameterProvider<TokenItem
|
|||
WalletPreviewData.tokenItemHiddenState,
|
||||
WalletPreviewData.loadingTokenItemState,
|
||||
WalletPreviewData.testnetTokenItemVisibleState,
|
||||
WalletPreviewData.customTokenItemVisibleState,
|
||||
WalletPreviewData.customTestnetTokenItemVisibleState,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,152 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.CircleShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
|
||||
private const val GRAY_SCALE_SATURATION = 0f
|
||||
|
||||
@Composable
|
||||
internal fun TokenIcon(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is TokenItemState.ContentState -> ContentIcon(content = state, modifier = modifier)
|
||||
is TokenItemState.Loading -> LoadingIcon(modifier = modifier)
|
||||
is TokenItemState.Locked -> LockedIcon(modifier = modifier)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentIcon(content: TokenItemState.ContentState, modifier: Modifier = Modifier) {
|
||||
BaseContainer(modifier = modifier) {
|
||||
val isTestnet = when (content) {
|
||||
is TokenItemState.Content -> content.isTestnet
|
||||
is TokenItemState.Draggable -> content.isTestnet
|
||||
is TokenItemState.Unreachable -> false
|
||||
}
|
||||
|
||||
val colorFilter = remember(isTestnet) {
|
||||
if (isTestnet) {
|
||||
ColorFilter.colorMatrix(
|
||||
colorMatrix = ColorMatrix().apply { setToSaturation(GRAY_SCALE_SATURATION) },
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
Icon(
|
||||
content = content,
|
||||
colorFilter = colorFilter,
|
||||
modifier = Modifier.align(Alignment.BottomStart),
|
||||
)
|
||||
|
||||
NetworkBadge(
|
||||
iconResId = content.networkBadgeIconResId,
|
||||
colorFilter = colorFilter,
|
||||
modifier = Modifier.align(Alignment.TopEnd),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Icon(content: TokenItemState.ContentState, colorFilter: ColorFilter?, modifier: Modifier = Modifier) {
|
||||
val iconUrl = content.tokenIconUrl
|
||||
val iconData: Any = remember(iconUrl) {
|
||||
if (iconUrl.isNullOrEmpty()) content.tokenIconResId else iconUrl
|
||||
}
|
||||
|
||||
SubcomposeAsyncImage(
|
||||
modifier = modifier.iconSize(),
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(data = iconData)
|
||||
.placeholder(drawableResId = content.tokenIconResId)
|
||||
.error(drawableResId = content.tokenIconResId)
|
||||
.fallback(drawableResId = content.tokenIconResId)
|
||||
.crossfade(enable = true)
|
||||
.build(),
|
||||
colorFilter = colorFilter,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.NetworkBadge(
|
||||
@DrawableRes iconResId: Int?,
|
||||
colorFilter: ColorFilter?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = iconResId != null,
|
||||
modifier = modifier
|
||||
.size(TangemTheme.dimens.size18)
|
||||
.background(color = TangemTheme.colors.background.primary, shape = CircleShape),
|
||||
) {
|
||||
if (iconResId == null) return@AnimatedVisibility
|
||||
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.padding(all = TangemTheme.dimens.spacing2)
|
||||
.align(Alignment.Center),
|
||||
painter = painterResource(id = iconResId),
|
||||
colorFilter = colorFilter,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadingIcon(modifier: Modifier = Modifier) {
|
||||
BaseContainer(modifier) {
|
||||
CircleShimmer(
|
||||
modifier = Modifier
|
||||
.iconSize()
|
||||
.align(alignment = Alignment.BottomStart),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LockedIcon(modifier: Modifier = Modifier) {
|
||||
BaseContainer(modifier) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.iconSize()
|
||||
.align(Alignment.BottomStart),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.background(color = TangemTheme.colors.background.secondary, shape = CircleShape),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private inline fun BaseContainer(modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit) {
|
||||
Box(modifier = modifier.size(size = TangemTheme.dimens.size40), content = content)
|
||||
}
|
||||
|
||||
private fun Modifier.iconSize(): Modifier = composed {
|
||||
return@composed this.size(size = TangemTheme.dimens.size36)
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token.icon
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
|
||||
@Composable
|
||||
internal fun ContentIcon(icon: TokenItemState.IconState, colorFilter: ColorFilter?, modifier: Modifier = Modifier) {
|
||||
when (icon) {
|
||||
is TokenItemState.IconState.CoinIcon -> CoinIcon(
|
||||
modifier = modifier,
|
||||
url = icon.url,
|
||||
fallbackResId = icon.fallbackResId,
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
is TokenItemState.IconState.TokenIcon -> TokenIcon(
|
||||
modifier = modifier,
|
||||
url = icon.url,
|
||||
colorFilter = colorFilter,
|
||||
errorIcon = {
|
||||
CustomTokenIcon(
|
||||
modifier = modifier,
|
||||
tint = icon.fallbackTint,
|
||||
background = icon.fallbackBackground,
|
||||
)
|
||||
},
|
||||
)
|
||||
is TokenItemState.IconState.CustomTokenIcon -> CustomTokenIcon(
|
||||
modifier = modifier,
|
||||
tint = icon.tint,
|
||||
background = icon.background,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CoinIcon(
|
||||
url: String?,
|
||||
@DrawableRes fallbackResId: Int,
|
||||
colorFilter: ColorFilter?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val iconData: Any = if (url.isNullOrBlank()) fallbackResId else url
|
||||
|
||||
DefaultCurrencyIcon(
|
||||
modifier = modifier,
|
||||
iconData = iconData,
|
||||
errorIcon = {
|
||||
Image(
|
||||
painter = painterResource(id = fallbackResId),
|
||||
colorFilter = colorFilter,
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenIcon(
|
||||
url: String?,
|
||||
colorFilter: ColorFilter?,
|
||||
errorIcon: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (url == null) {
|
||||
errorIcon()
|
||||
} else {
|
||||
DefaultCurrencyIcon(
|
||||
modifier = modifier,
|
||||
iconData = url,
|
||||
errorIcon = errorIcon,
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomTokenIcon(tint: Color, background: Color, modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = background,
|
||||
shape = CircleShape,
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.matchParentSize(),
|
||||
painter = painterResource(id = R.drawable.ic_custom_token_44),
|
||||
tint = tint,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private inline fun DefaultCurrencyIcon(
|
||||
iconData: Any,
|
||||
colorFilter: ColorFilter?,
|
||||
crossinline errorIcon: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
SubcomposeAsyncImage(
|
||||
modifier = modifier,
|
||||
model = ImageRequest.Builder(context = LocalContext.current)
|
||||
.data(iconData)
|
||||
.crossfade(enable = true)
|
||||
.build(),
|
||||
loading = { LoadingIcon() },
|
||||
error = { errorIcon() },
|
||||
colorFilter = colorFilter,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token.icon
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
||||
@Composable
|
||||
internal fun NetworkBadge(@DrawableRes iconResId: Int, colorFilter: ColorFilter?, modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(TangemTheme.dimens.size18)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = CircleShape,
|
||||
),
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.padding(all = TangemTheme.dimens.spacing2)
|
||||
.matchParentSize(),
|
||||
painter = painterResource(id = iconResId),
|
||||
colorFilter = colorFilter,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun CustomBadge(modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(TangemTheme.dimens.size12)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = CircleShape,
|
||||
),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(all = TangemTheme.dimens.spacing2)
|
||||
.matchParentSize()
|
||||
.background(
|
||||
color = TangemTheme.colors.icon.informative,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package com.tangem.feature.wallet.presentation.common.component.token.icon
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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
|
||||
|
||||
private const val GRAY_SCALE_SATURATION = 0f
|
||||
|
||||
@Composable
|
||||
internal fun TokenIcon(state: TokenItemState, 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun LoadingIcon(modifier: Modifier = Modifier) {
|
||||
CircleShimmer(modifier = modifier)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LockedIcon(modifier: Modifier = Modifier) {
|
||||
Box(modifier = modifier) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.background(
|
||||
color = TangemTheme.colors.background.secondary,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.ContentIconContainer(icon: TokenItemState.IconState, modifier: Modifier = Modifier) {
|
||||
val networkBadgeOffset = TangemTheme.dimens.spacing4
|
||||
val colorFilter = remember(icon.isGrayscale) {
|
||||
if (icon.isGrayscale) {
|
||||
ColorFilter.colorMatrix(
|
||||
colorMatrix = ColorMatrix().apply { setToSaturation(GRAY_SCALE_SATURATION) },
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
ContentIcon(
|
||||
modifier = modifier,
|
||||
icon = icon,
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
|
||||
if (icon.networkBadgeIconResId != null) {
|
||||
NetworkBadge(
|
||||
modifier = Modifier
|
||||
.offset(x = networkBadgeOffset, y = -networkBadgeOffset)
|
||||
.align(Alignment.TopEnd),
|
||||
iconResId = requireNotNull(icon.networkBadgeIconResId),
|
||||
colorFilter = colorFilter,
|
||||
)
|
||||
}
|
||||
|
||||
if (icon is TokenItemState.IconState.CustomTokenIcon) {
|
||||
CustomBadge(modifier = Modifier.align(Alignment.BottomEnd))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private inline fun BaseContainer(modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit) {
|
||||
Box(modifier = modifier.size(size = TangemTheme.dimens.size40), content = content)
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ 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.PriceChangeConfig
|
||||
|
||||
/** Token item state */
|
||||
|
|
@ -18,80 +19,120 @@ internal sealed interface TokenItemState {
|
|||
data class Locked(override val id: String) : TokenItemState
|
||||
|
||||
/** Content state */
|
||||
sealed class ContentState(
|
||||
override val id: String,
|
||||
open val tokenIconUrl: String?,
|
||||
@DrawableRes open val tokenIconResId: Int,
|
||||
@DrawableRes open val networkBadgeIconResId: Int?,
|
||||
open val name: String,
|
||||
) : TokenItemState
|
||||
sealed class ContentState : TokenItemState {
|
||||
|
||||
abstract val icon: IconState
|
||||
abstract val name: String
|
||||
}
|
||||
|
||||
/**
|
||||
* Content token state
|
||||
*
|
||||
* @property id unique id
|
||||
* @property tokenIconUrl token icon url
|
||||
* @property tokenIconResId token icon resource id
|
||||
* @property networkBadgeIconResId network badge icon resource id, may be null if it is a coin
|
||||
* @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 isTestnet indicates whether the token is from test network or not
|
||||
* @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 tokenIconUrl: String?,
|
||||
@DrawableRes override val tokenIconResId: Int,
|
||||
@DrawableRes override val networkBadgeIconResId: Int?,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
val amount: String,
|
||||
val hasPending: Boolean,
|
||||
val tokenOptions: TokenOptionsState,
|
||||
val isTestnet: Boolean,
|
||||
val onItemClick: () -> Unit,
|
||||
val onItemLongClick: () -> Unit,
|
||||
) : ContentState(id, tokenIconUrl, tokenIconResId, networkBadgeIconResId, name)
|
||||
) : ContentState()
|
||||
|
||||
/**
|
||||
* Draggable token state
|
||||
*
|
||||
* @property id unique id
|
||||
* @property tokenIconUrl token icon url
|
||||
* @property tokenIconResId token icon resource id
|
||||
* @property networkBadgeIconResId network badge icon resource id, may be null if it is a coin
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
* @property fiatAmount fiat amount of token
|
||||
* @property isTestnet indicates whether the token is from test network or not
|
||||
*/
|
||||
data class Draggable(
|
||||
override val id: String,
|
||||
override val tokenIconUrl: String?,
|
||||
@DrawableRes override val tokenIconResId: Int,
|
||||
@DrawableRes override val networkBadgeIconResId: Int?,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
val fiatAmount: String,
|
||||
val isTestnet: Boolean,
|
||||
) : ContentState(id, tokenIconUrl, tokenIconResId, networkBadgeIconResId, name)
|
||||
) : ContentState()
|
||||
|
||||
/**
|
||||
* Unreachable token state
|
||||
*
|
||||
* @property id token id
|
||||
* @property tokenIconUrl token icon url
|
||||
* @property tokenIconResId token icon resource id
|
||||
* @property networkBadgeIconResId network badge icon resource id, may be null if it is a coin
|
||||
* @property icon token icon state
|
||||
* @property name token name
|
||||
*/
|
||||
data class Unreachable(
|
||||
override val id: String,
|
||||
override val tokenIconUrl: String?,
|
||||
@DrawableRes override val tokenIconResId: Int,
|
||||
@DrawableRes override val networkBadgeIconResId: Int?,
|
||||
override val icon: IconState,
|
||||
override val name: String,
|
||||
) : ContentState(id, tokenIconUrl, tokenIconResId, networkBadgeIconResId, name)
|
||||
) : ContentState()
|
||||
|
||||
/**
|
||||
* Represents the various states an icon can be in.
|
||||
*/
|
||||
@Immutable
|
||||
sealed class IconState {
|
||||
|
||||
abstract val networkBadgeIconResId: Int?
|
||||
abstract val isGrayscale: Boolean
|
||||
|
||||
/**
|
||||
* Represents a coin icon.
|
||||
*
|
||||
* @property url The URL where the coin icon can be fetched from. May be `null` if not found.
|
||||
* @property fallbackResId The drawable resource ID to be used as a fallback if the URL is not available.
|
||||
* @property isGrayscale Specifies whether to show the icon in grayscale.
|
||||
*/
|
||||
data class CoinIcon(
|
||||
val url: String?,
|
||||
@DrawableRes val fallbackResId: Int,
|
||||
override val isGrayscale: Boolean,
|
||||
) : IconState() {
|
||||
|
||||
override val networkBadgeIconResId: Int? = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a token icon.
|
||||
*
|
||||
* @property url The URL where the token icon can be fetched from. May be `null` if not found.
|
||||
* @property networkBadgeIconResId The drawable resource ID for the network badge.
|
||||
* @property isGrayscale Specifies whether to show the icon in grayscale.
|
||||
* @property fallbackTint The color to be used for tinting the fallback icon.
|
||||
* @property fallbackBackground The background color to be used for the fallback icon.
|
||||
*/
|
||||
data class TokenIcon(
|
||||
val url: String?,
|
||||
@DrawableRes override val networkBadgeIconResId: Int,
|
||||
override val isGrayscale: Boolean,
|
||||
val fallbackTint: Color,
|
||||
val fallbackBackground: Color,
|
||||
) : IconState()
|
||||
|
||||
/**
|
||||
* Represents a custom token icon.
|
||||
*
|
||||
* @property tint The color to be used for tinting the icon.
|
||||
* @property background The background color to be used for the icon.
|
||||
* @property networkBadgeIconResId The drawable resource ID for the network badge.
|
||||
* @property isGrayscale Specifies whether to show the icon in grayscale.
|
||||
*/
|
||||
data class CustomTokenIcon(
|
||||
val tint: Color,
|
||||
val background: Color,
|
||||
@DrawableRes override val networkBadgeIconResId: Int,
|
||||
override val isGrayscale: Boolean,
|
||||
) : IconState()
|
||||
}
|
||||
|
||||
/** Token options state */
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package com.tangem.feature.wallet.presentation.common.utils
|
||||
|
||||
import com.tangem.core.ui.extensions.getTintForTokenIcon
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.core.ui.extensions.tryGetBackgroundForTokenIcon
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class CryptoCurrencyToIconStateConverter : Converter<CryptoCurrency, TokenItemState.IconState> {
|
||||
|
||||
override fun convert(value: CryptoCurrency): TokenItemState.IconState {
|
||||
return when (value) {
|
||||
is CryptoCurrency.Coin -> getIconStateForCoin(value)
|
||||
is CryptoCurrency.Token -> getIconStateForToken(value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getIconStateForCoin(coin: CryptoCurrency.Coin): TokenItemState.IconState.CoinIcon {
|
||||
return TokenItemState.IconState.CoinIcon(
|
||||
url = coin.iconUrl,
|
||||
fallbackResId = coin.networkIconResId,
|
||||
isGrayscale = coin.network.isTestnet,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getIconStateForToken(token: CryptoCurrency.Token): TokenItemState.IconState {
|
||||
val background = token.tryGetBackgroundForTokenIcon()
|
||||
val tint = getTintForTokenIcon(background)
|
||||
|
||||
return if (token.isCustom) {
|
||||
TokenItemState.IconState.CustomTokenIcon(
|
||||
tint = tint,
|
||||
background = background,
|
||||
networkBadgeIconResId = token.networkIconResId,
|
||||
isGrayscale = token.network.isTestnet,
|
||||
)
|
||||
} else {
|
||||
TokenItemState.IconState.TokenIcon(
|
||||
url = token.iconUrl,
|
||||
networkBadgeIconResId = token.networkIconResId,
|
||||
isGrayscale = token.network.isTestnet,
|
||||
fallbackTint = tint,
|
||||
fallbackBackground = background,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
|
|
@ -37,7 +39,10 @@ import com.tangem.feature.wallet.presentation.common.component.TokenItem
|
|||
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
|
||||
import org.burnoutcrew.reorderable.*
|
||||
import org.burnoutcrew.reorderable.ReorderableItem
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.rememberReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.reorderable
|
||||
|
||||
@Composable
|
||||
internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier = Modifier) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.core.ui.extensions.networkBadgeIconResId
|
||||
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.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.utils.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getTokenItemId
|
||||
|
|
@ -16,6 +15,8 @@ internal class CryptoCurrencyToDraggableItemConverter(
|
|||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
) : Converter<CryptoCurrencyStatus, DraggableItem.Token> {
|
||||
|
||||
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
|
||||
|
||||
override fun convert(value: CryptoCurrencyStatus): DraggableItem.Token {
|
||||
return createDraggableToken(value, appCurrencyProvider())
|
||||
}
|
||||
|
|
@ -44,12 +45,9 @@ internal class CryptoCurrencyToDraggableItemConverter(
|
|||
|
||||
return TokenItemState.Draggable(
|
||||
id = getTokenItemId(currency.id),
|
||||
tokenIconUrl = currency.iconUrl,
|
||||
tokenIconResId = currencyStatus.currency.iconResId,
|
||||
networkBadgeIconResId = currencyStatus.currency.networkBadgeIconResId,
|
||||
icon = iconStateConverter.convert(currency),
|
||||
name = currency.name,
|
||||
fiatAmount = getFormattedFiatAmount(currencyStatus, appCurrency),
|
||||
isTestnet = currencyStatus.currency.network.isTestnet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ package com.tangem.feature.wallet.presentation.wallet.utils
|
|||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.core.ui.extensions.networkBadgeIconResId
|
||||
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.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.utils.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
|
||||
import com.tangem.utils.converter.Converter
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -18,6 +17,8 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
) : Converter<CryptoCurrencyStatus, TokenItemState> {
|
||||
|
||||
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
|
||||
|
||||
override fun convert(value: CryptoCurrencyStatus): TokenItemState {
|
||||
return when (value.value) {
|
||||
is CryptoCurrencyStatus.Loading -> TokenItemState.Loading(id = value.currency.id.value)
|
||||
|
|
@ -37,9 +38,7 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
return TokenItemState.Content(
|
||||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
tokenIconUrl = currency.iconUrl,
|
||||
tokenIconResId = currency.iconResId,
|
||||
networkBadgeIconResId = currency.networkBadgeIconResId,
|
||||
icon = iconStateConverter.convert(currency),
|
||||
amount = getFormattedAmount(),
|
||||
hasPending = value.hasCurrentNetworkTransactions,
|
||||
tokenOptions = if (isWalletContentHidden) {
|
||||
|
|
@ -50,7 +49,6 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
config = getPriceChangeConfig(),
|
||||
)
|
||||
},
|
||||
isTestnet = currency.network.isTestnet,
|
||||
onItemClick = { clickIntents.onTokenItemClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(currency) },
|
||||
)
|
||||
|
|
@ -72,9 +70,7 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
private fun CryptoCurrencyStatus.mapToUnreachableTokenItemState() = TokenItemState.Unreachable(
|
||||
id = currency.id.value,
|
||||
name = currency.name,
|
||||
tokenIconUrl = currency.iconUrl,
|
||||
tokenIconResId = currency.iconResId,
|
||||
networkBadgeIconResId = currency.networkBadgeIconResId,
|
||||
icon = iconStateConverter.convert(currency),
|
||||
)
|
||||
|
||||
private fun CryptoCurrencyStatus.getPriceChangeConfig(): PriceChangeConfig {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue