Updated on 2026-08-14
This commit is contained in:
parent
090e0964d4
commit
a9fbfc8a53
7 changed files with 272 additions and 107 deletions
|
|
@ -27,6 +27,8 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
private val priceChangeLce: Lce<Unit, PriceChange>? = null,
|
||||
private val onItemClick: ((Account.CryptoPortfolio) -> Unit)? = null,
|
||||
private val onItemLongClick: ((Account.CryptoPortfolio) -> Unit)? = null,
|
||||
private val fiatAmountStateProvider: ((TotalFiatBalance) -> FiatAmountState?)? = null,
|
||||
private val subtitle2StateProvider: ((Lce<Unit, PriceChange>) -> Subtitle2State?)? = null,
|
||||
) : Converter<TotalFiatBalance, TokenItemState> {
|
||||
|
||||
override fun convert(value: TotalFiatBalance): TokenItemState {
|
||||
|
|
@ -40,11 +42,11 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
private fun Account.CryptoPortfolio.mapToContentState(
|
||||
fiatBalance: TotalFiatBalance.Loaded,
|
||||
): TokenItemState.Content {
|
||||
val subtitle2State = priceChangeLce?.fold(
|
||||
ifLoading = { priceChange -> priceChange?.toSubtitle2State() ?: Subtitle2State.Loading },
|
||||
ifError = { null },
|
||||
ifContent = { priceChange -> priceChange.toSubtitle2State() },
|
||||
)
|
||||
val subtitle2State = if (priceChangeLce != null && subtitle2StateProvider != null) {
|
||||
subtitle2StateProvider(priceChangeLce)
|
||||
} else {
|
||||
createSubtitle2State(priceChangeLce)
|
||||
}
|
||||
return TokenItemState.Content(
|
||||
id = account.accountId.toItemId(),
|
||||
iconState = AccountIconItemStateConverter().convert(this),
|
||||
|
|
@ -59,11 +61,8 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
),
|
||||
isAvailable = false,
|
||||
),
|
||||
fiatAmountState = FiatAmountState.Content(
|
||||
text = fiatBalance.amount
|
||||
.format { fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol) },
|
||||
isFlickering = fiatBalance.source == StatusSource.CACHE,
|
||||
),
|
||||
fiatAmountState = fiatAmountStateProvider?.invoke(fiatBalance)
|
||||
?: createFiatAmountState(fiatBalance, appCurrency),
|
||||
subtitle2State = subtitle2State,
|
||||
onItemClick = onItemClick?.let { onItemClick -> { onItemClick(account) } },
|
||||
onItemLongClick = onItemLongClick?.let { onItemLongClick -> { onItemLongClick(account) } },
|
||||
|
|
@ -127,4 +126,30 @@ class AccountCryptoPortfolioItemStateConverter(
|
|||
type = this.value.getPriceChangeType(),
|
||||
isFlickering = this.source.isFlickering(),
|
||||
)
|
||||
|
||||
private fun createFiatAmountState(fiatBalance: TotalFiatBalance, appCurrency: AppCurrency): FiatAmountState {
|
||||
return when (fiatBalance) {
|
||||
TotalFiatBalance.Failed,
|
||||
TotalFiatBalance.Loading,
|
||||
-> FiatAmountState.Empty
|
||||
|
||||
is TotalFiatBalance.Loaded -> FiatAmountState.Content(
|
||||
text = fiatBalance.amount.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
},
|
||||
isFlickering = fiatBalance.source == StatusSource.CACHE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSubtitle2State(priceChangeLce: Lce<Unit, PriceChange>?): Subtitle2State? {
|
||||
return priceChangeLce?.fold(
|
||||
ifLoading = { priceChange -> priceChange?.toSubtitle2State() ?: Subtitle2State.Loading },
|
||||
ifError = { null },
|
||||
ifContent = { priceChange -> priceChange.toSubtitle2State() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,12 @@ sealed interface TokensListItemUM {
|
|||
is PortfolioItemContentUM.Tokens -> content.tokens
|
||||
is PortfolioItemContentUM.Empty -> persistentListOf()
|
||||
}
|
||||
|
||||
val tokensItemsList: List<Token>
|
||||
get() = when (content) {
|
||||
is PortfolioItemContentUM.Tokens -> content.tokens.filterIsInstance<Token>()
|
||||
is PortfolioItemContentUM.Empty -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
data class Text(override val id: Any, val text: TextReference) : TokensListItemUM
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package com.tangem.domain.wallets.usecase
|
|||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.util.LinkedHashMap
|
||||
|
||||
/**
|
||||
* Use case for getting list of user wallets
|
||||
|
|
@ -22,9 +22,13 @@ class GetWalletsUseCase(
|
|||
operator fun invoke(): Flow<List<UserWallet>> = userWalletsListRepository.userWallets.map { requireNotNull(it) }
|
||||
|
||||
@Throws(IllegalArgumentException::class)
|
||||
fun invokeAsMap(): Flow<LinkedHashMap<UserWalletId, UserWallet>> = userWalletsListRepository.userWallets
|
||||
.map { requireNotNull(it) }
|
||||
.map { wallets ->
|
||||
fun invokeAsMap(isOnlyMultiCurrency: Boolean = true): Flow<LinkedHashMap<UserWalletId, UserWallet>> = invoke()
|
||||
.map { list ->
|
||||
val wallets = if (isOnlyMultiCurrency) {
|
||||
list.filter { wallet -> wallet.isMultiCurrency }
|
||||
} else {
|
||||
list
|
||||
}
|
||||
wallets.associateByTo(
|
||||
destination = linkedMapOf(),
|
||||
keySelector = { wallet -> wallet.walletId },
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@ import com.tangem.common.ui.tokens.TokenConverterParams
|
|||
import com.tangem.common.ui.tokens.TokenItemGrouping.toGroupedItems
|
||||
import com.tangem.common.ui.tokens.TokenItemGrouping.toUngroupedItems
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter
|
||||
import com.tangem.core.ui.components.icons.IconTint
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState.FiatAmountState
|
||||
import com.tangem.core.ui.components.tokenlist.state.PortfolioTokensListItemUM
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.account.filterCryptoPortfolio
|
||||
|
|
@ -17,6 +20,7 @@ import com.tangem.domain.models.tokenlist.TokenList
|
|||
import com.tangem.feature.swap.choosetoken.impl.model.ClickIntents
|
||||
import com.tangem.feature.swap.choosetoken.impl.model.isSearchingState
|
||||
import com.tangem.feature.swap.models.TokenListUMData
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal class ChooseTokenListItemConverter(
|
||||
|
|
@ -57,10 +61,9 @@ internal class ChooseTokenListItemConverter(
|
|||
if (accountItems.isEmpty()) {
|
||||
return TokenListUMData.EmptyList
|
||||
}
|
||||
val accountsList = accountItems.toPersistentList()
|
||||
return TokenListUMData.AccountList(
|
||||
tokensList = accountsList,
|
||||
totalTokensCount = accountsList.size,
|
||||
tokensList = accountItems.toPersistentList(),
|
||||
totalTokensCount = accountItems.sumOf { portfolio -> portfolio.tokensItemsList.size },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -77,11 +80,19 @@ internal class ChooseTokenListItemConverter(
|
|||
clickIntents.onAccountExpandClick(clickedAccount)
|
||||
}
|
||||
}
|
||||
val fiatAmountStateProvider: ((TotalFiatBalance) -> FiatAmountState?) = if (isSearchingState) {
|
||||
{ _ -> FiatAmountState.Empty }
|
||||
} else {
|
||||
{ _ -> FiatAmountState.Icon(R.drawable.ic_chewron_down_20, IconTint.Informative) }
|
||||
}
|
||||
|
||||
val converter = AccountCryptoPortfolioItemStateConverter(
|
||||
appCurrency = appCurrency,
|
||||
account = account,
|
||||
onItemClick = onItemClick.takeIf { !isSearchingState },
|
||||
priceChangeLce = this.priceChangeLce,
|
||||
fiatAmountStateProvider = fiatAmountStateProvider,
|
||||
subtitle2StateProvider = { _ -> null },
|
||||
)
|
||||
val accountItem = converter.convert(tokenList.totalFiatBalance)
|
||||
val tokenConverter = tokenStatusConverter(this)
|
||||
|
|
@ -100,18 +111,14 @@ internal class ChooseTokenListItemConverter(
|
|||
|
||||
return when (tokenList) {
|
||||
is TokenList.Empty -> TokenListUMData.EmptyList
|
||||
is TokenList.GroupedByNetwork -> tokenList.toGroupedItems(tokenConverter).let { grouped ->
|
||||
TokenListUMData.TokenList(
|
||||
tokensList = grouped.toPersistentList(),
|
||||
totalTokensCount = grouped.size,
|
||||
)
|
||||
}
|
||||
is TokenList.Ungrouped -> tokenList.toUngroupedItems(tokenConverter).let { ungrouped ->
|
||||
TokenListUMData.TokenList(
|
||||
tokensList = ungrouped.toPersistentList(),
|
||||
totalTokensCount = ungrouped.size,
|
||||
)
|
||||
}
|
||||
is TokenList.GroupedByNetwork -> TokenListUMData.TokenList(
|
||||
tokensList = tokenList.toGroupedItems(tokenConverter).toPersistentList(),
|
||||
totalTokensCount = tokenList.flattenCurrencies().size,
|
||||
)
|
||||
is TokenList.Ungrouped -> TokenListUMData.TokenList(
|
||||
tokensList = tokenList.toUngroupedItems(tokenConverter).toPersistentList(),
|
||||
totalTokensCount = tokenList.flattenCurrencies().size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
|
|
@ -19,13 +18,9 @@ import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
|||
import com.tangem.feature.swap.choosetoken.api.*
|
||||
import com.tangem.feature.swap.choosetoken.impl.converter.SearchBarToggleTransformer
|
||||
import com.tangem.feature.swap.choosetoken.impl.converter.SearchBarUpdateQueryTransformer
|
||||
import com.tangem.feature.swap.choosetoken.impl.ui.ChooseTokenFullUM
|
||||
import com.tangem.feature.swap.choosetoken.impl.ui.ChooseTokenInitialUM
|
||||
import com.tangem.feature.swap.choosetoken.impl.ui.ChooseTokenUM
|
||||
import com.tangem.feature.swap.choosetoken.impl.ui.WalletListUM
|
||||
import com.tangem.feature.swap.choosetoken.impl.ui.*
|
||||
import com.tangem.feature.swap.converters.TokensDataConverter
|
||||
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
|
||||
import com.tangem.feature.swap.models.TokenListUMData
|
||||
import com.tangem.feature.swap.models.market.state.SwapMarketState
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
|
||||
|
|
@ -147,41 +142,39 @@ internal class ChooseTokenModel @Inject constructor(
|
|||
|
||||
@Suppress("LongMethod")
|
||||
private fun combineUI(): StateFlow<ChooseTokenUM?> = channelFlow {
|
||||
val allWalletsFlow: StateFlow<LinkedHashMap<UserWalletId, UserWallet>> =
|
||||
val allWalletsFlow: StateFlow<Map<UserWalletId, UserWallet>> =
|
||||
getWalletsUseCase.invokeAsMap().stateIn(this)
|
||||
|
||||
// todo swap add optional param, store, and GetSelectedWalletUseCase
|
||||
val firstSelectedWallet = allWalletsFlow.value.values.first()
|
||||
val selectedWalletFlow: StateFlow<UserWallet> =
|
||||
onWalletSelected.receiveAsFlow()
|
||||
.mapNotNull { walletId -> allWalletsFlow.value[walletId] }
|
||||
.stateIn(this, SharingStarted.Eagerly, allWalletsFlow.value.values.first())
|
||||
.stateIn(this, SharingStarted.Eagerly, firstSelectedWallet)
|
||||
|
||||
val selectedWalletTokensData: Flow<TokenListUMData> = combine(
|
||||
flow = selectedWalletFlow.map { wallet -> wallet.walletId }.distinctUntilChanged(),
|
||||
val fullPortfolioBlockFlow = combine(
|
||||
flow = allWalletsFlow,
|
||||
flow2 = portfolioListBlockDelegate.portfolioList,
|
||||
transform = { selectedWalletId, allPortfoliosData -> allPortfoliosData[selectedWalletId] },
|
||||
)
|
||||
.filterNotNull()
|
||||
.distinctUntilChanged()
|
||||
|
||||
val walletListUmFlow = combine(
|
||||
flow = selectedWalletFlow,
|
||||
flow2 = allWalletsFlow,
|
||||
transform = { selectedWallet, allWallets ->
|
||||
allWallets.entries
|
||||
flow3 = selectedWalletFlow.map { wallet -> wallet.walletId }.distinctUntilChanged(),
|
||||
transform = { allWallets, portfolioList, selectedWalletId ->
|
||||
val tokensListData = portfolioList[selectedWalletId] ?: return@combine null
|
||||
val walletsUM = allWallets.entries
|
||||
.map { (walletId, wallet) ->
|
||||
val type = if (selectedWallet.walletId == walletId) {
|
||||
TangemButtonType.Primary
|
||||
} else {
|
||||
TangemButtonType.Secondary
|
||||
}
|
||||
TangemButtonUM(
|
||||
val searchResultCount: TextReference? = portfolioList[walletId]?.totalTokensCount
|
||||
?.toString()
|
||||
?.let(::stringReference)
|
||||
?.takeIf { isSearchingState }
|
||||
WalletTabUM(
|
||||
text = stringReference(wallet.name),
|
||||
onClick = { onWalletSelected.trySend(walletId) },
|
||||
type = type,
|
||||
isSelected = selectedWalletId == walletId,
|
||||
count = searchResultCount,
|
||||
)
|
||||
}
|
||||
walletsUM to tokensListData
|
||||
},
|
||||
)
|
||||
.filterNotNull()
|
||||
.distinctUntilChanged()
|
||||
|
||||
portfolioListBlockDelegate.onTokenItemClick.receiveAsFlow()
|
||||
|
|
@ -195,11 +188,10 @@ internal class ChooseTokenModel @Inject constructor(
|
|||
.launchIn(this)
|
||||
|
||||
combine(
|
||||
flow = selectedWalletTokensData,
|
||||
flow = fullPortfolioBlockFlow,
|
||||
flow2 = settingContextUseCase.invoke(),
|
||||
flow3 = marketsStateFlow,
|
||||
flow4 = walletListUmFlow,
|
||||
transform = { tokensData, settings, marketsData, walletList ->
|
||||
transform = { (walletList, tokensData), settings, marketsData ->
|
||||
val walletsUM = if (walletList.size != 1) {
|
||||
WalletListUM(walletList.toPersistentList())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,23 @@
|
|||
package com.tangem.feature.swap.choosetoken.impl.ui
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
|
@ -17,10 +25,6 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.common.ui.tokens.portfolioTokensList
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.fields.SearchBar
|
||||
import com.tangem.core.ui.components.fields.TangemSearchBarDefaults
|
||||
|
|
@ -34,8 +38,6 @@ import com.tangem.core.ui.components.tokenlist.state.PortfolioItemContentUM
|
|||
import com.tangem.core.ui.components.tokenlist.state.PortfolioTokensListItemUM
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -54,6 +56,18 @@ import kotlin.random.Random
|
|||
|
||||
private const val LOAD_MORE_BUFFER = 25
|
||||
|
||||
private val ChooseTokenUM.isNotFoundState: Boolean
|
||||
get() = tokensListData.tokensList.isEmpty() &&
|
||||
isSearching &&
|
||||
marketsState !is SwapMarketState.Content &&
|
||||
marketsState !is SwapMarketState.Loading
|
||||
|
||||
private val ChooseTokenUM.isEmptyState: Boolean
|
||||
get() = tokensListData.tokensList.isEmpty() &&
|
||||
!isSearching &&
|
||||
marketsState !is SwapMarketState.Content &&
|
||||
marketsState !is SwapMarketState.Loading
|
||||
|
||||
@Composable
|
||||
internal fun ChooseTokenScreen(state: ChooseTokenFullUM, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
|
|
@ -93,7 +107,6 @@ private fun Content(state: ChooseTokenFullUM, modifier: Modifier = Modifier) {
|
|||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(nestedScrollConnection),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
state = lazyListState,
|
||||
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
|
||||
) {
|
||||
|
|
@ -108,20 +121,26 @@ private fun Content(state: ChooseTokenFullUM, modifier: Modifier = Modifier) {
|
|||
assetsTitle()
|
||||
|
||||
if (state.contentUM != null) {
|
||||
walletListItem(state.contentUM.walletList)
|
||||
when {
|
||||
state.contentUM.isNotFoundState -> tokensNotFound()
|
||||
state.contentUM.isEmptyState -> emptyTokensList()
|
||||
else -> {
|
||||
walletListItem(state.contentUM.walletList)
|
||||
|
||||
tokensListItems(
|
||||
tokensListData = state.contentUM.tokensListData,
|
||||
isBalanceHidden = state.contentUM.isBalanceHidden,
|
||||
)
|
||||
tokensListItems(
|
||||
tokensListData = state.contentUM.tokensListData,
|
||||
isBalanceHidden = state.contentUM.isBalanceHidden,
|
||||
)
|
||||
|
||||
if (state.contentUM.marketsState != null) {
|
||||
item("markets_title_spacer") { SpacerH(height = 20.dp) }
|
||||
swapMarketsListItems(state.contentUM.marketsState)
|
||||
if (state.contentUM.marketsState != null) {
|
||||
item("markets_title_spacer") { SpacerH(height = 20.dp) }
|
||||
swapMarketsListItems(state.contentUM.marketsState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.contentUM?.marketsState != null) {
|
||||
if (state.contentUM?.marketsState != null && !state.contentUM.isNotFoundState && !state.contentUM.isEmptyState) {
|
||||
SetupMarketScrollTracker(state.contentUM.marketsState, lazyListState)
|
||||
}
|
||||
}
|
||||
|
|
@ -183,26 +202,59 @@ private fun LazyListScope.assetsTitle() {
|
|||
private fun LazyListScope.walletListItem(walletList: WalletListUM) {
|
||||
if (walletList.items.isEmpty()) return
|
||||
item("wallet_list") {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16)
|
||||
.fillMaxWidth(),
|
||||
LazyRow(
|
||||
modifier = Modifier.padding(top = 12.dp, bottom = 4.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing8),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
) {
|
||||
walletList.items.forEach { um ->
|
||||
val colors = when (um.type) {
|
||||
TangemButtonType.Primary -> TangemButtonsDefaults.primaryButtonColors
|
||||
else -> TangemButtonsDefaults.secondaryButtonColors
|
||||
}
|
||||
TangemButton(
|
||||
text = um.text?.resolveReference().orEmpty(),
|
||||
icon = TangemButtonIconPosition.None,
|
||||
size = TangemButtonSize.Action,
|
||||
colors = colors,
|
||||
showProgress = false,
|
||||
onClick = um.onClick,
|
||||
enabled = true,
|
||||
items(walletList.items) { um ->
|
||||
WalletTabItem(um)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WalletTabItem(state: WalletTabUM, modifier: Modifier = Modifier) {
|
||||
val isSelected = state.isSelected
|
||||
val backgroundColor = if (isSelected) TangemTheme.colors.button.primary else TangemTheme.colors.button.secondary
|
||||
val buttonTextColor = if (isSelected) TangemTheme.colors.text.primary2 else TangemTheme.colors.text.primary1
|
||||
val countTextColor = if (isSelected) TangemTheme.colors.text.primary2 else TangemTheme.colors.text.secondary
|
||||
val countBackground = if (isSelected) {
|
||||
TangemTheme.colors.button.secondary.copy(alpha = 0.2f)
|
||||
} else {
|
||||
TangemTheme.colors.button.primary.copy(alpha = 0.1f)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.background(backgroundColor)
|
||||
.clickable(onClick = state.onClick)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = state.text.resolveReference(),
|
||||
color = buttonTextColor,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
|
||||
if (state.count != null) {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(countBackground, shape = CircleShape)
|
||||
.defaultMinSize(minWidth = 20.dp)
|
||||
.padding(horizontal = 4.dp, vertical = 2.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
text = state.count.resolveReference(),
|
||||
color = countTextColor,
|
||||
style = TangemTheme.typography.caption1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -253,6 +305,58 @@ private fun LazyListScope.tokensList(items: ImmutableList<TokensListItemUM>, isB
|
|||
)
|
||||
}
|
||||
|
||||
private fun LazyListScope.emptyTokensList(modifier: Modifier = Modifier) {
|
||||
item("EmptyTokensList") {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.fillParentMaxSize(),
|
||||
) {
|
||||
Column(modifier = Modifier.align(Alignment.Center)) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.size64)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
painter = painterResource(id = R.drawable.ic_no_token_44),
|
||||
colorFilter = ColorFilter.tint(TangemTheme.colors.icon.inactive),
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing16)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing30)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
text = stringResourceSafe(id = R.string.exchange_tokens_empty_tokens),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.tokensNotFound(modifier: Modifier = Modifier) {
|
||||
item("TokensNotFound") {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.fillParentMaxSize(),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = TangemTheme.dimens.spacing32)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing30)
|
||||
.align(Alignment.TopCenter),
|
||||
text = stringResourceSafe(id = R.string.express_token_list_empty_search),
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun TokenScreenPreview(@PreviewParameter(ChooseTokenScreenPreviewProvider::class) state: ChooseTokenFullUM) {
|
||||
|
|
@ -321,31 +425,42 @@ private val accounts
|
|||
|
||||
private val wallets
|
||||
get() = persistentListOf(
|
||||
TangemButtonUM(
|
||||
WalletTabUM(
|
||||
text = TextReference.Str(value = "Wallet 1"),
|
||||
type = TangemButtonType.Primary,
|
||||
isSelected = true,
|
||||
onClick = {},
|
||||
count = null,
|
||||
),
|
||||
TangemButtonUM(
|
||||
WalletTabUM(
|
||||
text = TextReference.Str(value = "Wallet 1"),
|
||||
isSelected = true,
|
||||
onClick = {},
|
||||
count = stringReference("3"),
|
||||
),
|
||||
WalletTabUM(
|
||||
text = TextReference.Str(value = "Wallet 2"),
|
||||
type = TangemButtonType.Secondary,
|
||||
isSelected = false,
|
||||
onClick = {},
|
||||
count = stringReference("333"),
|
||||
),
|
||||
TangemButtonUM(
|
||||
WalletTabUM(
|
||||
text = TextReference.Str(value = "Wallet 3"),
|
||||
type = TangemButtonType.Secondary,
|
||||
isSelected = false,
|
||||
onClick = {},
|
||||
count = null,
|
||||
),
|
||||
)
|
||||
|
||||
private val initialUM = ChooseTokenInitialUM(
|
||||
screenTitle = stringReference("Choose token"),
|
||||
onCloseClick = {},
|
||||
searchBar = searchBar,
|
||||
)
|
||||
|
||||
private class ChooseTokenScreenPreviewProvider : PreviewParameterProvider<ChooseTokenFullUM> {
|
||||
override val values: Sequence<ChooseTokenFullUM> = sequenceOf(
|
||||
ChooseTokenFullUM(
|
||||
initialUM = ChooseTokenInitialUM(
|
||||
screenTitle = stringReference("Choose token"),
|
||||
onCloseClick = {},
|
||||
searchBar = searchBar,
|
||||
),
|
||||
initialUM = initialUM,
|
||||
contentUM = ChooseTokenUM(
|
||||
walletList = WalletListUM(wallets),
|
||||
isBalanceHidden = false,
|
||||
|
|
@ -357,5 +472,15 @@ private class ChooseTokenScreenPreviewProvider : PreviewParameterProvider<Choose
|
|||
marketsState = SwapSelectTokenPreviewProvider.defaultState.marketsState,
|
||||
),
|
||||
),
|
||||
ChooseTokenFullUM(
|
||||
initialUM = initialUM,
|
||||
contentUM = ChooseTokenUM(
|
||||
walletList = WalletListUM(wallets),
|
||||
isBalanceHidden = false,
|
||||
isSearching = false,
|
||||
tokensListData = TokenListUMData.EmptyList,
|
||||
marketsState = null,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.feature.swap.choosetoken.impl.ui
|
||||
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.feature.swap.models.TokenListUMData
|
||||
import com.tangem.feature.swap.models.market.state.SwapMarketState
|
||||
|
|
@ -27,5 +26,12 @@ internal data class ChooseTokenInitialUM(
|
|||
)
|
||||
|
||||
internal data class WalletListUM(
|
||||
val items: ImmutableList<TangemButtonUM>,
|
||||
val items: ImmutableList<WalletTabUM>,
|
||||
)
|
||||
|
||||
internal data class WalletTabUM(
|
||||
val text: TextReference,
|
||||
val count: TextReference?,
|
||||
val isSelected: Boolean,
|
||||
val onClick: () -> Unit,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue