Merge branch 'develop' into new_custom_woka_scene

This commit is contained in:
Piotr 'pwh' Hanusiak
2022-03-28 12:30:26 +02:00
29 changed files with 773 additions and 249 deletions
+7
View File
@@ -1,5 +1,12 @@
import { isSilentStore, requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
import { get } from "svelte/store";
import { WorkAdventureDesktopApi } from "@wa-preload-app";
declare global {
interface Window {
WAD: WorkAdventureDesktopApi;
}
}
class DesktopApi {
isSilent: boolean = false;
@@ -13,20 +13,20 @@
let unsubscriberFileStore: Unsubscriber | null = null;
let unsubscriberVolumeStore: Unsubscriber | null = null;
let decreaseWhileTalking: boolean = true;
let isAudioAllowed: boolean = true;
onMount(() => {
let volume = Math.min(localUserStore.getAudioPlayerVolume(), get(audioManagerVolumeStore).volume);
audioManagerVolumeStore.setVolume(volume);
audioManagerVolumeStore.setMuted(localUserStore.getAudioPlayerMuted());
unsubscriberFileStore = audioManagerFileStore.subscribe((src) => {
unsubscriberFileStore = audioManagerFileStore.subscribe((src: string) => {
HTMLAudioPlayer.pause();
HTMLAudioPlayer.src = src;
HTMLAudioPlayer.loop = get(audioManagerVolumeStore).loop;
HTMLAudioPlayer.volume = get(audioManagerVolumeStore).volume;
HTMLAudioPlayer.muted = get(audioManagerVolumeStore).muted;
void HTMLAudioPlayer.play();
tryPlay();
});
unsubscriberVolumeStore = audioManagerVolumeStore.subscribe((audioManager: audioManagerVolume) => {
const reduceVolume = audioManager.talking && audioManager.decreaseWhileTalking;
@@ -52,6 +52,16 @@
}
});
function tryPlay() {
void HTMLAudioPlayer.play()
.then(() => {
isAudioAllowed = true;
})
.catch(() => {
isAudioAllowed = false;
});
}
function updateVolumeUI() {
if (get(audioManagerVolumeStore).muted) {
audioPlayerVolumeIcon.classList.add("muted");
@@ -90,73 +100,67 @@
audioPlayerVol.blur();
return false;
}
function setDecrease() {
audioManagerVolumeStore.setDecreaseWhileTalking(decreaseWhileTalking);
}
</script>
<div class="main-audio-manager nes-container is-rounded">
<div class="audio-manager-player-volume">
<span
id="audioplayer_volume_icon_playing"
alt="player volume"
bind:this={audioPlayerVolumeIcon}
on:click={onMute}
>
<svg
width="2em"
height="2em"
viewBox="0 0 16 16"
class="bi bi-volume-up"
fill="white"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06zM6 5.04L4.312 6.39A.5.5 0 0 1 4 6.5H2v3h2a.5.5 0 0 1 .312.11L6 10.96V5.04z"
/>
<g id="audioplayer_volume_icon_playing_high">
<div class:hidden={!isAudioAllowed}>
<div class="audio-manager-player-volume">
<span id="audioplayer_volume_icon_playing" bind:this={audioPlayerVolumeIcon} on:click={onMute}>
<svg
width="2em"
height="2em"
viewBox="0 0 16 16"
class="bi bi-volume-up"
fill="white"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11.536 14.01A8.473 8.473 0 0 0 14.026 8a8.473 8.473 0 0 0-2.49-6.01l-.708.707A7.476 7.476 0 0 1 13.025 8c0 2.071-.84 3.946-2.197 5.303l.708.707z"
fill-rule="evenodd"
d="M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06zM6 5.04L4.312 6.39A.5.5 0 0 1 4 6.5H2v3h2a.5.5 0 0 1 .312.11L6 10.96V5.04z"
/>
</g>
<g id="audioplayer_volume_icon_playing_mid">
<path
d="M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.483 5.483 0 0 1 11.025 8a5.483 5.483 0 0 1-1.61 3.89l.706.706z"
/>
</g>
<g id="audioplayer_volume_icon_playing_low">
<path
d="M8.707 11.182A4.486 4.486 0 0 0 10.025 8a4.486 4.486 0 0 0-1.318-3.182L8 5.525A3.489 3.489 0 0 1 9.025 8 3.49 3.49 0 0 1 8 10.475l.707.707z"
/>
</g>
</svg>
</span>
<input
type="range"
min="0"
max="1"
step="0.025"
bind:this={audioPlayerVol}
on:change={setVolume}
on:keydown={disallowKeys}
/>
</div>
<div class="audio-manager-reduce-conversation">
<label>
{$LL.audio.manager.reduce()}
<input type="checkbox" bind:checked={decreaseWhileTalking} on:change={setDecrease} />
</label>
<g id="audioplayer_volume_icon_playing_high">
<path
d="M11.536 14.01A8.473 8.473 0 0 0 14.026 8a8.473 8.473 0 0 0-2.49-6.01l-.708.707A7.476 7.476 0 0 1 13.025 8c0 2.071-.84 3.946-2.197 5.303l.708.707z"
/>
</g>
<g id="audioplayer_volume_icon_playing_mid">
<path
d="M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.483 5.483 0 0 1 11.025 8a5.483 5.483 0 0 1-1.61 3.89l.706.706z"
/>
</g>
<g id="audioplayer_volume_icon_playing_low">
<path
d="M8.707 11.182A4.486 4.486 0 0 0 10.025 8a4.486 4.486 0 0 0-1.318-3.182L8 5.525A3.489 3.489 0 0 1 9.025 8 3.49 3.49 0 0 1 8 10.475l.707.707z"
/>
</g>
</svg>
</span>
<input
type="range"
min="0"
max="1"
step="0.025"
bind:this={audioPlayerVol}
on:change={setVolume}
on:keydown={disallowKeys}
/>
</div>
<section class="audio-manager-file">
<!-- svelte-ignore a11y-media-has-caption -->
<audio class="audio-manager-audioplayer" bind:this={HTMLAudioPlayer} />
</section>
</div>
<div class:hidden={isAudioAllowed}>
<button type="button" class="nes-btn" on:click={tryPlay}>{$LL.audio.manager.allow()}</button>
</div>
</div>
<style lang="scss">
div.main-audio-manager.nes-container.is-rounded {
.hidden {
display: none;
}
div.main-audio-manager {
position: absolute;
top: 1%;
max-height: clamp(150px, 10vh, 15vh); //replace @media for small screen
@@ -44,7 +44,6 @@
async function logOut() {
disableMenuStores();
loginSceneVisibleStore.set(true);
return connectionManager.logout();
}
@@ -7,17 +7,24 @@
import type { Locales } from "../../i18n/i18n-types";
import { displayableLocales, setCurrentLocale } from "../../i18n/locales";
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
import { audioManagerVolumeStore } from "../../Stores/AudioManagerStore";
let fullscreen: boolean = localUserStore.getFullscreen();
let notification: boolean = localUserStore.getNotification() === "granted";
let forceCowebsiteTrigger: boolean = localUserStore.getForceCowebsiteTrigger();
let ignoreFollowRequests: boolean = localUserStore.getIgnoreFollowRequests();
let decreaseAudioPlayerVolumeWhileTalking: boolean = localUserStore.getDecreaseAudioPlayerVolumeWhileTalking();
let valueGame: number = localUserStore.getGameQualityValue();
let valueVideo: number = localUserStore.getVideoQualityValue();
let valueLocale: string = $locale;
let valueCameraPrivacySettings = localUserStore.getCameraPrivacySettings();
let valueMicrophonePrivacySettings = localUserStore.getMicrophonePrivacySettings();
let previewValueGame = valueGame;
let previewValueVideo = valueVideo;
let previewValueLocale = valueLocale;
let previewCameraPrivacySettings = valueCameraPrivacySettings;
let previewMicrophonePrivacySettings = valueMicrophonePrivacySettings;
function saveSetting() {
let change = false;
@@ -38,6 +45,18 @@
change = true;
}
if (valueCameraPrivacySettings !== previewCameraPrivacySettings) {
previewCameraPrivacySettings = valueCameraPrivacySettings;
localUserStore.setCameraPrivacySettings(valueCameraPrivacySettings);
}
if (valueMicrophonePrivacySettings !== previewMicrophonePrivacySettings) {
previewMicrophonePrivacySettings = valueMicrophonePrivacySettings;
localUserStore.setMicrophonePrivacySettings(valueMicrophonePrivacySettings);
}
audioManagerVolumeStore.setDecreaseWhileTalking(decreaseAudioPlayerVolumeWhileTalking);
if (change) {
window.location.reload();
}
@@ -82,6 +101,10 @@
localUserStore.setIgnoreFollowRequests(ignoreFollowRequests);
}
function changeDecreaseAudioPlayerVolumeWhileTalking() {
localUserStore.setDecreaseAudioPlayerVolumeWhileTalking(decreaseAudioPlayerVolumeWhileTalking);
}
function closeMenu() {
menuVisiblilityStore.set(false);
}
@@ -154,6 +177,19 @@
</select>
</div>
</section>
<section>
<h3>{$LL.menu.settings.privacySettings.title()}</h3>
<p>{$LL.menu.settings.privacySettings.explanation()}</p>
<label>
<input type="checkbox" class="nes-checkbox is-dark" bind:checked={valueCameraPrivacySettings} />
<span>{$LL.menu.settings.privacySettings.cameraToggle()}</span>
</label>
<label>
<input type="checkbox" class="nes-checkbox is-dark" bind:checked={valueMicrophonePrivacySettings} />
<span>{$LL.menu.settings.privacySettings.microphoneToggle()}</span>
</label>
</section>
<section class="settings-section-save">
<p>{$LL.menu.settings.save.warning()}</p>
<button type="button" class="nes-btn is-primary" on:click|preventDefault={saveSetting}
@@ -196,6 +232,15 @@
on:change={changeIgnoreFollowRequests}
/>
<span>{$LL.menu.settings.ignoreFollowRequest()}</span>
<label>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={decreaseAudioPlayerVolumeWhileTalking}
on:change={changeDecreaseAudioPlayerVolumeWhileTalking}
/>
<span>{$LL.audio.manager.reduce()}</span>
</label>
</label>
</section>
</div>
@@ -217,12 +262,15 @@
outline: none;
}
}
section.settings-section-save {
text-align: center;
p {
margin: 16px 0;
}
}
section.settings-section-noSaveOption {
display: flex;
align-items: center;
+20 -10
View File
@@ -45,8 +45,10 @@ class ConnectionManager {
/**
* TODO fix me to be move in game manager
*
* Returns the URL that we need to redirect to to load the OpenID screen, or "null" if no redirection needs to happen.
*/
public loadOpenIDScreen() {
public loadOpenIDScreen(): URL | null {
const state = localUserStore.generateState();
const nonce = localUserStore.generateNonce();
localUserStore.setAuthToken(null);
@@ -55,11 +57,10 @@ class ConnectionManager {
loginSceneVisibleIframeStore.set(false);
return null;
}
const redirectUrl = new URL(`${this._currentRoom.iframeAuthentication}`);
const redirectUrl = new URL(`${this._currentRoom.iframeAuthentication}`, window.location.href);
redirectUrl.searchParams.append("state", state);
redirectUrl.searchParams.append("nonce", nonce);
redirectUrl.searchParams.append("playUri", this._currentRoom.key);
window.location.assign(redirectUrl.toString());
return redirectUrl;
}
@@ -83,8 +84,10 @@ class ConnectionManager {
/**
* Tries to login to the node server and return the starting map url to be loaded
*
* @return returns a promise to the Room we are going to load OR a pointer to the URL we must redirect to if authentication is needed.
*/
public async initGameConnexion(): Promise<Room> {
public async initGameConnexion(): Promise<Room | URL> {
const connexionType = urlManager.getGameConnexionType();
this.connexionType = connexionType;
this._currentRoom = null;
@@ -101,8 +104,9 @@ class ConnectionManager {
if (connexionType === GameConnexionTypes.login) {
this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl()));
if (this.loadOpenIDScreen() !== null) {
return Promise.reject(new Error("You will be redirect on login page"));
const redirect = this.loadOpenIDScreen();
if (redirect !== null) {
return redirect;
}
urlManager.pushRoomIdToUrl(this._currentRoom);
} else if (connexionType === GameConnexionTypes.jwt) {
@@ -124,8 +128,11 @@ class ConnectionManager {
analyticsClient.loggedWithSso();
} catch (err) {
console.error(err);
this.loadOpenIDScreen();
return Promise.reject(new Error("You will be redirect on login page"));
const redirect = this.loadOpenIDScreen();
if (redirect === null) {
throw new Error("Unable to redirect on login page.");
}
return redirect;
}
urlManager.pushRoomIdToUrl(this._currentRoom);
} else if (connexionType === GameConnexionTypes.register) {
@@ -212,8 +219,11 @@ class ConnectionManager {
err.response?.data &&
err.response.data !== "User cannot to be connected on openid provider")
) {
this.loadOpenIDScreen();
return Promise.reject(new Error("You will be redirect on login page"));
const redirect = this.loadOpenIDScreen();
if (redirect === null) {
throw new Error("Unable to redirect on login page.");
}
return redirect;
}
}
}
+58
View File
@@ -15,6 +15,7 @@ const helpCameraSettingsShown = "helpCameraSettingsShown";
const fullscreenKey = "fullscreen";
const forceCowebsiteTriggerKey = "forceCowebsiteTrigger";
const ignoreFollowRequests = "ignoreFollowRequests";
const decreaseAudioPlayerVolumeWhileTalking = "decreaseAudioPlayerVolumeWhileTalking";
const lastRoomUrl = "lastRoomUrl";
const authToken = "authToken";
const state = "state";
@@ -24,11 +25,14 @@ const code = "code";
const cameraSetup = "cameraSetup";
const cacheAPIIndex = "workavdenture-cache";
const userProperties = "user-properties";
const cameraPrivacySettings = "cameraPrivacySettings";
const microphonePrivacySettings = "microphonePrivacySettings";
class LocalUserStore {
saveUser(localUser: LocalUser) {
localStorage.setItem("localUser", JSON.stringify(localUser));
}
getLocalUser(): LocalUser | null {
const data = localStorage.getItem("localUser");
return data ? JSON.parse(data) : null;
@@ -37,6 +41,7 @@ class LocalUserStore {
setName(name: string): void {
localStorage.setItem(playerNameKey, name);
}
getName(): string | null {
const value = localStorage.getItem(playerNameKey) || "";
return isUserNameValid(value) ? value : null;
@@ -45,6 +50,7 @@ class LocalUserStore {
setPlayerCharacterIndex(playerCharacterIndex: number): void {
localStorage.setItem(selectedPlayerKey, "" + playerCharacterIndex);
}
getPlayerCharacterIndex(): number {
return parseInt(localStorage.getItem(selectedPlayerKey) || "");
}
@@ -52,6 +58,7 @@ class LocalUserStore {
setCustomCursorPosition(activeRow: number, selectedLayers: number[]): void {
localStorage.setItem(customCursorPositionKey, JSON.stringify({ activeRow, selectedLayers }));
}
getCustomCursorPosition(): { activeRow: number; selectedLayers: number[] } | null {
return JSON.parse(localStorage.getItem(customCursorPositionKey) || "null");
}
@@ -59,6 +66,7 @@ class LocalUserStore {
setCharacterLayers(layers: string[]): void {
localStorage.setItem(characterLayersKey, JSON.stringify(layers));
}
getCharacterLayers(): string[] | null {
const value = JSON.parse(localStorage.getItem(characterLayersKey) || "null");
return areCharacterLayersValid(value) ? value : null;
@@ -67,6 +75,7 @@ class LocalUserStore {
setCompanion(companion: string | null): void {
return localStorage.setItem(companionKey, JSON.stringify(companion));
}
getCompanion(): string | null {
const companion = JSON.parse(localStorage.getItem(companionKey) || "null");
@@ -76,6 +85,7 @@ class LocalUserStore {
return companion;
}
wasCompanionSet(): boolean {
return localStorage.getItem(companionKey) ? true : false;
}
@@ -83,6 +93,7 @@ class LocalUserStore {
setGameQualityValue(value: number): void {
localStorage.setItem(gameQualityKey, "" + value);
}
getGameQualityValue(): number {
return parseInt(localStorage.getItem(gameQualityKey) || "60");
}
@@ -90,6 +101,7 @@ class LocalUserStore {
setVideoQualityValue(value: number): void {
localStorage.setItem(videoQualityKey, "" + value);
}
getVideoQualityValue(): number {
return parseInt(localStorage.getItem(videoQualityKey) || "20");
}
@@ -97,6 +109,7 @@ class LocalUserStore {
setAudioPlayerVolume(value: number): void {
localStorage.setItem(audioPlayerVolumeKey, "" + value);
}
getAudioPlayerVolume(): number {
return parseFloat(localStorage.getItem(audioPlayerVolumeKey) || "1");
}
@@ -104,6 +117,7 @@ class LocalUserStore {
setAudioPlayerMuted(value: boolean): void {
localStorage.setItem(audioPlayerMuteKey, value.toString());
}
getAudioPlayerMuted(): boolean {
return localStorage.getItem(audioPlayerMuteKey) === "true";
}
@@ -111,6 +125,7 @@ class LocalUserStore {
setHelpCameraSettingsShown(): void {
localStorage.setItem(helpCameraSettingsShown, "1");
}
getHelpCameraSettingsShown(): boolean {
return localStorage.getItem(helpCameraSettingsShown) === "1";
}
@@ -118,6 +133,7 @@ class LocalUserStore {
setFullscreen(value: boolean): void {
localStorage.setItem(fullscreenKey, value.toString());
}
getFullscreen(): boolean {
return localStorage.getItem(fullscreenKey) === "true";
}
@@ -125,6 +141,7 @@ class LocalUserStore {
setForceCowebsiteTrigger(value: boolean): void {
localStorage.setItem(forceCowebsiteTriggerKey, value.toString());
}
getForceCowebsiteTrigger(): boolean {
return localStorage.getItem(forceCowebsiteTriggerKey) === "true";
}
@@ -132,9 +149,16 @@ class LocalUserStore {
setIgnoreFollowRequests(value: boolean): void {
localStorage.setItem(ignoreFollowRequests, value.toString());
}
getIgnoreFollowRequests(): boolean {
return localStorage.getItem(ignoreFollowRequests) === "true";
}
setDecreaseAudioPlayerVolumeWhileTalking(value: boolean): void {
localStorage.setItem(decreaseAudioPlayerVolumeWhileTalking, value.toString());
}
getDecreaseAudioPlayerVolumeWhileTalking(): boolean {
return localStorage.getItem(decreaseAudioPlayerVolumeWhileTalking) === "true";
}
async setLastRoomUrl(roomUrl: string): Promise<void> {
localStorage.setItem(lastRoomUrl, roomUrl.toString());
@@ -148,11 +172,13 @@ class LocalUserStore {
}
}
}
getLastRoomUrl(): string {
return (
localStorage.getItem(lastRoomUrl) ?? window.location.protocol + "//" + window.location.host + START_ROOM_URL
);
}
getLastRoomUrlCacheApi(): Promise<string | undefined> {
if (!("caches" in window)) {
return Promise.resolve(undefined);
@@ -169,6 +195,7 @@ class LocalUserStore {
setAuthToken(value: string | null) {
value ? localStorage.setItem(authToken, value) : localStorage.removeItem(authToken);
}
getAuthToken(): string | null {
return localStorage.getItem(authToken);
}
@@ -195,23 +222,29 @@ class LocalUserStore {
}
return oldValue === value;
}
setState(value: string) {
localStorage.setItem(state, value);
}
getState(): string | null {
return localStorage.getItem(state);
}
generateNonce(): string {
const newNonce = uuidv4();
localStorage.setItem(nonce, newNonce);
return newNonce;
}
getNonce(): string | null {
return localStorage.getItem(nonce);
}
setCode(value: string): void {
localStorage.setItem(code, value);
}
getCode(): string | null {
return localStorage.getItem(code);
}
@@ -219,11 +252,36 @@ class LocalUserStore {
setCameraSetup(cameraId: string) {
localStorage.setItem(cameraSetup, cameraId);
}
getCameraSetup(): { video: unknown; audio: unknown } | undefined {
const cameraSetupValues = localStorage.getItem(cameraSetup);
return cameraSetupValues != undefined ? JSON.parse(cameraSetupValues) : undefined;
}
setCameraPrivacySettings(option: boolean) {
localStorage.setItem(cameraPrivacySettings, option.toString());
}
getCameraPrivacySettings() {
//if this setting doesn't exist in LocalUserStore, we set a default value
if (localStorage.getItem(cameraPrivacySettings) == null) {
localStorage.setItem(cameraPrivacySettings, "false");
}
return localStorage.getItem(cameraPrivacySettings) === "true";
}
setMicrophonePrivacySettings(option: boolean) {
localStorage.setItem(microphonePrivacySettings, option.toString());
}
getMicrophonePrivacySettings() {
//if this setting doesn't exist in LocalUserStore, we set a default value
if (localStorage.getItem(microphonePrivacySettings) == null) {
localStorage.setItem(microphonePrivacySettings, "true");
}
return localStorage.getItem(microphonePrivacySettings) === "true";
}
getAllUserProperties(): Map<string, unknown> {
const result = new Map<string, string>();
for (let i = 0; i < localStorage.length; i++) {
+7 -6
View File
@@ -220,6 +220,7 @@ export class RoomConnection implements RoomConnection {
this.socket.onmessage = (messageEvent) => {
const arrayBuffer: ArrayBuffer = messageEvent.data;
const initCharacterLayers = characterLayers;
const serverToClientMessage = ServerToClientMessageTsProto.decode(new Uint8Array(arrayBuffer));
//const message = ServerToClientMessage.deserializeBinary(new Uint8Array(arrayBuffer));
@@ -342,12 +343,12 @@ export class RoomConnection implements RoomConnection {
this._userRoomToken = roomJoinedMessage.userRoomToken;
// If one of the URLs sent to us does not exist, let's go to the Woka selection screen.
for (const characterLayer of roomJoinedMessage.characterLayer) {
if (!characterLayer.url) {
this.goToSelectYourWokaScene();
this.closed = true;
break;
}
if (
roomJoinedMessage.characterLayer.length !== initCharacterLayers.length ||
roomJoinedMessage.characterLayer.find((layer) => !layer.url)
) {
this.goToSelectYourWokaScene();
this.closed = true;
}
if (this.closed) {
+9 -1
View File
@@ -9,6 +9,7 @@ import { EnableCameraSceneName } from "../Login/EnableCameraScene";
import { LoginSceneName } from "../Login/LoginScene";
import { SelectCharacterSceneName } from "../Login/SelectCharacterScene";
import { GameScene } from "./GameScene";
import { EmptySceneName } from "../Login/EmptyScene";
/**
* This class should be responsible for any scene starting/stopping
@@ -32,7 +33,14 @@ export class GameManager {
public async init(scenePlugin: Phaser.Scenes.ScenePlugin): Promise<string> {
this.scenePlugin = scenePlugin;
this.startRoom = await connectionManager.initGameConnexion();
const result = await connectionManager.initGameConnexion();
if (result instanceof URL) {
window.location.assign(result.toString());
// window.location.assign is not immediate and Javascript keeps running after.
// so we need to redirect to an empty Phaser scene, waiting for the redirection to take place
return EmptySceneName;
}
this.startRoom = result;
this.loadMap(this.startRoom);
//If player name was not set show login scene with player name
+17
View File
@@ -0,0 +1,17 @@
import { Scene } from "phaser";
export const EmptySceneName = "EmptyScene";
export class EmptyScene extends Scene {
constructor() {
super({
key: EmptySceneName,
});
}
preload() {}
create() {}
update(time: number, delta: number): void {}
}
+4 -1
View File
@@ -28,7 +28,10 @@ export class LoginScene extends ResizableScene {
gameManager.currentStartedRoom &&
gameManager.currentStartedRoom.authenticationMandatory
) {
connectionManager.loadOpenIDScreen();
const redirect = connectionManager.loadOpenIDScreen();
if (redirect !== null) {
window.location.assign(redirect.toString());
}
loginSceneVisibleIframeStore.set(true);
}
loginSceneVisibleStore.set(true);
+11 -2
View File
@@ -11,7 +11,7 @@ import { peerStore } from "./PeerStore";
import { privacyShutdownStore } from "./PrivacyShutdownStore";
import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError";
import { SoundMeter } from "../Phaser/Components/SoundMeter";
import { AudioContext } from "standardized-audio-context";
import { visibilityStore } from "./VisibilityStore";
/**
* A store that contains the camera state requested by the user (on or off).
@@ -242,6 +242,7 @@ export const mediaStreamConstraintsStore = derived(
privacyShutdownStore,
cameraEnergySavingStore,
isSilentStore,
visibilityStore,
],
(
[
@@ -254,6 +255,7 @@ export const mediaStreamConstraintsStore = derived(
$privacyShutdownStore,
$cameraEnergySavingStore,
$isSilentStore,
$visibilityStore,
],
set
) => {
@@ -292,7 +294,14 @@ export const mediaStreamConstraintsStore = derived(
// Disable webcam for privacy reasons (the game is not visible and we were talking to no one)
if ($privacyShutdownStore === true) {
currentVideoConstraint = false;
const userMicrophonePrivacySetting = localUserStore.getMicrophonePrivacySettings();
const userCameraPrivacySetting = localUserStore.getCameraPrivacySettings();
if (!userMicrophonePrivacySetting) {
currentAudioConstraint = false;
}
if (!userCameraPrivacySetting) {
currentVideoConstraint = false;
}
}
// Disable webcam for energy reasons (the user is not moving and we are talking to no one)
+2 -1
View File
@@ -2,7 +2,8 @@ import type { Translation } from "../i18n-types";
const audio: NonNullable<Translation["audio"]> = {
manager: {
reduce: "Während Unterhaltungen verringern",
reduce: "Verringern Sie die Lautstärke des Audioplayers während des Sprechens",
allow: "Ton zulassen",
},
message: "Sprachnachricht",
};
+7
View File
@@ -57,6 +57,13 @@ const menu: NonNullable<Translation["menu"]> = {
language: {
title: "Sprache",
},
privacySettings: {
title: "Einstellungen Abwesenheitsmodus",
explanation:
"Falls der WorkAdventure Tab nicht aktiv ist wird in den Abwesenheitsmodus umgeschaltet. Für diesen Modus kann eingestellt werden, ob die Kamera und/oder das Mikrofon deaktiviert sind solange der Tab nicht sichtbar ist.",
cameraToggle: "Kamera",
microphoneToggle: "Mikrofon",
},
save: {
warning: "(Das Spiel wird nach dem Speichern neugestartet)",
button: "Speichern",
+2 -1
View File
@@ -2,7 +2,8 @@ import type { BaseTranslation } from "../i18n-types";
const audio: BaseTranslation = {
manager: {
reduce: "reduce in conversations",
reduce: "Decrease audio player volume while speaking",
allow: "Allow audio",
},
message: "Audio message",
};
+7
View File
@@ -57,6 +57,13 @@ const menu: BaseTranslation = {
language: {
title: "Language",
},
privacySettings: {
title: "Away mode settings",
explanation:
'When the WorkAdventure tab is not visible, it switches to "away mode". In this mode, you can decide to automatically disable your webcam and/or microphone for as long as the tab stays hidden.',
cameraToggle: "Camera",
microphoneToggle: "Microphone",
},
save: {
warning: "(Saving these settings will restart the game)",
button: "Save",
+2 -1
View File
@@ -2,7 +2,8 @@ import type { Translation } from "../i18n-types";
const audio: NonNullable<Translation["audio"]> = {
manager: {
reduce: "réduit dans les conversations",
reduce: "Diminuer le volume du lecteur audio dans les conversations",
allow: "Autoriser l'audio",
},
message: "Message audio",
};
+7
View File
@@ -57,6 +57,13 @@ const menu: NonNullable<Translation["menu"]> = {
language: {
title: "Langage",
},
privacySettings: {
title: "Paramètres du mode absent",
explanation:
"Quand l'onglet WorkAdventure n'est pas visible, vous passez en \"mode absent\". Lorsque ce mode est actif, vous pouvez décider de garder vos webcam et/ou micro désactivés tant que vous ne revenez pas sur l'onglet",
cameraToggle: "Camera",
microphoneToggle: "Microphone",
},
save: {
warning: "(La sauvegarde de ces paramètres redémarre le jeu)",
button: "Sauvegarder",
+7 -1
View File
@@ -21,7 +21,6 @@ import type { Popup } from "./Api/iframe/Ui/Popup";
import type { Sound } from "./Api/iframe/Sound/Sound";
import { answerPromises, queryWorkadventure } from "./Api/iframe/IframeApiContribution";
import camera from "./Api/iframe/camera";
import {} from "./window";
const globalState = createState("global");
@@ -183,6 +182,13 @@ const wa = {
export type WorkAdventureApi = typeof wa;
declare global {
interface Window {
WA: WorkAdventureApi;
}
let WA: WorkAdventureApi;
}
window.WA = wa;
window.addEventListener(
-10
View File
@@ -1,10 +0,0 @@
import { WorkAdventureApi } from "./iframe_api";
import { WorkAdventureDesktopApi } from "@wa-preload-app";
declare global {
interface Window {
WA: WorkAdventureApi;
WAD: WorkAdventureDesktopApi;
}
let WA: WorkAdventureApi;
}