Skip to content

Commit 84c17b0

Browse files
authored
Finish drag on focus change (#530)
* fix: End a keyboard move if the user moves focus off the block * fix formatting * Add test for finishing a drag on focus lost * Formatting
1 parent 2e0a750 commit 84c17b0

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

src/actions/mover.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,21 @@ export class Mover {
125125
);
126126
if (!DraggerClass) throw new Error('no Dragger registered');
127127
const dragger = new DraggerClass(block, workspace);
128+
// Set up a blur listener to end the move if the user clicks away
129+
const blurListener = () => {
130+
this.finishMove(workspace);
131+
};
128132
// Record that a move is in progress and start dragging.
129133
workspace.setKeyboardMoveInProgress(true);
130-
const info = new MoveInfo(block, dragger);
134+
const info = new MoveInfo(block, dragger, blurListener);
131135
this.moves.set(workspace, info);
132136
// Begin drag.
133137
dragger.onDragStart(info.fakePointerEvent('pointerdown'));
134138
info.updateTotalDelta();
135139
// In case the block is detached, ensure that it still retains focus
136140
// (otherwise dragging will break).
137141
getFocusManager().focusNode(block);
142+
block.getFocusableElement().addEventListener('blur', blurListener);
138143
return true;
139144
}
140145

@@ -152,6 +157,11 @@ export class Mover {
152157
const info = this.moves.get(workspace);
153158
if (!info) throw new Error('no move info for workspace');
154159

160+
// Remove the blur listener before ending the drag
161+
info.block
162+
.getFocusableElement()
163+
.removeEventListener('blur', info.blurListener);
164+
155165
info.dragger.onDragEnd(
156166
info.fakePointerEvent('pointerup'),
157167
new utils.Coordinate(0, 0),
@@ -341,6 +351,7 @@ export class MoveInfo {
341351
constructor(
342352
readonly block: BlockSvg,
343353
readonly dragger: IDragger,
354+
readonly blurListener: EventListener,
344355
) {
345356
this.parentNext = block.previousConnection?.targetConnection ?? null;
346357
this.parentInput = block.outputConnection?.targetConnection ?? null;

test/webdriverio/test/basic_test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import * as chai from 'chai';
88
import * as Blockly from 'blockly';
99
import {
10+
isDragging,
1011
setCurrentCursorNodeById,
1112
setCurrentCursorNodeByIdAndFieldName,
1213
getCurrentFocusNodeId,
@@ -247,6 +248,21 @@ suite('Keyboard navigation on Blocks', function () {
247248
.expect(await getCurrentFocusedBlockId(this.browser))
248249
.equal('controls_repeat_1');
249250
});
251+
252+
test('Losing focus cancels move', async function () {
253+
await tabNavigateToWorkspace(this.browser);
254+
await this.browser.pause(PAUSE_TIME);
255+
await setCurrentCursorNodeById(this.browser, 'text_print_1');
256+
await this.browser.keys('m');
257+
await this.browser.pause(PAUSE_TIME);
258+
259+
chai.assert.isTrue(await isDragging(this.browser));
260+
261+
await this.browser.keys(Key.Tab);
262+
await this.browser.pause(PAUSE_TIME);
263+
264+
chai.assert.isFalse(await isDragging(this.browser));
265+
});
250266
});
251267

252268
// TODO(#499) These tests fail because focusing on a field doesn't update the cursor

test/webdriverio/test/test_setup.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,17 @@ export async function tabNavigateForward(browser: WebdriverIO.Browser) {
356356
await browser.keys(webdriverio.Key.Tab);
357357
await browser.pause(PAUSE_TIME);
358358
}
359+
360+
/**
361+
* Returns whether there's a drag in progress on the main workspace.
362+
*
363+
* @param browser The active WebdriverIO Browser object.
364+
*/
365+
export async function isDragging(
366+
browser: WebdriverIO.Browser,
367+
): Promise<boolean> {
368+
return await browser.execute(() => {
369+
const workspaceSvg = Blockly.getMainWorkspace() as Blockly.WorkspaceSvg;
370+
return workspaceSvg.isDragging();
371+
});
372+
}

0 commit comments

Comments
 (0)