From 2821174fece0409e52680d5fa90ca564242a0e82 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 15 May 2024 14:55:32 +0200 Subject: [PATCH 01/21] Update WooPosCartScreen --- .../ui/woopos/cart/WooPosCartScreen.kt | 74 +++++++++++++++++-- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt index 7080802376b..298875b4796 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt @@ -1,14 +1,29 @@ package com.woocommerce.android.ui.woopos.cart +import android.annotation.SuppressLint import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.material.Button +import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold import androidx.compose.material.Text +import androidx.compose.material.TopAppBar +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout import com.woocommerce.android.ui.woopos.util.WooPosPreview @Composable @@ -22,20 +37,63 @@ fun WooPosCartScreen( ) } +@SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable private fun WooPosCartScreen(onButtonClicked: () -> Unit) { Box( Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - Column { - Text( - text = "Cart", - style = MaterialTheme.typography.h3, - color = MaterialTheme.colors.primary, - ) - Button(onClick = onButtonClicked) { - Text("Checkout") + Scaffold( + topBar = { + TopAppBar( + navigationIcon = { + Icon( + imageVector = Icons.Default.Close, + contentDescription = "Close POS" + ) + }, + title = { + Text( + modifier = Modifier.fillMaxWidth(), + text = "⚠️ Reader not connected", + style = MaterialTheme.typography.h5, + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.Center, + ) + }, + actions = { + Text(text = "History") + } + ) + }, + ) { + Row( + modifier = Modifier.padding(16.dp) + ) { + ConstraintLayout( + modifier = Modifier.fillMaxWidth(0.7f) + ) { + Text( + text = "Products", + style = MaterialTheme.typography.h3, + color = MaterialTheme.colors.primary, + ) + } + Column { + Text( + text = "Cart", + style = MaterialTheme.typography.h3, + color = MaterialTheme.colors.primary, + ) + Spacer(modifier = Modifier.weight(1f)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = onButtonClicked, + ) { + Text("Checkout") + } + } } } } From 975003c5f337d63ce800de6905ca141f178060a8 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 17 May 2024 17:13:38 +0200 Subject: [PATCH 02/21] Implement products data source --- .../cart/products/ProductsDataSource.kt | 10 ++++++++++ .../cart/products/ProductsDataSourceImpl.kt | 18 +++++++++++++++++ .../android/ui/woopos/di/POSModule.kt | 20 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt new file mode 100644 index 00000000000..b9cd9945004 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt @@ -0,0 +1,10 @@ +package com.woocommerce.android.ui.woopos.cart.products + +import com.woocommerce.android.model.Product +import kotlinx.coroutines.flow.Flow + +interface ProductsDataSource { + val products: Flow> + suspend fun loadProducts() + suspend fun loadMore() +} \ No newline at end of file diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt new file mode 100644 index 00000000000..4056bf14a2a --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt @@ -0,0 +1,18 @@ +package com.woocommerce.android.ui.woopos.cart.products + +import com.woocommerce.android.model.Product +import com.woocommerce.android.ui.products.selector.ProductListHandler +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class ProductsDataSourceImpl @Inject constructor(private val handler: ProductListHandler) : ProductsDataSource { + override val products: Flow> = handler.productsFlow + + override suspend fun loadProducts() { + handler.loadFromCacheAndFetch(searchType = ProductListHandler.SearchType.DEFAULT) + } + + override suspend fun loadMore() { + handler.loadMore() + } +} \ No newline at end of file diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt new file mode 100644 index 00000000000..566201078d7 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt @@ -0,0 +1,20 @@ +package com.woocommerce.android.ui.woopos.di + +import com.woocommerce.android.ui.products.selector.ProductListHandler +import com.woocommerce.android.ui.woopos.cart.products.ProductsDataSource +import com.woocommerce.android.ui.woopos.cart.products.ProductsDataSourceImpl +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@InstallIn(SingletonComponent::class) +@Module +class POSModule { + @Provides + fun provideProductList( + handler: ProductListHandler + ): ProductsDataSource { + return ProductsDataSourceImpl(handler) + } +} \ No newline at end of file From 8d33e576e4ee6c4cd7df35b882a0a8aca310c061 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 17 May 2024 17:14:11 +0200 Subject: [PATCH 03/21] Implement base product selector vm --- .../cart/products/ProductSelectorViewModel.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt new file mode 100644 index 00000000000..52d09fbd4c2 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt @@ -0,0 +1,51 @@ +package com.woocommerce.android.ui.woopos.cart.products + +import androidx.lifecycle.SavedStateHandle +import com.woocommerce.android.viewmodel.ScopedViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ProductSelectorViewModel @Inject constructor( + private val productsDataSource: ProductsDataSource, + savedStateHandle: SavedStateHandle, +) : ScopedViewModel(savedStateHandle) { + + val viewState: StateFlow = productsDataSource.products.map { products -> + ViewState( + products = products.map { product -> + ListItem( + productId = product.remoteId, + title = product.name, + imageUrl = product.firstImageUrl + ) + } + ) + }.toStateFlow(ViewState(products = emptyList())) + + init { + launch { + productsDataSource.loadProducts() + } + } + + fun onLoadMore() { + launch { + productsDataSource.loadMore() + } + } + + data class ViewState( + val products: List, + ) + + data class ListItem( + val productId: Long, + val title: String, + val imageUrl: String? = null, + ) +} + From 437c925707c242594f6fda8835778b4037656091 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 17 May 2024 17:27:41 +0200 Subject: [PATCH 04/21] Display grid with product titles --- .../ui/woopos/cart/WooPosCartNavigation.kt | 7 +- .../ui/woopos/cart/WooPosCartScreen.kt | 72 +++++++++++-------- .../woopos/cart/products/ProductSelector.kt | 67 +++++++++++++++++ .../cart/products/ProductsDataSourceImpl.kt | 6 +- 4 files changed, 117 insertions(+), 35 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt index 9eb461c75a6..3555a787674 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt @@ -3,6 +3,7 @@ package com.woocommerce.android.ui.woopos.cart import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import com.woocommerce.android.ui.woopos.cart.products.ProductSelectorViewModel internal const val CART_ROUTE = "cart" @@ -10,10 +11,12 @@ internal fun NavGraphBuilder.cartScreen( onCheckoutClick: () -> Unit ) { composable(CART_ROUTE) { - val viewModel: WooPosCartViewModel = hiltViewModel() + val cartViewModel: WooPosCartViewModel = hiltViewModel() + val productsViewModel: ProductSelectorViewModel = hiltViewModel() WooPosCartScreen( - viewModel = viewModel, + cartViewModel = cartViewModel, + productsViewModel = productsViewModel, onCheckoutClick = onCheckoutClick ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt index 298875b4796..964a8d3fecf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt @@ -5,11 +5,9 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.material.Button import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme @@ -23,23 +21,31 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.constraintlayout.compose.ConstraintLayout +import com.woocommerce.android.ui.woopos.cart.products.ProductSelector +import com.woocommerce.android.ui.woopos.cart.products.ProductSelectorViewModel import com.woocommerce.android.ui.woopos.util.WooPosPreview +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow @Composable @Suppress("UNUSED_PARAMETER") fun WooPosCartScreen( - viewModel: WooPosCartViewModel, + cartViewModel: WooPosCartViewModel, + productsViewModel: ProductSelectorViewModel, onCheckoutClick: () -> Unit, ) { WooPosCartScreen( - onButtonClicked = onCheckoutClick + onButtonClicked = onCheckoutClick, + productsState = productsViewModel.viewState, ) } @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable -private fun WooPosCartScreen(onButtonClicked: () -> Unit) { +private fun WooPosCartScreen( + onButtonClicked: () -> Unit, + productsState: StateFlow, +) { Box( Modifier.fillMaxSize(), contentAlignment = Alignment.Center @@ -71,36 +77,42 @@ private fun WooPosCartScreen(onButtonClicked: () -> Unit) { Row( modifier = Modifier.padding(16.dp) ) { - ConstraintLayout( - modifier = Modifier.fillMaxWidth(0.7f) - ) { - Text( - text = "Products", - style = MaterialTheme.typography.h3, - color = MaterialTheme.colors.primary, - ) - } - Column { - Text( - text = "Cart", - style = MaterialTheme.typography.h3, - color = MaterialTheme.colors.primary, - ) - Spacer(modifier = Modifier.weight(1f)) - Button( - modifier = Modifier.fillMaxWidth(), - onClick = onButtonClicked, - ) { - Text("Checkout") - } - } + ProductSelector(productsState) + Cart(onButtonClicked) } } } } +@Composable +private fun Cart(onButtonClicked: () -> Unit) { + Column { + Text( + text = "Cart", + style = MaterialTheme.typography.h3, + color = MaterialTheme.colors.primary, + ) + Spacer(modifier = Modifier.weight(1f)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = onButtonClicked, + ) { + Text("Checkout") + } + } +} + @Composable @WooPosPreview fun WooPosCartScreenPreview() { - WooPosCartScreen(onButtonClicked = {}) + val productState = MutableStateFlow( + ProductSelectorViewModel.ViewState( + products = listOf( + ProductSelectorViewModel.ListItem(1, "Product 1"), + ProductSelectorViewModel.ListItem(2, "Product 2"), + ProductSelectorViewModel.ListItem(3, "Product 3"), + ) + ) + ) + WooPosCartScreen(onButtonClicked = {}, productsState = productState) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt new file mode 100644 index 00000000000..70052f61a87 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt @@ -0,0 +1,67 @@ +package com.woocommerce.android.ui.woopos.cart.products + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import com.woocommerce.android.ui.woopos.util.WooPosPreview +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +@Composable +fun ProductSelector(productsState: StateFlow) { + ConstraintLayout( + modifier = Modifier.fillMaxWidth(0.7f) + ) { + val state = productsState.collectAsState() + LazyVerticalGrid( + columns = GridCells.Adaptive(minSize = 128.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + items( + count = state.value.products.size, + key = { index -> state.value.products[index].productId } + ) { index -> + ProductItem(product = state.value.products[index]) + } + } + } +} + +@Composable +fun ProductItem(product: ProductSelectorViewModel.ListItem) { + ConstraintLayout( + modifier = Modifier.background(Color.Yellow) + ) { + Text( + text = product.title, + style = MaterialTheme.typography.body1, + color = MaterialTheme.colors.onSurface, + ) + } +} + +@Composable +@WooPosPreview +fun ProductSelectorPreview() { + val state = MutableStateFlow( + ProductSelectorViewModel.ViewState( + listOf( + ProductSelectorViewModel.ListItem(1, "Product 1"), + ProductSelectorViewModel.ListItem(2, "Product 2"), + ProductSelectorViewModel.ListItem(3, "Product 3"), + ) + ) + ) + ProductSelector(state) +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt index 4056bf14a2a..fa882fdd8d0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt @@ -9,10 +9,10 @@ class ProductsDataSourceImpl @Inject constructor(private val handler: ProductLis override val products: Flow> = handler.productsFlow override suspend fun loadProducts() { - handler.loadFromCacheAndFetch(searchType = ProductListHandler.SearchType.DEFAULT) + handler.loadFromCacheAndFetch(searchType = ProductListHandler.SearchType.DEFAULT) } override suspend fun loadMore() { - handler.loadMore() + handler.loadMore() } -} \ No newline at end of file +} From 29db876573aeaaff32e3ddfc9b6b565af2eabd3d Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 17 May 2024 17:28:28 +0200 Subject: [PATCH 05/21] Address detekt's complaints --- .../android/ui/woopos/cart/products/ProductSelectorViewModel.kt | 1 - .../android/ui/woopos/cart/products/ProductsDataSource.kt | 2 +- .../kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt index 52d09fbd4c2..9c28486f1dd 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt @@ -48,4 +48,3 @@ class ProductSelectorViewModel @Inject constructor( val imageUrl: String? = null, ) } - diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt index b9cd9945004..ee5a968df94 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt @@ -7,4 +7,4 @@ interface ProductsDataSource { val products: Flow> suspend fun loadProducts() suspend fun loadMore() -} \ No newline at end of file +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt index 566201078d7..6c9fc5083ff 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt @@ -17,4 +17,4 @@ class POSModule { ): ProductsDataSource { return ProductsDataSourceImpl(handler) } -} \ No newline at end of file +} From 8f716e6ca120ea87ff50600090987bb51ed94a1d Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 17 May 2024 17:45:28 +0200 Subject: [PATCH 06/21] Implement infinite grid loading --- .../ui/woopos/cart/WooPosCartScreen.kt | 6 ++- .../woopos/cart/products/ProductSelector.kt | 42 ++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt index 964a8d3fecf..d9a4eb20718 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt @@ -37,6 +37,7 @@ fun WooPosCartScreen( WooPosCartScreen( onButtonClicked = onCheckoutClick, productsState = productsViewModel.viewState, + onLoadMore = productsViewModel::onLoadMore, ) } @@ -45,6 +46,7 @@ fun WooPosCartScreen( private fun WooPosCartScreen( onButtonClicked: () -> Unit, productsState: StateFlow, + onLoadMore: () -> Unit, ) { Box( Modifier.fillMaxSize(), @@ -77,7 +79,7 @@ private fun WooPosCartScreen( Row( modifier = Modifier.padding(16.dp) ) { - ProductSelector(productsState) + ProductSelector(productsState, onLoadMore) Cart(onButtonClicked) } } @@ -114,5 +116,5 @@ fun WooPosCartScreenPreview() { ) ) ) - WooPosCartScreen(onButtonClicked = {}, productsState = productState) + WooPosCartScreen(onButtonClicked = {}, productsState = productState, onLoadMore = {}) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt index 70052f61a87..c741373c138 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt @@ -4,11 +4,17 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp @@ -16,17 +22,24 @@ import androidx.constraintlayout.compose.ConstraintLayout import com.woocommerce.android.ui.woopos.util.WooPosPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter @Composable -fun ProductSelector(productsState: StateFlow) { +fun ProductSelector( + productsState: StateFlow, + onLoadMore: () -> Unit, +) { ConstraintLayout( modifier = Modifier.fillMaxWidth(0.7f) ) { val state = productsState.collectAsState() + val gridState = rememberLazyGridState() LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 128.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp), + state = gridState ) { items( count = state.value.products.size, @@ -35,6 +48,9 @@ fun ProductSelector(productsState: StateFlow ProductItem(product = state.value.products[index]) } } + InfiniteGridHandler(gridState) { + onLoadMore() + } } } @@ -51,6 +67,28 @@ fun ProductItem(product: ProductSelectorViewModel.ListItem) { } } +@Composable +fun InfiniteGridHandler(gridState: LazyGridState, buffer: Int = 1, onLoadMore: () -> Unit) { + val loadMore = remember { + derivedStateOf { + val layoutInfo = gridState.layoutInfo + val totalItemsNumber = layoutInfo.totalItemsCount + val lastVisibleItemIndex = (layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0) + 1 + + lastVisibleItemIndex > (totalItemsNumber - buffer) + } + } + + LaunchedEffect(loadMore) { + snapshotFlow { loadMore.value } + .distinctUntilChanged() + .filter { it } + .collect { + onLoadMore() + } + } +} + @Composable @WooPosPreview fun ProductSelectorPreview() { @@ -63,5 +101,5 @@ fun ProductSelectorPreview() { ) ) ) - ProductSelector(state) + ProductSelector(productsState = state, onLoadMore = {}) } From dd36fbe1e304240803a80f69420c81833057e0ea Mon Sep 17 00:00:00 2001 From: samiuelson Date: Mon, 20 May 2024 22:05:23 +0200 Subject: [PATCH 07/21] =?UTF-8?q?Rename=20function:=20onLoadMode=20?= =?UTF-8?q?=F0=9F=91=89=20onEndOfProductsGridReached?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/woopos/cart/WooPosCartScreen.kt | 8 ++++---- .../android/ui/woopos/cart/products/ProductSelector.kt | 10 +++++----- .../woopos/cart/products/ProductSelectorViewModel.kt | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt index d9a4eb20718..19c05b70b06 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt @@ -37,7 +37,7 @@ fun WooPosCartScreen( WooPosCartScreen( onButtonClicked = onCheckoutClick, productsState = productsViewModel.viewState, - onLoadMore = productsViewModel::onLoadMore, + onEndOfProductsGridReached = productsViewModel::onEndOfProductsGridReached, ) } @@ -46,7 +46,7 @@ fun WooPosCartScreen( private fun WooPosCartScreen( onButtonClicked: () -> Unit, productsState: StateFlow, - onLoadMore: () -> Unit, + onEndOfProductsGridReached: () -> Unit, ) { Box( Modifier.fillMaxSize(), @@ -79,7 +79,7 @@ private fun WooPosCartScreen( Row( modifier = Modifier.padding(16.dp) ) { - ProductSelector(productsState, onLoadMore) + ProductSelector(productsState, onEndOfProductsGridReached) Cart(onButtonClicked) } } @@ -116,5 +116,5 @@ fun WooPosCartScreenPreview() { ) ) ) - WooPosCartScreen(onButtonClicked = {}, productsState = productState, onLoadMore = {}) + WooPosCartScreen(onButtonClicked = {}, productsState = productState, onEndOfProductsGridReached = {}) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt index c741373c138..470d683edf6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt @@ -28,7 +28,7 @@ import kotlinx.coroutines.flow.filter @Composable fun ProductSelector( productsState: StateFlow, - onLoadMore: () -> Unit, + onEndOfProductsGridReached: () -> Unit, ) { ConstraintLayout( modifier = Modifier.fillMaxWidth(0.7f) @@ -49,7 +49,7 @@ fun ProductSelector( } } InfiniteGridHandler(gridState) { - onLoadMore() + onEndOfProductsGridReached() } } } @@ -68,7 +68,7 @@ fun ProductItem(product: ProductSelectorViewModel.ListItem) { } @Composable -fun InfiniteGridHandler(gridState: LazyGridState, buffer: Int = 1, onLoadMore: () -> Unit) { +fun InfiniteGridHandler(gridState: LazyGridState, buffer: Int = 1, onEndOfProductsGridReached: () -> Unit) { val loadMore = remember { derivedStateOf { val layoutInfo = gridState.layoutInfo @@ -84,7 +84,7 @@ fun InfiniteGridHandler(gridState: LazyGridState, buffer: Int = 1, onLoadMore: ( .distinctUntilChanged() .filter { it } .collect { - onLoadMore() + onEndOfProductsGridReached() } } } @@ -101,5 +101,5 @@ fun ProductSelectorPreview() { ) ) ) - ProductSelector(productsState = state, onLoadMore = {}) + ProductSelector(productsState = state, onEndOfProductsGridReached = {}) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt index 9c28486f1dd..d4f0e61f472 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt @@ -32,7 +32,7 @@ class ProductSelectorViewModel @Inject constructor( } } - fun onLoadMore() { + fun onEndOfProductsGridReached() { launch { productsDataSource.loadMore() } From 3d41aef6929baa0280ac3ca43edccaa34a73a935 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 12:08:48 +0200 Subject: [PATCH 08/21] Rename param --- .../android/ui/woopos/cart/WooPosCartScreen.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt index 19c05b70b06..f00b6dc4020 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt @@ -35,7 +35,7 @@ fun WooPosCartScreen( onCheckoutClick: () -> Unit, ) { WooPosCartScreen( - onButtonClicked = onCheckoutClick, + onCheckoutClick = onCheckoutClick, productsState = productsViewModel.viewState, onEndOfProductsGridReached = productsViewModel::onEndOfProductsGridReached, ) @@ -44,7 +44,7 @@ fun WooPosCartScreen( @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable private fun WooPosCartScreen( - onButtonClicked: () -> Unit, + onCheckoutClick: () -> Unit, productsState: StateFlow, onEndOfProductsGridReached: () -> Unit, ) { @@ -80,7 +80,7 @@ private fun WooPosCartScreen( modifier = Modifier.padding(16.dp) ) { ProductSelector(productsState, onEndOfProductsGridReached) - Cart(onButtonClicked) + Cart(onCheckoutClick) } } } @@ -116,5 +116,5 @@ fun WooPosCartScreenPreview() { ) ) ) - WooPosCartScreen(onButtonClicked = {}, productsState = productState, onEndOfProductsGridReached = {}) + WooPosCartScreen(onCheckoutClick = {}, productsState = productState, onEndOfProductsGridReached = {}) } From f30af433fdea6744f35f4893a8fabeaead809d18 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 12:15:16 +0200 Subject: [PATCH 09/21] Reorganise packages --- .../com/woocommerce/android/ui/woopos/di/POSModule.kt | 4 ++-- .../ui/woopos/{ => home}/cart/WooPosCartNavigation.kt | 4 ++-- .../android/ui/woopos/{ => home}/cart/WooPosCartScreen.kt | 6 +++--- .../ui/woopos/{ => home}/cart/WooPosCartViewModel.kt | 2 +- .../ui/woopos/{cart => home}/products/ProductSelector.kt | 2 +- .../{cart => home}/products/ProductSelectorViewModel.kt | 2 +- .../ui/woopos/{cart => home}/products/ProductsDataSource.kt | 2 +- .../{cart => home}/products/ProductsDataSourceImpl.kt | 5 +++-- .../ui/woopos/root/navigation/WooPosMainFlowGraph.kt | 4 ++-- 9 files changed, 16 insertions(+), 15 deletions(-) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{ => home}/cart/WooPosCartNavigation.kt (84%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{ => home}/cart/WooPosCartScreen.kt (95%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{ => home}/cart/WooPosCartViewModel.kt (86%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{cart => home}/products/ProductSelector.kt (98%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{cart => home}/products/ProductSelectorViewModel.kt (95%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{cart => home}/products/ProductsDataSource.kt (79%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/{cart => home}/products/ProductsDataSourceImpl.kt (82%) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt index 6c9fc5083ff..93c8d04108b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/di/POSModule.kt @@ -1,8 +1,8 @@ package com.woocommerce.android.ui.woopos.di import com.woocommerce.android.ui.products.selector.ProductListHandler -import com.woocommerce.android.ui.woopos.cart.products.ProductsDataSource -import com.woocommerce.android.ui.woopos.cart.products.ProductsDataSourceImpl +import com.woocommerce.android.ui.woopos.home.products.ProductsDataSource +import com.woocommerce.android.ui.woopos.home.products.ProductsDataSourceImpl import dagger.Module import dagger.Provides import dagger.hilt.InstallIn diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartNavigation.kt similarity index 84% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartNavigation.kt index 3555a787674..b4d1d1572ca 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartNavigation.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartNavigation.kt @@ -1,9 +1,9 @@ -package com.woocommerce.android.ui.woopos.cart +package com.woocommerce.android.ui.woopos.home.cart import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable -import com.woocommerce.android.ui.woopos.cart.products.ProductSelectorViewModel +import com.woocommerce.android.ui.woopos.home.products.ProductSelectorViewModel internal const val CART_ROUTE = "cart" diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt similarity index 95% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt index f00b6dc4020..b535f78e9b4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt @@ -1,4 +1,4 @@ -package com.woocommerce.android.ui.woopos.cart +package com.woocommerce.android.ui.woopos.home.cart import android.annotation.SuppressLint import androidx.compose.foundation.layout.Box @@ -21,8 +21,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.woocommerce.android.ui.woopos.cart.products.ProductSelector -import com.woocommerce.android.ui.woopos.cart.products.ProductSelectorViewModel +import com.woocommerce.android.ui.woopos.home.products.ProductSelector +import com.woocommerce.android.ui.woopos.home.products.ProductSelectorViewModel import com.woocommerce.android.ui.woopos.util.WooPosPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartViewModel.kt similarity index 86% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartViewModel.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartViewModel.kt index 0e106608c46..da84295a865 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/WooPosCartViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartViewModel.kt @@ -1,4 +1,4 @@ -package com.woocommerce.android.ui.woopos.cart +package com.woocommerce.android.ui.woopos.home.cart import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.viewmodel.ScopedViewModel diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt similarity index 98% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt index 470d683edf6..22cd82506b4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt @@ -1,4 +1,4 @@ -package com.woocommerce.android.ui.woopos.cart.products +package com.woocommerce.android.ui.woopos.home.products import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt similarity index 95% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt index d4f0e61f472..3211ec3bda2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt @@ -1,4 +1,4 @@ -package com.woocommerce.android.ui.woopos.cart.products +package com.woocommerce.android.ui.woopos.home.products import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.viewmodel.ScopedViewModel diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductsDataSource.kt similarity index 79% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductsDataSource.kt index ee5a968df94..d9a24f33134 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSource.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductsDataSource.kt @@ -1,4 +1,4 @@ -package com.woocommerce.android.ui.woopos.cart.products +package com.woocommerce.android.ui.woopos.home.products import com.woocommerce.android.model.Product import kotlinx.coroutines.flow.Flow diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductsDataSourceImpl.kt similarity index 82% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductsDataSourceImpl.kt index fa882fdd8d0..c1d574d2d94 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/cart/products/ProductsDataSourceImpl.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductsDataSourceImpl.kt @@ -1,11 +1,12 @@ -package com.woocommerce.android.ui.woopos.cart.products +package com.woocommerce.android.ui.woopos.home.products import com.woocommerce.android.model.Product import com.woocommerce.android.ui.products.selector.ProductListHandler import kotlinx.coroutines.flow.Flow import javax.inject.Inject -class ProductsDataSourceImpl @Inject constructor(private val handler: ProductListHandler) : ProductsDataSource { +class ProductsDataSourceImpl @Inject constructor(private val handler: ProductListHandler) : + ProductsDataSource { override val products: Flow> = handler.productsFlow override suspend fun loadProducts() { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt index cd600a29857..5e88d6ee6b4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt @@ -3,8 +3,8 @@ package com.woocommerce.android.ui.woopos.root.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.navigation -import com.woocommerce.android.ui.woopos.cart.CART_ROUTE -import com.woocommerce.android.ui.woopos.cart.cartScreen +import com.woocommerce.android.ui.woopos.home.cart.CART_ROUTE +import com.woocommerce.android.ui.woopos.home.cart.cartScreen import com.woocommerce.android.ui.woopos.checkout.checkoutScreen import com.woocommerce.android.ui.woopos.checkout.navigateToCheckoutScreen From 65894b9d594a9836a188970989d08479b38dc62e Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 12:20:11 +0200 Subject: [PATCH 10/21] Optimise imports --- .../android/ui/woopos/home/products/ProductSelector.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt index 22cd82506b4..15ac95d5437 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.woopos.home.products import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyGridState @@ -37,8 +38,8 @@ fun ProductSelector( val gridState = rememberLazyGridState() LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 128.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalArrangement = spacedBy(4.dp), + verticalArrangement = spacedBy(4.dp), state = gridState ) { items( From 172e67cdef98f9d12299a87911761e7973823b8f Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 12:27:24 +0200 Subject: [PATCH 11/21] Extract view state class to separate file --- .../woopos/home/products/ProductSelectorViewModel.kt | 10 ---------- .../android/ui/woopos/home/products/ViewState.kt | 12 ++++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt index 3211ec3bda2..d4caf0faabd 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt @@ -37,14 +37,4 @@ class ProductSelectorViewModel @Inject constructor( productsDataSource.loadMore() } } - - data class ViewState( - val products: List, - ) - - data class ListItem( - val productId: Long, - val title: String, - val imageUrl: String? = null, - ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt new file mode 100644 index 00000000000..b6339fe910b --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt @@ -0,0 +1,12 @@ +package com.woocommerce.android.ui.woopos.home.products + + +data class ViewState( + val products: List, +) + +data class ListItem( + val productId: Long, + val title: String, + val imageUrl: String? = null, +) \ No newline at end of file From f4760a6290513cc37679759fccd2f63734436927 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 12:27:24 +0200 Subject: [PATCH 12/21] Extract view state class to separate file --- .../android/ui/woopos/home/cart/WooPosCartScreen.kt | 12 +++++++----- .../ui/woopos/home/products/ProductSelector.kt | 13 ++++++------- .../home/products/ProductSelectorViewModel.kt | 10 ---------- .../android/ui/woopos/home/products/ViewState.kt | 12 ++++++++++++ 4 files changed, 25 insertions(+), 22 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt index b535f78e9b4..2f11245d822 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt @@ -21,8 +21,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import com.woocommerce.android.ui.woopos.home.products.ListItem import com.woocommerce.android.ui.woopos.home.products.ProductSelector import com.woocommerce.android.ui.woopos.home.products.ProductSelectorViewModel +import com.woocommerce.android.ui.woopos.home.products.ViewState import com.woocommerce.android.ui.woopos.util.WooPosPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -45,7 +47,7 @@ fun WooPosCartScreen( @Composable private fun WooPosCartScreen( onCheckoutClick: () -> Unit, - productsState: StateFlow, + productsState: StateFlow, onEndOfProductsGridReached: () -> Unit, ) { Box( @@ -108,11 +110,11 @@ private fun Cart(onButtonClicked: () -> Unit) { @WooPosPreview fun WooPosCartScreenPreview() { val productState = MutableStateFlow( - ProductSelectorViewModel.ViewState( + ViewState( products = listOf( - ProductSelectorViewModel.ListItem(1, "Product 1"), - ProductSelectorViewModel.ListItem(2, "Product 2"), - ProductSelectorViewModel.ListItem(3, "Product 3"), + ListItem(1, "Product 1"), + ListItem(2, "Product 2"), + ListItem(3, "Product 3"), ) ) ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt index 15ac95d5437..eb97ba31367 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt @@ -1,7 +1,6 @@ package com.woocommerce.android.ui.woopos.home.products import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.grid.GridCells @@ -28,7 +27,7 @@ import kotlinx.coroutines.flow.filter @Composable fun ProductSelector( - productsState: StateFlow, + productsState: StateFlow, onEndOfProductsGridReached: () -> Unit, ) { ConstraintLayout( @@ -56,7 +55,7 @@ fun ProductSelector( } @Composable -fun ProductItem(product: ProductSelectorViewModel.ListItem) { +fun ProductItem(product: ListItem) { ConstraintLayout( modifier = Modifier.background(Color.Yellow) ) { @@ -94,11 +93,11 @@ fun InfiniteGridHandler(gridState: LazyGridState, buffer: Int = 1, onEndOfProduc @WooPosPreview fun ProductSelectorPreview() { val state = MutableStateFlow( - ProductSelectorViewModel.ViewState( + ViewState( listOf( - ProductSelectorViewModel.ListItem(1, "Product 1"), - ProductSelectorViewModel.ListItem(2, "Product 2"), - ProductSelectorViewModel.ListItem(3, "Product 3"), + ListItem(1, "Product 1"), + ListItem(2, "Product 2"), + ListItem(3, "Product 3"), ) ) ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt index 3211ec3bda2..d4caf0faabd 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt @@ -37,14 +37,4 @@ class ProductSelectorViewModel @Inject constructor( productsDataSource.loadMore() } } - - data class ViewState( - val products: List, - ) - - data class ListItem( - val productId: Long, - val title: String, - val imageUrl: String? = null, - ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt new file mode 100644 index 00000000000..b6339fe910b --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt @@ -0,0 +1,12 @@ +package com.woocommerce.android.ui.woopos.home.products + + +data class ViewState( + val products: List, +) + +data class ListItem( + val productId: Long, + val title: String, + val imageUrl: String? = null, +) \ No newline at end of file From 07737180cabd9de2496e2c1a5fd5a16a97435c49 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 13:00:04 +0200 Subject: [PATCH 13/21] Fix detekt's complaints --- .../ui/woopos/home/products/ProductSelectorViewModel.kt | 6 ++++++ .../android/ui/woopos/home/products/ViewState.kt | 3 +-- .../ui/woopos/root/navigation/WooPosMainFlowGraph.kt | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt index d4caf0faabd..5d050db6478 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt @@ -3,6 +3,7 @@ package com.woocommerce.android.ui.woopos.home.products import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.viewmodel.ScopedViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -14,6 +15,9 @@ class ProductSelectorViewModel @Inject constructor( savedStateHandle: SavedStateHandle, ) : ScopedViewModel(savedStateHandle) { + private var loadProductsJob: Job? = null + private var loadMoreProductsJob: Job? = null + val viewState: StateFlow = productsDataSource.products.map { products -> ViewState( products = products.map { product -> @@ -27,6 +31,8 @@ class ProductSelectorViewModel @Inject constructor( }.toStateFlow(ViewState(products = emptyList())) init { + loadProductsJob?.cancel() + loadMoreProductsJob?.cancel() launch { productsDataSource.loadProducts() } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt index b6339fe910b..dc3c4b9e35e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ViewState.kt @@ -1,6 +1,5 @@ package com.woocommerce.android.ui.woopos.home.products - data class ViewState( val products: List, ) @@ -9,4 +8,4 @@ data class ListItem( val productId: Long, val title: String, val imageUrl: String? = null, -) \ No newline at end of file +) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt index 5e88d6ee6b4..07ae94546c7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt @@ -3,10 +3,10 @@ package com.woocommerce.android.ui.woopos.root.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.navigation -import com.woocommerce.android.ui.woopos.home.cart.CART_ROUTE -import com.woocommerce.android.ui.woopos.home.cart.cartScreen import com.woocommerce.android.ui.woopos.checkout.checkoutScreen import com.woocommerce.android.ui.woopos.checkout.navigateToCheckoutScreen +import com.woocommerce.android.ui.woopos.home.cart.CART_ROUTE +import com.woocommerce.android.ui.woopos.home.cart.cartScreen const val MAIN_GRAPH_ROUTE = "main-graph" From 76056fdd2167f7298f346c1d5df47edd1de6e0fa Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 13:10:50 +0200 Subject: [PATCH 14/21] Clean up code --- .../ui/woopos/home/products/ProductSelectorViewModel.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt index 5d050db6478..5dc7ebf9690 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorViewModel.kt @@ -15,7 +15,6 @@ class ProductSelectorViewModel @Inject constructor( savedStateHandle: SavedStateHandle, ) : ScopedViewModel(savedStateHandle) { - private var loadProductsJob: Job? = null private var loadMoreProductsJob: Job? = null val viewState: StateFlow = productsDataSource.products.map { products -> @@ -31,15 +30,14 @@ class ProductSelectorViewModel @Inject constructor( }.toStateFlow(ViewState(products = emptyList())) init { - loadProductsJob?.cancel() - loadMoreProductsJob?.cancel() launch { productsDataSource.loadProducts() } } fun onEndOfProductsGridReached() { - launch { + loadMoreProductsJob?.cancel() + loadMoreProductsJob = launch { productsDataSource.loadMore() } } From 94ec44a72e33984e5397ff7ffbc1ea980abe3848 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Wed, 22 May 2024 14:55:31 +0200 Subject: [PATCH 15/21] Simplify UI layouts --- .../ui/woopos/home/cart/WooPosCartScreen.kt | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt index 2f11245d822..28b1260a475 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt @@ -50,40 +50,35 @@ private fun WooPosCartScreen( productsState: StateFlow, onEndOfProductsGridReached: () -> Unit, ) { - Box( - Modifier.fillMaxSize(), - contentAlignment = Alignment.Center + Scaffold( + topBar = { + TopAppBar( + navigationIcon = { + Icon( + imageVector = Icons.Default.Close, + contentDescription = "Close POS" + ) + }, + title = { + Text( + modifier = Modifier.fillMaxWidth(), + text = "⚠️ Reader not connected", + style = MaterialTheme.typography.h5, + color = MaterialTheme.colors.onPrimary, + textAlign = TextAlign.Center, + ) + }, + actions = { + Text(text = "History") + } + ) + }, ) { - Scaffold( - topBar = { - TopAppBar( - navigationIcon = { - Icon( - imageVector = Icons.Default.Close, - contentDescription = "Close POS" - ) - }, - title = { - Text( - modifier = Modifier.fillMaxWidth(), - text = "⚠️ Reader not connected", - style = MaterialTheme.typography.h5, - color = MaterialTheme.colors.onPrimary, - textAlign = TextAlign.Center, - ) - }, - actions = { - Text(text = "History") - } - ) - }, + Row( + modifier = Modifier.padding(16.dp) ) { - Row( - modifier = Modifier.padding(16.dp) - ) { - ProductSelector(productsState, onEndOfProductsGridReached) - Cart(onCheckoutClick) - } + ProductSelector(productsState, onEndOfProductsGridReached) + Cart(onCheckoutClick) } } } @@ -118,5 +113,8 @@ fun WooPosCartScreenPreview() { ) ) ) - WooPosCartScreen(onCheckoutClick = {}, productsState = productState, onEndOfProductsGridReached = {}) + WooPosCartScreen( + onCheckoutClick = {}, + productsState = productState, + onEndOfProductsGridReached = {}) } From c5dbaf20250c21ed10b2e4ba0c87df2d18a75e94 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Mon, 3 Jun 2024 21:41:01 +0200 Subject: [PATCH 16/21] Update grid UI --- .../woopos/home/products/ProductSelector.kt | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt index eb97ba31367..574e399107f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt @@ -1,12 +1,18 @@ package com.woocommerce.android.ui.woopos.home.products +import android.util.Log import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement.spacedBy +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.itemsIndexed import androidx.compose.foundation.lazy.grid.rememberLazyGridState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -19,7 +25,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout -import com.woocommerce.android.ui.woopos.util.WooPosPreview +import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged @@ -36,20 +42,19 @@ fun ProductSelector( val state = productsState.collectAsState() val gridState = rememberLazyGridState() LazyVerticalGrid( - columns = GridCells.Adaptive(minSize = 128.dp), - horizontalArrangement = spacedBy(4.dp), - verticalArrangement = spacedBy(4.dp), + columns = GridCells.Fixed(2), + horizontalArrangement = spacedBy(34.dp), + verticalArrangement = spacedBy(34.dp), + contentPadding = PaddingValues(16.dp), state = gridState ) { - items( - count = state.value.products.size, - key = { index -> state.value.products[index].productId } - ) { index -> - ProductItem(product = state.value.products[index]) + itemsIndexed(state.value.products) { _, product -> + ProductItem(product = product) } } InfiniteGridHandler(gridState) { onEndOfProductsGridReached() + Log.d("ProductSelector", "End of products grid reached") } } } @@ -57,7 +62,10 @@ fun ProductSelector( @Composable fun ProductItem(product: ListItem) { ConstraintLayout( - modifier = Modifier.background(Color.Yellow) + modifier = Modifier + .border(1.dp, Color.Gray, shape = RoundedCornerShape(4.dp)) + .padding(16.dp) + .fillMaxWidth(0.5f) ) { Text( text = product.title, @@ -68,7 +76,11 @@ fun ProductItem(product: ListItem) { } @Composable -fun InfiniteGridHandler(gridState: LazyGridState, buffer: Int = 1, onEndOfProductsGridReached: () -> Unit) { +fun InfiniteGridHandler( + gridState: LazyGridState, + buffer: Int = 1, + onEndOfProductsGridReached: () -> Unit +) { val loadMore = remember { derivedStateOf { val layoutInfo = gridState.layoutInfo From e20e62939c14bbc46fb58ab0b08bf1d60e945fcb Mon Sep 17 00:00:00 2001 From: samiuelson Date: Mon, 3 Jun 2024 21:41:10 +0200 Subject: [PATCH 17/21] Update grid UI --- .../android/ui/woopos/home/products/ProductSelector.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt index 574e399107f..e4b041bf391 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt @@ -54,7 +54,6 @@ fun ProductSelector( } InfiniteGridHandler(gridState) { onEndOfProductsGridReached() - Log.d("ProductSelector", "End of products grid reached") } } } From 9896ea735f52624ef7cbe677f18f2c29e0e1427a Mon Sep 17 00:00:00 2001 From: samiuelson Date: Mon, 3 Jun 2024 22:03:31 +0200 Subject: [PATCH 18/21] Adjust colors for dark/light theme --- .../ui/woopos/common/composeui/WooPosTheme.kt | 14 ++++++++------ .../ui/woopos/home/cart/WooPosCartScreen.kt | 14 ++++++++++++-- .../ui/woopos/home/products/ProductSelector.kt | 5 ++++- .../ui/woopos/root/WooPosRootBottomToolbar.kt | 5 +++-- .../android/ui/woopos/root/WooPosRootScreen.kt | 3 ++- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt index 8f9ffae6dc8..bde985f497b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt @@ -11,23 +11,25 @@ import androidx.compose.ui.graphics.Color import com.woocommerce.android.ui.compose.theme.WooTypography private val DarkColorPalette = darkColors( - primary = Color(0xFF1E88E5), + primary = Color(0xFFAD86E9), primaryVariant = Color(0xFF1565C0), secondary = Color(0xFFD32F2F), onPrimary = Color.White, secondaryVariant = Color(0xFFB39DDB), - surface = Color.White, - onSurface = Color.Black, + surface = Color.Black, + onSurface = Color.White, + background = Color.Black ) private val LightColorPalette = lightColors( - primary = Color(0xFF1E88E5), + primary = Color(0xFFAD86E9), primaryVariant = Color(0xFF1565C0), secondary = Color(0xFFD32F2F), onPrimary = Color.White, secondaryVariant = Color(0xFFB39DDB), - surface = Color.Black, - onSurface = Color.White + surface = Color.White, + onSurface = Color.Black, + background = Color.Black ) @Composable diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt index 4b6c766692d..471211cb5cb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -44,7 +45,12 @@ private fun WooPosCartScreen( productsState: StateFlow, onEndOfProductsGridReached: () -> Unit, ) { - Row { + Row( + modifier = Modifier + .background(MaterialTheme.colors.background) + .padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 0.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { ProductSelector(productsState, onEndOfProductsGridReached) Cart(onCheckoutClick) } @@ -52,7 +58,11 @@ private fun WooPosCartScreen( @Composable private fun Cart(onButtonClicked: () -> Unit) { - Column { + Column( + modifier = Modifier + .background(MaterialTheme.colors.surface, RoundedCornerShape(8.dp)) + .padding(16.dp) + ) { Text( text = "Cart", style = MaterialTheme.typography.h3, diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt index e4b041bf391..d7a4b542514 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt @@ -37,7 +37,10 @@ fun ProductSelector( onEndOfProductsGridReached: () -> Unit, ) { ConstraintLayout( - modifier = Modifier.fillMaxWidth(0.7f) + modifier = Modifier + .fillMaxWidth(0.7f) + .background(MaterialTheme.colors.surface, RoundedCornerShape(8.dp)) + .padding(16.dp) ) { val state = productsState.collectAsState() val gridState = rememberLazyGridState() diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootBottomToolbar.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootBottomToolbar.kt index 18cce59b04c..0efb96a5afb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootBottomToolbar.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootBottomToolbar.kt @@ -15,6 +15,7 @@ import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.woocommerce.android.R @@ -27,7 +28,7 @@ fun WooPosBottomToolbar(onUIEvent: (WooPosRootUIEvents) -> Unit) { modifier = Modifier .fillMaxWidth() .wrapContentHeight(), - color = MaterialTheme.colors.surface + color = MaterialTheme.colors.background ) { Row( modifier = Modifier @@ -40,7 +41,7 @@ fun WooPosBottomToolbar(onUIEvent: (WooPosRootUIEvents) -> Unit) { TextButton(onClick = { onUIEvent(WooPosRootUIEvents.ExitPOSClicked) }) { Text( text = stringResource(id = R.string.woopos_exit_pos), - color = MaterialTheme.colors.onSurface, + color = Color.White, style = MaterialTheme.typography.button ) } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt index c37a92e7b1d..b9b82905e9c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.woopos.root import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -19,7 +20,7 @@ fun WooPosRootScreen() { @Composable private fun WooPosRootScreen(onUIEvent: (WooPosRootUIEvents) -> Unit) { WooPosTheme { - Column(modifier = Modifier.background(Color.Black)) { + Column(modifier = Modifier.background(MaterialTheme.colors.background)) { WooPosRootHost(modifier = Modifier.weight(1f)) WooPosBottomToolbar(onUIEvent) } From 4c7d9c8a78038a4e00b8dc16ef95023c4bc71a43 Mon Sep 17 00:00:00 2001 From: samiuelson Date: Tue, 4 Jun 2024 09:36:45 +0200 Subject: [PATCH 19/21] Decouple product selector from cart --- ...tNavigation.kt => WooPosHomeNavigation.kt} | 11 ++--- ...ooPosCartScreen.kt => WooPosHomeScreen.kt} | 43 ++++--------------- .../android/ui/woopos/home/cart/CartScreen.kt | 38 ++++++++++++++++ ...ctSelector.kt => ProductSelectorScreen.kt} | 1 - .../ui/woopos/root/WooPosRootScreen.kt | 1 - .../root/navigation/WooPosMainFlowGraph.kt | 8 ++-- WooCommerce/src/main/res/values/strings.xml | 1 + 7 files changed, 57 insertions(+), 46 deletions(-) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/{cart/WooPosCartNavigation.kt => WooPosHomeNavigation.kt} (65%) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/{cart/WooPosCartScreen.kt => WooPosHomeScreen.kt} (66%) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/CartScreen.kt rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/{ProductSelector.kt => ProductSelectorScreen.kt} (99%) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartNavigation.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeNavigation.kt similarity index 65% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartNavigation.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeNavigation.kt index abba99b8b2a..ada21a4f0f7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartNavigation.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeNavigation.kt @@ -1,18 +1,19 @@ -package com.woocommerce.android.ui.woopos.home.cart +package com.woocommerce.android.ui.woopos.home import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import com.woocommerce.android.ui.woopos.home.cart.WooPosCartViewModel import com.woocommerce.android.ui.woopos.home.products.ProductSelectorViewModel -internal const val CART_ROUTE = "cart" +internal const val HOME_ROUTE = "home" -internal fun NavGraphBuilder.cartScreen(onCheckoutClick: () -> Unit) { - composable(CART_ROUTE) { +internal fun NavGraphBuilder.homeScreen(onCheckoutClick: () -> Unit) { + composable(HOME_ROUTE) { val cartViewModel: WooPosCartViewModel = hiltViewModel() val productsViewModel: ProductSelectorViewModel = hiltViewModel() - WooPosCartScreen( + WooPosHomeScreen( cartViewModel = cartViewModel, productsViewModel = productsViewModel, onCheckoutClick = onCheckoutClick diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt similarity index 66% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt index 471211cb5cb..9558df656e8 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/WooPosCartScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt @@ -1,22 +1,17 @@ -package com.woocommerce.android.ui.woopos.home.cart +package com.woocommerce.android.ui.woopos.home import android.annotation.SuppressLint import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview +import com.woocommerce.android.ui.woopos.home.cart.Cart +import com.woocommerce.android.ui.woopos.home.cart.WooPosCartViewModel import com.woocommerce.android.ui.woopos.home.products.ListItem import com.woocommerce.android.ui.woopos.home.products.ProductSelector import com.woocommerce.android.ui.woopos.home.products.ProductSelectorViewModel @@ -26,12 +21,12 @@ import kotlinx.coroutines.flow.StateFlow @Composable @Suppress("UNUSED_PARAMETER") -fun WooPosCartScreen( +fun WooPosHomeScreen( cartViewModel: WooPosCartViewModel, productsViewModel: ProductSelectorViewModel, onCheckoutClick: () -> Unit, ) { - WooPosCartScreen( + WooPosHomeScreen( onCheckoutClick = onCheckoutClick, productsState = productsViewModel.viewState, onEndOfProductsGridReached = productsViewModel::onEndOfProductsGridReached, @@ -40,7 +35,7 @@ fun WooPosCartScreen( @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable -private fun WooPosCartScreen( +private fun WooPosHomeScreen( onCheckoutClick: () -> Unit, productsState: StateFlow, onEndOfProductsGridReached: () -> Unit, @@ -56,31 +51,9 @@ private fun WooPosCartScreen( } } -@Composable -private fun Cart(onButtonClicked: () -> Unit) { - Column( - modifier = Modifier - .background(MaterialTheme.colors.surface, RoundedCornerShape(8.dp)) - .padding(16.dp) - ) { - Text( - text = "Cart", - style = MaterialTheme.typography.h3, - color = MaterialTheme.colors.primary, - ) - Spacer(modifier = Modifier.weight(1f)) - Button( - modifier = Modifier.fillMaxWidth(), - onClick = onButtonClicked, - ) { - Text("Checkout") - } - } -} - @Composable @WooPosPreview -fun WooPosCartScreenPreview() { +fun WooPosHomeScreenPreview() { val productState = MutableStateFlow( ViewState( products = listOf( @@ -90,7 +63,7 @@ fun WooPosCartScreenPreview() { ) ) ) - WooPosCartScreen( + WooPosHomeScreen( onCheckoutClick = {}, productsState = productState, onEndOfProductsGridReached = {} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/CartScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/CartScreen.kt new file mode 100644 index 00000000000..686f0559a32 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/cart/CartScreen.kt @@ -0,0 +1,38 @@ +package com.woocommerce.android.ui.woopos.home.cart + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.woocommerce.android.R + +@Composable +fun Cart(onButtonClicked: () -> Unit) { + Column( + modifier = Modifier + .background(MaterialTheme.colors.surface, RoundedCornerShape(8.dp)) + .padding(16.dp) + ) { + Text( + text = "Cart", + style = MaterialTheme.typography.h3, + color = MaterialTheme.colors.primary, + ) + Spacer(modifier = Modifier.weight(1f)) + Button( + modifier = Modifier.fillMaxWidth(), + onClick = onButtonClicked, + ) { + Text(stringResource(id = R.string.woopos_checkout)) + } + } +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt similarity index 99% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt index d7a4b542514..9dacfa61653 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelector.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt @@ -1,6 +1,5 @@ package com.woocommerce.android.ui.woopos.home.products -import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement.spacedBy diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt index b9b82905e9c..c550fc4c57f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/WooPosRootScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.hilt.navigation.compose.hiltViewModel import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview import com.woocommerce.android.ui.woopos.common.composeui.WooPosTheme diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt index c3d2dcc450a..8488f5437e4 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/root/navigation/WooPosMainFlowGraph.kt @@ -5,17 +5,17 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.navigation import com.woocommerce.android.ui.woopos.checkout.checkoutScreen import com.woocommerce.android.ui.woopos.checkout.navigateToCheckoutScreen -import com.woocommerce.android.ui.woopos.home.cart.CART_ROUTE -import com.woocommerce.android.ui.woopos.home.cart.cartScreen +import com.woocommerce.android.ui.woopos.home.HOME_ROUTE +import com.woocommerce.android.ui.woopos.home.homeScreen const val MAIN_GRAPH_ROUTE = "main-graph" fun NavGraphBuilder.checkoutGraph(navController: NavController) { navigation( - startDestination = CART_ROUTE, + startDestination = HOME_ROUTE, route = MAIN_GRAPH_ROUTE, ) { - cartScreen(onCheckoutClick = navController::navigateToCheckoutScreen) + homeScreen(onCheckoutClick = navController::navigateToCheckoutScreen) checkoutScreen(onBackClick = navController::popBackStack) } } diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index 0d50cd6c2ff..f9e0e465426 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -4116,4 +4116,5 @@ --> Exit POS Reader Connected + Checkout From 081df9cca85af3a0b0c751617e8405b9d90ca58c Mon Sep 17 00:00:00 2001 From: samiuelson Date: Tue, 4 Jun 2024 12:18:31 +0200 Subject: [PATCH 20/21] Fix lint --- .../android/ui/woopos/common/composeui/WooPosTheme.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt index bde985f497b..57fa4169fb9 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/composeui/WooPosTheme.kt @@ -18,7 +18,8 @@ private val DarkColorPalette = darkColors( secondaryVariant = Color(0xFFB39DDB), surface = Color.Black, onSurface = Color.White, - background = Color.Black + background = Color.Black, + onBackground = Color.White, ) private val LightColorPalette = lightColors( @@ -29,7 +30,8 @@ private val LightColorPalette = lightColors( secondaryVariant = Color(0xFFB39DDB), surface = Color.White, onSurface = Color.Black, - background = Color.Black + background = Color.Black, + onBackground = Color.White, ) @Composable From d522c9209fe3f959f92b2fb3aefecf8b5796afec Mon Sep 17 00:00:00 2001 From: samiuelson Date: Tue, 4 Jun 2024 12:21:57 +0200 Subject: [PATCH 21/21] Fill product selector's height --- .../android/ui/woopos/home/products/ProductSelectorScreen.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt index 9dacfa61653..51ae35e4ad8 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/products/ProductSelectorScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells @@ -38,6 +39,7 @@ fun ProductSelector( ConstraintLayout( modifier = Modifier .fillMaxWidth(0.7f) + .fillMaxHeight() .background(MaterialTheme.colors.surface, RoundedCornerShape(8.dp)) .padding(16.dp) ) {