Skip to content

Conversation

@alecgeatches
Copy link
Contributor

What?

Adds awareness functions to getSyncProvider().awareness:

// Listen for awareness updates
addListener: (
	eventType: 'update' | 'change',
	listener: AwarenessEventListener
) => void;

// Get awareness states
getStates: () => Map< number, Record< string, any > > | null;

// Set awareness field
setLocalStateField: ( field: string, value: any ) => void;

// Remove self from awareness
removeAwarenessStates: () => void;

These functions are proxied to actual awareness functions, and can be enqueued and called before awareness is available. Usage looks like this:

domReady( function () {
	const syncProvider: SyncProvider = getSyncProvider();
} );

awareness.addListener(
	'change',
	async ( { added, updated, removed }: {
		added: Array< number >;
		updated: Array< number >;
		removed: Array< number >;
	} ) => {
		const states = awareness.getStates();

		// Process updates...
	}
);

Why?

This will allow plugins to use and implement presense and awareness updates with Yjs using getSyncProvider().awareness.

How?

getSyncProvider() is bootstrapped when the editor is ready, which can make it difficult to use awareness functionality from a plugin. The implementation here uses a pending queue to immediately send/process messages when awareness functionality is ready, and the user can call getSyncProvider().awarness functions anytime. Additionally we proxy awareness functions to give the user more restricted access to the Yjs internal model.

@github-actions
Copy link

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 <[email protected]>

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

@alecgeatches
Copy link
Contributor Author

@ingeniumed Please take a look and potentially make a merge when you have the chance. Thank you!

@t-hamano t-hamano added [Type] Enhancement A suggestion for improvement. [Feature] Real-time Collaboration Phase 3 of the Gutenberg roadmap around real-time collaboration labels Jul 12, 2025
/** @typedef {import('./types').UndoManager} UndoManager */
/** @typedef {import('./types').HistoryRecord} HistoryRecord */

const AWARENESS_DOC_TYPE = 'postType/Posts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker rn, but for a future PR: Should this be just postType similar to the undo manager so that it works for pages and other CPTs as well rather than just posts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, good call-out.

awareness: connectRemoteResult?.awareness || null,
destroy: () => {
destroyLocalConnection?.();
connectLocalResult?.destroy?.();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice spot 👍🏾

@ingeniumed ingeniumed merged commit 7c90a38 into WordPress:add/expertimental-collaborative-editing Jul 14, 2025
50 of 69 checks passed
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 [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants