Skip to content

Commit fd1e4fb

Browse files
authored
fix: Allow some things to handle the enter key on read only workspaces (#597)
* Allow some things to handle return on read only workspaces * Allow navigating to the toolbox on readonly workspaces * Allow navigating to the main workspace from readonly workspaces * Make tests with mouse more robust * Minor fixes and refactor out a method to check if ws should handle return * Respond to comments * Change default for handling enter to false.
1 parent f92085b commit fd1e4fb

File tree

12 files changed

+150
-41
lines changed

12 files changed

+150
-41
lines changed

src/actions/action_menu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class ActionMenu {
5252
);
5353
},
5454
callback: (workspace) => {
55-
switch (this.navigation.getState(workspace)) {
55+
switch (this.navigation.getState()) {
5656
case Constants.STATE.WORKSPACE:
5757
case Constants.STATE.FLYOUT:
5858
return this.openActionMenu(workspace);

src/actions/arrow_navigation.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export class ArrowNavigation {
6363
? workspace.targetWorkspace?.getFlyout()
6464
: workspace.getFlyout();
6565
let isHandled = false;
66-
switch (this.navigation.getState(workspace)) {
66+
switch (this.navigation.getState()) {
6767
case Constants.STATE.WORKSPACE:
6868
isHandled = this.fieldShortcutHandler(workspace, shortcut);
6969
if (!isHandled && workspace) {
@@ -97,7 +97,7 @@ export class ArrowNavigation {
9797
? workspace.targetWorkspace?.getToolbox()
9898
: workspace.getToolbox();
9999
let isHandled = false;
100-
switch (this.navigation.getState(workspace)) {
100+
switch (this.navigation.getState()) {
101101
case Constants.STATE.WORKSPACE:
102102
isHandled = this.fieldShortcutHandler(workspace, shortcut);
103103
if (!isHandled && workspace) {
@@ -161,7 +161,7 @@ export class ArrowNavigation {
161161
callback: (workspace, e, shortcut) => {
162162
keyboardNavigationController.setIsActive(true);
163163
let isHandled = false;
164-
switch (this.navigation.getState(workspace)) {
164+
switch (this.navigation.getState()) {
165165
case Constants.STATE.WORKSPACE:
166166
isHandled = this.fieldShortcutHandler(workspace, shortcut);
167167
if (!isHandled && workspace) {
@@ -223,7 +223,7 @@ export class ArrowNavigation {
223223
callback: (workspace, e, shortcut) => {
224224
keyboardNavigationController.setIsActive(true);
225225
let isHandled = false;
226-
switch (this.navigation.getState(workspace)) {
226+
switch (this.navigation.getState()) {
227227
case Constants.STATE.WORKSPACE:
228228
isHandled = this.fieldShortcutHandler(workspace, shortcut);
229229
if (!isHandled) {

src/actions/clipboard.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ export class Clipboard {
285285
!!this.oldCopyShortcut?.callback &&
286286
this.oldCopyShortcut.callback(workspace, e, shortcut, scope);
287287
if (didCopy) {
288-
this.copyWorkspace = workspace;
288+
this.copyWorkspace = workspace.isFlyout
289+
? workspace.targetWorkspace
290+
: workspace;
289291
showCopiedHint(workspace);
290292
}
291293
return didCopy;

src/actions/disconnect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class DisconnectAction {
5858
this.navigation.canCurrentlyEdit(workspace),
5959
callback: (workspace) => {
6060
keyboardNavigationController.setIsActive(true);
61-
switch (this.navigation.getState(workspace)) {
61+
switch (this.navigation.getState()) {
6262
case Constants.STATE.WORKSPACE:
6363
this.disconnectBlocks(workspace);
6464
return true;

src/actions/enter.ts

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import {
88
Events,
9-
Msg,
109
ShortcutRegistry,
1110
utils as BlocklyUtils,
1211
getFocusManager,
@@ -54,33 +53,48 @@ export class EnterAction {
5453
*/
5554
ShortcutRegistry.registry.register({
5655
name: Constants.SHORTCUT_NAMES.EDIT_OR_CONFIRM,
57-
preconditionFn: (workspace) =>
58-
this.navigation.canCurrentlyEdit(workspace),
59-
callback: (workspace, event) => {
56+
preconditionFn: (workspace): boolean => {
57+
switch (this.navigation.getState()) {
58+
case Constants.STATE.WORKSPACE:
59+
return this.shouldHandleEnterForWS(workspace);
60+
case Constants.STATE.FLYOUT: {
61+
// If we're in the flyout the only supported actions are inserting
62+
// blocks or clicking buttons, so don't handle this if the
63+
// main workspace is read only.
64+
const targetWorkspace = workspace.isFlyout
65+
? workspace.targetWorkspace
66+
: workspace;
67+
return !!targetWorkspace && !targetWorkspace.isReadOnly();
68+
}
69+
default:
70+
return false;
71+
}
72+
},
73+
callback: (workspace, event): boolean => {
6074
event.preventDefault();
6175

76+
const targetWorkspace = workspace.isFlyout
77+
? workspace.targetWorkspace
78+
: workspace;
79+
if (!targetWorkspace) return false;
80+
6281
let flyoutCursor;
6382
let curNode;
6483

65-
switch (this.navigation.getState(workspace)) {
84+
switch (this.navigation.getState()) {
6685
case Constants.STATE.WORKSPACE:
67-
this.handleEnterForWS(workspace);
68-
return true;
86+
return this.handleEnterForWS(workspace);
6987
case Constants.STATE.FLYOUT:
70-
if (!workspace.targetWorkspace) return false;
71-
flyoutCursor = this.navigation.getFlyoutCursor(
72-
workspace.targetWorkspace,
73-
);
88+
flyoutCursor = this.navigation.getFlyoutCursor(targetWorkspace);
7489
if (!flyoutCursor) {
7590
return false;
7691
}
7792
curNode = flyoutCursor.getCurNode();
7893
if (curNode instanceof BlockSvg) {
79-
this.insertFromFlyout(workspace.targetWorkspace);
94+
this.insertFromFlyout(targetWorkspace);
8095
} else if (curNode instanceof FlyoutButton) {
8196
this.triggerButtonCallback(workspace);
8297
}
83-
8498
return true;
8599
default:
86100
return false;
@@ -90,30 +104,57 @@ export class EnterAction {
90104
});
91105
}
92106

107+
/**
108+
* Checks if the enter key should do anything for this ws.
109+
*
110+
* @param workspace The workspace to check.
111+
* @returns True if the enter action should be handled.
112+
*/
113+
private shouldHandleEnterForWS(workspace: WorkspaceSvg): boolean {
114+
const cursor = workspace.getCursor();
115+
const curNode = cursor?.getCurNode();
116+
if (!curNode) return false;
117+
if (curNode instanceof Field) return curNode.isClickable();
118+
if (
119+
curNode instanceof RenderedConnection ||
120+
curNode instanceof WorkspaceSvg
121+
) {
122+
return !workspace.isReadOnly();
123+
}
124+
// Returning true is sometimes incorrect for icons, but there's no API to check.
125+
if (curNode instanceof icons.Icon) return true;
126+
return false;
127+
}
128+
93129
/**
94130
* Handles hitting the enter key on the workspace.
95131
*
96132
* @param workspace The workspace.
133+
* @returns True if the enter was handled, false otherwise.
97134
*/
98-
private handleEnterForWS(workspace: WorkspaceSvg) {
135+
private handleEnterForWS(workspace: WorkspaceSvg): boolean {
99136
const cursor = workspace.getCursor();
100-
if (!cursor) return;
101-
const curNode = cursor.getCurNode();
102-
if (!curNode) return;
137+
const curNode = cursor?.getCurNode();
138+
if (!curNode) return false;
103139
if (curNode instanceof Field) {
104140
curNode.showEditor();
141+
return true;
105142
} else if (curNode instanceof BlockSvg) {
106143
if (!this.tryShowFullBlockFieldEditor(curNode)) {
107144
showHelpHint(workspace);
108145
}
146+
return true;
109147
} else if (
110148
curNode instanceof RenderedConnection ||
111149
curNode instanceof WorkspaceSvg
112150
) {
113151
this.navigation.openToolboxOrFlyout(workspace);
152+
return true;
114153
} else if (curNode instanceof icons.Icon) {
115154
curNode.onClick();
155+
return true;
116156
}
157+
return false;
117158
}
118159

119160
/**

src/actions/exit.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class ExitAction {
3131
preconditionFn: (workspace) =>
3232
this.navigation.canCurrentlyNavigate(workspace),
3333
callback: (workspace) => {
34-
switch (this.navigation.getState(workspace)) {
34+
switch (this.navigation.getState()) {
3535
case Constants.STATE.FLYOUT:
3636
case Constants.STATE.TOOLBOX:
3737
getFocusManager().focusTree(workspace.targetWorkspace ?? workspace);

src/actions/mover.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class Mover {
8585
*/
8686
canMove(workspace: WorkspaceSvg, block: BlockSvg) {
8787
return !!(
88-
this.navigation.getState(workspace) === Constants.STATE.WORKSPACE &&
88+
this.navigation.getState() === Constants.STATE.WORKSPACE &&
8989
this.navigation.canCurrentlyEdit(workspace) &&
9090
!this.moves.has(workspace) && // No move in progress.
9191
block?.isMovable()

src/actions/ws_movement.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,16 @@ export class WorkspaceMovement {
6868
/** Move the cursor to the workspace. */
6969
{
7070
name: Constants.SHORTCUT_NAMES.CREATE_WS_CURSOR,
71-
preconditionFn: (workspace) =>
72-
this.navigation.canCurrentlyEdit(workspace),
71+
preconditionFn: (workspace) => {
72+
return true;
73+
},
7374
callback: (workspace) => {
75+
const targetWorkspace = workspace.isFlyout
76+
? workspace.targetWorkspace
77+
: workspace;
78+
if (!targetWorkspace) return false;
7479
keyboardNavigationController.setIsActive(true);
75-
return this.createWSCursor(workspace);
80+
return this.createWSCursor(targetWorkspace);
7681
},
7782
keyCodes: [KeyCodes.W],
7883
},

src/navigation.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,9 @@ export class Navigation {
9393
* Note that this assumes a workspace with passive focus (including for its
9494
* toolbox or flyout) has a state of NOWHERE.
9595
*
96-
* @param workspace The workspace to get the state of.
9796
* @returns The state of the given workspace.
9897
*/
99-
getState(workspace: Blockly.WorkspaceSvg): Constants.STATE {
98+
getState(): Constants.STATE {
10099
const focusedTree = Blockly.getFocusManager().getFocusedTree();
101100
if (focusedTree instanceof Blockly.WorkspaceSvg) {
102101
if (focusedTree.isFlyout) {
@@ -105,9 +104,7 @@ export class Navigation {
105104
return Constants.STATE.WORKSPACE;
106105
}
107106
} else if (focusedTree instanceof Blockly.Toolbox) {
108-
if (workspace === focusedTree.getWorkspace()) {
109-
return Constants.STATE.TOOLBOX;
110-
}
107+
return Constants.STATE.TOOLBOX;
111108
} else if (focusedTree instanceof Blockly.Flyout) {
112109
return Constants.STATE.FLYOUT;
113110
}
@@ -222,7 +219,7 @@ export class Navigation {
222219
}
223220
} else if (
224221
e.type === Blockly.Events.BLOCK_CREATE &&
225-
this.getState(mainWorkspace) === Constants.STATE.FLYOUT
222+
this.getState() === Constants.STATE.FLYOUT
226223
) {
227224
// When variables are created, that recreates the flyout contents, leaving the
228225
// cursor in an invalid state.
@@ -825,7 +822,7 @@ export class Navigation {
825822
: workspace.keyboardAccessibilityMode;
826823
return (
827824
!!accessibilityMode &&
828-
this.getState(workspace) !== Constants.STATE.NOWHERE &&
825+
this.getState() !== Constants.STATE.NOWHERE &&
829826
!Blockly.getFocusManager().ephemeralFocusTaken()
830827
);
831828
}

src/navigation_controller.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,10 @@ export class NavigationController {
196196
/** Move focus to or from the toolbox. */
197197
focusToolbox: {
198198
name: Constants.SHORTCUT_NAMES.TOOLBOX,
199-
preconditionFn: (workspace) =>
200-
!workspace.isDragging() && this.navigation.canCurrentlyEdit(workspace),
199+
preconditionFn: (workspace) => !workspace.isDragging(),
201200
callback: (workspace) => {
202201
keyboardNavigationController.setIsActive(true);
203-
switch (this.navigation.getState(workspace)) {
202+
switch (this.navigation.getState()) {
204203
case Constants.STATE.WORKSPACE:
205204
Blockly.getFocusManager().focusTree(
206205
workspace.getToolbox() ??

0 commit comments

Comments
 (0)