diff --git a/front/src/Components/EmbedScreens/CoWebsiteThumbnailSlot.svelte b/front/src/Components/EmbedScreens/CoWebsiteThumbnailSlot.svelte index 2043315b..b01dbf0a 100644 --- a/front/src/Components/EmbedScreens/CoWebsiteThumbnailSlot.svelte +++ b/front/src/Components/EmbedScreens/CoWebsiteThumbnailSlot.svelte @@ -2,9 +2,10 @@ import { onMount } from "svelte"; import { ICON_URL } from "../../Enum/EnvironmentVariable"; - import { coWebsitesNotAsleep, mainCoWebsite, jitsiCoWebsite } from "../../Stores/CoWebsiteStore"; + import { mainCoWebsite } from "../../Stores/CoWebsiteStore"; import { highlightedEmbedScreen } from "../../Stores/EmbedScreensStore"; import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite"; + import { JitsiCoWebsite } from "../../WebRtc/CoWebsite/JitsiCoWebsite"; import { iframeStates } from "../../WebRtc/CoWebsiteManager"; import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager"; @@ -15,10 +16,10 @@ let icon: HTMLImageElement; let iconLoaded = false; let state = coWebsite.getStateSubscriber(); - let isJitsi: boolean = false; + let isJitsi: boolean = coWebsite instanceof JitsiCoWebsite; + const mainState = coWebsiteManager.getMainStateSubscriber(); onMount(() => { - isJitsi = Boolean($jitsiCoWebsite && $jitsiCoWebsite.getId() === coWebsite.getId()); icon.src = isJitsi ? "/resources/logos/meet.svg" : `${ICON_URL}/icon?url=${coWebsite.getUrl().hostname}&size=64..96..256&fallback_icon_color=14304c`; @@ -33,20 +34,23 @@ coWebsiteManager.goToMain(coWebsite); } else if ($mainCoWebsite) { if ($mainCoWebsite.getId() === coWebsite.getId()) { - const coWebsites = $coWebsitesNotAsleep; - const newMain = $highlightedEmbedScreen ?? coWebsites.length > 1 ? coWebsites[1] : undefined; - if (newMain && newMain.getId() !== $mainCoWebsite.getId()) { - coWebsiteManager.goToMain(newMain); - } else if (coWebsiteManager.getMainState() === iframeStates.closed) { + if (coWebsiteManager.getMainState() === iframeStates.closed) { coWebsiteManager.displayMain(); + } else if ($highlightedEmbedScreen?.type === "cowebsite") { + coWebsiteManager.goToMain($highlightedEmbedScreen.embed); } else { coWebsiteManager.hideMain(); } } else { - highlightedEmbedScreen.toggleHighlight({ - type: "cowebsite", - embed: coWebsite, - }); + if (coWebsiteManager.getMainState() === iframeStates.closed) { + coWebsiteManager.goToMain(coWebsite); + coWebsiteManager.displayMain(); + } else { + highlightedEmbedScreen.toggleHighlight({ + type: "cowebsite", + embed: coWebsite, + }); + } } } @@ -64,7 +68,10 @@ let isHighlight: boolean = false; let isMain: boolean = false; $: { - isMain = $mainCoWebsite !== undefined && $mainCoWebsite.getId() === coWebsite.getId(); + isMain = + $mainState === iframeStates.opened && + $mainCoWebsite !== undefined && + $mainCoWebsite.getId() === coWebsite.getId(); isHighlight = $highlightedEmbedScreen !== null && $highlightedEmbedScreen.type === "cowebsite" && @@ -212,7 +219,8 @@ } &:not(.vertical) { - animation: bounce 0.35s ease 6 alternate; + transition: all 300ms; + transform: translateY(0px); } &.vertical { @@ -233,7 +241,7 @@ &.displayed { &:not(.vertical) { - animation: activeThumbnail 300ms ease-in 0s forwards; + transform: translateY(-15px); } } @@ -262,16 +270,6 @@ } } - @keyframes activeThumbnail { - 0% { - transform: translateY(0); - } - - 100% { - transform: translateY(-15px); - } - } - @keyframes bounce { from { transform: translateY(0); diff --git a/front/src/Phaser/Game/GameMapPropertiesListener.ts b/front/src/Phaser/Game/GameMapPropertiesListener.ts index 22073610..103cc4bc 100644 --- a/front/src/Phaser/Game/GameMapPropertiesListener.ts +++ b/front/src/Phaser/Game/GameMapPropertiesListener.ts @@ -10,6 +10,13 @@ import type { ITiledMapLayer } from "../Map/ITiledMap"; import { GameMapProperties } from "./GameMapProperties"; import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite"; import { SimpleCoWebsite } from "../../WebRtc/CoWebsite/SimpleCoWebsite"; +import { jitsiFactory } from "../../WebRtc/JitsiFactory"; +import { JITSI_PRIVATE_MODE, JITSI_URL } from "../../Enum/EnvironmentVariable"; +import { JitsiCoWebsite } from "../../WebRtc/CoWebsite/JitsiCoWebsite"; +import { audioManagerFileStore, audioManagerVisibilityStore } from "../../Stores/AudioManagerStore"; +import { iframeListener } from "../../Api/IframeListener"; +import { Room } from "../../Connexion/Room"; +import LL from "../../i18n/i18n-svelte"; interface OpenCoWebsite { actionId: string; @@ -23,6 +30,7 @@ export class GameMapPropertiesListener { constructor(private scene: GameScene, private gameMap: GameMap) {} register() { + // Website on new tab this.gameMap.onPropertyChange(GameMapProperties.OPEN_TAB, (newValue, oldValue, allProps) => { if (newValue === undefined) { layoutManagerActionStore.removeAction("openTab"); @@ -33,7 +41,7 @@ export class GameMapPropertiesListener { if (forceTrigger || openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) { let message = allProps.get(GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE); if (message === undefined) { - message = "Press SPACE or touch here to open web site in new tab"; + message = get(LL).trigger.newTab(); } layoutManagerActionStore.addAction({ uuid: "openTab", @@ -48,6 +56,129 @@ export class GameMapPropertiesListener { } }); + // Jitsi room + this.gameMap.onPropertyChange(GameMapProperties.JITSI_ROOM, (newValue, oldValue, allProps) => { + if (newValue === undefined) { + layoutManagerActionStore.removeAction("jitsi"); + coWebsiteManager.getCoWebsites().forEach((coWebsite) => { + if (coWebsite instanceof JitsiCoWebsite) { + coWebsiteManager.closeCoWebsite(coWebsite); + } + }); + } else { + const openJitsiRoomFunction = () => { + const roomName = jitsiFactory.getRoomName(newValue.toString(), this.scene.instance); + const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined; + + if (JITSI_PRIVATE_MODE && !jitsiUrl) { + const adminTag = allProps.get(GameMapProperties.JITSI_ADMIN_ROOM_TAG) as string | undefined; + + this.scene.connection?.emitQueryJitsiJwtMessage(roomName, adminTag); + } else { + let domain = jitsiUrl || JITSI_URL; + if (domain === undefined) { + throw new Error("Missing JITSI_URL environment variable or jitsiUrl parameter in the map."); + } + + if (domain.substring(0, 7) !== "http://" && domain.substring(0, 8) !== "https://") { + domain = `${location.protocol}//${domain}`; + } + + const coWebsite = new JitsiCoWebsite(new URL(domain), false, undefined, undefined, false); + + coWebsiteManager.addCoWebsiteToStore(coWebsite, 0); + this.scene.initialiseJitsi(coWebsite, roomName, undefined); + } + layoutManagerActionStore.removeAction("jitsi"); + }; + + const jitsiTriggerValue = allProps.get(GameMapProperties.JITSI_TRIGGER); + const forceTrigger = localUserStore.getForceCowebsiteTrigger(); + if (forceTrigger || jitsiTriggerValue === ON_ACTION_TRIGGER_BUTTON) { + let message = allProps.get(GameMapProperties.JITSI_TRIGGER_MESSAGE); + if (message === undefined) { + message = get(LL).trigger.jitsiRoom(); + } + layoutManagerActionStore.addAction({ + uuid: "jitsi", + type: "message", + message: message, + callback: () => openJitsiRoomFunction(), + userInputManager: this.scene.userInputManager, + }); + } else { + openJitsiRoomFunction(); + } + } + }); + + this.gameMap.onPropertyChange(GameMapProperties.EXIT_SCENE_URL, (newValue, oldValue) => { + if (newValue) { + this.scene + .onMapExit( + Room.getRoomPathFromExitSceneUrl( + newValue as string, + window.location.toString(), + this.scene.MapUrlFile + ) + ) + .catch((e) => console.error(e)); + } else { + setTimeout(() => { + layoutManagerActionStore.removeAction("roomAccessDenied"); + }, 2000); + } + }); + + this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => { + if (newValue) { + this.scene + .onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString())) + .catch((e) => console.error(e)); + } else { + setTimeout(() => { + layoutManagerActionStore.removeAction("roomAccessDenied"); + }, 2000); + } + }); + + this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue, oldValue) => { + if (newValue === undefined || newValue === false || newValue === "") { + this.scene.connection?.setSilent(false); + this.scene.CurrentPlayer.noSilent(); + } else { + this.scene.connection?.setSilent(true); + this.scene.CurrentPlayer.isSilent(); + } + }); + + this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO, (newValue, oldValue, allProps) => { + const volume = allProps.get(GameMapProperties.AUDIO_VOLUME) as number | undefined; + const loop = allProps.get(GameMapProperties.AUDIO_LOOP) as boolean | undefined; + newValue === undefined + ? audioManagerFileStore.unloadAudio() + : audioManagerFileStore.playAudio(newValue, this.scene.getMapDirUrl(), volume, loop); + audioManagerVisibilityStore.set(!(newValue === undefined)); + }); + + // TODO: This legacy property should be removed at some point + this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO_LOOP, (newValue, oldValue) => { + newValue === undefined + ? audioManagerFileStore.unloadAudio() + : audioManagerFileStore.playAudio(newValue, this.scene.getMapDirUrl(), undefined, true); + audioManagerVisibilityStore.set(!(newValue === undefined)); + }); + + // TODO: Legacy functionnality replace by layer change + this.gameMap.onPropertyChange(GameMapProperties.ZONE, (newValue, oldValue) => { + if (oldValue) { + iframeListener.sendLeaveEvent(oldValue as string); + } + if (newValue) { + iframeListener.sendEnterEvent(newValue as string); + } + }); + // Open a new co-website by the property. this.gameMap.onEnterLayer((newLayers) => { const handler = () => { @@ -135,7 +266,7 @@ export class GameMapPropertiesListener { websiteTriggerProperty === ON_ACTION_TRIGGER_BUTTON ) { if (!websiteTriggerMessageProperty) { - websiteTriggerMessageProperty = "Press SPACE or touch here to open web site"; + websiteTriggerMessageProperty = get(LL).trigger.cowebsite(); } this.coWebsitesActionTriggerByLayer.set(layer, actionId); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 9b5a9918..8ad668eb 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -20,15 +20,8 @@ import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager"; import { lazyLoadPlayerCharacterTextures, loadCustomTexture } from "../Entity/PlayerTexturesLoadingManager"; import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager"; -import { ON_ACTION_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager"; import { iframeListener } from "../../Api/IframeListener"; -import { - DEBUG_MODE, - JITSI_PRIVATE_MODE, - JITSI_URL, - MAX_PER_GROUP, - POSITION_DELAY, -} from "../../Enum/EnvironmentVariable"; +import { DEBUG_MODE, JITSI_URL, MAX_PER_GROUP, POSITION_DELAY } from "../../Enum/EnvironmentVariable"; import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils"; import { Room } from "../../Connexion/Room"; import { jitsiFactory } from "../../WebRtc/JitsiFactory"; @@ -82,7 +75,7 @@ import { emoteStore, emoteMenuStore } from "../../Stores/EmoteStore"; import { userIsAdminStore } from "../../Stores/GameStore"; import { contactPageStore } from "../../Stores/MenuStore"; import type { WasCameraUpdatedEvent } from "../../Api/Events/WasCameraUpdatedEvent"; -import { audioManagerFileStore, audioManagerVisibilityStore } from "../../Stores/AudioManagerStore"; +import { audioManagerFileStore } from "../../Stores/AudioManagerStore"; import EVENT_TYPE = Phaser.Scenes.Events; import Texture = Phaser.Textures.Texture; @@ -636,7 +629,6 @@ export class GameScene extends DirtyScene { ); new GameMapPropertiesListener(this, this.gameMap).register(); - this.triggerOnMapLayerPropertyChange(); if (!this.room.isDisconnected()) { this.scene.sleep(); @@ -815,7 +807,7 @@ export class GameScene extends DirtyScene { const coWebsite = new JitsiCoWebsite(new URL(domain), false, undefined, undefined, false); coWebsiteManager.addCoWebsiteToStore(coWebsite, 0); - this.startJitsi(coWebsite, message.jitsiRoom, message.jwt); + this.initialiseJitsi(coWebsite, message.jitsiRoom, message.jwt); }); this.messageSubscription = this.connection.worldFullMessageStream.subscribe((message) => { @@ -952,116 +944,6 @@ export class GameScene extends DirtyScene { } } - private triggerOnMapLayerPropertyChange() { - this.gameMap.onPropertyChange(GameMapProperties.EXIT_SCENE_URL, (newValue, oldValue) => { - if (newValue) { - this.onMapExit( - Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile) - ).catch((e) => console.error(e)); - } else { - setTimeout(() => { - layoutManagerActionStore.removeAction("roomAccessDenied"); - }, 2000); - } - }); - this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => { - if (newValue) { - this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString())).catch((e) => - console.error(e) - ); - } else { - setTimeout(() => { - layoutManagerActionStore.removeAction("roomAccessDenied"); - }, 2000); - } - }); - - this.gameMap.onPropertyChange(GameMapProperties.JITSI_ROOM, (newValue, oldValue, allProps) => { - if (newValue === undefined) { - layoutManagerActionStore.removeAction("jitsi"); - this.stopJitsi(); - } else { - const openJitsiRoomFunction = () => { - const roomName = jitsiFactory.getRoomName(newValue.toString(), this.instance); - const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined; - - if (JITSI_PRIVATE_MODE && !jitsiUrl) { - const adminTag = allProps.get(GameMapProperties.JITSI_ADMIN_ROOM_TAG) as string | undefined; - - this.connection?.emitQueryJitsiJwtMessage(roomName, adminTag); - } else { - let domain = jitsiUrl || JITSI_URL; - if (domain === undefined) { - throw new Error("Missing JITSI_URL environment variable or jitsiUrl parameter in the map."); - } - - if (domain.substring(0, 7) !== "http://" && domain.substring(0, 8) !== "https://") { - domain = `${location.protocol}//${domain}`; - } - - const coWebsite = new JitsiCoWebsite(new URL(domain), false, undefined, undefined, false); - - coWebsiteManager.addCoWebsiteToStore(coWebsite, 0); - this.startJitsi(coWebsite, roomName, undefined); - } - layoutManagerActionStore.removeAction("jitsi"); - }; - - const jitsiTriggerValue = allProps.get(GameMapProperties.JITSI_TRIGGER); - const forceTrigger = localUserStore.getForceCowebsiteTrigger(); - if (forceTrigger || jitsiTriggerValue === ON_ACTION_TRIGGER_BUTTON) { - let message = allProps.get(GameMapProperties.JITSI_TRIGGER_MESSAGE); - if (message === undefined) { - message = "Press SPACE or touch here to enter Jitsi Meet room"; - } - layoutManagerActionStore.addAction({ - uuid: "jitsi", - type: "message", - message: message, - callback: () => openJitsiRoomFunction(), - userInputManager: this.userInputManager, - }); - } else { - openJitsiRoomFunction(); - } - } - }); - this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue, oldValue) => { - if (newValue === undefined || newValue === false || newValue === "") { - this.connection?.setSilent(false); - this.CurrentPlayer.noSilent(); - } else { - this.connection?.setSilent(true); - this.CurrentPlayer.isSilent(); - } - }); - this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO, (newValue, oldValue, allProps) => { - const volume = allProps.get(GameMapProperties.AUDIO_VOLUME) as number | undefined; - const loop = allProps.get(GameMapProperties.AUDIO_LOOP) as boolean | undefined; - newValue === undefined - ? audioManagerFileStore.unloadAudio() - : audioManagerFileStore.playAudio(newValue, this.getMapDirUrl(), volume, loop); - audioManagerVisibilityStore.set(!(newValue === undefined)); - }); - // TODO: This legacy property should be removed at some point - this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO_LOOP, (newValue, oldValue) => { - newValue === undefined - ? audioManagerFileStore.unloadAudio() - : audioManagerFileStore.playAudio(newValue, this.getMapDirUrl(), undefined, true); - audioManagerVisibilityStore.set(!(newValue === undefined)); - }); - - // TODO: Legacy functionnality replace by layer change - this.gameMap.onPropertyChange(GameMapProperties.ZONE, (newValue, oldValue) => { - if (oldValue) { - iframeListener.sendLeaveEvent(oldValue as string); - } - if (newValue) { - iframeListener.sendEnterEvent(newValue as string); - } - }); - } - private listenToIframeEvents(): void { this.iframeSubscriptionList = []; this.iframeSubscriptionList.push( @@ -1417,7 +1299,7 @@ ${escapedMessage} //Create new colliders with the new GameMap this.createCollisionWithPlayer(); //Create new trigger with the new GameMap - this.triggerOnMapLayerPropertyChange(); + new GameMapPropertiesListener(this, this.gameMap).register(); resolve(newFirstgid); }); }); @@ -1534,11 +1416,11 @@ ${escapedMessage} this.markDirty(); } - private getMapDirUrl(): string { - return this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf("/")); + public getMapDirUrl(): string { + return this.MapUrlFile.substring(0, this.MapUrlFile.lastIndexOf("/")); } - private async onMapExit(roomUrl: URL) { + public async onMapExit(roomUrl: URL) { if (this.mapTransitioning) return; this.mapTransitioning = true; @@ -1604,7 +1486,6 @@ ${escapedMessage} iframeListener.unregisterScript(script); } - this.stopJitsi(); audioManagerFileStore.unloadAudio(); // We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map. this.connection?.closeConnection(); @@ -2145,7 +2026,7 @@ ${escapedMessage} mediaManager.hideMyCamera(); } - public startJitsi(coWebsite: JitsiCoWebsite, roomName: string, jwt?: string): void { + public initialiseJitsi(coWebsite: JitsiCoWebsite, roomName: string, jwt?: string): void { const allProps = this.gameMap.getCurrentProperties(); const jitsiConfig = this.safeParseJSONstring( allProps.get(GameMapProperties.JITSI_CONFIG) as string | undefined, @@ -2168,13 +2049,6 @@ ${escapedMessage} analyticsClient.enteredJitsi(roomName, this.room.id); } - public stopJitsi(): void { - const coWebsite = coWebsiteManager.searchJitsi(); - if (coWebsite) { - coWebsiteManager.closeCoWebsite(coWebsite); - } - } - //todo: put this into an 'orchestrator' scene (EntryScene?) private bannedUser() { this.cleanupClosingScene(); diff --git a/front/src/Stores/CoWebsiteStore.ts b/front/src/Stores/CoWebsiteStore.ts index 7f922db4..c4ed2f65 100644 --- a/front/src/Stores/CoWebsiteStore.ts +++ b/front/src/Stores/CoWebsiteStore.ts @@ -1,6 +1,5 @@ -import { derived, get, writable } from "svelte/store"; +import { derived, writable } from "svelte/store"; import type { CoWebsite } from "../WebRtc/CoWebsite/CoWesbite"; -import { JitsiCoWebsite } from "../WebRtc/CoWebsite/JitsiCoWebsite"; function createCoWebsiteStore() { const { subscribe, set, update } = writable(Array()); @@ -50,7 +49,3 @@ export const coWebsitesNotAsleep = derived([coWebsites], ([$coWebsites]) => export const mainCoWebsite = derived([coWebsites], ([$coWebsites]) => $coWebsites.find((coWebsite) => coWebsite.getState() !== "asleep") ); - -export const jitsiCoWebsite = derived([coWebsites], ([$coWebsites]) => - $coWebsites.find((coWebsite) => coWebsite instanceof JitsiCoWebsite) -); diff --git a/front/src/WebRtc/CoWebsite/JitsiCoWebsite.ts b/front/src/WebRtc/CoWebsite/JitsiCoWebsite.ts index 654bb924..a09b2bcb 100644 --- a/front/src/WebRtc/CoWebsite/JitsiCoWebsite.ts +++ b/front/src/WebRtc/CoWebsite/JitsiCoWebsite.ts @@ -1,22 +1,11 @@ import CancelablePromise from "cancelable-promise"; import { gameManager } from "../../Phaser/Game/GameManager"; -import { coWebsiteManager } from "../CoWebsiteManager"; import { jitsiFactory } from "../JitsiFactory"; import { SimpleCoWebsite } from "./SimpleCoWebsite"; export class JitsiCoWebsite extends SimpleCoWebsite { private jitsiLoadPromise?: () => CancelablePromise; - constructor(url: URL, allowApi?: boolean, allowPolicy?: string, widthPercent?: number, closable?: boolean) { - const coWebsite = coWebsiteManager.searchJitsi(); - - if (coWebsite) { - coWebsiteManager.closeCoWebsite(coWebsite); - } - - super(url, allowApi, allowPolicy, widthPercent, closable); - } - setJitsiLoadPromise(promise: () => CancelablePromise): void { this.jitsiLoadPromise = promise; } @@ -26,7 +15,6 @@ export class JitsiCoWebsite extends SimpleCoWebsite { this.state.set("loading"); gameManager.getCurrentGameScene().disableMediaBehaviors(); - jitsiFactory.restart(); if (!this.jitsiLoadPromise) { return reject("Undefined Jitsi start callback"); diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index f67b6e18..a5c57ed6 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -1,8 +1,8 @@ import { HtmlUtils } from "./HtmlUtils"; import { Subject } from "rxjs"; import { waScaleManager } from "../Phaser/Services/WaScaleManager"; -import { coWebsites, coWebsitesNotAsleep, jitsiCoWebsite, mainCoWebsite } from "../Stores/CoWebsiteStore"; -import { get } from "svelte/store"; +import { coWebsites, coWebsitesNotAsleep, mainCoWebsite } from "../Stores/CoWebsiteStore"; +import { get, Readable, Writable, writable } from "svelte/store"; import { embedScreenLayout, highlightedEmbedScreen } from "../Stores/EmbedScreensStore"; import { isMediaBreakpointDown } from "../Utils/BreakpointsUtils"; import { LayoutMode } from "./LayoutManager"; @@ -34,7 +34,7 @@ interface TouchMoveCoordinates { } class CoWebsiteManager { - private openedMain: iframeStates = iframeStates.closed; + private openedMain: Writable = writable(iframeStates.closed); private _onResize: Subject = new Subject(); public onResize = this._onResize.asObservable(); @@ -57,6 +57,10 @@ class CoWebsiteManager { }); public getMainState() { + return get(this.openedMain); + } + + public getMainStateSubscriber(): Readable { return this.openedMain; } @@ -324,7 +328,7 @@ class CoWebsiteManager { } this.cowebsiteDom.classList.add("closing"); this.cowebsiteDom.classList.remove("opened"); - this.openedMain = iframeStates.closed; + this.openedMain.set(iframeStates.closed); this.fire(); } @@ -332,7 +336,7 @@ class CoWebsiteManager { this.toggleFullScreenIcon(true); this.cowebsiteDom.classList.add("closing"); this.cowebsiteDom.classList.remove("opened"); - this.openedMain = iframeStates.closed; + this.openedMain.set(iframeStates.closed); this.resetStyleMain(); this.fire(); } @@ -386,14 +390,14 @@ class CoWebsiteManager { } this.cowebsiteDom.classList.add("opened"); - this.openedMain = iframeStates.loading; + this.openedMain.set(iframeStates.loading); } private openMain(): void { this.cowebsiteDom.addEventListener("transitionend", () => { this.resizeAllIframes(); }); - this.openedMain = iframeStates.opened; + this.openedMain.set(iframeStates.opened); } public resetStyleMain() { @@ -556,19 +560,12 @@ class CoWebsiteManager { mainCoWebsite.getId() !== coWebsite.getId() && mainCoWebsite.getState() !== "asleep" ) { - highlightedEmbedScreen.toggleHighlight({ - type: "cowebsite", - embed: mainCoWebsite, - }); + highlightedEmbedScreen.removeHighlight(); } this.resizeAllIframes(); } - public searchJitsi(): CoWebsite | undefined { - return get(jitsiCoWebsite); - } - public addCoWebsiteToStore(coWebsite: CoWebsite, position: number | undefined) { const coWebsitePosition = position === undefined ? get(coWebsites).length : position; coWebsites.add(coWebsite, coWebsitePosition); @@ -591,7 +588,7 @@ class CoWebsiteManager { } // Check if the main is hide - if (this.getMainCoWebsite() && this.openedMain === iframeStates.closed) { + if (this.getMainCoWebsite() && this.getMainState() === iframeStates.closed) { this.displayMain(); } @@ -665,7 +662,7 @@ class CoWebsiteManager { } public getGameSize(): { width: number; height: number } { - if (this.openedMain === iframeStates.closed) { + if (this.getMainState() === iframeStates.closed) { return { width: window.innerWidth, height: window.innerHeight, diff --git a/front/src/WebRtc/JitsiFactory.ts b/front/src/WebRtc/JitsiFactory.ts index 1faa9897..d328a72d 100644 --- a/front/src/WebRtc/JitsiFactory.ts +++ b/front/src/WebRtc/JitsiFactory.ts @@ -2,7 +2,6 @@ import { JITSI_URL } from "../Enum/EnvironmentVariable"; import { coWebsiteManager } from "./CoWebsiteManager"; import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore"; import { get } from "svelte/store"; -import type { CoWebsite } from "./CoWebsite/CoWesbite"; import CancelablePromise from "cancelable-promise"; interface jitsiConfigInterface { @@ -180,13 +179,14 @@ class JitsiFactory { const iframe = coWebsiteManager .getCoWebsiteBuffer() .querySelector('[id*="jitsi" i]'); + if (iframe && this.jitsiApi) { this.jitsiApi.addListener("videoConferenceLeft", () => { - this.closeOrUnload(); + this.closeOrUnload(iframe); }); this.jitsiApi.addListener("readyToClose", () => { - this.closeOrUnload(); + this.closeOrUnload(iframe); }); return resolve(iframe); @@ -209,8 +209,9 @@ class JitsiFactory { }); } - private closeOrUnload = function () { - const coWebsite = coWebsiteManager.searchJitsi(); + private closeOrUnload = function (iframe: HTMLIFrameElement) { + const coWebsite = coWebsiteManager.getCoWebsites().find((coWebsite) => coWebsite.getIframe() === iframe); + if (!coWebsite) { return; } @@ -224,30 +225,6 @@ class JitsiFactory { } }; - public restart() { - if (!this.jitsiApi) { - return; - } - - this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback); - this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback); - - const coWebsite = coWebsiteManager.searchJitsi(); - - if (!coWebsite) { - this.destroy(); - return; - } - - this.jitsiApi.addListener("videoConferenceLeft", () => { - this.closeOrUnload(); - }); - - this.jitsiApi.addListener("readyToClose", () => { - this.closeOrUnload(); - }); - } - public stop() { if (!this.jitsiApi) { return; diff --git a/front/src/i18n/de-DE/index.ts b/front/src/i18n/de-DE/index.ts index ab628a4d..40b63558 100644 --- a/front/src/i18n/de-DE/index.ts +++ b/front/src/i18n/de-DE/index.ts @@ -14,7 +14,7 @@ import warning from "./warning"; import woka from "./woka"; const de_DE: Translation = { - ...en_US, + ...(en_US as Translation), language: "Deutsch", country: "Deutschland", audio, diff --git a/front/src/i18n/en-US/index.ts b/front/src/i18n/en-US/index.ts index 2d3ac74a..b1a0e422 100644 --- a/front/src/i18n/en-US/index.ts +++ b/front/src/i18n/en-US/index.ts @@ -11,6 +11,7 @@ import menu from "./menu"; import report from "./report"; import warning from "./warning"; import emoji from "./emoji"; +import trigger from "./trigger"; const en_US: BaseTranslation = { language: "English", @@ -27,6 +28,7 @@ const en_US: BaseTranslation = { report, warning, emoji, + trigger, }; export default en_US; diff --git a/front/src/i18n/en-US/trigger.ts b/front/src/i18n/en-US/trigger.ts new file mode 100644 index 00000000..40e84bf4 --- /dev/null +++ b/front/src/i18n/en-US/trigger.ts @@ -0,0 +1,9 @@ +import type { BaseTranslation } from "../i18n-types"; + +const trigger: BaseTranslation = { + cowebsite: "Press SPACE or touch here to open web site", + jitsiRoom: "Press SPACE or touch here to enter Jitsi Meet room", + newTab: "Press SPACE or touch here to open web site in new tab", +}; + +export default trigger; diff --git a/front/src/i18n/fr-FR/index.ts b/front/src/i18n/fr-FR/index.ts index b9f91b13..77acbb4a 100644 --- a/front/src/i18n/fr-FR/index.ts +++ b/front/src/i18n/fr-FR/index.ts @@ -12,9 +12,10 @@ import menu from "./menu"; import report from "./report"; import warning from "./warning"; import woka from "./woka"; +import trigger from "./trigger"; const fr_FR: Translation = { - ...en_US, + ...(en_US as Translation), language: "Français", country: "France", audio, @@ -29,6 +30,7 @@ const fr_FR: Translation = { report, warning, emoji, + trigger, }; export default fr_FR; diff --git a/front/src/i18n/fr-FR/menu.ts b/front/src/i18n/fr-FR/menu.ts index 54481ec8..1ca20fd7 100644 --- a/front/src/i18n/fr-FR/menu.ts +++ b/front/src/i18n/fr-FR/menu.ts @@ -63,7 +63,7 @@ const menu: NonNullable = { }, fullscreen: "Plein écran", notifications: "Notifications", - cowebsiteTrigger: "Demander toujours avant d'ouvrir des sites web et des salles de réunion Jitsi", + cowebsiteTrigger: "Demander toujours avant d'ouvrir des sites web et des salles de conférence Jitsi", ignoreFollowRequest: "Ignorer les demandes de suivi des autres utilisateurs", }, invite: { diff --git a/front/src/i18n/fr-FR/trigger.ts b/front/src/i18n/fr-FR/trigger.ts new file mode 100644 index 00000000..5940e92a --- /dev/null +++ b/front/src/i18n/fr-FR/trigger.ts @@ -0,0 +1,9 @@ +import type { Translation } from "../i18n-types"; + +const trigger: NonNullable = { + cowebsite: "Appuyez sur ESPACE ou ici pour ouvrir le site Web", + jitsiRoom: "Appuyez sur ESPACE ou ici pour entrer dans la salle conférence Jitsi", + newTab: "Appuyez sur ESPACE ou ici pour ouvrir le site Web dans un nouvel onglet", +}; + +export default trigger;