Skip to content

Add pagination to navigation menus#22560

Merged
nbradbury merged 17 commits intotrunkfrom
issue/menus-pagination
Feb 6, 2026
Merged

Add pagination to navigation menus#22560
nbradbury merged 17 commits intotrunkfrom
issue/menus-pagination

Conversation

@nbradbury
Copy link
Contributor

@nbradbury nbradbury commented Feb 5, 2026

Description

Partially addresses CMM-1166.

Adds pagination support to the navigation menus feature, allowing users to browse large lists of menus, menu items, and linkable items (posts, pages, categories, tags) without loading everything at once.

Key changes:

  • Add pagination to menu list, menu item list, and linkable items selection
  • Replace linkable items dropdown with modal bottom sheet (fixes crash with LazyColumn inside ExposedDropdownMenu)
  • Add mutex protection to prevent race conditions during rapid pagination requests
  • Cancel in-flight linkable items requests when menu item type changes
  • Simplify error handling
  • Updated URL validation logic based on WordPress documentation

Limitations

  • Saving menu items other than custom links will always fail
  • I've skipped adding new tests for the pagination for now

Testing instructions

Menu list pagination:

  1. Open navigation menus for a site with many menus (or create 20+ menus)
  2. Scroll to the bottom of the menu list
  • Verify loading indicator appears when reaching the end
  • Verify more menus load and append to the list

Menu item list pagination:

  1. Open a menu with many items (or create 20+ items in a menu)
  2. Scroll to the bottom of the menu item list
  • Verify loading indicator appears
  • Verify more items load correctly with proper hierarchy/indentation

Linkable items pagination:

  1. Create a new menu item
  2. Select "Page" as the type
  3. Tap the "Link to" field to open the bottom sheet
  • Verify pages load in the bottom sheet
  1. Scroll to the bottom of the list
  • Verify more pages load
  1. Switch type to "Post"
  • Verify previous loading is cancelled and posts load instead

Error handling:

  1. Put device in airplane mode
  2. Try to load more menus/items
  • Verify error message appears
  • Verify you can retry after re-enabling network
Screen_recording_20260205_072459.mp4

nbradbury and others added 4 commits February 5, 2026 06:12
Implements infinite scroll pagination for menu list, menu item list, and
linkable items dropdown with page size of 20. Shows loading spinner when
fetching more items.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix pagination not triggering after second page by properly tracking
  state changes in LaunchedEffect keys
- Remove inaccurate menu item count from menu list
- Remove unused fetchAllMenuItems function
- Move Edit Items button to end of menu card, centered vertically
- Fix detekt warnings: swallowed exceptions, unused imports, complexity
- Extract MenuItemListContent and sibling helper functions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ExposedDropdownMenu doesn't support LazyColumn (SubcomposeLayout
intrinsic measurement issue), causing crashes when opening the dropdown.
This replaces it with a ModalBottomSheet which properly supports
pagination with LazyColumn.

Also restores PAGE_SIZE to 20 (was 5 for testing).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This resource was left over after removing the menu item count feature.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@nbradbury nbradbury added the Menus label Feb 5, 2026
@dangermattic
Copy link
Collaborator

dangermattic commented Feb 5, 2026

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

- Extract duplicate type selection label logic to helper function
- Simplify parseErrorMessage by consolidating redundant cases
- Consolidate findPreviousSiblingIndex/findNextSiblingIndex into single function

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Feb 5, 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
Versionpr22560-0fbb501
Build Number1483
Application IDcom.jetpack.android.prealpha
Commit0fbb501
Installation URL6bgriur6pc670
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Feb 5, 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
Versionpr22560-0fbb501
Build Number1483
Application IDorg.wordpress.android.prealpha
Commit0fbb501
Installation URL741jd6kq2e3tg
Note: Google Login is not supported on these builds.

@codecov
Copy link

codecov bot commented Feb 5, 2026

Codecov Report

❌ Patch coverage is 5.45455% with 364 lines in your changes missing coverage. Please review.
✅ Project coverage is 38.18%. Comparing base (908e00d) to head (0fbb501).
⚠️ Report is 2 commits behind head on trunk.

Files with missing lines Patch % Lines
...wordpress/android/ui/navmenus/NavMenusViewModel.kt 8.33% 128 Missing and 4 partials ⚠️
...ndroid/ui/navmenus/screens/MenuItemDetailScreen.kt 0.00% 108 Missing ⚠️
.../android/ui/navmenus/screens/MenuItemListScreen.kt 0.00% 48 Missing ⚠️
...ress/android/ui/navmenus/screens/MenuListScreen.kt 0.00% 46 Missing ⚠️
...ress/android/ui/navmenus/data/NavMenuRestClient.kt 9.09% 30 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk   #22560      +/-   ##
==========================================
- Coverage   38.23%   38.18%   -0.06%     
==========================================
  Files        2237     2237              
  Lines      111111   111318     +207     
  Branches    15544    15579      +35     
==========================================
+ Hits        42486    42505      +19     
- Misses      65087    65272     +185     
- Partials     3538     3541       +3     

☔ 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.

@claude

This comment was marked as resolved.

nbradbury and others added 4 commits February 5, 2026 08:09
Prevents race conditions when multiple pagination requests occur in
rapid succession. Each pagination function now uses a mutex to ensure
atomic read-check-update operations, preventing duplicate items or
incorrect pagination state.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ensure canLoadMore remains true when pagination fails, allowing users
to retry after transient errors (network issues, timeouts, etc.).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Prevents stale data from overwriting state when user rapidly switches
between menu item types.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@claude

This comment was marked as outdated.

nbradbury and others added 4 commits February 5, 2026 08:35
Support all 22 protocols from wp_allowed_protocols(): http, https, ftp,
ftps, mailto, news, irc, irc6, ircs, gopher, nntp, feed, telnet, mms,
rtsp, sms, svn, tel, fax, xmpp, webcal, urn. Also adds support for
anchor links (#section) and protocol-relative URLs (//).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Derive offset from UI state instead of cache variables to avoid race
  conditions between initial load and pagination
- Set canLoadMore=true on initial load errors to allow retry

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pre-compute parent-to-children mapping to reduce child lookup from O(n)
to O(1) per item, improving overall complexity from O(n²) to O(n log n).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use when expression to reduce return statements from 4 to 2.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@nbradbury nbradbury requested a review from adalpari February 5, 2026 14:34
@nbradbury nbradbury marked this pull request as ready for review February 5, 2026 14:34
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 6, 2026

}
val offset = currentState.menus.size

@Suppress("TooGenericExceptionCaught")
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ I think it's a bit more clear to extract the Suppress to the function signature level

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the review! I'll mull this over and make the change in a future PR if needed.

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.

LGTM! Just left a minor comment

@nbradbury nbradbury merged commit d0ce0ad into trunk Feb 6, 2026
32 of 43 checks passed
@nbradbury nbradbury deleted the issue/menus-pagination branch February 6, 2026 18:54
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