partey_workadventure/front/src/iframe_api.ts

248 lines
7.7 KiB
TypeScript
Raw Normal View History

import {ChatEvent, isChatEvent} from "./Api/Events/ChatEvent";
import {isIframeEventWrapper} from "./Api/Events/IframeEvent";
import {isUserInputChatEvent, UserInputChatEvent} from "./Api/Events/UserInputChatEvent";
import {Subject} from "rxjs";
import {EnterLeaveEvent, isEnterLeaveEvent} from "./Api/Events/EnterLeaveEvent";
import {OpenPopupEvent} from "./Api/Events/OpenPopupEvent";
2021-03-09 18:05:07 +01:00
import {isButtonClickedEvent} from "./Api/Events/ButtonClickedEvent";
2021-05-16 14:04:45 +02:00
import {ClosePopupEvent, isClosePopupEvent} from "./Api/Events/ClosePopupEvent";
import {OpenTabEvent} from "./Api/Events/OpenTabEvent";
import {GoToPageEvent} from "./Api/Events/GoToPageEvent";
import {OpenCoWebSiteEvent} from "./Api/Events/OpenCoWebSiteEvent";
interface WorkAdventureApi {
sendChatMessage(message: string, author: string): void;
onChatMessage(callback: (message: string) => void): void;
2021-05-16 14:04:45 +02:00
closeChatMessage(): void;
onEnterZone(name: string, callback: () => void): void;
onLeaveZone(name: string, callback: () => void): void;
2021-05-16 14:04:45 +02:00
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[], input: boolean): Popup;
openTab(url: string): void;
goToPage(url: string): void;
openCoWebSite(url: string): void;
closeCoWebSite(): void;
2021-05-16 14:04:45 +02:00
disablePlayerControl(): void;
restorePlayerControl(): void;
displayBubble(): void;
removeBubble(): void;
}
declare global {
// eslint-disable-next-line no-var
var WA: WorkAdventureApi
}
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 popups: Map<number, Popup> = new Map<number, Popup>();
const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<number, Map<number, ButtonClickedCallback>>();
2021-03-09 18:05:07 +01:00
let popupId = 0;
interface ButtonDescriptor {
/**
* The label of the button
*/
label: string,
/**
* The type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled"
*/
2021-05-16 14:04:45 +02:00
className?: "normal" | "primary" | "success" | "warning" | "error" | "disabled",
/**
* Callback called if the button is pressed
*/
callback: ButtonClickedCallback,
}
class Popup {
2021-05-16 14:04:45 +02:00
inputValue: string;
constructor(private id: number) {
2021-05-16 14:04:45 +02:00
this.inputValue = '';
}
/**
* Closes the popup
*/
public close(): void {
window.parent.postMessage({
'type': 'closePopup',
'data': {
'popupId': this.id,
2021-05-16 14:04:45 +02:00
'inputValue': this.inputValue,
} as ClosePopupEvent
}, '*');
}
}
window.WA = {
/**
* Send a message in the chat.
* Only the local user will receive this message.
*/
sendChatMessage(message: string, author: string) {
window.parent.postMessage({
'type': 'chat',
'data': {
'message': message,
'author': author
} as ChatEvent
}, '*');
},
2021-05-16 14:04:45 +02:00
closeChatMessage(): void {
2021-05-16 10:22:05 +02:00
window.parent.postMessage({
2021-05-16 14:04:45 +02:00
"type": 'closeChatMessage'
}, '*');
2021-05-16 10:22:05 +02:00
},
2021-05-16 14:04:45 +02:00
disablePlayerControl(): void {
window.parent.postMessage({'type': 'disablePlayerControl'}, '*');
},
2021-05-16 14:04:45 +02:00
restorePlayerControl(): void {
window.parent.postMessage({'type': 'restorePlayerControl'}, '*');
},
2021-05-16 14:04:45 +02:00
displayBubble(): void {
window.parent.postMessage({'type': 'displayBubble'}, '*');
},
2021-05-16 14:04:45 +02:00
removeBubble(): void {
window.parent.postMessage({'type': 'removeBubble'}, '*');
},
2021-05-16 14:04:45 +02:00
openTab(url: string): void {
window.parent.postMessage({
2021-05-16 14:04:45 +02:00
"type": 'openTab',
"data": {
url
} as OpenTabEvent
2021-05-16 14:04:45 +02:00
}, '*');
},
2021-05-16 14:04:45 +02:00
goToPage(url: string): void {
window.parent.postMessage({
2021-05-16 14:04:45 +02:00
"type": 'goToPage',
"data": {
url
} as GoToPageEvent
2021-05-16 14:04:45 +02:00
}, '*');
},
2021-05-16 14:04:45 +02:00
openCoWebSite(url: string): void {
window.parent.postMessage({
2021-05-16 14:04:45 +02:00
"type": 'openCoWebSite',
"data": {
url
} as OpenCoWebSiteEvent
2021-05-16 14:04:45 +02:00
}, '*');
},
2021-05-16 14:04:45 +02:00
closeCoWebSite(): void {
window.parent.postMessage({
2021-05-16 14:04:45 +02:00
"type": 'closeCoWebSite'
}, '*');
},
2021-05-16 14:04:45 +02:00
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[], input: boolean = false): Popup {
popupId++;
const popup = new Popup(popupId);
const btnMap = new Map<number, () => void>();
popupCallbacks.set(popupId, btnMap);
let id = 0;
2021-05-16 14:04:45 +02:00
for(const button of buttons) {
const callback = button.callback;
2021-05-16 14:04:45 +02:00
if(callback) {
btnMap.set(id, () => {
callback(popup);
});
}
id++;
}
2021-05-16 14:04:45 +02:00
if(input) {
this.disablePlayerControl();
}
window.parent.postMessage({
'type': 'openPopup',
'data': {
popupId,
targetObject,
message,
buttons: buttons.map((button) => {
return {
label: button.label,
className: button.className
};
2021-05-16 14:04:45 +02:00
}),
input: input
} as OpenPopupEvent
}, '*');
popups.set(popupId, popup)
return popup;
},
/**
* Listen to messages sent by the local user, in the chat.
*/
onChatMessage(callback: ChatMessageCallback): void {
userInputChatStream.subscribe((userInputChatEvent) => {
callback(userInputChatEvent.message);
});
},
onEnterZone(name: string, callback: () => void): void {
let subject = enterStreams.get(name);
2021-05-16 14:04:45 +02:00
if(subject === undefined) {
subject = new Subject<EnterLeaveEvent>();
enterStreams.set(name, subject);
}
subject.subscribe(callback);
},
onLeaveZone(name: string, callback: () => void): void {
let subject = leaveStreams.get(name);
2021-05-16 14:04:45 +02:00
if(subject === undefined) {
subject = new Subject<EnterLeaveEvent>();
leaveStreams.set(name, subject);
}
subject.subscribe(callback);
},
}
window.addEventListener('message', message => {
2021-05-16 14:04:45 +02:00
if(message.source !== window.parent) {
return; // Skip message in this event listener
}
const payload = message.data;
console.log(payload);
2021-05-16 14:04:45 +02:00
if(isIframeEventWrapper(payload)) {
const payloadData = payload.data;
2021-05-16 14:04:45 +02:00
if(payload.type === 'userInputChat' && isUserInputChatEvent(payloadData)) {
userInputChatStream.next(payloadData);
2021-05-16 14:04:45 +02:00
} else if(payload.type === 'enterEvent' && isEnterLeaveEvent(payloadData)) {
enterStreams.get(payloadData.name)?.next();
2021-05-16 14:04:45 +02:00
} else if(payload.type === 'leaveEvent' && isEnterLeaveEvent(payloadData)) {
leaveStreams.get(payloadData.name)?.next();
2021-05-16 14:04:45 +02:00
} else if(payload.type === 'buttonClickedEvent' && isButtonClickedEvent(payloadData)) {
2021-03-09 18:05:07 +01:00
const callback = popupCallbacks.get(payloadData.popupId)?.get(payloadData.buttonId);
const popup = popups.get(payloadData.popupId);
2021-05-16 14:04:45 +02:00
if(popup === undefined) {
throw new Error('Could not find popup with ID "' + payloadData.popupId + '"');
}
2021-05-16 14:04:45 +02:00
if(callback) {
popup.inputValue = payloadData.inputValue;
callback(popup);
2021-03-09 18:05:07 +01:00
}
}
}
// ...
});