Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-16 16:23:08 +04:00
parent 93c1276828
commit 77a12bcb13
13 changed files with 235 additions and 166 deletions

View file

@ -9,8 +9,8 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery
import com.tangem.feature.swap.choosetoken.api.model.ChooseTokenPortfolioFullBlockUM
import com.tangem.feature.swap.domain.models.ui.CurrenciesGroup
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.feature.swap.presentation.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
@ -29,6 +29,8 @@ interface ChooseTokenBridge : ChooseTokenBridgeLegacy, ChooseTokenBridgeInternal
*/
val tokenFilter: MutableStateFlow<(AccountStatus.CryptoPortfolio, CryptoCurrencyStatus) -> Boolean>
fun selectWalletTab(walletId: UserWalletId)
data class Settings(
val title: TextReference,
val isShowMarketBlock: Boolean,
@ -61,7 +63,7 @@ interface ChooseTokenBridgeInternal {
val settings: ChooseTokenBridge.Settings
val analyticsPayload: Set<ChooseTokenAnalyticsPayload>
val searchQueryState: StateFlow<SearchQuery>
val portfolioListBlock: Flow<Map<UserWalletId, TokenListUMData>>
val fullPortfolioBlock: StateFlow<ChooseTokenPortfolioFullBlockUM?>
fun onSearchQuery(query: SearchQuery)
fun onSearchQuery(query: String) = onSearchQuery(SearchQuery(query))

View file

@ -0,0 +1,51 @@
package com.tangem.feature.swap.choosetoken.api.model
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
data class ChooseTokenPortfolioFullBlockUM(
val walletList: WalletListUM,
val isBalanceHidden: Boolean,
val isSearching: Boolean,
val tokensListData: TokenListUMData,
)
data class WalletListUM(
val items: ImmutableList<WalletTabUM>,
)
data class WalletTabUM(
val text: TextReference,
val count: TextReference?,
val isSelected: Boolean,
val onClick: () -> Unit,
)
@Immutable
sealed interface TokenListUMData {
val tokensList: ImmutableList<TokensListItemUM>
val totalTokensCount: Int
data class AccountList(
override val tokensList: ImmutableList<TokensListItemUM.Portfolio>,
override val totalTokensCount: Int,
) : TokenListUMData
data class TokenList(
override val tokensList: ImmutableList<TokensListItemUM>,
override val totalTokensCount: Int,
) : TokenListUMData
data object EmptyList : TokenListUMData {
override val tokensList: ImmutableList<TokensListItemUM> = persistentListOf()
override val totalTokensCount: Int = EMPTY_TOKENS_COUNT
}
private companion object {
const val EMPTY_TOKENS_COUNT = 0
}
}

View file

@ -10,10 +10,11 @@ import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridge.Settings
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery
import com.tangem.feature.swap.choosetoken.api.ChooseTokenResult
import com.tangem.feature.swap.choosetoken.api.ChooseTokenResultOld
import com.tangem.feature.swap.choosetoken.api.model.ChooseTokenPortfolioFullBlockUM
import com.tangem.feature.swap.choosetoken.impl.model.ChooseTokenModel.Companion.DEBOUNCE_SEARCH_DELAY
import com.tangem.feature.swap.choosetoken.impl.model.PortfolioFullBlockDelegate
import com.tangem.feature.swap.choosetoken.impl.model.PortfolioListBlockDelegate
import com.tangem.feature.swap.domain.models.ui.CurrenciesGroup
import com.tangem.feature.swap.models.TokenListUMData
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -24,6 +25,7 @@ import kotlinx.coroutines.flow.*
internal class DefaultChooseTokenBridge @AssistedInject constructor(
@Assisted private val modelScope: CoroutineScope,
portfolioListBlockDelegateFactory: PortfolioListBlockDelegate.Factory,
portfolioFullBlockDelegateFactory: PortfolioFullBlockDelegate.Factory,
@Assisted override val settings: Settings,
@Assisted override val analyticsPayload: Set<ChooseTokenAnalyticsPayload>,
) : ChooseTokenBridge {
@ -44,10 +46,17 @@ internal class DefaultChooseTokenBridge @AssistedInject constructor(
searchQueryState = searchQueryState,
)
private val portfolioFullBlockDelegate: PortfolioFullBlockDelegate = portfolioFullBlockDelegateFactory.create(
modelScope = modelScope,
searchQueryState = searchQueryState,
portfolioListBlockDelegate = portfolioListBlockDelegate,
)
override val tokenFilter: MutableStateFlow<(AccountStatus.CryptoPortfolio, CryptoCurrencyStatus) -> Boolean>
get() = portfolioListBlockDelegate.tokenFilter
override val portfolioListBlock: Flow<Map<UserWalletId, TokenListUMData>>
get() = portfolioListBlockDelegate.portfolioList
override val fullPortfolioBlock: StateFlow<ChooseTokenPortfolioFullBlockUM?>
get() = portfolioFullBlockDelegate.fullPortfolioBlock
private val _currenciesGroupFlow = MutableStateFlow<CurrenciesGroup?>(null)
override val currenciesGroup: Flow<CurrenciesGroup> = _currenciesGroupFlow.filterNotNull()
@ -58,6 +67,10 @@ internal class DefaultChooseTokenBridge @AssistedInject constructor(
.launchIn(modelScope)
}
override fun selectWalletTab(walletId: UserWalletId) {
portfolioFullBlockDelegate.selectWalletTab(walletId)
}
override fun onSearchQuery(query: SearchQuery) {
onSearchQuery.trySend(query)
}

View file

@ -19,8 +19,8 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.tokenlist.TokenList
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery.Companion.isSearchingState
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.choosetoken.impl.model.ClickIntents
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.feature.swap.presentation.R
import kotlinx.collections.immutable.toPersistentList

View file

@ -5,27 +5,20 @@ 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.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.feature.swap.choosetoken.api.*
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery.Companion.isSearchingState
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.*
import com.tangem.feature.swap.choosetoken.impl.ui.ChooseTokenFullUM
import com.tangem.feature.swap.choosetoken.impl.ui.ChooseTokenInitialUM
import com.tangem.feature.swap.converters.TokensDataConverter
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
import com.tangem.feature.swap.models.market.state.SwapMarketState
import com.tangem.feature.swap.presentation.R
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
import javax.inject.Inject
@ -34,7 +27,6 @@ import javax.inject.Inject
internal class ChooseTokenModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val settingContextUseCase: SettingContextUseCase,
private val getWalletsUseCase: GetWalletsUseCase,
marketBlockDelegateFactory: MarketBlockDelegate.Factory,
paramsContainer: ParamsContainer,
) : Model() {
@ -61,25 +53,29 @@ internal class ChooseTokenModel @Inject constructor(
}
private val expandedAccountsFlow: MutableStateFlow<Map<AccountId, Boolean>> = MutableStateFlow(emptyMap())
private val onWalletSelected = Channel<UserWalletId>()
val stateOld: StateFlow<SwapSelectTokenStateHolder?> = combineUIOld()
private val contentState: StateFlow<ChooseTokenUM?> = combineUI()
private val initialState: MutableStateFlow<ChooseTokenInitialUM> = MutableStateFlow(getInitState())
val state: StateFlow<ChooseTokenFullUM> = combine(
flow = initialState,
flow2 = contentState,
transform = { initial, content ->
flow2 = bridge.fullPortfolioBlock,
flow3 = marketsStateFlow,
transform = { initial, content, marketBlock ->
ChooseTokenFullUM(
initialUM = initial,
contentUM = content,
portfolioBlock = content,
marketsBlock = marketBlock,
)
},
).stateIn(
scope = modelScope,
started = SharingStarted.Eagerly,
initialValue = ChooseTokenFullUM(initialState.value, contentState.value),
initialValue = ChooseTokenFullUM(
initialUM = initialState.value,
portfolioBlock = bridge.fullPortfolioBlock.value,
marketsBlock = null,
),
)
init {
@ -143,68 +139,6 @@ internal class ChooseTokenModel @Inject constructor(
.flowOn(dispatchers.default)
.stateIn(modelScope, SharingStarted.Eagerly, initialValue = null)
@Suppress("LongMethod")
private fun combineUI(): StateFlow<ChooseTokenUM?> = channelFlow {
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, firstSelectedWallet)
val fullPortfolioBlockFlow = combine(
flow = allWalletsFlow,
flow2 = bridge.portfolioListBlock,
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 searchResultCount: TextReference? = portfolioList[walletId]?.totalTokensCount
?.toString()
?.let(::stringReference)
?.takeIf { isSearchingState }
WalletTabUM(
text = stringReference(wallet.name),
onClick = { onWalletSelected.trySend(walletId) },
isSelected = selectedWalletId == walletId,
count = searchResultCount,
)
}
walletsUM to tokensListData
},
)
.filterNotNull()
.distinctUntilChanged()
combine(
flow = fullPortfolioBlockFlow,
flow2 = settingContextUseCase.invoke(),
flow3 = marketsStateFlow,
transform = { (walletList, tokensData), settings, marketsData ->
val walletsUM = if (walletList.size != 1) {
WalletListUM(walletList.toPersistentList())
} else {
WalletListUM(persistentListOf())
}
ChooseTokenUM(
walletList = walletsUM,
isBalanceHidden = settings.isBalanceHidden,
isSearching = isSearchingState,
tokensListData = tokensData,
marketsState = marketsData,
)
},
)
.distinctUntilChanged()
.collect { newUM -> channel.send(newUM) }
}
.flowOn(dispatchers.default)
.stateIn(modelScope, SharingStarted.Eagerly, initialValue = null)
fun onBackClicked() {
bridge.onClose()
}

View file

@ -0,0 +1,106 @@
package com.tangem.feature.swap.choosetoken.impl.model
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery.Companion.isSearchingState
import com.tangem.feature.swap.choosetoken.api.SettingContextUseCase
import com.tangem.feature.swap.choosetoken.api.model.ChooseTokenPortfolioFullBlockUM
import com.tangem.feature.swap.choosetoken.api.model.WalletListUM
import com.tangem.feature.swap.choosetoken.api.model.WalletTabUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
@Suppress("LongParameterList")
internal class PortfolioFullBlockDelegate @AssistedInject constructor(
private val settingContextUseCase: SettingContextUseCase,
private val getWalletsUseCase: GetWalletsUseCase,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val dispatchers: CoroutineDispatcherProvider,
private val selectedWalletUseCase: GetSelectedWalletUseCase,
@Assisted private val modelScope: CoroutineScope,
@Assisted private val portfolioListBlockDelegate: PortfolioListBlockDelegate,
@Assisted private val searchQueryState: StateFlow<SearchQuery>,
) {
private val isSearchingState: Boolean get() = searchQueryState.isSearchingState
private val onWalletSelected = Channel<UserWalletId>()
val selectedWalletFlow: SharedFlow<UserWallet> = onWalletSelected.receiveAsFlow()
.distinctUntilChanged()
.mapNotNull { walletId -> getUserWalletUseCase.invoke(walletId).getOrNull() }
.shareIn(modelScope, SharingStarted.Eagerly, replay = 1)
val fullPortfolioBlock: StateFlow<ChooseTokenPortfolioFullBlockUM?> = buildFlow()
.flowOn(dispatchers.default)
.stateIn(modelScope, SharingStarted.Eagerly, initialValue = null)
private fun buildFlow() = flow {
val isNoHaveSelectedWallet = selectedWalletFlow.replayCache.isEmpty()
if (isNoHaveSelectedWallet) {
val firstSelectedWallet = selectedWalletUseCase.sync().getOrNull()
?: getWalletsUseCase.invokeSync().first()
selectWalletTab(firstSelectedWallet.walletId)
}
val fullPortfolioBlockFlow = combine(
flow = getWalletsUseCase.invokeAsMap(),
flow2 = portfolioListBlockDelegate.portfolioList,
flow3 = selectedWalletFlow.map { wallet -> wallet.walletId }.distinctUntilChanged(),
flow4 = settingContextUseCase.invoke(),
transform = { allWallets, portfolioList, selectedWalletId, settings ->
val tokensListData = portfolioList[selectedWalletId] ?: return@combine null
val walletsUM = allWallets.entries
.map { (walletId, wallet) ->
val searchResultCount: TextReference? = portfolioList[walletId]?.totalTokensCount
?.toString()
?.let(::stringReference)
?.takeIf { isSearchingState }
WalletTabUM(
text = stringReference(wallet.name),
onClick = { selectWalletTab(walletId) },
isSelected = selectedWalletId == walletId,
count = searchResultCount,
)
}
val walletListUM = if (walletsUM.size != 1) {
WalletListUM(walletsUM.toPersistentList())
} else {
WalletListUM(persistentListOf())
}
ChooseTokenPortfolioFullBlockUM(
walletList = walletListUM,
isBalanceHidden = settings.isBalanceHidden,
isSearching = isSearchingState,
tokensListData = tokensListData,
)
},
)
emitAll(fullPortfolioBlockFlow)
}
fun selectWalletTab(walletId: UserWalletId) {
onWalletSelected.trySend(walletId)
}
@AssistedFactory
interface Factory {
fun create(
modelScope: CoroutineScope,
portfolioListBlockDelegate: PortfolioListBlockDelegate,
searchQueryState: StateFlow<SearchQuery>,
): PortfolioFullBlockDelegate
}
}

View file

@ -16,8 +16,8 @@ import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQ
import com.tangem.feature.swap.choosetoken.api.ChooseTokenBridgeInternal.SearchQuery.Companion.isSearchingState
import com.tangem.feature.swap.choosetoken.api.ChooseTokenResult
import com.tangem.feature.swap.choosetoken.api.SettingContextUseCase
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.choosetoken.impl.converter.ChooseTokenListItemConverter
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.utils.extensions.mapNotNullValues
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -41,7 +41,7 @@ internal class PortfolioListBlockDelegate @AssistedInject constructor(
val tokenFilter: MutableStateFlow<(AccountStatus.CryptoPortfolio, CryptoCurrencyStatus) -> Boolean> =
MutableStateFlow { _, _ -> true }
val portfolioList: Flow<Map<UserWalletId, TokenListUMData>> = buildDataFlow()
val portfolioList: SharedFlow<Map<UserWalletId, TokenListUMData>> = buildDataFlow()
.distinctUntilChanged()
.shareIn(modelScope, SharingStarted.Eagerly, replay = 1)

View file

@ -44,7 +44,10 @@ import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.BuyTokenScreenTestTags
import com.tangem.core.ui.utils.lazyListItemPosition
import com.tangem.core.ui.utils.rememberHideKeyboardNestedScrollConnection
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.feature.swap.choosetoken.api.model.ChooseTokenPortfolioFullBlockUM
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.choosetoken.api.model.WalletListUM
import com.tangem.feature.swap.choosetoken.api.model.WalletTabUM
import com.tangem.feature.swap.models.market.state.SwapMarketState
import com.tangem.feature.swap.presentation.R
import com.tangem.feature.swap.ui.market.swapMarketsListItems
@ -56,17 +59,25 @@ 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 ChooseTokenFullUM.isNotFoundState: Boolean
get() {
if (portfolioBlock == null) return false
if (marketsBlock == null) return false
return portfolioBlock.tokensListData.tokensList.isEmpty() &&
portfolioBlock.isSearching &&
marketsBlock !is SwapMarketState.Content &&
marketsBlock !is SwapMarketState.Loading
}
private val ChooseTokenUM.isEmptyState: Boolean
get() = tokensListData.tokensList.isEmpty() &&
!isSearching &&
marketsState !is SwapMarketState.Content &&
marketsState !is SwapMarketState.Loading
private val ChooseTokenFullUM.isEmptyState: Boolean
get() {
if (portfolioBlock == null) return false
if (marketsBlock == null) return false
return portfolioBlock.tokensListData.tokensList.isEmpty() &&
!portfolioBlock.isSearching &&
marketsBlock !is SwapMarketState.Content &&
marketsBlock !is SwapMarketState.Loading
}
@Composable
internal fun ChooseTokenScreen(state: ChooseTokenFullUM, modifier: Modifier = Modifier) {
@ -120,27 +131,27 @@ private fun Content(state: ChooseTokenFullUM, modifier: Modifier = Modifier) {
assetsTitle()
if (state.contentUM != null) {
walletListItem(state.contentUM.walletList)
if (state.portfolioBlock != null) {
walletListItem(state.portfolioBlock.walletList)
when {
state.contentUM.isNotFoundState -> tokensNotFound()
state.contentUM.isEmptyState -> emptyTokensList()
state.isNotFoundState -> tokensNotFound()
state.isEmptyState -> emptyTokensList()
else -> {
tokensListItems(
tokensListData = state.contentUM.tokensListData,
isBalanceHidden = state.contentUM.isBalanceHidden,
tokensListData = state.portfolioBlock.tokensListData,
isBalanceHidden = state.portfolioBlock.isBalanceHidden,
)
if (state.contentUM.marketsState != null) {
if (state.marketsBlock != null) {
item("markets_title_spacer") { SpacerH(height = 20.dp) }
swapMarketsListItems(state.contentUM.marketsState)
swapMarketsListItems(state.marketsBlock)
}
}
}
}
}
if (state.contentUM?.marketsState != null && !state.contentUM.isNotFoundState && !state.contentUM.isEmptyState) {
SetupMarketScrollTracker(state.contentUM.marketsState, lazyListState)
if (state.marketsBlock != null && !state.isNotFoundState && !state.isEmptyState) {
SetupMarketScrollTracker(state.marketsBlock, lazyListState)
}
}
@ -460,7 +471,7 @@ private class ChooseTokenScreenPreviewProvider : PreviewParameterProvider<Choose
override val values: Sequence<ChooseTokenFullUM> = sequenceOf(
ChooseTokenFullUM(
initialUM = initialUM,
contentUM = ChooseTokenUM(
portfolioBlock = ChooseTokenPortfolioFullBlockUM(
walletList = WalletListUM(wallets),
isBalanceHidden = false,
isSearching = false,
@ -468,18 +479,18 @@ private class ChooseTokenScreenPreviewProvider : PreviewParameterProvider<Choose
tokensList = accounts,
accounts.size,
),
marketsState = SwapSelectTokenPreviewProvider.defaultState.marketsState,
),
marketsBlock = SwapSelectTokenPreviewProvider.defaultState.marketsState,
),
ChooseTokenFullUM(
initialUM = initialUM,
contentUM = ChooseTokenUM(
portfolioBlock = ChooseTokenPortfolioFullBlockUM(
walletList = WalletListUM(wallets),
isBalanceHidden = false,
isSearching = false,
tokensListData = TokenListUMData.EmptyList,
marketsState = null,
),
marketsBlock = null,
),
)
}

View file

@ -2,36 +2,17 @@ package com.tangem.feature.swap.choosetoken.impl.ui
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.feature.swap.choosetoken.api.model.ChooseTokenPortfolioFullBlockUM
import com.tangem.feature.swap.models.market.state.SwapMarketState
import kotlinx.collections.immutable.ImmutableList
internal data class ChooseTokenFullUM(
val initialUM: ChooseTokenInitialUM,
val contentUM: ChooseTokenUM?,
)
internal data class ChooseTokenUM(
val walletList: WalletListUM,
val isBalanceHidden: Boolean,
val isSearching: Boolean,
val tokensListData: TokenListUMData,
val marketsState: SwapMarketState?,
val portfolioBlock: ChooseTokenPortfolioFullBlockUM?,
val marketsBlock: SwapMarketState?,
)
internal data class ChooseTokenInitialUM(
val screenTitle: TextReference,
val onCloseClick: () -> Unit,
val searchBar: SearchBarUM,
)
internal data class WalletListUM(
val items: ImmutableList<WalletTabUM>,
)
internal data class WalletTabUM(
val text: TextReference,
val count: TextReference?,
val isSelected: Boolean,
val onClick: () -> Unit,
)

View file

@ -6,9 +6,9 @@ import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.account.Account
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.domain.models.ui.CurrenciesGroup
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 kotlinx.collections.immutable.persistentListOf

View file

@ -1,10 +1,7 @@
package com.tangem.feature.swap.models
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.models.market.state.SwapMarketState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
internal data class SwapSelectTokenStateHolder(
val marketsState: SwapMarketState,
@ -14,32 +11,6 @@ internal data class SwapSelectTokenStateHolder(
val onSearchEntered: (String) -> Unit,
)
@Immutable
sealed interface TokenListUMData {
val tokensList: ImmutableList<TokensListItemUM>
val totalTokensCount: Int
data class AccountList(
override val tokensList: ImmutableList<TokensListItemUM.Portfolio>,
override val totalTokensCount: Int,
) : TokenListUMData
data class TokenList(
override val tokensList: ImmutableList<TokensListItemUM>,
override val totalTokensCount: Int,
) : TokenListUMData
data object EmptyList : TokenListUMData {
override val tokensList: ImmutableList<TokensListItemUM> = persistentListOf()
override val totalTokensCount: Int = EMPTY_TOKENS_COUNT
}
private companion object {
const val EMPTY_TOKENS_COUNT = 0
}
}
internal val SwapSelectTokenStateHolder.isNotFoundState: Boolean
get() =
tokensListData.tokensList.isEmpty() && isAfterSearch &&

View file

@ -39,8 +39,8 @@ import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.BuyTokenScreenTestTags
import com.tangem.core.ui.test.MainScreenTestTags
import com.tangem.core.ui.utils.lazyListItemPosition
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.feature.swap.models.isEmptyState
import com.tangem.feature.swap.models.isNotFoundState
import com.tangem.feature.swap.models.market.state.SwapMarketState

View file

@ -13,8 +13,8 @@ import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.feature.swap.choosetoken.api.model.TokenListUMData
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
import com.tangem.feature.swap.models.TokenListUMData
import com.tangem.feature.swap.models.market.state.SwapMarketState
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList