From 6e27ffb2d55ae4113458e25732adff07b192a038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 16 Dec 2021 18:18:55 +0100 Subject: [PATCH 1/2] Starting fixing unhandled promises --- front/.eslintrc.js | 1 - front/src/Administration/AnalyticsClient.ts | 20 +++++++++---------- front/src/Api/iframe/Ui/ActionMessage.ts | 2 +- front/src/Api/iframe/state.ts | 2 +- .../AudioManager/AudioManager.svelte | 2 +- .../Menu/GlobalMessagesSubMenu.svelte | 6 +++--- .../src/Components/Menu/ProfileSubMenu.svelte | 4 ++-- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/front/.eslintrc.js b/front/.eslintrc.js index 117cb7e6..dc2b6bd6 100644 --- a/front/.eslintrc.js +++ b/front/.eslintrc.js @@ -35,7 +35,6 @@ module.exports = { "no-unused-vars": "off", "@typescript-eslint/no-explicit-any": "error", // TODO: remove those ignored rules and write a stronger code! - "@typescript-eslint/no-floating-promises": "off", "@typescript-eslint/no-unsafe-call": "off", "@typescript-eslint/restrict-plus-operands": "off", "@typescript-eslint/no-unsafe-assignment": "off", diff --git a/front/src/Administration/AnalyticsClient.ts b/front/src/Administration/AnalyticsClient.ts index fb2b604b..4248339b 100644 --- a/front/src/Administration/AnalyticsClient.ts +++ b/front/src/Administration/AnalyticsClient.ts @@ -20,62 +20,62 @@ class AnalyticsClient { identifyUser(uuid: string, email: string | null) { this.posthogPromise?.then((posthog) => { posthog.identify(uuid, { uuid, email, wa: true }); - }); + }).catch(e => console.error(e)); } loggedWithSso() { this.posthogPromise?.then((posthog) => { posthog.capture("wa-logged-sso"); - }); + }).catch(e => console.error(e)); } loggedWithToken() { this.posthogPromise?.then((posthog) => { posthog.capture("wa-logged-token"); - }); + }).catch(e => console.error(e)); } enteredRoom(roomId: string, roomGroup: string | null) { this.posthogPromise?.then((posthog) => { posthog.capture("$pageView", { roomId, roomGroup }); posthog.capture("enteredRoom"); - }); + }).catch(e => console.error(e)); } openedMenu() { this.posthogPromise?.then((posthog) => { posthog.capture("wa-opened-menu"); - }); + }).catch(e => console.error(e)); } launchEmote(emote: string) { this.posthogPromise?.then((posthog) => { posthog.capture("wa-emote-launch", { emote }); - }); + }).catch(e => console.error(e)); } enteredJitsi(roomName: string, roomId: string) { this.posthogPromise?.then((posthog) => { posthog.capture("wa-entered-jitsi", { roomName, roomId }); - }); + }).catch(e => console.error(e)); } validationName() { this.posthogPromise?.then((posthog) => { posthog.capture("wa-name-validation"); - }); + }).catch(e => console.error(e)); } validationWoka(scene: string) { this.posthogPromise?.then((posthog) => { posthog.capture("wa-woka-validation", { scene }); - }); + }).catch(e => console.error(e)); } validationVideo() { this.posthogPromise?.then((posthog) => { posthog.capture("wa-video-validation"); - }); + }).catch(e => console.error(e)); } } export const analyticsClient = new AnalyticsClient(); diff --git a/front/src/Api/iframe/Ui/ActionMessage.ts b/front/src/Api/iframe/Ui/ActionMessage.ts index 912603b9..f4e6a937 100644 --- a/front/src/Api/iframe/Ui/ActionMessage.ts +++ b/front/src/Api/iframe/Ui/ActionMessage.ts @@ -26,7 +26,7 @@ export class ActionMessage { this.message = actionMessageOptions.message; this.type = actionMessageOptions.type ?? "message"; this.callback = actionMessageOptions.callback; - this.create(); + this.create().catch(e => console.error(e)); } private async create() { diff --git a/front/src/Api/iframe/state.ts b/front/src/Api/iframe/state.ts index 7021b251..ccc671f6 100644 --- a/front/src/Api/iframe/state.ts +++ b/front/src/Api/iframe/state.ts @@ -95,7 +95,7 @@ export function createState(target: "global" | "player"): WorkadventureStateComm set(target: WorkadventureStateCommands, p: PropertyKey, value: unknown, receiver: unknown): boolean { // Note: when using "set", there is no way to wait, so we ignore the return of the promise. // User must use WA.state.saveVariable to have error message. - target.saveVariable(p.toString(), value); + target.saveVariable(p.toString(), value).catch(e => console.error(e)); return true; }, has(target: WorkadventureStateCommands, p: PropertyKey): boolean { diff --git a/front/src/Components/AudioManager/AudioManager.svelte b/front/src/Components/AudioManager/AudioManager.svelte index c4ca44f9..b62d8fbe 100644 --- a/front/src/Components/AudioManager/AudioManager.svelte +++ b/front/src/Components/AudioManager/AudioManager.svelte @@ -25,7 +25,7 @@ HTMLAudioPlayer.loop = get(audioManagerVolumeStore).loop; HTMLAudioPlayer.volume = get(audioManagerVolumeStore).volume; HTMLAudioPlayer.muted = get(audioManagerVolumeStore).muted; - HTMLAudioPlayer.play(); + void HTMLAudioPlayer.play(); }); unsubscriberVolumeStore = audioManagerVolumeStore.subscribe((audioManager: audioManagerVolume) => { const reduceVolume = audioManager.talking && audioManager.decreaseWhileTalking; diff --git a/front/src/Components/Menu/GlobalMessagesSubMenu.svelte b/front/src/Components/Menu/GlobalMessagesSubMenu.svelte index 524e5e50..e755a243 100644 --- a/front/src/Components/Menu/GlobalMessagesSubMenu.svelte +++ b/front/src/Components/Menu/GlobalMessagesSubMenu.svelte @@ -19,12 +19,12 @@ uploadAudioActive = true; } - function send() { + async function send(): Promise { if (inputSendTextActive) { - handleSendText.sendTextMessage(broadcastToWorld); + return handleSendText.sendTextMessage(broadcastToWorld); } if (uploadAudioActive) { - handleSendAudio.sendAudioMessage(broadcastToWorld); + return handleSendAudio.sendAudioMessage(broadcastToWorld); } } diff --git a/front/src/Components/Menu/ProfileSubMenu.svelte b/front/src/Components/Menu/ProfileSubMenu.svelte index 07356f6c..87bf57c9 100644 --- a/front/src/Components/Menu/ProfileSubMenu.svelte +++ b/front/src/Components/Menu/ProfileSubMenu.svelte @@ -41,10 +41,10 @@ gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene()); } - function logOut() { + async function logOut() { disableMenuStores(); loginSceneVisibleStore.set(true); - connectionManager.logout(); + return connectionManager.logout(); } function getProfileUrl() { From 24baf5664cf1cc04cdd70fb726b0e2ba667a5e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Tue, 4 Jan 2022 16:48:47 +0100 Subject: [PATCH 2/2] All promises are now handled --- front/src/Administration/AnalyticsClient.ts | 82 +++++++----- front/src/Api/iframe/Ui/ActionMessage.ts | 2 +- front/src/Api/iframe/state.ts | 2 +- .../Components/Menu/SettingsSubMenu.svelte | 22 ++-- front/src/Components/UI/AudioPlaying.svelte | 2 +- front/src/Connexion/ConnectionManager.ts | 4 +- front/src/Connexion/LocalUserStore.ts | 9 +- front/src/Connexion/RoomConnection.ts | 2 +- front/src/Phaser/Companion/Companion.ts | 16 ++- .../CompanionTexturesLoadingManager.ts | 2 +- front/src/Phaser/Components/Loader.ts | 8 +- .../Phaser/Game/GameMapPropertiesListener.ts | 7 +- front/src/Phaser/Game/GameScene.ts | 97 ++++++++------ front/src/Phaser/Login/CustomizeScene.ts | 28 ++-- .../src/Phaser/Login/SelectCharacterScene.ts | 14 +- front/src/Stores/MediaStore.ts | 29 ++--- front/src/Stores/ScreenSharingStore.ts | 2 +- front/src/Url/UrlManager.ts | 2 +- front/src/WebRtc/CoWebsiteManager.ts | 122 +++++++++--------- front/src/WebRtc/JitsiFactory.ts | 8 +- front/src/iframe_api.ts | 10 +- 21 files changed, 262 insertions(+), 208 deletions(-) diff --git a/front/src/Administration/AnalyticsClient.ts b/front/src/Administration/AnalyticsClient.ts index 4248339b..4c1ca93a 100644 --- a/front/src/Administration/AnalyticsClient.ts +++ b/front/src/Administration/AnalyticsClient.ts @@ -18,64 +18,84 @@ class AnalyticsClient { } identifyUser(uuid: string, email: string | null) { - this.posthogPromise?.then((posthog) => { - posthog.identify(uuid, { uuid, email, wa: true }); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.identify(uuid, { uuid, email, wa: true }); + }) + .catch((e) => console.error(e)); } loggedWithSso() { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-logged-sso"); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-logged-sso"); + }) + .catch((e) => console.error(e)); } loggedWithToken() { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-logged-token"); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-logged-token"); + }) + .catch((e) => console.error(e)); } enteredRoom(roomId: string, roomGroup: string | null) { - this.posthogPromise?.then((posthog) => { - posthog.capture("$pageView", { roomId, roomGroup }); - posthog.capture("enteredRoom"); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("$pageView", { roomId, roomGroup }); + posthog.capture("enteredRoom"); + }) + .catch((e) => console.error(e)); } openedMenu() { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-opened-menu"); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-opened-menu"); + }) + .catch((e) => console.error(e)); } launchEmote(emote: string) { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-emote-launch", { emote }); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-emote-launch", { emote }); + }) + .catch((e) => console.error(e)); } enteredJitsi(roomName: string, roomId: string) { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-entered-jitsi", { roomName, roomId }); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-entered-jitsi", { roomName, roomId }); + }) + .catch((e) => console.error(e)); } validationName() { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-name-validation"); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-name-validation"); + }) + .catch((e) => console.error(e)); } validationWoka(scene: string) { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-woka-validation", { scene }); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-woka-validation", { scene }); + }) + .catch((e) => console.error(e)); } validationVideo() { - this.posthogPromise?.then((posthog) => { - posthog.capture("wa-video-validation"); - }).catch(e => console.error(e)); + this.posthogPromise + ?.then((posthog) => { + posthog.capture("wa-video-validation"); + }) + .catch((e) => console.error(e)); } } export const analyticsClient = new AnalyticsClient(); diff --git a/front/src/Api/iframe/Ui/ActionMessage.ts b/front/src/Api/iframe/Ui/ActionMessage.ts index f4e6a937..ff0908ff 100644 --- a/front/src/Api/iframe/Ui/ActionMessage.ts +++ b/front/src/Api/iframe/Ui/ActionMessage.ts @@ -26,7 +26,7 @@ export class ActionMessage { this.message = actionMessageOptions.message; this.type = actionMessageOptions.type ?? "message"; this.callback = actionMessageOptions.callback; - this.create().catch(e => console.error(e)); + this.create().catch((e) => console.error(e)); } private async create() { diff --git a/front/src/Api/iframe/state.ts b/front/src/Api/iframe/state.ts index ccc671f6..278b208e 100644 --- a/front/src/Api/iframe/state.ts +++ b/front/src/Api/iframe/state.ts @@ -95,7 +95,7 @@ export function createState(target: "global" | "player"): WorkadventureStateComm set(target: WorkadventureStateCommands, p: PropertyKey, value: unknown, receiver: unknown): boolean { // Note: when using "set", there is no way to wait, so we ignore the return of the promise. // User must use WA.state.saveVariable to have error message. - target.saveVariable(p.toString(), value).catch(e => console.error(e)); + target.saveVariable(p.toString(), value).catch((e) => console.error(e)); return true; }, has(target: WorkadventureStateCommands, p: PropertyKey): boolean { diff --git a/front/src/Components/Menu/SettingsSubMenu.svelte b/front/src/Components/Menu/SettingsSubMenu.svelte index 1db14036..1ad1ac8b 100644 --- a/front/src/Components/Menu/SettingsSubMenu.svelte +++ b/front/src/Components/Menu/SettingsSubMenu.svelte @@ -33,9 +33,9 @@ const body = HtmlUtils.querySelectorOrFail("body"); if (body) { if (document.fullscreenElement !== null && !fullscreen) { - document.exitFullscreen(); + document.exitFullscreen().catch((e) => console.error(e)); } else { - body.requestFullscreen(); + body.requestFullscreen().catch((e) => console.error(e)); } localUserStore.setFullscreen(fullscreen); } @@ -45,14 +45,16 @@ if (Notification.permission === "granted") { localUserStore.setNotification(notification ? "granted" : "denied"); } else { - Notification.requestPermission().then((response) => { - if (response === "granted") { - localUserStore.setNotification(notification ? "granted" : "denied"); - } else { - localUserStore.setNotification("denied"); - notification = false; - } - }); + Notification.requestPermission() + .then((response) => { + if (response === "granted") { + localUserStore.setNotification(notification ? "granted" : "denied"); + } else { + localUserStore.setNotification("denied"); + notification = false; + } + }) + .catch((e) => console.error(e)); } } diff --git a/front/src/Components/UI/AudioPlaying.svelte b/front/src/Components/UI/AudioPlaying.svelte index 09ffd639..a8d12ec9 100644 --- a/front/src/Components/UI/AudioPlaying.svelte +++ b/front/src/Components/UI/AudioPlaying.svelte @@ -12,7 +12,7 @@ } afterUpdate(() => { - audio.play(); + audio.play().catch((e) => console.error(e)); }); diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index 19750ee8..20c4aae9 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -188,7 +188,7 @@ class ConnectionManager { //Set last room visited! (connected or nor, must to be saved in localstorage and cache API) //use href to keep # value - localUserStore.setLastRoomUrl(this._currentRoom.href); + await localUserStore.setLastRoomUrl(this._currentRoom.href); //todo: add here some kind of warning if authToken has expired. if (!this.authToken && !this._currentRoom.authenticationMandatory) { @@ -301,7 +301,7 @@ class ConnectionManager { this.reconnectingTimeout = setTimeout(() => { //todo: allow a way to break recursion? //todo: find a way to avoid recursive function. Otherwise, the call stack will grow indefinitely. - this.connectToRoomSocket(roomUrl, name, characterLayers, position, viewport, companion).then( + void this.connectToRoomSocket(roomUrl, name, characterLayers, position, viewport, companion).then( (connection) => resolve(connection) ); }, 4000 + Math.floor(Math.random() * 2000)); diff --git a/front/src/Connexion/LocalUserStore.ts b/front/src/Connexion/LocalUserStore.ts index 4f03a546..cc84f043 100644 --- a/front/src/Connexion/LocalUserStore.ts +++ b/front/src/Connexion/LocalUserStore.ts @@ -136,13 +136,12 @@ class LocalUserStore { return localStorage.getItem(ignoreFollowRequests) === "true"; } - setLastRoomUrl(roomUrl: string): void { + async setLastRoomUrl(roomUrl: string): Promise { localStorage.setItem(lastRoomUrl, roomUrl.toString()); if ("caches" in window) { - caches.open(cacheAPIIndex).then((cache) => { - const stringResponse = new Response(JSON.stringify({ roomUrl })); - cache.put(`/${lastRoomUrl}`, stringResponse); - }); + const cache = await caches.open(cacheAPIIndex); + const stringResponse = new Response(JSON.stringify({ roomUrl })); + await cache.put(`/${lastRoomUrl}`, stringResponse); } } getLastRoomUrl(): string { diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index 96c6dd23..d360c705 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -352,7 +352,7 @@ export class RoomConnection implements RoomConnection { break; } case "tokenExpiredMessage": { - connectionManager.logout(); + connectionManager.logout().catch((e) => console.error(e)); this.closed = true; //technically, this isn't needed since loadOpenIDScreen() will do window.location.assign() but I prefer to leave it for consistency break; } diff --git a/front/src/Phaser/Companion/Companion.ts b/front/src/Phaser/Companion/Companion.ts index 80b0236e..6157ebaa 100644 --- a/front/src/Phaser/Companion/Companion.ts +++ b/front/src/Phaser/Companion/Companion.ts @@ -41,13 +41,15 @@ export class Companion extends Container { this.companionName = name; this._pictureStore = writable(undefined); - texturePromise.then((resource) => { - this.addResource(resource); - this.invisible = false; - return this.getSnapshot().then((htmlImageElementSrc) => { - this._pictureStore.set(htmlImageElementSrc); - }); - }); + texturePromise + .then((resource) => { + this.addResource(resource); + this.invisible = false; + return this.getSnapshot().then((htmlImageElementSrc) => { + this._pictureStore.set(htmlImageElementSrc); + }); + }) + .catch((e) => console.error(e)); this.scene.physics.world.enableBody(this); diff --git a/front/src/Phaser/Companion/CompanionTexturesLoadingManager.ts b/front/src/Phaser/Companion/CompanionTexturesLoadingManager.ts index bd87ba75..98cceafa 100644 --- a/front/src/Phaser/Companion/CompanionTexturesLoadingManager.ts +++ b/front/src/Phaser/Companion/CompanionTexturesLoadingManager.ts @@ -3,7 +3,7 @@ import { COMPANION_RESOURCES, CompanionResourceDescriptionInterface } from "./Co export const getAllCompanionResources = (loader: LoaderPlugin): CompanionResourceDescriptionInterface[] => { COMPANION_RESOURCES.forEach((resource: CompanionResourceDescriptionInterface) => { - lazyLoadCompanionResource(loader, resource.name); + lazyLoadCompanionResource(loader, resource.name).catch((e) => console.error(e)); }); return COMPANION_RESOURCES; diff --git a/front/src/Phaser/Components/Loader.ts b/front/src/Phaser/Components/Loader.ts index e013e758..7eb08e6d 100644 --- a/front/src/Phaser/Components/Loader.ts +++ b/front/src/Phaser/Components/Loader.ts @@ -72,9 +72,11 @@ export class Loader { if (this.loadingText) { this.loadingText.destroy(); } - promiseLoadLogoTexture.then((resLoadingImage: Phaser.GameObjects.Image) => { - resLoadingImage.destroy(); - }); + promiseLoadLogoTexture + .then((resLoadingImage: Phaser.GameObjects.Image) => { + resLoadingImage.destroy(); + }) + .catch((e) => console.error(e)); this.progress.destroy(); this.progressContainer.destroy(); if (this.scene instanceof DirtyScene) { diff --git a/front/src/Phaser/Game/GameMapPropertiesListener.ts b/front/src/Phaser/Game/GameMapPropertiesListener.ts index 2dc36df8..f6c28862 100644 --- a/front/src/Phaser/Game/GameMapPropertiesListener.ts +++ b/front/src/Phaser/Game/GameMapPropertiesListener.ts @@ -123,7 +123,7 @@ export class GameMapPropertiesListener { .then((coWebsite) => { const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer); if (coWebsiteOpen && coWebsiteOpen.state === OpenCoWebsiteState.MUST_BE_CLOSE) { - coWebsiteManager.closeCoWebsite(coWebsite); + coWebsiteManager.closeCoWebsite(coWebsite).catch((e) => console.error(e)); this.coWebsitesOpenByLayer.delete(layer); this.coWebsitesActionTriggerByLayer.delete(layer); } else { @@ -132,7 +132,8 @@ export class GameMapPropertiesListener { state: OpenCoWebsiteState.OPENED, }); } - }); + }) + .catch((e) => console.error(e)); layoutManagerActionStore.removeAction(actionUuid); }; @@ -198,7 +199,7 @@ export class GameMapPropertiesListener { } if (coWebsiteOpen.coWebsite !== undefined) { - coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite); + coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite).catch((e) => console.error(e)); } this.coWebsitesOpenByLayer.delete(layer); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 42b0c06e..b6d7274c 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -241,7 +241,7 @@ export class GameScene extends DirtyScene { const textures = localUser?.textures; if (textures) { for (const texture of textures) { - loadCustomTexture(this.load, texture); + loadCustomTexture(this.load, texture).catch((e) => console.error(e)); } } @@ -268,7 +268,7 @@ export class GameScene extends DirtyScene { this.load.on( "filecomplete-tilemapJSON-" + this.MapUrlFile, (key: string, type: string, data: unknown) => { - this.onMapLoad(data); + this.onMapLoad(data).catch((e) => console.error(e)); } ); return; @@ -292,14 +292,14 @@ export class GameScene extends DirtyScene { this.load.on( "filecomplete-tilemapJSON-" + this.MapUrlFile, (key: string, type: string, data: unknown) => { - this.onMapLoad(data); + this.onMapLoad(data).catch((e) => console.error(e)); } ); // If the map has already been loaded as part of another GameScene, the "on load" event will not be triggered. // In this case, we check in the cache to see if the map is here and trigger the event manually. if (this.cache.tilemap.exists(this.MapUrlFile)) { const data = this.cache.tilemap.get(this.MapUrlFile); - this.onMapLoad(data); + this.onMapLoad(data).catch((e) => console.error(e)); } return; } @@ -320,7 +320,7 @@ export class GameScene extends DirtyScene { }); this.load.scenePlugin("AnimatedTiles", AnimatedTiles, "animatedTiles", "animatedTiles"); this.load.on("filecomplete-tilemapJSON-" + this.MapUrlFile, (key: string, type: string, data: unknown) => { - this.onMapLoad(data); + this.onMapLoad(data).catch((e) => console.error(e)); }); //TODO strategy to add access token this.load.tilemapTiledJSON(this.MapUrlFile, this.MapUrlFile); @@ -328,7 +328,7 @@ export class GameScene extends DirtyScene { // In this case, we check in the cache to see if the map is here and trigger the event manually. if (this.cache.tilemap.exists(this.MapUrlFile)) { const data = this.cache.tilemap.get(this.MapUrlFile); - this.onMapLoad(data); + this.onMapLoad(data).catch((e) => console.error(e)); } //eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -406,21 +406,23 @@ export class GameScene extends DirtyScene { this.load.on("complete", () => { // FIXME: the factory might fail because the resources might not be loaded yet... // We would need to add a loader ended event in addition to the createPromise - this.createPromise.then(async () => { - itemFactory.create(this); + this.createPromise + .then(async () => { + itemFactory.create(this); - const roomJoinedAnswer = await this.connectionAnswerPromise; + const roomJoinedAnswer = await this.connectionAnswerPromise; - for (const object of objectsOfType) { - // TODO: we should pass here a factory to create sprites (maybe?) + for (const object of objectsOfType) { + // TODO: we should pass here a factory to create sprites (maybe?) - // Do we have a state for this object? - const state = roomJoinedAnswer.items[object.id]; + // Do we have a state for this object? + const state = roomJoinedAnswer.items[object.id]; - const actionableItem = itemFactory.factory(this, object, state); - this.actionableItems.set(actionableItem.getId(), actionableItem); - } - }); + const actionableItem = itemFactory.factory(this, object, state); + this.actionableItems.set(actionableItem.getId(), actionableItem); + } + }) + .catch((e) => console.error(e)); }); } } @@ -486,11 +488,11 @@ export class GameScene extends DirtyScene { if (exitSceneUrl !== undefined) { this.loadNextGame( Room.getRoomPathFromExitSceneUrl(exitSceneUrl, window.location.toString(), this.MapUrlFile) - ); + ).catch((e) => console.error(e)); } const exitUrl = this.getExitUrl(layer); if (exitUrl !== undefined) { - this.loadNextGameFromExitUrl(exitUrl); + this.loadNextGameFromExitUrl(exitUrl).catch((e) => console.error(e)); } } if (layer.type === "objectgroup") { @@ -530,7 +532,7 @@ export class GameScene extends DirtyScene { } this.gameMap.exitUrls.forEach((exitUrl) => { - this.loadNextGameFromExitUrl(exitUrl); + this.loadNextGameFromExitUrl(exitUrl).catch((e) => console.error(e)); }); this.startPositionCalculator = new StartPositionCalculator( @@ -551,7 +553,10 @@ export class GameScene extends DirtyScene { mediaManager.setUserInputManager(this.userInputManager); if (localUserStore.getFullscreen()) { - document.querySelector("body")?.requestFullscreen(); + document + .querySelector("body") + ?.requestFullscreen() + .catch((e) => console.error(e)); } //notify game manager can to create currentUser in map @@ -657,9 +662,16 @@ export class GameScene extends DirtyScene { } }); - Promise.all([this.connectionAnswerPromise as Promise, ...scriptPromises]).then(() => { - this.scene.wake(); - }); + Promise.all([this.connectionAnswerPromise as Promise, ...scriptPromises]) + .then(() => { + this.scene.wake(); + }) + .catch((e) => + console.error( + "Some scripts failed to load ot the connection failed to establish to WorkAdventure server", + e + ) + ); } /** @@ -859,7 +871,8 @@ export class GameScene extends DirtyScene { // iframeListener.sendLeaveLayerEvent(layer.name); // }); // }); - }); + }) + .catch((e) => console.error(e)); } //todo: into dedicated classes @@ -912,7 +925,7 @@ export class GameScene extends DirtyScene { if (newValue) { this.onMapExit( Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile) - ); + ).catch((e) => console.error(e)); } else { setTimeout(() => { layoutManagerActionStore.removeAction("roomAccessDenied"); @@ -921,7 +934,9 @@ export class GameScene extends DirtyScene { }); this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => { if (newValue) { - this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString())); + this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString())).catch((e) => + console.error(e) + ); } else { setTimeout(() => { layoutManagerActionStore.removeAction("roomAccessDenied"); @@ -1107,7 +1122,9 @@ ${escapedMessage} this.iframeSubscriptionList.push( iframeListener.playSoundStream.subscribe((playSoundEvent) => { const url = new URL(playSoundEvent.url, this.MapUrlFile); - soundManager.playSound(this.load, this.sound, url.toString(), playSoundEvent.config); + soundManager + .playSound(this.load, this.sound, url.toString(), playSoundEvent.config) + .catch((e) => console.error(e)); }) ); @@ -1145,7 +1162,7 @@ ${escapedMessage} this.iframeSubscriptionList.push( iframeListener.loadSoundStream.subscribe((loadSoundEvent) => { const url = new URL(loadSoundEvent.url, this.MapUrlFile); - soundManager.loadSound(this.load, this.sound, url.toString()); + soundManager.loadSound(this.load, this.sound, url.toString()).catch((e) => console.error(e)); }) ); @@ -1156,11 +1173,15 @@ ${escapedMessage} ); this.iframeSubscriptionList.push( iframeListener.loadPageStream.subscribe((url: string) => { - this.loadNextGameFromExitUrl(url).then(() => { - this.events.once(EVENT_TYPE.POST_UPDATE, () => { - this.onMapExit(Room.getRoomPathFromExitUrl(url, window.location.toString())); - }); - }); + this.loadNextGameFromExitUrl(url) + .then(() => { + this.events.once(EVENT_TYPE.POST_UPDATE, () => { + this.onMapExit(Room.getRoomPathFromExitUrl(url, window.location.toString())).catch((e) => + console.error(e) + ); + }); + }) + .catch((e) => console.error(e)); }) ); let scriptedBubbleSprite: Sprite; @@ -1417,7 +1438,7 @@ ${escapedMessage} propertyValue: string | number | boolean | undefined ): void { if (propertyName === GameMapProperties.EXIT_URL && typeof propertyValue === "string") { - this.loadNextGameFromExitUrl(propertyValue); + this.loadNextGameFromExitUrl(propertyValue).catch((e) => console.error(e)); } this.gameMap.setLayerProperty(layerName, propertyName, propertyValue); } @@ -1502,7 +1523,7 @@ ${escapedMessage} public cleanupClosingScene(): void { // stop playing audio, close any open website, stop any open Jitsi - coWebsiteManager.closeCoWebsites(); + coWebsiteManager.closeCoWebsites().catch((e) => console.error(e)); // Stop the script, if any const scripts = this.getScriptUrls(this.mapFile); for (const script of scripts) { @@ -2044,7 +2065,9 @@ ${escapedMessage} const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined; const jitsiWidth = allProps.get(GameMapProperties.JITSI_WIDTH) as number | undefined; - jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth); + jitsiFactory + .start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth) + .catch((e) => console.error(e)); this.connection?.setSilent(true); mediaManager.hideGameOverlay(); analyticsClient.enteredJitsi(roomName, this.room.id); diff --git a/front/src/Phaser/Login/CustomizeScene.ts b/front/src/Phaser/Login/CustomizeScene.ts index d5629c88..5c208edd 100644 --- a/front/src/Phaser/Login/CustomizeScene.ts +++ b/front/src/Phaser/Login/CustomizeScene.ts @@ -40,19 +40,21 @@ export class CustomizeScene extends AbstractCharacterScene { } preload() { - this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => { - bodyResourceDescriptions.forEach((bodyResourceDescription) => { - if ( - bodyResourceDescription.level == undefined || - bodyResourceDescription.level < 0 || - bodyResourceDescription.level > 5 - ) { - throw "Texture level is null"; - } - this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription); - }); - this.lazyloadingAttempt = true; - }); + this.loadCustomSceneSelectCharacters() + .then((bodyResourceDescriptions) => { + bodyResourceDescriptions.forEach((bodyResourceDescription) => { + if ( + bodyResourceDescription.level == undefined || + bodyResourceDescription.level < 0 || + bodyResourceDescription.level > 5 + ) { + throw "Texture level is null"; + } + this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription); + }); + this.lazyloadingAttempt = true; + }) + .catch((e) => console.error(e)); this.layers = loadAllLayers(this.load); this.lazyloadingAttempt = false; diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index 64fa9791..4e372e0e 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -41,12 +41,14 @@ export class SelectCharacterScene extends AbstractCharacterScene { } preload() { - this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => { - bodyResourceDescriptions.forEach((bodyResourceDescription) => { - this.playerModels.push(bodyResourceDescription); - }); - this.lazyloadingAttempt = true; - }); + this.loadSelectSceneCharacters() + .then((bodyResourceDescriptions) => { + bodyResourceDescriptions.forEach((bodyResourceDescription) => { + this.playerModels.push(bodyResourceDescription); + }); + this.lazyloadingAttempt = true; + }) + .catch((e) => console.error(e)); this.playerModels = loadAllDefaultModels(this.load); this.lazyloadingAttempt = false; diff --git a/front/src/Stores/MediaStore.ts b/front/src/Stores/MediaStore.ts index a0f1a92b..7eeac35d 100644 --- a/front/src/Stores/MediaStore.ts +++ b/front/src/Stores/MediaStore.ts @@ -360,32 +360,27 @@ const implementCorrectTrackBehavior = getNavigatorType() === NavigatorType.firef /** * Stops the camera from filming */ -function applyCameraConstraints(currentStream: MediaStream | null, constraints: MediaTrackConstraints | boolean): void { +async function applyCameraConstraints( + currentStream: MediaStream | null, + constraints: MediaTrackConstraints | boolean +): Promise { if (!currentStream) { - return; - } - for (const track of currentStream.getVideoTracks()) { - toggleConstraints(track, constraints).catch((e) => - console.error("Error while setting new camera constraints:", e) - ); + return []; } + return Promise.all(currentStream.getVideoTracks().map((track) => toggleConstraints(track, constraints))); } /** * Stops the microphone from listening */ -function applyMicrophoneConstraints( +async function applyMicrophoneConstraints( currentStream: MediaStream | null, constraints: MediaTrackConstraints | boolean -): void { +): Promise { if (!currentStream) { - return; - } - for (const track of currentStream.getAudioTracks()) { - toggleConstraints(track, constraints).catch((e) => - console.error("Error while setting new audio constraints:", e) - ); + return []; } + return Promise.all(currentStream.getAudioTracks().map((track) => toggleConstraints(track, constraints))); } async function toggleConstraints(track: MediaStreamTrack, constraints: MediaTrackConstraints | boolean): Promise { @@ -477,8 +472,8 @@ export const localStreamStore = derived, LocalS } } - applyMicrophoneConstraints(currentStream, constraints.audio || false); - applyCameraConstraints(currentStream, constraints.video || false); + applyMicrophoneConstraints(currentStream, constraints.audio || false).catch((e) => console.error(e)); + applyCameraConstraints(currentStream, constraints.video || false).catch((e) => console.error(e)); if (implementCorrectTrackBehavior) { //on good navigators like firefox, we can instantiate the stream once and simply disable or enable the tracks as needed diff --git a/front/src/Stores/ScreenSharingStore.ts b/front/src/Stores/ScreenSharingStore.ts index d68dbf8b..dc2c495c 100644 --- a/front/src/Stores/ScreenSharingStore.ts +++ b/front/src/Stores/ScreenSharingStore.ts @@ -156,7 +156,7 @@ export const screenSharingLocalStreamStore = derived console.error(e)); } ); diff --git a/front/src/Url/UrlManager.ts b/front/src/Url/UrlManager.ts index 50dbedc9..95ea12f2 100644 --- a/front/src/Url/UrlManager.ts +++ b/front/src/Url/UrlManager.ts @@ -41,7 +41,7 @@ class UrlManager { if (window.location.pathname === room.id) return; //Set last room visited! (connected or nor, must to be saved in localstorage and cache API) //use href to keep # value - localUserStore.setLastRoomUrl(room.href); + localUserStore.setLastRoomUrl(room.href).catch((e) => console.error(e)); const hash = window.location.hash; const search = room.search.toString(); history.pushState({}, "WorkAdventure", room.id + (search ? "?" + search : "") + hash); diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index 7a003604..8bff2acb 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -149,7 +149,7 @@ class CoWebsiteManager { } buttonCloseCoWebsites.blur(); - this.closeCoWebsites(); + this.closeCoWebsites().catch((e) => console.error(e)); }); const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId); @@ -515,70 +515,72 @@ class CoWebsiteManager { throw new Error("Too many we"); } - Promise.resolve(callback(this.cowebsiteBufferDom)).then((iframe) => { - iframe?.classList.add("pixel"); + Promise.resolve(callback(this.cowebsiteBufferDom)) + .then((iframe) => { + iframe?.classList.add("pixel"); - if (!iframe.id) { - do { - iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7); - } while (this.getCoWebsiteById(iframe.id)); - } - - const onloadPromise = new Promise((resolve) => { - iframe.onload = () => resolve(); - }); - - const icon = this.generateCoWebsiteIcon(iframe); - - const coWebsite = { - iframe, - icon, - position: position ?? this.coWebsites.length, - }; - - // Iframe management on mobile - icon.addEventListener("click", () => { - if (this.isSmallScreen()) { - this.moveRightPreviousCoWebsite(coWebsite, 0); + if (!iframe.id) { + do { + iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7); + } while (this.getCoWebsiteById(iframe.id)); } - }); - this.coWebsites.push(coWebsite); - this.cowebsiteSubIconsDom.appendChild(icon); + const onloadPromise = new Promise((resolve) => { + iframe.onload = () => resolve(); + }); - const onTimeoutPromise = new Promise((resolve) => { - setTimeout(() => resolve(), 2000); - }); + const icon = this.generateCoWebsiteIcon(iframe); - this.currentOperationPromise = this.currentOperationPromise - .then(() => Promise.race([onloadPromise, onTimeoutPromise])) - .then(() => { - if (coWebsite.position === 0) { - this.openMain(); - if (widthPercent) { - this.widthPercent = widthPercent; - } + const coWebsite = { + iframe, + icon, + position: position ?? this.coWebsites.length, + }; - setTimeout(() => { - this.fire(); + // Iframe management on mobile + icon.addEventListener("click", () => { + if (this.isSmallScreen()) { + this.moveRightPreviousCoWebsite(coWebsite, 0); + } + }); + + this.coWebsites.push(coWebsite); + this.cowebsiteSubIconsDom.appendChild(icon); + + const onTimeoutPromise = new Promise((resolve) => { + setTimeout(() => resolve(), 2000); + }); + + this.currentOperationPromise = this.currentOperationPromise + .then(() => Promise.race([onloadPromise, onTimeoutPromise])) + .then(() => { + if (coWebsite.position === 0) { + this.openMain(); + if (widthPercent) { + this.widthPercent = widthPercent; + } + + setTimeout(() => { + this.fire(); + position !== undefined + ? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) + : this.moveCoWebsite(coWebsite, coWebsite.position); + }, animationTime); + } else { position !== undefined ? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) : this.moveCoWebsite(coWebsite, coWebsite.position); - }, animationTime); - } else { - position !== undefined - ? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) - : this.moveCoWebsite(coWebsite, coWebsite.position); - } + } - return resolve(coWebsite); - }) - .catch((err) => { - console.error("Error loadCoWebsite => ", err); - this.removeCoWebsiteFromStack(coWebsite); - return reject(); - }); - }); + return resolve(coWebsite); + }) + .catch((err) => { + console.error("Error loadCoWebsite => ", err); + this.removeCoWebsiteFromStack(coWebsite); + return reject(); + }); + }) + .catch((e) => console.error("Error loadCoWebsite >=> ", e)); }); } @@ -603,17 +605,21 @@ class CoWebsiteManager { return this.currentOperationPromise; } - public closeJitsi() { + public async closeJitsi() { const jitsi = this.searchJitsi(); if (jitsi) { - this.closeCoWebsite(jitsi); + return this.closeCoWebsite(jitsi); } } public closeCoWebsites(): Promise { this.currentOperationPromise = this.currentOperationPromise.then(() => { + const promises: Promise[] = []; this.coWebsites.forEach((coWebsite: CoWebsite) => { - this.closeCoWebsite(coWebsite); + promises.push(this.closeCoWebsite(coWebsite)); + }); + return Promise.all(promises).then(() => { + return; }); }); return this.currentOperationPromise; diff --git a/front/src/WebRtc/JitsiFactory.ts b/front/src/WebRtc/JitsiFactory.ts index 0f205f47..c067a255 100644 --- a/front/src/WebRtc/JitsiFactory.ts +++ b/front/src/WebRtc/JitsiFactory.ts @@ -1,5 +1,5 @@ import { JITSI_URL } from "../Enum/EnvironmentVariable"; -import { coWebsiteManager } from "./CoWebsiteManager"; +import { CoWebsite, coWebsiteManager } from "./CoWebsiteManager"; import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore"; import { get } from "svelte/store"; @@ -140,8 +140,8 @@ class JitsiFactory { interfaceConfig?: object, jitsiUrl?: string, jitsiWidth?: number - ): void { - coWebsiteManager.addCoWebsite( + ): Promise { + return coWebsiteManager.addCoWebsite( async (cowebsiteDiv) => { // Jitsi meet external API maintains some data in local storage // which is sent via the appData URL parameter when joining a @@ -200,7 +200,7 @@ class JitsiFactory { const jitsiCoWebsite = coWebsiteManager.searchJitsi(); if (jitsiCoWebsite) { - coWebsiteManager.closeJitsi(); + coWebsiteManager.closeJitsi().catch((e) => console.error(e)); } this.jitsiApi.removeListener("audioMuteStatusChanged", this.audioCallback); diff --git a/front/src/iframe_api.ts b/front/src/iframe_api.ts index 6b3ec8c3..66ee77c0 100644 --- a/front/src/iframe_api.ts +++ b/front/src/iframe_api.ts @@ -9,7 +9,7 @@ import { } from "./Api/Events/IframeEvent"; import chat from "./Api/iframe/chat"; import type { IframeCallback } from "./Api/iframe/IframeApiContribution"; -import nav from "./Api/iframe/nav"; +import nav, { CoWebsite } from "./Api/iframe/nav"; import controls from "./Api/iframe/controls"; import ui from "./Api/iframe/ui"; import sound from "./Api/iframe/sound"; @@ -136,17 +136,17 @@ const wa = { /** * @deprecated Use WA.nav.openCoWebSite instead */ - openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void { + openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): Promise { console.warn("Method WA.openCoWebSite is deprecated. Please use WA.nav.openCoWebSite instead"); - nav.openCoWebSite(url, allowApi, allowPolicy); + return nav.openCoWebSite(url, allowApi, allowPolicy); }, /** * @deprecated Use WA.nav.closeCoWebSite instead */ - closeCoWebSite(): void { + closeCoWebSite(): Promise { console.warn("Method WA.closeCoWebSite is deprecated. Please use WA.nav.closeCoWebSite instead"); - nav.closeCoWebSite(); + return nav.closeCoWebSite(); }, /**