diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/CatalogListContent.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/CatalogListContent.kt index 5824d3a..be575a2 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/CatalogListContent.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/CatalogListContent.kt @@ -13,9 +13,11 @@ import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItemTuple import dev.marlonlom.apps.cappajv.features.catalog_list.screens.CompactTableTopCatalogListScreen import dev.marlonlom.apps.cappajv.features.catalog_list.screens.DefaultPortraitCatalogListScreen import dev.marlonlom.apps.cappajv.features.catalog_list.screens.LandscapeCompactCatalogListScreen +import dev.marlonlom.apps.cappajv.features.catalog_list.screens.TwoPaneCatalogListScreen import dev.marlonlom.apps.cappajv.ui.layout.DevicePosture import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState import dev.marlonlom.apps.cappajv.ui.main.scaffold.ScaffoldContentType +import dev.marlonlom.apps.cappajv.ui.navigation.NavigationType /** * Catalog list content composable ui, conditioned by application ui state. @@ -44,6 +46,19 @@ fun CatalogListContent( ) { when { + appState.isLandscape.and(appState.devicePosture == DevicePosture.Normal) + .and(appState.navigationType == NavigationType.EXPANDED_NAV) -> { + TwoPaneCatalogListScreen( + appState = appState, + catalogItemsListState = catalogItemsListState, + catalogItems = catalogItems, + categories = categories, + selectedCategory = selectedCategory, + onSelectedCategoryChanged = onSelectedCategoryChanged, + onCatalogItemSelected = onCatalogItemSelected, + ) + } + (appState.devicePosture is DevicePosture.Separating.Book).and(appState.isCompactHeight.not()) .and(appState.isLandscape.not()) -> { @@ -101,3 +116,4 @@ fun CatalogListContent( } } } + diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/parts/CatalogTupleRow.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/parts/CatalogTupleRow.kt index c21124d..8719b7f 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/parts/CatalogTupleRow.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/parts/CatalogTupleRow.kt @@ -32,12 +32,12 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp -import androidx.core.text.trimmedLength import coil.compose.AsyncImage import coil.request.ImageRequest import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItemTuple import dev.marlonlom.apps.cappajv.ui.layout.DevicePosture import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState +import dev.marlonlom.apps.cappajv.ui.navigation.NavigationType /** * Catalog tuple row composable ui. @@ -65,9 +65,13 @@ internal fun CatalogTupleRow( onCatalogItemTupleClicked(tuple.id) }, ) { + val verticalAlignment = when { + appState.navigationType == NavigationType.EXPANDED_NAV -> Alignment.Bottom + else -> Alignment.CenterVertically + } Row( modifier = modifier.padding(vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, + verticalAlignment = verticalAlignment, horizontalArrangement = Arrangement.spacedBy(16.dp) ) { CatalogTuplePosterImage(tuple, appState) @@ -77,7 +81,7 @@ internal fun CatalogTupleRow( .padding(end = 10.dp) ) { CatalogTupleTitle(tuple, appState) - CatalogTupleSamplePunctuationText(tuple) + CatalogTupleSamplePunctuationText(tuple, appState) } } } @@ -88,11 +92,13 @@ internal fun CatalogTupleRow( * * @author marlonlom * - * @param tuple Catalog item. + * @param tuple Catalog item tuple data. + * @param appState Application ui state. */ @Composable private fun CatalogTupleSamplePunctuationText( - tuple: CatalogItemTuple + tuple: CatalogItemTuple, + appState: CappajvAppState, ) { val samplePunctuationTxt = buildAnnotatedString { val textParts = tuple.samplePunctuation.split(":") @@ -102,11 +108,7 @@ private fun CatalogTupleSamplePunctuationText( color = MaterialTheme.colorScheme.secondary, ) ) { - val punctuationTitle = when { - textParts[0].trimmedLength() > 10 -> textParts[0].split(" ")[0].plus(" ...") - else -> textParts[0] - } - append(punctuationTitle) + append(textParts[0]) } append(": ") append(textParts[1].trim()) @@ -122,9 +124,21 @@ private fun CatalogTupleSamplePunctuationText( } } } + + val textStyle = when { + appState.navigationType == NavigationType.EXPANDED_NAV -> MaterialTheme.typography.bodyLarge + else -> MaterialTheme.typography.labelMedium + } + + val bottomPadding = when { + appState.navigationType == NavigationType.EXPANDED_NAV -> 10.dp + else -> 0.dp + } + Text( + modifier = Modifier.padding(bottom = bottomPadding), text = samplePunctuationTxt, - style = MaterialTheme.typography.labelMedium, + style = textStyle, ) } @@ -138,7 +152,8 @@ private fun CatalogTupleSamplePunctuationText( */ @Composable private fun CatalogTupleTitle( - tuple: CatalogItemTuple, appState: CappajvAppState + tuple: CatalogItemTuple, + appState: CappajvAppState, ) { Text( text = tuple.title, @@ -160,7 +175,8 @@ private fun CatalogTupleTitle( */ @Composable private fun CatalogTuplePosterImage( - tuple: CatalogItemTuple, appState: CappajvAppState + tuple: CatalogItemTuple, + appState: CappajvAppState, ) { val imageRequest = ImageRequest.Builder(LocalContext.current).data(tuple.picture).crossfade(true).build() @@ -180,8 +196,15 @@ private fun CatalogTuplePosterImage( ) } +/** + * returns catalog tuple card image size. + * + * @param appState Application ui state. + */ @Composable private fun getCatalogTupleImageSizeDp(appState: CappajvAppState): DpSize = when { + appState.navigationType == NavigationType.EXPANDED_NAV -> DpSize(88.dp, 104.dp) + appState.isCompactWidth.and(appState.isLandscape.not()) .and(appState.devicePosture is DevicePosture.Separating.TableTop) -> DpSize(48.dp, 56.dp) @@ -189,8 +212,15 @@ private fun getCatalogTupleImageSizeDp(appState: CappajvAppState): DpSize = when } +/** + * returns catalog tuple card title text style. + * + * @param appState Application ui state. + */ @Composable private fun getCatalogTupleTitleStyle(appState: CappajvAppState) = when { + appState.navigationType == NavigationType.EXPANDED_NAV -> MaterialTheme.typography.titleLarge + appState.isCompactWidth.and(appState.isLandscape.not()) .and(appState.devicePosture is DevicePosture.Separating.TableTop) -> MaterialTheme.typography.bodyMedium diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/screens/TwoPaneCatalogListScreen.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/screens/TwoPaneCatalogListScreen.kt new file mode 100644 index 0000000..ae36942 --- /dev/null +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_list/screens/TwoPaneCatalogListScreen.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2024 Marlonlom + * SPDX-License-Identifier: Apache-2.0 + */ + +package dev.marlonlom.apps.cappajv.features.catalog_list.screens + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.safeContentPadding +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItemTuple +import dev.marlonlom.apps.cappajv.features.catalog_list.parts.CatalogListHeadline +import dev.marlonlom.apps.cappajv.features.catalog_list.slots.CatalogCategoriesChipGroup +import dev.marlonlom.apps.cappajv.features.catalog_list.slots.CatalogListBanner +import dev.marlonlom.apps.cappajv.features.catalog_list.slots.CatalogListTuplesSlot +import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState + + +/** + * Landscape Two pane catalog list screen composable ui. + * + * @author marlonlom + * + * @param appState Application ui state. + * @param catalogItemsListState Catalog items lazy list state. + * @param catalogItems Catalog items list. + * @param categories Categories list. + * @param selectedCategory Selected category name. + * @param onSelectedCategoryChanged Action for category selected. + * @param onCatalogItemSelected Action for catalog item selected. + * @param modifier Modifier for this composable. + */ +@ExperimentalLayoutApi +@ExperimentalFoundationApi +@Composable +fun TwoPaneCatalogListScreen( + appState: CappajvAppState, + catalogItemsListState: LazyListState, + catalogItems: List, + categories: List, + selectedCategory: String, + onSelectedCategoryChanged: (String) -> Unit, + onCatalogItemSelected: (Long) -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(20.dp) + ) { + Column( + modifier = modifier.fillMaxWidth(0.33f) + ) { + CatalogListHeadline(appState) + CatalogListBanner(appState) + CatalogCategoriesChipGroup( + categories = categories, + selectedCategory = selectedCategory, + onCategoryChipSelected = { onSelectedCategoryChanged(it) }, + ) + CatalogListTuplesSlot( + appState = appState, + catalogItemsListState = catalogItemsListState, + catalogTuples = catalogItems, + onCatalogItemTupleClicked = { onCatalogItemSelected(it) }, + ) + } + Column( + modifier = modifier + .fillMaxSize() + .safeContentPadding() + .background( + MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.25f) + ), + ) { + + } + } +} diff --git a/features/core/catalog-source/src/main/resources/en/catalog.json b/features/core/catalog-source/src/main/resources/en/catalog.json index c1a7c3d..795234a 100644 --- a/features/core/catalog-source/src/main/resources/en/catalog.json +++ b/features/core/catalog-source/src/main/resources/en/catalog.json @@ -376,7 +376,7 @@ "title": "Nevado café reducido en azucar", "category": "Cold drinks", "detail": "It is a creamy cold coffee-based drink, reduced in sugar decorated with Chantilly.", - "picture": "https://juanvaldez.com/wp-content/uploads/2023/02/nevado_rejado_en_azucar_300ml_700x700px.jpg", + "picture": "https://juanvaldez.com/wp-content/uploads/2023/02/nevado_reducido_en_azucar_300ml_700x700px.jpg", "punctuations": [ { "label": "Medium",