merged develop

This commit is contained in:
Hanusiak Piotr 2021-12-07 13:56:28 +01:00
commit e62ad6b9c9
84 changed files with 3531 additions and 1845 deletions

View file

@ -1,6 +1,6 @@
<script lang="ts">
import { gameManager } from "../../Phaser/Game/GameManager";
import {onMount} from "svelte";
import { onMount } from "svelte";
let gameScene = gameManager.getCurrentGameScene();
@ -14,29 +14,33 @@
onMount(() => {
if (gameScene.mapFile.properties !== undefined) {
const propertyName = gameScene.mapFile.properties.find((property) => property.name === 'mapName')
if ( propertyName !== undefined && typeof propertyName.value === 'string') {
const propertyName = gameScene.mapFile.properties.find((property) => property.name === "mapName");
if (propertyName !== undefined && typeof propertyName.value === "string") {
mapName = propertyName.value;
}
const propertyDescription = gameScene.mapFile.properties.find((property) => property.name === 'mapDescription')
if (propertyDescription !== undefined && typeof propertyDescription.value === 'string') {
const propertyDescription = gameScene.mapFile.properties.find(
(property) => property.name === "mapDescription"
);
if (propertyDescription !== undefined && typeof propertyDescription.value === "string") {
mapDescription = propertyDescription.value;
}
const propertyCopyright = gameScene.mapFile.properties.find((property) => property.name === 'mapCopyright')
if (propertyCopyright !== undefined && typeof propertyCopyright.value === 'string') {
const propertyCopyright = gameScene.mapFile.properties.find((property) => property.name === "mapCopyright");
if (propertyCopyright !== undefined && typeof propertyCopyright.value === "string") {
mapCopyright = propertyCopyright.value;
}
}
for (const tileset of gameScene.mapFile.tilesets) {
if (tileset.properties !== undefined) {
const propertyTilesetCopyright = tileset.properties.find((property) => property.name === 'tilesetCopyright')
if (propertyTilesetCopyright !== undefined && typeof propertyTilesetCopyright.value === 'string') {
const propertyTilesetCopyright = tileset.properties.find(
(property) => property.name === "tilesetCopyright"
);
if (propertyTilesetCopyright !== undefined && typeof propertyTilesetCopyright.value === "string") {
tilesetCopyright = [...tilesetCopyright, propertyTilesetCopyright.value]; //Assignment needed to trigger Svelte's reactivity
}
}
}
})
});
</script>
<div class="about-room-main">
@ -44,51 +48,58 @@
<section class="container-overflow">
<h3>{mapName}</h3>
<p class="string-HTML">{mapDescription}</p>
<h3 class="nes-pointer hoverable" on:click={() => expandedMapCopyright = !expandedMapCopyright}>Copyrights of the map</h3>
<p class="string-HTML" hidden="{!expandedMapCopyright}">{mapCopyright}</p>
<h3 class="nes-pointer hoverable" on:click={() => expandedTilesetCopyright = !expandedTilesetCopyright}>Copyrights of the tilesets</h3>
<section hidden="{!expandedTilesetCopyright}">
<h3 class="nes-pointer hoverable" on:click={() => (expandedMapCopyright = !expandedMapCopyright)}>
Copyrights of the map
</h3>
<p class="string-HTML" hidden={!expandedMapCopyright}>{mapCopyright}</p>
<h3 class="nes-pointer hoverable" on:click={() => (expandedTilesetCopyright = !expandedTilesetCopyright)}>
Copyrights of the tilesets
</h3>
<section hidden={!expandedTilesetCopyright}>
{#each tilesetCopyright as copyright}
<p class="string-HTML">{copyright}</p>
{:else}
<p>The map creator did not declare a copyright for the tilesets. Warning, This doesn't mean that those tilesets have no license.</p>
<p>
The map creator did not declare a copyright for the tilesets. Warning, This doesn't mean that those
tilesets have no license.
</p>
{/each}
</section>
</section>
</div>
<style lang="scss">
.string-HTML{
white-space: pre-line;
}
div.about-room-main {
height: calc(100% - 56px);
h2, h3 {
width: 100%;
text-align: center;
.string-HTML {
white-space: pre-line;
}
h3.hoverable:hover {
background-color: #3c3e40;
border-radius: 32px;
}
section.container-overflow {
height: calc(100% - 220px);
margin: 0;
padding: 0;
overflow-y: auto;
}
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
div.about-room-main {
section.container-overflow {
height: calc(100% - 120px);
}
height: calc(100% - 56px);
h2,
h3 {
width: 100%;
text-align: center;
}
h3.hoverable:hover {
background-color: #3c3e40;
border-radius: 32px;
}
section.container-overflow {
height: calc(100% - 220px);
margin: 0;
padding: 0;
overflow-y: auto;
}
}
}
</style>
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
div.about-room-main {
section.container-overflow {
height: calc(100% - 120px);
}
}
}
</style>

View file

@ -26,31 +26,31 @@
const selectedFile = inputAudio.files ? inputAudio.files[0] : null;
if (!selectedFile) {
errorFile = true;
throw 'no file selected';
throw "no file selected";
}
const fd = new FormData();
fd.append('file', selectedFile);
fd.append("file", selectedFile);
const res = await gameScene.connection?.uploadAudio(fd);
const audioGlobalMessage: PlayGlobalMessageInterface = {
content: (res as { path: string }).path,
type: AUDIO_TYPE,
broadcastToWorld: broadcast
}
inputAudio.value = '';
broadcastToWorld: broadcast,
};
inputAudio.value = "";
gameScene.connection?.emitGlobalMessage(audioGlobalMessage);
}
}
},
};
function inputAudioFile(event: Event) {
const eventTarget : EventTargetFiles = (event.target as EventTargetFiles);
if(!eventTarget || !eventTarget.files || eventTarget.files.length === 0){
const eventTarget: EventTargetFiles = event.target as EventTargetFiles;
if (!eventTarget || !eventTarget.files || eventTarget.files.length === 0) {
return;
}
const file = eventTarget.files[0];
if(!file) {
if (!file) {
return;
}
@ -61,52 +61,65 @@
function getFileSize(number: number) {
if (number < 1024) {
return number + 'bytes';
return number + "bytes";
} else if (number >= 1024 && number < 1048576) {
return (number / 1024).toFixed(1) + 'KB';
return (number / 1024).toFixed(1) + "KB";
} else if (number >= 1048576) {
return (number / 1048576).toFixed(1) + 'MB';
return (number / 1048576).toFixed(1) + "MB";
} else {
return '';
return "";
}
}
</script>
<section class="section-input-send-audio">
<img class="nes-pointer" src="{uploadFile}" alt="Upload a file" on:click|preventDefault={ () => {fileInput.click();}}>
<img
class="nes-pointer"
src={uploadFile}
alt="Upload a file"
on:click|preventDefault={() => {
fileInput.click();
}}
/>
{#if fileName !== undefined}
<p>{fileName} : {fileSize}</p>
{/if}
{#if errorFile}
<p class="err">No file selected. You need to upload a file before sending it.</p>
{/if}
<input type="file" id="input-send-audio" bind:this={fileInput} on:change={(e) => {inputAudioFile(e)}}>
<input
type="file"
id="input-send-audio"
bind:this={fileInput}
on:change={(e) => {
inputAudioFile(e);
}}
/>
</section>
<style lang="scss">
section.section-input-send-audio {
display: flex;
flex-direction: column;
section.section-input-send-audio {
display: flex;
flex-direction: column;
height: 100%;
text-align: center;
height: 100%;
text-align: center;
img {
flex: 1 1 auto;
max-height: 80%;
margin-bottom: 20px;
img {
flex: 1 1 auto;
max-height: 80%;
margin-bottom: 20px;
}
p {
margin-bottom: 5px;
color: whitesmoke;
font-size: 1rem;
&.err {
color: #ce372b;
}
}
input {
display: none;
}
}
p {
margin-bottom: 5px;
color: whitesmoke;
font-size: 1rem;
&.err {
color: #ce372b;
}
}
input {
display: none;
}
}
</style>
</style>

View file

@ -1,5 +1,4 @@
<script lang="ts">
function goToGettingStarted() {
const sparkHost = "https://workadventu.re/getting-started";
window.open(sparkHost, "_blank");
@ -10,7 +9,7 @@
window.open(sparkHost, "_blank");
}
import {contactPageStore} from "../../Stores/MenuStore";
import { contactPageStore } from "../../Stores/MenuStore";
</script>
<div class="create-map-main">
@ -18,8 +17,8 @@
<section>
<h3>Getting started</h3>
<p>
WorkAdventure allows you to create an online space to communicate spontaneously with others.
And it all starts with creating your own space. Choose from a large selection of prefabricated maps by our team.
WorkAdventure allows you to create an online space to communicate spontaneously with others. And it all
starts with creating your own space. Choose from a large selection of prefabricated maps by our team.
</p>
<button type="button" class="nes-btn is-primary" on:click={goToGettingStarted}>Getting started</button>
</section>
@ -30,35 +29,37 @@
<button type="button" class="nes-btn" on:click={goToBuildingMap}>Create your map</button>
</section>
<iframe title="contact"
src="{$contactPageStore}"
allow="clipboard-read; clipboard-write self {$contactPageStore}"
allowfullscreen></iframe>
<iframe
title="contact"
src={$contactPageStore}
allow="clipboard-read; clipboard-write self {$contactPageStore}"
allowfullscreen
/>
</section>
</div>
<style lang="scss">
div.create-map-main {
height: calc(100% - 56px);
height: calc(100% - 56px);
text-align: center;
text-align: center;
section {
margin-bottom: 50px;
}
section {
margin-bottom: 50px;
}
section.container-overflow {
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
section.container-overflow {
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
}
iframe {
border: none;
height: calc(100% - 56px);
width: 100%;
margin: 0;
border: none;
height: calc(100% - 56px);
width: 100%;
margin: 0;
}
</style>
</style>

View file

@ -1,33 +1,32 @@
<script lang="ts">
import {onDestroy, onMount} from "svelte";
import {iframeListener} from "../../Api/IframeListener";
import { onDestroy, onMount } from "svelte";
import { iframeListener } from "../../Api/IframeListener";
export let url: string;
export let allowApi: boolean;
let HTMLIframe: HTMLIFrameElement;
onMount( () => {
onMount(() => {
if (allowApi) {
iframeListener.registerIframe(HTMLIframe);
}
})
});
onDestroy( () => {
onDestroy(() => {
if (allowApi) {
iframeListener.unregisterIframe(HTMLIframe);
}
})
});
</script>
<iframe title="customSubMenu" src="{url}" bind:this={HTMLIframe}></iframe>
<iframe title="customSubMenu" src={url} bind:this={HTMLIframe} />
<style lang="scss">
iframe {
border: none;
height: calc(100% - 56px);
width: 100%;
margin: 0;
}
</style>
iframe {
border: none;
height: calc(100% - 56px);
width: 100%;
margin: 0;
}
</style>

View file

@ -1,6 +1,6 @@
<script lang="ts">
import TextGlobalMessage from './TextGlobalMessage.svelte';
import AudioGlobalMessage from './AudioGlobalMessage.svelte';
import TextGlobalMessage from "./TextGlobalMessage.svelte";
import AudioGlobalMessage from "./AudioGlobalMessage.svelte";
let handleSendText: { sendTextMessage(broadcast: boolean): void };
let handleSendAudio: { sendAudioMessage(broadcast: boolean): Promise<void> };
@ -32,23 +32,31 @@
<div class="global-message-main">
<div class="global-message-subOptions">
<section>
<button type="button" class="nes-btn {inputSendTextActive ? 'is-disabled' : ''}" on:click|preventDefault={activateInputText}>Text</button>
<button
type="button"
class="nes-btn {inputSendTextActive ? 'is-disabled' : ''}"
on:click|preventDefault={activateInputText}>Text</button
>
</section>
<section>
<button type="button" class="nes-btn {uploadAudioActive ? 'is-disabled' : ''}" on:click|preventDefault={activateUploadAudio}>Audio</button>
<button
type="button"
class="nes-btn {uploadAudioActive ? 'is-disabled' : ''}"
on:click|preventDefault={activateUploadAudio}>Audio</button
>
</section>
</div>
<div class="global-message-content">
{#if inputSendTextActive}
<TextGlobalMessage bind:handleSending={handleSendText}/>
<TextGlobalMessage bind:handleSending={handleSendText} />
{/if}
{#if uploadAudioActive}
<AudioGlobalMessage bind:handleSending={handleSendAudio}/>
<AudioGlobalMessage bind:handleSending={handleSendAudio} />
{/if}
</div>
<div class="global-message-footer">
<label>
<input type="checkbox" class="nes-checkbox is-dark nes-pointer" bind:checked={broadcastToWorld}>
<input type="checkbox" class="nes-checkbox is-dark nes-pointer" bind:checked={broadcastToWorld} />
<span>Broadcast to all rooms of the world</span>
</label>
<section>
@ -57,62 +65,59 @@
</div>
</div>
<style lang="scss">
div.global-message-main {
height: calc(100% - 50px);
display: grid;
grid-template-rows: 15% 65% 20%;
div.global-message-subOptions {
height: calc(100% - 50px);
display: grid;
grid-template-columns: 50% 50%;
margin-bottom: 20px;
grid-template-rows: 15% 65% 20%;
section {
display: flex;
justify-content: center;
align-items: center;
}
}
div.global-message-subOptions {
display: grid;
grid-template-columns: 50% 50%;
margin-bottom: 20px;
div.global-message-footer {
margin-bottom: 10px;
display: grid;
grid-template-rows: 50% 50%;
section {
display: flex;
justify-content: center;
align-items: center;
section {
display: flex;
justify-content: center;
align-items: center;
}
}
label {
margin: 10px;
display: flex;
justify-content: center;
align-items: center;
div.global-message-footer {
margin-bottom: 10px;
span {
font-family: "Press Start 2P";
}
display: grid;
grid-template-rows: 50% 50%;
section {
display: flex;
justify-content: center;
align-items: center;
}
label {
margin: 10px;
display: flex;
justify-content: center;
align-items: center;
span {
font-family: "Press Start 2P";
}
}
}
}
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
.global-message-content {
height: calc(100% - 5px);
}
.global-message-footer {
margin-bottom: 0;
label {
width: calc(100% - 10px);
.global-message-content {
height: calc(100% - 5px);
}
.global-message-footer {
margin-bottom: 0;
label {
width: calc(100% - 10px);
}
}
}
}
</style>
</style>

View file

@ -1,18 +1,18 @@
<script lang="ts">
function copyLink() {
const input: HTMLInputElement = document.getElementById('input-share-link') as HTMLInputElement;
const input: HTMLInputElement = document.getElementById("input-share-link") as HTMLInputElement;
input.focus();
input.select();
document.execCommand('copy');
document.execCommand("copy");
}
async function shareLink() {
const shareData = {url: location.toString()};
const shareData = { url: location.toString() };
try {
await navigator.share(shareData);
} catch (err) {
console.error('Error: ' + err);
console.error("Error: " + err);
copyLink();
}
}
@ -22,12 +22,12 @@
<section class="container-overflow">
<section class="share-url not-mobile">
<h3>Share the link of the room !</h3>
<input type="text" readonly id="input-share-link" value={location.toString()}>
<input type="text" readonly id="input-share-link" value={location.toString()} />
<button type="button" class="nes-btn is-primary" on:click={copyLink}>Copy</button>
</section>
<section class="is-mobile">
<h3>Share the link of the room !</h3>
<input type="hidden" readonly id="input-share-link" value={location.toString()}>
<input type="hidden" readonly id="input-share-link" value={location.toString()} />
<button type="button" class="nes-btn is-primary" on:click={shareLink}>Share</button>
</section>
</section>
@ -35,41 +35,41 @@
<style lang="scss">
div.guest-main {
height: calc(100% - 56px);
height: calc(100% - 56px);
text-align: center;
text-align: center;
section {
margin-bottom: 50px;
}
section.container-overflow {
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
section.is-mobile {
display: none;
}
}
@media only screen and (max-width: 900px), only screen and (max-height: 600px) {
div.guest-main {
section.share-url.not-mobile {
display: none;
}
section.is-mobile {
display: block;
text-align: center;
margin-bottom: 20px;
section {
margin-bottom: 50px;
}
section.container-overflow {
height: calc(100% - 120px);
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
}
section.is-mobile {
display: none;
}
}
}
</style>
@media only screen and (max-width: 900px), only screen and (max-height: 600px) {
div.guest-main {
section.share-url.not-mobile {
display: none;
}
section.is-mobile {
display: block;
text-align: center;
margin-bottom: 20px;
}
section.container-overflow {
height: calc(100% - 120px);
}
}
}
</style>

View file

@ -1,46 +1,46 @@
<script lang="typescript">
import {fly} from "svelte/transition";
import { fly } from "svelte/transition";
import SettingsSubMenu from "./SettingsSubMenu.svelte";
import ProfileSubMenu from "./ProfileSubMenu.svelte";
import AboutRoomSubMenu from "./AboutRoomSubMenu.svelte";
import GlobalMessageSubMenu from "./GlobalMessagesSubMenu.svelte";
import ContactSubMenu from "./ContactSubMenu.svelte";
import CustomSubMenu from "./CustomSubMenu.svelte"
import CustomSubMenu from "./CustomSubMenu.svelte";
import GuestSubMenu from "./GuestSubMenu.svelte";
import {
checkSubMenuToShow,
customMenuIframe,
menuVisiblilityStore,
SubMenusInterface,
subMenusStore
subMenusStore,
} from "../../Stores/MenuStore";
import {onDestroy, onMount} from "svelte";
import {get} from "svelte/store";
import type {Unsubscriber} from "svelte/store";
import {sendMenuClickedEvent} from "../../Api/iframe/Ui/MenuItem";
import { onDestroy, onMount } from "svelte";
import { get } from "svelte/store";
import type { Unsubscriber } from "svelte/store";
import { sendMenuClickedEvent } from "../../Api/iframe/Ui/MenuItem";
let activeSubMenu: string = SubMenusInterface.profile;
let activeComponent: typeof ProfileSubMenu | typeof CustomSubMenu = ProfileSubMenu;
let props: { url: string, allowApi: boolean };
let props: { url: string; allowApi: boolean };
let unsubscriberSubMenuStore: Unsubscriber;
onMount(() => {
unsubscriberSubMenuStore = subMenusStore.subscribe(() => {
if(!get(subMenusStore).includes(activeSubMenu)) {
if (!get(subMenusStore).includes(activeSubMenu)) {
switchMenu(SubMenusInterface.profile);
}
})
});
checkSubMenuToShow();
switchMenu(SubMenusInterface.profile);
})
});
onDestroy(() => {
if(unsubscriberSubMenuStore) {
if (unsubscriberSubMenuStore) {
unsubscriberSubMenuStore();
}
})
});
function switchMenu(menu: string) {
if (get(subMenusStore).find((subMenu) => subMenu === menu)) {
@ -64,7 +64,7 @@
case SubMenusInterface.contact:
activeComponent = ContactSubMenu;
break;
default:
default: {
const customMenu = customMenuIframe.get(menu);
if (customMenu !== undefined) {
props = { url: customMenu.url, allowApi: customMenu.allowApi };
@ -74,109 +74,113 @@
menuVisiblilityStore.set(false);
}
break;
}
}
} else throw ("There is no menu called " + menu);
} else throw "There is no menu called " + menu;
}
function closeMenu() {
menuVisiblilityStore.set(false);
}
function onKeyDown(e:KeyboardEvent) {
if (e.key === 'Escape') {
function onKeyDown(e: KeyboardEvent) {
if (e.key === "Escape") {
closeMenu();
}
}
</script>
<svelte:window on:keydown={onKeyDown}/>
<svelte:window on:keydown={onKeyDown} />
<div class="menu-container-main">
<div class="menu-nav-sidebar nes-container is-rounded" transition:fly="{{ x: -1000, duration: 500 }}">
<div class="menu-nav-sidebar nes-container is-rounded" transition:fly={{ x: -1000, duration: 500 }}>
<h2>Menu</h2>
<nav>
{#each $subMenusStore as submenu}
<button type="button" class="nes-btn {activeSubMenu === submenu ? 'is-disabled' : ''}" on:click|preventDefault={() => switchMenu(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 }}">
<div class="menu-submenu-container nes-container is-rounded" transition:fly={{ y: -1000, duration: 500 }}>
<button type="button" class="nes-btn is-error close" on:click={closeMenu}>&times</button>
<h2>{activeSubMenu}</h2>
<svelte:component this={activeComponent} {...props}/>
<svelte:component this={activeComponent} {...props} />
</div>
</div>
<style lang="scss">
.nes-container {
padding: 5px;
}
div.menu-container-main {
--size-first-columns-grid: 200px;
font-family: "Press Start 2P";
pointer-events: auto;
height: 80%;
width: 75%;
top: 10%;
position: relative;
z-index: 80;
margin: auto;
display: grid;
grid-template-columns: var(--size-first-columns-grid) calc(100% - var(--size-first-columns-grid));
grid-template-rows: 100%;
h2 {
text-align: center;
margin-bottom: 20px;
.nes-container {
padding: 5px;
}
div.menu-nav-sidebar {
background-color: #333333;
color: whitesmoke;
nav button {
width: calc(100% - 10px);
margin-bottom: 10px;
}
}
div.menu-submenu-container {
background-color: #333333;
color: whitesmoke;
.nes-btn.is-error.close {
position: absolute;
top: -20px;
right: -20px;
}
}
}
@media only screen and (max-width: 800px) {
div.menu-container-main {
--size-first-columns-grid: 120px;
height: 70%;
top: 55px;
width: 100%;
font-size: 0.5em;
--size-first-columns-grid: 200px;
div.menu-nav-sidebar {
overflow-y: auto;
}
font-family: "Press Start 2P";
pointer-events: auto;
height: 80%;
width: 75%;
top: 10%;
div.menu-submenu-container {
.nes-btn.is-error.close {
position: absolute;
top: -35px;
right: 0;
position: relative;
z-index: 80;
margin: auto;
display: grid;
grid-template-columns: var(--size-first-columns-grid) calc(100% - var(--size-first-columns-grid));
grid-template-rows: 100%;
h2 {
text-align: center;
margin-bottom: 20px;
}
div.menu-nav-sidebar {
background-color: #333333;
color: whitesmoke;
nav button {
width: calc(100% - 10px);
margin-bottom: 10px;
}
}
div.menu-submenu-container {
background-color: #333333;
color: whitesmoke;
.nes-btn.is-error.close {
position: absolute;
top: -20px;
right: -20px;
}
}
}
}
}
</style>
@media only screen and (max-width: 800px) {
div.menu-container-main {
--size-first-columns-grid: 120px;
height: 70%;
top: 55px;
width: 100%;
font-size: 0.5em;
div.menu-nav-sidebar {
overflow-y: auto;
}
div.menu-submenu-container {
.nes-btn.is-error.close {
position: absolute;
top: -35px;
right: 0;
}
}
}
}
</style>

View file

@ -1,62 +1,78 @@
<script lang="typescript">
import logoTalk from "../images/logo-message-pixel.png"
import logoTalk from "../images/logo-message-pixel.png";
import logoWA from "../images/logo-WA-pixel.png";
import {menuVisiblilityStore} from "../../Stores/MenuStore";
import {chatVisibilityStore} from "../../Stores/ChatStore";
import {get} from "svelte/store";
import Woka from '../Woka/Woka.svelte';
import { menuVisiblilityStore } from "../../Stores/MenuStore";
import { chatVisibilityStore } from "../../Stores/ChatStore";
import { get } from "svelte/store";
import Woka from "../Woka/Woka.svelte";
function showMenu(){
menuVisiblilityStore.set(!get(menuVisiblilityStore))
function showMenu() {
menuVisiblilityStore.set(!get(menuVisiblilityStore));
}
function showChat(){
function showChat() {
chatVisibilityStore.set(true);
}
</script>
<svelte:window/>
<svelte:window />
<main class="menuIcon">
<div class="nes-pointer woka" on:click|preventDefault={showMenu}>
<Woka userId={-1} placeholderSrc={logoWA}/>
<Woka userId={-1} placeholderSrc={logoWA} />
</div>
<img src={logoTalk} alt="open menu" class="nes-pointer" on:click|preventDefault={showChat}>
<img src={logoTalk} alt="open menu" class="nes-pointer" on:click|preventDefault={showChat} />
</main>
<style lang="scss">
.menuIcon {
display: inline-grid;
z-index: 90;
position: relative;
margin: 25px;
img {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
image-rendering: pixelated;
}
.woka {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
}
}
.menuIcon img:hover{
transform: scale(1.2);
}
.menuIcon .woka:hover{
transform: scale(1.2);
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
.menuIcon {
margin: 3px;
img {
width: 50px;
}
display: inline-grid;
z-index: 90;
position: relative;
margin: 25px;
img {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
image-rendering: pixelated;
}
.woka {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
}
}
.menuIcon img:hover {
transform: scale(1.2);
}
.menuIcon .woka:hover {
transform: scale(1.2);
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
.menuIcon {
display: inline-grid;
z-index: 90;
position: relative;
margin: 25px;
img {
pointer-events: auto;
width: 60px;
padding-top: 0;
margin: 3px;
}
}
.menuIcon img:hover {
transform: scale(1.2);
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
.menuIcon {
margin: 3px;
img {
width: 50px;
}
}
}
}
}
</style>

View file

@ -1,60 +1,59 @@
<script lang="typescript">
import {gameManager} from "../../Phaser/Game/GameManager";
import {SelectCompanionScene, SelectCompanionSceneName} from "../../Phaser/Login/SelectCompanionScene";
import {menuIconVisiblilityStore, menuVisiblilityStore, userIsConnected} from "../../Stores/MenuStore";
import {selectCompanionSceneVisibleStore} from "../../Stores/SelectCompanionStore";
import {LoginScene, LoginSceneName} from "../../Phaser/Login/LoginScene";
import {loginSceneVisibleStore} from "../../Stores/LoginSceneStore";
import {selectCharacterSceneVisibleStore} from "../../Stores/SelectCharacterStore";
import {SelectCharacterScene, SelectCharacterSceneName} from "../../Phaser/Login/SelectCharacterScene";
import {connectionManager} from "../../Connexion/ConnectionManager";
import {PROFILE_URL} from "../../Enum/EnvironmentVariable";
import {localUserStore} from "../../Connexion/LocalUserStore";
import {EnableCameraScene, EnableCameraSceneName} from "../../Phaser/Login/EnableCameraScene";
import {enableCameraSceneVisibilityStore} from "../../Stores/MediaStore";
import { gameManager } from "../../Phaser/Game/GameManager";
import { SelectCompanionScene, SelectCompanionSceneName } from "../../Phaser/Login/SelectCompanionScene";
import { menuIconVisiblilityStore, menuVisiblilityStore, userIsConnected } from "../../Stores/MenuStore";
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
import { LoginScene, LoginSceneName } from "../../Phaser/Login/LoginScene";
import { loginSceneVisibleStore } from "../../Stores/LoginSceneStore";
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
import { connectionManager } from "../../Connexion/ConnectionManager";
import { PROFILE_URL } from "../../Enum/EnvironmentVariable";
import { localUserStore } from "../../Connexion/LocalUserStore";
import { EnableCameraScene, EnableCameraSceneName } from "../../Phaser/Login/EnableCameraScene";
import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
import btnProfileSubMenuCamera from "../images/btn-menu-profile-camera.svg";
import btnProfileSubMenuIdentity from "../images/btn-menu-profile-identity.svg";
import btnProfileSubMenuCompanion from "../images/btn-menu-profile-companion.svg";
import btnProfileSubMenuWoka from "../images/btn-menu-profile-woka.svg";
function disableMenuStores(){
function disableMenuStores() {
menuVisiblilityStore.set(false);
menuIconVisiblilityStore.set(false);
}
function openEditCompanionScene(){
function openEditCompanionScene() {
disableMenuStores();
selectCompanionSceneVisibleStore.set(true);
gameManager.leaveGame(SelectCompanionSceneName,new SelectCompanionScene());
gameManager.leaveGame(SelectCompanionSceneName, new SelectCompanionScene());
}
function openEditNameScene(){
function openEditNameScene() {
disableMenuStores();
loginSceneVisibleStore.set(true);
gameManager.leaveGame(LoginSceneName,new LoginScene());
gameManager.leaveGame(LoginSceneName, new LoginScene());
}
function openEditSkinScene(){
function openEditSkinScene() {
disableMenuStores();
selectCharacterSceneVisibleStore.set(true);
gameManager.leaveGame(SelectCharacterSceneName,new SelectCharacterScene());
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
}
function logOut(){
function logOut() {
disableMenuStores();
loginSceneVisibleStore.set(true);
connectionManager.logout();
}
function getProfileUrl(){
function getProfileUrl() {
return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`;
}
function openEnableCameraScene(){
function openEnableCameraScene() {
disableMenuStores();
enableCameraSceneVisibilityStore.showEnableCameraScene();
gameManager.leaveGame(EnableCameraSceneName,new EnableCameraScene());
gameManager.leaveGame(EnableCameraSceneName, new EnableCameraScene());
}
</script>
@ -62,19 +61,19 @@
<div class="submenu">
<section>
<button type="button" class="nes-btn" on:click|preventDefault={openEditNameScene}>
<img src={btnProfileSubMenuIdentity} alt="Edit your name">
<img src={btnProfileSubMenuIdentity} alt="Edit your name" />
<span class="btn-hover">Edit your name</span>
</button>
<button type="button" class="nes-btn" on:click|preventDefault={openEditSkinScene}>
<img src={btnProfileSubMenuWoka} alt="Edit your WOKA">
<img src={btnProfileSubMenuWoka} alt="Edit your WOKA" />
<span class="btn-hover">Edit your WOKA</span>
</button>
<button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>
<img src={btnProfileSubMenuCompanion} alt="Edit your companion">
<img src={btnProfileSubMenuCompanion} alt="Edit your companion" />
<span class="btn-hover">Edit your companion</span>
</button>
<button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>
<img src={btnProfileSubMenuCamera} alt="Edit your camera">
<img src={btnProfileSubMenuCamera} alt="Edit your camera" />
<span class="btn-hover">Edit your camera</span>
</button>
</section>
@ -84,7 +83,7 @@
{#if $userIsConnected}
<section>
{#if PROFILE_URL != undefined}
<iframe title="profile" src="{getProfileUrl()}"></iframe>
<iframe title="profile" src={getProfileUrl()} />
{/if}
</section>
<section>
@ -99,68 +98,68 @@
</div>
<style lang="scss">
div.customize-main{
width: 100%;
display: inline-flex;
div.submenu{
height: 100%;
width: 50px;
button {
transition: all .5s ease;
text-align: left;
white-space: nowrap;
margin-bottom: 10px;
max-height: 44px;
img {
height: 26px;
width: 26px;
cursor: pointer;
}
span.btn-hover{
display: none;
font-family: "Press Start 2P";
}
&:hover{
width: auto;
span.btn-hover {
display: initial;
}
}
}
}
div.content {
div.customize-main {
width: 100%;
section {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin-bottom: 20px;
display: inline-flex;
iframe {
width: 100%;
height: 50vh;
border: none;
}
div.submenu {
height: 100%;
width: 50px;
button {
height: 50px;
width: 250px;
}
button {
transition: all 0.5s ease;
text-align: left;
white-space: nowrap;
margin-bottom: 10px;
max-height: 44px;
img {
height: 26px;
width: 26px;
cursor: pointer;
}
span.btn-hover {
display: none;
font-family: "Press Start 2P";
}
&:hover {
width: auto;
span.btn-hover {
display: initial;
}
}
}
}
div.content {
width: 100%;
section {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin-bottom: 20px;
iframe {
width: 100%;
height: 50vh;
border: none;
}
button {
height: 50px;
width: 250px;
}
}
}
}
}
@media only screen and (max-width: 800px) {
div.customize-main.content section button {
width: 130px;
}
div.customize-main.content section button {
width: 130px;
}
}
</style>
</style>

View file

@ -1,62 +1,67 @@
<script lang="typescript">
import {localUserStore} from "../../Connexion/LocalUserStore";
import {videoConstraintStore} from "../../Stores/MediaStore";
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
import {isMobile} from "../../Enum/EnvironmentVariable";
import {menuVisiblilityStore} from "../../Stores/MenuStore";
import { localUserStore } from "../../Connexion/LocalUserStore";
import { videoConstraintStore } from "../../Stores/MediaStore";
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
import { isMobile } from "../../Enum/EnvironmentVariable";
import { menuVisiblilityStore } from "../../Stores/MenuStore";
let fullscreen : boolean = localUserStore.getFullscreen();
let notification : boolean = localUserStore.getNotification() === 'granted';
let valueGame : number = localUserStore.getGameQualityValue();
let valueVideo : number = localUserStore.getVideoQualityValue();
let previewValueGame = valueGame;
let previewValueVideo = valueVideo;
let fullscreen: boolean = localUserStore.getFullscreen();
let notification: boolean = localUserStore.getNotification() === "granted";
let forceCowebsiteTrigger: boolean = localUserStore.getForceCowebsiteTrigger();
let valueGame: number = localUserStore.getGameQualityValue();
let valueVideo: number = localUserStore.getVideoQualityValue();
let previewValueGame = valueGame;
let previewValueVideo = valueVideo;
function saveSetting(){
if (valueGame !== previewValueGame) {
previewValueGame = valueGame;
localUserStore.setGameQualityValue(valueGame);
window.location.reload();
}
if (valueVideo !== previewValueVideo) {
previewValueVideo = valueVideo;
videoConstraintStore.setFrameRate(valueVideo);
}
closeMenu();
}
function changeFullscreen() {
const body = HtmlUtils.querySelectorOrFail('body');
if (body) {
if (document.fullscreenElement !== null && !fullscreen) {
document.exitFullscreen()
} else {
body.requestFullscreen();
function saveSetting() {
if (valueGame !== previewValueGame) {
previewValueGame = valueGame;
localUserStore.setGameQualityValue(valueGame);
window.location.reload();
}
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');
if (valueVideo !== previewValueVideo) {
previewValueVideo = valueVideo;
videoConstraintStore.setFrameRate(valueVideo);
}
closeMenu();
}
function changeFullscreen() {
const body = HtmlUtils.querySelectorOrFail("body");
if (body) {
if (document.fullscreenElement !== null && !fullscreen) {
document.exitFullscreen();
} else {
localUserStore.setNotification('denied');
notification = false;
body.requestFullscreen();
}
})
localUserStore.setFullscreen(fullscreen);
}
}
}
function closeMenu() {
menuVisiblilityStore.set(false);
}
function changeNotification() {
if (Notification.permission === "granted") {
localUserStore.setNotification(notification ? "granted" : "denied");
} else {
Notification.requestPermission().then((response) => {
if (response === "granted") {
localUserStore.setNotification(notification ? "granted" : "denied");
} else {
localUserStore.setNotification("denied");
notification = false;
}
});
}
}
function changeForceCowebsiteTrigger() {
localUserStore.setForceCowebsiteTrigger(forceCowebsiteTrigger);
}
function closeMenu() {
menuVisiblilityStore.set(false);
}
</script>
<div class="settings-main" on:submit|preventDefault={saveSetting}>
@ -64,10 +69,12 @@ function closeMenu() {
<h3>Game quality</h3>
<div class="nes-select is-dark">
<select bind:value={valueGame}>
<option value="{120}">{isMobile() ? 'High (120 fps)' : 'High video quality (120 fps)'}</option>
<option value="{60}">{isMobile() ? 'Medium (60 fps)' : 'Medium video quality (60 fps, recommended)'}</option>
<option value="{40}">{isMobile() ? 'Minimum (40 fps)' : 'Minimum video quality (40 fps)'}</option>
<option value="{20}">{isMobile() ? 'Small (20 fps)' : 'Small video quality (20 fps)'}</option>
<option value={120}>{isMobile() ? "High (120 fps)" : "High video quality (120 fps)"}</option>
<option value={60}
>{isMobile() ? "Medium (60 fps)" : "Medium video quality (60 fps, recommended)"}</option
>
<option value={40}>{isMobile() ? "Minimum (40 fps)" : "Minimum video quality (40 fps)"}</option>
<option value={20}>{isMobile() ? "Small (20 fps)" : "Small video quality (20 fps)"}</option>
</select>
</div>
</section>
@ -75,10 +82,12 @@ function closeMenu() {
<h3>Video quality</h3>
<div class="nes-select is-dark">
<select bind:value={valueVideo}>
<option value="{30}">{isMobile() ? 'High (30 fps)' : 'High video quality (30 fps)'}</option>
<option value="{20}">{isMobile() ? 'Medium (20 fps)' : 'Medium video quality (20 fps, recommended)'}</option>
<option value="{10}">{isMobile() ? 'Minimum (10 fps)' : 'Minimum video quality (10 fps)'}</option>
<option value="{5}">{isMobile() ? 'Small (5 fps)' : 'Small video quality (5 fps)'}</option>
<option value={30}>{isMobile() ? "High (30 fps)" : "High video quality (30 fps)"}</option>
<option value={20}
>{isMobile() ? "Medium (20 fps)" : "Medium video quality (20 fps, recommended)"}</option
>
<option value={10}>{isMobile() ? "Minimum (10 fps)" : "Minimum video quality (10 fps)"}</option>
<option value={5}>{isMobile() ? "Small (5 fps)" : "Small video quality (5 fps)"}</option>
</select>
</div>
</section>
@ -88,55 +97,74 @@ function closeMenu() {
</section>
<section class="settings-section-noSaveOption">
<label>
<input type="checkbox" class="nes-checkbox is-dark" bind:checked={fullscreen} on:change={changeFullscreen}/>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={fullscreen}
on:change={changeFullscreen}
/>
<span>Fullscreen</span>
</label>
<label>
<input type="checkbox" class="nes-checkbox is-dark" bind:checked={notification} on:change={changeNotification}>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={notification}
on:change={changeNotification}
/>
<span>Notifications</span>
</label>
<label>
<input
type="checkbox"
class="nes-checkbox is-dark"
bind:checked={forceCowebsiteTrigger}
on:change={changeForceCowebsiteTrigger}
/>
<span>Always ask before opening websites and Jitsi Meet rooms</span>
</label>
</section>
</div>
<style lang="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;
}
}
}
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
div.settings-main {
section {
padding: 0;
}
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;
}
}
}
}
</style>
@media only screen and (max-width: 800px), only screen and (max-height: 800px) {
div.settings-main {
section {
padding: 0;
}
}
}
</style>

View file

@ -8,25 +8,25 @@
//toolbar
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
["bold", "italic", "underline", "strike"], // toggled buttons
["blockquote", "code-block"],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{ header: 1 }, { header: 2 }], // custom button values
[{ list: "ordered" }, { list: "bullet" }],
[{ script: "sub" }, { script: "super" }], // superscript/subscript
[{ indent: "-1" }, { indent: "+1" }], // outdent/indent
[{ direction: "rtl" }], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{ size: ["small", false, "large", "huge"] }], // custom dropdown
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
[{ font: [] }],
[{ align: [] }],
['clean'], // remove formatting button
["clean"], // remove formatting button
['link', 'image', 'video']
["link", "image", "video"],
];
const gameScene = gameManager.getCurrentGameScene();
@ -44,24 +44,24 @@
const textGlobalMessage: PlayGlobalMessageInterface = {
type: MESSAGE_TYPE,
content: text,
broadcastToWorld: broadcastToWorld
broadcastToWorld: broadcastToWorld,
};
quill.deleteText(0, quill.getLength());
gameScene.connection?.emitGlobalMessage(textGlobalMessage);
}
}
},
};
//Quill
onMount(async () => {
// Import quill
const {default: Quill} = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
const { default: Quill } = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
quill = new Quill(QUILL_EDITOR, {
placeholder: 'Enter your message here...',
theme: 'snow',
placeholder: "Enter your message here...",
theme: "snow",
modules: {
toolbar: toolbarOptions
toolbar: toolbarOptions,
},
});
menuInputFocusStore.set(true);
@ -69,14 +69,13 @@
onDestroy(() => {
menuInputFocusStore.set(false);
})
});
</script>
<section class="section-input-send-text">
<div class="input-send-text" bind:this={QUILL_EDITOR}></div>
<div class="input-send-text" bind:this={QUILL_EDITOR} />
</section>
<style lang="scss">
@import 'https://cdn.quilljs.com/1.3.7/quill.snow.css';
@import "https://cdn.quilljs.com/1.3.7/quill.snow.css";
</style>