diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt b/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt index 9d5c548b93..8f5f5ba4b7 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt @@ -4,8 +4,13 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.* @Composable -fun InfiniteListHandler(listState: LazyListState, onLoadMore: () -> Boolean, buffer: Int = 2) { - val loadMore by remember { +fun InfiniteListHandler( + listState: LazyListState, + onLoadMore: () -> Boolean, + buffer: Int = 2, + triggerLoadMoreCheckOnItemsCountChange: Boolean = false, +) { + val loadMore by remember(buffer, listState) { derivedStateOf { val layoutInfo = listState.layoutInfo val totalItemsNumber = layoutInfo.totalItemsCount @@ -15,12 +20,18 @@ fun InfiniteListHandler(listState: LazyListState, onLoadMore: () -> Boolean, buf } } - val totalItemsCount by remember { derivedStateOf { listState.layoutInfo.totalItemsCount } } - var emitted by remember(totalItemsCount) { mutableStateOf(false) } + val totalItemsCount by remember(listState) { derivedStateOf { listState.layoutInfo.totalItemsCount } } + var emitted by remember(totalItemsCount, buffer, listState) { mutableStateOf(false) } LaunchedEffect(loadMore) { if (loadMore && !emitted) { emitted = onLoadMore() } } + + LaunchedEffect(totalItemsCount) { + if (triggerLoadMoreCheckOnItemsCountChange && loadMore && !emitted) { + emitted = onLoadMore() + } + } } \ No newline at end of file diff --git a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt index 95fb2cca25..18c7155b03 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt @@ -9,6 +9,7 @@ import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.markets.TangemTechMarketsApi import com.tangem.datasource.api.markets.models.response.TokenMarketChartListResponse import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.TangemTechApi.Companion.marketsQuoteFields import com.tangem.domain.markets.TokenMarket import com.tangem.domain.markets.TokenMarketUpdateRequest import com.tangem.pagination.Batch @@ -70,7 +71,7 @@ internal class MarketsBatchUpdateFetcher( tangemTechApi.getQuotes( currencyId = updateRequest.currencyId, coinIds = idsToUpdate.map { it.second }.flatten().joinToString(separator = ","), - fields = quoteFields.joinToString(separator = ","), + fields = marketsQuoteFields.joinToString(separator = ","), ).getOrThrow() } } @@ -120,13 +121,4 @@ internal class MarketsBatchUpdateFetcher( throw e } } - - companion object { - private val quoteFields = listOf( - "price", - "priceChange24h", - "priceChange1w", - "priceChange30d", - ) - } } \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt index f22b26c622..65d8c2df96 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt @@ -14,7 +14,6 @@ import com.tangem.features.markets.tokenlist.impl.ui.state.MarketsListUM import com.tangem.features.markets.tokenlist.impl.ui.state.SortByTypeUM import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.* @@ -111,54 +110,55 @@ internal class MarketsListUMStateManager( private fun MarketsListUM.updateItems(newItems: ImmutableList): MarketsListUM { val currentState = this - val isNextPageInSearch = isInSearchState && (this.list as? ListUM.Content)?.showUnder100kTokens == true - var searchUiItemsCached: ImmutableList = persistentListOf() - val items = when { - isInSearchState && isNextPageInSearch.not() -> { - searchUiItemsCached = newItems - val filtered = newItems.filter { item -> item.isUnder100kMarketCap.not() }.toImmutableList() + if (isInSearchMode.not() || currentState.showUnder100kButtonAlreadyPressed()) { + val itemsWithFilteredPriceChange = newItems.filterPriceChangeByVisibility() - if (filtered.size == newItems.size) { - return currentState.copy(list = generalContentState(newItems)) - } else { - filtered - } - } - else -> { - searchUiItemsCached = persistentListOf() - newItems - } + return currentState.copy( + list = generalContentState(itemsWithFilteredPriceChange) + .copy( + showUnder100kTokensNotificationWasHidden = currentState.showUnder100kButtonAlreadyPressed(), + ), + ) } - val itemsWithFilteredPriceChange = items.filterPriceChangeByVisibility() + // Search state cases - return currentState.copy( - list = ListUM.Content( - items = itemsWithFilteredPriceChange, - loadMore = onLoadMoreUiItems, - visibleIdsChanged = visibleItemsChanged, - showUnder100kTokens = isInSearchState.not() || isNextPageInSearch, - onShowTokensUnder100kClicked = { - if (searchUiItemsCached.isNotEmpty()) { + val filtered = newItems.filter { item -> item.isUnder100kMarketCap.not() } + .toImmutableList() + .filterPriceChangeByVisibility() + + if (filtered.size != newItems.size) { + val searchUiItemsCached = newItems.filterPriceChangeByVisibility() + + return currentState.copy( + list = generalContentState(filtered).copy( + showUnder100kTokensNotificationWasHidden = false, + showUnder100kTokensNotification = true, + onShowTokensUnder100kClicked = { state.update { s -> - if (s.list is ListUM.Content) { + (s.list as? ListUM.Content)?.let { s.copy( list = s.list.copy( items = searchUiItemsCached, - showUnder100kTokens = true, + showUnder100kTokensNotification = false, + showUnder100kTokensNotificationWasHidden = true, ), ) - } else { - s - } + } ?: s } - } - }, - triggerScrollReset = consumedEvent(), - onItemClick = onTokenClick, - ), - ) + }, + ), + ) + } else { + return currentState.copy( + list = generalContentState(newItems.filterPriceChangeByVisibility()), + ) + } + } + + private fun MarketsListUM.showUnder100kButtonAlreadyPressed(): Boolean { + return this.list is ListUM.Content && this.isInSearchMode && this.list.showUnder100kTokensNotificationWasHidden } // Show price change animation for visible items only @@ -182,10 +182,11 @@ internal class MarketsListUMStateManager( items = newItems, loadMore = onLoadMoreUiItems, visibleIdsChanged = visibleItemsChanged, - showUnder100kTokens = true, + showUnder100kTokensNotification = false, onShowTokensUnder100kClicked = {}, triggerScrollReset = consumedEvent(), onItemClick = onTokenClick, + showUnder100kTokensNotificationWasHidden = false, ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt index 9c52cb6bdb..6847621b60 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt @@ -301,7 +301,8 @@ private fun Preview() { item.copy(id = index.toString()) } .toImmutableList(), - showUnder100kTokens = false, + showUnder100kTokensNotification = false, + showUnder100kTokensNotificationWasHidden = false, loadMore = {}, visibleIdsChanged = {}, onShowTokensUnder100kClicked = {}, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt index 5d70d6e85e..f4dd833503 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt @@ -22,6 +22,7 @@ import com.tangem.features.markets.tokenlist.impl.ui.state.ListUM import kotlinx.coroutines.launch private const val LOAD_NEXT_PAGE_ON_END_INDEX = 50 +private const val LOAD_NEXT_PAGE_ON_END_INDEX_SEARCH = 25 private const val TOKEN_LAZY_LIST_ID_SEPARATOR = "***" @Composable @@ -95,7 +96,7 @@ internal fun MarketsListLazyColumn( ) } - if (isInSearchMode && state.showUnder100kTokens.not()) { + if (isInSearchMode && state.showUnder100kTokensNotification) { item(key = "show tokens under 100k".hashCode()) { ShowTokensUnder100kItem( onShowTokensClick = state.onShowTokensUnder100kClicked, @@ -112,10 +113,15 @@ internal fun MarketsListLazyColumn( InfiniteListHandler( listState = lazyListState, - buffer = LOAD_NEXT_PAGE_ON_END_INDEX, + buffer = if (isInSearchMode) { + LOAD_NEXT_PAGE_ON_END_INDEX_SEARCH + } else { + LOAD_NEXT_PAGE_ON_END_INDEX + }, + triggerLoadMoreCheckOnItemsCountChange = true, onLoadMore = remember(state) { { - if (state is ListUM.Content && state.showUnder100kTokens) { + if (state is ListUM.Content && state.showUnder100kTokensNotification.not()) { state.loadMore() true } else { diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt index 41d1596f68..e0c4a52d54 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt @@ -22,6 +22,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -34,6 +35,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet trendPercentText = "12.43%", trendType = PriceChangeType.NEUTRAL, chardData = null, + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -48,6 +50,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -62,6 +65,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -76,6 +80,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -90,6 +95,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), ), ) \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt index 9f3821c9c5..9bc808aee8 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt @@ -17,7 +17,7 @@ data class MarketsListItemUM( val trendPercentText: String, val trendType: PriceChangeType, val chardData: MarketChartRawData?, - val isUnder100kMarketCap: Boolean = false, + val isUnder100kMarketCap: Boolean, ) { val chartType: MarketChartLook.Type = when (trendType) { PriceChangeType.UP -> MarketChartLook.Type.Growing diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt index 7906cc1fb9..10ed82175e 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt @@ -41,7 +41,8 @@ sealed class ListUM { data class Content( val items: ImmutableList, - val showUnder100kTokens: Boolean, + val showUnder100kTokensNotification: Boolean, + val showUnder100kTokensNotificationWasHidden: Boolean, val loadMore: () -> Unit, val visibleIdsChanged: (List) -> Unit, val onShowTokensUnder100kClicked: () -> Unit, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index fc8d3b6572..7243dbb143 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -462,7 +462,9 @@ private inline fun BaseScaffoldWithMarkets( color = BottomSheetDefaults.ScrimColor, visible = bottomSheetState.targetValue == TangemSheetValue.Expanded || state.showMarketsOnboarding, - onDismissRequest = { coroutineScope.launch { bottomSheetState.partialExpand() } }, + onDismissRequest = { + coroutineScope.launch { bottomSheetState.partialExpand() } + }, ) MarketsTooltip( @@ -486,7 +488,6 @@ private inline fun BaseScaffoldWithMarkets( } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun MarketsTooltip( availableHeight: Dp, @@ -644,6 +645,21 @@ private fun BottomSheetStateEffects( val systemUiController = rememberSystemUiController() val navigationBarColor = TangemTheme.colors.background.primary + LaunchedEffect(Unit) { + delay(timeMillis = 100) + when (bottomSheetState.currentValue) { + TangemSheetValue.Hidden, + TangemSheetValue.Expanded, + -> systemUiController.setNavigationBarColor( + color = Color.Transparent, + darkIcons = navigationBarColor.luminance() > 0.5f, + navigationBarContrastEnforced = true, + ) + TangemSheetValue.PartiallyExpanded, + -> systemUiController.setNavigationBarColor(navigationBarColor) + } + } + LaunchedEffect(key1 = bottomSheetState.targetValue, navigationBarColor) { when (bottomSheetState.targetValue) { TangemSheetValue.Hidden,