Skip to content

Commit ca4c449

Browse files
authored
add monkey patch workaround for blockly focus issue when deleting block (#11122)
1 parent 3a0b95b commit ca4c449

1 file changed

Lines changed: 53 additions & 0 deletions

File tree

pxtblocks/monkeyPatches/blockSvg.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,57 @@ export function monkeyPatchBlockSvg() {
2020
}
2121
}
2222
}
23+
24+
// This is duplicated exactly from Blockly.BlockSvg.prototype.dispose,
25+
// except the radius of the connection search is increased to make
26+
// it more likely to focus a nearby block instead of the workspace
27+
// when a block is deleted. See https://github.com/RaspberryPiFoundation/blockly/issues/9585
28+
Blockly.BlockSvg.prototype.dispose = function (this: Blockly.BlockSvg, healStack: boolean, animate: boolean) {
29+
this.disposing = true;
30+
31+
Blockly.Tooltip.dispose();
32+
Blockly.ContextMenu.hide();
33+
34+
// If this block (or a descendant) was focused, focus its parent or
35+
// workspace instead.
36+
const focusManager = Blockly.getFocusManager();
37+
if (
38+
this.getSvgRoot().contains(
39+
focusManager.getFocusedNode()?.getFocusableElement() ?? null,
40+
)
41+
) {
42+
let parent: Blockly.BlockSvg | undefined | null = this.getParent();
43+
if (!parent) {
44+
const connection = this.outputConnection ?? this.previousConnection;
45+
if (connection) {
46+
// By default, Blockly searches for nearby connections within a radius of 0
47+
// to only get blocks that are touching. As a result, it usually returns nothing
48+
// and focuses the root of the workspace. Instead, we use the workspace dimensions
49+
// to try and find a block that's on screen
50+
const workspace = this.workspace;
51+
const viewMetrics = workspace?.getMetrics();
52+
const radius = viewMetrics ? Math.max(viewMetrics.viewWidth, viewMetrics.viewHeight) / 2: 0;
53+
54+
const targetConnection = connection.closest(
55+
radius,
56+
new Blockly.utils.Coordinate(0, 0),
57+
).connection;
58+
parent = targetConnection?.getSourceBlock();
59+
}
60+
}
61+
if (parent) {
62+
focusManager.focusNode(parent);
63+
} else {
64+
setTimeout(() => focusManager.focusTree(this.workspace), 0);
65+
}
66+
}
67+
68+
if (animate) {
69+
this.unplug(healStack);
70+
Blockly.blockAnimations.disposeUiEffect(this);
71+
}
72+
73+
Blockly.Block.prototype.dispose.call(this, !!healStack);
74+
Blockly.utils.dom.removeNode(this.getSvgRoot());
75+
}
2376
}

0 commit comments

Comments
 (0)