fix: do not create extra shadow blocks when mirroring events (#7427)

This commit is contained in:
Maribeth Bottorff
2023-08-23 16:20:40 -07:00
committed by GitHub
parent d6d1074f51
commit b9a7a0c7ad
2 changed files with 57 additions and 0 deletions

View File

@@ -138,6 +138,7 @@ export class BlockCreate extends BlockBase {
'the constructor, or call fromJson',
);
}
if (allShadowBlocks(workspace, this.ids)) return;
if (forward) {
blocks.append(this.json, workspace);
} else {
@@ -154,6 +155,26 @@ export class BlockCreate extends BlockBase {
}
}
}
/**
* Returns true if all blocks in the list are shadow blocks. If so, that means
* the top-level block being created is a shadow block. This only happens when a
* block that was covering up a shadow block is removed. We don't need to create
* an additional block in that case because the original block still has its
* shadow block.
*
* @param workspace Workspace to check for blocks
* @param ids A list of block ids that were created in this event
* @returns True if all block ids in the list are shadow blocks
*/
const allShadowBlocks = function (
workspace: Workspace,
ids: string[],
): boolean {
const shadows = ids
.map((id) => workspace.getBlockById(id))
.filter((block) => block && block.isShadow());
return shadows.length === ids.length;
};
export interface BlockCreateJson extends BlockBaseJson {
xml: string;

View File

@@ -56,6 +56,42 @@ suite('Block Create Event', function () {
chai.assert.equal(event.xml.tagName, 'shadow');
});
test('Does not create extra shadow blocks', function () {
const shadowId = 'shadow_block';
const blockJson = {
'type': 'math_arithmetic',
'id': 'parent_with_shadow',
'fields': {'OP': 'ADD'},
'inputs': {
'A': {
'shadow': {
'type': 'math_number',
'id': shadowId,
'fields': {'NUM': 1},
},
},
},
};
// If there is a shadow block on the workspace and then we get
// a block create event with the same ID as the shadow block,
// this represents a block that had been covering a shadow block
// being removed.
Blockly.serialization.blocks.append(blockJson, this.workspace);
const shadowBlock = this.workspace.getBlockById(shadowId);
const blocksBefore = this.workspace.getAllBlocks();
const event = new Blockly.Events.BlockCreate(shadowBlock);
event.run(true);
const blocksAfter = this.workspace.getAllBlocks();
chai.assert.deepEqual(
blocksAfter,
blocksBefore,
'No new blocks should be created from an event that only creates shadow blocks',
);
});
suite('Serialization', function () {
test('events round-trip through JSON', function () {
const block = this.workspace.newBlock('row_block', 'block_id');