Skip to content

Improve error handling in RS post list#22633

Merged
nbradbury merged 81 commits intotrunkfrom
issue/rs-posts-friendlier-errors
Feb 27, 2026
Merged

Improve error handling in RS post list#22633
nbradbury merged 81 commits intotrunkfrom
issue/rs-posts-friendlier-errors

Conversation

@nbradbury
Copy link
Contributor

@nbradbury nbradbury commented Feb 26, 2026

Description

Replaces silent failures and low-visibility Toasts with Snackbars (with optional retry actions) and adds a retry button to the full-screen error state. Raw wordpress-rs exception messages are no longer surfaced to users — instead, the error type is inspected to show context-specific messages for offline, authentication, and generic failures.

Before / After

Scenario Before After
Full-screen error (no posts) Error text only; user must know to pull-to-refresh Error text + Retry button
Refresh fails with stale posts visible Full-screen error replaces the post list Posts stay visible; Snackbar with Retry action
Pagination failure (load more) Silent — no user feedback Snackbar with context-specific message
Post action success (trash, delete, publish, etc.) Toast Snackbar
Post action failure Toast Snackbar
Network unavailable (pre-action check) Toast Snackbar
Post not found in local DB Toast Snackbar
ListState.ERROR with stale posts Full-screen error replaces the post list Posts stay visible; Snackbar with Retry action
Blog not found on init Toast (before Activity finishes) Toast (unchanged)
Error message: offline Raw wordpress-rs exception A network error occurred. Please check your connection and try again.
Error message: auth failure Raw wordpress-rs exception Your authentication has expired. Please sign in again.
Error message: other Raw wordpress-rs exception There was a problem handling the request. Please try again later.

Test simulation toggles (removed)

In PostRsListViewModel.kt companion object, flip any constant to true to trigger that error path:

Toggle Error path
SIMULATE_INIT_ERROR Full-screen error with retry button (generic error)
SIMULATE_REFRESH_ERROR Snackbar with Retry if posts exist, full-screen error if empty
SIMULATE_LOAD_MORE_ERROR Snackbar on scroll (generic error)
SIMULATE_ACTION_ERROR Error snackbar when trashing, publishing, etc.
SIMULATE_AUTH_ERROR Auth-specific error message in init, refresh, and load-more paths

Testing instructions

Test with simulation toggles:

  1. Set SIMULATE_INIT_ERROR = true, build and open the post list

    • Verify full-screen error shows with centered title/subtitle and a Retry button
    • Subtitle should say: There was a problem handling the request. Please try again later.
    • Tap Retry — verify it attempts to reload
  2. Set SIMULATE_AUTH_ERROR = true (others false), build and open the post list

    • Verify full-screen error subtitle says: Your authentication has expired. Please sign in again.
  3. Set SIMULATE_REFRESH_ERROR = true (others false), build and open the post list

    • Verify posts load on first open (init succeeds, refresh fails silently on first load)
    • Pull to refresh
    • Verify posts remain visible and a Snackbar appears with a Retry action
  4. Set SIMULATE_LOAD_MORE_ERROR = true (others false), build and open the post list on a site with >20 posts

    • Scroll to the bottom
    • Verify a Snackbar appears with an error message
  5. Set SIMULATE_ACTION_ERROR = true (others false), build and open the post list

    • Tap overflow menu on a post, choose Trash, confirm
    • Verify a Snackbar shows the error (not a Toast)

Test with airplane mode:

  1. Enable airplane mode, open the post list

    • Verify error subtitle says: A network error occurred. Please check your connection and try again.
  2. Open the post list normally, then enable airplane mode and pull to refresh

    • Verify posts stay visible with a Snackbar

nbradbury and others added 30 commits February 17, 2026 09:09
Add three-dot overflow menu to each post card with status-aware actions:
Published/Private posts get View, Read, Move to Draft, Duplicate, Share,
Blaze, Stats, Comments, and Trash. Draft/Pending/Scheduled posts get
Duplicate and Trash. Trashed posts get Move to Draft and Delete Permanently.

Navigation actions (View, Read, Share, Stats, Comments, Blaze) are fully
wired to launch the appropriate activities. Mutation actions (Move to Draft,
Duplicate, Trash, Delete) are UI-only no-ops that will be connected to
wordpress-rs networking in a follow-up PR.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…king

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Group confirmation dialog callbacks into ConfirmationDialogState data
  class, reducing PostRsListScreen from 19 to 15 parameters
- Extract TrashConfirmationDialog and DeleteConfirmationDialog composables
- Add TODO for findPost() linear scan optimization
- Fix import ordering for uniffi.wp_api.PostStatus
- Remove unused featuredImageId field from PostRsUiModel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…atching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace "Not implemented yet" placeholders with actual API calls for
Trash, Delete Permanently, Publish, Move to Draft, and Duplicate
actions using wordpress-rs (no FluxC). After each successful mutation
all initialized tab collections are refreshed so the list updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The duplicate networking (fetching + creating on server) is deferred
to a later branch so the approach can be revisited.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Optimistically remove the post from local tab state on success so
Compose's animateItem() can fade it out and smoothly slide remaining
items up, instead of the list jumping instantly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused post_rs_duplicated and post_rs_error_duplicate strings
- Consolidate ShowError into ShowToast (both showed a toast)
- Make ConfirmationDialogState a data class
- Remove trailing blank line in PostRsRestClient

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of checking getSelectedSite() in 6 different places with
inconsistent null-handling patterns, store the site at construction
time and send Finish event (with toast) if no site is selected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace defensive val site = site ?: return with site!! since the
Activity finishes on init when site is null. Consolidate two
postStore.getPostByRemotePostId calls into a getFluxCPost helper
that shows a toast when the post isn't found.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use a private _site backing field with a non-null site getter that
calls requireNotNull with a descriptive message. This eliminates 14
uses of site!! and provides a clear error if site is accessed after
the Activity should have finished.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adapt to API change: WpSelfHostedService replaced by WpService
with factory method, ApiUrlResolver parameter removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename WpSelfHostedServiceProvider to WpServiceProvider and add WP.com
support using WpService.wordpressCom() with bearer token auth. Update
PostRsRestClient to route WP.com post mutations through the WP.com REST
API proxy. Update ActivityLauncher gateway to allow WP.com sites when
the RS post list experimental feature is enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove "self-hosted" qualifier since the feature now supports all sites
with application passwords.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplify the RS post list gateway to require hasApplicationPassword()
for all sites, matching the feature description. Cache WP.com WpApiClient
instances by siteId to avoid recreating them on every mutation call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nbradbury and others added 3 commits February 26, 2026 07:53
Network errors from wordpress-rs surface verbose internal messages like
"UniffiWpApiException$RequestExecutionFailed..." to the user. Replace all
raw e.message / listInfo.errorMessage usage with a helper that checks
network state and returns the appropriate user-facing string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The error screen title and subtitle were both "An error occurred". Now the
subtitle gives actionable context: a network-specific message when offline,
or a generic request failure message otherwise. The subtitle text is also
center-aligned to match the title.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flip any SIMULATE_*_ERROR constant to true to trigger that error path.
Remove before merging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dangermattic
Copy link
Collaborator

dangermattic commented Feb 26, 2026

1 Warning
⚠️ PR is not assigned to a milestone.

Generated by 🚫 Danger

@nbradbury nbradbury changed the base branch from issue/rs-posts-auth-featured-images to trunk February 26, 2026 14:04
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Feb 26, 2026

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
FlavorJalapeno
Build TypeDebug
Versionpr22633-42cc798
Build Number1485
Application IDcom.jetpack.android.prealpha
Commit42cc798
Installation URL0iqkk1vst2cf0
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Feb 26, 2026

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
FlavorJalapeno
Build TypeDebug
Versionpr22633-42cc798
Build Number1485
Application IDorg.wordpress.android.prealpha
Commit42cc798
Installation URL1m28vmt99gs1o
Note: Google Login is not supported on these builds.

nbradbury and others added 4 commits February 26, 2026 09:52
Inspect WpApiException subtypes to distinguish offline, auth, and generic
errors. Invalid or revoked application passwords now show "Your
authentication has expired. Please sign in again." instead of the generic
request failure message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Throws a WpApiException with HttpAuthenticationRejectedError to verify
the "Your authentication has expired" message appears. Remove before
merging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The friendly error messages weren't matching specific error types
because exceptions are now wrapped in FetchException.Api. Unwrap
the inner WpApiException before checking for auth errors, offline
status, and other specific error codes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Feb 26, 2026

Codecov Report

❌ Patch coverage is 0% with 103 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.12%. Comparing base (09ba92d) to head (42cc798).
⚠️ Report is 1 commits behind head on trunk.

Files with missing lines Patch % Lines
...ordpress/android/ui/postsrs/PostRsListViewModel.kt 0.00% 77 Missing ⚠️
.../android/ui/postsrs/screens/PostRsTabListScreen.kt 0.00% 11 Missing ⚠️
...ess/android/ui/postsrs/screens/PostRsListScreen.kt 0.00% 10 Missing ⚠️
.../wordpress/android/ui/postsrs/PostRsListUiState.kt 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk   #22633      +/-   ##
==========================================
- Coverage   38.15%   38.12%   -0.03%     
==========================================
  Files        2263     2263              
  Lines      115731   115813      +82     
  Branches    16073    16093      +20     
==========================================
  Hits        44157    44157              
- Misses      67949    68031      +82     
  Partials     3625     3625              

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

@nbradbury nbradbury requested a review from adalpari February 26, 2026 16:51
@nbradbury nbradbury marked this pull request as ready for review February 26, 2026 16:51
@adalpari
Copy link
Contributor

Set SIMULATE_AUTH_ERROR = true (others false), build and open the post list
Verify full-screen error subtitle says: Your authentication has expired. Please sign in again.

Shouldn't we hide the "Retry" button in this case?

Set SIMULATE_REFRESH_ERROR = true (others false), build and open the post list

In this case, the first loading doesn't work either. I directly see a "There was a problem handling the request" screen.
However, since I can reproduce the scenario with the airplane mode, I think it's just probably a hardcoded error handling problem, and it's not affecrting the login behind it.

Copy link
Contributor

@adalpari adalpari left a comment

Choose a reason for hiding this comment

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

Nice improvement!!
I just left a couple of comments, but I don't think they are blocking the PR.

nbradbury and others added 3 commits February 27, 2026 06:47
Auth failures won't resolve by retrying, so suppress the retry action
in both the full-screen error state and snackbar messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nbradbury
Copy link
Contributor Author

Shouldn't we hide the "Retry" button in this case?

Good call, I added this in 4f674f8.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link

@nbradbury nbradbury enabled auto-merge (squash) February 27, 2026 12:39
@nbradbury nbradbury merged commit 18046b0 into trunk Feb 27, 2026
23 of 24 checks passed
@nbradbury nbradbury deleted the issue/rs-posts-friendlier-errors branch February 27, 2026 13:06
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