Skip to content

Conversation

irfano
Copy link
Contributor

@irfano irfano commented Oct 2, 2025

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

  1. Use a CIAB site.
  2. Manually install the bookings plugin from this ZIP file: p1758531103469849/1758101141.913349-slack-C03L1NF1EA3
  3. You'll need to enable bookings v2 on your CIAB testing site. You can do that by installing the Code Snippets plugin to your site and adding the following PHP snippet: define( 'WC_BOOKINGS_NEXT_ENABLED', true );
  4. Navigate to Bookings.
  5. Tap "Sort by" button.
  6. Change the selected option.
  7. Change the tab and repeat 5-6.

The tests that have been performed

Steps above

Images/gif

Screen_recording_20251003_015759.webm
  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

)
}

state.contentState.loadingState == BookingListLoadingState.Loading -> {
Copy link
Contributor Author

@irfano irfano Oct 2, 2025

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.

Remove_deleting_bookings_logic.patch

Copy link
Member

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.

Copy link
Contributor Author

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

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Oct 2, 2025

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App Name WooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commitd3ff701
Direct Downloadwoocommerce-wear-prototype-build-pr14687-d3ff701.apk

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Oct 2, 2025

📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App Name WooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commitd3ff701
Direct Downloadwoocommerce-prototype-build-pr14687-d3ff701.apk

@irfano irfano force-pushed the issue/WOOMOB-1237-booking-list-sorting-logic branch from 77a7eac to a201bb2 Compare October 3, 2025 00:24
@codecov-commenter
Copy link

codecov-commenter commented Oct 3, 2025

Codecov Report

❌ Patch coverage is 50.87719% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.39%. Comparing base (36df697) to head (d3ff701).
⚠️ Report is 24 commits behind head on trunk.

Files with missing lines Patch % Lines
...commerce/android/ui/bookings/BookingsRepository.kt 0.00% 6 Missing ⚠️
...e/android/ui/bookings/list/BookingListViewModel.kt 60.00% 2 Missing and 4 partials ⚠️
...xc/network/rest/wpcom/wc/bookings/BookingsStore.kt 0.00% 4 Missing ⚠️
...press/android/fluxc/persistence/dao/BookingsDao.kt 0.00% 4 Missing ⚠️
...rce/android/ui/bookings/list/BookingListHandler.kt 85.00% 1 Missing and 2 partials ⚠️
...twork/rest/wpcom/wc/bookings/BookingsRestClient.kt 0.00% 3 Missing ⚠️
...work/rest/wpcom/wc/bookings/BookingsOrderOption.kt 60.00% 2 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

isSortSheetVisible.value = false
// TODO Apply the selected sorting to the data for the active tab
bookingsFetchJob?.cancel()
bookingsFetchJob = fetchBookings(BookingListLoadingState.Loading)
Copy link
Member

@hichamboushaba hichamboushaba Oct 3, 2025

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.

Copy link
Member

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.

Copy link
Contributor Author

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
Base automatically changed from issue/WOOMOB-1237-booking-list-sorting-ui to trunk October 3, 2025 15:43
@irfano irfano added this to the 23.5 milestone Oct 4, 2025
irfano added 3 commits October 4, 2025 17:12
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.
@irfano irfano force-pushed the issue/WOOMOB-1237-booking-list-sorting-logic branch from d0c7c70 to d3ff701 Compare October 4, 2025 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants