-
Notifications
You must be signed in to change notification settings - Fork 133
[Bookings] Add "Sort by" logic to booking list screen #14687
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Conversation
) | ||
} | ||
|
||
state.contentState.loadingState == BookingListLoadingState.Loading -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the position of the Loading
state. Now the state is Loading
, we now show the loading indicator even if content already exists. Rationale: once a load starts, the on-screen data is about to change and is effectively outdated, so it’s clearer to show a loading indicator until the refreshed list arrives.
As an alternative, after switching tabs we could cached DB data first (a silent update), kick off the backend fetch, and then update if the data changes. But we can't do that currently because BookingsStore
clears the DB after fetching the first page.
@hichamboushaba, what was the reason for clearing the DB? I removed that behavior in the patch below; tab switching feels smoother without it, but I’d like to understand the original motivation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the position of the Loading state. Now the state is Loading, we now show the loading indicator even if content already exists
Hmm, with this we lose any benefits of the DB cache, we'll always show the loading screen.
@hichamboushaba, what was the reason for clearing the DB?
We clear the DB because there might some deleted bookings there, we need to delete them on the client too, this is the same approach we use for other screens (for example for products).
To make it clear we are refreshing the data when changing the order, we can use fetchBookings(BookingListLoadingState.Refreshing)
, this will show the pull-to-refresh indicator, same as what we do for the other screens, and it will allow us to keep displaying the cached data while we load the updated data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've applied all of your suggestions.
I also considered using a “refreshing” state, but there’s an issue when we don’t show the loading state.
In the video, only the first page is initially loaded. When I change the Sort by option to "Newest," the screen first sorts the currently loaded bookings, then fetches additional data and updates the list a second time, you can notice this in the recording. My intent was to avoid that double update.
This will be mostly affect the All tab, since the newest and oldest bookings are on different pages. We won't see it on the Today and Upcoming tabs if they don't have more than 25 bookings.
I also tested the Products screen and it shows the same behavior. For consistency, I’m fine proceeding with this PR, but I wanted to call out this behavior.
Screen_recording_20251004_170517.webm
📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
|
📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.
|
77a7eac
to
a201bb2
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## trunk #14687 +/- ##
==========================================
Coverage 38.38% 38.39%
+ Complexity 9836 9829 -7
==========================================
Files 2094 2096 +2
Lines 116801 116902 +101
Branches 15633 15636 +3
==========================================
+ Hits 44837 44879 +42
- Misses 67801 67861 +60
+ Partials 4163 4162 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
isSortSheetVisible.value = false | ||
// TODO Apply the selected sorting to the data for the active tab | ||
bookingsFetchJob?.cancel() | ||
bookingsFetchJob = fetchBookings(BookingListLoadingState.Loading) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a full review yet, but just sharing a remark here 🙂, it would be great to keep the screen reactive here as it would make the logic simpler, and would be less error prone.
So let's react to the changes of sortOptionsByTab
instead of doing the fetch here, what I mean can be achieved by something like this patch:
Patch
Index: WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModel.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModel.kt
--- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModel.kt (revision a201bb2c18c3e21b3b63e87d1520303914543f03)
+++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModel.kt (date 1759485611365)
@@ -8,11 +8,15 @@
import com.woocommerce.android.viewmodel.ScopedViewModel
import com.woocommerce.android.viewmodel.getStateFlow
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.drop
+import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption
import javax.inject.Inject
@@ -86,14 +90,26 @@
monitorFilterChanges()
}
+ @OptIn(ExperimentalCoroutinesApi::class)
private fun monitorFilterChanges() {
launch {
- selectedTab.collectLatest {
+ val sortFlow = selectedTab.flatMapLatest { tab ->
+ sortOptionsByTab.map { it[tab] ?: BookingListSortOption.NewestToOldest }
+ .drop(1) // Skip the initial value to avoid double fetch on init
+ }
+
+ merge(selectedTab, sortFlow).collectLatest {
// Cancel any ongoing fetch or load more operations
bookingsFetchJob?.cancel()
bookingsLoadMoreJob?.cancel()
- bookingsFetchJob = fetchBookings(BookingListLoadingState.Loading)
+ bookingsFetchJob = fetchBookings(
+ initialLoadingState = if (it is BookingListSortOption) {
+ BookingListLoadingState.Refreshing
+ } else {
+ BookingListLoadingState.Loading
+ }
+ )
}
}
}
@@ -143,8 +159,6 @@
sortOptionsByTab.value = sortOptionsByTab.value.toMutableMap()
.also { it[tab] = option }
isSortSheetVisible.value = false
- bookingsFetchJob?.cancel()
- bookingsFetchJob = fetchBookings(BookingListLoadingState.Loading)
}
private fun onSortDismiss() {
If you check the updated BookingListViewModel
now in trunk, you'll see we use the same thing for search, and it works well.
The patch also includes a check to make sure we use Refreshing
instead of Loading
when changing the sort order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you agree with my remark here, it'll simplify the logic quite a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, we should follow the reactive pattern here, I just missed that. I’ve applied your patch (885de66). Thank you!
…OOMOB-1237-booking-list-sorting-logic # Conflicts: # WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/BookingsRepository.kt # WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListHandler.kt # WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModel.kt # WooCommerce/src/test/kotlin/com/woocommerce/android/ui/bookings/list/BookingListHandlerTest.kt # WooCommerce/src/test/kotlin/com/woocommerce/android/ui/bookings/list/BookingListViewModelTest.kt # libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsRestClient.kt # libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsStore.kt
Refactor the bookings list fetching logic to be triggered by changes in the sort option flow. This removes the explicit fetch call in the `onSortOptionSelected` function and uses a `Refreshing` state when sorting.
d0c7c70
to
d3ff701
Compare
Part of WOOMOB-1237
Description
This PR adds logic for the “Sort by” option on the Bookings list screen.
See WOOBOOK-406 for details about the API.
Steps to reproduce
define( 'WC_BOOKINGS_NEXT_ENABLED', true );
The tests that have been performed
Steps above
Images/gif
Screen_recording_20251003_015759.webm
RELEASE-NOTES.txt
if necessary. Use the "[Internal]" label for non-user-facing changes.