Adds settings options and localUser functions

This commit is contained in:
Benedicte Quimbert
2022-03-07 15:43:00 +01:00
parent d4e20a792e
commit 85f3a1a9c8
6 changed files with 287 additions and 216 deletions
+245 -216
View File
@@ -17,251 +17,280 @@
let valueGame: number = localUserStore.getGameQualityValue(); let valueGame: number = localUserStore.getGameQualityValue();
let valueVideo: number = localUserStore.getVideoQualityValue(); let valueVideo: number = localUserStore.getVideoQualityValue();
let valueLocale: string = $locale; let valueLocale: string = $locale;
let valuePrivacySettings = localUserStore.getPrivacySettings();
let previewValueGame = valueGame; let previewValueGame = valueGame;
let previewValueVideo = valueVideo; let previewValueVideo = valueVideo;
let previewValueLocale = valueLocale; let previewValueLocale = valueLocale;
let previewPrivacySettings = valuePrivacySettings; // TODO: retreive from local storage
function saveSetting() { function saveSetting() {
let change = false; let change = false;
if (valueLocale !== previewValueLocale) { if (valueLocale !== previewValueLocale) {
previewValueLocale = valueLocale; previewValueLocale = valueLocale;
setCurrentLocale(valueLocale as Locales); setCurrentLocale(valueLocale as Locales);
}
if (valueVideo !== previewValueVideo) {
previewValueVideo = valueVideo;
videoConstraintStore.setFrameRate(valueVideo);
}
if (valueGame !== previewValueGame) {
previewValueGame = valueGame;
localUserStore.setGameQualityValue(valueGame);
change = true;
}
audioManagerVolumeStore.setDecreaseWhileTalking(decreaseAudioPlayerVolumeWhileTalking);
if (change) {
window.location.reload();
}
closeMenu();
} }
function changeFullscreen() { if (valueVideo !== previewValueVideo) {
const body = HtmlUtils.querySelectorOrFail("body"); previewValueVideo = valueVideo;
if (body) { videoConstraintStore.setFrameRate(valueVideo);
if (document.fullscreenElement !== null && !fullscreen) {
document.exitFullscreen().catch((e) => console.error(e));
} else {
body.requestFullscreen().catch((e) => console.error(e));
}
localUserStore.setFullscreen(fullscreen);
}
} }
function changeNotification() { if (valueGame !== previewValueGame) {
if (Notification.permission === "granted") { previewValueGame = valueGame;
localUserStore.setGameQualityValue(valueGame);
change = true;
}
if (valuePrivacySettings !== previewPrivacySettings) {
console.log(`was: ${previewPrivacySettings} | is: ${valuePrivacySettings}`)
localUserStore.setPrivacySettings(valuePrivacySettings);
}
if (change) {
window.location.reload();
}
audioManagerVolumeStore.setDecreaseWhileTalking(decreaseAudioPlayerVolumeWhileTalking);
closeMenu();
}
function changeFullscreen() {
const body = HtmlUtils.querySelectorOrFail("body");
if (body) {
if (document.fullscreenElement !== null && !fullscreen) {
document.exitFullscreen().catch((e) => console.error(e));
} else {
body.requestFullscreen().catch((e) => console.error(e));
}
localUserStore.setFullscreen(fullscreen);
}
}
function changeNotification() {
if (Notification.permission === "granted") {
localUserStore.setNotification(notification ? "granted" : "denied");
} else {
Notification.requestPermission()
.then((response) => {
if (response === "granted") {
localUserStore.setNotification(notification ? "granted" : "denied"); localUserStore.setNotification(notification ? "granted" : "denied");
} else { } else {
Notification.requestPermission() localUserStore.setNotification("denied");
.then((response) => { notification = false;
if (response === "granted") { }
localUserStore.setNotification(notification ? "granted" : "denied"); })
} else { .catch((e) => console.error(e));
localUserStore.setNotification("denied");
notification = false;
}
})
.catch((e) => console.error(e));
}
} }
}
function changeForceCowebsiteTrigger() { function changeForceCowebsiteTrigger() {
localUserStore.setForceCowebsiteTrigger(forceCowebsiteTrigger); localUserStore.setForceCowebsiteTrigger(forceCowebsiteTrigger);
} }
function changeIgnoreFollowRequests() { function changeIgnoreFollowRequests() {
localUserStore.setIgnoreFollowRequests(ignoreFollowRequests); localUserStore.setIgnoreFollowRequests(ignoreFollowRequests);
} }
function closeMenu() {
menuVisiblilityStore.set(false);
}
function changeDecreaseAudioPlayerVolumeWhileTalking() { function changeDecreaseAudioPlayerVolumeWhileTalking() {
localUserStore.setDecreaseAudioPlayerVolumeWhileTalking(decreaseAudioPlayerVolumeWhileTalking); localUserStore.setDecreaseAudioPlayerVolumeWhileTalking(decreaseAudioPlayerVolumeWhileTalking);
} }
function closeMenu() { const isMobile = isMediaBreakpointUp("md");
menuVisiblilityStore.set(false);
}
const isMobile = isMediaBreakpointUp("md");
</script> </script>
<div class="settings-main" on:submit|preventDefault={saveSetting}> <div class="settings-main" on:submit|preventDefault={saveSetting}>
<section> <section>
<h3>{$LL.menu.settings.gameQuality.title()}</h3> <h3>{$LL.menu.settings.gameQuality.title()}</h3>
<div class="nes-select is-dark"> <div class="nes-select is-dark">
<select bind:value={valueGame}> <select bind:value={valueGame}>
<option value={120} <option value={120}
>{isMobile >{isMobile
? $LL.menu.settings.gameQuality.short.high() ? $LL.menu.settings.gameQuality.short.high()
: $LL.menu.settings.gameQuality.long.high()}</option : $LL.menu.settings.gameQuality.long.high()}</option
>
<option value={60}
>{isMobile
? $LL.menu.settings.gameQuality.short.medium()
: $LL.menu.settings.gameQuality.long.medium()}</option
>
<option value={40}
>{isMobile
? $LL.menu.settings.gameQuality.short.small()
: $LL.menu.settings.gameQuality.long.small()}</option
>
<option value={20}
>{isMobile
? $LL.menu.settings.gameQuality.short.minimum()
: $LL.menu.settings.gameQuality.long.minimum()}</option
>
</select>
</div>
</section>
<section>
<h3>{$LL.menu.settings.videoQuality.title()}</h3>
<div class="nes-select is-dark">
<select bind:value={valueVideo}>
<option value={30}
>{isMobile
? $LL.menu.settings.videoQuality.short.high()
: $LL.menu.settings.videoQuality.long.high()}</option
>
<option value={20}
>{isMobile
? $LL.menu.settings.videoQuality.short.medium()
: $LL.menu.settings.videoQuality.long.medium()}</option
>
<option value={10}
>{isMobile
? $LL.menu.settings.videoQuality.short.small()
: $LL.menu.settings.videoQuality.long.small()}</option
>
<option value={5}
>{isMobile
? $LL.menu.settings.videoQuality.short.minimum()
: $LL.menu.settings.videoQuality.long.minimum()}</option
>
</select>
</div>
</section>
<section>
<h3>{$LL.menu.settings.language.title()}</h3>
<div class="nes-select is-dark">
<select class="languages-switcher" bind:value={valueLocale}>
{#each displayableLocales as locale (locale.id)}
<option value={locale.id}>{`${locale.language} (${locale.country})`}</option>
{/each}
</select>
</div>
</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}
>{$LL.menu.settings.save.button()}</button
> >
</section> <option value={60}
<section class="settings-section-noSaveOption"> >{isMobile
<label> ? $LL.menu.settings.gameQuality.short.medium()
<input : $LL.menu.settings.gameQuality.long.medium()}</option
type="checkbox" >
class="nes-checkbox is-dark" <option value={40}
bind:checked={fullscreen} >{isMobile
on:change={changeFullscreen} ? $LL.menu.settings.gameQuality.short.small()
/> : $LL.menu.settings.gameQuality.long.small()}</option
<span>{$LL.menu.settings.fullscreen()}</span> >
</label> <option value={20}
<label> >{isMobile
<input ? $LL.menu.settings.gameQuality.short.minimum()
type="checkbox" : $LL.menu.settings.gameQuality.long.minimum()}</option
class="nes-checkbox is-dark" >
bind:checked={notification} </select>
on:change={changeNotification} </div>
/> </section>
<span>{$LL.menu.settings.notifications()}</span> <section>
</label> <h3>{$LL.menu.settings.videoQuality.title()}</h3>
<label> <div class="nes-select is-dark">
<input <select bind:value={valueVideo}>
type="checkbox" <option value={30}
class="nes-checkbox is-dark" >{isMobile
bind:checked={forceCowebsiteTrigger} ? $LL.menu.settings.videoQuality.short.high()
on:change={changeForceCowebsiteTrigger} : $LL.menu.settings.videoQuality.long.high()}</option
/> >
<span>{$LL.menu.settings.cowebsiteTrigger()}</span> <option value={20}
</label> >{isMobile
<label> ? $LL.menu.settings.videoQuality.short.medium()
<input : $LL.menu.settings.videoQuality.long.medium()}</option
type="checkbox" >
class="nes-checkbox is-dark" <option value={10}
bind:checked={ignoreFollowRequests} >{isMobile
on:change={changeIgnoreFollowRequests} ? $LL.menu.settings.videoQuality.short.small()
/> : $LL.menu.settings.videoQuality.long.small()}</option
<span>{$LL.menu.settings.ignoreFollowRequest()}</span> >
</label> <option value={5}
<label> >{isMobile
<input ? $LL.menu.settings.videoQuality.short.minimum()
type="checkbox" : $LL.menu.settings.videoQuality.long.minimum()}</option
class="nes-checkbox is-dark" >
bind:checked={decreaseAudioPlayerVolumeWhileTalking} </select>
on:change={changeDecreaseAudioPlayerVolumeWhileTalking} </div>
/> </section>
<span>{$LL.audio.manager.reduce()}</span> <section>
</label> <h3>{$LL.menu.settings.language.title()}</h3>
</section> <div class="nes-select is-dark">
<select class="languages-switcher" bind:value={valueLocale}>
{#each displayableLocales as locale (locale.id)}
<option value={locale.id}>{`${locale.language} (${locale.country})`}</option>
{/each}
</select>
</div>
</section>
<section>
<h3>{$LL.menu.settings.privacySettings.title()}</h3>
<p>{$LL.menu.settings.privacySettings.explaination()}</p>
<div class="nes-select is-dark">
<select class="privacy-settings-switcher" bind:value={valuePrivacySettings}>
<option value={"allEnabled"}
>{ $LL.menu.settings.privacySettings.allEnabled() }
</option>
<option value={"microphoneEnabled"}
>{ $LL.menu.settings.privacySettings.onlyMicrophoneEnabled() }
</option>
<option value={"cameraEnabled"}
>{ $LL.menu.settings.privacySettings.onlyCameraEnabled() }
</option>
<option value={"noneEnabled"}
>{ $LL.menu.settings.privacySettings.allDisabled() }
</option>
</select>
</div>
</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}
>{$LL.menu.settings.save.button()}</button
>
</section>
<section class="settings-section-noSaveOption">
<label>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={fullscreen}
on:change={changeFullscreen}
/>
<span>{$LL.menu.settings.fullscreen()}</span>
</label>
<label>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={notification}
on:change={changeNotification}
/>
<span>{$LL.menu.settings.notifications()}</span>
</label>
<label>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={forceCowebsiteTrigger}
on:change={changeForceCowebsiteTrigger}
/>
<span>{$LL.menu.settings.cowebsiteTrigger()}</span>
</label>
<label>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={ignoreFollowRequests}
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> </div>
<style lang="scss"> <style lang="scss">
@import "../../../style/breakpoints.scss"; @import "../../../style/breakpoints.scss";
div.settings-main {
height: calc(100% - 40px);
overflow-y: auto;
section {
width: 100%;
padding: 20px 20px 0;
margin-bottom: 20px;
text-align: center;
div.nes-select select:focus {
outline: none;
}
}
section.settings-section-save {
text-align: center;
p {
margin: 16px 0;
}
}
section.settings-section-noSaveOption {
display: flex;
align-items: center;
flex-wrap: wrap;
label {
flex: 1 1 auto;
text-align: center;
margin: 0 0 15px;
}
}
.languages-switcher option {
text-transform: capitalize;
}
}
@include media-breakpoint-up(md) {
div.settings-main { div.settings-main {
height: calc(100% - 40px); section {
overflow-y: auto; padding: 0;
}
section {
width: 100%;
padding: 20px 20px 0;
margin-bottom: 20px;
text-align: center;
div.nes-select select:focus {
outline: none;
}
}
section.settings-section-save {
text-align: center;
p {
margin: 16px 0;
}
}
section.settings-section-noSaveOption {
display: flex;
align-items: center;
flex-wrap: wrap;
label {
flex: 1 1 auto;
text-align: center;
margin: 0 0 15px;
}
}
.languages-switcher option {
text-transform: capitalize;
}
}
@include media-breakpoint-up(md) {
div.settings-main {
section {
padding: 0;
}
}
} }
}
</style> </style>
+9
View File
@@ -25,6 +25,7 @@ const code = "code";
const cameraSetup = "cameraSetup"; const cameraSetup = "cameraSetup";
const cacheAPIIndex = "workavdenture-cache"; const cacheAPIIndex = "workavdenture-cache";
const userProperties = "user-properties"; const userProperties = "user-properties";
const privacySettings = "privacySettings";
class LocalUserStore { class LocalUserStore {
saveUser(localUser: LocalUser) { saveUser(localUser: LocalUser) {
@@ -231,6 +232,14 @@ class LocalUserStore {
return cameraSetupValues != undefined ? JSON.parse(cameraSetupValues) : undefined; return cameraSetupValues != undefined ? JSON.parse(cameraSetupValues) : undefined;
} }
setPrivacySettings(option: string) {
localStorage.setItem(privacySettings, option)
}
getPrivacySettings() {
return localStorage.getItem(privacySettings);
}
getAllUserProperties(): Map<string, unknown> { getAllUserProperties(): Map<string, unknown> {
const result = new Map<string, string>(); const result = new Map<string, string>();
for (let i = 0; i < localStorage.length; i++) { for (let i = 0; i < localStorage.length; i++) {
+9
View File
@@ -12,6 +12,7 @@ import { privacyShutdownStore } from "./PrivacyShutdownStore";
import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError"; import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError";
import { SoundMeter } from "../Phaser/Components/SoundMeter"; import { SoundMeter } from "../Phaser/Components/SoundMeter";
import { AudioContext } from "standardized-audio-context"; import { AudioContext } from "standardized-audio-context";
import { visibilityStore } from "./VisibilityStore";
/** /**
* A store that contains the camera state requested by the user (on or off). * A store that contains the camera state requested by the user (on or off).
@@ -242,6 +243,8 @@ export const mediaStreamConstraintsStore = derived(
privacyShutdownStore, privacyShutdownStore,
cameraEnergySavingStore, cameraEnergySavingStore,
isSilentStore, isSilentStore,
visibilityStore,
//TODO: optionState
], ],
( (
[ [
@@ -254,6 +257,7 @@ export const mediaStreamConstraintsStore = derived(
$privacyShutdownStore, $privacyShutdownStore,
$cameraEnergySavingStore, $cameraEnergySavingStore,
$isSilentStore, $isSilentStore,
$visibilityStore
], ],
set set
) => { ) => {
@@ -308,6 +312,11 @@ export const mediaStreamConstraintsStore = derived(
currentAudioConstraint = false; currentAudioConstraint = false;
} }
// if ($visibilityStore === false && $option) {
//
// }
//TODO
// Let's make the changes only if the new value is different from the old one. // Let's make the changes only if the new value is different from the old one.
if ( if (
previousComputedVideoConstraint != currentVideoConstraint || previousComputedVideoConstraint != currentVideoConstraint ||
+8
View File
@@ -57,6 +57,14 @@ const menu: NonNullable<Translation["menu"]> = {
language: { language: {
title: "Sprache", title: "Sprache",
}, },
privacySettings: {
title: "Datenschutzeinstellungen", //TODO: confirm & complete translation
explaination: "",
allEnabled: "",
onlyCameraEnabled: "",
onlyMicrophoneEnabled: "",
allDisabled: ""
},
save: { save: {
warning: "(Das Spiel wird nach dem Speichern neugestartet)", warning: "(Das Spiel wird nach dem Speichern neugestartet)",
button: "Speichern", button: "Speichern",
+8
View File
@@ -57,6 +57,14 @@ const menu: BaseTranslation = {
language: { language: {
title: "Language", title: "Language",
}, },
privacySettings: {
title: "Privacy settings",
explaination: "Here you can set an option to keep your microphone/camera enabled when switching active tabs.",
allEnabled: "Camera and microphone always enabled",
onlyCameraEnabled: "Microphone disabled when the WA tab is not focused",
onlyMicrophoneEnabled: "Camera disabled when the WA tab is not focused",
allDisabled: "Both disabled when the WA tab is not focused"
},
save: { save: {
warning: "(Saving these settings will restart the game)", warning: "(Saving these settings will restart the game)",
button: "Save", button: "Save",
+8
View File
@@ -57,6 +57,14 @@ const menu: NonNullable<Translation["menu"]> = {
language: { language: {
title: "Langage", title: "Langage",
}, },
privacySettings: {
title: "Paramètres de confidentialité",
explaination: "Vous pouvez définir ici si vous souhaitez conserver ou non l'activation du microphone/de la caméra au passage sur un autre onglet.",
allEnabled: "Camera et microphone toujours actifs",
onlyCameraEnabled: "Seul le microphone est activé quand l'onglet WA n'est pas sélectionné",
onlyMicrophoneEnabled: "Seule la caméra est activé quand l'onglet WA n'est pas sélectionné",
allDisabled: "Tout désactiver quand l'onglet WA n'est pas sélectionné"
},
save: { save: {
warning: "(La sauvegarde de ces paramètres redémarre le jeu)", warning: "(La sauvegarde de ces paramètres redémarre le jeu)",
button: "Sauvegarder", button: "Sauvegarder",