Skip to content

Commit 83753bd

Browse files
authored
fix: Disallow undo/redo during a keyboard-driven move. (RaspberryPiFoundation#407)
1 parent 26ddea5 commit 83753bd

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

src/actions/undo_redo.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {
8+
ShortcutRegistry,
9+
utils as BlocklyUtils,
10+
ShortcutItems,
11+
WorkspaceSvg,
12+
} from 'blockly/core';
13+
14+
import * as Constants from '../constants';
15+
import type {Navigation} from '../navigation';
16+
17+
const KeyCodes = BlocklyUtils.KeyCodes;
18+
19+
/**
20+
* Class for registering a shortcut for undo/redo actions.
21+
*/
22+
export class UndoRedoAction {
23+
private originalUndo?: ShortcutRegistry.KeyboardShortcut;
24+
private originalRedo?: ShortcutRegistry.KeyboardShortcut;
25+
/**
26+
* Patches the existing undo/redo shortcuts in the registry.
27+
*/
28+
install() {
29+
const undo =
30+
ShortcutRegistry.registry.getRegistry()[ShortcutItems.names.UNDO];
31+
if (undo) {
32+
this.originalUndo = undo;
33+
const patchedUndo = {
34+
...this.originalUndo,
35+
preconditionFn: (workspace: WorkspaceSvg) => {
36+
return !!(
37+
!workspace.isDragging() && undo.preconditionFn?.(workspace)
38+
);
39+
},
40+
allowCollision: true,
41+
};
42+
43+
ShortcutRegistry.registry.register(patchedUndo, true);
44+
}
45+
46+
const redo =
47+
ShortcutRegistry.registry.getRegistry()[ShortcutItems.names.REDO];
48+
if (redo) {
49+
this.originalRedo = redo;
50+
const patchedRedo = {
51+
...this.originalRedo,
52+
preconditionFn: (workspace: WorkspaceSvg) => {
53+
return !!(
54+
!workspace.isDragging() && redo.preconditionFn?.(workspace)
55+
);
56+
},
57+
allowCollision: true,
58+
};
59+
60+
ShortcutRegistry.registry.register(patchedRedo, true);
61+
}
62+
}
63+
64+
/**
65+
* Reverts the patched undo/redo shortcuts in the registry.
66+
*/
67+
uninstall() {
68+
if (this.originalUndo) {
69+
ShortcutRegistry.registry.register(this.originalUndo, true);
70+
this.originalUndo = undefined;
71+
}
72+
if (this.originalRedo) {
73+
ShortcutRegistry.registry.register(this.originalRedo, true);
74+
this.originalRedo = undefined;
75+
}
76+
}
77+
}

src/navigation_controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {DisconnectAction} from './actions/disconnect';
3636
import {ActionMenu} from './actions/action_menu';
3737
import {MoveActions} from './actions/move';
3838
import {Mover} from './actions/mover';
39+
import {UndoRedoAction} from './actions/undo_redo';
3940

4041
const KeyCodes = BlocklyUtils.KeyCodes;
4142

@@ -72,6 +73,8 @@ export class NavigationController {
7273

7374
enterAction: EnterAction = new EnterAction(this.navigation);
7475

76+
undoRedoAction: UndoRedoAction = new UndoRedoAction();
77+
7578
actionMenu: ActionMenu = new ActionMenu(this.navigation);
7679

7780
moveActions = new MoveActions(this.mover);
@@ -289,6 +292,7 @@ export class NavigationController {
289292
this.exitAction.install();
290293
this.enterAction.install();
291294
this.disconnectAction.install();
295+
this.undoRedoAction.install();
292296
this.actionMenu.install();
293297

294298
this.clipboard.install();
@@ -315,6 +319,7 @@ export class NavigationController {
315319
this.arrowNavigation.uninstall();
316320
this.exitAction.uninstall();
317321
this.enterAction.uninstall();
322+
this.undoRedoAction.uninstall();
318323
this.actionMenu.uninstall();
319324
this.shortcutDialog.uninstall();
320325

0 commit comments

Comments
 (0)