Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions packages/core-data/src/utils/crdt-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface Block {
innerBlocks: Block[];
originalContent?: string; // unserializable
validationIssues?: string[]; // unserializable
name: string;
}

// The Y.Map type is not easy to work with. The generic type it accepts represents
Expand Down Expand Up @@ -48,12 +49,13 @@ function makeBlocksSerializable(
): Block[] {
return blocks.map( ( block: Block | YBlock ) => {
const blockAsJson = block instanceof Y.Map ? block.toJSON() : block;
const { innerBlocks, attributes, ...rest } = blockAsJson;
const { name, innerBlocks, attributes, ...rest } = blockAsJson;
delete rest.validationIssues;
delete rest.originalContent;
// delete rest.isValid
return {
...rest,
name,
attributes: makeBlockAttributesSerializable( attributes ),
innerBlocks: makeBlocksSerializable( innerBlocks ),
};
Expand All @@ -67,7 +69,7 @@ function makeBlocksSerializable(
function areBlocksEqual( gblock: Block, yblock: YBlock ): boolean {
const yblockAsJson = yblock.toJSON();

// we must not sync clientId, as this can't be generated consistenctly and
// we must not sync clientId, as this can't be generated consistently and
// hence will lead to merge conflicts.
const overwrites = {
innerBlocks: null,
Expand Down Expand Up @@ -100,7 +102,12 @@ export function mergeBlocks(
makeBlocksSerializable( newValue )
);
}
const blocks = serializableBlocksCache.get( newValue ) ?? [];
const unfilteredBlocks = serializableBlocksCache.get( newValue ) ?? [];

// Ensure we skip blocks that we don't want to sync at the moment
const blocks = unfilteredBlocks.filter( ( block ) =>
shouldBlockBeSynced( block )
);

// This is a rudimentary diff implementation similar to the y-prosemirror diffing
// approach.
Expand Down Expand Up @@ -187,3 +194,29 @@ export function mergeBlocks(
knownClientIds.add( clientId );
}
}

/**
* Determine if a block should be synced.
*
* Ex: A gallery block should not be synced until the images have been
* uploaded to WordPress, and their url is available. Before that,
* it's not possible to access the blobs on a client as those are
* local.
*
* @param block The block to check.
* @return True if the block should be synced, false otherwise.
*/
function shouldBlockBeSynced( block: Block ): boolean {
// Verify that the gallery block is ready to be synced.
// This means that, all images have had their blobs converted to full URLs.
// Checking for only the blobs ensures that blocks that have just been inserted work as well.
if ( 'core/gallery' === block.name ) {
Copy link
Author

@ingeniumed ingeniumed Aug 25, 2025

Choose a reason for hiding this comment

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

I switched this from a switch case into an if statement just to keep it clean

return ! block.innerBlocks.some(
( innerBlock ) =>
innerBlock.attributes && innerBlock.attributes.blob
);
}

// Allow all other blocks to be synced.
return true;
}
Loading