From f5f71f32eed44fa2feb13cd55a0341fb5e55dcc5 Mon Sep 17 00:00:00 2001 From: Alexis Faizeau Date: Tue, 8 Feb 2022 11:19:29 +0100 Subject: [PATCH] Fix cowebsite closing on fast opening/closing --- .../Layouts/PresentationLayout.svelte | 8 +- .../Phaser/Game/GameMapPropertiesListener.ts | 55 ++---- front/src/Phaser/Game/GameScene.ts | 18 +- front/src/WebRtc/CoWebsiteManager.ts | 161 ++++++++---------- front/src/WebRtc/JitsiFactory.ts | 10 +- 5 files changed, 97 insertions(+), 155 deletions(-) diff --git a/front/src/Components/EmbedScreens/Layouts/PresentationLayout.svelte b/front/src/Components/EmbedScreens/Layouts/PresentationLayout.svelte index f4a9f939..1ecb53e0 100644 --- a/front/src/Components/EmbedScreens/Layouts/PresentationLayout.svelte +++ b/front/src/Components/EmbedScreens/Layouts/PresentationLayout.svelte @@ -10,13 +10,9 @@ function closeCoWebsite() { if ($highlightedEmbedScreen?.type === "cowebsite") { if ($highlightedEmbedScreen.embed.closable) { - coWebsiteManager.closeCoWebsite($highlightedEmbedScreen.embed).catch(() => { - console.error("Error during co-website highlighted closing"); - }); + coWebsiteManager.closeCoWebsite($highlightedEmbedScreen.embed); } else { - coWebsiteManager.unloadCoWebsite($highlightedEmbedScreen.embed).catch(() => { - console.error("Error during co-website highlighted unloading"); - }); + coWebsiteManager.unloadCoWebsite($highlightedEmbedScreen.embed); } } } diff --git a/front/src/Phaser/Game/GameMapPropertiesListener.ts b/front/src/Phaser/Game/GameMapPropertiesListener.ts index 497b6cbc..6ac00665 100644 --- a/front/src/Phaser/Game/GameMapPropertiesListener.ts +++ b/front/src/Phaser/Game/GameMapPropertiesListener.ts @@ -9,17 +9,12 @@ import { get } from "svelte/store"; import { ON_ACTION_TRIGGER_BUTTON, ON_ICON_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager"; import type { ITiledMapLayer } from "../Map/ITiledMap"; import { GameMapProperties } from "./GameMapProperties"; - -enum OpenCoWebsiteState { - ASLEEP, - OPENED, - MUST_BE_CLOSE, -} +import type CancelablePromise from "cancelable-promise"; interface OpenCoWebsite { actionId: string; coWebsite?: CoWebsite; - state: OpenCoWebsiteState; + loadPromise?: CancelablePromise; } export class GameMapPropertiesListener { @@ -106,34 +101,16 @@ export class GameMapPropertiesListener { return; } - this.coWebsitesOpenByLayer.set(layer, { + const coWebsiteOpen: OpenCoWebsite = { actionId: actionId, - coWebsite: undefined, - state: OpenCoWebsiteState.ASLEEP, - }); + }; + + this.coWebsitesOpenByLayer.set(layer, coWebsiteOpen); const loadCoWebsiteFunction = (coWebsite: CoWebsite) => { - coWebsiteManager - .loadCoWebsite(coWebsite) - .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); - }); + coWebsiteOpen.loadPromise = coWebsiteManager.loadCoWebsite(coWebsite).catch(() => { + console.error("Error during loading a co-website: " + coWebsite.url); + }); layoutManagerActionStore.removeAction(actionId); }; @@ -149,6 +126,8 @@ export class GameMapPropertiesListener { false ); + coWebsiteOpen.coWebsite = coWebsite; + loadCoWebsiteFunction(coWebsite); }; @@ -180,11 +159,7 @@ export class GameMapPropertiesListener { false ); - const ObjectByLayer = this.coWebsitesOpenByLayer.get(layer); - - if (ObjectByLayer) { - ObjectByLayer.coWebsite = coWebsite; - } + coWebsiteOpen.coWebsite = coWebsite; } if (!websiteTriggerProperty) { @@ -228,12 +203,12 @@ export class GameMapPropertiesListener { return; } - if (coWebsiteOpen.state === OpenCoWebsiteState.ASLEEP) { - coWebsiteOpen.state = OpenCoWebsiteState.MUST_BE_CLOSE; + if (coWebsiteOpen.loadPromise !== undefined) { + coWebsiteOpen.loadPromise.cancel(); } if (coWebsiteOpen.coWebsite !== undefined) { - coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite).catch((e) => console.error(e)); + coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite); } this.coWebsitesOpenByLayer.delete(layer); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 9b758a45..39b84b76 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1289,22 +1289,18 @@ ${escapedMessage} }); }); - iframeListener.registerAnswerer("closeCoWebsite", async (coWebsiteId) => { + iframeListener.registerAnswerer("closeCoWebsite", (coWebsiteId) => { const coWebsite = coWebsiteManager.getCoWebsiteById(coWebsiteId); if (!coWebsite) { throw new Error("Unknown co-website"); } - return coWebsiteManager.closeCoWebsite(coWebsite).catch((error) => { - throw new Error("Error on closing co-website"); - }); + return coWebsiteManager.closeCoWebsite(coWebsite); }); - iframeListener.registerAnswerer("closeCoWebsites", async () => { - return await coWebsiteManager.closeCoWebsites().catch((error) => { - throw new Error("Error on closing all co-websites"); - }); + iframeListener.registerAnswerer("closeCoWebsites", () => { + return coWebsiteManager.closeCoWebsites(); }); iframeListener.registerAnswerer("getMapData", () => { @@ -1568,7 +1564,7 @@ ${escapedMessage} public cleanupClosingScene(): void { // 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 const scripts = this.getScriptUrls(this.mapFile); for (const script of scripts) { @@ -2138,9 +2134,7 @@ ${escapedMessage} public stopJitsi(): void { const coWebsite = coWebsiteManager.searchJitsi(); if (coWebsite) { - coWebsiteManager.closeCoWebsite(coWebsite).catch((e) => { - console.error("Error during Jitsi co-website closing", e); - }); + coWebsiteManager.closeCoWebsite(coWebsite); } } diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index 476526da..0758409f 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -9,6 +9,7 @@ import { isMediaBreakpointDown } from "../Utils/BreakpointsUtils"; import { jitsiFactory } from "./JitsiFactory"; import { gameManager } from "../Phaser/Game/GameManager"; import { LayoutMode } from "./LayoutManager"; +import CancelablePromise from "cancelable-promise"; export enum iframeStates { closed = 1, @@ -53,11 +54,7 @@ class CoWebsiteManager { private _onResize: Subject = new Subject(); 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 = Promise.resolve(); + private cowebsiteDom: HTMLDivElement; private resizing: boolean = false; private gameOverlayDom: HTMLDivElement; @@ -148,13 +145,9 @@ class CoWebsiteManager { } if (coWebsite.closable) { - this.closeCoWebsite(coWebsite).catch(() => { - console.error("Error during closing a co-website by a button"); - }); + this.closeCoWebsite(coWebsite); } else { - this.unloadCoWebsite(coWebsite).catch(() => { - console.error("Error during unloading a co-website by a button"); - }); + this.unloadCoWebsite(coWebsite); } }); @@ -647,7 +640,7 @@ class CoWebsiteManager { return newCoWebsite; } - public loadCoWebsite(coWebsite: CoWebsite): Promise { + public loadCoWebsite(coWebsite: CoWebsite): CancelablePromise { if (get(coWebsitesNotAsleep).length < 1) { coWebsites.remove(coWebsite); coWebsites.add(coWebsite, 0); @@ -663,7 +656,7 @@ class CoWebsiteManager { const mainCoWebsite = this.getMainCoWebsite(); - return new Promise((resolve, reject) => { + return new CancelablePromise((resolve, reject, cancel) => { const onloadPromise = new Promise((resolve) => { coWebsite.iframe.onload = () => { coWebsite.state.set("ready"); @@ -683,8 +676,7 @@ class CoWebsiteManager { jitsiFactory.restart(); } - this.currentOperationPromise = this.currentOperationPromise - .then(() => Promise.race([onloadPromise, onTimeoutPromise])) + const race = CancelablePromise.race([onloadPromise, onTimeoutPromise]) .then(() => { if (mainCoWebsite && mainCoWebsite.iframe.id === coWebsite.iframe.id) { this.openMain(); @@ -701,83 +693,72 @@ class CoWebsiteManager { this.removeCoWebsiteFromStack(coWebsite); return reject(); }); - }); - } - public unloadCoWebsite(coWebsite: CoWebsite): Promise { - return new Promise((resolve, reject) => { - 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); - - resolve(); - }); - } - - public closeCoWebsite(coWebsite: CoWebsite): Promise { - 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 { - return (this.currentOperationPromise = this.currentOperationPromise.then(() => { - get(coWebsites).forEach((coWebsite: CoWebsite) => { - this.closeCoWebsite(coWebsite).catch(() => { - console.error("Error during closing a co-website"); - }); + cancel(() => { + race.cancel(); + this.unloadCoWebsite(coWebsite); }); - })); - 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 } { diff --git a/front/src/WebRtc/JitsiFactory.ts b/front/src/WebRtc/JitsiFactory.ts index 8f7ed952..a8f10e10 100644 --- a/front/src/WebRtc/JitsiFactory.ts +++ b/front/src/WebRtc/JitsiFactory.ts @@ -145,7 +145,7 @@ class JitsiFactory { const coWebsite = coWebsiteManager.searchJitsi(); if (coWebsite) { - await coWebsiteManager.closeCoWebsite(coWebsite); + coWebsiteManager.closeCoWebsite(coWebsite); } // Jitsi meet external API maintains some data in local storage @@ -214,13 +214,9 @@ class JitsiFactory { private closeOrUnload = function (coWebsite: CoWebsite) { if (coWebsite.closable) { - coWebsiteManager.closeCoWebsite(coWebsite).catch(() => { - console.error("Error during closing a Jitsi Meet"); - }); + coWebsiteManager.closeCoWebsite(coWebsite); } else { - coWebsiteManager.unloadCoWebsite(coWebsite).catch(() => { - console.error("Error during unloading a Jitsi Meet"); - }); + coWebsiteManager.unloadCoWebsite(coWebsite); } };