Merge branch 'develop' of github.com:thecodingmachine/workadventure

This commit is contained in:
_Bastler 2021-09-09 08:25:41 +02:00
commit 52489f9c72
12 changed files with 206 additions and 52 deletions

133
docs/maps/menu.php Normal file
View File

@ -0,0 +1,133 @@
<?php
$extraMenu = require __DIR__.'/../../scripting_api_extra_doc/menu.php';
$extraUtilsMenu = require __DIR__.'/../../scripting_api_extra_doc/menu_functions.php';
return [
[
'title' => 'Getting started',
'url' => '/map-building',
'markdown' => 'maps.index'
],
[
'title' => 'WorkAdventure maps',
'url' => '/map-building/wa-maps',
'markdown' => 'maps.wa-maps'
],
[
'title' => 'Entries and exits',
'url' => '/map-building/entry-exit.md',
'markdown' => 'maps.entry-exit'
],
[
'title' => 'Opening a website',
'url' => '/map-building/opening-a-website.md',
'markdown' => 'maps.opening-a-website'
],
[
'title' => 'Meeting rooms',
'url' => '/map-building/meeting-rooms.md',
'markdown' => 'maps.meeting-rooms'
],
[
'title' => 'Special zones',
'url' => '/map-building/special-zones.md',
'markdown' => 'maps.special-zones'
],
[
'title' => 'Animations',
'url' => '/map-building/animations.md',
'markdown' => 'maps.animations'
],
[
'title' => 'Integrated websites',
'url' => '/map-building/website-in-map.md',
'markdown' => 'maps.website-in-map'
],
[
'title' => 'Variables',
'url' => '/map-building/variables.md',
'markdown' => 'maps.variables'
],
[
'title' => 'Self-hosting your map',
'url' => '/map-building/hosting.md',
'markdown' => 'maps.hosting'
],
$extraMenu,
[
'title' => 'Scripting maps',
'url' => '/map-building/scripting',
'markdown' => 'maps.scripting',
'children' => [
[
'title' => 'Using Typescript',
'url' => '/map-building/using-typescript.md',
'markdown' => 'maps.using-typescript'
],
[
'title' => 'API Reference',
'url' => '/map-building/api-reference',
'markdown' => 'maps.api-reference',
'collapse' => true,
'children' => [
[
'title' => 'Initialization',
'url' => '/map-building/api-start.md',
'markdown' => 'maps.api-start',
],
[
'title' => 'Navigation',
'url' => '/map-building/api-nav.md',
'markdown' => 'maps.api-nav',
],
[
'title' => 'Chat',
'url' => '/map-building/api-chat.md',
'markdown' => 'maps.api-chat',
],
[
'title' => 'Room',
'url' => '/map-building/api-room.md',
'markdown' => 'maps.api-room',
],
[
'title' => 'State',
'url' => '/map-building/api-state.md',
'markdown' => 'maps.api-state',
],
[
'title' => 'Player',
'url' => '/map-building/api-player.md',
'markdown' => 'maps.api-player',
],
[
'title' => 'UI',
'url' => '/map-building/api-ui.md',
'markdown' => 'maps.api-ui',
],
[
'title' => 'Sound',
'url' => '/map-building/api-sound.md',
'markdown' => 'maps.api-sound',
],
[
'title' => 'Controls',
'url' => '/map-building/api-controls.md',
'markdown' => 'maps.api-controls',
],
[
'title' => 'Deprecated',
'url' => '/map-building/api-deprecated.md',
'markdown' => 'maps.api-deprecated',
],
]
],
$extraUtilsMenu
]
],
[
'title' => 'Troubleshooting',
'url' => '/map-building/troubleshooting',
'view' => 'content.map.troubleshooting'
],
];

View File

@ -13,6 +13,7 @@ In order to create a zone that opens websites:
* You must create a specific layer. * You must create a specific layer.
* In layer properties, you MUST add a "`openWebsite`" property (of type "`string`"). The value of the property is the URL of the website to open (the URL must start with "https://") * In layer properties, you MUST add a "`openWebsite`" property (of type "`string`"). The value of the property is the URL of the website to open (the URL must start with "https://")
* You may also use "`openWebsiteWidth`" property (of type "`number`" between 0 and 100) to control the width of the iframe. * You may also use "`openWebsiteWidth`" property (of type "`number`" between 0 and 100) to control the width of the iframe.
* You may also use "`openTab`" property (of type "`string`") to open in a new tab instead.
{.alert.alert-warning} {.alert.alert-warning}
A website can explicitly forbid another website from loading it in an iFrame using A website can explicitly forbid another website from loading it in an iFrame using

View File

@ -22,3 +22,5 @@ RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule "^[_@]/" "/index.html" [L] RewriteRule "^[_@]/" "/index.html" [L]
RewriteRule "^register/" "/index.html" [L] RewriteRule "^register/" "/index.html" [L]
RewriteRule "^login" "/index.html" [L]
RewriteRule "^jwt/" "/index.html" [L]

View File

@ -7,7 +7,13 @@
import GlobalMessageSubMenu from "./GlobalMessagesSubMenu.svelte"; import GlobalMessageSubMenu from "./GlobalMessagesSubMenu.svelte";
import ContactSubMenu from "./ContactSubMenu.svelte"; import ContactSubMenu from "./ContactSubMenu.svelte";
import CustomSubMenu from "./CustomSubMenu.svelte" import CustomSubMenu from "./CustomSubMenu.svelte"
import {customMenuIframe, menuVisiblilityStore, SubMenusInterface, subMenusStore} from "../../Stores/MenuStore"; import {
checkSubMenuToShow,
customMenuIframe,
menuVisiblilityStore,
SubMenusInterface,
subMenusStore
} from "../../Stores/MenuStore";
import {onDestroy, onMount} from "svelte"; import {onDestroy, onMount} from "svelte";
import {get} from "svelte/store"; import {get} from "svelte/store";
import type {Unsubscriber} from "svelte/store"; import type {Unsubscriber} from "svelte/store";
@ -25,6 +31,8 @@
} }
}) })
checkSubMenuToShow();
switchMenu(SubMenusInterface.settings); switchMenu(SubMenusInterface.settings);
}) })
@ -95,6 +103,7 @@
</nav> </nav>
</div> </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> <h2>{activeSubMenu}</h2>
<svelte:component this={activeComponent} {...props}/> <svelte:component this={activeComponent} {...props}/>
</div> </div>
@ -110,9 +119,9 @@
font-family: "Press Start 2P"; font-family: "Press Start 2P";
pointer-events: auto; pointer-events: auto;
height: 80vh; height: 80%;
width: 75vw; width: 75%;
top: 10vh; top: 10%;
position: relative; position: relative;
margin: auto; margin: auto;
@ -139,16 +148,34 @@
div.menu-submenu-container { div.menu-submenu-container {
background-color: #333333; background-color: #333333;
color: whitesmoke; color: whitesmoke;
.nes-btn.is-error.close {
position: absolute;
top: -20px;
right: -20px;
}
} }
} }
@media only screen and (max-width: 800px) { @media only screen and (max-width: 800px) {
div.menu-container-main { div.menu-container-main {
--size-first-columns-grid: 120px; --size-first-columns-grid: 120px;
height: 70vh; height: 70%;
top: 55px; top: 55px;
width: 100vw; width: 100%;
font-size: 0.5em; 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> </style>

View File

@ -45,11 +45,6 @@
enableCameraSceneVisibilityStore.showEnableCameraScene(); enableCameraSceneVisibilityStore.showEnableCameraScene();
gameManager.leaveGame(EnableCameraSceneName, new EnableCameraScene()); gameManager.leaveGame(EnableCameraSceneName, new EnableCameraScene());
} }
//TODO: Uncomment when login will be completely developed
/*function clickLogin() {
connectionManager.loadOpenIDScreen();
}*/
</script> </script>
<div class="customize-main"> <div class="customize-main">
@ -64,19 +59,16 @@
</section> </section>
{:else} {:else}
<section> <section>
<a type="button" class="nes-btn" href="/login">Sing in</a> <a type="button" class="nes-btn" href="/login">Sign in</a>
</section> </section>
{/if} {/if}
<section> <section>
<button type="button" class="nes-btn is-rounded" on:click|preventDefault={openEditSkinScene}>Edit Skin</button> <button type="button" class="nes-btn" on:click|preventDefault={openEditSkinScene}>Edit Skin</button>
<button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>Edit Companion</button> <button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}>Edit Companion</button>
</section> </section>
<section> <section>
<button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>Setup camera</button> <button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}>Setup camera</button>
</section> </section>
<!-- <section>
<button type="button" class="nes-btn is-primary" on:click|preventDefault={clickLogin}>Login</button>
</section>-->
</div> </div>
<style lang="scss"> <style lang="scss">
@ -85,6 +77,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-wrap: wrap;
margin-bottom: 20px; margin-bottom: 20px;
iframe { iframe {

View File

@ -94,6 +94,7 @@ function changeNotification() {
<style lang="scss"> <style lang="scss">
div.settings-main { div.settings-main {
height: calc(100% - 40px); height: calc(100% - 40px);
overflow-y: auto;
section { section {
width: 100%; width: 100%;
@ -112,14 +113,14 @@ function changeNotification() {
} }
} }
section.settings-section-noSaveOption { section.settings-section-noSaveOption {
--nb-noSaveOptions: 2; //number of sub-element in the section display: flex;
display: grid; align-items: center;
grid-template-columns: calc(100% / var(--nb-noSaveOptions)) calc(100% / var(--nb-noSaveOptions)); //Same size for every sub-element flex-wrap: wrap;
label { label {
flex: 1 1 auto;
text-align: center; text-align: center;
width: 100%; margin: 0 0 15px;
margin: 0;
} }
} }
} }
@ -129,12 +130,6 @@ function changeNotification() {
section { section {
padding: 0; padding: 0;
} }
section.settings-section-noSaveOption {
height: 80px;
grid-template-columns: none;
grid-template-rows: calc(100% / var(--nb-noSaveOptions)) calc(100% / var(--nb-noSaveOptions)); //Same size for every sub-element;
}
} }
} }
</style> </style>

View File

@ -57,7 +57,7 @@ class ConnectionManager {
loginSceneVisibleIframeStore.set(false); loginSceneVisibleIframeStore.set(false);
return null; return null;
} }
const redirectUrl = `${this._currentRoom.iframeAuthentication}?state=${state}&nonce=${nonce}`; const redirectUrl = `${this._currentRoom.iframeAuthentication}?state=${state}&nonce=${nonce}&playUri=${this._currentRoom.key}`;
window.location.assign(redirectUrl); window.location.assign(redirectUrl);
return redirectUrl; return redirectUrl;
} }
@ -88,10 +88,9 @@ class ConnectionManager {
this.connexionType = connexionType; this.connexionType = connexionType;
this._currentRoom = null; this._currentRoom = null;
if (connexionType === GameConnexionTypes.login) { if (connexionType === GameConnexionTypes.login) {
//TODO clear all cash and redirect on login scene (iframe)
localUserStore.setAuthToken(null);
this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl())); this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl()));
urlManager.pushRoomIdToUrl(this._currentRoom); this.loadOpenIDScreen();
return Promise.reject(new Error("You will be redirect on login page"));
} else if (connexionType === GameConnexionTypes.jwt) { } else if (connexionType === GameConnexionTypes.jwt) {
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code"); const code = urlParams.get("code");
@ -103,13 +102,14 @@ class ConnectionManager {
throw "No Auth code provided"; throw "No Auth code provided";
} }
localUserStore.setCode(code); localUserStore.setCode(code);
this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl()));
try { try {
await this.checkAuthUserConnexion(); await this.checkAuthUserConnexion();
} catch (err) { } catch (err) {
console.error(err); console.error(err);
this.loadOpenIDScreen(); this.loadOpenIDScreen();
return Promise.reject(new Error("You will be redirect on login page"));
} }
this._currentRoom = await Room.createRoom(new URL(localUserStore.getLastRoomUrl()));
urlManager.pushRoomIdToUrl(this._currentRoom); urlManager.pushRoomIdToUrl(this._currentRoom);
} else if (connexionType === GameConnexionTypes.register) { } else if (connexionType === GameConnexionTypes.register) {
//@deprecated //@deprecated

View File

@ -71,7 +71,7 @@ function createSubMenusStore() {
export const subMenusStore = createSubMenusStore(); export const subMenusStore = createSubMenusStore();
function checkSubMenuToShow() { export function checkSubMenuToShow() {
if (!get(userIsAdminStore)) { if (!get(userIsAdminStore)) {
subMenusStore.removeMenu(SubMenusInterface.globalMessages); subMenusStore.removeMenu(SubMenusInterface.globalMessages);
} }
@ -83,8 +83,6 @@ function checkSubMenuToShow() {
subMenusStore.removeMenu(SubMenusInterface.aboutRoom); subMenusStore.removeMenu(SubMenusInterface.aboutRoom);
} }
checkSubMenuToShow();
export const customMenuIframe = new Map<string, { url: string; allowApi: boolean }>(); export const customMenuIframe = new Map<string, { url: string; allowApi: boolean }>();
export function handleMenuRegistrationEvent( export function handleMenuRegistrationEvent(

View File

@ -1,10 +1,10 @@
//TextGlobalMessage //TextGlobalMessage
section.section-input-send-text { section.section-input-send-text {
--height-toolbar: 15%; --height-toolbar: 20%;
height: 100%; height: 100%;
.ql-toolbar{ .ql-toolbar{
height: var(--height-toolbar); max-height: var(--height-toolbar);
background: whitesmoke; background: whitesmoke;
} }

View File

@ -1101,7 +1101,7 @@ div.is-silent {
border-radius: 15px 15px 15px 15px; border-radius: 15px 15px 15px 15px;
max-height: 20%; max-height: 20%;
transition: right 350ms; transition: right 350ms;
right: -20vw; right: -300px;
background-color: black; background-color: black;
font-size: 20px; font-size: 20px;
color: white; color: white;

View File

@ -27,13 +27,17 @@ export class AuthenticateController extends BaseController {
console.warn("/message request was aborted"); console.warn("/message request was aborted");
}); });
const { nonce, state } = parse(req.getQuery()); const { nonce, state, playUri } = parse(req.getQuery());
if (!state || !nonce) { if (!state || !nonce) {
res.writeStatus("400 Unauthorized").end("missing state and nonce URL parameters"); res.writeStatus("400 Unauthorized").end("missing state and nonce URL parameters");
return; return;
} }
try { try {
const loginUri = await openIDClient.authorizationUrl(state as string, nonce as string); const loginUri = await openIDClient.authorizationUrl(
state as string,
nonce as string,
playUri as string | undefined
);
res.writeStatus("302"); res.writeStatus("302");
res.writeHeader("Location", loginUri); res.writeHeader("Location", loginUri);
return res.end(); return res.end();

View File

@ -20,13 +20,14 @@ class OpenIDClient {
return this.issuerPromise; return this.issuerPromise;
} }
public authorizationUrl(state: string, nonce: string) { public authorizationUrl(state: string, nonce: string, playUri?: string) {
return this.initClient().then((client) => { return this.initClient().then((client) => {
return client.authorizationUrl({ return client.authorizationUrl({
scope: "openid email", scope: "openid email",
prompt: "login", prompt: "login",
state: state, state: state,
nonce: nonce, nonce: nonce,
playUri: playUri,
}); });
}); });
} }