diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte
index 1e846185..72b17109 100644
--- a/front/src/Components/App.svelte
+++ b/front/src/Components/App.svelte
@@ -29,6 +29,8 @@
import ConsoleGlobalMessageManager from "./ConsoleGlobalMessageManager/ConsoleGlobalMessageManager.svelte";
import {warningContainerStore} from "../Stores/MenuStore";
import WarningContainer from "./WarningContainer/WarningContainer.svelte";
+ import {layoutManagerVisibilityStore} from "../Stores/LayoutManagerStore";
+ import LayoutManager from "./LayoutManager/LayoutManager.svelte";
export let game: Game;
@@ -65,6 +67,11 @@
{/if}
+ {#if $layoutManagerVisibilityStore}
+
diff --git a/front/src/Components/LayoutManager/LayoutManager.svelte b/front/src/Components/LayoutManager/LayoutManager.svelte
new file mode 100644
index 00000000..ef90a4e3
--- /dev/null
+++ b/front/src/Components/LayoutManager/LayoutManager.svelte
@@ -0,0 +1,78 @@
+
+
+
+
+ {#each $layoutManagerActionStore as action}
+
onClick(action.callback)}>
+
{action.message}
+
+ {/each}
+
+
+
+
\ No newline at end of file
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index 31acb83a..4ba569d8 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -21,7 +21,6 @@ import {
AUDIO_VOLUME_PROPERTY,
Box,
JITSI_MESSAGE_PROPERTIES,
- layoutManager,
ON_ACTION_TRIGGER_BUTTON,
TRIGGER_JITSI_PROPERTIES,
TRIGGER_WEBSITE_PROPERTIES,
@@ -89,6 +88,8 @@ import { SharedVariablesManager } from "./SharedVariablesManager";
import { playersStore } from "../../Stores/PlayersStore";
import { chatVisibilityStore } from "../../Stores/ChatStore";
import { userIsAdminStore } from "../../Stores/GameStore";
+import { layoutManagerActionStore, layoutManagerVisibilityStore } from "../../Stores/LayoutManagerStore";
+import { get } from "svelte/store";
export interface GameSceneInitInterface {
initPosition: PointInterface | null;
@@ -793,7 +794,7 @@ export class GameScene extends DirtyScene {
});
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
if (newValue === undefined) {
- layoutManager.removeActionButton("openWebsite", this.userInputManager);
+ layoutManagerVisibilityStore.set(false);
coWebsiteManager.closeCoWebsite();
} else {
const openWebsiteFunction = () => {
@@ -803,7 +804,7 @@ export class GameScene extends DirtyScene {
allProps.get("openWebsiteAllowApi") as boolean | undefined,
allProps.get("openWebsitePolicy") as string | undefined
);
- layoutManager.removeActionButton("openWebsite", this.userInputManager);
+ layoutManagerVisibilityStore.set(false);
};
const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES);
@@ -812,14 +813,13 @@ export class GameScene extends DirtyScene {
if (message === undefined) {
message = "Press SPACE or touch here to open web site";
}
- layoutManager.addActionButton(
- "openWebsite",
- message.toString(),
- () => {
- openWebsiteFunction();
- },
- this.userInputManager
- );
+ layoutManagerActionStore.addAction({
+ type: "openWebsite",
+ message: message,
+ callback: () => openWebsiteFunction(),
+ userInputManager: this.userInputManager,
+ });
+ layoutManagerVisibilityStore.set(true);
} else {
openWebsiteFunction();
}
@@ -827,7 +827,7 @@ export class GameScene extends DirtyScene {
});
this.gameMap.onPropertyChange("jitsiRoom", (newValue, oldValue, allProps) => {
if (newValue === undefined) {
- layoutManager.removeActionButton("jitsiRoom", this.userInputManager);
+ layoutManagerVisibilityStore.set(false);
this.stopJitsi();
} else {
const openJitsiRoomFunction = () => {
@@ -840,7 +840,7 @@ export class GameScene extends DirtyScene {
} else {
this.startJitsi(roomName, undefined);
}
- layoutManager.removeActionButton("jitsiRoom", this.userInputManager);
+ layoutManagerVisibilityStore.set(false);
};
const jitsiTriggerValue = allProps.get(TRIGGER_JITSI_PROPERTIES);
@@ -849,14 +849,13 @@ export class GameScene extends DirtyScene {
if (message === undefined) {
message = "Press SPACE or touch here to enter Jitsi Meet room";
}
- layoutManager.addActionButton(
- "jitsiRoom",
- message.toString(),
- () => {
- openJitsiRoomFunction();
- },
- this.userInputManager
- );
+ layoutManagerActionStore.addAction({
+ type: "jitsiRoom",
+ message: message,
+ callback: () => openJitsiRoomFunction(),
+ userInputManager: this.userInputManager,
+ });
+ layoutManagerVisibilityStore.set(true);
} else {
openJitsiRoomFunction();
}
@@ -1153,7 +1152,7 @@ ${escapedMessage}
let targetRoom: Room;
try {
targetRoom = await Room.createRoom(roomUrl);
- } catch (e: unknown) {
+ } catch (e) {
console.error('Error while fetching new room "' + roomUrl.toString() + '"', e);
this.mapTransitioning = false;
return;
@@ -1279,7 +1278,7 @@ ${escapedMessage}
try {
const room = await Room.createRoom(exitRoomPath);
return gameManager.loadMap(room, this.scene);
- } catch (e: unknown) {
+ } catch (e) {
console.warn('Error while pre-loading exit room "' + exitRoomPath.toString() + '"', e);
}
}
diff --git a/front/src/Stores/LayoutManagerStore.ts b/front/src/Stores/LayoutManagerStore.ts
new file mode 100644
index 00000000..41fd283d
--- /dev/null
+++ b/front/src/Stores/LayoutManagerStore.ts
@@ -0,0 +1,53 @@
+import { writable } from "svelte/store";
+import type { UserInputManager } from "../Phaser/UserInput/UserInputManager";
+
+export interface LayoutManagerAction {
+ type: string;
+ message: string | number | boolean | undefined;
+ callback: () => void;
+ userInputManager: UserInputManager | undefined;
+}
+
+export const layoutManagerVisibilityStore = writable(false);
+
+function createLayoutManagerAction() {
+ const { subscribe, set, update } = writable
([]);
+
+ return {
+ subscribe,
+ addAction: (newAction: LayoutManagerAction): void => {
+ update((list: LayoutManagerAction[]) => {
+ let found = false;
+ for (const actions of list) {
+ if (actions.type === newAction.type && actions.message === newAction.message) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ list.push(newAction);
+ }
+
+ return list;
+ });
+ },
+ removeAction: (oldAction: LayoutManagerAction): void => {
+ update((list: LayoutManagerAction[]) => {
+ const index = list.findIndex(
+ (actions) => actions.type === oldAction.type && actions.message === oldAction.message
+ );
+
+ if (index !== -1) {
+ list.splice(index, 1);
+ }
+
+ return list;
+ });
+ },
+ clearActions: (): void => {
+ set([]);
+ },
+ };
+}
+
+export const layoutManagerActionStore = createLayoutManagerAction();
diff --git a/front/src/WebRtc/LayoutManager.ts b/front/src/WebRtc/LayoutManager.ts
index 47864139..0d9a4ba9 100644
--- a/front/src/WebRtc/LayoutManager.ts
+++ b/front/src/WebRtc/LayoutManager.ts
@@ -1,6 +1,3 @@
-import type { UserInputManager } from "../Phaser/UserInput/UserInputManager";
-import { HtmlUtils } from "./HtmlUtils";
-
export enum LayoutMode {
// All videos are displayed on the right side of the screen. If there is a screen sharing, it is displayed in the middle.
Presentation = "Presentation",
@@ -27,85 +24,3 @@ export const AUDIO_VOLUME_PROPERTY = "audioVolume";
export const AUDIO_LOOP_PROPERTY = "audioLoop";
export type Box = { xStart: number; yStart: number; xEnd: number; yEnd: number };
-
-class LayoutManager {
- private actionButtonTrigger: Map = new Map();
- private actionButtonInformation: Map = new Map();
-
- public addActionButton(id: string, text: string, callBack: Function, userInputManager: UserInputManager) {
- //delete previous element
- this.removeActionButton(id, userInputManager);
-
- //create div and text html component
- const p = document.createElement("p");
- p.classList.add("action-body");
- p.innerText = text;
-
- const div = document.createElement("div");
- div.classList.add("action");
- div.id = id;
- div.appendChild(p);
-
- this.actionButtonInformation.set(id, div);
-
- const mainContainer = HtmlUtils.getElementByIdOrFail("main-container");
- mainContainer.appendChild(div);
-
- //add trigger action
- div.onpointerdown = () => callBack();
- this.actionButtonTrigger.set(id, callBack);
- userInputManager.addSpaceEventListner(callBack);
- }
-
- public removeActionButton(id: string, userInputManager?: UserInputManager) {
- //delete previous element
- const previousDiv = this.actionButtonInformation.get(id);
- if (previousDiv) {
- previousDiv.remove();
- this.actionButtonInformation.delete(id);
- }
- const previousEventCallback = this.actionButtonTrigger.get(id);
- if (previousEventCallback && userInputManager) {
- userInputManager.removeSpaceEventListner(previousEventCallback);
- }
- }
-
- public addInformation(id: string, text: string, callBack?: Function, userInputManager?: UserInputManager) {
- //delete previous element
- for (const [key, value] of this.actionButtonInformation) {
- this.removeActionButton(key, userInputManager);
- }
-
- //create div and text html component
- const p = document.createElement("p");
- p.classList.add("action-body");
- p.innerText = text;
-
- const div = document.createElement("div");
- div.classList.add("action");
- div.classList.add(id);
- div.id = id;
- div.appendChild(p);
-
- this.actionButtonInformation.set(id, div);
-
- const mainContainer = HtmlUtils.getElementByIdOrFail("main-container");
- mainContainer.appendChild(div);
- //add trigger action
- if (callBack) {
- div.onpointerdown = () => {
- callBack();
- this.removeActionButton(id, userInputManager);
- };
- }
-
- //remove it after 10 sec
- setTimeout(() => {
- this.removeActionButton(id, userInputManager);
- }, 10000);
- }
-}
-
-const layoutManager = new LayoutManager();
-
-export { layoutManager };
diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts
index d7e9f514..2f8c637a 100644
--- a/front/src/WebRtc/MediaManager.ts
+++ b/front/src/WebRtc/MediaManager.ts
@@ -1,4 +1,3 @@
-import { layoutManager } from "./LayoutManager";
import { HtmlUtils } from "./HtmlUtils";
import type { UserInputManager } from "../Phaser/UserInput/UserInputManager";
import { localStreamStore } from "../Stores/MediaStore";
@@ -10,6 +9,8 @@ export type StopScreenSharingCallback = (media: MediaStream) => void;
import { cowebsiteCloseButtonId } from "./CoWebsiteManager";
import { gameOverlayVisibilityStore } from "../Stores/GameOverlayStoreVisibility";
+import { layoutManagerActionStore, layoutManagerVisibilityStore } from "../Stores/LayoutManagerStore";
+import { get } from "svelte/store";
export class MediaManager {
startScreenSharingCallBacks: Set = new Set();
@@ -23,14 +24,16 @@ export class MediaManager {
localStreamStore.subscribe((result) => {
if (result.type === "error") {
console.error(result.error);
- layoutManager.addInformation(
- "warning",
- "Camera access denied. Click here and check your browser permissions.",
- () => {
+ layoutManagerActionStore.addAction({
+ type: "warning",
+ message: "Camera access denied. Click here and check your browser permissions.",
+ callback: () => {
helpCameraSettingsVisibleStore.set(true);
+ layoutManagerVisibilityStore.set(false);
},
- this.userInputManager
- );
+ userInputManager: this.userInputManager,
+ });
+ layoutManagerVisibilityStore.set(true);
return;
}
});
@@ -38,14 +41,16 @@ export class MediaManager {
screenSharingLocalStreamStore.subscribe((result) => {
if (result.type === "error") {
console.error(result.error);
- layoutManager.addInformation(
- "warning",
- "Screen sharing denied. Click here and check your browser permissions.",
- () => {
+ layoutManagerActionStore.addAction({
+ type: "warning",
+ message: "Screen sharing denied. Click here and check your browser permissions.",
+ callback: () => {
helpCameraSettingsVisibleStore.set(true);
+ layoutManagerVisibilityStore.set(false);
},
- this.userInputManager
- );
+ userInputManager: this.userInputManager,
+ });
+ layoutManagerVisibilityStore.set(true);
return;
}
});