Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions packages/blockly/core/events/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import type {Workspace} from '../workspace.js';
import type {WorkspaceSvg} from '../workspace_svg.js';
import type {Abstract} from './events_abstract.js';
import type {BlockCreate} from './events_block_create.js';
import type {BlockDrag} from './events_block_drag.js';
import type {BlockMove} from './events_block_move.js';
import type {CommentCreate} from './events_comment_create.js';
import type {CommentMove} from './events_comment_move.js';
import type {CommentResize} from './events_comment_resize.js';
import {
isBlockChange,
isBlockCreate,
isBlockDrag,
isBlockMove,
isBubbleOpen,
isClick,
Expand Down Expand Up @@ -404,8 +406,17 @@ export function get(
* @param event Custom data for event.
*/
export function disableOrphans(event: Abstract) {
if (isBlockMove(event) || isBlockCreate(event)) {
const blockEvent = event as BlockMove | BlockCreate;
// BlockMove/BlockCreate events that fire mid-drag are skipped below (we
// don't want to disable a block while it's still being positioned). For
// keyboard-driven inserts from the flyout there may be no further move
// event after the drag ends, so also act on the end-of-drag event, at
// which point the workspace is no longer dragging.
if (
isBlockMove(event) ||
isBlockCreate(event) ||
(isBlockDrag(event) && !event.isStart)
) {
const blockEvent = event as BlockMove | BlockCreate | BlockDrag;
if (!blockEvent.workspaceId) {
return;
}
Expand Down
34 changes: 34 additions & 0 deletions packages/blockly/tests/mocha/event_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1637,5 +1637,39 @@ suite('Events', function () {
'Undo stack should not contain any disabled events',
);
});
test('Orphan is disabled by end-of-drag event', function () {
this.workspace.addChangeListener(eventUtils.disableOrphans);

// Simulate a drag/move being in progress, as happens when a block is
// inserted from the flyout via the keyboard. The block-create event
// fires while dragging, so its orphan-disabling branch is skipped.
const isDraggingStub = sinon
.stub(this.workspace, 'isDragging')
.returns(true);
const block = this.workspace.newBlock('controls_for');
block.initSvg();
block.render();

this.clock.runAll();

assert.isTrue(
block.isEnabled(),
'Block should not be disabled while a drag is in progress',
);

// The drag ends with no further move event (e.g. the block was
// committed in place). The end-of-drag event should disable the orphan.
isDraggingStub.returns(false);
eventUtils.fire(
new Blockly.Events.BlockDrag(block, false, block.getDescendants(false)),
);

this.clock.runAll();

assert.isFalse(
block.isEnabled(),
'Expected orphan block to be disabled after the drag ends',
);
});
});
});
Loading