Merge branch 'develop' of github.com:thecodingmachine/workadventure into windows-focus-blur-camera

This commit is contained in:
David Négrier 2020-11-06 17:36:43 +01:00
commit 00b83ae349
22 changed files with 324 additions and 206 deletions

View file

@ -2,47 +2,90 @@ import {HtmlUtils} from "./HtmlUtils";
export type CoWebsiteStateChangedCallback = () => void;
export class CoWebsiteManager {
enum iframeStates {
closed = 1,
loading, // loading an iframe can be slow, so we show some placeholder until it is ready
opened,
}
private static observers = new Array<CoWebsiteStateChangedCallback>();
const cowebsiteDivId = "cowebsite"; // the id of the parent div of the iframe.
const animationTime = 500; //time used by the css transitions, in ms.
public static loadCoWebsite(url: string): void {
const cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("cowebsite");
class CoWebsiteManager {
private opened: iframeStates = iframeStates.closed;
private observers = new Array<CoWebsiteStateChangedCallback>();
private close(): HTMLDivElement {
const cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDivId);
cowebsiteDiv.classList.remove('loaded'); //edit the css class to trigger the transition
cowebsiteDiv.classList.add('hidden');
this.opened = iframeStates.closed;
return cowebsiteDiv;
}
private load(): HTMLDivElement {
const cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDivId);
cowebsiteDiv.classList.remove('hidden'); //edit the css class to trigger the transition
cowebsiteDiv.classList.add('loading');
this.opened = iframeStates.loading;
return cowebsiteDiv;
}
private open(): HTMLDivElement {
const cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDivId);
cowebsiteDiv.classList.remove('loading', 'hidden'); //edit the css class to trigger the transition
this.opened = iframeStates.opened;
return cowebsiteDiv;
}
public loadCoWebsite(url: string): void {
const cowebsiteDiv = this.load();
cowebsiteDiv.innerHTML = '';
const iframe = document.createElement('iframe');
iframe.id = 'cowebsite-iframe';
iframe.src = url;
const onloadPromise = new Promise((resolve) => {
iframe.onload = () => resolve();
});
cowebsiteDiv.appendChild(iframe);
//iframe.onload = () => {
// onload can be long to trigger. Maybe we should display the website, whatever happens, after 1 second?
CoWebsiteManager.fire();
//}
const onTimeoutPromise = new Promise((resolve) => {
setTimeout(() => resolve(), 2000);
});
Promise.race([onloadPromise, onTimeoutPromise]).then(() => {
this.open();
setTimeout(() => {
this.fire();
}, animationTime)
});
}
/**
* Just like loadCoWebsite but the div can be filled by the user.
*/
public static insertCoWebsite(callback: (cowebsite: HTMLDivElement) => void): void {
const cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("cowebsite");
cowebsiteDiv.innerHTML = '';
callback(cowebsiteDiv);
//iframe.onload = () => {
// onload can be long to trigger. Maybe we should display the website, whatever happens, after 1 second?
CoWebsiteManager.fire();
//}
public insertCoWebsite(callback: (cowebsite: HTMLDivElement) => Promise<void>): void {
const cowebsiteDiv = this.load();
callback(cowebsiteDiv).then(() => {
this.open();
setTimeout(() => {
this.fire();
}, animationTime)
});
}
public static closeCoWebsite(): void {
const cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("cowebsite");
cowebsiteDiv.innerHTML = '';
CoWebsiteManager.fire();
public closeCoWebsite(): Promise<void> {
return new Promise((resolve, reject) => {
const cowebsiteDiv = this.close();
this.fire();
setTimeout(() => {
resolve();
setTimeout(() => cowebsiteDiv.innerHTML = '', 500)
}, animationTime)
});
}
public static getGameSize(): {width: number, height: number} {
const hasChildren = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("cowebsite").children.length > 0;
if (hasChildren === false) {
public getGameSize(): {width: number, height: number} {
if (this.opened !== iframeStates.opened) {
return {
width: window.innerWidth,
height: window.innerHeight
@ -61,13 +104,15 @@ export class CoWebsiteManager {
}
}
public static onStateChange(observer: CoWebsiteStateChangedCallback) {
CoWebsiteManager.observers.push(observer);
public onStateChange(observer: CoWebsiteStateChangedCallback) {
this.observers.push(observer);
}
private static fire(): void {
for (const callback of CoWebsiteManager.observers) {
private fire(): void {
for (const callback of this.observers) {
callback();
}
}
}
export const coWebsiteManager = new CoWebsiteManager();

View file

@ -1,6 +1,6 @@
import {CoWebsiteManager} from "./CoWebsiteManager";
import {JITSI_URL} from "../Enum/EnvironmentVariable";
import {mediaManager} from "./MediaManager";
import {coWebsiteManager} from "./CoWebsiteManager";
declare const window:any; // eslint-disable-line @typescript-eslint/no-explicit-any
const interfaceConfig = {
@ -31,9 +31,9 @@ class JitsiFactory {
private videoCallback = this.onVideoChange.bind(this);
public start(roomName: string, playerName:string, jwt?: string): void {
CoWebsiteManager.insertCoWebsite((cowebsiteDiv => {
coWebsiteManager.insertCoWebsite((cowebsiteDiv => {
const domain = JITSI_URL;
const options = {
const options: any = { // eslint-disable-line @typescript-eslint/no-explicit-any
roomName: roomName,
jwt: jwt,
width: "100%",
@ -49,19 +49,23 @@ class JitsiFactory {
if (!options.jwt) {
delete options.jwt;
}
this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options);
this.jitsiApi.executeCommand('displayName', playerName);
return new Promise((resolve) => {
options.onload = () => resolve(); //we want for the iframe to be loaded before triggering animations.
this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options);
this.jitsiApi.executeCommand('displayName', playerName);
this.jitsiApi.addListener('audioMuteStatusChanged', this.audioCallback);
this.jitsiApi.addListener('videoMuteStatusChanged', this.videoCallback);
this.jitsiApi.addListener('audioMuteStatusChanged', this.audioCallback);
this.jitsiApi.addListener('videoMuteStatusChanged', this.videoCallback);
});
}));
}
public stop(): void {
public async stop(): Promise<void> {
await coWebsiteManager.closeCoWebsite();
this.jitsiApi.removeListener('audioMuteStatusChanged', this.audioCallback);
this.jitsiApi.removeListener('videoMuteStatusChanged', this.videoCallback);
this.jitsiApi?.dispose();
CoWebsiteManager.closeCoWebsite();
}
private onAudioChange({muted}: {muted: boolean}): void {