diff --git a/plugins/block-dynamic-connection/README.md b/plugins/block-dynamic-connection/README.md index 50a7d69d47..c045f88365 100644 --- a/plugins/block-dynamic-connection/README.md +++ b/plugins/block-dynamic-connection/README.md @@ -15,7 +15,7 @@ npm install @blockly/block-dynamic-connection --save import * as Blockly from 'blockly'; import * as BlockDynamicConnection from '@blockly/block-dynamic-connection'; -const ws = Blockly.inject({ +const myWorkspace = Blockly.inject({ // options... plugins: { connectionPreviewer: @@ -26,6 +26,9 @@ const ws = Blockly.inject({ ), }, }; + +// Add the change listener so connections will be finalized on deletion. +workspace.addChangeListener(BlockDynamicConnection.finalizeConnections); ``` ## API diff --git a/plugins/block-dynamic-connection/src/connection_previewer.ts b/plugins/block-dynamic-connection/src/connection_previewer.ts index ec7e0612fa..a0f0fbfe80 100644 --- a/plugins/block-dynamic-connection/src/connection_previewer.ts +++ b/plugins/block-dynamic-connection/src/connection_previewer.ts @@ -15,7 +15,11 @@ interface DynamicBlock extends Blockly.BlockSvg { finalizeConnections(): void; } -function blockIsDynamic(block: Blockly.BlockSvg): block is DynamicBlock { +/** + * A type guard that checks if the given block fulfills the DynamicBlock + * interface. + */ +export function blockIsDynamic(block: Blockly.BlockSvg): block is DynamicBlock { return ( (block as DynamicBlock)['onPendingConnection'] !== undefined && (block as DynamicBlock)['finalizeConnections'] !== undefined diff --git a/plugins/block-dynamic-connection/src/index.ts b/plugins/block-dynamic-connection/src/index.ts index bc581d2b4e..a5dc030ff1 100644 --- a/plugins/block-dynamic-connection/src/index.ts +++ b/plugins/block-dynamic-connection/src/index.ts @@ -13,12 +13,28 @@ import * as Blockly from 'blockly/core'; import './dynamic_if'; import './dynamic_text_join'; import './dynamic_list_create'; -import {decoratePreviewer} from './connection_previewer'; +import {decoratePreviewer, blockIsDynamic} from './connection_previewer'; -export {decoratePreviewer}; +export {decoratePreviewer, blockIsDynamic}; export const overrideOldBlockDefinitions = function (): void { Blockly.Blocks['lists_create_with'] = Blockly.Blocks['dynamic_list_create']; Blockly.Blocks['text_join'] = Blockly.Blocks['dynamic_text_join']; Blockly.Blocks['controls_if'] = Blockly.Blocks['dynamic_if']; }; + +/** + * Finalizes connections when certain events (such as block deletion) are + * detected. + */ +export function finalizeConnections(e: Blockly.Events.Abstract) { + if (e.type === Blockly.Events.BLOCK_DELETE) { + const ws = Blockly.Workspace.getById(e.workspaceId ?? ''); + if (!ws) return; + for (const block of ws.getAllBlocks() as Blockly.BlockSvg[]) { + if (blockIsDynamic(block)) { + block.finalizeConnections(); + } + } + } +} diff --git a/plugins/block-dynamic-connection/test/index.ts b/plugins/block-dynamic-connection/test/index.ts index b057355055..3b12c355e3 100644 --- a/plugins/block-dynamic-connection/test/index.ts +++ b/plugins/block-dynamic-connection/test/index.ts @@ -23,7 +23,9 @@ function createWorkspace( blocklyDiv: HTMLElement, options: Blockly.BlocklyOptions, ): Blockly.WorkspaceSvg { - return Blockly.inject(blocklyDiv, options); + const ws = Blockly.inject(blocklyDiv, options); + ws.addChangeListener(BlockDynamicConnection.finalizeConnections); + return ws; } document.addEventListener('DOMContentLoaded', function () {