diff --git a/front/src/Phaser/Game/GameMapPropertyChange.ts b/front/src/Phaser/Game/GameMapPropertyChange.ts index 929b94c8..76a7a3d4 100644 --- a/front/src/Phaser/Game/GameMapPropertyChange.ts +++ b/front/src/Phaser/Game/GameMapPropertyChange.ts @@ -18,7 +18,6 @@ export class GameMapPropertyChange { scriptUtils.openTab(newValue); } }); - this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => { if (newValue === undefined) { layoutManagerActionStore.removeAction("openWebsite"); @@ -29,11 +28,11 @@ export class GameMapPropertyChange { newValue as string, this.scene.MapUrlFile, allProps.get("openWebsiteAllowApi") as boolean | undefined, - allProps.get("openWebsitePolicy") as string | undefined + allProps.get("openWebsitePolicy") as string | undefined, + allProps.get("openWebsiteWidth") as number | undefined ); layoutManagerActionStore.removeAction("openWebsite"); }; - const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES); if (openWebsiteTriggerValue && openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) { let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 9ab097c5..d29c5e3c 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1809,8 +1809,9 @@ ${escapedMessage} "jitsiInterfaceConfig" ); const jitsiUrl = allProps.get("jitsiUrl") as string | undefined; + const jitsiWidth = allProps.get("jitsiWidth") as number | undefined; - jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl); + jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth); this.connection?.setSilent(true); mediaManager.hideGameOverlay(); diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index f2de3580..9f23beee 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -48,6 +48,10 @@ class CoWebsiteManager { this.cowebsiteDiv.style.width = width + "px"; } + set widthPercent(width: number) { + this.cowebsiteDiv.style.width = width + "%"; + } + get height(): number { return this.cowebsiteDiv.clientHeight; } @@ -162,7 +166,13 @@ class CoWebsiteManager { return iframe; } - public loadCoWebsite(url: string, base: string, allowApi?: boolean, allowPolicy?: string): void { + public loadCoWebsite( + url: string, + base: string, + allowApi?: boolean, + allowPolicy?: string, + widthPercent?: number + ): void { this.load(); this.cowebsiteMainDom.innerHTML = ``; @@ -186,6 +196,9 @@ class CoWebsiteManager { .then(() => Promise.race([onloadPromise, onTimeoutPromise])) .then(() => { this.open(); + if (widthPercent) { + this.widthPercent = widthPercent; + } setTimeout(() => { this.fire(); }, animationTime); @@ -199,13 +212,16 @@ class CoWebsiteManager { /** * Just like loadCoWebsite but the div can be filled by the user. */ - public insertCoWebsite(callback: (cowebsite: HTMLDivElement) => Promise): void { + public insertCoWebsite(callback: (cowebsite: HTMLDivElement) => Promise, widthPercent?: number): void { this.load(); this.cowebsiteMainDom.innerHTML = ``; this.currentOperationPromise = this.currentOperationPromise .then(() => callback(this.cowebsiteMainDom)) .then(() => { this.open(); + if (widthPercent) { + this.widthPercent = widthPercent; + } setTimeout(() => { this.fire(); }, animationTime); diff --git a/front/src/WebRtc/JitsiFactory.ts b/front/src/WebRtc/JitsiFactory.ts index d2b9ebdd..7a3264f1 100644 --- a/front/src/WebRtc/JitsiFactory.ts +++ b/front/src/WebRtc/JitsiFactory.ts @@ -1,37 +1,43 @@ -import {JITSI_URL} from "../Enum/EnvironmentVariable"; -import {mediaManager} from "./MediaManager"; -import {coWebsiteManager} from "./CoWebsiteManager"; -import {requestedCameraState, requestedMicrophoneState} from "../Stores/MediaStore"; -import {get} from "svelte/store"; -declare const window:any; // eslint-disable-line @typescript-eslint/no-explicit-any +import { JITSI_URL } from "../Enum/EnvironmentVariable"; +import { mediaManager } from "./MediaManager"; +import { coWebsiteManager } from "./CoWebsiteManager"; +import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore"; +import { get } from "svelte/store"; +declare const window: any; // eslint-disable-line @typescript-eslint/no-explicit-any interface jitsiConfigInterface { - startWithAudioMuted: boolean - startWithVideoMuted: boolean - prejoinPageEnabled: boolean + startWithAudioMuted: boolean; + startWithVideoMuted: boolean; + prejoinPageEnabled: boolean; } -const getDefaultConfig = () : jitsiConfigInterface => { +const getDefaultConfig = (): jitsiConfigInterface => { return { startWithAudioMuted: !get(requestedMicrophoneState), startWithVideoMuted: !get(requestedCameraState), - prejoinPageEnabled: false - } -} + prejoinPageEnabled: false, + }; +}; const mergeConfig = (config?: object) => { const currentDefaultConfig = getDefaultConfig(); - if(!config){ + if (!config) { return currentDefaultConfig; } return { ...currentDefaultConfig, ...config, - startWithAudioMuted: (config as jitsiConfigInterface).startWithAudioMuted ? true : currentDefaultConfig.startWithAudioMuted, - startWithVideoMuted: (config as jitsiConfigInterface).startWithVideoMuted ? true : currentDefaultConfig.startWithVideoMuted, - prejoinPageEnabled: (config as jitsiConfigInterface).prejoinPageEnabled ? true : currentDefaultConfig.prejoinPageEnabled - } -} + startWithAudioMuted: (config as jitsiConfigInterface).startWithAudioMuted + ? true + : currentDefaultConfig.startWithAudioMuted, + startWithVideoMuted: (config as jitsiConfigInterface).startWithVideoMuted + ? true + : currentDefaultConfig.startWithVideoMuted, + prejoinPageEnabled: (config as jitsiConfigInterface).prejoinPageEnabled + ? true + : currentDefaultConfig.prejoinPageEnabled, + }; +}; const defaultInterfaceConfig = { SHOW_CHROME_EXTENSION_BANNER: false, @@ -49,25 +55,45 @@ const defaultInterfaceConfig = { SHOW_WATERMARK_FOR_GUESTS: false, TOOLBAR_BUTTONS: [ - 'microphone', 'camera', 'closedcaptions', 'desktop', /*'embedmeeting',*/ 'fullscreen', - 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording', - 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand', - 'videoquality', 'filmstrip', /*'invite',*/ 'feedback', 'stats', 'shortcuts', - 'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone', /*'security'*/ + "microphone", + "camera", + "closedcaptions", + "desktop", + /*'embedmeeting',*/ "fullscreen", + "fodeviceselection", + "hangup", + "profile", + "chat", + "recording", + "livestreaming", + "etherpad", + "sharedvideo", + "settings", + "raisehand", + "videoquality", + "filmstrip", + /*'invite',*/ "feedback", + "stats", + "shortcuts", + "tileview", + "videobackgroundblur", + "download", + "help", + "mute-everyone" /*'security'*/, ], }; const slugify = (...args: (string | number)[]): string => { - const value = args.join(' ') + const value = args.join(" "); return value - .normalize('NFD') // split an accented letter in the base letter and the accent - .replace(/[\u0300-\u036f]/g, '') // remove all previously split accents + .normalize("NFD") // split an accented letter in the base letter and the accent + .replace(/[\u0300-\u036f]/g, "") // remove all previously split accents .toLowerCase() .trim() - .replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced) - .replace(/\s+/g, '-') // separator -} + .replace(/[^a-z0-9 ]/g, "") // remove all chars not letters, numbers and spaces (to be replaced) + .replace(/\s+/g, "-"); // separator +}; class JitsiFactory { private jitsiApi: any; // eslint-disable-line @typescript-eslint/no-explicit-any @@ -79,11 +105,19 @@ class JitsiFactory { * Slugifies the room name and prepends the room name with the instance */ public getRoomName(roomName: string, instance: string): string { - return slugify(instance.replace('/', '-') + "-" + roomName); + return slugify(instance.replace("/", "-") + "-" + roomName); } - public start(roomName: string, playerName:string, jwt?: string, config?: object, interfaceConfig?: object, jitsiUrl?: string): void { - coWebsiteManager.insertCoWebsite((async cowebsiteDiv => { + public start( + roomName: string, + playerName: string, + jwt?: string, + config?: object, + interfaceConfig?: object, + jitsiUrl?: string, + jitsiWidth?: number + ): void { + coWebsiteManager.insertCoWebsite(async (cowebsiteDiv) => { // Jitsi meet external API maintains some data in local storage // which is sent via the appData URL parameter when joining a // conference. Problem is that this data grows indefinitely. Thus @@ -94,18 +128,19 @@ class JitsiFactory { const domain = jitsiUrl || JITSI_URL; if (domain === undefined) { - throw new Error('Missing JITSI_URL environment variable or jitsiUrl parameter in the map.') + throw new Error("Missing JITSI_URL environment variable or jitsiUrl parameter in the map."); } await this.loadJitsiScript(domain); - const options: any = { // eslint-disable-line @typescript-eslint/no-explicit-any + const options: any = { + // eslint-disable-line @typescript-eslint/no-explicit-any roomName: roomName, jwt: jwt, width: "100%", height: "100%", parentNode: cowebsiteDiv, configOverwrite: mergeConfig(config), - interfaceConfigOverwrite: {...defaultInterfaceConfig, ...interfaceConfig} + interfaceConfigOverwrite: { ...defaultInterfaceConfig, ...interfaceConfig }, }; if (!options.jwt) { delete options.jwt; @@ -115,25 +150,25 @@ class JitsiFactory { options.onload = () => resolve(); //we want for the iframe to be loaded before triggering animations. setTimeout(() => resolve(), 2000); //failsafe in case the iframe is deleted before loading or too long to load this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options); - this.jitsiApi.executeCommand('displayName', playerName); + this.jitsiApi.executeCommand("displayName", playerName); - this.jitsiApi.addListener('audioMuteStatusChanged', this.audioCallback); - this.jitsiApi.addListener('videoMuteStatusChanged', this.videoCallback); + this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback); + this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback); }); - })); + }, jitsiWidth); } public async stop(): Promise { - if(!this.jitsiApi){ + if (!this.jitsiApi) { return; } await coWebsiteManager.closeCoWebsite(); - this.jitsiApi.removeListener('audioMuteStatusChanged', this.audioCallback); - this.jitsiApi.removeListener('videoMuteStatusChanged', this.videoCallback); + this.jitsiApi.removeListener("audioMuteStatusChanged", this.audioCallback); + this.jitsiApi.removeListener("videoMuteStatusChanged", this.videoCallback); this.jitsiApi?.dispose(); } - private onAudioChange({muted}: {muted: boolean}): void { + private onAudioChange({ muted }: { muted: boolean }): void { if (muted) { requestedMicrophoneState.disableMicrophone(); } else { @@ -141,7 +176,7 @@ class JitsiFactory { } } - private onVideoChange({muted}: {muted: boolean}): void { + private onVideoChange({ muted }: { muted: boolean }): void { if (muted) { requestedCameraState.disableWebcam(); } else { @@ -159,20 +194,17 @@ class JitsiFactory { this.jitsiScriptLoaded = true; // Load Jitsi if the environment variable is set. - const jitsiScript = document.createElement('script'); - jitsiScript.src = 'https://' + domain + '/external_api.js'; + const jitsiScript = document.createElement("script"); + jitsiScript.src = "https://" + domain + "/external_api.js"; jitsiScript.onload = () => { resolve(); - } + }; jitsiScript.onerror = () => { reject(); - } + }; document.head.appendChild(jitsiScript); - - }) - - + }); } }