Clean up JS message dispatcher and fix a bug thrown on empty-data messages
Fixes bug in #394
This commit is contained in:
parent
1cf90bde9a
commit
d4e3684744
|
|
@ -220,6 +220,7 @@ img {
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
|
// State providers
|
||||||
import dialog from "@/utilities/dialog";
|
import dialog from "@/utilities/dialog";
|
||||||
import documents from "@/utilities/documents";
|
import documents from "@/utilities/documents";
|
||||||
import fullscreen from "@/utilities/fullscreen";
|
import fullscreen from "@/utilities/fullscreen";
|
||||||
|
|
|
||||||
|
|
@ -424,14 +424,14 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
subscribeJsMessage(UpdateLayer, (updateLayer) => {
|
subscribeJsMessage(UpdateLayer, (updateLayer) => {
|
||||||
const responsePath = updateLayer.data.path;
|
const targetPath = updateLayer.data.path;
|
||||||
const responseLayer = updateLayer.data;
|
const targetLayer = updateLayer.data;
|
||||||
|
|
||||||
const layer = this.layerCache.get(responsePath.toString());
|
const layer = this.layerCache.get(targetPath.toString());
|
||||||
if (layer) {
|
if (layer) {
|
||||||
Object.assign(this.layerCache.get(responsePath.toString()), responseLayer);
|
Object.assign(this.layerCache.get(targetPath.toString()), targetLayer);
|
||||||
} else {
|
} else {
|
||||||
this.layerCache.set(responsePath.toString(), responseLayer);
|
this.layerCache.set(targetPath.toString(), targetLayer);
|
||||||
}
|
}
|
||||||
this.setBlendModeForSelectedLayers();
|
this.setBlendModeForSelectedLayers();
|
||||||
this.setOpacityForSelectedLayers();
|
this.setOpacityForSelectedLayers();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { createDialog, dismissDialog } from "@/utilities/dialog";
|
import { createDialog, dismissDialog } from "@/utilities/dialog";
|
||||||
import { TextButtonWidget } from "@/components/widgets/widgets";
|
import { TextButtonWidget } from "@/components/widgets/widgets";
|
||||||
import { subscribeJsMessage } from "@/utilities/js-message-dispatcher";
|
import { subscribeJsMessage } from "@/utilities/js-message-dispatcher";
|
||||||
import { DisplayError, DisplayPanic } from "./js-messages";
|
import { DisplayError, DisplayPanic } from "@/utilities/js-messages";
|
||||||
|
|
||||||
// Coming soon dialog
|
// Coming soon dialog
|
||||||
export function comingSoon(issueNumber?: number) {
|
export function comingSoon(issueNumber?: number) {
|
||||||
|
|
@ -139,8 +139,7 @@ function browserVersion(): string {
|
||||||
|
|
||||||
function operatingSystem(): string {
|
function operatingSystem(): string {
|
||||||
const osTable: Record<string, string> = {
|
const osTable: Record<string, string> = {
|
||||||
"Windows NT 11": "Windows 11",
|
"Windows NT 10": "Windows 10 or 11",
|
||||||
"Windows NT 10": "Windows 10",
|
|
||||||
"Windows NT 6.3": "Windows 8.1",
|
"Windows NT 6.3": "Windows 8.1",
|
||||||
"Windows NT 6.2": "Windows 8",
|
"Windows NT 6.2": "Windows 8",
|
||||||
"Windows NT 6.1": "Windows 7",
|
"Windows NT 6.1": "Windows 7",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { toggleFullscreen } from "@/utilities/fullscreen";
|
import { toggleFullscreen } from "@/utilities/fullscreen";
|
||||||
import { dialogIsVisible, dismissDialog, submitDialog } from "@/utilities/dialog";
|
import { dialogIsVisible, dismissDialog, submitDialog } from "@/utilities/dialog";
|
||||||
import { panicProxy } from "@/utilities/panic-proxy";
|
import { panicProxy } from "@/utilities/panic-proxy";
|
||||||
import documents from "./documents";
|
import documents from "@/utilities/documents";
|
||||||
|
|
||||||
const wasm = import("@/../wasm/pkg").then(panicProxy);
|
const wasm = import("@/../wasm/pkg").then(panicProxy);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import { plainToInstance } from "class-transformer";
|
import { plainToInstance } from "class-transformer";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
JsMessage,
|
||||||
DisplayConfirmationToCloseAllDocuments,
|
DisplayConfirmationToCloseAllDocuments,
|
||||||
DisplayConfirmationToCloseDocument,
|
DisplayConfirmationToCloseDocument,
|
||||||
DisplayError,
|
DisplayError,
|
||||||
DisplayPanic,
|
DisplayPanic,
|
||||||
ExportDocument,
|
ExportDocument,
|
||||||
newDisplayFolderTreeStructure,
|
newDisplayFolderTreeStructure as DisplayFolderTreeStructure,
|
||||||
OpenDocumentBrowse,
|
OpenDocumentBrowse,
|
||||||
SaveDocument,
|
SaveDocument,
|
||||||
SetActiveDocument,
|
SetActiveDocument,
|
||||||
|
|
@ -22,29 +21,16 @@ import {
|
||||||
UpdateScrollbars,
|
UpdateScrollbars,
|
||||||
UpdateWorkingColors,
|
UpdateWorkingColors,
|
||||||
UpdateLayer,
|
UpdateLayer,
|
||||||
JsMessage,
|
} from "@/utilities/js-messages";
|
||||||
} from "./js-messages";
|
|
||||||
|
|
||||||
type JsMessageCallback<T extends JsMessage> = (responseData: T) => void;
|
const messageConstructors = {
|
||||||
type JsMessageCallbackMap = {
|
|
||||||
[response: string]: JsMessageCallback<any> | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
responseMap: {} as JsMessageCallbackMap,
|
|
||||||
});
|
|
||||||
|
|
||||||
type Constructs<T> = new (...args: any[]) => T;
|
|
||||||
type ConstructsJsMessage = Constructs<JsMessage> & typeof JsMessage;
|
|
||||||
|
|
||||||
const responseMap = {
|
|
||||||
UpdateCanvas,
|
UpdateCanvas,
|
||||||
UpdateScrollbars,
|
UpdateScrollbars,
|
||||||
UpdateRulers,
|
UpdateRulers,
|
||||||
ExportDocument,
|
ExportDocument,
|
||||||
SaveDocument,
|
SaveDocument,
|
||||||
OpenDocumentBrowse,
|
OpenDocumentBrowse,
|
||||||
DisplayFolderTreeStructure: newDisplayFolderTreeStructure,
|
DisplayFolderTreeStructure,
|
||||||
UpdateLayer,
|
UpdateLayer,
|
||||||
SetActiveTool,
|
SetActiveTool,
|
||||||
SetActiveDocument,
|
SetActiveDocument,
|
||||||
|
|
@ -57,39 +43,51 @@ const responseMap = {
|
||||||
DisplayConfirmationToCloseDocument,
|
DisplayConfirmationToCloseDocument,
|
||||||
DisplayConfirmationToCloseAllDocuments,
|
DisplayConfirmationToCloseAllDocuments,
|
||||||
} as const;
|
} as const;
|
||||||
|
type JsMessageType = keyof typeof messageConstructors;
|
||||||
|
|
||||||
export type JsMessageType = keyof typeof responseMap;
|
type JsMessageCallback<T extends JsMessage> = (messageData: T) => void;
|
||||||
|
type JsMessageCallbackMap = {
|
||||||
|
[message: string]: JsMessageCallback<any> | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
function isJsMessageConstructor(fn: ConstructsJsMessage | ((data: any) => JsMessage)): fn is ConstructsJsMessage {
|
type Constructs<T> = new (...args: any[]) => T;
|
||||||
return (fn as ConstructsJsMessage).jsMessageMarker !== undefined;
|
type ConstructsJsMessage = Constructs<JsMessage> & typeof JsMessage;
|
||||||
|
|
||||||
|
const subscriptions = {} as JsMessageCallbackMap;
|
||||||
|
|
||||||
|
export function subscribeJsMessage<T extends JsMessage>(messageType: Constructs<T>, callback: JsMessageCallback<T>) {
|
||||||
|
subscriptions[messageType.name] = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleJsMessage(responseType: JsMessageType, responseData: any) {
|
export function handleJsMessage(messageType: JsMessageType, messageData: any) {
|
||||||
const messageMaker = responseMap[responseType];
|
const messageConstructor = messageConstructors[messageType];
|
||||||
let message: JsMessage;
|
if (!messageConstructor) {
|
||||||
|
|
||||||
if (!messageMaker) {
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(`Received a Response of type "${responseType}" but but was not able to parse the data.`);
|
console.error(`Received a frontend message of type "${messageType}" but but was not able to parse the data.`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isJsMessageConstructor(messageMaker)) {
|
// Messages with non-empty data are provided by wasm-bindgen as an object with one key as the message name, like: { NameOfThisMessage: { ... } }
|
||||||
message = plainToInstance(messageMaker, responseData[responseType]);
|
// Messages with empty data are provided by wasm-bindgen as a string with the message name, like: "NameOfThisMessage"
|
||||||
|
const unwrappedMessageData = messageData[messageType] || {};
|
||||||
|
|
||||||
|
const isJsMessageConstructor = (fn: ConstructsJsMessage | ((data: any) => JsMessage)): fn is ConstructsJsMessage => {
|
||||||
|
return (fn as ConstructsJsMessage).jsMessageMarker !== undefined;
|
||||||
|
};
|
||||||
|
let message: JsMessage;
|
||||||
|
if (isJsMessageConstructor(messageConstructor)) {
|
||||||
|
message = plainToInstance(messageConstructor, unwrappedMessageData);
|
||||||
} else {
|
} else {
|
||||||
message = messageMaker(responseData[responseType]);
|
message = messageConstructor(unwrappedMessageData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is ok to use constructor.name even with minification since it is used consistently with registerHandler
|
// It is ok to use constructor.name even with minification since it is used consistently with registerHandler
|
||||||
const callback = state.responseMap[message.constructor.name];
|
const callback = subscriptions[message.constructor.name];
|
||||||
|
|
||||||
if (callback && message) {
|
if (callback && message) {
|
||||||
callback(message);
|
callback(message);
|
||||||
} else if (message) {
|
} else if (message) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(`Received a Response of type "${responseType}" but no handler was registered for it from the client.`);
|
console.error(`Received a frontend message of type "${messageType}" but no handler was registered for it from the client.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function subscribeJsMessage<T extends JsMessage>(responseType: Constructs<T>, callback: JsMessageCallback<T>) {
|
|
||||||
state.responseMap[responseType.name] = callback;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue