fix: Improve flyout behavior (#9576)

* fix: Don't suppress and re-fire events when dragging blocks from the flyout

* fix: Fix bug that could cause blocks to get bumped when dragging from the flyout

* fix: Fix bug that made it more difficult to drag blocks from scrollable flyouts

* chore: Run formatter

* refactor: Clean up `createBlock`

* fix: Hide chaff at the end of block creation
This commit is contained in:
Aaron Dodson
2026-02-06 08:25:13 -08:00
committed by GitHub
parent 3acdf5e536
commit 87afe3e688
2 changed files with 26 additions and 77 deletions
+14 -60
View File
@@ -38,7 +38,6 @@ import * as dom from './utils/dom.js';
import * as idGenerator from './utils/idgenerator.js';
import {Svg} from './utils/svg.js';
import * as toolbox from './utils/toolbox.js';
import * as Variables from './variables.js';
import {WorkspaceSvg} from './workspace_svg.js';
/**
@@ -813,44 +812,23 @@ export abstract class Flyout
* @internal
*/
createBlock(originalBlock: BlockSvg): BlockSvg {
let newBlock = null;
eventUtils.disable();
const variablesBeforeCreation = this.targetWorkspace
.getVariableMap()
.getAllVariables();
this.targetWorkspace.setResizesEnabled(false);
try {
newBlock = this.placeNewBlock(originalBlock);
} finally {
eventUtils.enable();
const targetWorkspace = this.targetWorkspace;
const svgRootOld = originalBlock.getSvgRoot();
if (!svgRootOld) {
throw Error('oldBlock is not rendered');
}
// Close the flyout.
this.targetWorkspace.hideChaff();
// Clone the block.
const json = this.serializeBlock(originalBlock);
// Normally this resizes leading to weird jumps. Save it for terminateDrag.
targetWorkspace.setResizesEnabled(false);
const block = blocks.appendInternal(json, targetWorkspace, {
recordUndo: true,
}) as BlockSvg;
const newVariables = Variables.getAddedVariables(
this.targetWorkspace,
variablesBeforeCreation,
);
if (eventUtils.isEnabled()) {
eventUtils.setGroup(true);
// Fire a VarCreate event for each (if any) new variable created.
for (let i = 0; i < newVariables.length; i++) {
const thisVariable = newVariables[i];
eventUtils.fire(
new (eventUtils.get(EventType.VAR_CREATE))(thisVariable),
);
}
// Block events come after var events, in case they refer to newly created
// variables.
eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(newBlock));
}
if (this.autoClose) {
this.hide();
}
return newBlock;
this.positionNewBlock(originalBlock, block);
targetWorkspace.hideChaff();
return block;
}
/**
@@ -873,30 +851,6 @@ export abstract class Flyout
: false;
}
/**
* Copy a block from the flyout to the workspace and position it correctly.
*
* @param oldBlock The flyout block to copy.
* @returns The new block in the main workspace.
*/
private placeNewBlock(oldBlock: BlockSvg): BlockSvg {
const targetWorkspace = this.targetWorkspace;
const svgRootOld = oldBlock.getSvgRoot();
if (!svgRootOld) {
throw Error('oldBlock is not rendered');
}
// Clone the block.
const json = this.serializeBlock(oldBlock);
// Normally this resizes leading to weird jumps. Save it for terminateDrag.
targetWorkspace.setResizesEnabled(false);
const block = blocks.append(json, targetWorkspace) as BlockSvg;
this.positionNewBlock(oldBlock, block);
return block;
}
/**
* Serialize a block to JSON.
*
+12 -17
View File
@@ -274,24 +274,19 @@ export class Gesture {
throw new Error(`Cannot update dragging from the flyout because the ' +
'flyout's target workspace is undefined`);
}
if (
!this.flyout.isScrollable() ||
this.flyout.isDragTowardWorkspace(this.currentDragDeltaXY)
) {
this.startWorkspace_ = this.flyout.targetWorkspace;
this.startWorkspace_.updateScreenCalculationsIfScrolled();
// Start the event group now, so that the same event group is used for
// block creation and block dragging.
if (!eventUtils.getGroup()) {
eventUtils.setGroup(true);
}
// The start block is no longer relevant, because this is a drag.
this.startBlock = null;
this.targetBlock = this.flyout.createBlock(this.targetBlock);
getFocusManager().focusNode(this.targetBlock);
return true;
this.startWorkspace_ = this.flyout.targetWorkspace;
this.startWorkspace_.updateScreenCalculationsIfScrolled();
// Start the event group now, so that the same event group is used for
// block creation and block dragging.
if (!eventUtils.getGroup()) {
eventUtils.setGroup(true);
}
return false;
// The start block is no longer relevant, because this is a drag.
this.startBlock = null;
this.targetBlock = this.flyout.createBlock(this.targetBlock);
getFocusManager().focusNode(this.targetBlock);
return true;
}
/**