Skip to content

Commit d07eab0

Browse files
committed
Clean up JS message dispatcher and fix a bug thrown on empty-data messages
Fixes bug in #394
1 parent 50ae24e commit d07eab0

File tree

5 files changed

+44
-46
lines changed

5 files changed

+44
-46
lines changed

frontend/src/App.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ img {
220220
<script lang="ts">
221221
import { defineComponent } from "vue";
222222
223+
// State providers
223224
import dialog from "@/utilities/dialog";
224225
import documents from "@/utilities/documents";
225226
import fullscreen from "@/utilities/fullscreen";

frontend/src/components/panels/LayerTree.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -424,14 +424,14 @@ export default defineComponent({
424424
});
425425
426426
subscribeJsMessage(UpdateLayer, (updateLayer) => {
427-
const responsePath = updateLayer.data.path;
428-
const responseLayer = updateLayer.data;
427+
const targetPath = updateLayer.data.path;
428+
const targetLayer = updateLayer.data;
429429
430-
const layer = this.layerCache.get(responsePath.toString());
430+
const layer = this.layerCache.get(targetPath.toString());
431431
if (layer) {
432-
Object.assign(this.layerCache.get(responsePath.toString()), responseLayer);
432+
Object.assign(this.layerCache.get(targetPath.toString()), targetLayer);
433433
} else {
434-
this.layerCache.set(responsePath.toString(), responseLayer);
434+
this.layerCache.set(targetPath.toString(), targetLayer);
435435
}
436436
this.setBlendModeForSelectedLayers();
437437
this.setOpacityForSelectedLayers();

frontend/src/utilities/errors.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createDialog, dismissDialog } from "@/utilities/dialog";
22
import { TextButtonWidget } from "@/components/widgets/widgets";
33
import { subscribeJsMessage } from "@/utilities/js-message-dispatcher";
4-
import { DisplayError, DisplayPanic } from "./js-messages";
4+
import { DisplayError, DisplayPanic } from "@/utilities/js-messages";
55

66
// Coming soon dialog
77
export function comingSoon(issueNumber?: number) {
@@ -139,8 +139,7 @@ function browserVersion(): string {
139139

140140
function operatingSystem(): string {
141141
const osTable: Record<string, string> = {
142-
"Windows NT 11": "Windows 11",
143-
"Windows NT 10": "Windows 10",
142+
"Windows NT 10": "Windows 10 or 11",
144143
"Windows NT 6.3": "Windows 8.1",
145144
"Windows NT 6.2": "Windows 8",
146145
"Windows NT 6.1": "Windows 7",

frontend/src/utilities/input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { toggleFullscreen } from "@/utilities/fullscreen";
22
import { dialogIsVisible, dismissDialog, submitDialog } from "@/utilities/dialog";
33
import { panicProxy } from "@/utilities/panic-proxy";
4-
import documents from "./documents";
4+
import documents from "@/utilities/documents";
55

66
const wasm = import("@/../wasm/pkg").then(panicProxy);
77

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22

3-
import { reactive } from "vue";
43
import { plainToInstance } from "class-transformer";
5-
64
import {
5+
JsMessage,
76
DisplayConfirmationToCloseAllDocuments,
87
DisplayConfirmationToCloseDocument,
98
DisplayError,
109
DisplayPanic,
1110
ExportDocument,
12-
newDisplayFolderTreeStructure,
11+
newDisplayFolderTreeStructure as DisplayFolderTreeStructure,
1312
OpenDocumentBrowse,
1413
SaveDocument,
1514
SetActiveDocument,
@@ -22,29 +21,16 @@ import {
2221
UpdateScrollbars,
2322
UpdateWorkingColors,
2423
UpdateLayer,
25-
JsMessage,
26-
} from "./js-messages";
27-
28-
type JsMessageCallback<T extends JsMessage> = (responseData: T) => void;
29-
type JsMessageCallbackMap = {
30-
[response: string]: JsMessageCallback<any> | undefined;
31-
};
24+
} from "@/utilities/js-messages";
3225

33-
const state = reactive({
34-
responseMap: {} as JsMessageCallbackMap,
35-
});
36-
37-
type Constructs<T> = new (...args: any[]) => T;
38-
type ConstructsJsMessage = Constructs<JsMessage> & typeof JsMessage;
39-
40-
const responseMap = {
26+
const messageConstructors = {
4127
UpdateCanvas,
4228
UpdateScrollbars,
4329
UpdateRulers,
4430
ExportDocument,
4531
SaveDocument,
4632
OpenDocumentBrowse,
47-
DisplayFolderTreeStructure: newDisplayFolderTreeStructure,
33+
DisplayFolderTreeStructure,
4834
UpdateLayer,
4935
SetActiveTool,
5036
SetActiveDocument,
@@ -57,39 +43,51 @@ const responseMap = {
5743
DisplayConfirmationToCloseDocument,
5844
DisplayConfirmationToCloseAllDocuments,
5945
} as const;
46+
type JsMessageType = keyof typeof messageConstructors;
47+
48+
type JsMessageCallback<T extends JsMessage> = (messageData: T) => void;
49+
type JsMessageCallbackMap = {
50+
[message: string]: JsMessageCallback<any> | undefined;
51+
};
6052

61-
export type JsMessageType = keyof typeof responseMap;
53+
type Constructs<T> = new (...args: any[]) => T;
54+
type ConstructsJsMessage = Constructs<JsMessage> & typeof JsMessage;
6255

63-
function isJsMessageConstructor(fn: ConstructsJsMessage | ((data: any) => JsMessage)): fn is ConstructsJsMessage {
64-
return (fn as ConstructsJsMessage).jsMessageMarker !== undefined;
65-
}
56+
const subscriptions = {} as JsMessageCallbackMap;
6657

67-
export function handleJsMessage(responseType: JsMessageType, responseData: any) {
68-
const messageMaker = responseMap[responseType];
69-
let message: JsMessage;
58+
export function subscribeJsMessage<T extends JsMessage>(messageType: Constructs<T>, callback: JsMessageCallback<T>) {
59+
subscriptions[messageType.name] = callback;
60+
}
7061

71-
if (!messageMaker) {
62+
export function handleJsMessage(messageType: JsMessageType, messageData: any) {
63+
const messageConstructor = messageConstructors[messageType];
64+
if (!messageConstructor) {
7265
// eslint-disable-next-line no-console
73-
console.error(`Received a Response of type "${responseType}" but but was not able to parse the data.`);
66+
console.error(`Received a frontend message of type "${messageType}" but but was not able to parse the data.`);
67+
return;
7468
}
7569

76-
if (isJsMessageConstructor(messageMaker)) {
77-
message = plainToInstance(messageMaker, responseData[responseType]);
70+
// Messages with non-empty data are provided by wasm-bindgen as an object with one key as the message name, like: { NameOfThisMessage: { ... } }
71+
// Messages with empty data are provided by wasm-bindgen as a string with the message name, like: "NameOfThisMessage"
72+
const unwrappedMessageData = messageData[messageType] || {};
73+
74+
const isJsMessageConstructor = (fn: ConstructsJsMessage | ((data: any) => JsMessage)): fn is ConstructsJsMessage => {
75+
return (fn as ConstructsJsMessage).jsMessageMarker !== undefined;
76+
};
77+
let message: JsMessage;
78+
if (isJsMessageConstructor(messageConstructor)) {
79+
message = plainToInstance(messageConstructor, unwrappedMessageData);
7880
} else {
79-
message = messageMaker(responseData[responseType]);
81+
message = messageConstructor(unwrappedMessageData);
8082
}
8183

8284
// It is ok to use constructor.name even with minification since it is used consistently with registerHandler
83-
const callback = state.responseMap[message.constructor.name];
85+
const callback = subscriptions[message.constructor.name];
8486

8587
if (callback && message) {
8688
callback(message);
8789
} else if (message) {
8890
// eslint-disable-next-line no-console
89-
console.error(`Received a Response of type "${responseType}" but no handler was registered for it from the client.`);
91+
console.error(`Received a frontend message of type "${messageType}" but no handler was registered for it from the client.`);
9092
}
9193
}
92-
93-
export function subscribeJsMessage<T extends JsMessage>(responseType: Constructs<T>, callback: JsMessageCallback<T>) {
94-
state.responseMap[responseType.name] = callback;
95-
}

0 commit comments

Comments
 (0)