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

@@ -19,5 +19,9 @@ gradlePlugin {
id = "gq.kirmanak.mealient.library"
implementationClass = "AndroidLibraryConventionPlugin"
}
register("compose") {
id = "gq.kirmanak.mealient.compose"
implementationClass = "AndroidLibraryComposeConventionPlugin"
}
}
}

View File

@@ -0,0 +1,16 @@
import com.android.build.gradle.LibraryExtension
import gq.kirmanak.mealient.configureAndroidCompose
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
extensions.configure<LibraryExtension> {
configureAndroidCompose(this)
}
}
}
}

View File

@@ -0,0 +1,74 @@
package gq.kirmanak.mealient
import com.android.build.api.dsl.CommonExtension
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.provider.Provider
import org.gradle.kotlin.dsl.dependencies
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
internal fun Project.configureAndroidCompose(
commonExtension: CommonExtension<*, *, *, *>,
) {
val variants = when (commonExtension) {
is BaseAppModuleExtension -> commonExtension.applicationVariants
is LibraryExtension -> commonExtension.libraryVariants
else -> error("Unsupported extension type")
}
commonExtension.apply {
buildFeatures {
compose = true
}
composeOptions {
val version = libs.findVersion("composeKotlinCompilerExtension")
kotlinCompilerExtensionVersion = version.get().toString()
}
// Add compose-destinations generated code to Gradle source sets
variants.all {
kotlin.sourceSets {
getByName(name) {
kotlin.srcDir("build/generated/ksp/$name/kotlin")
}
}
}
dependencies {
val bom = library("androidx-compose-bom")
add("implementation", platform(bom))
add("androidTestImplementation", platform(bom))
add("implementation", library("androidx-compose-material3"))
add("implementation", library("androidx-compose-ui-toolingPreview"))
add("implementation", library("androidx-compose-runtime-livedata"))
add("implementation", library("androidx-lifecycle-viewmodelCompose"))
add("implementation", library("google-accompanist-themeadapter-material3"))
add("debugImplementation", library("androidx-compose-ui-tooling"))
add("debugImplementation", library("androidx-compose-ui-testManifest"))
add("androidTestImplementation", library("androidx-compose-ui-testJunit"))
add("implementation", library("composeDestinations-core"))
add("ksp", library("composeDestinations-ksp"))
}
}
}
private fun Project.library(name: String): Provider<MinimalExternalModuleDependency> {
return libs.findLibrary(name).get()
}
private val Project.kotlin: KotlinAndroidProjectExtension
get() = (this as ExtensionAware).extensions.getByName("kotlin") as KotlinAndroidProjectExtension
private fun KotlinAndroidProjectExtension.sourceSets(configure: Action<NamedDomainObjectContainer<KotlinSourceSet>>): Unit =
(this as ExtensionAware).extensions.configure("sourceSets", configure)

View File

@@ -27,7 +27,11 @@ internal fun Project.configureKotlinAndroid(
}
lint {
disable += listOf("ObsoleteLintCustomCheck", "IconMissingDensityFolder")
disable += listOf(
"ObsoleteLintCustomCheck",
"IconMissingDensityFolder",
"MissingTranslation"
)
enable += listOf(
"ConvertToWebp",
"DuplicateStrings",