diff --git a/core/block_svg.ts b/core/block_svg.ts index e3a60315ee2..d8638f98ff0 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -278,7 +278,7 @@ export class BlockSvg this.addSelect(); } - /** Unselects this block. Unhighlights the blockv visually. */ + /** Unselects this block. Unhighlights the block visually. */ unselect() { if (this.isShadow()) { this.getParent()?.unselect(); @@ -798,6 +798,25 @@ export class BlockSvg blockAnimations.disposeUiEffect(this); } + // Selecting a shadow block highlights an ancestor block, but that highlight + // should be removed if the shadow block will be deleted. So, before + // deleting blocks and severing the connections between them, check whether + // doing so would delete a selected block and make sure that any associated + // parent is updated. + const selection = common.getSelected(); + if (selection instanceof Block) { + let selectionAncestor: Block | null = selection; + while (selectionAncestor !== null) { + if (selectionAncestor === this) { + // The block to be deleted contains the selected block, so remove any + // selection highlight associated with the selected block before + // deleting them. + selection.unselect(); + } + selectionAncestor = selectionAncestor.getParent(); + } + } + super.dispose(!!healStack); dom.removeNode(this.svgGroup_); } diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index 1b685a445b5..29afbd37ff5 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import * as common from '../../build/src/core/common.js'; import {ConnectionType} from '../../build/src/core/connection_type.js'; import * as eventUtils from '../../build/src/core/events/utils.js'; import {EndRowInput} from '../../build/src/core/inputs/end_row_input.js'; @@ -443,6 +444,39 @@ suite('Blocks', function () { }); }); }); + + suite('Disposing selected shadow block', function () { + setup(function () { + this.workspace = Blockly.inject('blocklyDiv'); + this.parentBlock = this.workspace.newBlock('row_block'); + this.parentBlock.initSvg(); + this.parentBlock.render(); + this.parentBlock.inputList[0].connection.setShadowState({ + 'type': 'row_block', + 'id': 'shadow_child', + }); + this.shadowChild = + this.parentBlock.inputList[0].connection.targetConnection.getSourceBlock(); + }); + + teardown(function () { + workspaceTeardown.call(this, this.workspace); + }); + + test('Disposing selected shadow unhighlights parent', function () { + const parentBlock = this.parentBlock; + common.setSelected(this.shadowChild); + assert.isTrue( + parentBlock.pathObject.svgRoot.classList.contains('blocklySelected'), + 'Expected parent to be highlighted after selecting shadow child', + ); + this.shadowChild.dispose(); + assert.isFalse( + parentBlock.pathObject.svgRoot.classList.contains('blocklySelected'), + 'Expected parent to be unhighlighted after deleting shadow child', + ); + }); + }); }); suite('Remove Input', function () {