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:
@@ -11,4 +11,10 @@ android {
|
||||
dependencies {
|
||||
implementation(libs.google.dagger.hiltAndroid)
|
||||
kapt(libs.google.dagger.hiltCompiler)
|
||||
|
||||
testImplementation(libs.jetbrains.kotlinx.coroutinesTest)
|
||||
testImplementation(libs.androidx.test.junit)
|
||||
testImplementation(libs.androidx.coreTesting)
|
||||
testImplementation(libs.google.truth)
|
||||
testImplementation(project(":testing"))
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package gq.kirmanak.mealient.architecture
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
|
||||
fun <T> Flow<T>.valueUpdatesOnly(): Flow<T> = when (this) {
|
||||
is ValueUpdateOnlyFlowImpl<T> -> this
|
||||
else -> ValueUpdateOnlyFlowImpl(this)
|
||||
}
|
||||
|
||||
private class ValueUpdateOnlyFlowImpl<T>(private val upstream: Flow<T>) : Flow<T> {
|
||||
|
||||
override suspend fun collect(collector: FlowCollector<T>) {
|
||||
var previousValue: T? = null
|
||||
upstream.collect { value ->
|
||||
if (previousValue != null && previousValue != value) {
|
||||
collector.emit(value)
|
||||
}
|
||||
previousValue = value
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package gq.kirmanak.mealient.architecture
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import gq.kirmanak.mealient.test.BaseUnitTest
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class FlowExtensionsKtTest : BaseUnitTest() {
|
||||
|
||||
@Test
|
||||
fun `when flow has an update then valueUpdatesOnly sends updated value`() = runTest {
|
||||
val flow = flowOf(1, 2)
|
||||
assertThat(flow.valueUpdatesOnly().toList()).isEqualTo(listOf(2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when flow has repeated values then valueUpdatesOnly sends updated value`() = runTest {
|
||||
val flow = flowOf(1, 1, 1, 2)
|
||||
assertThat(flow.valueUpdatesOnly().toList()).isEqualTo(listOf(2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when flow has one value then valueUpdatesOnly is empty`() = runTest {
|
||||
val flow = flowOf(1)
|
||||
assertThat(flow.valueUpdatesOnly().toList()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when flow has two updates then valueUpdatesOnly sends both`() = runTest {
|
||||
val flow = flowOf(1, 2, 1)
|
||||
assertThat(flow.valueUpdatesOnly().toList()).isEqualTo(listOf(2, 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when flow has three updates then valueUpdatesOnly sends all`() = runTest {
|
||||
val flow = flowOf(1, 2, 1, 3)
|
||||
assertThat(flow.valueUpdatesOnly().toList()).isEqualTo(listOf(2, 1, 3))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user