Updated on 2026-08-14
This commit is contained in:
parent
9836b18ff4
commit
050c7b6106
13 changed files with 369 additions and 222 deletions
|
|
@ -2,12 +2,21 @@ package com.tangem.core.ui.components.account
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.compose.animation.animateContentSize
|
||||||
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
|
@ -15,7 +24,9 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import com.tangem.core.ui.R
|
import com.tangem.core.ui.R
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
|
|
@ -36,14 +47,28 @@ enum class AccountIconSize {
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun AccountResIcon(@DrawableRes resId: Int, color: Color, size: AccountIconSize, modifier: Modifier = Modifier) {
|
fun AccountResIcon(@DrawableRes resId: Int, color: Color, size: AccountIconSize, modifier: Modifier = Modifier) {
|
||||||
val boxModifier = modifier.selectBoxModifier(size)
|
val boxSize by animateDpAsState(
|
||||||
val iconSize = Modifier.selectIconSize(size)
|
targetValue = size.boxSizeInDp(),
|
||||||
|
animationSpec = animation(),
|
||||||
|
)
|
||||||
|
val boxShapeCornerSize by animateDpAsState(
|
||||||
|
targetValue = size.boxShapeSizeInDp(),
|
||||||
|
animationSpec = animation(),
|
||||||
|
)
|
||||||
|
val iconSize by animateDpAsState(
|
||||||
|
targetValue = size.iconSizeInDp(),
|
||||||
|
animationSpec = animation(),
|
||||||
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = boxModifier.background(color),
|
modifier = modifier
|
||||||
|
.size(boxSize)
|
||||||
|
.clip(RoundedCornerShape(boxShapeCornerSize))
|
||||||
|
.background(color),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = iconSize,
|
modifier = Modifier.size(iconSize),
|
||||||
tint = TangemTheme.colors.text.constantWhite,
|
tint = TangemTheme.colors.text.constantWhite,
|
||||||
imageVector = ImageVector.vectorResource(id = resId),
|
imageVector = ImageVector.vectorResource(id = resId),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
|
|
@ -64,7 +89,14 @@ fun AccountResIcon(@DrawableRes resId: Int, color: Color, size: AccountIconSize,
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun AccountCharIcon(char: Char, color: Color, size: AccountIconSize, modifier: Modifier = Modifier) {
|
fun AccountCharIcon(char: Char, color: Color, size: AccountIconSize, modifier: Modifier = Modifier) {
|
||||||
val boxModifier = modifier.selectBoxModifier(size)
|
val boxSize by animateDpAsState(
|
||||||
|
size.boxSizeInDp(),
|
||||||
|
animationSpec = animation(),
|
||||||
|
)
|
||||||
|
val boxShapeCornerSize by animateDpAsState(
|
||||||
|
size.boxShapeSizeInDp(),
|
||||||
|
animationSpec = animation(),
|
||||||
|
)
|
||||||
val textStyle = when (size) {
|
val textStyle = when (size) {
|
||||||
AccountIconSize.Default -> TangemTheme.typography.h3
|
AccountIconSize.Default -> TangemTheme.typography.h3
|
||||||
AccountIconSize.Large -> TangemTheme.typography.h1
|
AccountIconSize.Large -> TangemTheme.typography.h1
|
||||||
|
|
@ -72,32 +104,52 @@ fun AccountCharIcon(char: Char, color: Color, size: AccountIconSize, modifier: M
|
||||||
AccountIconSize.Small -> TangemTheme.typography.subtitle2
|
AccountIconSize.Small -> TangemTheme.typography.subtitle2
|
||||||
AccountIconSize.ExtraSmall -> TangemTheme.typography.caption1
|
AccountIconSize.ExtraSmall -> TangemTheme.typography.caption1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val textSize by animateFloatAsState(
|
||||||
|
textStyle.fontSize.value,
|
||||||
|
animationSpec = animation(),
|
||||||
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
modifier = boxModifier.background(color),
|
modifier = modifier
|
||||||
|
.size(boxSize)
|
||||||
|
.clip(RoundedCornerShape(boxShapeCornerSize))
|
||||||
|
.background(color),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier.animateContentSize(animationSpec = animation()),
|
||||||
text = char.uppercase(),
|
text = char.uppercase(),
|
||||||
style = textStyle,
|
style = textStyle.copy(fontSize = textSize.sp),
|
||||||
color = TangemTheme.colors.text.constantWhite,
|
color = TangemTheme.colors.text.constantWhite,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Modifier.selectIconSize(size: AccountIconSize): Modifier = when (size) {
|
private fun <T> animation() = tween<T>(durationMillis = 350)
|
||||||
AccountIconSize.Default -> this.size(20.dp)
|
|
||||||
AccountIconSize.Large -> this.size(40.dp)
|
private fun AccountIconSize.iconSizeInDp(): Dp = when (this) {
|
||||||
AccountIconSize.Medium -> this.size(16.dp)
|
AccountIconSize.Default -> 20.dp
|
||||||
AccountIconSize.Small -> this.size(12.dp)
|
AccountIconSize.Large -> 40.dp
|
||||||
AccountIconSize.ExtraSmall -> this.size(8.dp)
|
AccountIconSize.Medium -> 16.dp
|
||||||
|
AccountIconSize.Small -> 12.dp
|
||||||
|
AccountIconSize.ExtraSmall -> 8.dp
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Modifier.selectBoxModifier(size: AccountIconSize): Modifier = when (size) {
|
private fun AccountIconSize.boxSizeInDp(): Dp = when (this) {
|
||||||
AccountIconSize.Default -> size(36.dp).clip(RoundedCornerShape(10.dp))
|
AccountIconSize.Default -> 36.dp
|
||||||
AccountIconSize.Large -> size(88.dp).clip(RoundedCornerShape(24.dp))
|
AccountIconSize.Large -> 88.dp
|
||||||
AccountIconSize.Medium -> size(28.dp).clip(RoundedCornerShape(8.dp))
|
AccountIconSize.Medium -> 28.dp
|
||||||
AccountIconSize.Small -> size(20.dp).clip(RoundedCornerShape(6.dp))
|
AccountIconSize.Small -> 20.dp
|
||||||
AccountIconSize.ExtraSmall -> size(14.dp).clip(RoundedCornerShape(4.dp))
|
AccountIconSize.ExtraSmall -> 14.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AccountIconSize.boxShapeSizeInDp(): Dp = when (this) {
|
||||||
|
AccountIconSize.Default -> 10.dp
|
||||||
|
AccountIconSize.Large -> 24.dp
|
||||||
|
AccountIconSize.Medium -> 8.dp
|
||||||
|
AccountIconSize.Small -> 6.dp
|
||||||
|
AccountIconSize.ExtraSmall -> 4.dp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
|
|
@ -115,7 +167,20 @@ private fun Preview() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Sample() {
|
private fun Sample() {
|
||||||
|
var sizeState by remember { mutableStateOf(AccountIconSize.ExtraSmall) }
|
||||||
|
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
|
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
|
||||||
|
AccountResIcon(resId = R.drawable.ic_shirt_24, color = Color.Red, size = sizeState)
|
||||||
|
Button(onClick = {
|
||||||
|
sizeState = when (sizeState) {
|
||||||
|
AccountIconSize.Default -> AccountIconSize.Large
|
||||||
|
AccountIconSize.Large -> AccountIconSize.Medium
|
||||||
|
AccountIconSize.Medium -> AccountIconSize.Small
|
||||||
|
AccountIconSize.Small -> AccountIconSize.ExtraSmall
|
||||||
|
AccountIconSize.ExtraSmall -> AccountIconSize.Default
|
||||||
|
}
|
||||||
|
}) { Text("Change") }
|
||||||
|
|
||||||
AccountResIcon(resId = R.drawable.ic_shirt_24, color = Color.Red, size = AccountIconSize.Default)
|
AccountResIcon(resId = R.drawable.ic_shirt_24, color = Color.Red, size = AccountIconSize.Default)
|
||||||
AccountResIcon(resId = R.drawable.ic_rounded_star_24, color = Color.Blue, size = AccountIconSize.Large)
|
AccountResIcon(resId = R.drawable.ic_rounded_star_24, color = Color.Blue, size = AccountIconSize.Large)
|
||||||
AccountResIcon(resId = R.drawable.ic_user_24, color = Color.Magenta, size = AccountIconSize.Medium)
|
AccountResIcon(resId = R.drawable.ic_user_24, color = Color.Magenta, size = AccountIconSize.Medium)
|
||||||
|
|
@ -123,6 +188,7 @@ private fun Sample() {
|
||||||
AccountResIcon(resId = R.drawable.ic_wallet_24, color = Color.Green, size = AccountIconSize.ExtraSmall)
|
AccountResIcon(resId = R.drawable.ic_wallet_24, color = Color.Green, size = AccountIconSize.ExtraSmall)
|
||||||
}
|
}
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
|
Column(verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8)) {
|
||||||
|
AccountCharIcon(char = 'D', color = Color.Red, size = sizeState)
|
||||||
AccountCharIcon(char = 'D', color = Color.Red, size = AccountIconSize.Default)
|
AccountCharIcon(char = 'D', color = Color.Red, size = AccountIconSize.Default)
|
||||||
AccountCharIcon(char = 'L', color = Color.Blue, size = AccountIconSize.Large)
|
AccountCharIcon(char = 'L', color = Color.Blue, size = AccountIconSize.Large)
|
||||||
AccountCharIcon(char = 'M', color = Color.Magenta, size = AccountIconSize.Medium)
|
AccountCharIcon(char = 'M', color = Color.Magenta, size = AccountIconSize.Medium)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import com.tangem.core.ui.R
|
import com.tangem.core.ui.R
|
||||||
import com.tangem.core.ui.components.account.AccountCharIcon
|
import com.tangem.core.ui.components.account.AccountCharIcon
|
||||||
import com.tangem.core.ui.components.account.AccountIconSize
|
|
||||||
import com.tangem.core.ui.components.account.AccountResIcon
|
import com.tangem.core.ui.components.account.AccountResIcon
|
||||||
import com.tangem.core.ui.components.currency.DefaultCurrencyIcon
|
import com.tangem.core.ui.components.currency.DefaultCurrencyIcon
|
||||||
import com.tangem.core.ui.extensions.resolveReference
|
import com.tangem.core.ui.extensions.resolveReference
|
||||||
|
|
@ -66,13 +65,13 @@ internal fun ContentIcon(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
resId = icon.resId,
|
resId = icon.resId,
|
||||||
color = icon.color,
|
color = icon.color,
|
||||||
size = AccountIconSize.Default,
|
size = icon.size,
|
||||||
)
|
)
|
||||||
is CurrencyIconState.CryptoPortfolio.Letter -> AccountCharIcon(
|
is CurrencyIconState.CryptoPortfolio.Letter -> AccountCharIcon(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
char = icon.char.resolveReference().first(),
|
char = icon.char.resolveReference().first(),
|
||||||
color = icon.color,
|
color = icon.color,
|
||||||
size = AccountIconSize.Default,
|
size = icon.size,
|
||||||
)
|
)
|
||||||
CurrencyIconState.Loading,
|
CurrencyIconState.Loading,
|
||||||
CurrencyIconState.Locked,
|
CurrencyIconState.Locked,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.components.CircleShimmer
|
import com.tangem.core.ui.components.CircleShimmer
|
||||||
|
import com.tangem.core.ui.extensions.conditional
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.utils.getGreyScaleColorFilter
|
import com.tangem.core.ui.utils.getGreyScaleColorFilter
|
||||||
|
|
||||||
|
|
@ -33,12 +34,20 @@ fun CurrencyIcon(
|
||||||
state: CurrencyIconState,
|
state: CurrencyIconState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
shouldDisplayNetwork: Boolean = true,
|
shouldDisplayNetwork: Boolean = true,
|
||||||
|
withFixedSize: Boolean = true,
|
||||||
iconSize: Dp = 36.dp,
|
iconSize: Dp = 36.dp,
|
||||||
) {
|
) {
|
||||||
BaseContainer(modifier = modifier) {
|
Box(
|
||||||
|
modifier = modifier
|
||||||
|
.conditional(withFixedSize) {
|
||||||
|
size(size = 40.dp)
|
||||||
|
},
|
||||||
|
) {
|
||||||
val iconModifier = Modifier
|
val iconModifier = Modifier
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
.size(iconSize)
|
.conditional(withFixedSize) {
|
||||||
|
size(iconSize)
|
||||||
|
}
|
||||||
|
|
||||||
when (state) {
|
when (state) {
|
||||||
is CurrencyIconState.Loading -> LoadingIcon(modifier = iconModifier)
|
is CurrencyIconState.Loading -> LoadingIcon(modifier = iconModifier)
|
||||||
|
|
@ -132,9 +141,4 @@ private fun BoxScope.ContentIconContainer(
|
||||||
modifier = Modifier.align(Alignment.BottomEnd),
|
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)
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.annotation.DrawableRes
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import com.tangem.core.ui.R
|
import com.tangem.core.ui.R
|
||||||
|
import com.tangem.core.ui.components.account.AccountIconSize
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -92,17 +93,20 @@ sealed class CurrencyIconState {
|
||||||
override val shouldShowCustomBadge: Boolean = false
|
override val shouldShowCustomBadge: Boolean = false
|
||||||
override val topBadgeIconResId: Int? = null
|
override val topBadgeIconResId: Int? = null
|
||||||
abstract val color: Color
|
abstract val color: Color
|
||||||
|
abstract val size: AccountIconSize
|
||||||
|
|
||||||
data class Icon(
|
data class Icon(
|
||||||
@DrawableRes val resId: Int,
|
@DrawableRes val resId: Int,
|
||||||
override val color: Color,
|
override val color: Color,
|
||||||
override val isGrayscale: Boolean,
|
override val isGrayscale: Boolean,
|
||||||
|
override val size: AccountIconSize = AccountIconSize.Default,
|
||||||
) : CryptoPortfolio()
|
) : CryptoPortfolio()
|
||||||
|
|
||||||
data class Letter(
|
data class Letter(
|
||||||
val char: TextReference,
|
val char: TextReference,
|
||||||
override val color: Color,
|
override val color: Color,
|
||||||
override val isGrayscale: Boolean,
|
override val isGrayscale: Boolean,
|
||||||
|
override val size: AccountIconSize = AccountIconSize.Default,
|
||||||
) : CryptoPortfolio()
|
) : CryptoPortfolio()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.composed
|
import androidx.compose.ui.composed
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
@ -31,6 +32,7 @@ import com.tangem.core.ui.components.token.state.TokenItemState
|
||||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
||||||
import com.tangem.core.ui.components.token.state.TokenItemState.Subtitle2State
|
import com.tangem.core.ui.components.token.state.TokenItemState.Subtitle2State
|
||||||
import com.tangem.core.ui.components.token.state.TokenItemState.PromoBannerState
|
import com.tangem.core.ui.components.token.state.TokenItemState.PromoBannerState
|
||||||
|
import com.tangem.core.ui.components.token.state.TokenItemState.TitleState
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
import com.tangem.core.ui.extensions.rememberHapticFeedback
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
|
@ -65,6 +67,7 @@ fun TokenItem(
|
||||||
state: TokenItemState,
|
state: TokenItemState,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
composables: TokenItemComposables? = null,
|
||||||
itemPaddingValues: PaddingValues = PaddingValues(horizontal = TangemTheme.dimens.spacing12),
|
itemPaddingValues: PaddingValues = PaddingValues(horizontal = TangemTheme.dimens.spacing12),
|
||||||
) {
|
) {
|
||||||
TokenItem(
|
TokenItem(
|
||||||
|
|
@ -73,9 +76,16 @@ fun TokenItem(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
reorderableTokenListState = null,
|
reorderableTokenListState = null,
|
||||||
itemPaddingValues = itemPaddingValues,
|
itemPaddingValues = itemPaddingValues,
|
||||||
|
composables = composables,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
class TokenItemComposables(
|
||||||
|
val title: @Composable (Modifier) -> Unit,
|
||||||
|
val icon: @Composable (Modifier) -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Token item for reorderable list
|
* Token item for reorderable list
|
||||||
*
|
*
|
||||||
|
|
@ -88,6 +98,7 @@ fun TokenItem(
|
||||||
* @see <a href = "https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=1051-866&t=ew8mbGp2lacuJfFm-4"
|
* @see <a href = "https://www.figma.com/design/14ISV23YB1yVW1uNVwqrKv/Android?node-id=1051-866&t=ew8mbGp2lacuJfFm-4"
|
||||||
* >Figma Component</a>
|
* >Figma Component</a>
|
||||||
*/
|
*/
|
||||||
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun TokenItem(
|
fun TokenItem(
|
||||||
state: TokenItemState,
|
state: TokenItemState,
|
||||||
|
|
@ -95,6 +106,7 @@ fun TokenItem(
|
||||||
reorderableTokenListState: ReorderableLazyListState?,
|
reorderableTokenListState: ReorderableLazyListState?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
itemPaddingValues: PaddingValues = PaddingValues(horizontal = TangemTheme.dimens.spacing12),
|
itemPaddingValues: PaddingValues = PaddingValues(horizontal = TangemTheme.dimens.spacing12),
|
||||||
|
composables: TokenItemComposables? = null,
|
||||||
) {
|
) {
|
||||||
val betweenRowsMargin = TangemTheme.dimens.spacing2
|
val betweenRowsMargin = TangemTheme.dimens.spacing2
|
||||||
|
|
||||||
|
|
@ -104,13 +116,22 @@ fun TokenItem(
|
||||||
.tokenClickable(state = state)
|
.tokenClickable(state = state)
|
||||||
.padding(itemPaddingValues),
|
.padding(itemPaddingValues),
|
||||||
) {
|
) {
|
||||||
CurrencyIcon(
|
if (composables != null) {
|
||||||
state = state.iconState,
|
composables.icon.invoke(
|
||||||
modifier = Modifier
|
Modifier
|
||||||
.layoutId(layoutId = LayoutId.ICON)
|
.layoutId(layoutId = LayoutId.ICON)
|
||||||
.padding(end = TangemTheme.dimens.spacing8)
|
.padding(end = TangemTheme.dimens.spacing8)
|
||||||
.testTag(TokenElementsTestTags.TOKEN_ICON),
|
.testTag(TokenElementsTestTags.TOKEN_ICON),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
CurrencyIcon(
|
||||||
|
state = state.iconState,
|
||||||
|
modifier = Modifier
|
||||||
|
.layoutId(layoutId = LayoutId.ICON)
|
||||||
|
.padding(end = TangemTheme.dimens.spacing8)
|
||||||
|
.testTag(TokenElementsTestTags.TOKEN_ICON),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
YieldSupplyPromoBanner(
|
YieldSupplyPromoBanner(
|
||||||
state = state.promoBannerState,
|
state = state.promoBannerState,
|
||||||
|
|
@ -120,14 +141,24 @@ fun TokenItem(
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
)
|
)
|
||||||
|
|
||||||
TokenTitle(
|
if (composables != null) {
|
||||||
state = state.titleState,
|
composables.title.invoke(
|
||||||
modifier = Modifier
|
Modifier
|
||||||
.layoutId(layoutId = LayoutId.TITLE)
|
.layoutId(layoutId = LayoutId.TITLE)
|
||||||
.padding(end = TangemTheme.dimens.spacing8)
|
.padding(end = TangemTheme.dimens.spacing8)
|
||||||
.padding(bottom = betweenRowsMargin)
|
.padding(bottom = betweenRowsMargin)
|
||||||
.testTag(TokenElementsTestTags.TOKEN_TITLE),
|
.testTag(TokenElementsTestTags.TOKEN_TITLE),
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
TokenTitle(
|
||||||
|
state = state.titleState,
|
||||||
|
modifier = Modifier
|
||||||
|
.layoutId(layoutId = LayoutId.TITLE)
|
||||||
|
.padding(end = TangemTheme.dimens.spacing8)
|
||||||
|
.padding(bottom = betweenRowsMargin)
|
||||||
|
.testTag(TokenElementsTestTags.TOKEN_TITLE),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
TokenFiatAmount(
|
TokenFiatAmount(
|
||||||
state = state.fiatAmountState,
|
state = state.fiatAmountState,
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.components.token.state.TokenItemState.TitleState as TokenTitleState
|
import com.tangem.core.ui.components.token.state.TokenItemState.TitleState as TokenTitleState
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun TokenTitle(state: TokenTitleState?, modifier: Modifier = Modifier) {
|
fun TokenTitle(state: TokenTitleState?, modifier: Modifier = Modifier) {
|
||||||
when (state) {
|
when (state) {
|
||||||
is TokenTitleState.Content -> {
|
is TokenTitleState.Content -> {
|
||||||
ContentTitle(state = state, modifier = modifier)
|
ContentTitle(state = state, modifier = modifier)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
package com.tangem.core.ui.components.tokenlist
|
package com.tangem.core.ui.components.tokenlist
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedContent
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.BoundsTransform
|
||||||
|
import androidx.compose.animation.SharedTransitionLayout
|
||||||
|
import androidx.compose.animation.SharedTransitionScope
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.togetherWith
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
|
@ -18,9 +25,12 @@ import com.tangem.core.ui.components.SpacerW4
|
||||||
import com.tangem.core.ui.components.account.AccountCharIcon
|
import com.tangem.core.ui.components.account.AccountCharIcon
|
||||||
import com.tangem.core.ui.components.account.AccountIconSize
|
import com.tangem.core.ui.components.account.AccountIconSize
|
||||||
import com.tangem.core.ui.components.account.AccountResIcon
|
import com.tangem.core.ui.components.account.AccountResIcon
|
||||||
|
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||||
import com.tangem.core.ui.components.fields.SearchBar
|
import com.tangem.core.ui.components.fields.SearchBar
|
||||||
import com.tangem.core.ui.components.token.TokenItem
|
import com.tangem.core.ui.components.token.TokenItem
|
||||||
|
import com.tangem.core.ui.components.token.TokenItemComposables
|
||||||
|
import com.tangem.core.ui.components.token.internal.TokenTitle
|
||||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||||
import com.tangem.core.ui.components.tokenlist.internal.GroupTitleItem
|
import com.tangem.core.ui.components.tokenlist.internal.GroupTitleItem
|
||||||
import com.tangem.core.ui.components.tokenlist.state.PortfolioTokensListItemUM
|
import com.tangem.core.ui.components.tokenlist.state.PortfolioTokensListItemUM
|
||||||
|
|
@ -57,16 +67,80 @@ fun TokenListItem(state: TokensListItemUM, isBalanceHidden: Boolean, modifier: M
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber", "ReusedModifierInstance")
|
||||||
@Composable
|
@Composable
|
||||||
fun PortfolioListItem(state: TokensListItemUM.Portfolio, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
|
fun PortfolioListItem(state: TokensListItemUM.Portfolio, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
|
||||||
if (state.isExpanded) {
|
// Box is not needed here, but due to a bug in compose
|
||||||
ExpandedPortfolioHeader(state = state.tokenItemUM, isCollapsable = state.isCollapsable, modifier = modifier)
|
// we use it like a wrapper to properly handle lookahead scope inside this composable
|
||||||
} else {
|
Box(modifier) {
|
||||||
TokenItem(
|
SharedTransitionLayout {
|
||||||
state = state.tokenItemUM,
|
AnimatedContent(
|
||||||
isBalanceHidden = isBalanceHidden,
|
state.isExpanded,
|
||||||
modifier = modifier,
|
transitionSpec = {
|
||||||
)
|
fadeIn(animationSpec = tween(350, delayMillis = 90))
|
||||||
|
.togetherWith(fadeOut(animationSpec = tween(350)))
|
||||||
|
},
|
||||||
|
) { isExpanded ->
|
||||||
|
val animatedContentScope = this
|
||||||
|
val iconSharedContentState = rememberSharedContentState(key = "icon")
|
||||||
|
val titleSharedContentState = rememberSharedContentState(key = "title")
|
||||||
|
val boundsTransform = BoundsTransform { _, _ -> tween(350) }
|
||||||
|
|
||||||
|
val composables =
|
||||||
|
TokenItemComposables(
|
||||||
|
icon = { modifier: Modifier ->
|
||||||
|
val iconState = when (val icon = state.tokenItemUM.iconState) {
|
||||||
|
is CurrencyIconState.CryptoPortfolio.Icon ->
|
||||||
|
icon.copy(
|
||||||
|
size = if (isExpanded) AccountIconSize.ExtraSmall else AccountIconSize.Default,
|
||||||
|
)
|
||||||
|
is CurrencyIconState.CryptoPortfolio.Letter ->
|
||||||
|
icon.copy(
|
||||||
|
size = if (isExpanded) AccountIconSize.ExtraSmall else AccountIconSize.Default,
|
||||||
|
)
|
||||||
|
else -> icon
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrencyIcon(
|
||||||
|
state = iconState,
|
||||||
|
withFixedSize = false,
|
||||||
|
modifier = modifier
|
||||||
|
.sharedBounds(
|
||||||
|
sharedContentState = iconSharedContentState,
|
||||||
|
animatedVisibilityScope = animatedContentScope,
|
||||||
|
boundsTransform = boundsTransform,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
title = { modifier: Modifier ->
|
||||||
|
TokenTitle(
|
||||||
|
state = state.tokenItemUM.titleState,
|
||||||
|
modifier = modifier
|
||||||
|
.sharedElement(
|
||||||
|
sharedContentState = titleSharedContentState,
|
||||||
|
animatedVisibilityScope = animatedContentScope,
|
||||||
|
boundsTransform = boundsTransform,
|
||||||
|
placeholderSize = SharedTransitionScope.PlaceholderSize.AnimatedSize,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isExpanded) {
|
||||||
|
ExpandedPortfolioHeader(
|
||||||
|
state = state.tokenItemUM,
|
||||||
|
isCollapsable = state.isCollapsable,
|
||||||
|
composables = composables,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
TokenItem(
|
||||||
|
state = state.tokenItemUM,
|
||||||
|
isBalanceHidden = isBalanceHidden,
|
||||||
|
composables = composables,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,52 +156,89 @@ fun PortfolioTokensListItem(state: PortfolioTokensListItemUM, isBalanceHidden: B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun ExpandedPortfolioHeader(state: TokenItemState, isCollapsable: Boolean, modifier: Modifier = Modifier) {
|
fun ExpandedPortfolioHeader(
|
||||||
|
state: TokenItemState,
|
||||||
|
isCollapsable: Boolean,
|
||||||
|
composables: TokenItemComposables?,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable(onClick = { state.onItemClick?.invoke(state) })
|
.clickable(onClick = { state.onItemClick?.invoke(state) })
|
||||||
.padding(
|
.padding(
|
||||||
vertical = TangemTheme.dimens.spacing4,
|
vertical = if (composables != null) 8.dp else 4.dp,
|
||||||
horizontal = TangemTheme.dimens.spacing12,
|
horizontal = 12.dp,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
when (val icon = state.iconState) {
|
if (composables != null) {
|
||||||
is CurrencyIconState.CryptoPortfolio.Icon -> AccountResIcon(
|
composables.icon.invoke(Modifier)
|
||||||
resId = icon.resId,
|
} else {
|
||||||
color = icon.color,
|
when (val icon = state.iconState) {
|
||||||
size = AccountIconSize.ExtraSmall,
|
is CurrencyIconState.CryptoPortfolio.Icon -> AccountResIcon(
|
||||||
)
|
resId = icon.resId,
|
||||||
is CurrencyIconState.CryptoPortfolio.Letter -> AccountCharIcon(
|
color = icon.color,
|
||||||
char = icon.char.resolveReference().first(),
|
size = AccountIconSize.ExtraSmall,
|
||||||
color = icon.color,
|
)
|
||||||
size = AccountIconSize.ExtraSmall,
|
is CurrencyIconState.CryptoPortfolio.Letter -> AccountCharIcon(
|
||||||
)
|
char = icon.char.resolveReference().first(),
|
||||||
is CurrencyIconState.CoinIcon,
|
color = icon.color,
|
||||||
is CurrencyIconState.CustomTokenIcon,
|
size = AccountIconSize.ExtraSmall,
|
||||||
is CurrencyIconState.Empty,
|
)
|
||||||
is CurrencyIconState.FiatIcon,
|
is CurrencyIconState.CoinIcon,
|
||||||
CurrencyIconState.Loading,
|
is CurrencyIconState.CustomTokenIcon,
|
||||||
CurrencyIconState.Locked,
|
is CurrencyIconState.Empty,
|
||||||
is CurrencyIconState.TokenIcon,
|
is CurrencyIconState.FiatIcon,
|
||||||
-> Unit
|
CurrencyIconState.Loading,
|
||||||
|
CurrencyIconState.Locked,
|
||||||
|
is CurrencyIconState.TokenIcon,
|
||||||
|
-> Unit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpacerW4()
|
SpacerW4()
|
||||||
|
|
||||||
when (val titleState = state.titleState) {
|
Row(
|
||||||
TokenItemState.TitleState.Loading -> Unit
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
TokenItemState.TitleState.Locked -> Unit
|
modifier = Modifier.weight(1f),
|
||||||
is TokenItemState.TitleState.Content -> Text(
|
) {
|
||||||
modifier = Modifier.weight(1f),
|
if (composables != null) {
|
||||||
text = titleState.text.resolveReference(),
|
composables.title.invoke(Modifier.alignByBaseline())
|
||||||
color = TangemTheme.colors.text.primary1,
|
} else {
|
||||||
overflow = TextOverflow.Ellipsis,
|
when (val titleState = state.titleState) {
|
||||||
maxLines = 1,
|
TokenItemState.TitleState.Loading -> Unit
|
||||||
style = TangemTheme.typography.caption1,
|
TokenItemState.TitleState.Locked -> Unit
|
||||||
)
|
is TokenItemState.TitleState.Content -> Text(
|
||||||
|
text = titleState.text.resolveReference(),
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
style = TangemTheme.typography.caption1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val text = when (val fiatAmountState = state.fiatAmountState) {
|
||||||
|
is TokenItemState.FiatAmountState.Content -> fiatAmountState.text
|
||||||
|
is TokenItemState.FiatAmountState.TextContent -> fiatAmountState.text
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(text != null) {
|
||||||
|
Text(
|
||||||
|
text = text.orEmpty(),
|
||||||
|
modifier = Modifier
|
||||||
|
.alignByBaseline()
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
color = TangemTheme.colors.text.tertiary,
|
||||||
|
style = TangemTheme.typography.caption1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCollapsable) {
|
if (isCollapsable) {
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@ private fun LazyItemScope.DraggableItem(
|
||||||
is DraggableItem.Portfolio -> ExpandedPortfolioHeader(
|
is DraggableItem.Portfolio -> ExpandedPortfolioHeader(
|
||||||
state = item.tokenItemState,
|
state = item.tokenItemState,
|
||||||
isCollapsable = false,
|
isCollapsable = false,
|
||||||
|
composables = null,
|
||||||
modifier = modifierWithBackground
|
modifier = modifierWithBackground
|
||||||
.padding(top = 8.dp)
|
.padding(top = 8.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.drawBehind
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
|
@ -57,7 +56,6 @@ import com.tangem.core.ui.components.rememberIsKeyboardVisible
|
||||||
import com.tangem.core.ui.components.sheetscaffold.*
|
import com.tangem.core.ui.components.sheetscaffold.*
|
||||||
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
|
import com.tangem.core.ui.components.snackbar.CopiedTextSnackbar
|
||||||
import com.tangem.core.ui.components.snackbar.TangemSnackbar
|
import com.tangem.core.ui.components.snackbar.TangemSnackbar
|
||||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
|
||||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||||
import com.tangem.core.ui.event.StateEvent
|
import com.tangem.core.ui.event.StateEvent
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
|
|
@ -79,7 +77,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistor
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.fastForEach
|
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.nftCollections
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.nftCollections
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeTokensButton
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeTokensButton
|
||||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
|
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
|
||||||
|
|
@ -154,7 +151,6 @@ private fun WalletContent(
|
||||||
*/
|
*/
|
||||||
val selectedWalletIndex by remember(state.selectedWalletIndex) { mutableIntStateOf(state.selectedWalletIndex) }
|
val selectedWalletIndex by remember(state.selectedWalletIndex) { mutableIntStateOf(state.selectedWalletIndex) }
|
||||||
val selectedWallet = state.wallets.getOrElse(selectedWalletIndex) { state.wallets[state.selectedWalletIndex] }
|
val selectedWallet = state.wallets.getOrElse(selectedWalletIndex) { state.wallets[state.selectedWalletIndex] }
|
||||||
val (expandedState, collapsedState) = getExpandPortfolioStates(selectedWallet)
|
|
||||||
|
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
|
|
||||||
|
|
@ -199,6 +195,7 @@ private fun WalletContent(
|
||||||
contentType = state.wallets.map { it.walletCardState.id },
|
contentType = state.wallets.map { it.walletCardState.id },
|
||||||
) {
|
) {
|
||||||
WalletsList(
|
WalletsList(
|
||||||
|
modifier = Modifier.animateItem(fadeInSpec = null, fadeOutSpec = null),
|
||||||
lazyListState = walletsListState,
|
lazyListState = walletsListState,
|
||||||
wallets = state.wallets.map(WalletState::walletCardState).toImmutableList(),
|
wallets = state.wallets.map(WalletState::walletCardState).toImmutableList(),
|
||||||
isBalanceHidden = state.isHidingMode,
|
isBalanceHidden = state.isHidingMode,
|
||||||
|
|
@ -263,13 +260,6 @@ private fun WalletContent(
|
||||||
txHistoryItems = txHistoryItems,
|
txHistoryItems = txHistoryItems,
|
||||||
isBalanceHidden = state.isHidingMode,
|
isBalanceHidden = state.isHidingMode,
|
||||||
modifier = movableItemModifier,
|
modifier = movableItemModifier,
|
||||||
portfolioVisibleState = {
|
|
||||||
findPortfolioVisibleState(
|
|
||||||
portfolio = it,
|
|
||||||
expandedState = expandedState,
|
|
||||||
collapsedState = collapsedState,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
nftCollections(state = selectedWallet, itemModifier = itemModifier)
|
nftCollections(state = selectedWallet, itemModifier = itemModifier)
|
||||||
|
|
@ -307,61 +297,6 @@ private fun WalletContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findPortfolioVisibleState(
|
|
||||||
portfolio: TokensListItemUM.Portfolio,
|
|
||||||
expandedState: SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
|
||||||
collapsedState: SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
|
||||||
): MutableTransitionState<Boolean> {
|
|
||||||
val portfolioKey = portfolio.id
|
|
||||||
|
|
||||||
fun forceVisible() = MutableTransitionState(true).apply { targetState = true }
|
|
||||||
val shouldExpand = portfolio.isExpanded
|
|
||||||
return if (shouldExpand) {
|
|
||||||
collapsedState[portfolioKey] ?: forceVisible()
|
|
||||||
} else {
|
|
||||||
expandedState[portfolioKey] ?: forceVisible()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun getExpandPortfolioStates(
|
|
||||||
state: WalletState,
|
|
||||||
): Pair<
|
|
||||||
SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
|
||||||
SnapshotStateMap<String, MutableTransitionState<Boolean>>,
|
|
||||||
> {
|
|
||||||
val expandedTransitionState =
|
|
||||||
remember { mutableStateMapOf<String, MutableTransitionState<Boolean>>() }
|
|
||||||
val collapsedTransitionState =
|
|
||||||
remember { mutableStateMapOf<String, MutableTransitionState<Boolean>>() }
|
|
||||||
|
|
||||||
val portfolioContent = state is WalletState.MultiCurrency.Content &&
|
|
||||||
state.tokensListState is WalletTokensListState.ContentState.PortfolioContent
|
|
||||||
if (!portfolioContent) {
|
|
||||||
return expandedTransitionState to collapsedTransitionState
|
|
||||||
}
|
|
||||||
|
|
||||||
state.tokensListState.items.fastForEach { portfolio ->
|
|
||||||
val portfolioKey = portfolio.id
|
|
||||||
val shouldExpand = portfolio.isExpanded
|
|
||||||
|
|
||||||
fun toggleVisible() = MutableTransitionState(false).apply { targetState = true }
|
|
||||||
fun forceVisible() = MutableTransitionState(true).apply { targetState = true }
|
|
||||||
|
|
||||||
val isFirstCall = collapsedTransitionState[portfolioKey] == null ||
|
|
||||||
expandedTransitionState[portfolioKey] == null
|
|
||||||
when {
|
|
||||||
isFirstCall -> {
|
|
||||||
collapsedTransitionState[portfolioKey] = forceVisible()
|
|
||||||
expandedTransitionState[portfolioKey] = forceVisible()
|
|
||||||
}
|
|
||||||
shouldExpand -> expandedTransitionState[portfolioKey] = toggleVisible()
|
|
||||||
else -> collapsedTransitionState[portfolioKey] = toggleVisible()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return expandedTransitionState to collapsedTransitionState
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("LongParameterList", "LongMethod", "CyclomaticComplexMethod")
|
@Suppress("LongParameterList", "LongMethod", "CyclomaticComplexMethod")
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,14 @@ internal fun WalletsList(
|
||||||
lazyListState: LazyListState,
|
lazyListState: LazyListState,
|
||||||
wallets: ImmutableList<WalletCardState>,
|
wallets: ImmutableList<WalletCardState>,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val horizontalCardPadding = TangemTheme.dimens.spacing16
|
val horizontalCardPadding = TangemTheme.dimens.spacing16
|
||||||
val screenWidth = LocalWindowSize.current.width
|
val screenWidth = LocalWindowSize.current.width
|
||||||
val itemWidth by remember(screenWidth) { derivedStateOf { screenWidth - horizontalCardPadding * 2 } }
|
val itemWidth by remember(screenWidth) { derivedStateOf { screenWidth - horizontalCardPadding * 2 } }
|
||||||
|
|
||||||
LazyRow(
|
LazyRow(
|
||||||
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
|
modifier = modifier.background(color = TangemTheme.colors.background.secondary),
|
||||||
state = lazyListState,
|
state = lazyListState,
|
||||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||||
|
|
||||||
import androidx.compose.animation.core.MutableTransitionState
|
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.paging.compose.LazyPagingItems
|
||||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
|
||||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||||
import com.tangem.core.ui.components.transactions.txHistoryItems
|
import com.tangem.core.ui.components.transactions.txHistoryItems
|
||||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||||
|
|
@ -24,11 +22,10 @@ internal fun LazyListScope.contentItems(
|
||||||
txHistoryItems: LazyPagingItems<TxHistoryState.TxHistoryItemState>?,
|
txHistoryItems: LazyPagingItems<TxHistoryState.TxHistoryItemState>?,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
|
||||||
) {
|
) {
|
||||||
when (state) {
|
when (state) {
|
||||||
is WalletState.MultiCurrency -> {
|
is WalletState.MultiCurrency -> {
|
||||||
tokensListItems(state.tokensListState, modifier, isBalanceHidden, portfolioVisibleState)
|
tokensListItems(state.tokensListState, modifier, isBalanceHidden)
|
||||||
}
|
}
|
||||||
is WalletState.SingleCurrency -> {
|
is WalletState.SingleCurrency -> {
|
||||||
txHistoryItems(state.txHistoryState, txHistoryItems, isBalanceHidden, modifier)
|
txHistoryItems(state.txHistoryState, txHistoryItems, isBalanceHidden, modifier)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||||
|
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.*
|
||||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
|
||||||
import androidx.compose.animation.core.MutableTransitionState
|
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.semantics.semantics
|
import androidx.compose.ui.semantics.semantics
|
||||||
|
|
@ -20,12 +24,12 @@ import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.test.MainScreenTestTags
|
import com.tangem.core.ui.test.MainScreenTestTags
|
||||||
import com.tangem.core.ui.utils.lazyListItemPosition
|
import com.tangem.core.ui.utils.lazyListItemPosition
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
internal fun LazyListScope.portfolioContentItems(
|
internal fun LazyListScope.portfolioContentItems(
|
||||||
items: ImmutableList<TokensListItemUM.Portfolio>,
|
items: ImmutableList<TokensListItemUM.Portfolio>,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
|
||||||
) {
|
) {
|
||||||
items.forEachIndexed { index, item ->
|
items.forEachIndexed { index, item ->
|
||||||
portfolioTokensList(
|
portfolioTokensList(
|
||||||
|
|
@ -33,7 +37,6 @@ internal fun LazyListScope.portfolioContentItems(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
portfolioIndex = index,
|
portfolioIndex = index,
|
||||||
isBalanceHidden = isBalanceHidden,
|
isBalanceHidden = isBalanceHidden,
|
||||||
portfolioVisibleState = portfolioVisibleState,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -43,35 +46,34 @@ internal fun LazyListScope.portfolioTokensList(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
portfolioIndex: Int,
|
portfolioIndex: Int,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
|
||||||
) {
|
) {
|
||||||
val tokens = portfolio.tokens
|
val tokens = portfolio.tokens
|
||||||
val isExpanded = portfolio.isExpanded
|
val isExpanded = portfolio.isExpanded
|
||||||
|
val lastIndex = tokens.lastIndex.inc()
|
||||||
|
|
||||||
portfolioItem(
|
portfolioItem(
|
||||||
portfolio = portfolio,
|
portfolio = portfolio,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
portfolioIndex = portfolioIndex,
|
portfolioIndex = portfolioIndex,
|
||||||
isBalanceHidden = isBalanceHidden,
|
isBalanceHidden = isBalanceHidden,
|
||||||
portfolioVisibleState = portfolioVisibleState,
|
|
||||||
)
|
)
|
||||||
if (!isExpanded) return
|
|
||||||
if (tokens.isEmpty()) {
|
if (tokens.isEmpty()) {
|
||||||
item(
|
item(
|
||||||
key = "$NON_CONTENT_TOKENS_LIST_KEY account-${portfolio.id}",
|
key = "$NON_CONTENT_TOKENS_LIST_KEY account-${portfolio.id}",
|
||||||
contentType = "$NON_CONTENT_TOKENS_LIST_KEY account-${portfolio.id}",
|
contentType = "$NON_CONTENT_TOKENS_LIST_KEY account-${portfolio.id}",
|
||||||
) {
|
) {
|
||||||
val appear = portfolioVisibleState(portfolio)
|
|
||||||
SlideInItemVisibility(
|
SlideInItemVisibility(
|
||||||
|
currentIndex = 1,
|
||||||
|
lastIndex = lastIndex,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.animateItem()
|
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
||||||
.roundedShapeItemDecoration(
|
.roundedShapeItemDecoration(
|
||||||
radius = TangemTheme.dimens.radius14,
|
radius = TangemTheme.dimens.radius14,
|
||||||
currentIndex = 1,
|
currentIndex = 1,
|
||||||
lastIndex = 1,
|
lastIndex = 1,
|
||||||
backgroundColor = TangemTheme.colors.background.primary,
|
backgroundColor = TangemTheme.colors.background.primary,
|
||||||
),
|
),
|
||||||
visibleState = appear,
|
visible = isExpanded,
|
||||||
) {
|
) {
|
||||||
NonContentItemContent(
|
NonContentItemContent(
|
||||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing28),
|
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing28),
|
||||||
|
|
@ -86,19 +88,19 @@ internal fun LazyListScope.portfolioTokensList(
|
||||||
contentType = { _, item -> item::class.java },
|
contentType = { _, item -> item::class.java },
|
||||||
itemContent = { tokenIndex, token ->
|
itemContent = { tokenIndex, token ->
|
||||||
val indexWithHeader = tokenIndex.inc()
|
val indexWithHeader = tokenIndex.inc()
|
||||||
val lastIndex = tokens.lastIndex.inc()
|
|
||||||
val appear = portfolioVisibleState(portfolio)
|
|
||||||
SlideInItemVisibility(
|
SlideInItemVisibility(
|
||||||
|
currentIndex = tokenIndex,
|
||||||
|
lastIndex = lastIndex,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.testModifier(indexWithHeader)
|
.testModifier(indexWithHeader)
|
||||||
.animateItem()
|
.animateItem(fadeInSpec = null, placementSpec = null, fadeOutSpec = null)
|
||||||
.roundedShapeItemDecoration(
|
.roundedShapeItemDecoration(
|
||||||
radius = TangemTheme.dimens.radius14,
|
radius = TangemTheme.dimens.radius14,
|
||||||
currentIndex = indexWithHeader,
|
currentIndex = indexWithHeader,
|
||||||
lastIndex = lastIndex,
|
lastIndex = lastIndex,
|
||||||
backgroundColor = TangemTheme.colors.background.primary,
|
backgroundColor = TangemTheme.colors.background.primary,
|
||||||
),
|
),
|
||||||
visibleState = appear,
|
visible = isExpanded,
|
||||||
) {
|
) {
|
||||||
val modifier = if (indexWithHeader == lastIndex) Modifier.padding(bottom = 8.dp) else Modifier
|
val modifier = if (indexWithHeader == lastIndex) Modifier.padding(bottom = 8.dp) else Modifier
|
||||||
PortfolioTokensListItem(
|
PortfolioTokensListItem(
|
||||||
|
|
@ -116,11 +118,9 @@ private fun LazyListScope.portfolioItem(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
portfolioIndex: Int,
|
portfolioIndex: Int,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
|
||||||
) {
|
) {
|
||||||
val tokens = portfolio.tokens
|
val tokens = portfolio.tokens
|
||||||
val isExpanded = portfolio.isExpanded
|
val isExpanded = portfolio.isExpanded
|
||||||
|
|
||||||
val lastIndex = when {
|
val lastIndex = when {
|
||||||
isExpanded && tokens.isEmpty() -> 1
|
isExpanded && tokens.isEmpty() -> 1
|
||||||
isExpanded -> tokens.lastIndex.inc()
|
isExpanded -> tokens.lastIndex.inc()
|
||||||
|
|
@ -128,60 +128,61 @@ private fun LazyListScope.portfolioItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
item(
|
item(
|
||||||
key = "account-${portfolio.id}-isExpanded$isExpanded",
|
key = "account-${portfolio.id}",
|
||||||
contentType = "account-isExpanded$isExpanded",
|
contentType = "account-content",
|
||||||
) {
|
) {
|
||||||
val anchorModifier = modifier
|
var lastIndexProxy by remember { mutableIntStateOf(lastIndex) }
|
||||||
.testModifier(portfolioIndex)
|
|
||||||
.animateItem()
|
// When collapsing the portfolio, we delay updating lastIndexProxy to allow
|
||||||
.roundedShapeItemDecoration(
|
// shrinking animation to complete before changing the shape.
|
||||||
currentIndex = 0,
|
LaunchedEffect(lastIndex) {
|
||||||
radius = TangemTheme.dimens.radius14,
|
if (lastIndex != 0) {
|
||||||
lastIndex = lastIndex,
|
lastIndexProxy = lastIndex
|
||||||
backgroundColor = TangemTheme.colors.background.primary,
|
return@LaunchedEffect
|
||||||
)
|
|
||||||
val appear = portfolioVisibleState(portfolio)
|
|
||||||
if (isExpanded) {
|
|
||||||
SlideInItemVisibility(
|
|
||||||
modifier = anchorModifier,
|
|
||||||
visibleState = appear,
|
|
||||||
) {
|
|
||||||
PortfolioListItem(
|
|
||||||
state = portfolio,
|
|
||||||
isBalanceHidden = isBalanceHidden,
|
|
||||||
modifier = Modifier.padding(vertical = 8.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AnimatedVisibility(
|
|
||||||
modifier = anchorModifier,
|
|
||||||
visibleState = appear,
|
|
||||||
enter = fadeIn(),
|
|
||||||
exit = ExitTransition.None,
|
|
||||||
) {
|
|
||||||
PortfolioListItem(
|
|
||||||
state = portfolio,
|
|
||||||
isBalanceHidden = isBalanceHidden,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
delay(timeMillis = (50 * tokens.size).toLong())
|
||||||
|
lastIndexProxy = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PortfolioListItem(
|
||||||
|
state = portfolio,
|
||||||
|
isBalanceHidden = isBalanceHidden,
|
||||||
|
modifier = modifier
|
||||||
|
.testModifier(portfolioIndex)
|
||||||
|
.roundedShapeItemDecoration(
|
||||||
|
currentIndex = 0,
|
||||||
|
radius = TangemTheme.dimens.radius14,
|
||||||
|
lastIndex = lastIndexProxy,
|
||||||
|
backgroundColor = TangemTheme.colors.background.primary,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
@Composable
|
@Composable
|
||||||
private fun SlideInItemVisibility(
|
private fun SlideInItemVisibility(
|
||||||
visibleState: MutableTransitionState<Boolean>,
|
visible: Boolean,
|
||||||
|
currentIndex: Int,
|
||||||
|
lastIndex: Int,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
content: @Composable() AnimatedVisibilityScope.() -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
visibleState = visibleState,
|
visible = visible,
|
||||||
enter = slideInVertically(
|
enter = fadeIn(
|
||||||
animationSpec = tween(easing = LinearOutSlowInEasing),
|
tween(100, delayMillis = 50 * currentIndex),
|
||||||
initialOffsetY = { it },
|
) + expandVertically(
|
||||||
) + fadeIn(),
|
tween(100, delayMillis = 50 * currentIndex),
|
||||||
exit = ExitTransition.None,
|
expandFrom = Alignment.Top,
|
||||||
|
),
|
||||||
|
exit = fadeOut(
|
||||||
|
tween(100, delayMillis = 50 * (lastIndex - currentIndex - 1)),
|
||||||
|
) + shrinkVertically(
|
||||||
|
tween(100, delayMillis = 50 * (lastIndex - currentIndex - 1)),
|
||||||
|
shrinkTowards = Alignment.Top,
|
||||||
|
),
|
||||||
) {
|
) {
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||||
|
|
||||||
import androidx.compose.animation.core.MutableTransitionState
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
|
@ -41,14 +40,12 @@ internal fun LazyListScope.tokensListItems(
|
||||||
state: WalletTokensListState,
|
state: WalletTokensListState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
portfolioVisibleState: (portfolio: TokensListItemUM.Portfolio) -> MutableTransitionState<Boolean>,
|
|
||||||
) {
|
) {
|
||||||
when (state) {
|
when (state) {
|
||||||
is WalletTokensListState.ContentState.PortfolioContent -> portfolioContentItems(
|
is WalletTokensListState.ContentState.PortfolioContent -> portfolioContentItems(
|
||||||
items = state.items,
|
items = state.items,
|
||||||
isBalanceHidden = isBalanceHidden,
|
isBalanceHidden = isBalanceHidden,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
portfolioVisibleState = portfolioVisibleState,
|
|
||||||
)
|
)
|
||||||
is WalletTokensListState.ContentState.Content,
|
is WalletTokensListState.ContentState.Content,
|
||||||
is WalletTokensListState.ContentState.Loading,
|
is WalletTokensListState.ContentState.Loading,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue