Merge branch 'iframe_api' of https://github.com/thecodingmachine/workadventure into FTUEPopup

* 'iframe_api' of https://github.com/thecodingmachine/workadventure:
  Removing closeOnClick as it is not implemented
  Adding a Popup object with a close() method on it.
This commit is contained in:
DESKTOP-FMM8UI0\CLV 2021-03-10 09:00:47 +01:00
commit 5e4940dba6
6 changed files with 87 additions and 44 deletions

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isClosePopupEvent =
new tg.IsInterface().withProperties({
popupId: tg.isNumber,
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type ClosePopupEvent = tg.GuardedType<typeof isClosePopupEvent>;

View File

@ -3,8 +3,7 @@ import * as tg from "generic-type-guard";
const isButtonDescriptor =
new tg.IsInterface().withProperties({
label: tg.isString,
className: tg.isOptional(tg.isString),
closeOnClick: tg.isOptional(tg.isBoolean)
className: tg.isOptional(tg.isString)
}).get();
export const isOpenPopupEvent =

View File

@ -7,6 +7,7 @@ import {HtmlUtils} from "../WebRtc/HtmlUtils";
import {EnterLeaveEvent} from "./Events/EnterLeaveEvent";
import {isOpenPopupEvent, OpenPopupEvent} from "./Events/OpenPopupEvent";
import {ButtonClickedEvent} from "./Events/ButtonClickedEvent";
import {ClosePopupEvent, isClosePopupEvent} from "./Events/ClosePopupEvent";
@ -21,6 +22,9 @@ class IframeListener {
private readonly _openPopupStream: Subject<OpenPopupEvent> = new Subject();
public readonly openPopupStream = this._openPopupStream.asObservable();
private readonly _closePopupStream: Subject<ClosePopupEvent> = new Subject();
public readonly closePopupStream = this._closePopupStream.asObservable();
private readonly iframes = new Set<HTMLIFrameElement>();
private readonly scripts = new Map<string, HTMLIFrameElement>();
@ -46,6 +50,8 @@ class IframeListener {
this._chatStream.next(payload.data);
} else if (payload.type === 'openPopup' && isOpenPopupEvent(payload.data)) {
this._openPopupStream.next(payload.data);
} else if (payload.type === 'closePopup' && isClosePopupEvent(payload.data)) {
this._closePopupStream.next(payload.data);
}
}

View File

@ -777,7 +777,6 @@ ${escapedMessage}
const btnId = id;
button.onclick = () => {
iframeListener.sendButtonClickedEvent(openPopupEvent.popupId, btnId);
console.log('BUTTON CLICKED', btnId);
}
id++;
}
@ -791,34 +790,24 @@ ${escapedMessage}
this.popUpElements.set(openPopupEvent.popupId, domElement);
});
/*this.gameMap.onPropertyChange('inGameConsoleMessage', (newValue, oldValue, allProps) => {
if (newValue !== undefined) {
this.popUpElement?.destroy();
this.popUpElement = this.add.dom(2100, 150).createFromHTML(newValue as string);
this.popUpElement.scale = 0;
this.tweens.add({
targets : this.popUpElement ,
scale : 1,
ease : "EaseOut",
duration : 400,
});
this.popUpElement.setClassName("popUpElement");
} else {
this.tweens.add({
targets : this.popUpElement ,
scale : 0,
ease : "EaseOut",
duration : 400,
onComplete : () => {
this.popUpElement?.destroy();
this.popUpElement = undefined;
},
});
iframeListener.closePopupStream.subscribe((closePopupEvent) => {
const popUpElement = this.popUpElements.get(closePopupEvent.popupId);
if (popUpElement === undefined) {
console.error('Could not close popup with ID ', closePopupEvent.popupId,'. Maybe it has already been closed?');
}
});*/
this.tweens.add({
targets : popUpElement ,
scale : 0,
ease : "EaseOut",
duration : 400,
onComplete : () => {
popUpElement?.destroy();
this.popUpElements.delete(closePopupEvent.popupId);
},
});
});
}
private onMapExit(exitKey: string) {

View File

@ -5,13 +5,14 @@ import {Subject} from "rxjs";
import {EnterLeaveEvent, isEnterLeaveEvent} from "./Api/Events/EnterLeaveEvent";
import {OpenPopupEvent} from "./Api/Events/OpenPopupEvent";
import {isButtonClickedEvent} from "./Api/Events/ButtonClickedEvent";
import {ClosePopupEvent} from "./Api/Events/ClosePopupEvent";
interface WorkAdventureApi {
sendChatMessage(message: string, author: string): void;
onChatMessage(callback: (message: string) => void): void;
onEnterZone(name: string, callback: () => void): void;
onLeaveZone(name: string, callback: () => void): void;
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): number;
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup;
}
declare global {
@ -20,11 +21,13 @@ declare global {
}
type ChatMessageCallback = (message: string) => void;
type ButtonClickedCallback = (popup: Popup) => void;
const userInputChatStream: Subject<UserInputChatEvent> = new Subject();
const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
const leaveStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
const popupCallbacks: Map<number, Map<number, () => void>> = new Map<number, Map<number, () => void>>();
const popups: Map<number, Popup> = new Map<number, Popup>();
const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<number, Map<number, ButtonClickedCallback>>();
let popupId = 0;
interface ButtonDescriptor {
@ -39,11 +42,24 @@ interface ButtonDescriptor {
/**
* Callback called if the button is pressed
*/
callback?: () => void,
callback: ButtonClickedCallback,
}
class Popup {
constructor(private id: number) {
}
/**
* If set to true, the popup is closed when the button is clicked
* Closes the popup
*/
closeOnClick?: boolean
public close(): void {
window.parent.postMessage({
'type': 'closePopup',
'data': {
'popupId': this.id,
} as ClosePopupEvent
}, '*');
}
}
@ -61,8 +77,25 @@ window.WA = {
} as ChatEvent
}, '*');
},
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): number {
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup {
popupId++;
const popup = new Popup(popupId);
const btnMap = new Map<number, () => void>();
popupCallbacks.set(popupId, btnMap);
let id = 0;
for (const button of buttons) {
const callback = button.callback;
if (callback) {
btnMap.set(id, () => {
callback(popup);
});
}
id++;
}
window.parent.postMessage({
'type': 'openPopup',
'data': {
@ -72,13 +105,14 @@ window.WA = {
buttons: buttons.map((button) => {
return {
label: button.label,
className: button.className,
closeOnClick: button.closeOnClick
className: button.className
};
})
} as OpenPopupEvent
}, '*');
return popupId;
popups.set(popupId, popup)
return popup;
},
/**
* Listen to messages sent by the local user, in the chat.
@ -125,8 +159,12 @@ window.addEventListener('message', message => {
leaveStreams.get(payloadData.name)?.next();
} else if (payload.type === 'buttonClickedEvent' && isButtonClickedEvent(payloadData)) {
const callback = popupCallbacks.get(payloadData.popupId)?.get(payloadData.buttonId);
const popup = popups.get(payloadData.popupId);
if (popup === undefined) {
throw new Error('Could not find popup with ID "'+payloadData.popupId+'"');
}
if (callback) {
callback();
callback(popup);
}
}
}

View File

@ -19,20 +19,20 @@ WA.onEnterZone('notExist', () => {
WA.sendChatMessage("YOU SHOULD NEVER SEE THIS", 'Poly Parrot');
})
let popupId;
WA.onEnterZone('popupZone', () => {
popupId = WA.openPopup('foobar', 'This is a test message. Hi!', [
WA.openPopup('foobar', 'This is a test message. Hi!', [
{
label: "Close",
className: "normal",
closeOnClick: true
callback: (popup) => {
popup.close();
}
},
{
label: "Next",
className: "success",
callback: () => {
console.log('BUTTON CLICKED')
callback: (popup) => {
popup.close();
}
}
])