add input popup

This commit is contained in:
_Bastler 2021-05-16 14:04:45 +02:00
parent c6eee39057
commit c7623300f2
6 changed files with 81 additions and 60 deletions

View File

@ -4,6 +4,8 @@ export const isButtonClickedEvent =
new tg.IsInterface().withProperties({ new tg.IsInterface().withProperties({
popupId: tg.isNumber, popupId: tg.isNumber,
buttonId: tg.isNumber, buttonId: tg.isNumber,
input : tg.isBoolean,
inputValue : tg.isString,
}).get(); }).get();
/** /**
* A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property. * A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property.

View File

@ -3,6 +3,7 @@ import * as tg from "generic-type-guard";
export const isClosePopupEvent = export const isClosePopupEvent =
new tg.IsInterface().withProperties({ new tg.IsInterface().withProperties({
popupId: tg.isNumber, popupId: tg.isNumber,
inputValue : tg.isString,
}).get(); }).get();
/** /**

View File

@ -11,7 +11,8 @@ export const isOpenPopupEvent =
popupId: tg.isNumber, popupId: tg.isNumber,
targetObject: tg.isString, targetObject: tg.isString,
message: tg.isString, message: tg.isString,
buttons: tg.isArray(isButtonDescriptor) buttons: tg.isArray(isButtonDescriptor),
input: tg.isBoolean
}).get(); }).get();
/** /**

View File

@ -222,12 +222,14 @@ class IframeListener {
}); });
} }
sendButtonClickedEvent(popupId: number, buttonId: number): void { sendButtonClickedEvent(popupId: number, buttonId: number, input : boolean, inputValue : string | null): void {
this.postMessage({ this.postMessage({
'type': 'buttonClickedEvent', 'type': 'buttonClickedEvent',
'data': { 'data': {
popupId, popupId,
buttonId buttonId,
input,
inputValue,
} as ButtonClickedEvent } as ButtonClickedEvent
}); });
} }

View File

@ -794,9 +794,12 @@ export class GameScene extends ResizableScene implements CenterListener {
return; return;
} }
const escapedMessage = HtmlUtils.escapeHtml(openPopupEvent.message); const escapedMessage = HtmlUtils.escapeHtml(openPopupEvent.message);
let html = `<div id="container" hidden><div class="nes-container with-title is-centered"> let html = `<div id="container" hidden><div class="nes-container with-title is-centered">`;
${escapedMessage} html += escapedMessage;
</div> `; if (openPopupEvent.input) {
html += `<input id="popupinput-${openPopupEvent.popupId}" class="nes-input" \>`
}
html += `</div> `;
const buttonContainer = `<div class="buttonContainer"</div>`; const buttonContainer = `<div class="buttonContainer"</div>`;
html += buttonContainer; html += buttonContainer;
let id = 0; let id = 0;
@ -818,12 +821,15 @@ ${escapedMessage}
}, 100); }, 100);
id = 0; id = 0;
let inputElement : HTMLInputElement;
if (openPopupEvent.input) {
inputElement = HtmlUtils.getElementByIdOrFail<HTMLInputElement>(`popupinput-${openPopupEvent.popupId}`);
}
for (const button of openPopupEvent.buttons) { for (const button of openPopupEvent.buttons) {
const button = HtmlUtils.getElementByIdOrFail<HTMLButtonElement>(`popup-${openPopupEvent.popupId}-${id}`); const button = HtmlUtils.getElementByIdOrFail<HTMLButtonElement>(`popup-${openPopupEvent.popupId}-${id}`);
const btnId = id; const btnId = id;
button.onclick = () => { button.onclick = () => {
iframeListener.sendButtonClickedEvent(openPopupEvent.popupId, btnId); iframeListener.sendButtonClickedEvent(openPopupEvent.popupId, btnId, openPopupEvent.input, openPopupEvent.input ? inputElement.value : '');
button.disabled = true;
} }
id++; id++;
} }

View File

@ -5,7 +5,7 @@ import {Subject} from "rxjs";
import {EnterLeaveEvent, isEnterLeaveEvent} from "./Api/Events/EnterLeaveEvent"; import {EnterLeaveEvent, isEnterLeaveEvent} from "./Api/Events/EnterLeaveEvent";
import {OpenPopupEvent} from "./Api/Events/OpenPopupEvent"; import {OpenPopupEvent} from "./Api/Events/OpenPopupEvent";
import {isButtonClickedEvent} from "./Api/Events/ButtonClickedEvent"; import {isButtonClickedEvent} from "./Api/Events/ButtonClickedEvent";
import {ClosePopupEvent} from "./Api/Events/ClosePopupEvent"; import {ClosePopupEvent, isClosePopupEvent} from "./Api/Events/ClosePopupEvent";
import {OpenTabEvent} from "./Api/Events/OpenTabEvent"; import {OpenTabEvent} from "./Api/Events/OpenTabEvent";
import {GoToPageEvent} from "./Api/Events/GoToPageEvent"; import {GoToPageEvent} from "./Api/Events/GoToPageEvent";
import {OpenCoWebSiteEvent} from "./Api/Events/OpenCoWebSiteEvent"; import {OpenCoWebSiteEvent} from "./Api/Events/OpenCoWebSiteEvent";
@ -13,18 +13,18 @@ import {OpenCoWebSiteEvent} from "./Api/Events/OpenCoWebSiteEvent";
interface WorkAdventureApi { interface WorkAdventureApi {
sendChatMessage(message: string, author: string): void; sendChatMessage(message: string, author: string): void;
onChatMessage(callback: (message: string) => void): void; onChatMessage(callback: (message: string) => void): void;
closeChatMessage() : void; closeChatMessage(): void;
onEnterZone(name: string, callback: () => void): void; onEnterZone(name: string, callback: () => void): void;
onLeaveZone(name: string, callback: () => void): void; onLeaveZone(name: string, callback: () => void): void;
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup; openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[], input: boolean): Popup;
openTab(url : string): void; openTab(url: string): void;
goToPage(url : string): void; goToPage(url: string): void;
openCoWebSite(url : string): void; openCoWebSite(url: string): void;
closeCoWebSite(): void; closeCoWebSite(): void;
disablePlayerControl() : void; disablePlayerControl(): void;
restorePlayerControl() : void; restorePlayerControl(): void;
displayBubble() : void; displayBubble(): void;
removeBubble() : void; removeBubble(): void;
} }
declare global { declare global {
@ -51,7 +51,7 @@ interface ButtonDescriptor {
/** /**
* The type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled" * The type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled"
*/ */
className?: "normal"|"primary"|"success"|"warning"|"error"|"disabled", className?: "normal" | "primary" | "success" | "warning" | "error" | "disabled",
/** /**
* Callback called if the button is pressed * Callback called if the button is pressed
*/ */
@ -59,7 +59,10 @@ interface ButtonDescriptor {
} }
class Popup { class Popup {
inputValue: string;
constructor(private id: number) { constructor(private id: number) {
this.inputValue = '';
} }
/** /**
@ -70,6 +73,7 @@ class Popup {
'type': 'closePopup', 'type': 'closePopup',
'data': { 'data': {
'popupId': this.id, 'popupId': this.id,
'inputValue': this.inputValue,
} as ClosePopupEvent } as ClosePopupEvent
}, '*'); }, '*');
} }
@ -89,69 +93,69 @@ window.WA = {
} as ChatEvent } as ChatEvent
}, '*'); }, '*');
}, },
closeChatMessage() : void{ closeChatMessage(): void {
window.parent.postMessage({ window.parent.postMessage({
"type" : 'closeChatMessage' "type": 'closeChatMessage'
},'*'); }, '*');
}, },
disablePlayerControl() : void { disablePlayerControl(): void {
window.parent.postMessage({'type' : 'disablePlayerControl'},'*'); window.parent.postMessage({'type': 'disablePlayerControl'}, '*');
}, },
restorePlayerControl() : void { restorePlayerControl(): void {
window.parent.postMessage({'type' : 'restorePlayerControl'},'*'); window.parent.postMessage({'type': 'restorePlayerControl'}, '*');
}, },
displayBubble() : void { displayBubble(): void {
window.parent.postMessage({'type' : 'displayBubble'},'*'); window.parent.postMessage({'type': 'displayBubble'}, '*');
}, },
removeBubble() : void { removeBubble(): void {
window.parent.postMessage({'type' : 'removeBubble'},'*'); window.parent.postMessage({'type': 'removeBubble'}, '*');
}, },
openTab(url : string) : void{ openTab(url: string): void {
window.parent.postMessage({ window.parent.postMessage({
"type" : 'openTab', "type": 'openTab',
"data" : { "data": {
url url
} as OpenTabEvent } as OpenTabEvent
},'*'); }, '*');
}, },
goToPage(url : string) : void{ goToPage(url: string): void {
window.parent.postMessage({ window.parent.postMessage({
"type" : 'goToPage', "type": 'goToPage',
"data" : { "data": {
url url
} as GoToPageEvent } as GoToPageEvent
},'*'); }, '*');
}, },
openCoWebSite(url : string) : void{ openCoWebSite(url: string): void {
window.parent.postMessage({ window.parent.postMessage({
"type" : 'openCoWebSite', "type": 'openCoWebSite',
"data" : { "data": {
url url
} as OpenCoWebSiteEvent } as OpenCoWebSiteEvent
},'*'); }, '*');
}, },
closeCoWebSite() : void{ closeCoWebSite(): void {
window.parent.postMessage({ window.parent.postMessage({
"type" : 'closeCoWebSite' "type": 'closeCoWebSite'
},'*'); }, '*');
}, },
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup { openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[], input: boolean = false): Popup {
popupId++; popupId++;
const popup = new Popup(popupId); const popup = new Popup(popupId);
const btnMap = new Map<number, () => void>(); const btnMap = new Map<number, () => void>();
popupCallbacks.set(popupId, btnMap); popupCallbacks.set(popupId, btnMap);
let id = 0; let id = 0;
for (const button of buttons) { for(const button of buttons) {
const callback = button.callback; const callback = button.callback;
if (callback) { if(callback) {
btnMap.set(id, () => { btnMap.set(id, () => {
callback(popup); callback(popup);
}); });
@ -159,6 +163,9 @@ window.WA = {
id++; id++;
} }
if(input) {
this.disablePlayerControl();
}
window.parent.postMessage({ window.parent.postMessage({
'type': 'openPopup', 'type': 'openPopup',
@ -171,7 +178,8 @@ window.WA = {
label: button.label, label: button.label,
className: button.className className: button.className
}; };
}) }),
input: input
} as OpenPopupEvent } as OpenPopupEvent
}, '*'); }, '*');
@ -188,7 +196,7 @@ window.WA = {
}, },
onEnterZone(name: string, callback: () => void): void { onEnterZone(name: string, callback: () => void): void {
let subject = enterStreams.get(name); let subject = enterStreams.get(name);
if (subject === undefined) { if(subject === undefined) {
subject = new Subject<EnterLeaveEvent>(); subject = new Subject<EnterLeaveEvent>();
enterStreams.set(name, subject); enterStreams.set(name, subject);
} }
@ -196,7 +204,7 @@ window.WA = {
}, },
onLeaveZone(name: string, callback: () => void): void { onLeaveZone(name: string, callback: () => void): void {
let subject = leaveStreams.get(name); let subject = leaveStreams.get(name);
if (subject === undefined) { if(subject === undefined) {
subject = new Subject<EnterLeaveEvent>(); subject = new Subject<EnterLeaveEvent>();
leaveStreams.set(name, subject); leaveStreams.set(name, subject);
} }
@ -205,7 +213,7 @@ window.WA = {
} }
window.addEventListener('message', message => { window.addEventListener('message', message => {
if (message.source !== window.parent) { if(message.source !== window.parent) {
return; // Skip message in this event listener return; // Skip message in this event listener
} }
@ -213,21 +221,22 @@ window.addEventListener('message', message => {
console.log(payload); console.log(payload);
if (isIframeEventWrapper(payload)) { if(isIframeEventWrapper(payload)) {
const payloadData = payload.data; const payloadData = payload.data;
if (payload.type === 'userInputChat' && isUserInputChatEvent(payloadData)) { if(payload.type === 'userInputChat' && isUserInputChatEvent(payloadData)) {
userInputChatStream.next(payloadData); userInputChatStream.next(payloadData);
} else if (payload.type === 'enterEvent' && isEnterLeaveEvent(payloadData)) { } else if(payload.type === 'enterEvent' && isEnterLeaveEvent(payloadData)) {
enterStreams.get(payloadData.name)?.next(); enterStreams.get(payloadData.name)?.next();
} else if (payload.type === 'leaveEvent' && isEnterLeaveEvent(payloadData)) { } else if(payload.type === 'leaveEvent' && isEnterLeaveEvent(payloadData)) {
leaveStreams.get(payloadData.name)?.next(); leaveStreams.get(payloadData.name)?.next();
} else if (payload.type === 'buttonClickedEvent' && isButtonClickedEvent(payloadData)) { } else if(payload.type === 'buttonClickedEvent' && isButtonClickedEvent(payloadData)) {
const callback = popupCallbacks.get(payloadData.popupId)?.get(payloadData.buttonId); const callback = popupCallbacks.get(payloadData.popupId)?.get(payloadData.buttonId);
const popup = popups.get(payloadData.popupId); const popup = popups.get(payloadData.popupId);
if (popup === undefined) { if(popup === undefined) {
throw new Error('Could not find popup with ID "'+payloadData.popupId+'"'); throw new Error('Could not find popup with ID "' + payloadData.popupId + '"');
} }
if (callback) { if(callback) {
popup.inputValue = payloadData.inputValue;
callback(popup); callback(popup);
} }
} }