Updated on 2026-08-14
This commit is contained in:
parent
93c1276828
commit
77a12bcb13
13 changed files with 235 additions and 166 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue