Skip to content

Newsletter: fix the editor warning about unsaved changes after changing post settings - #50998

Open
arcangelini wants to merge 7 commits into
trunkfrom
fix/nl-797-phantom-meta-dirt
Open

Newsletter: fix the editor warning about unsaved changes after changing post settings#50998
arcangelini wants to merge 7 commits into
trunkfrom
fix/nl-797-phantom-meta-dirt

Conversation

@arcangelini

@arcangelini arcangelini commented Aug 3, 2026

Copy link
Copy Markdown
Member

Fixes NL-797

Alternative to #50924. Same issue, fixed one layer down so it covers both panels NL-797 reports.

Proposed changes

  • Any post meta edit leaves the post permanently unsaved on a site with real-time collaboration. The header sticks on "Save draft", pressing Save doesn't clear it, and leaving the editor warns about losing changes. Only a reload helps.
  • This affects the Newsletter toggle and the Access panelNL-797 reports both. It is not specific to either; it reproduces with a plain core meta key and no Jetpack code involved.
  • Adds useClearPhantomMetaDirt. Once a save comes back, it copies the collaboration snapshot the server returned over the stale one the editor is still holding, and the post goes back to "Saved". It touches nothing else, and only runs when a save request actually went out and succeeded.
  • Drops the saveEditedEntityRecord call from the Newsletter toggle so the setting rides the normal editor save. That call also silently converted a brand-new post into a draft, because core forces status: 'draft' on auto-drafts during save.
  • Fixes the toggle's disabled prop, which was set on ToggleGroupControl where it does nothing instead of on its options.
  • This one changes saved data: picking an access level now writes 0 to the post's newsletter tier instead of deleting the tier field. Deleting it only ever worked inside the browser — the field was left out of the save entirely, so the old tier stayed on the post. A post switched to "Anyone subscribed" could quietly still be carrying a paid tier. Writing 0 clears it for real. Nothing looks different in the editor: 0 and "no tier" are already treated the same by everything that reads it.

Root cause

Collaboration serializes a fresh _crdt_document into the save payload after the meta edit was staged (prePersistPostType). core-data compares the whole meta object at once, so the staged copy matches neither the response record nor the sent edits, and the edits reducer keeps it. Each further save mints another snapshot, so it never reconciles.

The fix stays deliberately narrow. The hook only ever puts back _crdt_document, a field nothing in the editor can edit, so restoring the server's copy cannot throw away something a writer typed. Every other difference is left alone: the save payload is captured before the request goes out and is never visible afterwards, so a value the server changed looks exactly like an edit that was never sent. The one case that used to need special handling here — useSetAccess deleting the tier field — is fixed at the source instead.

This belongs upstream in Gutenberg — the comparison at core-data/src/reducer.js can never match once prePersist rewrites meta. The hook is a no-op when collaboration is off and a no-op again once that lands.

Testing instructions

Needs real-time collaboration, which is on by default on WordPress.com. Self-hosted: install Gutenberg and enable Settings → Writing → Collaboration.

Reproduce first, on trunk:

  1. New post, add a title and a paragraph, save the draft, wait for "Saved".
  2. Open the Jetpack Newsletter sidebar and click Post only.
  3. The header flips to "Save draft". Press Save draft — it stays on "Save draft".
  4. Navigate away. The browser warns about unsaved changes.
  5. Repeat steps 1–4 using the Access panel instead (set it to "Anyone subscribed"). Same result.

Then on this branch, both flows should return to "Saved" after pressing Save, and navigating away should be silent.

Also confirm nothing unrelated is swallowed:

  1. On a saved draft, type a new paragraph but don't save.
  2. Change the Newsletter setting and press Save.
  3. Reload. Your paragraph and the setting should both be there.

And that a new post still behaves:

  1. Start a new post, type a title and some text, don't save.
  2. Click Post only, then save the draft.
  3. The setting sticks and the post saves normally.

And the tier change, which needs at least two paid newsletter tiers:

  1. Set a post to Paid subscribers, pick a tier, and save.
  2. Switch access to Anyone subscribed, save, then reload.
  3. Switch back to Paid subscribers. No tier should be pre-selected.

Does this pull request change what data or activity we track or use?

No.

@arcangelini arcangelini added the [Status] Needs Review This PR is ready for review. label Aug 3, 2026
@arcangelini arcangelini self-assigned this Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the fix/nl-797-phantom-meta-dirt branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack fix/nl-797-phantom-meta-dirt

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions github-actions Bot added [Block] Subscriptions [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Tests] Includes Tests labels Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@jp-launch-control

jp-launch-control Bot commented Aug 3, 2026

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 2 files.

File Coverage Δ% Δ Uncovered
projects/plugins/jetpack/extensions/blocks/subscriptions/panel.jsx 45/58 (77.59%) 0.80% 0 💚
projects/plugins/jetpack/extensions/shared/memberships/settings.jsx 34/85 (40.00%) 8.67% -6 💚

1 file is newly checked for coverage.

File Coverage
projects/plugins/jetpack/extensions/shared/use-clear-phantom-meta-dirt.js 14/15 (93.33%) 💚

Full summary · PHP report · JS report

The editor's save cycle also completes when preSavePost rejects and no request
runs, and the outgoing payload is snapshotted before the request starts, so
neither the success check nor the sent-meta snapshot could be trusted to
decide whether a staged meta value was really saved. Both paths could revert
a pending edit.
The staged copy losing a key was the only reason the hook restored missing
keys, and that restore cancelled a deletion made while a save was in flight.
Writing 0 clears the tier for real -- omitting the key from the REST payload
never did -- and keeps the staged key set complete, so the hook can leave
every non-CRDT difference alone.
Nothing but a save response ever moves `_crdt_document`: peers never sync it, and
only a non-autosave save runs the prePersist that mints a new one. Watching that
value replaces the save-transition tracking, the autosave and save-error guards,
and the ref, and it can no longer write an undefined snapshot back.

Also moves the hook out of memberships/, since nothing in it is specific to
newsletters, and trims the tests to the three branches that matter.
Disabling the options renders them with a native `disabled` and no tabindex, so
the whole group drops out of the tab order. Fall back to the current value as
text, the way the access panel already does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Block] Subscriptions [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Status] Needs Review This PR is ready for review. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant