Merge branch 'master' into luke

This commit is contained in:
LuckyLaszlo
2023-01-01 22:41:25 +01:00
48 changed files with 2505 additions and 1338 deletions

View File

@@ -0,0 +1,5 @@
<script context="module">
export const Domain = "transcendance";
export const Port = "8080";
export const PortIo = "8080";
</script>

View File

@@ -3,12 +3,13 @@
import { push } from "svelte-spa-router";
import { onMount } from 'svelte';
import { get } from "svelte/store";
import { Domain, Port } from "../Constantes.svelte";
let user;
onMount(async () => {
user = await fetch('http://transcendance:8080/api/v2/user')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then((resp) => resp.json())
// i mean i could do a failed to load user or some shit, maybe with a .catch or something? but atm why bother
@@ -32,14 +33,14 @@
});
const login = async() => {
window.location.href = 'http://transcendance:8080/api/v2/auth';
window.location.href = `http://${Domain}:${Port}/api/v2/auth`;
console.log('you are now logged in');
}
// i could prolly put this in it's own compoent, i seem to use it in several places... or maybe just some JS? like no need for html
// we could .then( () => replace('/') ) need the func so TS compatible...
const logout = async() => {
await fetch('http://transcendance:8080/api/v2/auth/logout', {
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, {
method: 'POST',
});
user = undefined;

View File

@@ -1,9 +1,10 @@
<script lang="ts">
import { onMount } from "svelte";
import { push } from "svelte-spa-router";
import { Domain, Port } from "../Constantes.svelte";
// onMount( async() => {
// await fetch("http://transcendance:8080/api/v2/auth/2fa/generate",
// await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`,
// {
// method: 'POST',
// })
@@ -19,7 +20,7 @@
let qrCode = "";
let wrongCode = "";
const fetchQrCodeImg = (async() => {
await fetch("http://transcendance:8080/api/v2/auth/2fa/generate",
await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`,
{
method: 'POST',
})
@@ -31,7 +32,7 @@
})()
const submitCode = async() => {
const response = await fetch("http://transcendance:8080/api/v2/auth/2fa/check",
const response = await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/check`,
{
method : 'POST',
headers : {

View File

@@ -3,6 +3,7 @@
import { onMount, onDestroy } from "svelte";
import Header from '../../pieces/Header.svelte';
import { fade, fly } from 'svelte/transition';
import { Domain, Port } from "../../Constantes.svelte";
import * as pong from "./client/pong";
import { gameState } from "./client/ws";
@@ -34,9 +35,9 @@
let idOfIntevalCheckTerminationOfTheMatch;
onMount( async() => {
user = await fetch('http://transcendance:8080/api/v2/user')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then( x => x.json() );
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
.then( x => x.json() );
options.playerOneUsername = user.username;
})
@@ -52,7 +53,7 @@
showWaitPage = true;
const matchOptions = pong.computeMatchOptions(options);
const responseWhenGrantToken = fetch("http://transcendance:8080/api/v2/game/ticket", {
const responseWhenGrantToken = fetch(`http://${Domain}:${Port}/api/v2/game/ticket`, {
method : "POST",
headers : {'Content-Type': 'application/json'},
body : JSON.stringify({
@@ -140,13 +141,13 @@
const showInvitation = async() => {
showGameOption = false;
showInvitations = true;
invitations = await fetch("http://transcendance:8080/api/v2/game/invitations")
invitations = await fetch(`http://${Domain}:${Port}/api/v2/game/invitations`)
.then(x => x.json())
invitations.length !== 0 ? isThereAnyInvitation = true : isThereAnyInvitation = false
}
const rejectInvitation = async(invitation) => {
await fetch("http://transcendance:8080/api/v2/game/decline",{
await fetch(`http://${Domain}:${Port}/api/v2/game/decline`, {
method: "POST",
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({
@@ -159,7 +160,7 @@
}
const acceptInvitation = async(invitation : any) => {
const res = await fetch("http://transcendance:8080/api/v2/game/accept",{
const res = await fetch(`http://${Domain}:${Port}/api/v2/game/accept`, {
method: "POST",
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({

View File

@@ -4,6 +4,7 @@
import Header from '../../pieces/Header.svelte';
import MatchListElem from "../../pieces/MatchListElem.svelte";
import { fade, fly } from 'svelte/transition';
import { Domain, Port } from "../../Constantes.svelte";
import * as pongSpectator from "./client/pongSpectator";
import { gameState } from "./client/ws";
@@ -48,9 +49,9 @@
let hiddenGame = true;
onMount( async() => {
user = await fetch('http://transcendance:8080/api/v2/user')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then( x => x.json() );
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
.then( x => x.json() );
// WIP: fetch for match list here
matchList = dummyMatchList;

View File

@@ -1,16 +1,17 @@
<script lang="ts">
import { onMount, onDestroy } from "svelte";
import Header from "../../pieces/Header.svelte";
import Header from "../../pieces/Header.svelte";
import { Domain, Port } from "../../Constantes.svelte";
//user's stuff
let currentUser;
let allUsers = [];
let idInterval;
onMount( async() => {
currentUser = await fetch('http://transcendance:8080/api/v2/user')
currentUser = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then( x => x.json() );
allUsers = await fetch('http://transcendance:8080/api/v2/game/ranking')
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/game/ranking`)
.then( x => x.json() );
idInterval = setInterval(fetchScores, 10000);
})
@@ -20,7 +21,7 @@
})
function fetchScores() {
fetch('http://transcendance:8080/api/v2/game/ranking')
fetch(`http://${Domain}:${Port}/api/v2/game/ranking`)
.then( x => x.json() )
.then( x => allUsers = x );
}

View File

@@ -1,21 +1,24 @@
<script lang="ts">
import { onMount } from 'svelte';
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
import { Domain, Port } from "../../Constantes.svelte";
import Chat from '../../pieces/chat/Chat.svelte';
let user;
onMount( async() => {
// console.log('mounting profile display')
user = await fetch('http://transcendance:8080/api/v2/user')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then( (x) => x.json() );
})
</script>
<Chat color="bisque"/>
<!-- is this if excessive? -->
<div class="outer">
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->

View File

@@ -1,7 +1,8 @@
<script lang="ts">
import { onMount } from "svelte";
import { binding_callbacks } from "svelte/internal";
import { binding_callbacks } from "svelte/internal";
import { Domain, Port } from "../../Constantes.svelte";
import Button from "../../pieces/Button.svelte";
import DisplayAUser from "../../pieces/DisplayAUser.svelte";
@@ -38,7 +39,7 @@ could be a list of friends and if they're active but i can't see that yet
onMount( async() => {
// yea no idea what
// i mean do i fetch user? i will for now
user = await fetch('http://transcendance:8080/api/v2/user')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then( (x) => x.json() );
// userBeingViewed = user;
@@ -46,26 +47,26 @@ could be a list of friends and if they're active but i can't see that yet
// console.log(user)
// console.log(user.username)
myFriends = await fetch("http://transcendance:8080/api/v2/network/myfriends")
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`)
.then( (x) => x.json() );
// console.log('my friends')
// console.log(myFriends)
requestsMade = await fetch('http://transcendance:8080/api/v2/network/pending')
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`)
.then( x => x.json() );
// console.log('Requests pending ');
// console.log(requestsMade);
requestsRecieved = await fetch('http://transcendance:8080/api/v2/network/received')
requestsRecieved = await fetch(`http://${Domain}:${Port}/api/v2/network/received`)
.then( x => x.json() );
// console.log('Requests received ');
// console.log(requestsRecieved);
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
.then( x => x.json() );
// console.log('got all users ' + allUsers)
@@ -74,20 +75,20 @@ could be a list of friends and if they're active but i can't see that yet
const displayAllUsers = async() => {
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`)
.then( x => x.json() );
// console.log('got all users ' + allUsers)
};
const displayAllFriends = async() => {
myFriends = await fetch('http://transcendance:8080/api/v2/network/myfriends')
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`)
.then( x => x.json() );
// console.log('got all friends ' + allFriends)
};
const displayRequestsMade = async() => {
requestsMade = await fetch('http://transcendance:8080/api/v2/network/pending')
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`)
.then( x => x.json() );
// console.log('got requests made ' + requestsMade)
};
@@ -106,7 +107,7 @@ could be a list of friends and if they're active but i can't see that yet
}
if (valid) {
sentFriendRequest = await fetch("http://transcendance:8080/api/v2/network/myfriends", {
sentFriendRequest = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`, {
method : "POST",
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({
@@ -124,7 +125,7 @@ could be a list of friends and if they're active but i can't see that yet
// sendUsername = userBeingViewed.username;
// prolly like fetch if you're friends or not?
// GET http://transcendance:8080/api/v2/networks/myfriends?username=aUser but i need to make that as long as Cherif
// GET `http://${Domain}:${Port}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif
// doesn't have a better option
// like i want this thing to return the Friendship ID ideally
};

View File

@@ -55,4 +55,4 @@
background-image: url('/img/wave-haikei.svg');
} */
</style>
</style>

View File

@@ -3,6 +3,7 @@
import Card from '../../pieces/Card.svelte';
import {onMount} from 'svelte';
import { push } from 'svelte-spa-router';
import { Domain, Port } from "../../Constantes.svelte";
import Button from '../../pieces/Button.svelte';
let user;
@@ -16,7 +17,7 @@
let success = {username: '', avatar: '' };
onMount( async() => {
user = await fetch('http://transcendance:8080/api/v2/user')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`)
.then( (x) => x.json() );
// do a .catch?
@@ -33,7 +34,7 @@
// console.log('this is what is in the avatar before fetch')
// console.log(avatar)
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
@@ -63,7 +64,7 @@
else {
errors.username = '';
}
await fetch('http://transcendance:8080/api/v2/user',{
await fetch(`http://${Domain}:${Port}/api/v2/user`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
@@ -100,7 +101,7 @@
// tmp
console.log(data);
await fetch("http://transcendance:8080/api/v2/user/avatar",
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`,
{
method : 'POST',
body : data,
@@ -108,7 +109,7 @@
.then(() => uploadAvatarSuccess = true ) // for some reason it needs to be a function, i think a TS thing, not a promis otherwise
.then(() => success.avatar = 'Your changes have been saved')
.catch(() => errors.avatar = 'Sorry failed to upload your new Avatar' );
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);

View File

@@ -45,4 +45,4 @@
background: white;
border: 2px solid #45c496;
}
</style>
</style>

View File

@@ -2,6 +2,7 @@
import { onMount } from 'svelte';
import GenerateUserDisplay from './GenerateUserDisplay.svelte';
import { Domain, Port } from "../Constantes.svelte";
// import {updateGeneratedUser} from './GenerateUserDisplay.svelte';
export let aUsername;
@@ -9,8 +10,8 @@
onMount( async() => {
console.log('Display aUser username: '+ aUsername)
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() );
// console.log('Display a user: ')
@@ -26,15 +27,15 @@
const updateUser = async(updatedUser) => {
console.log('Display Update aUser username: '+ updateUser)
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
user = await fetch(`http://transcendance:8080/api/v2/user?username=${updateUser}`)
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`)
.then( (x) => x.json() );
};
// export const updateUser = async(updatedUser) => {
// console.log('Display Update aUser username: '+ updateUser)
// // http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
// user = await fetch(`http://transcendance:8080/api/v2/user?username=${updateUser}`)
// //`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve`
// user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`)
// .then( (x) => x.json() );
// updateGeneratedUser(updateUser);
@@ -56,4 +57,4 @@
<style>
</style>
</style>

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import { Domain, Port } from "../Constantes.svelte";
export let user;
export let primary;
@@ -11,7 +12,7 @@
onMount( async() => {
// using this for now cuz for some reason there is yet to be a way to fet another person's avatar
if (primary) {
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
@@ -253,4 +254,4 @@
white-space: nowrap;
}
</style>
</style>

View File

@@ -1,13 +1,14 @@
<script lang="ts">
import { push } from "svelte-spa-router";
import { location } from 'svelte-spa-router';
import { Domain, Port } from "../Constantes.svelte";
import active from 'svelte-spa-router/active'
// or i could leave them all and not display if they're active?
let handleClickLogout = async () => {
await fetch('http://transcendance:8080/api/v2/auth/logout', {
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, {
method: 'POST',
})
// .then(resp => resp.json)

View File

@@ -0,0 +1,59 @@
<script lang="ts">
import Layouts from './Chat_layouts.svelte';
import { Domain, PortIo } from "../../Constantes.svelte";
export let color = "transparent";
/* web sockets with socket.io
*/
import { onMount } from 'svelte';
import io from 'socket.io-client';
const socket = io(`http://${Domain}:${PortIo}`, {
path: '/chat'
});
onMount(async => {
socket.on('connect', function(){
console.log("socket.io connected");
});
socket.on('disconnect', function(){
console.log("socket.io disconnected");
});
socket.on('connect_error', function(){
console.log("socket.io connect_error");
});
socket.on('connect_timeout', function(){
console.log("socket.io connect_timeout");
});
socket.on('error', function(){
console.log("socket.io error");
});
socket.on('reconnect', function(){
console.log("socket.io reconnect");
});
socket.on('reconnect_attempt', function(){
console.log("socket.io reconnect_attempt");
});
socket.on('reconnecting', function(){
console.log("socket.io reconnecting");
});
socket.on('reconnect_error', function(){
console.log("socket.io reconnect_error");
});
socket.on('reconnect_failed', function(){
console.log("socket.io reconnect_failed");
});
socket.on('ping', function(){
console.log("socket.io ping");
});
socket.on('pong', function(){
console.log("socket.io pong");
});
});
</script>
<Layouts color={color} />
<style></style>

View File

@@ -0,0 +1,133 @@
<script lang="ts">
export let color;
export let layout;
</script>
<div class="{layout} chat_box" style="background-color: {color};">
<slot></slot>
</div>
<style>
/* chat_box and default style
*/
.chat_box {
display: flex;
position: fixed;
bottom: 20px;
right: 20px;
padding: 0px;
width: auto;
height: auto;
border: 1px solid black;
z-index: 1;
}
/* * * * * * * * * * * * * * * * * * * * *
GLOBAL STYLES
*/
/* Hide scrollbar
*/
.chat_box :global(*) {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.chat_box :global(*::-webkit-scrollbar) {
display: none; /* Chrome, Safari and Opera */
}
/* for grid_box and all childrens
*/
.chat_box :global(.grid_box) {
display: grid;
margin: 5px;
gap: 5px;
width: 300px;
height: 400px;
}
.chat_box :global(.grid_box *) {
display: flex;
flex-direction: column;
position: relative;
box-sizing: border-box;
}
/* all p
*/
.chat_box :global(.grid_box p) {
padding: 10px;
font-size: 15px;
}
/* all panel
*/
.chat_box :global(.panel) {
overflow-y: scroll;
}
.chat_box :global(.panel > *) {
margin-top: 10px;
margin-bottom: 10px;
}
/* * * * * * * * * * * * * * * * * * * * *
GLOBAL UTILITIES
*/
/* __show_if_only_child
*/
.chat_box :global(.__show_if_only_child) {
display: none;
}
.chat_box :global(.__show_if_only_child:only-child) {
display: flex;
color: rgb(100, 100, 100);
}
/* __center
*/
.chat_box :global(.__center) {
margin-left: auto;
margin-right: auto;
}
/* __border_top
*/
.chat_box :global(.__border_top) {
border-top: 1px solid black;
}
/* __check_change_next
*/
.chat_box :global(.__check_change_next:checked ~ .__to_show) {
display: flex;
}
.chat_box :global(.__check_change_next:checked ~ .__to_block),
.chat_box :global(.__check_change_next:checked ~ .__to_block *) {
pointer-events: none;
color: rgb(100, 100, 100);
}
.chat_box :global(.__to_show) {
display: none;
}
</style>

View File

@@ -0,0 +1,188 @@
<!--
<Button
bind:layout
new_layout=""
on_click={}
my_class=""
my_title=""
>
value
</Button>
-->
<script lang="ts">
export let my_class = "";
export let my_title = "";
export let layout = "";
export let new_layout = "";
export let on_click = "";
function update_layout() {
layout = new_layout;
}
</script>
<button on:click={update_layout} on:click={on_click} title={my_title} class={my_class}>
<p><slot></slot></p>
</button>
<style>
/*
- default config
- for btn list
- for transparent btn
- for deactivated btn
- for icon
- for 3 dots btn
- for close btn
- for back btn
*/
/* default config
*/
button {
padding: 0px;
margin: auto;
width: 100%;
cursor: pointer;
outline: none;
border: none;
background-color: rgb(220, 220, 220);
}
button p {
width: 100%;
margin: auto;
text-align: center;
}
button:hover {
background-color: rgb(200, 200, 200);
}
button:active {
background-color: rgb(190, 190, 190);
}
/* for btn list
*/
.list:not(:hover) {
background-color: rgb(240, 240, 240);
}
.list p {
text-align: left;
}
/* for transparent btn
*/
.transparent:not(:hover) {
background-color: transparent;
}
/* for deactivated btn
*/
.deactivate {
background-color: transparent;
pointer-events: none;
}
/* for icon
*/
.icon p {
display: none;
}
.icon:not(:hover) {
background-color: transparent;
}
.icon {
width: 30px;
height: 100%;
padding: 0px;
}
/* for 3 dots btn
*/
.dots::after {
content: '\2807';
font-size: 20px;
position: absolute;
top: 50%;
left: 0px;
width: 100%;
height: auto;
text-align: center;
transform: translateY(-50%);
cursor: pointer;
}
/* for close btn
*/
.close::before {
content: "";
position: absolute;
top: calc(50% - 1px);
left: 5px;
width: 20px;
height: 2px;
background-color: black;
}
/* for back btn
*/
.back::before {
content: "";
position: absolute;
top: calc(50% - 6px - 1px);
left: 6px;
width: 14px;
height: 14px;
border-left: 1px solid black;
border-bottom: 1px solid black;
transform: rotate(45deg);
}
/* for blocked user
https://www.fileformat.info/info/unicode/category/So/list.htm
U+1F512 LOCK 🔒
U+1F513 OPEN LOCK 🔓
*/
.blocked {
padding-left: 30px;
}
.blocked::before {
content: "";
position: absolute;
top: calc(50% - 2px);
left: 10px;
cursor: pointer;
width: 13px;
height: 10px;
border-radius: 2px;
background-color: rgb(110, 110, 110);
}
.blocked::after {
content: "";
position: absolute;
top: calc(50% - 9px);
left: 12px;
cursor: pointer;
width: 9px;
height: 13px;
border-radius: 5px;
box-sizing: border-box;
border: 3px solid rgb(110, 110, 110);
}
</style>

View File

@@ -0,0 +1,86 @@
<script lang="ts">
import Debug from './tmp_debug.svelte';
import ChatBox from './Chat_box_css.svelte';
import CloseLayout from './Layout_close.svelte';
import HomeLayout from './Layout_home.svelte';
import RoomLayout from './Layout_room.svelte';
import NewLayout from './Layout_new.svelte';
import SettingsLayout from './Layout_settings.svelte';
import RoomsetLayout from './Layout_room_set.svelte';
import ProtectedLayout from './Layout_protected.svelte';
import CreateLayout from './Layout_create.svelte';
import MuteLayout from './Layout_mute.svelte';
import UserLayout from './Layout_user.svelte';
import Button from './Chat_button.svelte';
/* global variables
*/
export let color;
let room = "";
let admin = false;
let layout = "close";
let layouts = ["home", "home"];
/* hold previous version of layout, to go back
*/
function set_layouts(layout)
{
if (layout === "close")
return;
if (layout === layouts[0])
return;
if (layout === layouts[1])
layouts = [layout, "home"];
else
layouts = [layout, layouts[0]];
}
$: set_layouts(layout);
</script>
<ChatBox layout={layout} color={color}>
{#if layout === "home"}
<HomeLayout bind:layout />
{:else if layout === "close"}
<CloseLayout bind:layout />
{:else if layout === "room"}
<RoomLayout bind:layout back={layouts[1]} />
{:else if layout === "new"}
<NewLayout bind:layout back={layouts[1]} />
{:else if layout === "settings"}
<SettingsLayout bind:layout back={layouts[1]} />
{:else if layout === "room_set"}
<RoomsetLayout bind:layout back={layouts[1]} />
{:else if layout === "protected"}
<ProtectedLayout bind:layout back={layouts[1]} />
{:else if layout === "create"}
<CreateLayout bind:layout back={layouts[1]} />
{:else if layout === "mute"}
<MuteLayout bind:layout back={layouts[1]} />
{:else if layout === "user"}
<UserLayout bind:layout back={layouts[1]} />
{/if}
</ChatBox>
<!-- TMP DEBUG -->
<Debug bind:layout bind:layouts />
<style></style>

View File

@@ -0,0 +1,67 @@
<script>
export let name;
</script>
<div class="chat_msg {name}">
<p class="name">{name}</p>
<p class="msg"><slot></slot></p>
</div>
<style>
.chat_msg {
/*
white-space: pre-wrap;
*/
margin: 5px auto;
padding: 5px;
border-radius: 5px;
}
/* all msg
*/
.chat_msg {
margin-left: 0px;
background-color: rgb(210, 210, 210);
max-width: 80%;
}
.chat_msg p {
padding: 0px;
}
.chat_msg p.name {
margin: 0px;
font-size: 12px;
color: rgb(100, 100, 100);
}
.chat_msg p.msg {
margin: 5px 0px;
}
.chat_msg p.msg :global(*) {
display: inline;
}
/* msg perso
*/
.chat_msg.me {
margin-right: 0px;
margin-left: auto;
background-color: rgb(210, 110, 10);
}
.chat_msg.me p.name {
display: none;
}
/* msg server
*/
.chat_msg.SERVER {
margin-left: auto;
background-color: transparent;
}
.chat_msg.SERVER p.name {
display: none;
}
.chat_msg.SERVER p.msg {
margin: 0px auto;
font-size: 12px;
color: rgb(100, 100, 100);
}
</style>

View File

@@ -0,0 +1,137 @@
<script>
import Button from './Chat_button.svelte';
export let layout;
</script>
<div class="grid_box">
<Button bind:layout new_layout="home" my_class="chat">
chat
</Button>
</div>
<style>
/* layout "close"
*/
.grid_box :global(.chat) {grid-area: chat;}
.grid_box {
gap: 0px;
grid:
' chat ' auto
/ auto ;
}
:global(.chat_box.close) .grid_box {
margin: 0px;
width: auto;
height: auto;
}
/* * * * * * * * * * * * * * * * * * * * *
GLOBAL STYLES
*/
/* Hide scrollbar
*/
.chat_box :global(*) {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.chat_box :global(*::-webkit-scrollbar) {
display: none; /* Chrome, Safari and Opera */
}
/* for grid_box and all childrens
*/
.chat_box :global(.grid_box) {
display: grid;
margin: 0px;
gap: 5px;
width: 100%;
height: 100%;
}
.chat_box :global(.grid_box *) {
display: flex;
flex-direction: column;
position: relative;
box-sizing: border-box;
}
/* all p
*/
.chat_box :global(.grid_box p) {
padding: 10px;
font-size: 15px;
}
/* all panel
*/
.chat_box :global(.panel) {
overflow-y: scroll;
}
.chat_box :global(.panel > *) {
margin-top: 10px;
margin-bottom: 10px;
}
/* * * * * * * * * * * * * * * * * * * * *
GLOBAL UTILITIES
*/
/* __show_if_only_child
*/
.chat_box :global(.__show_if_only_child) {
display: none;
}
.chat_box :global(.__show_if_only_child:only-child) {
display: flex;
color: rgb(100, 100, 100);
}
/* __center
*/
.chat_box :global(.__center) {
margin-left: auto;
margin-right: auto;
}
/* __border_top
*/
.chat_box :global(.__border_top) {
border-top: 1px solid black;
}
/* __check_change_next
*/
.chat_box :global(.__check_change_next:checked ~ .__to_show) {
display: flex;
}
.chat_box :global(.__check_change_next:checked ~ .__to_block),
.chat_box :global(.__check_change_next:checked ~ .__to_block *) {
pointer-events: none;
color: rgb(100, 100, 100);
}
.chat_box :global(.__to_show) {
display: none;
}
</style>

View File

@@ -0,0 +1,113 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- create -->
<Button my_class="create deactivate">
create
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel_create -->
<div class="panel panel_create">
<form>
<!-- name: -->
<label for="chat_name"><p>new room name :</p></label>
<input id="chat_name" required>
<!-- [ ] pubic -->
<input id="chat_public" type="radio" name="chat_create_type" checked>
<label for="chat_public" class="_radio"><p>public</p></label>
<!-- [ ] private -->
<input id="chat_private" type="radio" name="chat_create_type">
<label for="chat_private" class="_radio"><p>private</p></label>
<!-- [ ] protected -->
<input id="chat_protected" class="__check_change_next" type="radio" name="chat_create_type">
<label for="chat_protected" class="_radio"><p>protected</p></label>
<!-- [x] protected -->
<div class="__to_show">
<label for="chat_pswd"><p>choose a password :</p></label>
<input id="chat_pswd" type="password" placeholder="minimum 8 characters" minlength="8">
<p>confirm password :</p>
<input type="password">
</div>
<input type="submit" value="&#x2BA1">
</form>
</div>
</div>
<style>
/* grid layout "create"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.create ) {grid-area: create;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_create) {grid-area: panel_create;}
.grid_box {
grid:
' back create close ' auto
' panel_create panel_create panel_create ' 1fr
/ auto 1fr auto ;
}
/* radio elements style check
*/
form input[type=radio] {
display: none;
}
form label._radio {
margin: 0px 20px 0px auto;
padding-right: 10px;
cursor: pointer;
}
form label._radio p {
margin-top: 0px;
margin-bottom: 0px;
}
form label._radio::after {
content: "";
position: absolute;
top: calc(50% - 6px);
right: 0px;
width: 12px;
height: 12px;
border-radius: 6px;
border: 2px solid rgb(150, 150, 150);
box-sizing: border-box;
cursor: pointer;
}
form input[type=radio]:checked
+ label._radio::after {
background-color: rgb(200, 200, 200);
}
/* submit
*/
form input[type=submit] {
margin-top: 20px;
}
</style>

View File

@@ -0,0 +1,73 @@
<script>
import Button from './Chat_button.svelte';
export let layout;
</script>
<div class="grid_box">
<!-- settings -->
<Button bind:layout new_layout="settings" my_class="settings dots icon">
settings
</Button>
<!-- new -->
<Button bind:layout new_layout="new" my_class="new transparent">
new
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel home -->
<div class="panel panel_home __border_top">
<p class="title">list of your rooms :</p>
<div class="room_list">
<div class="__show_if_only_child">
<p class="__center">/ you have no chat room yet /</p>
</div>
<!-- placeholders
<Button bind:layout new_layout="room" my_class="list">
a room
</Button>
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
placeholder
</Button>
------------- -->
<!-- END placeholders -->
</div>
</div>
</div>
<style>
/* grid layout "home"
*/
.grid_box :global(.settings ) {grid-area: settings;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.new ) {grid-area: new;}
.grid_box :global(.panel_home) {grid-area: panel_home;}
.grid_box {
grid:
' settings new close ' auto
' panel_home panel_home panel_home ' 1fr
/ auto 1fr auto ;
}
/* panel home
*/
.panel_home p.title {
margin: 10px auto 0px auto;
}
</style>

View File

@@ -0,0 +1,261 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- user -->
<Button my_class="user deactivate">
&lt;user&gt;
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel_mute -->
<!-- MUTE -->
<div class="panel panel_mute __border_top">
<p class="__center">mute this user for a time :</p>
<form>
<!-- forever -->
<input id="chat_mute_forever" class="__check_change_next" type="checkbox">
<label for="chat_mute_forever" class="_checkbox"><p>forever</p></label>
<div class="__to_block">
<!-- minutes -->
<label for="chat_mute_minutes" class="_select">
<p>minutes :</p>
<select id="chat_mute_minutes">
<option value="01">00</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="30">30</option>
<option value="31">31</option>
<option value="32">32</option>
<option value="33">33</option>
<option value="34">34</option>
<option value="35">35</option>
<option value="36">36</option>
<option value="37">37</option>
<option value="40">40</option>
<option value="41">41</option>
<option value="42">42</option>
<option value="43">43</option>
<option value="44">44</option>
<option value="45">45</option>
<option value="46">46</option>
<option value="47">47</option>
<option value="50">50</option>
<option value="51">51</option>
<option value="52">52</option>
<option value="53">53</option>
<option value="54">54</option>
<option value="55">55</option>
<option value="56">56</option>
<option value="57">57</option>
<option value="60">60</option>
</select>
</label>
<!-- hours -->
<label for="chat_mute_hours" class="_select">
<p>hours :</p>
<select id="chat_mute_hours">
<option value="01">00</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="30">30</option>
<option value="31">31</option>
<option value="32">32</option>
<option value="33">33</option>
<option value="34">34</option>
<option value="35">35</option>
<option value="36">36</option>
<option value="37">37</option>
<option value="40">40</option>
<option value="41">41</option>
<option value="42">42</option>
<option value="43">43</option>
<option value="44">44</option>
<option value="45">45</option>
<option value="46">46</option>
<option value="47">47</option>
<option value="50">50</option>
<option value="51">51</option>
<option value="52">52</option>
<option value="53">53</option>
<option value="54">54</option>
<option value="55">55</option>
<option value="56">56</option>
<option value="57">57</option>
<option value="60">60</option>
</select>
</label>
<!-- days -->
<label for="chat_mute_days" class="_select">
<p>days :</p>
<select id="chat_mute_days">
<option value="00">00</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</label>
</div>
<input type="submit" value="&#x2BA1">
</form>
</div>
</div>
<style>
/* grid layout "mute"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.user ) {grid-area: user;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_mute) {grid-area: panel_mute;}
.grid_box {
grid:
' back user close ' auto
' panel_mute panel_mute panel_mute ' 1fr
/ auto 1fr auto ;
}
/* checkbox
*/
form input[type=checkbox] {
display: none;
}
form label._checkbox {
margin: 0px auto 0px 10px;
padding-left: 10px;
cursor: pointer;
}
form label._checkbox::after {
content: "";
position: absolute;
top: calc(50% - 6px);
left: 0px;
width: 12px;
height: 12px;
border: 2px solid rgb(150, 150, 150);
box-sizing: border-box;
cursor: pointer;
}
form input[type=checkbox]:checked
+ label._checkbox::after {
background-color: rgb(200, 200, 200);
}
/* select
*/
form label._select {
flex-direction: row;
}
form label._select p {
margin: 0px;
}
form select {
margin: auto auto auto 10px;
background-color: rgb(220, 220, 220);
border: none;
padding: 5px;
cursor: pointer;
}
form select:hover {
background-color: rgb(200, 200, 200);
}
/* submit
*/
form input[type=submit] {
margin-top: 20px;
}
</style>

View File

@@ -0,0 +1,89 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- new -->
<Button my_class="new deactivate">
new
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel_new -->
<div class="panel panel_new __border_top">
<Button bind:layout new_layout="create" my_class="create">
create
</Button>
<p>join room :</p>
<div class="public_rooms">
<div class="__show_if_only_child">
<p class="__center">/ there are no public rooms yet /</p>
</div>
<!-- placeholders
<Button bind:layout new_layout="room" my_class="list">
placeholder
</Button>
<Button bind:layout new_layout="room" my_class="list">
join room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one room
</Button>
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one room
</Button>
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one room
</Button>
<Button bind:layout new_layout="room" my_class="list">
another room
</Button>
<Button bind:layout new_layout="room" my_class="list">
one more room
</Button>
------------- -->
<!-- END placeholders -->
</div>
</div>
</div>
<style>
/* grid layout "new"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.new ) {grid-area: new;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_new) {grid-area: panel_new;}
.grid_box {
grid:
' back new close ' auto
' panel_new panel_new panel_new ' 1fr
/ auto 1fr auto ;
}
</style>

View File

@@ -0,0 +1,65 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- room_name -->
<Button my_class="room_name deactivate">
&lt;room_name&gt;
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel_protected -->
<div class="panel panel_protected __border_top">
<p class="title __center">this room is protected</p>
<form>
<label for="chat_pswd"><p>password :</p></label>
<input id="chat_pswd" type="password" required>
<input type="submit" value="&#x2BA1">
</form>
</div>
</div>
<style>
/* grid layout "protected"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.room_name ) {grid-area: room_name;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_protected) {grid-area: panel_protected;}
.grid_box {
grid:
' back room_name close ' auto
' panel_protected panel_protected panel_protected ' 1fr
/ auto 1fr auto ;
}
/* submit
*/
form input[type=submit] {
margin-top: 20px;
}
</style>

View File

@@ -0,0 +1,149 @@
<script>
import Button from './Chat_button.svelte';
import Msg from './Chat_msg.svelte';
import io from 'socket.io-client';
export let layout = "";
export let back = "";
let msg = "";
let text_area;
let msgs = [];
function add_msg(from, the_msg)
{
msgs = [...msgs, { content: the_msg, name: from }];
}
function send_msg()
{
msg = msg.trim();
if (msg.length > 0) {
//socket.emit('sendmsg', msg);
add_msg("me", msg);
}
msg = "";
text_area.focus();
}
function send_msg_if(evt)
{
if (evt.shiftKey && evt.key === "Enter")
{
evt.preventDefault();
send_msg();
}
}
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- room_name -->
<Button bind:layout new_layout="room_set" my_class="room_name transparent">
&lt;room_name&gt;
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- msg -->
<div class="panel panel_msg">
<div class="msg_thread">
{#each msgs as msg}
<Msg name={msg.name}>{@html msg.content}</Msg>
{/each}
</div>
</div>
<!-- write -->
<div class="panel_write">
<div
class="text_area"
bind:innerHTML={msg}
bind:this={text_area}
on:keypress={send_msg_if}
contenteditable="true"
></div>
</div>
<!-- send -->
<Button my_class="send" on_click={send_msg}>
send
</Button>
</div>
<style>
/* grid layout "room"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.room_name ) {grid-area: room_name;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_msg ) {grid-area: panel_msg;}
.grid_box :global(.send ) {grid-area: send;}
.grid_box :global(.panel_write) {grid-area: panel_write;}
.grid_box {
grid:
' back room_name room_name close ' auto
' panel_msg panel_msg panel_msg panel_msg ' 1fr
' panel_write panel_write send send ' auto
/ auto 1fr auto auto ;
}
/* write area
*/
.grid_box .panel_write {
border: none;
overflow: visible;
}
.grid_box .text_area {
display: block;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
background-color: white;
border: 1px solid black;
}
.grid_box .text_area:focus {
height: auto;
min-height: 100%;
max-height: 300px;
}
.grid_box .panel_write .text_area :global(*) {
display: block ruby;
}
/* msg area
*/
.grid_box .panel_msg {
flex-direction: column-reverse;
border: 1px solid black;
}
.grid_box .msg_thread {
width: 100%;
padding: 0px 5px;
}
</style>

View File

@@ -0,0 +1,76 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- room_name -->
<Button my_class="room_name deactivate">
&lt;room_name&gt;
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel_room_set -->
<div class="panel panel_room_set __border_top">
<Button bind:layout new_layout="create" my_class="create">
leave
</Button>
<p>room users :</p>
<div class="room_users">
<div class="__show_if_only_child">
<p class="__center">/ there are no public rooms yet /</p>
</div>
<!-- placeholders
------------- -->
<Button bind:layout new_layout="user" my_class="list">
user 1
</Button>
<Button bind:layout new_layout="user" my_class="list blocked">
user 2
</Button>
<Button bind:layout new_layout="user" my_class="list">
user 3
</Button>
<Button bind:layout new_layout="user" my_class="list">
user 4
</Button>
<!-- END placeholders -->
</div>
</div>
</div>
<style>
/* grid layout "room_set"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.room_name ) {grid-area: room_name;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_room_set) {grid-area: panel_room_set;}
.grid_box {
grid:
' back room_name close ' auto
' panel_room_set panel_room_set panel_room_set ' 1fr
/ auto 1fr auto ;
}
</style>

View File

@@ -0,0 +1,72 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- settings -->
<Button my_class="room_name deactivate">
settings
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- panel_settings -->
<div class="panel panel_settings __border_top">
<p>blocked users :</p>
<div class="blocked_users">
<div class="__show_if_only_child">
<p class="__center">/ you have blocked no one /</p>
</div>
<!-- placeholders
<Button bind:layout new_layout="user" my_class="list blocked">
user 1
</Button>
<Button bind:layout new_layout="user" my_class="list blocked">
user 2
</Button>
<Button bind:layout new_layout="user" my_class="list blocked">
user 3
</Button>
<Button bind:layout new_layout="user" my_class="list blocked">
user 4
</Button>
------------- -->
<!-- END placeholders -->
</div>
</div>
</div>
<style>
/* grid layout "settings"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.settings ) {grid-area: settings;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.panel_settings) {grid-area: panel_settings;}
.grid_box {
grid:
' back settings close ' auto
' panel_settings panel_settings panel_settings ' 1fr
/ auto 1fr auto ;
}
</style>

View File

@@ -0,0 +1,91 @@
<script>
import Button from './Chat_button.svelte';
export let layout = "";
export let back = "";
let mute = "mute";
let block = "block";
</script>
<div class="grid_box">
<!-- back -->
<Button bind:layout new_layout={back} my_class="back icon" my_title="go back {back}">
back
</Button>
<!-- user -->
<Button my_class="user deactivate">
&lt;user&gt;
</Button>
<!-- close -->
<Button bind:layout new_layout="close" my_class="close icon">
close
</Button>
<!-- room_name -->
{#if back === "room_set"}
<Button my_class="room_name deactivate __border_top">
&lt;room_name&gt;
</Button>
{/if}
<!-- panel_user -->
<div class="panel panel_user __border_top">
<p class="__center">user options :</p>
<Button>
view profile
</Button>
<Button>
game invitation
</Button>
<Button>
{block}
</Button>
{#if back === "room_set"}
<Button>
make admin
</Button>
<Button>
{mute}
</Button>
{/if}
</div>
</div>
<style>
/* grid layout "user"
*/
.grid_box :global(.back ) {grid-area: back;}
.grid_box :global(.user ) {grid-area: user;}
.grid_box :global(.close ) {grid-area: close;}
.grid_box :global(.room_name ) {grid-area: room_name;}
.grid_box :global(.panel_user) {grid-area: panel_user;}
.grid_box {
grid:
' back user close ' auto
' room_name room_name room_name ' auto
' panel_user panel_user panel_user ' 1fr
/ auto 1fr auto ;
}
/* for line height
*/
.panel_user {
margin-top: -5px;
}
</style>

View File

@@ -0,0 +1,27 @@
<script>
export let layout = "";
export let layouts = [];
</script>
<div style="display: flex; flex-direction: column; font-size: 12px; position: fixed; top: 20px; left: 20px; background-color: white;">
<p>temp, for testing :</p>
<button on:click={function(){layout = "close" }}>close</button>
<button on:click={function(){layout = "home" }}>home</button>
<button on:click={function(){layout = "room" }}>room</button>
<button on:click={function(){layout = "new" }}>new</button>
<button on:click={function(){layout = "settings" }}>settings</button>
<button on:click={function(){layout = "room_set" }}>room_set</button>
<button on:click={function(){layout = "protected"}}>protected</button>
<button on:click={function(){layout = "create" }}>create</button>
<button on:click={function(){layout = "mute" }}>mute</button>
<button on:click={function(){
layouts = ["settings", "settings"];
layout = "user";
}}>user from settings</button>
<button on:click={function(){
layouts = ["room_set", "room_set"];
layout = "user";
}}>user from room_set</button>
</div>