Fix cowebsite closing on fast opening/closing

This commit is contained in:
Alexis Faizeau 2022-02-08 11:19:29 +01:00
parent 7334d59c4f
commit f5f71f32ee
5 changed files with 97 additions and 155 deletions

View File

@ -10,13 +10,9 @@
function closeCoWebsite() { function closeCoWebsite() {
if ($highlightedEmbedScreen?.type === "cowebsite") { if ($highlightedEmbedScreen?.type === "cowebsite") {
if ($highlightedEmbedScreen.embed.closable) { if ($highlightedEmbedScreen.embed.closable) {
coWebsiteManager.closeCoWebsite($highlightedEmbedScreen.embed).catch(() => { coWebsiteManager.closeCoWebsite($highlightedEmbedScreen.embed);
console.error("Error during co-website highlighted closing");
});
} else { } else {
coWebsiteManager.unloadCoWebsite($highlightedEmbedScreen.embed).catch(() => { coWebsiteManager.unloadCoWebsite($highlightedEmbedScreen.embed);
console.error("Error during co-website highlighted unloading");
});
} }
} }
} }

View File

@ -9,17 +9,12 @@ import { get } from "svelte/store";
import { ON_ACTION_TRIGGER_BUTTON, ON_ICON_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager"; import { ON_ACTION_TRIGGER_BUTTON, ON_ICON_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager";
import type { ITiledMapLayer } from "../Map/ITiledMap"; import type { ITiledMapLayer } from "../Map/ITiledMap";
import { GameMapProperties } from "./GameMapProperties"; import { GameMapProperties } from "./GameMapProperties";
import type CancelablePromise from "cancelable-promise";
enum OpenCoWebsiteState {
ASLEEP,
OPENED,
MUST_BE_CLOSE,
}
interface OpenCoWebsite { interface OpenCoWebsite {
actionId: string; actionId: string;
coWebsite?: CoWebsite; coWebsite?: CoWebsite;
state: OpenCoWebsiteState; loadPromise?: CancelablePromise;
} }
export class GameMapPropertiesListener { export class GameMapPropertiesListener {
@ -106,34 +101,16 @@ export class GameMapPropertiesListener {
return; return;
} }
this.coWebsitesOpenByLayer.set(layer, { const coWebsiteOpen: OpenCoWebsite = {
actionId: actionId, actionId: actionId,
coWebsite: undefined, };
state: OpenCoWebsiteState.ASLEEP,
}); this.coWebsitesOpenByLayer.set(layer, coWebsiteOpen);
const loadCoWebsiteFunction = (coWebsite: CoWebsite) => { const loadCoWebsiteFunction = (coWebsite: CoWebsite) => {
coWebsiteManager coWebsiteOpen.loadPromise = coWebsiteManager.loadCoWebsite(coWebsite).catch(() => {
.loadCoWebsite(coWebsite) console.error("Error during loading a co-website: " + coWebsite.url);
.then((coWebsite) => { });
const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer);
if (coWebsiteOpen && coWebsiteOpen.state === OpenCoWebsiteState.MUST_BE_CLOSE) {
coWebsiteManager.closeCoWebsite(coWebsite).catch(() => {
console.error("Error during a co-website closing");
});
this.coWebsitesOpenByLayer.delete(layer);
this.coWebsitesActionTriggerByLayer.delete(layer);
} else {
this.coWebsitesOpenByLayer.set(layer, {
actionId,
coWebsite,
state: OpenCoWebsiteState.OPENED,
});
}
})
.catch(() => {
console.error("Error during loading a co-website: " + coWebsite.url);
});
layoutManagerActionStore.removeAction(actionId); layoutManagerActionStore.removeAction(actionId);
}; };
@ -149,6 +126,8 @@ export class GameMapPropertiesListener {
false false
); );
coWebsiteOpen.coWebsite = coWebsite;
loadCoWebsiteFunction(coWebsite); loadCoWebsiteFunction(coWebsite);
}; };
@ -180,11 +159,7 @@ export class GameMapPropertiesListener {
false false
); );
const ObjectByLayer = this.coWebsitesOpenByLayer.get(layer); coWebsiteOpen.coWebsite = coWebsite;
if (ObjectByLayer) {
ObjectByLayer.coWebsite = coWebsite;
}
} }
if (!websiteTriggerProperty) { if (!websiteTriggerProperty) {
@ -228,12 +203,12 @@ export class GameMapPropertiesListener {
return; return;
} }
if (coWebsiteOpen.state === OpenCoWebsiteState.ASLEEP) { if (coWebsiteOpen.loadPromise !== undefined) {
coWebsiteOpen.state = OpenCoWebsiteState.MUST_BE_CLOSE; coWebsiteOpen.loadPromise.cancel();
} }
if (coWebsiteOpen.coWebsite !== undefined) { if (coWebsiteOpen.coWebsite !== undefined) {
coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite).catch((e) => console.error(e)); coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite);
} }
this.coWebsitesOpenByLayer.delete(layer); this.coWebsitesOpenByLayer.delete(layer);

View File

@ -1289,22 +1289,18 @@ ${escapedMessage}
}); });
}); });
iframeListener.registerAnswerer("closeCoWebsite", async (coWebsiteId) => { iframeListener.registerAnswerer("closeCoWebsite", (coWebsiteId) => {
const coWebsite = coWebsiteManager.getCoWebsiteById(coWebsiteId); const coWebsite = coWebsiteManager.getCoWebsiteById(coWebsiteId);
if (!coWebsite) { if (!coWebsite) {
throw new Error("Unknown co-website"); throw new Error("Unknown co-website");
} }
return coWebsiteManager.closeCoWebsite(coWebsite).catch((error) => { return coWebsiteManager.closeCoWebsite(coWebsite);
throw new Error("Error on closing co-website");
});
}); });
iframeListener.registerAnswerer("closeCoWebsites", async () => { iframeListener.registerAnswerer("closeCoWebsites", () => {
return await coWebsiteManager.closeCoWebsites().catch((error) => { return coWebsiteManager.closeCoWebsites();
throw new Error("Error on closing all co-websites");
});
}); });
iframeListener.registerAnswerer("getMapData", () => { iframeListener.registerAnswerer("getMapData", () => {
@ -1568,7 +1564,7 @@ ${escapedMessage}
public cleanupClosingScene(): void { public cleanupClosingScene(): void {
// stop playing audio, close any open website, stop any open Jitsi // stop playing audio, close any open website, stop any open Jitsi
coWebsiteManager.closeCoWebsites().catch((e) => console.error(e)); coWebsiteManager.closeCoWebsites();
// Stop the script, if any // Stop the script, if any
const scripts = this.getScriptUrls(this.mapFile); const scripts = this.getScriptUrls(this.mapFile);
for (const script of scripts) { for (const script of scripts) {
@ -2138,9 +2134,7 @@ ${escapedMessage}
public stopJitsi(): void { public stopJitsi(): void {
const coWebsite = coWebsiteManager.searchJitsi(); const coWebsite = coWebsiteManager.searchJitsi();
if (coWebsite) { if (coWebsite) {
coWebsiteManager.closeCoWebsite(coWebsite).catch((e) => { coWebsiteManager.closeCoWebsite(coWebsite);
console.error("Error during Jitsi co-website closing", e);
});
} }
} }

View File

@ -9,6 +9,7 @@ import { isMediaBreakpointDown } from "../Utils/BreakpointsUtils";
import { jitsiFactory } from "./JitsiFactory"; import { jitsiFactory } from "./JitsiFactory";
import { gameManager } from "../Phaser/Game/GameManager"; import { gameManager } from "../Phaser/Game/GameManager";
import { LayoutMode } from "./LayoutManager"; import { LayoutMode } from "./LayoutManager";
import CancelablePromise from "cancelable-promise";
export enum iframeStates { export enum iframeStates {
closed = 1, closed = 1,
@ -53,11 +54,7 @@ class CoWebsiteManager {
private _onResize: Subject<void> = new Subject(); private _onResize: Subject<void> = new Subject();
public onResize = this._onResize.asObservable(); public onResize = this._onResize.asObservable();
/**
* Quickly going in and out of an iframe trigger can create conflicts between the iframe states.
* So we use this promise to queue up every cowebsite state transition
*/
private currentOperationPromise: Promise<void> = Promise.resolve();
private cowebsiteDom: HTMLDivElement; private cowebsiteDom: HTMLDivElement;
private resizing: boolean = false; private resizing: boolean = false;
private gameOverlayDom: HTMLDivElement; private gameOverlayDom: HTMLDivElement;
@ -148,13 +145,9 @@ class CoWebsiteManager {
} }
if (coWebsite.closable) { if (coWebsite.closable) {
this.closeCoWebsite(coWebsite).catch(() => { this.closeCoWebsite(coWebsite);
console.error("Error during closing a co-website by a button");
});
} else { } else {
this.unloadCoWebsite(coWebsite).catch(() => { this.unloadCoWebsite(coWebsite);
console.error("Error during unloading a co-website by a button");
});
} }
}); });
@ -647,7 +640,7 @@ class CoWebsiteManager {
return newCoWebsite; return newCoWebsite;
} }
public loadCoWebsite(coWebsite: CoWebsite): Promise<CoWebsite> { public loadCoWebsite(coWebsite: CoWebsite): CancelablePromise<CoWebsite> {
if (get(coWebsitesNotAsleep).length < 1) { if (get(coWebsitesNotAsleep).length < 1) {
coWebsites.remove(coWebsite); coWebsites.remove(coWebsite);
coWebsites.add(coWebsite, 0); coWebsites.add(coWebsite, 0);
@ -663,7 +656,7 @@ class CoWebsiteManager {
const mainCoWebsite = this.getMainCoWebsite(); const mainCoWebsite = this.getMainCoWebsite();
return new Promise((resolve, reject) => { return new CancelablePromise((resolve, reject, cancel) => {
const onloadPromise = new Promise<void>((resolve) => { const onloadPromise = new Promise<void>((resolve) => {
coWebsite.iframe.onload = () => { coWebsite.iframe.onload = () => {
coWebsite.state.set("ready"); coWebsite.state.set("ready");
@ -683,8 +676,7 @@ class CoWebsiteManager {
jitsiFactory.restart(); jitsiFactory.restart();
} }
this.currentOperationPromise = this.currentOperationPromise const race = CancelablePromise.race([onloadPromise, onTimeoutPromise])
.then(() => Promise.race([onloadPromise, onTimeoutPromise]))
.then(() => { .then(() => {
if (mainCoWebsite && mainCoWebsite.iframe.id === coWebsite.iframe.id) { if (mainCoWebsite && mainCoWebsite.iframe.id === coWebsite.iframe.id) {
this.openMain(); this.openMain();
@ -701,83 +693,72 @@ class CoWebsiteManager {
this.removeCoWebsiteFromStack(coWebsite); this.removeCoWebsiteFromStack(coWebsite);
return reject(); return reject();
}); });
});
}
public unloadCoWebsite(coWebsite: CoWebsite): Promise<void> { cancel(() => {
return new Promise((resolve, reject) => { race.cancel();
this.removeHighlightCoWebsite(coWebsite); this.unloadCoWebsite(coWebsite);
coWebsite.iframe.parentNode?.removeChild(coWebsite.iframe);
coWebsite.state.set("asleep");
coWebsites.remove(coWebsite);
if (coWebsite.jitsi) {
jitsiFactory.stop();
const gameScene = gameManager.getCurrentGameScene();
gameScene.enableMediaBehaviors();
}
const mainCoWebsite = this.getMainCoWebsite();
if (mainCoWebsite) {
this.removeHighlightCoWebsite(mainCoWebsite);
this.goToMain(mainCoWebsite);
this.resizeAllIframes();
} else {
this.closeMain();
}
coWebsites.add(coWebsite, get(coWebsites).length);
resolve();
});
}
public closeCoWebsite(coWebsite: CoWebsite): Promise<void> {
this.currentOperationPromise = this.currentOperationPromise.then(
() =>
new Promise((resolve) => {
if (coWebsite.jitsi) {
jitsiFactory.destroy();
const gameScene = gameManager.getCurrentGameScene();
gameScene.enableMediaBehaviors();
}
if (get(coWebsites).length === 1) {
this.fire();
}
if (coWebsite.allowApi) {
iframeListener.unregisterIframe(coWebsite.iframe);
}
this.removeCoWebsiteFromStack(coWebsite);
const mainCoWebsite = this.getMainCoWebsite();
if (mainCoWebsite) {
this.removeHighlightCoWebsite(mainCoWebsite);
this.goToMain(mainCoWebsite);
this.resizeAllIframes();
} else {
this.closeMain();
}
resolve();
})
);
return this.currentOperationPromise;
}
public closeCoWebsites(): Promise<void> {
return (this.currentOperationPromise = this.currentOperationPromise.then(() => {
get(coWebsites).forEach((coWebsite: CoWebsite) => {
this.closeCoWebsite(coWebsite).catch(() => {
console.error("Error during closing a co-website");
});
}); });
})); });
return this.currentOperationPromise; }
public unloadCoWebsite(coWebsite: CoWebsite): void {
this.removeHighlightCoWebsite(coWebsite);
coWebsite.iframe.parentNode?.removeChild(coWebsite.iframe);
coWebsite.state.set("asleep");
coWebsites.remove(coWebsite);
if (coWebsite.jitsi) {
jitsiFactory.stop();
const gameScene = gameManager.getCurrentGameScene();
gameScene.enableMediaBehaviors();
}
const mainCoWebsite = this.getMainCoWebsite();
if (mainCoWebsite) {
this.removeHighlightCoWebsite(mainCoWebsite);
this.goToMain(mainCoWebsite);
this.resizeAllIframes();
} else {
this.closeMain();
}
coWebsites.add(coWebsite, get(coWebsites).length);
}
public closeCoWebsite(coWebsite: CoWebsite): void {
if (coWebsite.jitsi) {
jitsiFactory.destroy();
const gameScene = gameManager.getCurrentGameScene();
gameScene.enableMediaBehaviors();
}
if (get(coWebsites).length === 1) {
this.fire();
}
if (coWebsite.allowApi) {
iframeListener.unregisterIframe(coWebsite.iframe);
}
this.removeCoWebsiteFromStack(coWebsite);
const mainCoWebsite = this.getMainCoWebsite();
if (mainCoWebsite) {
this.removeHighlightCoWebsite(mainCoWebsite);
this.goToMain(mainCoWebsite);
this.resizeAllIframes();
} else {
this.closeMain();
}
}
public closeCoWebsites(): void {
get(coWebsites).forEach((coWebsite: CoWebsite) => {
this.closeCoWebsite(coWebsite);
});
} }
public getGameSize(): { width: number; height: number } { public getGameSize(): { width: number; height: number } {

View File

@ -145,7 +145,7 @@ class JitsiFactory {
const coWebsite = coWebsiteManager.searchJitsi(); const coWebsite = coWebsiteManager.searchJitsi();
if (coWebsite) { if (coWebsite) {
await coWebsiteManager.closeCoWebsite(coWebsite); coWebsiteManager.closeCoWebsite(coWebsite);
} }
// Jitsi meet external API maintains some data in local storage // Jitsi meet external API maintains some data in local storage
@ -214,13 +214,9 @@ class JitsiFactory {
private closeOrUnload = function (coWebsite: CoWebsite) { private closeOrUnload = function (coWebsite: CoWebsite) {
if (coWebsite.closable) { if (coWebsite.closable) {
coWebsiteManager.closeCoWebsite(coWebsite).catch(() => { coWebsiteManager.closeCoWebsite(coWebsite);
console.error("Error during closing a Jitsi Meet");
});
} else { } else {
coWebsiteManager.unloadCoWebsite(coWebsite).catch(() => { coWebsiteManager.unloadCoWebsite(coWebsite);
console.error("Error during unloading a Jitsi Meet");
});
} }
}; };