Skip to content

Redesign Reader post detail header for adaptive layout#22754

Draft
nbradbury wants to merge 48 commits intotrunkfrom
feature/CMM-2002-adaptive-post-details
Draft

Redesign Reader post detail header for adaptive layout#22754
nbradbury wants to merge 48 commits intotrunkfrom
feature/CMM-2002-adaptive-post-details

Conversation

@nbradbury
Copy link
Copy Markdown
Contributor

@nbradbury nbradbury commented Mar 27, 2026

Description

Updated Reader post detail to more closely match iOS, especially the recent redesigns to the Reader post detail header. This PR contains the following changes:

  • Featured image moved into header view — relocated from the collapsing toolbar to ReaderPostDetailHeaderView, below the title. Uses ShapeableImageView with rounded corners and supports tap-to-preview.
  • Redesigned blog section — author name and date shown on separate rows instead of inline with a dot separator.
  • Like/comment counts below content — interaction counts moved from the header to below tags. Standalone like count text removed in favor of the liker faces train, which shows avatars with the count.
  • Tags moved below content — expandable tags view relocated from the header to below the post content.
  • "View original" button — added to the header for opening the post in a browser.
  • "View site" link — "Visit site" renamed to "View site" and now opens the site in Reader.
  • Excerpt display — blog description shown below the featured image when available.
  • Simplified toolbar — removed collapsing toolbar image behavior; toolbar icon colors are now applied once at init instead of on every scroll event.
  • Date format — publication date no longer includes time.

Testing instructions

I recommend viewing this branch alongside the iOS reader and noting any differences between the two (keeping in mind there will be minor rendering differences in the post content).

nbradbury and others added 14 commits March 25, 2026 10:21
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only use editorial.image, featured_image, or featured_media.uri
as featured image sources instead of scanning post content for
suitable images or videos.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorder ConstraintLayout constraints so the visual hierarchy is:
blog header → featured image → title → excerpt → interactions → footer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a Reader post has a portrait featured image, the image is now
scaled to fit the container height and centered horizontally with a
gray background fill, instead of being center-cropped which often
cuts off heads and other important content.

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>
Move featured image from collapsing AppBar to inline in the header view
with adaptive aspect ratio. Restructure blog section so site name,
author, and date each appear on their own line with absolute date+time
format. Add reading time indicator and excerpt display to the header.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract Regex and date format constants in header UI state builder
- Replace verbose null-check patterns with setTextOrHide helper
- Hoist Paint allocation to class property in PortraitAwareCropTransformation
- Remove unnecessary list allocation in applyInteractionSectionTheme

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

Replace ?attr/colorOnSurfaceVariant (Material3-only) with compatible
alternatives since the reading preferences ContextThemeWrapper uses
Theme.MaterialComponents.DayNight which lacks this attribute.

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

- Remove unused postDetailsHeaderViewUiStateBuilder injection from fragment
- Replace per-scroll toolbar coloring with one-time setup in initAppBar
- Inline trivial buildPostDetailsHeaderUiState delegation
- Remove unnecessary default values in ReaderFeaturedImageUiState

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

dangermattic commented Mar 27, 2026

2 Warnings
⚠️ View files have been modified, but no screenshot or video is included in the pull request. Consider adding some for clarity.
⚠️ 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

@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Mar 27, 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
Build TypeDebug
Versionpr22754-95b090d
Build Number1488
Application IDcom.jetpack.android.prealpha
Commit95b090d
Installation URL4luuktiqu6qoo
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

wpmobilebot commented Mar 27, 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
Build TypeDebug
Versionpr22754-95b090d
Build Number1488
Application IDorg.wordpress.android.prealpha
Commit95b090d
Installation URL25mqpp02d8ip8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

nbradbury and others added 5 commits March 27, 2026 12:19
Replace HtmlCompat.fromHtml() with lighter HtmlUtils.fastStripHtml()
for word counting, fix detekt ReturnCount and checkstyle empty-line
violations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Chain blog name and author vertically against the avatar, add
marginStart with goneMarginStart so text aligns flush when there
is no avatar.

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

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>
nbradbury and others added 6 commits March 27, 2026 13:18
Move blog name to top, post title second, avatar with author and
date below title, then featured image, blog description (up to 3
lines), and reading time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Anchor dateline start directly to avatar so it stays positioned
when author name is hidden. Add barrier below blog name and follow
button so the post title clears both.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
findPost() excludes the text column for performance, so
shouldAddFeaturedImage() couldn't detect the image was already
in the post body HTML. Fetch with text column included when
returning from comments to preserve deduplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Flatten ReaderPostDetailsHeaderViewUiState sealed class into
  top-level data classes (only had one subclass)
- Inline trivial wrapper methods in the header UI state builder
- Inline single-line delegation methods in the header view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nbradbury and others added 4 commits March 30, 2026 05:52
…d, rename excerpt to blogDescription

- Cache SimpleDateFormat as a class property instead of allocating per call
- Wrap ReaderBlogTableWrapper.getBlogInfo() in withContext(Dispatchers.IO)
  and propagate suspend through the call chain
- Rename excerpt/text_excerpt to blogDescription/text_blog_description
  since the field shows blog description, not post excerpt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This drawable was only referenced by the collapsing toolbar featured
image FrameLayout which was removed in the header redesign.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove redundant likeCount/commentCount local variables
- Simplify featured image null handling with if/else
- Make ReaderFeaturedImageUiState.url and onFeaturedImageClicked
  non-null since the state object is only created with valid values
- Rewrite buildReadingTime with early returns for readability

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

codecov bot commented Mar 30, 2026

Codecov Report

❌ Patch coverage is 24.13793% with 88 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.40%. Comparing base (41691ee) to head (af962f1).

Files with missing lines Patch % Lines
...views/ReaderPostDetailsHeaderViewUiStateBuilder.kt 2.50% 78 Missing ⚠️
.../ui/reader/viewmodels/ReaderPostDetailViewModel.kt 81.25% 2 Missing and 1 partial ⚠️
...er/views/uistates/ReaderPostDetailsHeaderAction.kt 0.00% 3 Missing ⚠️
...ews/uistates/ReaderPostDetailsHeaderViewUiState.kt 80.00% 3 Missing ⚠️
...roid/util/image/PortraitAwareCropTransformation.kt 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk   #22754      +/-   ##
==========================================
- Coverage   37.42%   37.40%   -0.03%     
==========================================
  Files        2321     2321              
  Lines      123663   123709      +46     
  Branches    16768    16785      +17     
==========================================
- Hits        46278    46268      -10     
- Misses      73673    73730      +57     
+ Partials     3712     3711       -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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

nbradbury and others added 16 commits March 30, 2026 08:43
- Move DB query off main thread in onUserNavigateFromComments
- Replace SimpleDateFormat with thread-safe DateTimeFormatter
- Reapply toolbar icon colors after menu visibility changes
- Hide blog name in blog section layout XML instead of at runtime
- Move featured image click lambda out of data class for proper equality
- Guard reading time word count against empty split results
- Revert formatting-only test changes to reduce diff noise

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a flat text button with a circled arrow icon on the right side of
the reading time row. Tapping it opens the post's original URL in the
browser. The button is only shown when the post has a URL.

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>
The comment count is already shown above the comment list, so it's
redundant in the likes area. Simplified to a single like count TextView.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Preserve the featured image state across UI re-renders so it doesn't
disappear when fresh post text causes the URL deduplication heuristic
to produce a different result.

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>
Display up to 5 small circular liker avatars before the like count
text below post content. Ungates the liker data pipeline so avatar
URLs are fetched regardless of the likes enhancements feature flag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
onRefreshLikersData() was not called from updatePostDetailsUi(),
so the liker data pipeline was never triggered during the initial
post load. This meant the likesUiState observer never received
data and the avatar ImageViews stayed hidden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the 5 small inline avatar ImageViews from the like count
row and revert the layout to the original MaterialTextView. The
existing liker faces train (32dp RecyclerView avatars) is now
always shown since the data pipeline was ungated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The like count was shown twice: once as a standalone TextView below
the tags and again as a trailing label in the liker faces train.
Remove the standalone header_like_count TextView and let the faces
train be the sole display of like count and liker avatars.

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>
@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Mar 30, 2026

🤖 Build Failure Analysis

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

nbradbury and others added 3 commits March 30, 2026 16:03
Use medium-emphasis color for pill stroke and text instead of black.
Adjust layout constraints so the pill drives row height and the blog
name centers vertically against it, preventing top clipping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Derive tag visibility from tagItems.isNotEmpty() and view-original
visibility from onViewOriginalClicked != null. Also remove unused
lambda binding in onFeaturedImageClicked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract buildInteractionSection and buildViewOriginalClicked helpers
to shorten mapPostToUiState. Remove unused OpenPost imports and
delete unused ic_arrow_circle_right_16dp drawable.

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

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.

3 participants