Skip to content

Commit 159e69f

Browse files
Allow optional actions to avoid console errors (#310)
1 parent f286b9d commit 159e69f

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

packages/client/src/base/action-dispatcher.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
*
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
16-
import { inject, injectable } from 'inversify';
1716
import { Action, ActionDispatcher, RequestAction, ResponseAction } from '@eclipse-glsp/sprotty';
17+
import { inject, injectable } from 'inversify';
18+
import { OptionalAction } from './model/glsp-model-source';
1819
import { ModelInitializationConstraint } from './model/model-initialization-constraint';
1920

2021
@injectable()
@@ -76,6 +77,9 @@ export class GLSPActionDispatcher extends ActionDispatcher {
7677
action.responseId = '';
7778
}
7879
}
80+
if (!this.hasHandler(action) && OptionalAction.is(action)) {
81+
return Promise.resolve();
82+
}
7983
return super.handleAction(action);
8084
}
8185

packages/client/src/base/model/glsp-model-source.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616

17-
import { inject, injectable, preDestroy } from 'inversify';
1817
import {
1918
Action,
2019
ActionMessage,
@@ -29,8 +28,10 @@ import {
2928
ModelSource,
3029
TYPES
3130
} from '@eclipse-glsp/sprotty';
31+
import { inject, injectable, preDestroy } from 'inversify';
3232
import { GLSPActionHandlerRegistry } from '../action-handler-registry';
3333
import { IDiagramOptions } from './diagram-loader';
34+
3435
/**
3536
* A helper interface that allows the client to mark actions that have been received from the server.
3637
*/
@@ -44,14 +45,37 @@ export namespace ServerAction {
4445
}
4546

4647
/**
47-
* Mark the given action as {@link ServerAction} by attaching the "_receivedFromServer" property
48+
* Mark the given action as {@link ServerAction} by attaching the "__receivedFromServer" property
4849
* @param action The action that should be marked as server action
4950
*/
5051
export function mark(action: Action): void {
5152
(action as ServerAction).__receivedFromServer = true;
5253
}
5354
}
5455

56+
/**
57+
* A helper interface that allows the client to mark actions that can be considered optional and should not throw an error if
58+
* no handler is available.
59+
*/
60+
export interface OptionalAction extends Action {
61+
__skipErrorIfNoHandler: true;
62+
}
63+
64+
export namespace OptionalAction {
65+
export function is(object: unknown): object is ServerAction {
66+
return Action.is(object) && '__skipErrorIfNoHandler' in object && object.__skipErrorIfNoHandler === true;
67+
}
68+
69+
/**
70+
* Mark the given action as {@link OptionalAction} by attaching the "__skipErrorIfNoHandler" property
71+
* @param action The action that should be marked as optional action
72+
*/
73+
export function mark<T extends Action>(action: T): T & OptionalAction {
74+
(action as unknown as OptionalAction).__skipErrorIfNoHandler = true;
75+
return action as T & OptionalAction;
76+
}
77+
}
78+
5579
/**
5680
* Central component for enabling the client-server action flow with the help of an underlying {@link GLSPClient}.
5781
* Handles & forwards actions that are intended for the GLSP server. In addition, it handles {@link ActionMessage}s received

packages/client/src/features/tools/change-bounds/change-bounds-tool-feedback.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { DebouncedFunc, debounce } from 'lodash';
3636
import { DragAwareMouseListener } from '../../../base/drag-aware-mouse-listener';
3737
import { CursorCSS, cursorFeedbackAction } from '../../../base/feedback/css-feedback';
3838
import { FeedbackCommand } from '../../../base/feedback/feedback-command';
39+
import { OptionalAction } from '../../../base/model/glsp-model-source';
3940
import { forEachElement } from '../../../utils/gmodel-util';
4041
import { SResizeHandle, addResizeHandles, isResizable, removeResizeHandles } from '../../change-bounds/model';
4142
import { createMovementRestrictionFeedback, removeMovementRestrictionFeedback } from '../../change-bounds/movement-restrictor';
@@ -125,7 +126,7 @@ export namespace MoveInitializedEventAction {
125126
}
126127

127128
export function create(): MoveInitializedEventAction {
128-
return { kind: KIND };
129+
return OptionalAction.mark({ kind: KIND });
129130
}
130131
}
131132

@@ -141,7 +142,7 @@ export namespace MoveFinishedEventAction {
141142
}
142143

143144
export function create(): MoveFinishedEventAction {
144-
return { kind: KIND };
145+
return OptionalAction.mark({ kind: KIND });
145146
}
146147
}
147148

@@ -157,6 +158,7 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
157158
protected positionUpdater;
158159
protected elementId2startPos = new Map<string, Point>();
159160
protected pendingMoveInitialized?: DebouncedFunc<() => void>;
161+
protected moveInitialized = false;
160162

161163
constructor(protected tool: ChangeBoundsTool) {
162164
super();
@@ -178,10 +180,12 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
178180
}
179181

180182
protected scheduleMoveInitialized(): void {
183+
this.moveInitialized = false;
181184
this.pendingMoveInitialized?.cancel();
182185
this.pendingMoveInitialized = debounce(() => {
183186
this.tool.registerFeedback([MoveInitializedEventAction.create()], this);
184187
this.pendingMoveInitialized = undefined;
188+
this.moveInitialized = true;
185189
}, 750);
186190
this.pendingMoveInitialized();
187191
}
@@ -329,11 +333,12 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
329333
const moveAction = MoveAction.create(elementMoves, { animate: false, finished: true });
330334
this.tool.deregisterFeedback(this, [moveAction]);
331335
}
332-
} else if (resetFeedback) {
336+
} else if (resetFeedback && this.moveInitialized) {
333337
this.tool.deregisterFeedback(this, [MoveFinishedEventAction.create()]);
334338
}
335339
this.positionUpdater.resetPosition();
336340
this._isMouseDrag = false;
341+
this.moveInitialized = false;
337342
this.rootElement = undefined;
338343
this.elementId2startPos.clear();
339344
}

0 commit comments

Comments
 (0)