Implement shopping lists screen (#129)

* Initialize shopping lists feature

* Start shopping lists screen with Compose

* Add icon to shopping list name

* Add shopping lists to menu

* Set max size for the list

* Replace compose-adapter with accompanist

* Remove unused fields from shopping lists response

* Show list of shopping lists from BE

* Hide shopping lists if Mealie is 0.5.6

* Add shopping list item click listener

* Create material app theme for Compose

* Use shorter names

* Load shopping lists by pages and save to db

* Make page handling logic match recipes

* Add swipe to refresh to shopping lists

* Extract SwipeToRefresh Composable

* Make LazyPagingColumn generic

* Show refresh only when mediator is refreshing

* Do not refresh automatically

* Allow controlling Activity state from modules

* Implement navigating to shopping list screen

* Move Compose libraries setup to a plugin

* Implement loading full shopping list info

* Move Storage classes to database module

* Save shopping list items to DB

* Use separate names for separate ids

* Do only one DB version update

* Use unique names for all columns

* Display shopping list items

* Move OperationUiState to ui module

* Subscribe to shopping lists updates

* Indicate progress with progress bar

* Use strings from resources

* Format shopping list item quantities

* Hide unit/food/note/quantity if they are not set

* Implement updating shopping list item checked state

* Remove unnecessary null checks

* Disable checkbox when it is being updated

* Split shopping list screen into composables

* Show items immediately if they are saved

* Fix showing "list is empty" before the items

* Show Snackbar when error happens

* Reduce shopping list items paddings

* Remove shopping lists when URL is changed

* Add error/empty state handling to shopping lists

* Fix empty error state

* Fix tests compilation

* Add margin between text and button

* Add divider between checked and unchecked items

* Move divider to the item

* Refresh the shopping lists on authentication

* Use retry when necessary

* Remove excessive logging

* Fix pages bounds check

* Move FlowExtensionsTest

* Update Compose version

* Fix showing loading indicator for shopping lists

* Add Russian translation

* Fix SDK version lint check

* Rename parameter to match interface

* Add DB migration TODO

* Get rid of DB migrations

* Do not use pagination with shopping lists

* Cleanup after the pagination removal

* Load shopping list items

* Remove shopping lists storage

* Rethrow CancellationException in LoadingHelper

* Add pull-to-refresh on shopping list screen

* Extract LazyColumnWithLoadingState

* Split refresh errors and loading state

* Reuse LazyColumnWithLoadingState for shopping list items

* Remove paging-compose dependency

* Refresh shopping list items on authentication

* Disable missing translation lint check

* Update Compose and Kotlin versions

* Fix order of checked items

* Hide useless information from a shopping list item
This commit is contained in:
Kirill Kamakin
2023-07-03 15:07:19 +02:00
committed by GitHub
parent a40f9a78ea
commit 1e5e727e92
157 changed files with 3360 additions and 3715 deletions

View File

@@ -0,0 +1,128 @@
package gq.kirmanak.mealient.database
import gq.kirmanak.mealient.database.recipe.entity.RecipeEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeIngredientEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeInstructionEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.database.recipe.entity.RecipeWithSummaryAndIngredientsAndInstructions
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
val CAKE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity(
remoteId = "1",
name = "Cake",
slug = "cake",
description = "A tasty cake",
dateAdded = LocalDate.parse("2021-11-13"),
dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"),
imageId = "cake",
isFavorite = false,
)
val PORRIDGE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity(
remoteId = "2",
name = "Porridge",
slug = "porridge",
description = "A tasty porridge",
dateAdded = LocalDate.parse("2021-11-12"),
dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"),
imageId = "porridge",
isFavorite = false,
)
val TEST_RECIPE_SUMMARY_ENTITIES =
listOf(CAKE_RECIPE_SUMMARY_ENTITY, PORRIDGE_RECIPE_SUMMARY_ENTITY)
val MIX_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
recipeId = "1",
text = "Mix the ingredients",
)
val BAKE_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
recipeId = "1",
text = "Bake the ingredients",
)
val CAKE_RECIPE_ENTITY = RecipeEntity(
remoteId = "1",
recipeYield = "4 servings",
disableAmounts = true,
)
val CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
recipeId = "1",
note = "2 oz of white sugar",
quantity = 1.0,
unit = null,
food = null,
title = null,
)
val CAKE_BREAD_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
recipeId = "1",
note = "2 oz of white bread",
quantity = 1.0,
unit = null,
food = null,
title = null,
)
val FULL_CAKE_INFO_ENTITY = RecipeWithSummaryAndIngredientsAndInstructions(
recipeEntity = CAKE_RECIPE_ENTITY,
recipeSummaryEntity = CAKE_RECIPE_SUMMARY_ENTITY,
recipeIngredients = listOf(
CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY,
CAKE_BREAD_RECIPE_INGREDIENT_ENTITY,
),
recipeInstructions = listOf(
MIX_CAKE_RECIPE_INSTRUCTION_ENTITY,
BAKE_CAKE_RECIPE_INSTRUCTION_ENTITY,
),
)
val PORRIDGE_RECIPE_ENTITY_FULL = RecipeEntity(
remoteId = "2",
recipeYield = "3 servings",
disableAmounts = true,
)
val PORRIDGE_MILK_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
recipeId = "2",
note = "2 oz of white milk",
quantity = 1.0,
unit = null,
food = null,
title = null,
)
val PORRIDGE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
recipeId = "2",
note = "2 oz of white sugar",
quantity = 1.0,
unit = null,
food = null,
title = null,
)
val PORRIDGE_MIX_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
recipeId = "2",
text = "Mix the ingredients"
)
val PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
recipeId = "2",
text = "Boil the ingredients"
)
val FULL_PORRIDGE_INFO_ENTITY = RecipeWithSummaryAndIngredientsAndInstructions(
recipeEntity = PORRIDGE_RECIPE_ENTITY_FULL,
recipeSummaryEntity = PORRIDGE_RECIPE_SUMMARY_ENTITY,
recipeIngredients = listOf(
PORRIDGE_SUGAR_RECIPE_INGREDIENT_ENTITY,
PORRIDGE_MILK_RECIPE_INGREDIENT_ENTITY,
),
recipeInstructions = listOf(
PORRIDGE_MIX_RECIPE_INSTRUCTION_ENTITY,
PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY,
)
)