script api can add menu commands

# Conflicts:
#	front/src/Api/IframeListener.ts
#	front/src/iframe_api.ts
This commit is contained in:
jonny 2021-04-27 11:59:22 +02:00
parent ca628d9a90
commit fafaabb6e7
5 changed files with 84 additions and 5 deletions

View File

@ -0,0 +1,10 @@
import * as tg from "generic-type-guard";
export const isMenuItemClickedEvent =
new tg.IsInterface().withProperties({
menuItem: tg.isString
}).get();
/**
* A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property.
*/
export type MenuItemClickedEvent = tg.GuardedType<typeof isMenuItemClickedEvent>;

View File

@ -0,0 +1,10 @@
import * as tg from "generic-type-guard";
export const isMenuItemRegisterEvent =
new tg.IsInterface().withProperties({
menutItem: tg.isString
}).get();
/**
* A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property.
*/
export type MenuItemRegisterEvent = tg.GuardedType<typeof isMenuItemRegisterEvent>;

View File

@ -12,6 +12,8 @@ import {ClosePopupEvent, isClosePopupEvent} from "./Events/ClosePopupEvent";
import {scriptUtils} from "./ScriptUtils";
import {GoToPageEvent, isGoToPageEvent} from "./Events/GoToPageEvent";
import {isOpenCoWebsite, OpenCoWebSiteEvent} from "./Events/OpenCoWebSiteEvent";
import { isMenuItemRegisterEvent } from './Events/MenuItemRegisterEvent';
import { MenuItemClickedEvent } from './Events/MenuItemClickedEvent';
/**
@ -52,6 +54,8 @@ class IframeListener {
private readonly _removeBubbleStream: Subject<void> = new Subject();
public readonly removeBubbleStream = this._removeBubbleStream.asObservable();
private readonly _registerMenuCommandStream: Subject<string> = new Subject();
public readonly registerMenuCommandStream = this._registerMenuCommandStream.asObservable();
private readonly iframes = new Set<HTMLIFrameElement>();
private readonly scripts = new Map<string, HTMLIFrameElement>();
@ -103,6 +107,8 @@ class IframeListener {
}
else if (payload.type === 'removeBubble'){
this._removeBubbleStream.next();
} else if (payload.type == "registerMenuCommand" && isMenuItemRegisterEvent(payload.data)) {
this._registerMenuCommandStream.next(payload.data.menutItem)
}
}
@ -187,6 +193,15 @@ class IframeListener {
this.scripts.delete(scriptUrl);
}
sendMenuClickedEvent(menuItem: string) {
this.postMessage({
'type': 'menuItemClicked',
'data': {
menuItem: menuItem,
} as MenuItemClickedEvent
});
}
sendUserInputChat(message: string) {
this.postMessage({
'type': 'userInputChat',

View File

@ -9,6 +9,9 @@ import {connectionManager} from "../../Connexion/ConnectionManager";
import {GameConnexionTypes} from "../../Url/UrlManager";
import {WarningContainer, warningContainerHtml, warningContainerKey} from "../Components/WarningContainer";
import {worldFullWarningStream} from "../../Connexion/WorldFullWarningStream";
import { HtmlUtils } from '../../WebRtc/HtmlUtils';
import { iframeListener } from '../../Api/IframeListener';
import { Subscription } from 'rxjs';
export const MenuSceneName = 'MenuScene';
const gameMenuKey = 'gameMenu';
@ -36,11 +39,20 @@ export class MenuScene extends Phaser.Scene {
private warningContainer: WarningContainer | null = null;
private warningContainerTimeout: NodeJS.Timeout | null = null;
private apiMenus = []
private subscriptions = new Subscription()
constructor() {
super({key: MenuSceneName});
this.gameQualityValue = localUserStore.getGameQualityValue();
this.videoQualityValue = localUserStore.getVideoQualityValue();
this.subscriptions.add(iframeListener.registerMenuCommandStream.subscribe(menuCommand => {
this.addMenuOption(menuCommand);
}))
}
preload () {
@ -266,13 +278,28 @@ export class MenuScene extends Phaser.Scene {
});
}
public addMenuOption(menuText: string) {
const wrappingSection = document.createElement("section")
wrappingSection.innerHTML = `<button class="fromApi" id="${HtmlUtils.escapeHtml(menuText)}">${HtmlUtils.escapeHtml(menuText)}</button>`
const menuItemContainer = this.menuElement.node.querySelector("#gameMenu main");
if (menuItemContainer) {
menuItemContainer.insertBefore(wrappingSection, menuItemContainer.querySelector("#socialLinks"))
}
}
private onMenuClick(event: MouseEvent) {
if((event?.target as HTMLInputElement).classList.contains('not-button')){
const htmlMenuItem = (event?.target as HTMLInputElement);
if (htmlMenuItem.classList.contains('not-button')) {
return;
}
event.preventDefault();
switch ((event?.target as HTMLInputElement).id) {
if (htmlMenuItem.classList.contains("fromApi")) {
iframeListener.sendMenuClickedEvent(htmlMenuItem.id)
return
}
switch (htmlMenuItem.id) {
case 'changeNameButton':
this.closeSideMenu();
gameManager.leaveGame(this, LoginSceneName, new LoginScene());

View File

@ -9,6 +9,8 @@ import {ClosePopupEvent} from "./Api/Events/ClosePopupEvent";
import {OpenTabEvent} from "./Api/Events/OpenTabEvent";
import {GoToPageEvent} from "./Api/Events/GoToPageEvent";
import {OpenCoWebSiteEvent} from "./Api/Events/OpenCoWebSiteEvent";
import { isMenuItemClickedEvent } from './Api/Events/MenuItemClickedEvent';
import { MenuItemRegisterEvent } from './Api/Events/MenuItemRegisterEvent';
interface WorkAdventureApi {
sendChatMessage(message: string, author: string): void;
@ -24,6 +26,7 @@ interface WorkAdventureApi {
restorePlayerControl() : void;
displayBubble() : void;
removeBubble() : void;
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void
}
declare global {
@ -40,7 +43,7 @@ const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subj
const leaveStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
const popups: Map<number, Popup> = new Map<number, Popup>();
const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<number, Map<number, ButtonClickedCallback>>();
const menuCallbacks: Map<string, (command: string) => void> = new Map()
let popupId = 0;
interface ButtonDescriptor {
/**
@ -172,6 +175,16 @@ window.WA = {
popups.set(popupId, popup)
return popup;
},
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void) {
menuCallbacks.set(commandDescriptor, callback);
window.parent.postMessage({
'type': 'registerMenuCommand',
'data': {
menutItem: commandDescriptor
} as MenuItemRegisterEvent
}, '*');
},
/**
* Listen to messages sent by the local user, in the chat.
*/
@ -224,8 +237,12 @@ window.addEventListener('message', message => {
if (callback) {
callback(popup);
}
} else if (payload.type == "menuItemClicked" && isMenuItemClickedEvent(payload.data)) {
const callback = menuCallbacks.get(payload.data.menuItem);
if (callback) {
callback(payload.data.menuItem)
}
}
}
// ...