Skip to content

Commit 7d1d745

Browse files
authored
fix: Drag immovable and shadow blocks along with their parent. (#9281)
1 parent f9d0ec9 commit 7d1d745

2 files changed

Lines changed: 55 additions & 16 deletions

File tree

core/block.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -501,22 +501,32 @@ export class Block {
501501
// Detach this block from the parent's tree.
502502
this.previousConnection.disconnect();
503503
}
504-
const nextBlock = this.getNextBlock();
505-
if (opt_healStack && nextBlock && !nextBlock.isShadow()) {
506-
// Disconnect the next statement.
507-
const nextTarget = this.nextConnection?.targetConnection ?? null;
508-
nextTarget?.disconnect();
509-
if (
510-
previousTarget &&
511-
this.workspace.connectionChecker.canConnect(
512-
previousTarget,
513-
nextTarget,
514-
false,
515-
)
516-
) {
517-
// Attach the next statement to the previous statement.
518-
previousTarget.connect(nextTarget!);
519-
}
504+
505+
if (!opt_healStack) return;
506+
507+
// Immovable or shadow next blocks need to move along with the block; keep
508+
// going until we encounter a normal block or run off the end of the stack.
509+
let nextBlock = this.getNextBlock();
510+
while (nextBlock && (nextBlock.isShadow() || !nextBlock.isMovable())) {
511+
nextBlock = nextBlock.getNextBlock();
512+
}
513+
if (!nextBlock) return;
514+
515+
// Disconnect the next statement.
516+
const nextTarget =
517+
nextBlock.previousConnection?.targetBlock()?.nextConnection
518+
?.targetConnection ?? null;
519+
nextTarget?.disconnect();
520+
if (
521+
previousTarget &&
522+
this.workspace.connectionChecker.canConnect(
523+
previousTarget,
524+
nextTarget,
525+
false,
526+
)
527+
) {
528+
// Attach the next statement to the previous statement.
529+
previousTarget.connect(nextTarget!);
520530
}
521531
}
522532

tests/mocha/block_test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,35 @@ suite('Blocks', function () {
201201

202202
assertUnpluggedHealFailed(blocks);
203203
});
204+
test('Disconnect top of stack with immovable sibling', function () {
205+
this.blocks.B.setMovable(false);
206+
this.blocks.A.unplug(true);
207+
assert.equal(this.blocks.A.nextConnection.targetBlock(), this.blocks.B);
208+
assert.isNull(this.blocks.B.nextConnection.targetBlock());
209+
assert.isNull(this.blocks.C.previousConnection.targetBlock());
210+
});
211+
test('Heal with immovable sibling mid-stack', function () {
212+
const blockD = this.workspace.newBlock('stack_block', 'd');
213+
this.blocks.C.nextConnection.connect(blockD.previousConnection);
214+
this.blocks.C.setMovable(false);
215+
this.blocks.B.unplug(true);
216+
assert.equal(this.blocks.A.nextConnection.targetBlock(), blockD);
217+
assert.equal(this.blocks.B.nextConnection.targetBlock(), this.blocks.C);
218+
assert.isNull(this.blocks.C.nextConnection.targetBlock());
219+
});
220+
test('Heal with immovable sibling and shadow sibling mid-stack', function () {
221+
const blockD = this.workspace.newBlock('stack_block', 'd');
222+
const blockE = this.workspace.newBlock('stack_block', 'e');
223+
this.blocks.C.nextConnection.connect(blockD.previousConnection);
224+
blockD.nextConnection.connect(blockE.previousConnection);
225+
this.blocks.C.setMovable(false);
226+
blockD.setShadow(true);
227+
this.blocks.B.unplug(true);
228+
assert.equal(this.blocks.A.nextConnection.targetBlock(), blockE);
229+
assert.equal(this.blocks.B.nextConnection.targetBlock(), this.blocks.C);
230+
assert.equal(this.blocks.C.nextConnection.targetBlock(), blockD);
231+
assert.isNull(blockD.nextConnection.targetBlock());
232+
});
204233
test('Child is shadow', function () {
205234
const blocks = this.blocks;
206235
blocks.C.setShadow(true);

0 commit comments

Comments
 (0)