Refactor to only have one function registerMenuCommand
When selected custom menu is removed, go to settings menu Allow iframe in custom menu to use Scripting API Return menu object when it is registered, can call remove function on it
This commit is contained in:
@@ -32,7 +32,7 @@ import type {
|
||||
TriggerActionMessageEvent,
|
||||
} from "./ui/TriggerActionMessageEvent";
|
||||
import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/TriggerActionMessageEvent";
|
||||
import type { MenuIframeRegisterEvent, MenuItemRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent";
|
||||
import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent";
|
||||
|
||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||
data: T;
|
||||
@@ -63,8 +63,7 @@ export type IframeEventMap = {
|
||||
stopSound: null;
|
||||
getState: undefined;
|
||||
loadTileset: LoadTilesetEvent;
|
||||
registerMenuCommand: MenuItemRegisterEvent;
|
||||
registerMenuIframe: MenuIframeRegisterEvent;
|
||||
registerMenu: MenuRegisterEvent;
|
||||
unregisterMenu: UnregisterMenuEvent;
|
||||
setTiles: SetTilesEvent;
|
||||
modifyEmbeddedWebsite: Partial<EmbeddedWebsite>; // Note: name should be compulsory in fact
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
import { isMenuItemRegisterEvent } from "./ui/MenuRegisterEvent";
|
||||
|
||||
export const isSetVariableEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
|
||||
@@ -1,35 +1,5 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
/**
|
||||
* A message sent from a script to the game to add a new button in the menu.
|
||||
*/
|
||||
export const isMenuItemRegisterEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
menuItem: tg.isString,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type MenuItemRegisterEvent = tg.GuardedType<typeof isMenuItemRegisterEvent>;
|
||||
|
||||
export const isMenuItemRegisterIframeEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
type: tg.isSingletonString("registerMenuCommand"),
|
||||
data: isMenuItemRegisterEvent,
|
||||
})
|
||||
.get();
|
||||
|
||||
/**
|
||||
* A message sent from a script to the game to add an iframe submenu in the menu.
|
||||
*/
|
||||
export const isMenuIframeEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
name: tg.isString,
|
||||
url: tg.isString,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type MenuIframeRegisterEvent = tg.GuardedType<typeof isMenuIframeEvent>;
|
||||
|
||||
/**
|
||||
* A message sent from a script to the game to remove a custom menu from the menu
|
||||
*/
|
||||
@@ -40,3 +10,22 @@ export const isUnregisterMenuEvent = new tg.IsInterface()
|
||||
.get();
|
||||
|
||||
export type UnregisterMenuEvent = tg.GuardedType<typeof isUnregisterMenuEvent>;
|
||||
|
||||
export const isMenuRegisterOptions = new tg.IsInterface()
|
||||
.withProperties({
|
||||
allowApi: tg.isBoolean,
|
||||
})
|
||||
.get();
|
||||
|
||||
/**
|
||||
* A message sent from a script to the game to add a custom menu from the menu
|
||||
*/
|
||||
export const isMenuRegisterEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
name: tg.isString,
|
||||
iframe: tg.isUnion(tg.isString, tg.isUndefined),
|
||||
options: isMenuRegisterOptions,
|
||||
})
|
||||
.get();
|
||||
|
||||
export type MenuRegisterEvent = tg.GuardedType<typeof isMenuRegisterEvent>;
|
||||
|
||||
@@ -29,7 +29,7 @@ import { isSetPropertyEvent, SetPropertyEvent } from "./Events/setPropertyEvent"
|
||||
import { isLayerEvent, LayerEvent } from "./Events/LayerEvent";
|
||||
import type { HasPlayerMovedEvent } from "./Events/HasPlayerMovedEvent";
|
||||
import { isLoadPageEvent } from "./Events/LoadPageEvent";
|
||||
import { isMenuItemRegisterIframeEvent, isMenuIframeEvent, isUnregisterMenuEvent } from "./Events/ui/MenuRegisterEvent";
|
||||
import { isMenuRegisterEvent, isUnregisterMenuEvent } from "./Events/ui/MenuRegisterEvent";
|
||||
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
|
||||
import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
||||
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
||||
@@ -255,22 +255,21 @@ class IframeListener {
|
||||
this._removeBubbleStream.next();
|
||||
} else if (payload.type == "onPlayerMove") {
|
||||
this.sendPlayerMove = true;
|
||||
} else if (isMenuItemRegisterIframeEvent(payload)) {
|
||||
const data = payload.data.menuItem;
|
||||
this.iframeCloseCallbacks.get(iframe)?.push(() => {
|
||||
handleMenuUnregisterEvent(data);
|
||||
});
|
||||
handleMenuRegistrationEvent(payload.data.menuItem);
|
||||
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
||||
this._setTilesStream.next(payload.data);
|
||||
} else if (payload.type == "modifyEmbeddedWebsite" && isEmbeddedWebsiteEvent(payload.data)) {
|
||||
this._modifyEmbeddedWebsiteStream.next(payload.data);
|
||||
} else if (payload.type == "registerMenuIframe" && isMenuIframeEvent(payload.data)) {
|
||||
const data = payload.data.name;
|
||||
} else if (payload.type == "registerMenu" && isMenuRegisterEvent(payload.data)) {
|
||||
const dataName = payload.data.name;
|
||||
this.iframeCloseCallbacks.get(iframe)?.push(() => {
|
||||
handleMenuUnregisterEvent(data);
|
||||
handleMenuUnregisterEvent(dataName);
|
||||
});
|
||||
handleMenuRegistrationEvent(payload.data.name, payload.data.url, foundSrc);
|
||||
handleMenuRegistrationEvent(
|
||||
payload.data.name,
|
||||
payload.data.iframe,
|
||||
foundSrc,
|
||||
payload.data.options
|
||||
);
|
||||
} else if (payload.type == "unregisterMenu" && isUnregisterMenuEvent(payload.data)) {
|
||||
handleMenuUnregisterEvent(payload.data.name);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { sendToWorkadventure } from "../IframeApiContribution";
|
||||
|
||||
export class Menu {
|
||||
constructor(private menuName: string) {}
|
||||
|
||||
/**
|
||||
* remove the menu
|
||||
*/
|
||||
public remove() {
|
||||
sendToWorkadventure({
|
||||
type: "unregisterMenu",
|
||||
data: {
|
||||
name: this.menuName,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
+62
-27
@@ -6,6 +6,8 @@ import type { ButtonClickedCallback, ButtonDescriptor } from "./Ui/ButtonDescrip
|
||||
import { Popup } from "./Ui/Popup";
|
||||
import { ActionMessage } from "./Ui/ActionMessage";
|
||||
import { isMessageReferenceEvent } from "../Events/ui/TriggerActionMessageEvent";
|
||||
import { Menu } from "./Ui/Menu";
|
||||
import type { RequireOnlyOne } from "../../types";
|
||||
|
||||
let popupId = 0;
|
||||
const popups: Map<number, Popup> = new Map<number, Popup>();
|
||||
@@ -14,9 +16,18 @@ const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<
|
||||
Map<number, ButtonClickedCallback>
|
||||
>();
|
||||
|
||||
const menus: Map<string, Menu> = new Map<string, Menu>();
|
||||
const menuCallbacks: Map<string, (command: string) => void> = new Map();
|
||||
const actionMessages = new Map<string, ActionMessage>();
|
||||
|
||||
interface MenuDescriptor {
|
||||
callback?: (commandDescriptor: string) => void;
|
||||
iframe?: string;
|
||||
allowApi?: boolean;
|
||||
}
|
||||
|
||||
type CallbackOrIframe = RequireOnlyOne<MenuDescriptor, "callback" | "iframe">;
|
||||
|
||||
interface ZonedPopupOptions {
|
||||
zone: string;
|
||||
objectLayerName?: string;
|
||||
@@ -52,6 +63,10 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
|
||||
typeChecker: isMenuItemClickedEvent,
|
||||
callback: (event) => {
|
||||
const callback = menuCallbacks.get(event.menuItem);
|
||||
const menu = menus.get(event.menuItem);
|
||||
if (menu === undefined) {
|
||||
throw new Error('Could not find menu named "' + event.menuItem + '"');
|
||||
}
|
||||
if (callback) {
|
||||
callback(event.menuItem);
|
||||
}
|
||||
@@ -104,36 +119,56 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
|
||||
return popup;
|
||||
}
|
||||
|
||||
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void) {
|
||||
menuCallbacks.set(commandDescriptor, callback);
|
||||
sendToWorkadventure({
|
||||
type: "registerMenuCommand",
|
||||
data: {
|
||||
menuItem: commandDescriptor,
|
||||
},
|
||||
});
|
||||
}
|
||||
registerMenuCommand(
|
||||
commandDescriptor: string,
|
||||
options: CallbackOrIframe | ((commandDescriptor: string) => void)
|
||||
): Menu {
|
||||
const menu = new Menu(commandDescriptor);
|
||||
|
||||
registerMenuIframe(menuName: string, iframeUrl: string) {
|
||||
sendToWorkadventure({
|
||||
type: "registerMenuIframe",
|
||||
data: {
|
||||
name: menuName,
|
||||
url: iframeUrl,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (typeof options === "function") {
|
||||
menuCallbacks.set(commandDescriptor, options);
|
||||
sendToWorkadventure({
|
||||
type: "registerMenu",
|
||||
data: {
|
||||
name: commandDescriptor,
|
||||
options: {
|
||||
allowApi: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
options.allowApi = options.allowApi === undefined ? options.iframe !== undefined : options.allowApi;
|
||||
|
||||
unregisterMenu(menuName: string) {
|
||||
sendToWorkadventure({
|
||||
type: "unregisterMenu",
|
||||
data: {
|
||||
name: menuName,
|
||||
},
|
||||
});
|
||||
if (menuCallbacks.get(menuName)) {
|
||||
menuCallbacks.delete(menuName);
|
||||
if (options.iframe !== undefined) {
|
||||
sendToWorkadventure({
|
||||
type: "registerMenu",
|
||||
data: {
|
||||
name: commandDescriptor,
|
||||
iframe: options.iframe,
|
||||
options: {
|
||||
allowApi: options.allowApi,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (options.callback !== undefined) {
|
||||
menuCallbacks.set(commandDescriptor, options.callback);
|
||||
sendToWorkadventure({
|
||||
type: "registerMenu",
|
||||
data: {
|
||||
name: commandDescriptor,
|
||||
options: {
|
||||
allowApi: options.allowApi,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
throw new Error(
|
||||
"When adding a menu with WA.ui.registerMenuCommand, you must pass either an iframe or a callback"
|
||||
);
|
||||
}
|
||||
}
|
||||
menus.set(commandDescriptor, menu);
|
||||
return menu;
|
||||
}
|
||||
|
||||
displayBubble(): void {
|
||||
|
||||
Reference in New Issue
Block a user