Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-17 19:54:07 +07:00
parent 380e7ef082
commit d019d88149
10 changed files with 342 additions and 32 deletions

View file

@ -1,13 +1,29 @@
package com.tangem.core.ui.components.tokenlist
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
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.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.SpacerW4
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.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.fields.SearchBar
import com.tangem.core.ui.components.token.TokenItem
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.state.PortfolioTokensListItemUM
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
@ -24,16 +40,9 @@ import com.tangem.core.ui.res.TangemTheme
@Composable
fun TokenListItem(state: TokensListItemUM, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
when (state) {
is TokensListItemUM.GroupTitle -> {
GroupTitleItem(state, modifier)
}
is TokensListItemUM.Token -> {
TokenItem(
state = state.state,
isBalanceHidden = isBalanceHidden,
modifier = modifier,
)
}
is TokensListItemUM.GroupTitle -> PortfolioTokensListItem(state, isBalanceHidden, modifier)
is TokensListItemUM.Token -> PortfolioTokensListItem(state, isBalanceHidden, modifier)
is TokensListItemUM.Portfolio -> PortfolioListItem(state, isBalanceHidden, modifier)
is TokensListItemUM.SearchBar -> {
SearchBar(state = state.searchBarUM, modifier = modifier.padding(all = 12.dp))
}
@ -46,4 +55,86 @@ fun TokenListItem(state: TokensListItemUM, isBalanceHidden: Boolean, modifier: M
)
}
}
}
@Composable
fun PortfolioListItem(state: TokensListItemUM.Portfolio, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
if (state.isExpanded) {
ExpandedPortfolioHeader(state.state, modifier)
} else {
TokenItem(
state = state.state,
isBalanceHidden = isBalanceHidden,
modifier = modifier,
)
}
}
@Composable
fun PortfolioTokensListItem(state: PortfolioTokensListItemUM, isBalanceHidden: Boolean, modifier: Modifier = Modifier) {
when (state) {
is TokensListItemUM.GroupTitle -> GroupTitleItem(state, modifier)
is TokensListItemUM.Token -> TokenItem(
state = state.state,
isBalanceHidden = isBalanceHidden,
modifier = modifier,
)
}
}
@Composable
private fun ExpandedPortfolioHeader(state: TokenItemState, modifier: Modifier = Modifier) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.clickable(onClick = { state.onItemClick?.invoke(state) })
.padding(
vertical = TangemTheme.dimens.spacing4,
horizontal = TangemTheme.dimens.spacing12,
),
) {
when (val icon = state.iconState) {
is CurrencyIconState.CryptoPortfolio.Icon -> AccountResIcon(
resId = icon.resId,
color = icon.color,
size = AccountIconSize.ExtraSmall,
)
is CurrencyIconState.CryptoPortfolio.Letter -> AccountCharIcon(
char = icon.char.resolveReference().first(),
color = icon.color,
size = AccountIconSize.ExtraSmall,
)
is CurrencyIconState.CoinIcon,
is CurrencyIconState.CustomTokenIcon,
is CurrencyIconState.Empty,
is CurrencyIconState.FiatIcon,
CurrencyIconState.Loading,
CurrencyIconState.Locked,
is CurrencyIconState.TokenIcon,
-> Unit
}
SpacerW4()
when (val titleState = state.titleState) {
TokenItemState.TitleState.Loading -> Unit
TokenItemState.TitleState.Locked -> Unit
is TokenItemState.TitleState.Content -> Text(
modifier = Modifier.weight(1f),
text = titleState.text.resolveReference(),
color = TangemTheme.colors.text.primary1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = TangemTheme.typography.caption1,
)
}
Icon(
modifier = Modifier.size(TangemTheme.dimens.size16),
painter = painterResource(id = R.drawable.ic_minimize_24),
tint = TangemTheme.colors.icon.inactive,
contentDescription = null,
)
}
}

View file

@ -29,16 +29,29 @@ sealed interface TokensListItemUM {
* @property id id
* @property text title value
*/
data class GroupTitle(override val id: Any, val text: TextReference) : TokensListItemUM
data class GroupTitle(override val id: Any, val text: TextReference) : TokensListItemUM, PortfolioTokensListItemUM
/**
* Token item
*
* @property state token state
*/
data class Token(val state: TokenItemState) : TokensListItemUM {
data class Token(val state: TokenItemState) : TokensListItemUM, PortfolioTokensListItemUM {
override val id: String = state.id
}
data class Portfolio(
val state: TokenItemState,
val isExpanded: Boolean,
val tokens: List<PortfolioTokensListItemUM>,
) : TokensListItemUM {
override val id: String = state.id
}
data class Text(override val id: Any, val text: TextReference) : TokensListItemUM
}
sealed interface PortfolioTokensListItemUM {
/** Unique ID */
val id: Any
}

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M19.19,11.345H14.32C13.239,11.345 12.606,10.713 12.606,9.632V4.868C12.606,4.261 13.072,3.813 13.688,3.813C14.294,3.813 14.751,4.253 14.751,4.868V5.413L14.558,7.944L16.421,5.984L18.82,3.567C19.022,3.356 19.286,3.259 19.576,3.259C20.235,3.259 20.701,3.708 20.701,4.367C20.701,4.666 20.587,4.929 20.376,5.131L17.968,7.54L16.008,9.394L18.557,9.201H19.19C19.805,9.201 20.253,9.649 20.253,10.273C20.253,10.888 19.805,11.345 19.19,11.345ZM10.356,20.213C9.741,20.213 9.284,19.774 9.284,19.159V18.544L9.478,16.012L7.623,17.972L5.18,20.433C4.978,20.635 4.714,20.741 4.424,20.741C3.765,20.741 3.299,20.284 3.299,19.625C3.299,19.335 3.413,19.071 3.624,18.869L6.076,16.417L8.036,14.562L5.479,14.755H4.784C4.169,14.755 3.721,14.307 3.721,13.683C3.721,13.068 4.169,12.611 4.784,12.611H9.715C10.805,12.611 11.429,13.244 11.429,14.325V19.159C11.429,19.765 10.972,20.213 10.356,20.213Z"
android:fillColor="#1E1E1E"/>
</vector>