Migration of registerCustomMenu for Menu in Svelte
Refactor subMenuStore Suppression of old MenuScene and ReportMenu
This commit is contained in:
parent
9c1926f636
commit
8105e966ff
18 changed files with 137 additions and 617 deletions
|
@ -1,5 +1,6 @@
|
|||
import * as tg from "generic-type-guard";
|
||||
import { Subject } from "rxjs";
|
||||
import { subMenusStore } from "../../../Stores/MenuStore";
|
||||
|
||||
export const isMenuItemRegisterEvent = new tg.IsInterface()
|
||||
.withProperties({
|
||||
|
@ -22,5 +23,5 @@ const _registerMenuCommandStream: Subject<string> = new Subject();
|
|||
export const registerMenuCommandStream = _registerMenuCommandStream.asObservable();
|
||||
|
||||
export function handleMenuItemRegistrationEvent(event: MenuItemRegisterEvent) {
|
||||
_registerMenuCommandStream.next(event.menutItem);
|
||||
subMenusStore.addMenu(event.menutItem);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
|
|||
import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
||||
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
||||
import { EmbeddedWebsite } from "./iframe/Room/EmbeddedWebsite";
|
||||
import { subMenusStore } from "../Stores/MenuStore";
|
||||
|
||||
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
||||
query: IframeQueryMap[T]["query"],
|
||||
|
@ -93,12 +94,6 @@ class IframeListener {
|
|||
private readonly _setPropertyStream: Subject<SetPropertyEvent> = new Subject();
|
||||
public readonly setPropertyStream = this._setPropertyStream.asObservable();
|
||||
|
||||
private readonly _registerMenuCommandStream: Subject<string> = new Subject();
|
||||
public readonly registerMenuCommandStream = this._registerMenuCommandStream.asObservable();
|
||||
|
||||
private readonly _unregisterMenuCommandStream: Subject<string> = new Subject();
|
||||
public readonly unregisterMenuCommandStream = this._unregisterMenuCommandStream.asObservable();
|
||||
|
||||
private readonly _playSoundStream: Subject<PlaySoundEvent> = new Subject();
|
||||
public readonly playSoundStream = this._playSoundStream.asObservable();
|
||||
|
||||
|
@ -264,7 +259,7 @@ class IframeListener {
|
|||
const data = payload.data.menutItem;
|
||||
// @ts-ignore
|
||||
this.iframeCloseCallbacks.get(iframe).push(() => {
|
||||
this._unregisterMenuCommandStream.next(data);
|
||||
subMenusStore.removeMenu(data);
|
||||
});
|
||||
handleMenuItemRegistrationEvent(payload.data);
|
||||
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import type { MenuItemClickedEvent } from "../../Events/ui/MenuItemClickedEvent"
|
|||
import { iframeListener } from "../../IframeListener";
|
||||
|
||||
export function sendMenuClickedEvent(menuItem: string) {
|
||||
console.log("Menu " + menuItem);
|
||||
iframeListener.postMessage({
|
||||
type: "menuItemClicked",
|
||||
data: {
|
||||
|
|
|
@ -51,6 +51,7 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
|
|||
type: "menuItemClicked",
|
||||
typeChecker: isMenuItemClickedEvent,
|
||||
callback: (event) => {
|
||||
console.log("BOUM : " + event.menuItem);
|
||||
const callback = menuCallbacks.get(event.menuItem);
|
||||
if (callback) {
|
||||
callback(event.menuItem);
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<button type="button" class="nes-btn is-primary" on:click={copyLink}>Copy</button>
|
||||
</section>
|
||||
<section class="presentation-map">
|
||||
<p>This room use this map : </p>
|
||||
<p>This room use the following map : </p>
|
||||
<h3>{mapName}</h3>
|
||||
<p class="string-HTML">{mapDescription}</p>
|
||||
</section>
|
||||
|
|
|
@ -22,37 +22,37 @@
|
|||
The WorkAdventure team has its own offices in ... WorkAdventure!
|
||||
Do not hesitate to come see and talk to us.
|
||||
</p>
|
||||
<a href="https://play.staging.workadventu.re/@tcm/workadventure/wa-village" target="_blank">Visit us</a>
|
||||
<a class="nes-pointer" href="https://play.staging.workadventu.re/@tcm/workadventure/wa-village" target="_blank">Visit us</a>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Our Mail</h3>
|
||||
<p>Although we offer a solution to reduce their use, we have an email address that allows us to receive all your requests.</p>
|
||||
<a href="mailto:hello@workadventu.re" target="_blank">hello@workadventu.re</a>
|
||||
<a class="nes-pointer" href="mailto:hello@workadventu.re" target="_blank">hello@workadventu.re</a>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Our web site</h3>
|
||||
<p>If you want to know more about us, follow the link to our web site.</p>
|
||||
<a href="https://workadventu.re/about-us" target="_blank">About us</a>
|
||||
<a class="nes-pointer" href="https://workadventu.re/about-us" target="_blank">About us</a>
|
||||
</section>
|
||||
<section>
|
||||
<h3>Our social media</h3>
|
||||
<a href="https://discord.gg/YGtngdh9gt" target="_blank">
|
||||
<img src="{discordImg}" alt="{'Discord'}">
|
||||
<img class="nes-pointer" src="{discordImg}" alt="{'Discord'}">
|
||||
</a>
|
||||
<a href="https://www.facebook.com/workadventure.WA" target="_blank">
|
||||
<img src="{facebookImg}" alt="{'Facebook'}">
|
||||
<img class="nes-pointer" src="{facebookImg}" alt="{'Facebook'}">
|
||||
</a>
|
||||
<a href="https://www.instagram.com/workadventure_/" target="_blank">
|
||||
<img src="{instagramImg}" alt="{'Instagram'}">
|
||||
<img class="nes-pointer" src="{instagramImg}" alt="{'Instagram'}">
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/company/workadventure-by-tcm/" target="_blank">
|
||||
<img src="{linkedinImg}" alt="{'LinkedIn'}">
|
||||
<img class="nes-pointer" src="{linkedinImg}" alt="{'LinkedIn'}">
|
||||
</a>
|
||||
<a href="https://twitter.com/Workadventure_" target="_blank">
|
||||
<img src="{twitterImg}" alt="{'Twitter'}">
|
||||
<img class="nes-pointer" src="{twitterImg}" alt="{'Twitter'}">
|
||||
</a>
|
||||
<a href="https://www.youtube.com/channel/UCXJ9igV-kb9gw1ftR33y5tA" target="_blank">
|
||||
<img src="{youtubeImg}" alt="{'Youtube'}">
|
||||
<img class="nes-pointer" src="{youtubeImg}" alt="{'Youtube'}">
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
|
|
13
front/src/Components/Menu/CustomSubMenu.svelte
Normal file
13
front/src/Components/Menu/CustomSubMenu.svelte
Normal file
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts">
|
||||
import {sendMenuClickedEvent} from "../../Api/iframe/Ui/MenuItem";
|
||||
|
||||
export let menuCommand: string;
|
||||
|
||||
function menuItemClicked() {
|
||||
sendMenuClickedEvent(menuCommand);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<button type="button" class="nes-btn is-primary" on:click|preventDefault={menuItemClicked}>{menuCommand}</button>
|
||||
</div>
|
|
@ -1,32 +1,57 @@
|
|||
<script lang="typescript">
|
||||
import {fly} from "svelte/transition";
|
||||
import type { SvelteComponent } from "svelte";
|
||||
import SettingsSubMenu from "./SettingsSubMenu.svelte";
|
||||
import CreateMapSubMenu from "./CreateMapSubMenu.svelte";
|
||||
import ProfileSubMenu from "./ProfileSubMenu.svelte";
|
||||
import ContactSubMenu from "./ContactSubMenu.svelte";
|
||||
import CreateMapSubMenu from "./CreateMapSubMenu.svelte";
|
||||
import AboutRoomSubMenu from "./AboutRoomSubMenu.svelte";
|
||||
import GlobalMessagesSubMenu from "./GlobalMessagesSubMenu.svelte";
|
||||
import {menuVisiblilityStore} from "../../Stores/MenuStore";
|
||||
import GlobalMessageSubMenu from "./GlobalMessagesSubMenu.svelte";
|
||||
import ContactSubMenu from "./ContactSubMenu.svelte";
|
||||
import CustomSubMenu from "./CustomSubMenu.svelte";
|
||||
import {menuVisiblilityStore, SubMenusInterface, subMenusStore} from "../../Stores/MenuStore";
|
||||
import {userIsAdminStore} from "../../Stores/GameStore";
|
||||
import {onMount} from "svelte";
|
||||
import {get} from "svelte/store";
|
||||
|
||||
//TODO: When we register a new custom menu we need to add it here
|
||||
const SubMenus = new Map<string, typeof SvelteComponent>([
|
||||
['Settings', SettingsSubMenu],
|
||||
['Profile', ProfileSubMenu],
|
||||
['Create a Map', CreateMapSubMenu],
|
||||
['About the room', AboutRoomSubMenu],
|
||||
['Global Messages', GlobalMessagesSubMenu], //Remove if player has not the admin tag
|
||||
['Contact', ContactSubMenu] //Always last (except custom)
|
||||
]);
|
||||
let activeSubMenu: string = SubMenusInterface.settings;
|
||||
let props: { menuCommand: string } = { menuCommand: SubMenusInterface.settings};
|
||||
let activeComponent: typeof SettingsSubMenu | typeof CustomSubMenu = SettingsSubMenu;
|
||||
|
||||
let activeSubMenu = 'Settings';
|
||||
let activeComponent = SubMenus.get(activeSubMenu);
|
||||
onMount(() => {
|
||||
if(!get(userIsAdminStore)) {
|
||||
subMenusStore.removeMenu(SubMenusInterface.globalMessages);
|
||||
}
|
||||
|
||||
switchMenu(SubMenusInterface.settings);
|
||||
})
|
||||
|
||||
function switchMenu(menu: string) {
|
||||
if (SubMenus.has(menu)) {
|
||||
activeSubMenu = menu
|
||||
activeComponent = SubMenus.get(activeSubMenu);
|
||||
}
|
||||
if (get(subMenusStore).find((subMenu) => subMenu === menu)) {
|
||||
activeSubMenu = menu;
|
||||
props = {menuCommand: menu};
|
||||
switch (menu) {
|
||||
case SubMenusInterface.settings:
|
||||
activeComponent = SettingsSubMenu;
|
||||
break;
|
||||
case SubMenusInterface.profile:
|
||||
activeComponent = ProfileSubMenu;
|
||||
break;
|
||||
case SubMenusInterface.createMap:
|
||||
activeComponent = CreateMapSubMenu;
|
||||
break;
|
||||
case SubMenusInterface.aboutRoom:
|
||||
activeComponent = AboutRoomSubMenu;
|
||||
break;
|
||||
case SubMenusInterface.globalMessages:
|
||||
activeComponent = GlobalMessageSubMenu;
|
||||
break;
|
||||
case SubMenusInterface.contact:
|
||||
activeComponent = ContactSubMenu;
|
||||
break;
|
||||
default:
|
||||
activeComponent = CustomSubMenu;
|
||||
break;
|
||||
}
|
||||
} else throw ("There is no menu called " + menu);
|
||||
}
|
||||
|
||||
function closeMenu() {
|
||||
|
@ -46,16 +71,16 @@
|
|||
<div class="menu-nav-sidebar nes-container is-rounded" transition:fly="{{ x: -1000, duration: 500 }}">
|
||||
<h2>Menu</h2>
|
||||
<nav>
|
||||
{#each [...SubMenus] as [submenuKey, submenuComponent]}
|
||||
<button type="button" class="nes-btn {activeComponent === submenuComponent ? 'is-disabled' : ''}" on:click|preventDefault={() => switchMenu(submenuKey)}>{submenuKey}</button>
|
||||
{#each $subMenusStore as submenu}
|
||||
<button type="button" class="nes-btn {activeSubMenu === submenu ? 'is-disabled' : ''}" on:click|preventDefault={() => switchMenu(submenu)}>
|
||||
{submenu}
|
||||
</button>
|
||||
{/each}
|
||||
</nav>
|
||||
</div>
|
||||
<div class="menu-submenu-container nes-container is-rounded" transition:fly="{{ y: -1000, duration: 500 }}">
|
||||
<h2>{activeSubMenu}</h2>
|
||||
{#if activeComponent}
|
||||
<svelte:component this="{activeComponent}"/>
|
||||
{/if}
|
||||
<svelte:component this={activeComponent} {...props}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -65,7 +90,7 @@
|
|||
}
|
||||
|
||||
div.menu-container-main {
|
||||
--size-first-columns-grid: 15%; //TODO: clamp value
|
||||
--size-first-columns-grid: 15%;
|
||||
|
||||
font-family: "Press Start 2P";
|
||||
pointer-events: auto;
|
||||
|
|
|
@ -2,13 +2,21 @@
|
|||
import {menuVisiblilityStore} from "../../Stores/MenuStore";
|
||||
import {get} from "svelte/store";
|
||||
|
||||
function openMenu(){
|
||||
function showMenu(){
|
||||
menuVisiblilityStore.set(!get(menuVisiblilityStore))
|
||||
}
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
if (e.key === "Tab") {
|
||||
showMenu();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={onKeyDown}/>
|
||||
|
||||
<main class="menuIcon">
|
||||
<img src="/static/images/logo-WA-min.png" alt="open menu" on:click|preventDefault={openMenu}>
|
||||
<img src="/static/images/logo-WA-min.png" alt="open menu" class="nes-pointer" on:click|preventDefault={showMenu}>
|
||||
</main>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -18,7 +26,6 @@
|
|||
img {
|
||||
width: 60px;
|
||||
padding-top: 0;
|
||||
//cursor: url('/resources/logos/cursor_pointer.png'), pointer;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-height: 700px) {
|
||||
|
|
|
@ -54,7 +54,7 @@ function changeNotification() {
|
|||
<div class="settings-main" on:submit|preventDefault={saveSetting}>
|
||||
<section>
|
||||
<h3>Game quality</h3>
|
||||
<select bind:value={valueGame}>
|
||||
<select class="nes-pointer" bind:value={valueGame}>
|
||||
<option value="{120}">High video quality (120 fps)</option>
|
||||
<option value="{60}">Medium video quality (60 fps, recommended)</option>
|
||||
<option value="{40}">Minimum video quality (40 fps)</option>
|
||||
|
@ -63,7 +63,7 @@ function changeNotification() {
|
|||
</section>
|
||||
<section>
|
||||
<h3>Video quality</h3>
|
||||
<select bind:value={valueVideo}>
|
||||
<select class="nes-pointer" bind:value={valueVideo}>
|
||||
<option value="{30}">High video quality (30 fps)</option>
|
||||
<option value="{20}">Medium video quality (20 fps, recommended)</option>
|
||||
<option value="{10}">Minimum video quality (10 fps)</option>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { GameScene } from "./GameScene";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import type { Room } from "../../Connexion/Room";
|
||||
import { MenuScene, MenuSceneName } from "../Menu/MenuScene";
|
||||
import { LoginSceneName } from "../Login/LoginScene";
|
||||
import { SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import { EnableCameraSceneName } from "../Login/EnableCameraScene";
|
||||
|
@ -85,7 +84,6 @@ export class GameManager {
|
|||
public goToStartingMap(): void {
|
||||
console.log("starting " + (this.currentGameSceneName || this.startRoom.key));
|
||||
this.scenePlugin.start(this.currentGameSceneName || this.startRoom.key);
|
||||
this.scenePlugin.launch(MenuSceneName);
|
||||
|
||||
if (
|
||||
!localUserStore.getHelpCameraSettingsShown() &&
|
||||
|
@ -98,8 +96,6 @@ export class GameManager {
|
|||
|
||||
public gameSceneIsCreated(scene: GameScene) {
|
||||
this.currentGameSceneName = scene.scene.key;
|
||||
const menuScene: MenuScene = scene.scene.get(MenuSceneName) as MenuScene;
|
||||
menuScene.revealMenuIcon();
|
||||
menuIconVisiblilityStore.set(true);
|
||||
}
|
||||
|
||||
|
@ -112,7 +108,7 @@ export class GameManager {
|
|||
const gameScene: GameScene = this.scenePlugin.get(this.currentGameSceneName) as GameScene;
|
||||
gameScene.cleanupClosingScene();
|
||||
this.scenePlugin.stop(this.currentGameSceneName);
|
||||
this.scenePlugin.sleep(MenuSceneName);
|
||||
menuIconVisiblilityStore.set(false);
|
||||
if (!this.scenePlugin.get(targetSceneName)) {
|
||||
this.scenePlugin.add(targetSceneName, sceneClass, false);
|
||||
}
|
||||
|
@ -125,7 +121,7 @@ export class GameManager {
|
|||
tryResumingGame(fallbackSceneName: string) {
|
||||
if (this.currentGameSceneName) {
|
||||
this.scenePlugin.start(this.currentGameSceneName);
|
||||
this.scenePlugin.wake(MenuSceneName);
|
||||
menuIconVisiblilityStore.set(true);
|
||||
} else {
|
||||
this.scenePlugin.run(fallbackSceneName);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ import type { ActionableItem } from "../Items/ActionableItem";
|
|||
import type { ItemFactoryInterface } from "../Items/ItemFactoryInterface";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import type { ITiledMap, ITiledMapLayer, ITiledMapProperty, ITiledMapObject, ITiledTileSet } from "../Map/ITiledMap";
|
||||
import { MenuScene, MenuSceneName } from "../Menu/MenuScene";
|
||||
import { PlayerAnimationDirections } from "../Player/Animation";
|
||||
import { hasMovedEventName, Player, requestEmoteEventName } from "../Player/Player";
|
||||
import { ErrorSceneName } from "../Reconnecting/ErrorScene";
|
||||
|
@ -1298,9 +1297,6 @@ ${escapedMessage}
|
|||
urlManager.pushStartLayerNameToUrl(roomUrl.hash);
|
||||
}
|
||||
|
||||
const menuScene: MenuScene = this.scene.get(MenuSceneName) as MenuScene;
|
||||
menuScene.reset();
|
||||
|
||||
if (!targetRoom.isEqual(this.room)) {
|
||||
if (this.scene.get(targetRoom.key) === null) {
|
||||
console.error("next room not loaded", targetRoom.key);
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
import { gameManager } from "../Game/GameManager";
|
||||
import { TextField } from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import { mediaManager } from "../../WebRtc/MediaManager";
|
||||
import { SoundMeter } from "../Components/SoundMeter";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||
import { PinchManager } from "../UserInput/PinchManager";
|
||||
import Zone = Phaser.GameObjects.Zone;
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import { ResizableScene } from "./ResizableScene";
|
||||
import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import type { CompanionResourceDescriptionInterface } from "../Companion/Compani
|
|||
import { getAllCompanionResources } from "../Companion/CompanionTexturesLoadingManager";
|
||||
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||
import { PinchManager } from "../UserInput/PinchManager";
|
||||
import { MenuScene } from "../Menu/MenuScene";
|
||||
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
|
||||
import { waScaleManager } from "../Services/WaScaleManager";
|
||||
import { isMobile } from "../../Enum/EnvironmentVariable";
|
||||
|
|
|
@ -1,429 +0,0 @@
|
|||
import { LoginScene, LoginSceneName } from "../Login/LoginScene";
|
||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../Login/SelectCharacterScene";
|
||||
import { SelectCompanionScene, SelectCompanionSceneName } from "../Login/SelectCompanionScene";
|
||||
import { gameManager } from "../Game/GameManager";
|
||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||
import { gameReportKey, gameReportRessource, ReportMenu } from "./ReportMenu";
|
||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||
import { GameConnexionTypes } from "../../Url/UrlManager";
|
||||
import { menuIconVisiblilityStore, menuVisiblilityStore } from "../../Stores/MenuStore";
|
||||
import { videoConstraintStore } from "../../Stores/MediaStore";
|
||||
import { showReportScreenStore } from "../../Stores/ShowReportScreenStore";
|
||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||
import { iframeListener } from "../../Api/IframeListener";
|
||||
import { Subscription } from "rxjs";
|
||||
import { registerMenuCommandStream } from "../../Api/Events/ui/MenuItemRegisterEvent";
|
||||
import { sendMenuClickedEvent } from "../../Api/iframe/Ui/MenuItem";
|
||||
import { consoleGlobalMessageManagerVisibleStore } from "../../Stores/ConsoleGlobalMessageManagerStore";
|
||||
import { get } from "svelte/store";
|
||||
import { playersStore } from "../../Stores/PlayersStore";
|
||||
import { mediaManager } from "../../WebRtc/MediaManager";
|
||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
||||
import { ADMIN_URL } from "../../Enum/EnvironmentVariable";
|
||||
|
||||
export const MenuSceneName = "MenuScene";
|
||||
const gameMenuKey = "gameMenu";
|
||||
const gameMenuIconKey = "gameMenuIcon";
|
||||
const gameSettingsMenuKey = "gameSettingsMenu";
|
||||
const gameShare = "gameShare";
|
||||
|
||||
const closedSideMenuX = -1000;
|
||||
const openedSideMenuX = 0;
|
||||
|
||||
/**
|
||||
* The scene that manages the game menu, rendered using a DOM element.
|
||||
*/
|
||||
export class MenuScene extends Phaser.Scene {
|
||||
private menuElement!: Phaser.GameObjects.DOMElement;
|
||||
private gameQualityMenuElement!: Phaser.GameObjects.DOMElement;
|
||||
private gameShareElement!: Phaser.GameObjects.DOMElement;
|
||||
private gameReportElement!: ReportMenu;
|
||||
private sideMenuOpened = false;
|
||||
private settingsMenuOpened = false;
|
||||
private gameShareOpened = false;
|
||||
private gameQualityValue: number;
|
||||
private videoQualityValue: number;
|
||||
private menuButton!: Phaser.GameObjects.DOMElement;
|
||||
private subscriptions = new Subscription();
|
||||
constructor() {
|
||||
super({ key: MenuSceneName });
|
||||
|
||||
this.gameQualityValue = localUserStore.getGameQualityValue();
|
||||
this.videoQualityValue = localUserStore.getVideoQualityValue();
|
||||
|
||||
this.subscriptions.add(
|
||||
registerMenuCommandStream.subscribe((menuCommand) => {
|
||||
this.addMenuOption(menuCommand);
|
||||
})
|
||||
);
|
||||
|
||||
this.subscriptions.add(
|
||||
iframeListener.unregisterMenuCommandStream.subscribe((menuCommand) => {
|
||||
this.destroyMenu(menuCommand);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
reset() {
|
||||
const addedMenuItems = [...this.menuElement.node.querySelectorAll(".fromApi")];
|
||||
for (let index = addedMenuItems.length - 1; index >= 0; index--) {
|
||||
addedMenuItems[index].remove();
|
||||
}
|
||||
}
|
||||
|
||||
public addMenuOption(menuText: string) {
|
||||
const wrappingSection = document.createElement("section");
|
||||
const escapedHtml = HtmlUtils.escapeHtml(menuText);
|
||||
wrappingSection.innerHTML = `<button class="fromApi" id="${escapedHtml}">${escapedHtml}</button>`;
|
||||
const menuItemContainer = this.menuElement.node.querySelector("#gameMenu main");
|
||||
if (menuItemContainer) {
|
||||
menuItemContainer.querySelector(`#${escapedHtml}.fromApi`)?.remove();
|
||||
menuItemContainer.insertBefore(wrappingSection, menuItemContainer.querySelector("#socialLinks"));
|
||||
}
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.html(gameMenuKey, "resources/html/gameMenu.html");
|
||||
this.load.html(gameMenuIconKey, "resources/html/gameMenuIcon.html");
|
||||
this.load.html(gameSettingsMenuKey, "resources/html/gameQualityMenu.html");
|
||||
this.load.html(gameShare, "resources/html/gameShare.html");
|
||||
this.load.html(gameReportKey, gameReportRessource);
|
||||
}
|
||||
|
||||
create() {
|
||||
this.menuElement = this.add.dom(closedSideMenuX, 30).createFromCache(gameMenuKey);
|
||||
this.menuElement.setOrigin(0);
|
||||
MenuScene.revealMenusAfterInit(this.menuElement, "gameMenu");
|
||||
|
||||
if (mediaManager.hasNotification()) {
|
||||
HtmlUtils.getElementByIdOrFail("enableNotification").hidden = true;
|
||||
}
|
||||
|
||||
const middleX = window.innerWidth / 3 - 298;
|
||||
this.gameQualityMenuElement = this.add.dom(middleX, -400).createFromCache(gameSettingsMenuKey);
|
||||
MenuScene.revealMenusAfterInit(this.gameQualityMenuElement, "gameQuality");
|
||||
|
||||
this.gameShareElement = this.add.dom(middleX, -400).createFromCache(gameShare);
|
||||
MenuScene.revealMenusAfterInit(this.gameShareElement, gameShare);
|
||||
this.gameShareElement.addListener("click");
|
||||
this.gameShareElement.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if ((event?.target as HTMLInputElement).id === "gameShareFormSubmit") {
|
||||
this.copyLink();
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameShareFormCancel") {
|
||||
this.closeGameShare();
|
||||
}
|
||||
});
|
||||
|
||||
this.gameReportElement = new ReportMenu(
|
||||
this,
|
||||
connectionManager.getConnexionType === GameConnexionTypes.anonymous
|
||||
);
|
||||
showReportScreenStore.subscribe((user) => {
|
||||
if (user !== null) {
|
||||
this.closeAll();
|
||||
//this.gameReportElement.open(user., user.userName);
|
||||
}
|
||||
});
|
||||
|
||||
this.input.keyboard.on("keyup-TAB", () => {
|
||||
this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu();
|
||||
});
|
||||
this.menuButton = this.add.dom(0, 0).createFromCache(gameMenuIconKey);
|
||||
this.menuButton.addListener("click");
|
||||
this.menuButton.on("click", () => {
|
||||
this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu();
|
||||
});
|
||||
|
||||
this.menuElement.addListener("click");
|
||||
this.menuElement.on("click", this.onMenuClick.bind(this));
|
||||
|
||||
chatVisibilityStore.subscribe((v) => {
|
||||
this.menuButton.setVisible(!v);
|
||||
});
|
||||
}
|
||||
|
||||
//todo put this method in a parent menuElement class
|
||||
static revealMenusAfterInit(menuElement: Phaser.GameObjects.DOMElement, rootDomId: string) {
|
||||
//Dom elements will appear inside the viewer screen when creating before being moved out of it, which create a flicker effect.
|
||||
//To prevent this, we put a 'hidden' attribute on the root element, we remove it only after the init is done.
|
||||
setTimeout(() => {
|
||||
(menuElement.getChildByID(rootDomId) as HTMLElement).hidden = false;
|
||||
}, 250);
|
||||
}
|
||||
|
||||
public revealMenuIcon(): void {
|
||||
return;
|
||||
//TODO fix me: add try catch because at the same time, 'this.menuButton' variable doesn't exist and there is error on 'getChildByID' function
|
||||
try {
|
||||
(this.menuButton.getChildByID("menuIcon") as HTMLElement).hidden = false;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
openSideMenu() {
|
||||
menuVisiblilityStore.set(true);
|
||||
if (this.sideMenuOpened) return;
|
||||
|
||||
/*this.closeAll();
|
||||
this.sideMenuOpened = true;
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = 'X';
|
||||
const connection = gameManager.getCurrentGameScene(this).connection;
|
||||
if (connection && connection.isAdmin()) {
|
||||
const adminSection = this.menuElement.getChildByID('adminConsoleSection') as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
}
|
||||
//TODO bind with future metadata of card
|
||||
//if (connectionManager.getConnexionType === GameConnexionTypes.anonymous){
|
||||
const adminSection = this.menuElement.getChildByID('socialLinks') as HTMLElement;
|
||||
adminSection.hidden = false;
|
||||
//}
|
||||
this.tweens.add({
|
||||
targets: this.menuElement,
|
||||
x: openedSideMenuX,
|
||||
duration: 500,
|
||||
ease: 'Power3'
|
||||
});*/
|
||||
}
|
||||
|
||||
private closeSideMenu(): void {
|
||||
menuVisiblilityStore.set(false);
|
||||
/* if (!this.sideMenuOpened) return;
|
||||
this.sideMenuOpened = false;
|
||||
this.closeAll();
|
||||
this.menuButton.getChildByID('openMenuButton').innerHTML = `<img src="/static/images/menu.svg">`;
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
this.tweens.add({
|
||||
targets: this.menuElement,
|
||||
x: closedSideMenuX,
|
||||
duration: 500,
|
||||
ease: 'Power3'
|
||||
});*/
|
||||
}
|
||||
|
||||
private openGameSettingsMenu(): void {
|
||||
if (this.settingsMenuOpened) {
|
||||
this.closeGameQualityMenu();
|
||||
return;
|
||||
}
|
||||
//close all
|
||||
this.closeAll();
|
||||
|
||||
this.settingsMenuOpened = true;
|
||||
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID("select-game-quality") as HTMLInputElement;
|
||||
gameQualitySelect.value = "" + this.gameQualityValue;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID("select-video-quality") as HTMLInputElement;
|
||||
videoQualitySelect.value = "" + this.videoQualityValue;
|
||||
|
||||
this.gameQualityMenuElement.addListener("click");
|
||||
this.gameQualityMenuElement.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if ((event?.target as HTMLInputElement).id === "gameQualityFormSubmit") {
|
||||
const gameQualitySelect = this.gameQualityMenuElement.getChildByID(
|
||||
"select-game-quality"
|
||||
) as HTMLInputElement;
|
||||
const videoQualitySelect = this.gameQualityMenuElement.getChildByID(
|
||||
"select-video-quality"
|
||||
) as HTMLInputElement;
|
||||
this.saveSetting(parseInt(gameQualitySelect.value), parseInt(videoQualitySelect.value));
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameQualityFormCancel") {
|
||||
this.closeGameQualityMenu();
|
||||
}
|
||||
});
|
||||
|
||||
let middleY = this.scale.height / 2 - 392 / 2;
|
||||
if (middleY < 0) {
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = this.scale.width / 2 - 457 / 2;
|
||||
if (middleX < 0) {
|
||||
middleX = 0;
|
||||
}
|
||||
this.tweens.add({
|
||||
targets: this.gameQualityMenuElement,
|
||||
y: middleY,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private closeGameQualityMenu(): void {
|
||||
if (!this.settingsMenuOpened) return;
|
||||
this.settingsMenuOpened = false;
|
||||
|
||||
this.gameQualityMenuElement.removeListener("click");
|
||||
this.tweens.add({
|
||||
targets: this.gameQualityMenuElement,
|
||||
y: -400,
|
||||
duration: 1000,
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private openGameShare(): void {
|
||||
if (this.gameShareOpened) {
|
||||
this.closeGameShare();
|
||||
return;
|
||||
}
|
||||
//close all
|
||||
this.closeAll();
|
||||
|
||||
const gameShareLink = this.gameShareElement.getChildByID("gameShareLink") as HTMLInputElement;
|
||||
gameShareLink.value = location.toString();
|
||||
|
||||
this.gameShareOpened = true;
|
||||
|
||||
let middleY = this.scale.height / 2 - 85;
|
||||
if (middleY < 0) {
|
||||
middleY = 0;
|
||||
}
|
||||
let middleX = this.scale.width / 2 - 200;
|
||||
if (middleX < 0) {
|
||||
middleX = 0;
|
||||
}
|
||||
this.tweens.add({
|
||||
targets: this.gameShareElement,
|
||||
y: middleY,
|
||||
x: middleX,
|
||||
duration: 1000,
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private closeGameShare(): void {
|
||||
const gameShareInfo = this.gameShareElement.getChildByID("gameShareInfo") as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = "";
|
||||
gameShareInfo.style.display = "none";
|
||||
this.gameShareOpened = false;
|
||||
this.tweens.add({
|
||||
targets: this.gameShareElement,
|
||||
y: -400,
|
||||
duration: 1000,
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
private onMenuClick(event: MouseEvent) {
|
||||
const htmlMenuItem = event?.target as HTMLInputElement;
|
||||
if (htmlMenuItem.classList.contains("not-button")) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
if (htmlMenuItem.classList.contains("fromApi")) {
|
||||
sendMenuClickedEvent(htmlMenuItem.id);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ((event?.target as HTMLInputElement).id) {
|
||||
case "changeNameButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(LoginSceneName, new LoginScene());
|
||||
break;
|
||||
case "sparkButton":
|
||||
this.gotToCreateMapPage();
|
||||
break;
|
||||
case "changeSkinButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
|
||||
break;
|
||||
case "changeCompanionButton":
|
||||
this.closeSideMenu();
|
||||
gameManager.leaveGame(SelectCompanionSceneName, new SelectCompanionScene());
|
||||
break;
|
||||
case "closeButton":
|
||||
this.closeSideMenu();
|
||||
break;
|
||||
case "shareButton":
|
||||
this.openGameShare();
|
||||
break;
|
||||
case "editGameSettingsButton":
|
||||
this.openGameSettingsMenu();
|
||||
break;
|
||||
case "oidcLogin":
|
||||
connectionManager.loadOpenIDScreen();
|
||||
break;
|
||||
case "toggleFullscreen":
|
||||
this.toggleFullscreen();
|
||||
break;
|
||||
case "enableNotification":
|
||||
this.enableNotification();
|
||||
break;
|
||||
case "adminConsoleButton":
|
||||
if (get(consoleGlobalMessageManagerVisibleStore)) {
|
||||
consoleGlobalMessageManagerVisibleStore.set(false);
|
||||
} else {
|
||||
consoleGlobalMessageManagerVisibleStore.set(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async copyLink() {
|
||||
await navigator.clipboard.writeText(location.toString());
|
||||
const gameShareInfo = this.gameShareElement.getChildByID("gameShareInfo") as HTMLParagraphElement;
|
||||
gameShareInfo.innerText = "Link copied, you can share it now!";
|
||||
gameShareInfo.style.display = "block";
|
||||
}
|
||||
|
||||
private saveSetting(valueGame: number, valueVideo: number) {
|
||||
if (valueGame !== this.gameQualityValue) {
|
||||
this.gameQualityValue = valueGame;
|
||||
localUserStore.setGameQualityValue(valueGame);
|
||||
window.location.reload();
|
||||
}
|
||||
if (valueVideo !== this.videoQualityValue) {
|
||||
this.videoQualityValue = valueVideo;
|
||||
localUserStore.setVideoQualityValue(valueVideo);
|
||||
videoConstraintStore.setFrameRate(valueVideo);
|
||||
}
|
||||
this.closeGameQualityMenu();
|
||||
}
|
||||
|
||||
private gotToCreateMapPage() {
|
||||
//const sparkHost = 'https://'+window.location.host.replace('play.', '')+'/choose-map.html';
|
||||
//TODO fix me: this button can to send us on WorkAdventure BO.
|
||||
//const sparkHost = ADMIN_URL + "/getting-started";
|
||||
|
||||
//The redirection must be only on workadventu.re domain
|
||||
//To day the domain staging cannot be use by customer
|
||||
const sparkHost = "https://workadventu.re/getting-started";
|
||||
window.open(sparkHost, "_blank");
|
||||
}
|
||||
|
||||
private closeAll() {
|
||||
this.closeGameQualityMenu();
|
||||
this.closeGameShare();
|
||||
this.gameReportElement.close();
|
||||
}
|
||||
|
||||
private toggleFullscreen() {
|
||||
const body = document.querySelector("body");
|
||||
if (body) {
|
||||
if (document.fullscreenElement ?? document.fullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else {
|
||||
body.requestFullscreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public destroyMenu(menu: string) {
|
||||
this.menuElement.getChildByID(menu).remove();
|
||||
}
|
||||
|
||||
public isDirty(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
private enableNotification() {
|
||||
mediaManager.requestNotification().then(() => {
|
||||
if (mediaManager.hasNotification()) {
|
||||
HtmlUtils.getElementByIdOrFail("enableNotification").hidden = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
import { MenuScene } from "./MenuScene";
|
||||
import { gameManager } from "../Game/GameManager";
|
||||
import { blackListManager } from "../../WebRtc/BlackListManager";
|
||||
|
||||
export const gameReportKey = "gameReport";
|
||||
export const gameReportRessource = "resources/html/gameReport.html";
|
||||
|
||||
export class ReportMenu extends Phaser.GameObjects.DOMElement {
|
||||
private opened: boolean = false;
|
||||
|
||||
private userUuid!: string;
|
||||
private userName!: string | undefined;
|
||||
private anonymous: boolean;
|
||||
|
||||
constructor(scene: Phaser.Scene, anonymous: boolean) {
|
||||
super(scene, -2000, -2000);
|
||||
this.anonymous = anonymous;
|
||||
this.createFromCache(gameReportKey);
|
||||
|
||||
if (this.anonymous) {
|
||||
const divToHide = this.getChildByID("reportSection") as HTMLElement;
|
||||
divToHide.hidden = true;
|
||||
const textToHide = this.getChildByID("askActionP") as HTMLElement;
|
||||
textToHide.hidden = true;
|
||||
}
|
||||
|
||||
scene.add.existing(this);
|
||||
MenuScene.revealMenusAfterInit(this, gameReportKey);
|
||||
|
||||
this.addListener("click");
|
||||
this.on("click", (event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
if ((event?.target as HTMLInputElement).id === "gameReportFormSubmit") {
|
||||
this.submitReport();
|
||||
} else if ((event?.target as HTMLInputElement).id === "gameReportFormCancel") {
|
||||
this.close();
|
||||
} else if ((event?.target as HTMLInputElement).id === "toggleBlockButton") {
|
||||
this.toggleBlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public open(userUuid: string, userName: string | undefined): void {
|
||||
if (this.opened) {
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
|
||||
this.userUuid = userUuid;
|
||||
this.userName = userName;
|
||||
|
||||
const mainEl = this.getChildByID("gameReport") as HTMLElement;
|
||||
this.x = this.getCenteredX(mainEl);
|
||||
this.y = this.getHiddenY(mainEl);
|
||||
|
||||
const gameTitleReport = this.getChildByID("nameReported") as HTMLElement;
|
||||
gameTitleReport.innerText = userName || "";
|
||||
|
||||
const blockButton = this.getChildByID("toggleBlockButton") as HTMLElement;
|
||||
blockButton.innerText = blackListManager.isBlackListed(this.userUuid) ? "Unblock this user" : "Block this user";
|
||||
|
||||
this.opened = true;
|
||||
|
||||
//gameManager.getCurrentGameScene().userInputManager.disableControls();
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
y: this.getCenteredY(mainEl),
|
||||
duration: 1000,
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
//gameManager.getCurrentGameScene().userInputManager.restoreControls();
|
||||
this.opened = false;
|
||||
const mainEl = this.getChildByID("gameReport") as HTMLElement;
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
y: this.getHiddenY(mainEl),
|
||||
duration: 1000,
|
||||
ease: "Power3",
|
||||
});
|
||||
}
|
||||
|
||||
//todo: into a parent class?
|
||||
private getCenteredX(mainEl: HTMLElement): number {
|
||||
return window.innerWidth / 4 - mainEl.clientWidth / 2;
|
||||
}
|
||||
private getHiddenY(mainEl: HTMLElement): number {
|
||||
return -mainEl.clientHeight - 50;
|
||||
}
|
||||
private getCenteredY(mainEl: HTMLElement): number {
|
||||
return window.innerHeight / 4 - mainEl.clientHeight / 2;
|
||||
}
|
||||
|
||||
private toggleBlock(): void {
|
||||
!blackListManager.isBlackListed(this.userUuid)
|
||||
? blackListManager.blackList(this.userUuid)
|
||||
: blackListManager.cancelBlackList(this.userUuid);
|
||||
this.close();
|
||||
}
|
||||
|
||||
private submitReport(): void {
|
||||
const gamePError = this.getChildByID("gameReportErr") as HTMLParagraphElement;
|
||||
gamePError.innerText = "";
|
||||
gamePError.style.display = "none";
|
||||
const gameTextArea = this.getChildByID("gameReportInput") as HTMLInputElement;
|
||||
if (!gameTextArea || !gameTextArea.value) {
|
||||
gamePError.innerText = "Report message cannot to be empty.";
|
||||
gamePError.style.display = "block";
|
||||
return;
|
||||
}
|
||||
//gameManager.getCurrentGameScene().connection?.emitReportPlayerMessage(this.userId, gameTextArea.value);
|
||||
this.close();
|
||||
}
|
||||
}
|
|
@ -23,3 +23,46 @@ function createWarningContainerStore() {
|
|||
}
|
||||
|
||||
export const warningContainerStore = createWarningContainerStore();
|
||||
|
||||
export enum SubMenusInterface {
|
||||
settings = "Settings",
|
||||
profile = "Profile",
|
||||
createMap = "Create a Map",
|
||||
aboutRoom = "About the Room",
|
||||
globalMessages = "Global Messages",
|
||||
contact = "Contact",
|
||||
}
|
||||
|
||||
function createSubMenusStore() {
|
||||
const { subscribe, update } = writable<string[]>([
|
||||
SubMenusInterface.settings,
|
||||
SubMenusInterface.profile,
|
||||
SubMenusInterface.createMap,
|
||||
SubMenusInterface.aboutRoom,
|
||||
SubMenusInterface.globalMessages,
|
||||
SubMenusInterface.contact,
|
||||
]);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
addMenu(menuCommand: string) {
|
||||
update((menuList: string[]) => {
|
||||
if (!menuList.find((menu) => menu === menuCommand)) {
|
||||
menuList.push(menuCommand);
|
||||
}
|
||||
return menuList;
|
||||
});
|
||||
},
|
||||
removeMenu(menuCommand: string) {
|
||||
update((menuList: string[]) => {
|
||||
const index = menuList.findIndex((menu) => menu === menuCommand);
|
||||
if (index !== -1) {
|
||||
menuList.splice(index, 1);
|
||||
}
|
||||
return menuList;
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const subMenusStore = createSubMenusStore();
|
||||
|
|
|
@ -13,7 +13,6 @@ import WebFontLoaderPlugin from "phaser3-rex-plugins/plugins/webfontloader-plugi
|
|||
import OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
||||
import { EntryScene } from "./Phaser/Login/EntryScene";
|
||||
import { coWebsiteManager } from "./WebRtc/CoWebsiteManager";
|
||||
import { MenuScene } from "./Phaser/Menu/MenuScene";
|
||||
import { localUserStore } from "./Connexion/LocalUserStore";
|
||||
import { ErrorScene } from "./Phaser/Reconnecting/ErrorScene";
|
||||
import { iframeListener } from "./Api/IframeListener";
|
||||
|
@ -97,7 +96,6 @@ const config: GameConfig = {
|
|||
ReconnectingScene,
|
||||
ErrorScene,
|
||||
CustomizeScene,
|
||||
MenuScene,
|
||||
],
|
||||
//resolution: window.devicePixelRatio / 2,
|
||||
fps: fps,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue