From 0fed9edc18706e2b1ba48e5224e4ea25cffb14a6 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Wed, 1 Apr 2026 18:38:53 +0530 Subject: [PATCH] feat(search): Add dynamic column count for discover content based on screen width --- .../features/search/SearchDiscoverContent.kt | 19 ++++++-- .../nuvio/app/features/search/SearchScreen.kt | 48 ++++++++++++++----- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchDiscoverContent.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchDiscoverContent.kt index 57aa7603..1b627efe 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchDiscoverContent.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchDiscoverContent.kt @@ -51,6 +51,7 @@ import com.nuvio.app.features.watching.application.WatchingState internal fun LazyListScope.discoverContent( state: DiscoverUiState, + columns: Int, onTypeSelected: (String) -> Unit, onCatalogSelected: (String) -> Unit, onGenreSelected: (String?) -> Unit, @@ -87,7 +88,10 @@ internal fun LazyListScope.discoverContent( when { state.isLoading && state.items.isEmpty() -> { items(2) { - DiscoverSkeletonRow(modifier = Modifier.padding(horizontal = 16.dp)) + DiscoverSkeletonRow( + columns = columns, + modifier = Modifier.padding(horizontal = 16.dp), + ) } } @@ -102,9 +106,10 @@ internal fun LazyListScope.discoverContent( } else -> { - items(state.items.chunked(3)) { rowItems -> + items(state.items.chunked(columns)) { rowItems -> DiscoverGridRow( items = rowItems, + columns = columns, modifier = Modifier.padding(horizontal = 16.dp), watchedKeys = watchedKeys, onPosterClick = onPosterClick, @@ -234,6 +239,7 @@ private fun DiscoverDropdownChip( @Composable private fun DiscoverGridRow( items: List, + columns: Int, modifier: Modifier = Modifier, watchedKeys: Set = emptySet(), onPosterClick: ((MetaPreview) -> Unit)? = null, @@ -256,7 +262,7 @@ private fun DiscoverGridRow( onLongClick = onPosterLongClick?.let { { it(item) } }, ) } - repeat(3 - items.size) { + repeat(columns - items.size) { Spacer(modifier = Modifier.weight(1f)) } } @@ -321,12 +327,15 @@ private fun DiscoverPosterTile( } @Composable -private fun DiscoverSkeletonRow(modifier: Modifier = Modifier) { +private fun DiscoverSkeletonRow( + columns: Int, + modifier: Modifier = Modifier, +) { Row( modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp), ) { - repeat(3) { + repeat(columns) { Box( modifier = Modifier .weight(1f) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchScreen.kt index ed1e69cd..1cb27faa 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/search/SearchScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -32,6 +33,7 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.Alignment +import androidx.compose.ui.unit.Dp import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -145,13 +147,22 @@ fun SearchScreen( SearchHistoryRepository.recordSearch(normalizedQuery) } - NuvioScreen( - horizontalPadding = 0.dp, - listState = listState, + BoxWithConstraints( modifier = modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background), ) { + val discoverColumns = remember(maxWidth) { + discoverColumnCountForWidth(maxWidth) + } + + NuvioScreen( + horizontalPadding = 0.dp, + listState = listState, + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background), + ) { stickyHeader { androidx.compose.foundation.layout.Column( modifier = Modifier @@ -184,16 +195,17 @@ fun SearchScreen( ) } } - discoverContent( - state = discoverUiState, - onTypeSelected = SearchRepository::selectDiscoverType, - onCatalogSelected = SearchRepository::selectDiscoverCatalog, - onGenreSelected = SearchRepository::selectDiscoverGenre, - watchedKeys = watchedUiState.watchedKeys, - onPosterClick = onPosterClick, - onPosterLongClick = onPosterLongClick, - ) - } else { + discoverContent( + state = discoverUiState, + columns = discoverColumns, + onTypeSelected = SearchRepository::selectDiscoverType, + onCatalogSelected = SearchRepository::selectDiscoverCatalog, + onGenreSelected = SearchRepository::selectDiscoverGenre, + watchedKeys = watchedUiState.watchedKeys, + onPosterClick = onPosterClick, + onPosterLongClick = onPosterLongClick, + ) + } else { when { uiState.isLoading && uiState.sections.isEmpty() -> { items(2) { @@ -228,6 +240,16 @@ fun SearchScreen( } } } +} + +private fun discoverColumnCountForWidth(screenWidth: Dp): Int = + when { + screenWidth >= 1400.dp -> 7 + screenWidth >= 1200.dp -> 6 + screenWidth >= 1000.dp -> 5 + screenWidth >= 840.dp -> 4 + else -> 3 + } @Composable private fun SearchEmptyStateCard(