fix: Drag immovable and shadow blocks along with their parent. (#9281)

This commit is contained in:
Aaron Dodson
2025-08-06 14:08:01 -07:00
committed by GitHub
parent f9d0ec9d24
commit 7d1d745416
2 changed files with 55 additions and 16 deletions

View File

@@ -501,22 +501,32 @@ export class Block {
// Detach this block from the parent's tree.
this.previousConnection.disconnect();
}
const nextBlock = this.getNextBlock();
if (opt_healStack && nextBlock && !nextBlock.isShadow()) {
// Disconnect the next statement.
const nextTarget = this.nextConnection?.targetConnection ?? null;
nextTarget?.disconnect();
if (
previousTarget &&
this.workspace.connectionChecker.canConnect(
previousTarget,
nextTarget,
false,
)
) {
// Attach the next statement to the previous statement.
previousTarget.connect(nextTarget!);
}
if (!opt_healStack) return;
// Immovable or shadow next blocks need to move along with the block; keep
// going until we encounter a normal block or run off the end of the stack.
let nextBlock = this.getNextBlock();
while (nextBlock && (nextBlock.isShadow() || !nextBlock.isMovable())) {
nextBlock = nextBlock.getNextBlock();
}
if (!nextBlock) return;
// Disconnect the next statement.
const nextTarget =
nextBlock.previousConnection?.targetBlock()?.nextConnection
?.targetConnection ?? null;
nextTarget?.disconnect();
if (
previousTarget &&
this.workspace.connectionChecker.canConnect(
previousTarget,
nextTarget,
false,
)
) {
// Attach the next statement to the previous statement.
previousTarget.connect(nextTarget!);
}
}

View File

@@ -201,6 +201,35 @@ suite('Blocks', function () {
assertUnpluggedHealFailed(blocks);
});
test('Disconnect top of stack with immovable sibling', function () {
this.blocks.B.setMovable(false);
this.blocks.A.unplug(true);
assert.equal(this.blocks.A.nextConnection.targetBlock(), this.blocks.B);
assert.isNull(this.blocks.B.nextConnection.targetBlock());
assert.isNull(this.blocks.C.previousConnection.targetBlock());
});
test('Heal with immovable sibling mid-stack', function () {
const blockD = this.workspace.newBlock('stack_block', 'd');
this.blocks.C.nextConnection.connect(blockD.previousConnection);
this.blocks.C.setMovable(false);
this.blocks.B.unplug(true);
assert.equal(this.blocks.A.nextConnection.targetBlock(), blockD);
assert.equal(this.blocks.B.nextConnection.targetBlock(), this.blocks.C);
assert.isNull(this.blocks.C.nextConnection.targetBlock());
});
test('Heal with immovable sibling and shadow sibling mid-stack', function () {
const blockD = this.workspace.newBlock('stack_block', 'd');
const blockE = this.workspace.newBlock('stack_block', 'e');
this.blocks.C.nextConnection.connect(blockD.previousConnection);
blockD.nextConnection.connect(blockE.previousConnection);
this.blocks.C.setMovable(false);
blockD.setShadow(true);
this.blocks.B.unplug(true);
assert.equal(this.blocks.A.nextConnection.targetBlock(), blockE);
assert.equal(this.blocks.B.nextConnection.targetBlock(), this.blocks.C);
assert.equal(this.blocks.C.nextConnection.targetBlock(), blockD);
assert.isNull(blockD.nextConnection.targetBlock());
});
test('Child is shadow', function () {
const blocks = this.blocks;
blocks.C.setShadow(true);