Skip to content

CMM-2133: Expandable referrers with children in new Stats#23065

Closed
adalpari wants to merge 32 commits into
trunkfrom
feature/cmm-2133-referrer-rows-open-details
Closed

CMM-2133: Expandable referrers with children in new Stats#23065
adalpari wants to merge 32 commits into
trunkfrom
feature/cmm-2133-referrer-rows-open-details

Conversation

@adalpari

@adalpari adalpari commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Description

Adds expand/collapse support for child referrers in the new Stats "Referrers" card and its detail screen, and makes the detail screen show the full referrer list.

Referrer groups returned by the API can contain a list of child referrers (e.g. the "Search Engines" group nests "Google Search", etc.). Previously these were discarded and every group rendered as a flat row, and the detail screen only showed the same ~10 items as the card.

Changes:

  • Thread a children list (name, url, views) from the datasource → repository → UI state → ViewModel. Groups with children now render an expand/collapse dropdown (following the UTM card pattern).
  • Child rows open their URL in a Chrome Custom Tab (ActivityNavigator.openInCustomTab).
  • Only rows that actually navigate/open something show a chevron: the decorative right-arrow was removed from the shared Most Viewed rows (which affects Posts & Pages, Clicks, Search Terms, Video Plays, File Downloads too), and the right-chevron is kept only on the tappable URL child rows.
  • Referrers are now requested with max=0 (the server treats this as "all", vs. an unset max which defaults to 10), so the detail screen lists every referrer while the card still shows the first 10 — matching how Posts & Pages behaves.
  • The duplicated expand/collapse composables across the card and detail screens were extracted into a shared MostViewedCommonComposables.kt (reusing the existing StatsListRowContainer), and NewStatsActivity now injects ActivityNavigator rather than constructing it in a composable.

Note: This branch is stacked on feature/rs-unified-comments-detail, which is not yet on origin, so this PR targets trunk and will show those unrelated commits until that work merges. Only the 6 commits from f335aa3 onward belong to this change.

Testing instructions

Referrers card — expandable children:

  1. Open the new Stats screen on a site whose referrers include a group with children (e.g. "Search Engines").
  • Verify groups with children show an up/down dropdown arrow (before the views count) and expand/collapse when tapped, revealing indented child rows.
  • Verify groups without children have no chevron and are not tappable.
  • Verify tapping a child row opens its URL in a Chrome Custom Tab.
  1. Tap Show all to open the Referrers detail screen.
  • Verify the detail lists more than 10 referrers (the full set), while the card still shows the first 10.
  • Verify the same expand/collapse and child-tap behavior works, and expanded state survives scrolling.

Regression — shared Most Viewed cards:

  1. Open the Posts & Pages, Clicks, Search Terms, Video Plays and File Downloads cards.
  • Verify the rows look unchanged and no longer show a decorative right-arrow.

nbradbury and others added 30 commits June 30, 2026 08:31
Replace the abandoned unified comment detail stub with a working screen for
the site-comments path: view, moderation (approve/unapprove, spam, trash),
like, edit, and reply. The list auto-refreshes via the local comment cache.

Convert the UNIFIED_COMMENTS_DETAILS gate from a remote/build @feature flag to
a debug-only Experimental Feature, and drop the now-unused config + BuildConfig
field. Adds ViewModel unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- Format the comment date as a relative time span via DateTimeUtilsWrapper
- Open the post in the Reader when the post title is tapped
- Approve an unapproved comment when replying to it (legacy parity)

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- Copy the comment link to the clipboard
- Share the comment link via a chooser
- Permanently delete a trashed/spam comment, with confirmation

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Reuse the shared reader comment box for the reply input, adding:
- @-mention user suggestions (WP.com-accessed sites)
- full-screen reply expand
- per-comment draft autosave, cleared after a successful send

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- Register UnifiedCommentDetailsViewModel in ViewModelModule (fixes a crash
  when opening the screen: "View model not found")
- Use explicit text sizes so the comment text is readable (the Material3
  textAppearance attrs didn't resolve in this activity's theme)
- Handle toolbar up navigation so the back arrow works
- Replace the action buttons with the legacy icon-button footer
  (Approve / Spam / Like / More), moving Edit, Trash, Copy link, Share
  and Delete permanently into the More overflow

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Drop the unused binding field (inline the inflate) and the no-op
component().inject(this) call — the activity injects nothing.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Style the footer's moderate and like buttons per state like the old
comment detail: accent-tinted icon + label at full opacity when on
(approved / liked), colorOnSurface at medium opacity when off. Approved
comments now read "Approved" rather than "Unapprove", and trashed
comments show "Restore" with the undo icon.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add CommentsRsDataSource (load/moderate/trash/delete/reply via the
wordpress-rs /wp/v2/comments endpoint, like postsrs/pagesrs) and rewrite
UnifiedCommentDetailsViewModel to use it. FluxC is kept for liking (rs has
no comment like action) and to resync the still-FluxC comment list cache
after each rs write. Tests updated to mock the rs data source.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Use a generic key (rs_unified_comments) so the flag can also gate a future
wordpress-rs comment list, label it "RS Unified Comment Detail", and base the
description on the New Pages List one (WP.com + application-password sites).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Use INVISIBLE (not GONE) for the scroll view during load so its weighted
space is preserved, and show the Spam button up front instead of only once
the comment has loaded.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Log the swallowed share ActivityNotFoundException, suppress the
intentional generic catch and guard-clause return count (matching the
existing rs code), and drop an unused test import.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Return an RsResult carrying WpError.errorMessage from CommentsRsDataSource
writes and show that server message on moderation/reply failures (falling
back to the generic string). Extract the rs<->app comment status mapping to
testable functions and add CommentsRsStatusMapperTest.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- Use the comment's GMT date for relative time so it's correct on non-UTC
  sites (WpGmtDateTime is an absolute Date; the local date field had no offset)
- Guard onReplyClicked against a second in-flight reply
- Remove the comment from the FluxC cache on permanent delete instead of
  leaving an orphaned "deleted" row (new CommentsStore.removeCommentByRemoteId)
- Drop the fragment's redundant currentState shadow; read uiState.value directly

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…backs

Extract the repeated no-network check into an isOffline() helper, collapse the
onConfirm/onCollapse null guards, and fix an import ordering.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…etwork

The rs comment detail loads over the network, so guard in the activity's
onCreate: when offline, show a toast and finish before the screen appears.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
It was mapped from the rs response but never read (createReply uses the
comment's remote id as the parent).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Some sites reject DELETE ?force=false with "Invalid parameter(s): force".
Route trash through update(status=trash) like spam/approve, and drop the
now-unused CommentsRsDataSource.trash().

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Tint the Trash and Delete permanently more-menu items and the "Trashed"
status label with the error colour, matching the legacy comment detail.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- Ignore moderation taps while the comment is still loading: the footer
  stays visible during load and the default ui state would compute (and
  apply server-side) the wrong target status
- Hide the Like button on self-hosted application-password sites, where
  FluxC's likeComment always fails (legacy canLike parity)
- Don't open the Reader from the post title when the site has no WP.com
  blog id (self-hosted app-password sites), since it can't resolve the post
- Guard onLikeClicked against a second tap while a like is in flight,
  matching the existing reply guard

Co-Authored-By: Claude Fable 5 <[email protected]>
- Don't reset the ui state when refreshing after an edit: moderation/like
  during the reload acted on a default status (wrong toggle direction),
  and a failed refresh blanked the screen and force-closed it
- Fall back to the legacy detail on sites the rs client can't authenticate
  (no WP.com REST and no application password), like the rs pages gating
- Render the comment body with the shared comment HTML renderer (inline
  images, emoticons, whitespace trim) and tappable links, and only
  re-parse when the HTML changes
- Confirm before trashing, since the rs path commits immediately and has
  no undo affordance like the legacy list flow
- Run the offline bail-out only on first launch so rotating/restoring an
  already-loaded screen while offline doesn't kill it
- Key reply drafts and the full-screen dialog tag by the local site id;
  the WP.com blog id is 0 for all self-hosted app-password sites, which
  collided drafts across sites

Co-Authored-By: Claude Fable 5 <[email protected]>
Referrer groups can contain child referrers (e.g. "Search Engines"),
but the new stats Referrers card discarded them and rendered a flat
list. Thread a children list (name, url, views) from the datasource
through the repository, UI state and ViewModel, and render referrer
groups with children as expand/collapse rows in both the card and the
detail screen, following the UTM card pattern. Tapping a child opens
its URL in a Chrome Custom Tab.

CMM-2133

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Remove the decorative right arrow from Most Viewed rows (shared by
posts, referrers, clicks, search terms, video plays and file downloads)
since it did not navigate anywhere. Move the expand/collapse dropdown
arrow before the views count on referrer groups with children, and show
a right arrow only on clickable URL child rows to signal they open a
link.

CMM-2133

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Expanded child rows sat flush against their parent row in the referrers
and UTM cards and detail screens. Add a small top margin so children are
visually separated when a group is expanded.

CMM-2133

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
When a group had more than one child, the child rows were rendered flush
against each other. Space them evenly in the referrers and UTM cards and
detail screens.

CMM-2133

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
adalpari and others added 2 commits July 3, 2026 12:12
The referrers endpoint returns only 10 items when max is unset. Send an
explicit max=0 (which the server treats as unlimited) so it returns the
full referrer list, matching how Posts & Pages behaves: the card still
shows the first CARD_MAX_ITEMS entries while the detail screen shows all
of them.

CMM-2133

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Extract the duplicated chevron, child row and expandable-children block
from MostViewedCard and MostViewedDetailActivity into a shared
MostViewedCommonComposables file, reusing StatsListRowContainer for the
child row bar. Inject ActivityNavigator into NewStatsActivity and thread
the child-click callback down instead of constructing the navigator in a
composable and casting the context to Activity. Compute maxChildViews
only when a group is expanded, and document the referrers max=0
semantics.

CMM-2133

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@dangermattic

Copy link
Copy Markdown
Collaborator
1 Warning
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
1 Message
📖 This PR is still a Draft: some checks will be skipped.

Generated by 🚫 Danger

@adalpari

adalpari commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #23066, which is cleanly based on trunk with only the CMM-2133 commits.

@adalpari adalpari closed this Jul 3, 2026
@adalpari adalpari deleted the feature/cmm-2133-referrer-rows-open-details branch July 3, 2026 10:45
@wpmobilebot

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
Versionpr23065-7be239d
Build Number1498
Application IDcom.jetpack.android.prealpha
Commit7be239d
Installation URL60cqis9oco0lo
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

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
Versionpr23065-7be239d
Build Number1498
Application IDorg.wordpress.android.prealpha
Commit7be239d
Installation URL5vs5f0962j6jg
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants