Skip to content

RTC: Inject content function from remote changes to fix save button state#76848

Merged
ingeniumed merged 2 commits into
fix/save-button-visibilityfrom
fix/defered-content-updates
Mar 26, 2026
Merged

RTC: Inject content function from remote changes to fix save button state#76848
ingeniumed merged 2 commits into
fix/save-button-visibilityfrom
fix/defered-content-updates

Conversation

@alecgeatches
Copy link
Copy Markdown
Contributor

@alecgeatches alecgeatches commented Mar 26, 2026

What?

Fixes the save button not consistently appearing for RTC collaborators when another user edits blocks. Replaces the content serialization approach in #76796 with a lazy content function injection on the receiving side.

Why?

When blocks change in the editor, Gutenberg passes content as a function rather than a string in useEntityBlockEditor(). This is an optimization that defers the block serialization until it's actually needed on save. In RTC, this means the content value in the CRDT doc is often stale because these lazy functions aren't serialized and synced. Since blocks is a transient edit, block changes alone don't trigger the save button for collaborators.

The original fix (PR #76796) solved this by eagerly evaluating the content function and syncing the result via setTimeout(0). However, this has some performance costs that we'd like to avoid if possible.

How?

Instead of eagerly recomputing content on the sending side, the fix works on the receiving side. When getPostChangesFromCRDTDoc() detects that blocks have changed from a remote peer but content hasn't, it injects a lazy content function into the returned changes:

content: ({ blocks }) => __unstableSerializeAndClean(blocks)

This uses the exact same deferred serialization pattern that Gutenberg uses for local content changes. The function-valued content edit makes the entity dirty (so the save button appears), but the serialization itself is deferred until save or code editor view. This defers serialization cost for content as the editor currently does.

Testing Instructions

  1. Enable RTC via Settings -> Writing -> "Enable real-time collaboration" checkbox.
  2. Open the same post in two tabs.
  3. Type in one window and verify the save button appears in both.
  4. Undo all changes in the first window and verify the save button disappears in the second.
  5. Save from the second window and verify content is correct.
  6. Verify undo/redo works correctly in both windows (no extra undo levels).

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Used for: Understanding the lazy save pattern and implementing changes

@alecgeatches alecgeatches self-assigned this Mar 26, 2026
@alecgeatches alecgeatches requested a review from nerrad as a code owner March 26, 2026 18:22
@alecgeatches alecgeatches added the [Feature] Real-time Collaboration Phase 3 of the Gutenberg roadmap around real-time collaboration label Mar 26, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 26, 2026

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Core data, [Feature] Real-time Collaboration.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions
Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Feature] Real-time Collaboration.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 26, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: alecgeatches <alecgeatches@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions Bot added [Package] Date /packages/date [Package] Components /packages/components [Package] Editor /packages/editor [Package] Block library /packages/block-library [Package] Block editor /packages/block-editor [Package] Edit Site /packages/edit-site [Package] Commands /packages/commands [Package] DataViews /packages/dataviews [Package] UI /packages/ui labels Mar 26, 2026
@alecgeatches alecgeatches force-pushed the fix/defered-content-updates branch from 5661d30 to d0ec2a8 Compare March 26, 2026 18:23
@github-actions github-actions Bot removed the [Package] Date /packages/date label Mar 26, 2026
@ingeniumed ingeniumed merged commit 7a64545 into fix/save-button-visibility Mar 26, 2026
35 of 39 checks passed
@ingeniumed ingeniumed deleted the fix/defered-content-updates branch March 26, 2026 20:07
@alecgeatches alecgeatches added Backport to WP 7.0 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta and removed Backport to WP 7.0 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta labels Apr 27, 2026
@t-hamano t-hamano added the [Type] Bug An existing feature does not function as intended label Apr 28, 2026
@t-hamano
Copy link
Copy Markdown
Contributor

This PR does not target trunk, so the Backport to WP 7.0 Beta/RC label appears to be unnecessary.

@ellatrix ellatrix removed the Backport to WP 7.0 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label May 4, 2026
alecgeatches pushed a commit that referenced this pull request May 19, 2026
* Correctly sync the content changes, even if its a function

* Ensure the function is checked and add tests

* Fix the type issue in the test

* Switch to a timeout value and add the necessary tests

* Add a new comment explaining this

* RTC: Inject content function from remote changes to fix save button state (#76848)

* Return deferrer operations from applyPostChangesToCRDTDoc() to explicitly execute on a non-undo transaction

* Don't compute content changes, instead locally inject a content function when blocks change to match dirty state

* Fix WPBlock type

---------

Co-authored-by: ingeniumed <ingeniumed@git.wordpress.org>
Co-authored-by: alecgeatches <alecgeatches@git.wordpress.org>
Co-authored-by: peterwilsoncc <peterwilsoncc@git.wordpress.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Real-time Collaboration Phase 3 of the Gutenberg roadmap around real-time collaboration [Package] Core data /packages/core-data [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants