Skip to content

CMM-2376: Add a Featured image option to the pre-publish sheet - #23284

Open
adalpari wants to merge 16 commits into
trunkfrom
cmm-2376-featured-image-pre-publish-sheet
Open

CMM-2376: Add a Featured image option to the pre-publish sheet#23284
adalpari wants to merge 16 commits into
trunkfrom
cmm-2376-featured-image-pre-publish-sheet

Conversation

@adalpari

@adalpari adalpari commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

TL;DR

This PR is adding a new section to the "publish post" bottom sheet. It now allows to add a featured image before creating a post. This has been done to be in parity with iOS.

Screenshot_20260902-180650

Description

On iOS the pre-publish sheet includes a Featured image option, but on Android the classic pre-publish bottom sheet only exposed Publish date, Tags, Categories, and Social — there was no featured-image entry point in the publish flow. Featured image was already supported elsewhere (legacy post settings, the postsrs Compose settings, and the Gutenberg editor), so this closes the gap in the classic publish flow to reach parity with iOS.

This adds a Featured image row to the pre-publish home sheet (posts only, mirroring the neighboring Categories/Tags rows) that opens a sub-screen to set, replace, or remove the post's featured image, with an image preview plus upload progress/retry states.

No backend/model changes were needed — the implementation reuses the existing FeaturedImageHelper, UpdateFeaturedImageUseCase, MediaPickerLauncher, and EditPostRepository.featuredImageId.

Notable changes:

  • New PrepublishingFeaturedImageFragment + PrepublishingFeaturedImageViewModel sub-screen, following the existing Categories pattern.
  • New "Featured image" home row with a Set/Not set summary.
  • EditPostActivity.setFeaturedImageId now writes the id directly when the post settings fragment isn't present, so setting an image from the media library/stock — and upload completion — works while only the pre-publish sheet is open. The sheet reflects changes by observing EditPostRepository.postChanged and featured-image upload events.
  • Unit tests for the new ViewModel.

Testing instructions

Set a featured image while publishing:

  • Create a post and check you can add/remove a featured image
  • Edit a post and check you can add/remove a featured image

adalpari and others added 7 commits September 2, 2026 13:24
The publish flow had no featured-image entry point, unlike iOS. Add a
"Featured image" row that opens a set/replace/remove sub-screen, reusing
the existing featured-image helpers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Observe postChanged raw instead of via observeEvent, since it is a
single-consumption Event shared with other observers that would swallow
the refresh. Also render only one image view per state so an empty local
view can't cover the loaded remote image.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ixes

Route featured-image removal through a new EditorDataProvider hook so the
editor's cached featured image is cleared (set already synced via the
picker result path). Add featured-image row coverage to the home
ViewModel test and resolve detekt findings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address code-review findings on the featured-image pre-publish option:

- Gate the row to hosts that can fully edit a featured image via a new
  EditorDataProvider.supportsFeaturedImageEditing(); the posts-list
  quick-publish flow has no editor, so it no longer offers a Set button
  that can't complete.
- Fix GutenbergKitActivity.setFeaturedImageId to write the id and sync
  the editor when the settings screen isn't shown (sheet is open).
- Cancel any pending upload when replacing an image, matching the
  legacy choose path.
- Base the home row's Set/Not set label on the featured image state so
  an in-progress upload no longer reads as "Not set".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
setupHomeUiState runs on the main thread, so use a lightweight
FeaturedImageHelper.hasFeaturedImageOrPendingUpload check instead of
createCurrentFeaturedImageState, which does a media-store lookup and
Photon URL work just to produce a boolean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the featured-image sub-screen with an inline "Featured image"
card on the pre-publish home sheet, matching iOS: a placeholder that
opens the picker, and once set, tapping it offers Replace/Remove (and
Retry on a failed upload). The card updates live via a merged UI state
refreshed off the main thread on post/upload changes.

Also pin the publish/submit button as a footer so it stays visible while
the sheet scrolls, and compare the card by its rendered content in the
diff callback so repeated refreshes don't flicker the image.

Removes the now-unused PrepublishingFeaturedImageFragment/ViewModel,
its screen navigation, DI wiring and strings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dangermattic

dangermattic commented Sep 2, 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 Sep 2, 2026

Copy link
Copy Markdown
Contributor

🤖 Build Failure Analysis

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

adalpari and others added 3 commits September 3, 2026 09:13
The previous commit only captured the file deletions and the new card
layout; the code that renders and drives the card (adapter, view holder,
item state, view model, fragment, diff callback, layout and the pinned
publish button) was left unstaged. Commit it so the branch builds.

Also guard the featured-image view holder against a Hidden item instead
of requiring Visible (per review feedback).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The publish/submit button is now a pinned footer, so its RecyclerView
view type, view holder and layout are unreachable. Remove them; the
ButtonUiState branch in getItemViewType now errors since it should never
appear as a list item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@wpmobilebot

wpmobilebot commented Sep 3, 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
Versionpr23284-9cd5559
Build Number1498
Application IDorg.wordpress.android.prealpha
Commit9cd5559
Installation URL5t66kbu944eu0
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot

wpmobilebot commented Sep 3, 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
Versionpr23284-9cd5559
Build Number1498
Application IDcom.jetpack.android.prealpha
Commit9cd5559
Installation URL22r86vpqstago
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.66667% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.92%. Comparing base (7eb0796) to head (9cd5559).

Files with missing lines Patch % Lines
...s/prepublishing/home/PrepublishingHomeViewModel.kt 55.76% 19 Missing and 4 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##            trunk   #23284   +/-   ##
=======================================
  Coverage   37.91%   37.92%           
=======================================
  Files        2352     2352           
  Lines      128795   128848   +53     
  Branches    17898    17909   +11     
=======================================
+ Hits        48836    48867   +31     
- Misses      75964    75983   +19     
- Partials     3995     3998    +3     

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

Make refreshFeaturedImage single-flight: cancel the previous launch and
bail via ensureActive() before posting, so a slower in-flight read can't
overwrite the latest state and the redundant reads on sheet open collapse.

Fall back to the placeholder when a remote/local image state has no URI to
load, instead of showing a blank ImageView.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@adalpari
adalpari marked this pull request as ready for review September 3, 2026 07:47
@adalpari
adalpari requested a review from nbradbury September 3, 2026 07:58
@adalpari

adalpari commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

@nbradbury I've opened a new PR for this change and made quite a few changes in addition to your feedback in the previous one.

@nbradbury

Copy link
Copy Markdown
Contributor

@adalpari I think this is much better than the previous PR, nice work! I did notice that on the sheet the label for "Featured Image" is in all caps and uses a different font style than Tags, Categories, and Publish Date. Should these all match?

space

Also, I asked Claude for a review which you might want to look over.

review-pr-23284-featured-image-2026-09-03.pdf

adalpari and others added 3 commits September 3, 2026 14:17
Use the same subtitle text appearance, title case (not all caps),
default text color and top spacing as the Publish Date/Tags/Categories
rows instead of an iOS-style uppercase section header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GutenbergKitActivity.setFeaturedImageId took the settings-fragment branch
(which writes the id but doesn't touch the editor) and its editor-push
else was unreachable, so an image set from the pre-publish sheet never
reached the editor. Restructure so the id is written (settings fragment
if shown, else the use case) and the editor is always pushed with the
mediaId.

Also collapse the equivalent dead else in EditPostActivity into a nested
fallback and fix its misleading comment; its unconditional
sendToJSFeaturedImageId already syncs the editor there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
syncFeaturedImageIdToEditor() only stored the id on the fragment, leaving
the legacy Gutenberg editor's featured-image block showing a stale image
after a set/remove from the pre-publish sheet. Push it to the JS editor
via sendToJSFeaturedImageId(), matching the picker path.

GutenbergKit's GutenbergView has no app->webview featured-image setter, so
the equivalent call there only records the id; correct the misleading
comments to document that limitation instead of claiming a push.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@adalpari

adalpari commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

I did notice that on the sheet the label for "Featured Image" is in all caps and uses a different font style than Tags, Categories, and Publish Date

Good call! Changed!
Also made some changes after your feedback.

adalpari and others added 2 commits September 3, 2026 17:11
…resh to the post

- Build the featured-image card state in setupHomeUiState so it is present in the first
  frame instead of popping in (and reflowing the sheet) after the background refresh.
- Drop the redundant refreshFeaturedImage() in start(); the synchronous seed covers it,
  leaving onResume / postChanged / onMediaUploaded as the update paths.
- Share the state builder between the seed and the async refresh.
- Only refresh on OnMediaUploaded when the media belongs to this post, matching the
  EditPostActivity guard.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- onMediaUploaded: peel the null / initialization checks into early returns so the
  remaining guard is a two-part condition.
- createFeaturedImageUiState: fold the guards into a single conditional expression.

No behavior change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@nbradbury nbradbury 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.

Looks great! :shipit:

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