Skip to content

Refresh the RS post and page lists when FluxC changes a post - #23235

Merged
nbradbury merged 10 commits into
trunkfrom
issue/rs-posts-pages-fluxc-handling
Aug 20, 2026
Merged

Refresh the RS post and page lists when FluxC changes a post#23235
nbradbury merged 10 commits into
trunkfrom
issue/rs-posts-pages-fluxc-handling

Conversation

@nbradbury

@nbradbury nbradbury commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Description

TL/DR: the wordpress-rs post and page lists never noticed edits made in the editor. This PR adds a temporary FluxC bridge so they refresh themselves. Once the editor switches to wp-rs we can remove this in favor of an RS-based solution.


The rs lists are driven by an rs ObservableMetadataCollection, which only sees changes rs itself made. The editor and UploadService write through FluxC, so a post edited in the editor stayed stale in the list until the user pulled to refresh. The posts list subscribed to nothing at all; the pages list had a single ad-hoc OnPostUploaded handler added for the duplicate-page flow.

New RsPostChangeListener is the whole bridge — one file, injected into both view models, so when wordpress-rs can report these changes itself it's one deletion plus two constructor params. It reports OnPostUploaded, and the OnPostChanged causes that mean the server copy changed (UpdatePost with isLocalUpdate = false, DeletePost, RestorePost), filtered by site and post-vs-page. Emissions are debounced 500ms because a WP.com publish fires two events back to back. RemoteAutoSavePost is deliberately ignored — it stores a revision and leaves the published post the list renders untouched, and it's the common "back out of the editor without tapping Update" path. So is UpdatePost with isLocalUpdate = true, which fires on every debounced keystroke in the editor.

The pages list's inline handler is removed in favour of the shared one, which also gives it the OnPostChanged coverage it didn't have.

Three things worth knowing when reading the listener:

  • Threading. onPostChanged is delivered on ThreadMode.BACKGROUND, because deciding whether a post belongs to this list means reading it back out of the database and the event fires on every write FluxC makes. onPostUploaded stays on MAIN — the event already carries the PostModel. The fields both handlers read are @Volatile accordingly.
  • Start/stop contract. Collect changes before calling start(): the flow has no replay, so an event arriving before the collector subscribes is dropped. stop() is safe whether or not start() was ever reached, which matters because the view models clear unconditionally but only start when a site is selected.
  • Refreshes are deferred while the list is hidden. Most of these changes arrive while the editor is covering the list, and refreshing a screen nobody is looking at spends a request per open tab. A hidden list records that it's out of date, however many changes arrive, and refreshes once on onStart.

Also fixed here, because this PR is what makes it reachable without user action: refreshTab() had no in-flight guard, so a pull-to-refresh and an automatic refresh could run collection.refresh() concurrently on the same collection and each replace the other's metadata. RsTabRefreshJobs now holds a tab to one refresh at a time and replays a request that arrived mid-flight, since the running refresh may have asked the server before the change landed.

⚠️ Known trade-off: a refresh re-fetches page 1 and replaces the stored metadata, so a list scrolled well past 20 items snaps back. That's already how pull-to-refresh behaves; rs 0.6.0 has no narrower invalidation.

Out of scope: upload-progress and upload-error UI. The legacy lists use PostEvents / UploadService events for in-flight and failed badges — the rs lists have no such UI.

Testing instructions

Requires a site with an application password, so the rs lists are used.

Post list updates after an edit:

  1. Open Posts and tap a published post.
  2. Change the title and tap Update, then go back.
  • Verify the row shows the new title without a pull to refresh.

New post appears:

  1. Open Posts and create a new post.
  2. Publish it and go back.
  • Verify it appears on the Published tab.

Page duplication still works:

  1. Open Pages and duplicate a page.
  • Verify the duplicate appears in the list once it finishes publishing.

The rs collections only see changes rs itself made, so a post saved in
the editor stayed stale in the list until the user pulled to refresh.
RsPostChangeListener bridges the FluxC post events until wordpress-rs can
report those changes itself.
@dangermattic

dangermattic commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator
2 Warnings
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
⚠️ PR is not assigned to a milestone.

Generated by 🚫 Danger

@wpmobilebot

wpmobilebot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

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

App NameJetpack Android
Build TypeDebug
Versionpr23235-e8a28e6
Build Number1498
Application IDcom.jetpack.android.prealpha
Commite8a28e6
Installation URL18j1lb0udo3e8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot

wpmobilebot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

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

App NameWordPress Android
Build TypeDebug
Versionpr23235-e8a28e6
Build Number1498
Application IDorg.wordpress.android.prealpha
Commite8a28e6
Installation URL52dr1igpi1of0
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot

Copy link
Copy Markdown
Contributor

🤖 Build Failure Analysis

This build has failures. Claude has analyzed them - check the build annotations for details.

Guard start/stop so a view model that never selected a site doesn't
unregister a listener it never registered, subscribe to the change flow
before starting the listener so a change can't land before the collector
does, and move the post-changed handler off the main thread since
deciding whether a post belongs to the list reads it back from the DB.
Detekt caps a function at two return statements.
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.82353% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.97%. Comparing base (e51c12c) to head (e8a28e6).
⚠️ Report is 1 commits behind head on trunk.

Files with missing lines Patch % Lines
...rdpress/android/ui/pagesrs/PagesRsListViewModel.kt 63.63% 8 Missing ⚠️
...ordpress/android/ui/postsrs/PostRsListViewModel.kt 63.63% 8 Missing ⚠️
...rg/wordpress/android/ui/rs/RsPostChangeListener.kt 93.33% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk   #23235      +/-   ##
==========================================
+ Coverage   37.94%   37.97%   +0.03%     
==========================================
  Files        2334     2336       +2     
  Lines      127138   127214      +76     
  Branches    17609    17627      +18     
==========================================
+ Hits        48241    48312      +71     
- Misses      74952    74956       +4     
- Partials     3945     3946       +1     

☔ View full report in Codecov by Harness.
📢 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Most FluxC changes arrive while the editor covers the list, so refreshing
then spends a request per open tab on a screen nobody is looking at. A
hidden list now records that it is out of date and refreshes once when it
is shown again.

RsTabRefreshJobs holds each tab to one refresh at a time, since two
concurrent refreshes of a collection would each replace the other's
metadata, and replays a request that arrived mid-refresh because the
running one may have asked the server before the change landed.
Deferring only when the list was hidden meant a change arriving while it
was visible but offline was dropped, never to be refreshed. Remembering
it in both cases collapses the three functions the deferral was spread
over into one and makes the list catch up when it is next shown.
@nbradbury
nbradbury marked this pull request as ready for review August 19, 2026 13:04
@nbradbury
nbradbury requested a review from adalpari August 19, 2026 13:04
@adalpari

Copy link
Copy Markdown
Contributor

This is odd. I update a post title and it's not reflected in the list even if I pull to refresh 🤔

screen-20260819-164746-1787150857105.mp4

@nbradbury

Copy link
Copy Markdown
Contributor Author

This is odd. I update a post title and it's not reflected in the list even if I pull to refresh 🤔

That is definitely odd, but I'm not able to reproduce it. If you visit the blog's web site, did the changes get saved? It might be worth running the network inspector to see if anything is failing.

untitled.webm

@adalpari

Copy link
Copy Markdown
Contributor

This is odd because I cannot even create a post.
I have uninstalled and re-installed the app, and added a fresh jurassic-ninja site

Screen_recording_20260819_172737.mp4

logcat.txt

@nbradbury

nbradbury commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Update: The upload failures aren't due to changes in this PR. Actual problem filed in Linear CMM-2331.

@adalpari

Copy link
Copy Markdown
Contributor

Tested with a non-Jurassic-ninja site and it works as expected.

Just one note: when I create a new post, the list does not scroll to the top. I can slightly see there's a new card at the top, but I have to scroll the list to see the new post. Is that something we can improve?

screen-20260820-101626-1787213755495.mp4

@nbradbury

Copy link
Copy Markdown
Contributor Author

Just one note: when I create a new post, the list does not scroll to the top.

I filed a separate issue for this. It was waiting for the fix in this PR before it could be tackled.

@adalpari adalpari left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a CI issue, but overall LGTM!

@nbradbury
nbradbury enabled auto-merge (squash) August 20, 2026 12:38
@nbradbury
nbradbury merged commit f5292aa into trunk Aug 20, 2026
21 of 23 checks passed
@nbradbury
nbradbury deleted the issue/rs-posts-pages-fluxc-handling branch August 20, 2026 12:49
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