Skip to content

Commit 5d8bf4c

Browse files
Suggestions: Skip staleness prompt when applying a block-insert-after
The conflict check compares each attribute-set op's `before` against the live block's current attribute. For an inserted block the overlay baseline is `{}`, so every attribute-set op rides on `before: null`. On the accepting client the inserted block already carries the typed content, so the comparison reads as a divergence and the apply flow opens a 'This block has changed' dialog before every Insert apply. Inserted blocks have no pre-existing attributes to overwrite — the attribute-set ops describe the new block's content, not concurrent edits. Short-circuit `hasAttributeConflict` to false when the payload carries a `block-insert-after` structural op, and add a regression test.
1 parent 203de58 commit 5d8bf4c

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

packages/editor/src/components/suggestion-mode/provider.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,16 @@ export function hasAttributeConflict( currentAttributes, operations ) {
265265
if ( ! Array.isArray( operations ) ) {
266266
return false;
267267
}
268+
// Inserted blocks have no pre-existing attributes — the overlay's
269+
// baseline for a `block-insert-after` entry is `{}`, so every
270+
// attribute-set op rides on `before: null`. Comparing that against the
271+
// live (already-typed-into) block's attributes always reads as
272+
// divergence, which falsely fires the staleness prompt on apply. The
273+
// attribute-set ops describe the inserted block's content, not an
274+
// overwrite of pre-existing data, so there is nothing to conflict with.
275+
if ( findStructuralOp( operations )?.type === 'block-insert-after' ) {
276+
return false;
277+
}
268278
for ( const op of operations ) {
269279
if ( op.type !== 'attribute-set' ) {
270280
continue;

packages/editor/src/components/suggestion-mode/test/provider.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,37 @@ describe( 'hasAttributeConflict', () => {
295295
hasAttributeConflict( { content: wrapperOther }, [ CONTENT_OP ] )
296296
).toBe( true );
297297
} );
298+
299+
it( 'returns false for a block-insert-after payload even when attribute-set ops appear divergent', () => {
300+
// The overlay baseline for an inserted block is `{}` — every
301+
// attribute-set op the auto-save loop persists carries
302+
// `before: null` regardless of what the user typed. Comparing
303+
// that against the live (already-typed-into) block on the
304+
// accepting client must not fire the staleness prompt.
305+
const operations = [
306+
{
307+
type: 'block-insert-after',
308+
clientId: 'inserted',
309+
blockName: 'core/paragraph',
310+
anchorClientId: 'anchor',
311+
parentClientId: null,
312+
block: {
313+
name: 'core/paragraph',
314+
attributes: { content: 'Hi' },
315+
innerBlocks: [],
316+
},
317+
},
318+
{
319+
type: 'attribute-set',
320+
attribute: 'content',
321+
before: null,
322+
after: 'Hi',
323+
},
324+
];
325+
expect( hasAttributeConflict( { content: 'Hi' }, operations ) ).toBe(
326+
false
327+
);
328+
} );
298329
} );
299330

300331
describe( 'parseSuggestionPayload', () => {

0 commit comments

Comments
 (0)