diff --git a/CHANGELOG.md b/CHANGELOG.md index d9afd71e..b9b0a926 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ - Mouse wheel support to zoom in / out - Pinch support on mobile to zoom in / out - Improved virtual joystick size (adapts to the zoom level) +- Redesigned intermediate scenes + - Redesigned Select Companion scene + - Redesigned Enter Your Name scene + - Added a new `DISPLAY_TERMS_OF_USE` environment variable to trigger the display of terms of use - New scripting API features: - Use `WA.loadSound(): Sound` to load / play / stop a sound diff --git a/front/dist/resources/html/EnableCameraScene.html b/front/dist/resources/html/EnableCameraScene.html deleted file mode 100644 index 21c798b5..00000000 --- a/front/dist/resources/html/EnableCameraScene.html +++ /dev/null @@ -1,126 +0,0 @@ - - - diff --git a/front/dist/resources/html/loginScene.html b/front/dist/resources/html/loginScene.html deleted file mode 100644 index 9c076693..00000000 --- a/front/dist/resources/html/loginScene.html +++ /dev/null @@ -1,117 +0,0 @@ - - - diff --git a/front/src/Components/App.svelte b/front/src/Components/App.svelte index e9569175..fc0ffff5 100644 --- a/front/src/Components/App.svelte +++ b/front/src/Components/App.svelte @@ -1,7 +1,7 @@
+ {#if $loginSceneVisibleStore} + + {/if} {#if $selectCharacterSceneVisibleStore} {/if} @@ -28,6 +32,9 @@ {#if $selectCompanionSceneVisibleStore} {/if} + {#if $enableCameraSceneVisibilityStore} + + {/if} diff --git a/front/src/Components/EnableCamera/EnableCameraScene.svelte b/front/src/Components/EnableCamera/EnableCameraScene.svelte new file mode 100644 index 00000000..ac2cf992 --- /dev/null +++ b/front/src/Components/EnableCamera/EnableCameraScene.svelte @@ -0,0 +1,76 @@ + + +
+
+

Turn on your camera and microphone

+
+ +
+ +
+
+ + + diff --git a/front/src/Components/Login/LoginScene.svelte b/front/src/Components/Login/LoginScene.svelte new file mode 100644 index 00000000..ea824908 --- /dev/null +++ b/front/src/Components/Login/LoginScene.svelte @@ -0,0 +1,120 @@ + + +
+
+ WorkAdventure logo +
+
+

Enter your name

+
+ {startValidating = true}} class:is-error={name.trim() === '' && startValidating} /> +
+ {#if name.trim() === '' && startValidating } +

The name is empty

+ {/if} +
+ + {#if !DISPLAY_TERMS_OF_USE} +
+

By continuing, you are agreeing our terms of use, privacy policy and cookie policy.

+
+ {/if} +
+ +
+
+ + diff --git a/front/src/Components/SelectCompanion/SelectCompanionScene.svelte b/front/src/Components/SelectCompanion/SelectCompanionScene.svelte index 8638dc4d..9aaa0757 100644 --- a/front/src/Components/SelectCompanion/SelectCompanionScene.svelte +++ b/front/src/Components/SelectCompanion/SelectCompanionScene.svelte @@ -41,9 +41,6 @@ pointer-events: auto; color: #ebeeee; } - .selectCompanionScene button { - font-family: "Press Start 2P"; - } .selectCompanionScene section { margin: 10px; } @@ -80,4 +77,4 @@ } - \ No newline at end of file + diff --git a/front/src/Components/images/logo.png b/front/src/Components/images/logo.png new file mode 100644 index 00000000..f4440ad5 Binary files /dev/null and b/front/src/Components/images/logo.png differ diff --git a/front/src/Connexion/LocalUser.ts b/front/src/Connexion/LocalUser.ts index 43b184cf..f5a4ac2a 100644 --- a/front/src/Connexion/LocalUser.ts +++ b/front/src/Connexion/LocalUser.ts @@ -10,7 +10,7 @@ export interface CharacterTexture { export const maxUserNameLength: number = MAX_USERNAME_LENGTH; export function isUserNameValid(value: unknown): boolean { - return typeof value === "string" && value.length > 0 && value.length < maxUserNameLength && value.indexOf(' ') === -1; + return typeof value === "string" && value.length > 0 && value.length <= maxUserNameLength && value.indexOf(' ') === -1; } export function areCharacterLayersValid(value: string[] | null): boolean { diff --git a/front/src/Enum/EnvironmentVariable.ts b/front/src/Enum/EnvironmentVariable.ts index 85b63335..73f6427c 100644 --- a/front/src/Enum/EnvironmentVariable.ts +++ b/front/src/Enum/EnvironmentVariable.ts @@ -14,6 +14,7 @@ const POSITION_DELAY = 200; // Wait 200ms between sending position events const MAX_EXTRAPOLATION_TIME = 100; // Extrapolate a maximum of 250ms if no new movement is sent by the player export const MAX_USERNAME_LENGTH = parseInt(process.env.MAX_USERNAME_LENGTH || '') || 8; export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || '4'); +export const DISPLAY_TERMS_OF_USE = process.env.DISPLAY_TERMS_OF_USE == 'true'; export const isMobile = ():boolean => ( ( window.innerWidth <= 800 ) || ( window.innerHeight <= 600 ) ); diff --git a/front/src/Phaser/Login/EnableCameraScene.ts b/front/src/Phaser/Login/EnableCameraScene.ts index 6002da7b..73fa7303 100644 --- a/front/src/Phaser/Login/EnableCameraScene.ts +++ b/front/src/Phaser/Login/EnableCameraScene.ts @@ -12,8 +12,8 @@ import { MenuScene } from "../Menu/MenuScene"; import {ResizableScene} from "./ResizableScene"; import { audioConstraintStore, - enableCameraSceneVisibilityStore, localStreamStore, + enableCameraSceneVisibilityStore, mediaStreamConstraintsStore, videoConstraintStore } from "../../Stores/MediaStore"; @@ -28,8 +28,6 @@ enum LoginTextures { arrowUp = "arrow_up" } -const enableCameraSceneKey = 'enableCameraScene'; - export class EnableCameraScene extends ResizableScene { private textField!: TextField; private cameraNameField!: TextField; @@ -45,8 +43,6 @@ export class EnableCameraScene extends ResizableScene { private soundMeterSprite!: SoundMeterSprite; private microphoneNameField!: TextField; - private enableCameraSceneElement!: Phaser.GameObjects.DOMElement; - private mobileTapZone!: Zone; private localStreamStoreUnsubscriber!: Unsubscriber; @@ -58,9 +54,6 @@ export class EnableCameraScene extends ResizableScene { } preload() { - - this.load.html(enableCameraSceneKey, 'resources/html/EnableCameraScene.html'); - this.load.image(LoginTextures.playButton, "resources/objects/play_button.png"); this.load.image(LoginTextures.arrowRight, "resources/objects/arrow_right.png"); this.load.image(LoginTextures.arrowUp, "resources/objects/arrow_up.png"); @@ -69,18 +62,6 @@ export class EnableCameraScene extends ResizableScene { } create() { - - this.enableCameraSceneElement = this.add.dom(-1000, 0).createFromCache(enableCameraSceneKey); - this.centerXDomElement(this.enableCameraSceneElement, 300); - - MenuScene.revealMenusAfterInit(this.enableCameraSceneElement, enableCameraSceneKey); - - const continuingButton = this.enableCameraSceneElement.getChildByID('enableCameraSceneFormSubmit') as HTMLButtonElement; - continuingButton.addEventListener('click', (e) => { - e.preventDefault(); - this.login(); - }); - if (touchScreenManager.supportTouchScreen) { new PinchManager(this); } @@ -272,19 +253,17 @@ export class EnableCameraScene extends ResizableScene { this.arrowUp.x = this.microphoneNameField.x - this.microphoneNameField.width / 2 - 16; this.arrowUp.y = this.microphoneNameField.y; - const actionBtn = document.querySelector('#enableCameraScene .action'); + /*const actionBtn = document.querySelector('#enableCameraScene .action'); if (actionBtn !== null) { actionBtn.style.top = (this.scale.height - 65) + 'px'; - } + }*/ } update(time: number, delta: number): void { this.soundMeterSprite.setVolume(this.soundMeter.getVolume()); - - this.centerXDomElement(this.enableCameraSceneElement, 300); } - private login(): void { + public login(): void { HtmlUtils.getElementByIdOrFail('webRtcSetup').style.display = 'none'; this.soundMeter.stop(); diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts index 4b36e3d9..39a8f5f3 100644 --- a/front/src/Phaser/Login/LoginScene.ts +++ b/front/src/Phaser/Login/LoginScene.ts @@ -1,17 +1,12 @@ import {gameManager} from "../Game/GameManager"; import {SelectCharacterSceneName} from "./SelectCharacterScene"; import {ResizableScene} from "./ResizableScene"; -import { localUserStore } from "../../Connexion/LocalUserStore"; -import {MenuScene} from "../Menu/MenuScene"; -import { isUserNameValid } from "../../Connexion/LocalUser"; +import {loginSceneVisibleStore} from "../../Stores/LoginSceneStore"; export const LoginSceneName = "LoginScene"; -const loginSceneKey = 'loginScene'; - export class LoginScene extends ResizableScene { - private loginSceneElement!: Phaser.GameObjects.DOMElement; private name: string = ''; constructor() { @@ -22,65 +17,25 @@ export class LoginScene extends ResizableScene { } preload() { - this.load.html(loginSceneKey, 'resources/html/loginScene.html'); } create() { - this.loginSceneElement = this.add.dom(-1000, 0).createFromCache(loginSceneKey); - this.centerXDomElement(this.loginSceneElement, 200); - MenuScene.revealMenusAfterInit(this.loginSceneElement, loginSceneKey); - - const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement; - const inputElement = this.loginSceneElement.getChildByID('loginSceneName') as HTMLInputElement; - inputElement.value = localUserStore.getName() ?? ''; - inputElement.focus(); - inputElement.addEventListener('keypress', (event: KeyboardEvent) => { - if(inputElement.value.length > 7){ - event.preventDefault(); - return; - } - pErrorElement.innerHTML = ''; - if(inputElement.value && !isUserNameValid(inputElement.value)){ - pErrorElement.innerHTML = 'Invalid user name: No spaces are allowed.'; - } - if (event.key === 'Enter') { - event.preventDefault(); - this.login(inputElement); - return; - } - }); - - const continuingButton = this.loginSceneElement.getChildByID('loginSceneFormSubmit') as HTMLButtonElement; - continuingButton.addEventListener('click', (e) => { - e.preventDefault(); - this.login(inputElement); - }); + loginSceneVisibleStore.set(true); } - private login(inputElement: HTMLInputElement): void { - const pErrorElement = this.loginSceneElement.getChildByID('errorLoginScene') as HTMLInputElement; - this.name = inputElement.value; - if (this.name === '') { - pErrorElement.innerHTML = 'The name is empty'; - return - } - if(!isUserNameValid(this.name)){ - pErrorElement.innerHTML = 'Invalid user name: only letters and numbers are allowed. No spaces.'; - return - } - if (this.name === '') return - gameManager.setPlayerName(this.name); + public login(name: string): void { + name = name.trim(); + gameManager.setPlayerName(name); this.scene.stop(LoginSceneName) gameManager.tryResumingGame(this, SelectCharacterSceneName); - this.scene.remove(LoginSceneName) + this.scene.remove(LoginSceneName); + loginSceneVisibleStore.set(false); } update(time: number, delta: number): void { - } public onResize(): void { - this.centerXDomElement(this.loginSceneElement, 200); } } diff --git a/front/src/Stores/LoginSceneStore.ts b/front/src/Stores/LoginSceneStore.ts new file mode 100644 index 00000000..6e2ea18b --- /dev/null +++ b/front/src/Stores/LoginSceneStore.ts @@ -0,0 +1,3 @@ +import { writable } from "svelte/store"; + +export const loginSceneVisibleStore = writable(false); diff --git a/front/src/WebRtc/ScreenSharingPeer.ts b/front/src/WebRtc/ScreenSharingPeer.ts index 947549eb..d797f59b 100644 --- a/front/src/WebRtc/ScreenSharingPeer.ts +++ b/front/src/WebRtc/ScreenSharingPeer.ts @@ -60,6 +60,7 @@ export class ScreenSharingPeer extends Peer { const message = JSON.parse(chunk.toString('utf8')); if (message.streamEnded !== true) { console.error('Unexpected message on screen sharing peer connection'); + return; } mediaManager.removeActiveScreenSharingVideo("" + this.userId); }); diff --git a/front/style/fonts.scss b/front/style/fonts.scss index 748710fa..a49d3967 100644 --- a/front/style/fonts.scss +++ b/front/style/fonts.scss @@ -2,4 +2,8 @@ *{ font-family: PixelFont-7,monospace; -} \ No newline at end of file +} + +.nes-btn { + font-family: "Press Start 2P"; +} diff --git a/front/webpack.config.ts b/front/webpack.config.ts index 6ebf907f..99cbff77 100644 --- a/front/webpack.config.ts +++ b/front/webpack.config.ts @@ -7,6 +7,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import sveltePreprocess from 'svelte-preprocess'; import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin"; import NodePolyfillPlugin from 'node-polyfill-webpack-plugin'; +import {DISPLAY_TERMS_OF_USE} from "./src/Enum/EnvironmentVariable"; const mode = process.env.NODE_ENV ?? 'development'; const isProduction = mode === 'production'; @@ -175,7 +176,8 @@ module.exports = { 'JITSI_PRIVATE_MODE': null, 'START_ROOM_URL': null, 'MAX_USERNAME_LENGTH': 8, - 'MAX_PER_GROUP': 4 + 'MAX_PER_GROUP': 4, + 'DISPLAY_TERMS_OF_USE': false, }) ],