Updated on 2026-08-14
This commit is contained in:
parent
ae4029c4d5
commit
7db3810064
16 changed files with 159 additions and 40 deletions
|
|
@ -5,10 +5,7 @@ import androidx.compose.runtime.*
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.childStack
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.arkivanov.decompose.router.stack.*
|
||||
import com.arkivanov.decompose.value.Value
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
|
|
@ -87,8 +84,9 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onMarketOpenClick(sortBy: SortByTypeUM?) {
|
||||
innerRouter.push(
|
||||
route = FeedEntryChildFactory.Child.TokenList(
|
||||
// Markets list and search can reach each other
|
||||
stackNavigation.bringToFront(
|
||||
FeedEntryChildFactory.Child.TokenList(
|
||||
params = DefaultMarketsTokenListComponent.Params(
|
||||
preselectedSortType = sortBy ?: SortByTypeUM.Rating,
|
||||
preselectedInterval = MarketsListUM.TrendInterval.H24,
|
||||
|
|
@ -142,7 +140,7 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun openSearch(source: String) {
|
||||
innerRouter.push(FeedEntryChildFactory.Child.Search(source))
|
||||
stackNavigation.bringToFront(FeedEntryChildFactory.Child.Search(source))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,17 +7,18 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.navigation.Route
|
||||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioComponent
|
||||
import com.tangem.features.feed.components.earn.DefaultEarnComponent
|
||||
import com.tangem.features.feed.components.feed.DefaultFeedComponent
|
||||
import com.tangem.features.feed.components.feed.DefaultFeedComponent.FeedParams
|
||||
import com.tangem.features.feed.components.market.details.DefaultMarketsTokenDetailsComponent
|
||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioComponent
|
||||
import com.tangem.features.feed.components.market.details.portfolio.api.MarketsPortfolioComponent
|
||||
import com.tangem.features.feed.components.market.details.portfolioblock.PortfolioBlockComponent
|
||||
import com.tangem.features.feed.components.market.list.DefaultMarketsTokenListComponent
|
||||
import com.tangem.features.feed.components.news.details.DefaultNewsDetailsComponent
|
||||
import com.tangem.features.feed.components.news.list.DefaultNewsListComponent
|
||||
import com.tangem.features.feed.components.search.DefaultSearchComponent
|
||||
import com.tangem.features.feed.model.market.list.state.SortByTypeUM
|
||||
import com.tangem.features.promobanners.api.PromoBannersBlockComponent
|
||||
import kotlinx.serialization.Serializable
|
||||
import javax.inject.Inject
|
||||
|
|
@ -142,6 +143,7 @@ internal class FeedEntryChildFactory @Inject constructor(
|
|||
)
|
||||
},
|
||||
sourceParams = child.source,
|
||||
onSeeAllMarketsClick = { feedEntryClickIntents.onMarketOpenClick(SortByTypeUM.Rating) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,11 +84,14 @@ internal class DefaultSearchComponent(
|
|||
onTextHintClick = model::onTextHintClick,
|
||||
onResultMarketTokenClick = model::onResultMarketTokenClick,
|
||||
onHistoryTokenClick = model::onHistoryTokenClick,
|
||||
onTopMarketSeeAllClick = model::onTopMarketSeeAllClick,
|
||||
onTopMarketItemClick = model::onTopMarketItemClick,
|
||||
)
|
||||
}
|
||||
SearchContent(
|
||||
modifier = modifier,
|
||||
content = state.content,
|
||||
topMarkets = state.topMarkets,
|
||||
searchCallbacks = searchCallbacks,
|
||||
contentPadding = contentPadding,
|
||||
)
|
||||
|
|
@ -114,5 +117,6 @@ internal class DefaultSearchComponent(
|
|||
val onBackClick: () -> Unit,
|
||||
val onMarketTokenClick: ((TokenMarketParams, AppCurrency) -> Unit),
|
||||
val sourceParams: String,
|
||||
val onSeeAllMarketsClick: () -> Unit,
|
||||
)
|
||||
}
|
||||
|
|
@ -29,14 +29,9 @@ internal class FeedMarketsBatchFlowManager(
|
|||
private val currentAppCurrency: Provider<AppCurrency>,
|
||||
private val modelScope: CoroutineScope,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
orders: List<TokenMarketListConfig.Order> = TokenMarketListConfig.Order.entries,
|
||||
) {
|
||||
private val managersByOrder = listOf(
|
||||
TokenMarketListConfig.Order.ByRating,
|
||||
TokenMarketListConfig.Order.Trending,
|
||||
TokenMarketListConfig.Order.Buyers,
|
||||
TokenMarketListConfig.Order.TopGainers,
|
||||
TokenMarketListConfig.Order.TopLosers,
|
||||
).associateWith { order ->
|
||||
private val managersByOrder = orders.associateWith { order ->
|
||||
createManagerForOrder(order)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.tangem.domain.search.usecase.SaveRecentSearchTokenUseCase
|
|||
import com.tangem.domain.search.usecase.SaveSearchQueryUseCase
|
||||
import com.tangem.features.feed.components.search.DefaultSearchComponent
|
||||
import com.tangem.features.feed.components.search.SearchBottomSheetRoute
|
||||
import com.tangem.features.feed.model.feed.state.FeedMarketsBatchFlowManager
|
||||
import com.tangem.features.feed.model.market.list.state.MarketsListUM
|
||||
import com.tangem.features.feed.model.market.list.state.SortByTypeUM
|
||||
import com.tangem.features.feed.model.market.list.statemanager.MarketsListBatchFlowManager
|
||||
|
|
@ -33,6 +34,8 @@ import com.tangem.features.feed.model.search.analytics.SearchAnalyticsHelper
|
|||
import com.tangem.features.feed.model.search.converter.*
|
||||
import com.tangem.features.feed.model.search.state.SearchStateController
|
||||
import com.tangem.features.feed.model.search.state.transformers.*
|
||||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
import com.tangem.features.feed.ui.feed.state.SortChartConfigUM
|
||||
import com.tangem.features.feed.ui.search.state.MarketSearchResultUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchContentUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchUM
|
||||
|
|
@ -42,6 +45,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
|||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -57,6 +61,7 @@ internal class SearchModel @Inject constructor(
|
|||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
paramsContainer: ParamsContainer,
|
||||
getMarketsTokenListFlowUseCase: GetMarketsTokenListFlowUseCase,
|
||||
private val getTopFiveMarketTokenUseCase: GetTopFiveMarketTokenUseCase,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val getSearchResultsUseCase: GetSearchResultsUseCase,
|
||||
|
|
@ -115,6 +120,16 @@ internal class SearchModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private val topMarketsManager by lazy {
|
||||
FeedMarketsBatchFlowManager(
|
||||
getTopFiveMarketTokenUseCase = getTopFiveMarketTokenUseCase,
|
||||
currentAppCurrency = Provider { currentAppCurrency.value },
|
||||
modelScope = modelScope,
|
||||
dispatchers = dispatchers,
|
||||
orders = listOf(TokenMarketListConfig.Order.ByRating),
|
||||
)
|
||||
}
|
||||
|
||||
val bottomSheetNavigation: SlotNavigation<SearchBottomSheetRoute> = SlotNavigation()
|
||||
|
||||
val state: StateFlow<SearchUM> get() = stateController.uiState
|
||||
|
|
@ -127,6 +142,7 @@ internal class SearchModel @Inject constructor(
|
|||
subscribeToAppCurrencyChanges()
|
||||
subscribeToMarketLoadingErrors()
|
||||
subscribeToResultsShown()
|
||||
subscribeToTopMarkets()
|
||||
loadHistory()
|
||||
searchAnalyticsHelper.sendSearchScreenOpened(params.sourceParams)
|
||||
}
|
||||
|
|
@ -190,6 +206,15 @@ internal class SearchModel @Inject constructor(
|
|||
params.onMarketTokenClick(tokenMarketParams, currentAppCurrency.value)
|
||||
}
|
||||
|
||||
fun onTopMarketSeeAllClick() {
|
||||
params.onSeeAllMarketsClick()
|
||||
}
|
||||
|
||||
fun onTopMarketItemClick(item: MarketsListItemUM) {
|
||||
val token = topMarketsManager.getTokenMarketById(item.id) ?: return
|
||||
params.onMarketTokenClick(token.toSerializableParam(), currentAppCurrency.value)
|
||||
}
|
||||
|
||||
private fun initCallbacks() {
|
||||
stateController.update(object : SearchUMTransformer {
|
||||
override fun transform(prevState: SearchUM): SearchUM {
|
||||
|
|
@ -402,6 +427,35 @@ internal class SearchModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun subscribeToTopMarkets() {
|
||||
combine(
|
||||
topMarketsManager.itemsByOrder,
|
||||
topMarketsManager.loadingStatesByOrder,
|
||||
topMarketsManager.errorStatesByOrder,
|
||||
) { itemsByOrder, _, errorsByOrder ->
|
||||
val ratingItems = itemsByOrder[SortByTypeUM.Rating] ?: persistentListOf()
|
||||
val error = errorsByOrder[SortByTypeUM.Rating]
|
||||
when {
|
||||
ratingItems.isNotEmpty() -> MarketChartUM.Content(
|
||||
items = ratingItems,
|
||||
sortChartConfig = SortChartConfigUM(sortByType = SortByTypeUM.Rating, isSelected = true),
|
||||
)
|
||||
error != null -> MarketChartUM.LoadingError(
|
||||
onRetryClicked = { topMarketsManager.reloadManager(TokenMarketListConfig.Order.ByRating) },
|
||||
)
|
||||
else -> MarketChartUM.Loading
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.onEach { chart ->
|
||||
stateController.update(SetTopMarketsTransformer(chart))
|
||||
if (chart is MarketChartUM.Content) {
|
||||
topMarketsManager.loadCharts(TokenMarketListConfig.Order.ByRating)
|
||||
}
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun loadHistory() {
|
||||
modelScope.launch {
|
||||
getSearchResultsUseCase(query = "").collectLatest { searchResult ->
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.features.feed.impl.R
|
||||
import com.tangem.features.feed.model.search.state.transformers.SearchUMTransformer
|
||||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchContentUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchUM
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -38,6 +39,7 @@ internal class SearchStateController @Inject constructor() {
|
|||
onClearClick = {},
|
||||
),
|
||||
content = SearchContentUM.InitialEmpty,
|
||||
topMarkets = MarketChartUM.Loading,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.features.feed.model.search.state.transformers
|
||||
|
||||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchUM
|
||||
|
||||
internal class SetTopMarketsTransformer(private val topMarkets: MarketChartUM) : SearchUMTransformer {
|
||||
|
||||
override fun transform(prevState: SearchUM): SearchUM {
|
||||
return prevState.copy(topMarkets = topMarkets)
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +109,9 @@ private fun FeedListContent(
|
|||
|
||||
MarketBlock(
|
||||
marketChart = state.marketChartConfig.marketCharts[SortByTypeUM.Rating],
|
||||
feedListCallbacks = state.feedListCallbacks,
|
||||
onSeeAllClick = { state.feedListCallbacks.onMarketOpenClick(SortByTypeUM.Rating) },
|
||||
onItemClick = state.feedListCallbacks.onMarketItemClick,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
|
||||
promoBannersBlockComponent?.Content(
|
||||
|
|
|
|||
|
|
@ -28,17 +28,19 @@ internal fun ColumnScope.Header(
|
|||
onSeeAllClick: () -> Unit,
|
||||
isLoading: Boolean,
|
||||
shouldShowSeeAll: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
title: @Composable () -> Unit,
|
||||
) {
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
if (isRedesignEnabled) {
|
||||
SpacerH(12.dp)
|
||||
}
|
||||
AnimatedContent(isLoading) { animatedState ->
|
||||
AnimatedContent(
|
||||
targetState = isLoading,
|
||||
modifier = modifier,
|
||||
) { animatedState ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ private fun EarnBlockV1(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modif
|
|||
onSeeAllClick = onSeeAllClick,
|
||||
isLoading = earnListUM is EarnListUM.Loading,
|
||||
shouldShowSeeAll = earnListUM is EarnListUM.Content,
|
||||
modifier = Modifier.padding(horizontal = 20.dp),
|
||||
)
|
||||
|
||||
SpacerH(12.dp)
|
||||
|
|
@ -96,6 +97,7 @@ private fun EarnBlockV2(onSeeAllClick: () -> Unit, earnListUM: EarnListUM, modif
|
|||
onSeeAllClick = onSeeAllClick,
|
||||
isLoading = earnListUM is EarnListUM.Loading,
|
||||
shouldShowSeeAll = earnListUM is EarnListUM.Content,
|
||||
modifier = Modifier.padding(horizontal = 20.dp),
|
||||
)
|
||||
|
||||
SpacerH(12.dp)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,12 @@ import com.tangem.features.feed.ui.feed.state.MarketChartConfig
|
|||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
|
||||
@Composable
|
||||
internal fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedListCallbacks) {
|
||||
internal fun MarketBlock(
|
||||
marketChart: MarketChartUM?,
|
||||
onSeeAllClick: () -> Unit,
|
||||
onItemClick: (MarketsListItemUM) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
AnimatedContent(
|
||||
targetState = marketChart,
|
||||
|
|
@ -48,7 +53,7 @@ internal fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedLis
|
|||
MarketChartUM.Loading,
|
||||
is MarketChartUM.LoadingError,
|
||||
-> {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Column(modifier = modifier.fillMaxWidth()) {
|
||||
Header(
|
||||
title = {
|
||||
Text(
|
||||
|
|
@ -67,16 +72,18 @@ internal fun MarketBlock(marketChart: MarketChartUM?, feedListCallbacks: FeedLis
|
|||
maxLines = 1,
|
||||
)
|
||||
},
|
||||
onSeeAllClick = { feedListCallbacks.onMarketOpenClick(SortByTypeUM.Rating) },
|
||||
onSeeAllClick = onSeeAllClick,
|
||||
shouldShowSeeAll = currentChart is MarketChartUM.Content,
|
||||
isLoading = currentChart is MarketChartUM.Loading,
|
||||
// Header text is inset so it aligns with the list item text inside the card; the card itself
|
||||
// sits at the block edge (supplied by [modifier]).
|
||||
modifier = Modifier.padding(horizontal = MARKET_BLOCK_HEADER_PADDING),
|
||||
)
|
||||
|
||||
SpacerH(if (isRedesignEnabled) 20.dp else 12.dp)
|
||||
|
||||
Charts(
|
||||
onItemClick = feedListCallbacks.onMarketItemClick,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
onItemClick = onItemClick,
|
||||
marketChart = currentChart,
|
||||
)
|
||||
}
|
||||
|
|
@ -115,6 +122,7 @@ internal fun ColumnScope.MarketPulseBlock(marketChartConfig: MarketChartConfig,
|
|||
onSeeAllClick = { onSeeAllClick() },
|
||||
shouldShowSeeAll = true,
|
||||
isLoading = marketChartConfig.marketCharts[marketChartConfig.currentSortByType] is MarketChartUM.Loading,
|
||||
modifier = Modifier.padding(horizontal = 20.dp),
|
||||
)
|
||||
|
||||
LazyRow(
|
||||
|
|
@ -219,4 +227,7 @@ private fun Charts(
|
|||
}
|
||||
}
|
||||
|
||||
private const val DEFAULT_CHART_SIZE_IN_MARKET = 5
|
||||
private const val DEFAULT_CHART_SIZE_IN_MARKET = 5
|
||||
|
||||
/** Header inset so its text aligns with the list item text inside the card (the card sits at the block edge). */
|
||||
private val MARKET_BLOCK_HEADER_PADDING = 4.dp
|
||||
|
|
@ -2,11 +2,7 @@ package com.tangem.features.feed.ui.feed.components
|
|||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
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.foundation.layout.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -148,6 +144,7 @@ private fun NewsContentBlock(feedListCallbacks: FeedListCallbacks, news: NewsUM,
|
|||
onSeeAllClick = { feedListCallbacks.onOpenAllNews(false) },
|
||||
isLoading = news.newsUMState == NewsUMState.LOADING,
|
||||
shouldShowSeeAll = news.newsUMState == NewsUMState.CONTENT,
|
||||
modifier = Modifier.padding(horizontal = 20.dp),
|
||||
)
|
||||
SpacerH(12.dp)
|
||||
|
||||
|
|
@ -200,6 +197,7 @@ private fun NewsErrorBlock(onRetryClick: () -> Unit) {
|
|||
onSeeAllClick = {},
|
||||
shouldShowSeeAll = false,
|
||||
isLoading = false,
|
||||
modifier = Modifier.padding(horizontal = 20.dp),
|
||||
)
|
||||
SpacerH(12.dp)
|
||||
BlockCard(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,12 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.feed.ui.search.state.*
|
||||
import com.tangem.features.feed.ui.feed.components.MarketBlock
|
||||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
import com.tangem.features.feed.ui.search.state.MarketSearchResultUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchCallbacks
|
||||
import com.tangem.features.feed.ui.search.state.SearchContentUM
|
||||
import com.tangem.features.feed.ui.search.state.TextHintItemUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
private const val PLACEHOLDER_COUNT = 10
|
||||
|
|
@ -46,6 +51,7 @@ private const val USER_ASSETS_LIMIT = 3
|
|||
@Composable
|
||||
internal fun SearchContent(
|
||||
content: SearchContentUM,
|
||||
topMarkets: MarketChartUM,
|
||||
searchCallbacks: SearchCallbacks,
|
||||
contentPadding: PaddingValues,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -85,12 +91,16 @@ internal fun SearchContent(
|
|||
) {
|
||||
when (content) {
|
||||
is SearchContentUM.InitialEmpty -> Unit
|
||||
is SearchContentUM.History -> searchHistoryItems(
|
||||
history = content,
|
||||
onClearAllClick = searchCallbacks.onClearHintsClick,
|
||||
onHintClick = searchCallbacks.onTextHintClick,
|
||||
onHistoryTokenClick = searchCallbacks.onHistoryTokenClick,
|
||||
)
|
||||
is SearchContentUM.History -> if (content.textHints.isEmpty() && content.recentTokens.isEmpty()) {
|
||||
topMarketsBlock(topMarkets, searchCallbacks)
|
||||
} else {
|
||||
searchHistoryItems(
|
||||
history = content,
|
||||
onClearAllClick = searchCallbacks.onClearHintsClick,
|
||||
onHintClick = searchCallbacks.onTextHintClick,
|
||||
onHistoryTokenClick = searchCallbacks.onHistoryTokenClick,
|
||||
)
|
||||
}
|
||||
is SearchContentUM.Results -> searchResultsItems(
|
||||
results = content,
|
||||
isUserAssetsExpanded = isUserAssetsExpanded,
|
||||
|
|
@ -114,6 +124,16 @@ internal fun SearchContent(
|
|||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.topMarketsBlock(topMarkets: MarketChartUM, searchCallbacks: SearchCallbacks) {
|
||||
item(key = "top_markets") {
|
||||
MarketBlock(
|
||||
marketChart = topMarkets,
|
||||
onSeeAllClick = searchCallbacks.onTopMarketSeeAllClick,
|
||||
onItemClick = searchCallbacks.onTopMarketItemClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.searchHistoryItems(
|
||||
history: SearchContentUM.History,
|
||||
onClearAllClick: (() -> Unit),
|
||||
|
|
|
|||
|
|
@ -21,8 +21,14 @@ import com.tangem.core.ui.extensions.stringReference
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.feed.model.market.list.state.SortByTypeUM
|
||||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
import com.tangem.features.feed.ui.feed.state.SortChartConfigUM
|
||||
import com.tangem.features.feed.ui.search.SearchContent
|
||||
import com.tangem.features.feed.ui.search.state.*
|
||||
import com.tangem.features.feed.ui.search.state.MarketSearchResultUM
|
||||
import com.tangem.features.feed.ui.search.state.SearchCallbacks
|
||||
import com.tangem.features.feed.ui.search.state.SearchContentUM
|
||||
import com.tangem.features.feed.ui.search.state.TextHintItemUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
|
@ -373,6 +379,11 @@ internal object SearchContentPreviewFixtures {
|
|||
),
|
||||
).toImmutableList()
|
||||
|
||||
fun topMarketsContent(): MarketChartUM = MarketChartUM.Content(
|
||||
items = marketListShort(),
|
||||
sortChartConfig = SortChartConfigUM(sortByType = SortByTypeUM.Rating, isSelected = true),
|
||||
)
|
||||
|
||||
fun allScenarios(): List<SearchContentPreviewScenario> = listOf(
|
||||
scenarioInitialEmpty,
|
||||
scenarioHistoryEmptyBoth,
|
||||
|
|
@ -398,6 +409,8 @@ private val SearchContentPreviewCallbacks = SearchCallbacks(
|
|||
onTextHintClick = { _ -> },
|
||||
onResultMarketTokenClick = { _ -> },
|
||||
onHistoryTokenClick = { _ -> },
|
||||
onTopMarketSeeAllClick = {},
|
||||
onTopMarketItemClick = { _ -> },
|
||||
)
|
||||
|
||||
/** All [SearchContentPreviewScenario] values for the Preview Parameter dropdown in Android Studio. */
|
||||
|
|
@ -420,6 +433,7 @@ private fun SearchContentPreviewHost(
|
|||
) {
|
||||
SearchContent(
|
||||
content = scenario.content,
|
||||
topMarkets = SearchContentPreviewFixtures.topMarketsContent(),
|
||||
searchCallbacks = SearchContentPreviewCallbacks,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(),
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@ internal data class SearchCallbacks(
|
|||
val onTextHintClick: (hint: String) -> Unit,
|
||||
val onResultMarketTokenClick: (MarketsListItemUM) -> Unit,
|
||||
val onHistoryTokenClick: (MarketsListItemUM) -> Unit,
|
||||
val onTopMarketSeeAllClick: () -> Unit,
|
||||
val onTopMarketItemClick: (MarketsListItemUM) -> Unit,
|
||||
)
|
||||
|
|
@ -4,11 +4,13 @@ import androidx.compose.runtime.Immutable
|
|||
import com.tangem.common.ui.markets.models.MarketsListItemUM
|
||||
import com.tangem.common.ui.markets.tokenselector.UserAssetItemUM
|
||||
import com.tangem.core.ui.components.fields.entity.SearchBarUM
|
||||
import com.tangem.features.feed.ui.feed.state.MarketChartUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class SearchUM(
|
||||
internal data class SearchUM(
|
||||
val searchBar: SearchBarUM,
|
||||
val content: SearchContentUM,
|
||||
val topMarkets: MarketChartUM,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue