merged
This commit is contained in:
@@ -1,10 +1,26 @@
|
||||
<script>
|
||||
import { link } from "svelte-spa-router";
|
||||
import Header from '../pieces/Header.svelte';
|
||||
</script>
|
||||
|
||||
<h1>We are sorry!</h1>
|
||||
<p>This isn't a url that we use.</p>
|
||||
<p>Go home you're drunk.</p>
|
||||
<a href="/" use:link>
|
||||
<h2>Take me home →</h2>
|
||||
</a>
|
||||
|
||||
<div class="background-pages">
|
||||
<div class="content">
|
||||
<h1>We are sorry!</h1>
|
||||
<p>This isn't a url that we use.</p>
|
||||
<p>Go home you're drunk.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
.content {
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -9,22 +9,8 @@
|
||||
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_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
|
||||
|
||||
console.log('User var');
|
||||
console.log(user);
|
||||
// if (user && user.statusCode && user.statusCode === 403) {
|
||||
// console.log('user not logged in')
|
||||
// }
|
||||
// if (user && user.username) {
|
||||
// console.log('we have a user');
|
||||
// }
|
||||
|
||||
// user === undefined doesn't work cuz we declared user in the scope of onMount
|
||||
// if (user === undefined) {
|
||||
if (user && user.statusCode && user.statusCode === 403) {
|
||||
console.log('on mount no user, returned status code 403 so logging out of userStore')
|
||||
// userLogout(); // which i think should delete any previous local storage
|
||||
}
|
||||
|
||||
});
|
||||
@@ -34,8 +20,6 @@
|
||||
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://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
|
||||
method: 'POST',
|
||||
@@ -46,108 +30,71 @@
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<header class="grid-container">
|
||||
<h1>Potato Pong</h1>
|
||||
<nav>
|
||||
<!-- {#if user !== undefined} -->
|
||||
{#if user && user.username}
|
||||
<div on:click={ () => (push('/profile')) }>Profile</div>
|
||||
<div on:click={logout}>Logout</div>
|
||||
{:else}
|
||||
<div on:click={login}>Login</div>
|
||||
{/if}
|
||||
</nav>
|
||||
<h2>
|
||||
<div>Welcome to</div>
|
||||
<div>Potato Pong</div>
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<Canvas/>
|
||||
|
||||
<!-- doesn't work :( -->
|
||||
<!-- <svelte:body style="overflow-y: hidden"/> -->
|
||||
<div class="container">
|
||||
<div class="splash-page">
|
||||
{#if user && user.username}
|
||||
<button class="button-in" on:click={ () => (push('/profile')) }>Profile</button>
|
||||
<button class="button-out" on:click={logout}>Logout</button>
|
||||
{:else}
|
||||
<button class="button-in" on:click={login}>Login</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Bit5x3";
|
||||
src:
|
||||
url("/fonts/Bit5x3.woff2") format("woff2"),
|
||||
local("Bit5x3"),
|
||||
url("/fonts/Bit5x3.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* :global(body) {
|
||||
overflow-y: hidden;
|
||||
} */
|
||||
|
||||
header {
|
||||
/* didn't work... */
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background-image: url('/img/SPLASH_PAGE_BACKGROUND.png');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
||||
/* The actually important stuff */
|
||||
.splash-page {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 80%;
|
||||
-ms-transform: translateY(-80%);
|
||||
transform: translateY(-80%);
|
||||
left: 50%;
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.grid-container{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
.button-in {
|
||||
background-color: #8c0000;
|
||||
border-color: #071013;
|
||||
border-width: 2px;
|
||||
color: white;
|
||||
font-family: "Bit5x3";
|
||||
font-size: x-large;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* max-height: 100%; */
|
||||
white-space: nowrap;
|
||||
/* padding-bottom: 0; */
|
||||
margin-bottom: 0px;
|
||||
overflow: hidden;
|
||||
padding: 20px 40px;
|
||||
margin: 0px;
|
||||
.button-out {
|
||||
background-color: #008c8c;
|
||||
border-color: #071013;
|
||||
border-width: 2px;
|
||||
color: white;
|
||||
font-family: "Bit5x3";
|
||||
font-size: x-large;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
header h1{
|
||||
grid-column: 1 / 7;
|
||||
grid-row: 1;
|
||||
/* grid-column: span 6; */
|
||||
/* tmp? */
|
||||
padding: 20px;
|
||||
border: 1px solid bisque;
|
||||
}
|
||||
header nav{
|
||||
/* make it a flexbox? */
|
||||
grid-column: 7 / 13;
|
||||
grid-row: 1;
|
||||
justify-self: end;
|
||||
/* tmp? */
|
||||
padding: 20px;
|
||||
border: 1px solid bisque;
|
||||
}
|
||||
|
||||
header h2{
|
||||
grid-row: 3;
|
||||
grid-column: 5 / span 4;
|
||||
justify-self: center;
|
||||
/* tmp */
|
||||
border: 1px solid black;
|
||||
z-index: 3;
|
||||
}
|
||||
header h2 div{
|
||||
font-size: 2em;
|
||||
/* color: red; */
|
||||
}
|
||||
|
||||
nav div {
|
||||
display: inline;
|
||||
color: bisque;
|
||||
font-weight: bold;
|
||||
}
|
||||
nav > div {
|
||||
padding-left: 1em;
|
||||
/* didn't quite work, applies to both for some reason */
|
||||
/* nav:first-child doesn't work either*/
|
||||
}
|
||||
nav div:hover{
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
|
||||
import Header from '../../pieces/Header.svelte';
|
||||
import { fetchAvatar } from "../../pieces/utils";
|
||||
import { fetchUser, fetchAllUsers, fetchAvatar } from "../../pieces/utils";
|
||||
|
||||
import * as pong from "./client/pong";
|
||||
import { gameState } from "./client/ws";
|
||||
|
||||
import { invited_username } from '../../pieces/store_invitation';
|
||||
|
||||
//user's stuff
|
||||
let user;
|
||||
let allUsers;
|
||||
@@ -36,11 +38,21 @@
|
||||
const watchMatchStartIntervalRate = 111;
|
||||
|
||||
onMount( async() => {
|
||||
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
|
||||
.then( x => x.json() );
|
||||
allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
|
||||
.then( x => x.json() );
|
||||
user = await fetchUser();
|
||||
allUsers = await fetchAllUsers();
|
||||
|
||||
if (!user) {
|
||||
showError = true;
|
||||
errorMessage = "User load failed";
|
||||
return;
|
||||
}
|
||||
|
||||
options.playerOneUsername = user.username;
|
||||
if ($invited_username) {
|
||||
options.isSomeoneIsInvited = true;
|
||||
options.playerTwoUsername = $invited_username;
|
||||
invited_username.set("");
|
||||
}
|
||||
})
|
||||
|
||||
onDestroy( async() => {
|
||||
@@ -268,29 +280,38 @@
|
||||
<button class="pong_button" on:click={fetchInvitations}>Show invitations</button>
|
||||
<fieldset in:fly="{{ y: 10, duration: 1000 }}">
|
||||
<legend>game options</legend>
|
||||
<div>
|
||||
|
||||
<label for="multi_balls">
|
||||
<input type="checkbox" id="multi_balls" name="multi_balls" bind:checked={options.multi_balls}>
|
||||
<label for="multi_balls">Multiples balls</label>
|
||||
</div>
|
||||
<div>
|
||||
Multiples balls
|
||||
</label>
|
||||
|
||||
<label for="moving_walls">
|
||||
<input type="checkbox" id="moving_walls" name="moving_walls" bind:checked={options.moving_walls}>
|
||||
<label for="moving_walls">Moving walls</label>
|
||||
</div>
|
||||
Moving walls
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<p>sound :</p>
|
||||
<input type="radio" id="sound_on" name="sound_selector" bind:group={options.sound} value="on">
|
||||
<label for="sound_on">on</label>
|
||||
<input type="radio" id="sound_off" name="sound_selector" bind:group={options.sound} value="off">
|
||||
<label for="sound_off">off</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="isSomeoneIsInvited" bind:checked={options.isSomeoneIsInvited}>
|
||||
<label for="moving_walls">Invite a friend</label>
|
||||
sound :
|
||||
<label for="sound_on">
|
||||
<input type="radio" id="sound_on" name="sound_selector" bind:group={options.sound} value="on">
|
||||
on
|
||||
</label>
|
||||
<label for="sound_off">
|
||||
<input type="radio" id="sound_off" name="sound_selector" bind:group={options.sound} value="off">
|
||||
off
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label for="invitation_checkbox">
|
||||
<input type="checkbox" id="invitation_checkbox" bind:checked={options.isSomeoneIsInvited}>
|
||||
Invite a friend
|
||||
</label>
|
||||
|
||||
{#if options.isSomeoneIsInvited}
|
||||
<select bind:value={options.playerTwoUsername}>
|
||||
{#each allUsers as user }
|
||||
<option value={user.username}>{user.username}</option>
|
||||
{#each allUsers as invitedUser }
|
||||
<option value={invitedUser.username}>{invitedUser.username}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{/if}
|
||||
@@ -339,11 +360,16 @@
|
||||
}
|
||||
#game_page {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #222425;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
#game_option {
|
||||
margin-top: 20px;
|
||||
}
|
||||
#canvas_container {
|
||||
margin-top: 20px;
|
||||
|
||||
@@ -6,15 +6,11 @@
|
||||
import Header from '../../pieces/Header.svelte';
|
||||
import MatchListElem from "../../pieces/MatchListElem.svelte";
|
||||
import type { Match } from "../../pieces/Match";
|
||||
import { fetchAvatar } from "../../pieces/utils";
|
||||
import { fetchUser, fetchAllUsers, fetchAvatar } from "../../pieces/utils";
|
||||
|
||||
import * as pongSpectator from "./client/pongSpectator";
|
||||
import { gameState } from "./client/ws";
|
||||
|
||||
//user's stuff
|
||||
let user;
|
||||
let allUsers;
|
||||
|
||||
let playerOneAvatar;
|
||||
let playerTwoAvatar;
|
||||
|
||||
@@ -30,13 +26,7 @@
|
||||
const watchGameStateIntervalRate = 142;
|
||||
|
||||
onMount( async() => {
|
||||
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
|
||||
.then( x => x.json() );
|
||||
allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
|
||||
.then( x => x.json() );
|
||||
const responseForMatchList = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
|
||||
const jsonForMatchList = await responseForMatchList.json();
|
||||
matchList = jsonForMatchList;
|
||||
matchList = await fetchMatchList();
|
||||
})
|
||||
|
||||
onDestroy( async() => {
|
||||
@@ -82,12 +72,25 @@
|
||||
async function resetPage() {
|
||||
hiddenGame = true;
|
||||
pongSpectator.destroy();
|
||||
fetchMatchList();
|
||||
matchList = await fetchMatchList();
|
||||
};
|
||||
|
||||
async function fetchMatchList() {
|
||||
matchList = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
|
||||
.then( x => x.json() );
|
||||
async function fetchMatchList()
|
||||
{
|
||||
return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("All matchs not retrieved");
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((body) => {
|
||||
return body;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("catch fetchMatchList: ", error);
|
||||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
</script>
|
||||
@@ -131,13 +134,19 @@
|
||||
<fieldset>
|
||||
<legend>options</legend>
|
||||
<button class="pong_button" on:click={fetchMatchList}>Reload</button>
|
||||
|
||||
<div>
|
||||
<p>sound :</p>
|
||||
<input type="radio" id="sound_on" name="sound_selector" bind:group={sound} value="on">
|
||||
<label for="sound_on">on</label>
|
||||
<input type="radio" id="sound_off" name="sound_selector" bind:group={sound} value="off">
|
||||
<label for="sound_off">off</label>
|
||||
sound :
|
||||
<label for="sound_on">
|
||||
<input type="radio" id="sound_on" name="sound_selector" bind:group={sound} value="on">
|
||||
on
|
||||
</label>
|
||||
<label for="sound_off">
|
||||
<input type="radio" id="sound_off" name="sound_selector" bind:group={sound} value="off">
|
||||
off
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
{#if matchList.length !== 0}
|
||||
<menu id="match_list">
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</script>
|
||||
<Header />
|
||||
<br />
|
||||
|
||||
<div class="background-pages">
|
||||
<div class="principal-div">
|
||||
<table class="stats-table">
|
||||
<thead>
|
||||
@@ -59,6 +59,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -71,7 +72,6 @@
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
font-size: 0.9em;
|
||||
font-family: sans-serif;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,14 +59,20 @@ function start_after_countdown()
|
||||
abortControllerKeydown = new AbortController();
|
||||
window.addEventListener(
|
||||
'keydown',
|
||||
(e) => { pong.addKey(e.key); },
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
pong.addKey(e.key);
|
||||
},
|
||||
{signal: abortControllerKeydown.signal}
|
||||
);
|
||||
|
||||
abortControllerKeyup = new AbortController();
|
||||
window.addEventListener(
|
||||
'keyup',
|
||||
(e) => { pong.deleteKey(e.key); },
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
pong.deleteKey(e.key);
|
||||
},
|
||||
{signal: abortControllerKeyup.signal}
|
||||
);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
<Chat color="bisque"/>
|
||||
|
||||
<div class="background-pages">
|
||||
<div class="outer">
|
||||
{#if user !== undefined}
|
||||
<GenerateUserDisplay user={user}/>
|
||||
@@ -28,13 +29,13 @@
|
||||
<div>Failed to load current</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<style>
|
||||
|
||||
div.outer{
|
||||
max-width: 960px;
|
||||
margin: 40px auto;
|
||||
max-width: 100%;
|
||||
text-align: center;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -24,22 +24,10 @@
|
||||
|
||||
onMount( async() => {
|
||||
|
||||
// DO I ACTUALLY NEED TO ON MOUNT ALL THIS STUFF?
|
||||
// ALSO I COULD JUST USE THE FUNCITONS I MADE...
|
||||
|
||||
|
||||
// yea no idea what
|
||||
// i mean do i fetch user? i will for now
|
||||
user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
|
||||
.then( (x) => x.json() );
|
||||
|
||||
fetchAll();
|
||||
// ok this shit works!
|
||||
// const interval = setInterval(() => {
|
||||
// fetchAll();
|
||||
// }, 1000);
|
||||
|
||||
// return () => clearInterval(interval);
|
||||
});
|
||||
|
||||
const fetchAll = async() => {
|
||||
@@ -234,6 +222,7 @@
|
||||
</script>
|
||||
|
||||
|
||||
<div class="background-pages">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="top-grid">
|
||||
|
||||
@@ -353,7 +342,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<style>
|
||||
|
||||
/* ok so i want a 12 column grid with a sidebar */
|
||||
@@ -368,7 +357,14 @@
|
||||
|
||||
div.sidebar-list{
|
||||
grid-column: 1 / span 2;
|
||||
background: white;
|
||||
background: #FB8B24;
|
||||
padding: 1vw;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
border-right: 4px solid #071013;
|
||||
}
|
||||
|
||||
div.sidebar-item{
|
||||
@@ -393,7 +389,7 @@
|
||||
}
|
||||
|
||||
div.placeholder{
|
||||
color: darkgray;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -402,7 +398,7 @@
|
||||
}
|
||||
|
||||
div.tip{
|
||||
color: darkgray;
|
||||
color: white;
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
|
||||
|
||||
<main>
|
||||
<div class="background-pages">
|
||||
<h2>Look! You can change stuff</h2>
|
||||
<div class="cards">
|
||||
<Card>
|
||||
@@ -114,7 +115,7 @@
|
||||
<div class="label">New Username</div>
|
||||
<!-- it really hates {user.username} and ${user.username} -->
|
||||
<!-- <input type="text" placeholder="current username: ${user.username}" bind:value={set.username}> -->
|
||||
<input type="text" placeholder="current username: {nameTmp}" bind:value={set.username}>
|
||||
<input type="text" placeholder="{nameTmp}" bind:value={set.username}>
|
||||
<div class="success">{success.username}</div>
|
||||
<div class="error">{errors.username}</div>
|
||||
</div>
|
||||
@@ -144,7 +145,7 @@
|
||||
</form>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
@@ -158,6 +159,8 @@
|
||||
grid-gap: 20px; */
|
||||
}
|
||||
|
||||
|
||||
|
||||
div.cards{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
@@ -190,6 +193,7 @@
|
||||
|
||||
.inline-check{
|
||||
display: inline;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,126 +21,84 @@
|
||||
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<header>
|
||||
<div>
|
||||
<img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}>
|
||||
<h1>Potato Pong</h1>
|
||||
</div>
|
||||
<nav>
|
||||
<button class:selected="{current === '/game'}" on:click={() => (push('/game'))}>Play</button>
|
||||
<button class:selected="{current === '/spectator'}" on:click={() => (push('/spectator'))}>Spectate</button>
|
||||
<button class:selected="{current === '/ranking'}" on:click={() => (push('/ranking'))}>Ranking</button>
|
||||
<div class="header">
|
||||
<img src="/img/logo_potato.png" alt="Potato Pong Logo" on:click={() => (push('/'))}>
|
||||
<div class="center">
|
||||
<button class:selected="{current === '/game'}" on:click={() => (push('/game'))}>Play</button>
|
||||
<button class:selected="{current === '/spectator'}" on:click={() => (push('/spectator'))}>Spectate</button>
|
||||
<button class:selected="{current === '/ranking'}" on:click={() => (push('/ranking'))}>Ranking</button>
|
||||
<button class:selected="{current === '/profile'}" on:click={() => (push('/profile'))}>My Profile</button>
|
||||
<button class:selected="{current === '/profile/friends'}" on:click={() => (push('/profile/friends'))}>Friends</button>
|
||||
<button on:click={handleClickLogout}>Log Out</button>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<button class:selected="{current === '/profile/friends'}" on:click={() => (push('/profile/friends'))}>Friends</button>
|
||||
</div>
|
||||
<button class="logout" on:click={handleClickLogout}>Log Out</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* See "possible_fonts.css" for more font options... */
|
||||
@font-face {
|
||||
font-family: 'Bondi';
|
||||
src:url('/fonts/Bondi.ttf.woff') format('woff'),
|
||||
url('/fonts/Bondi.ttf.svg#Bondi') format('svg'),
|
||||
url('/fonts/Bondi.ttf.eot'),
|
||||
url('/fonts/Bondi.ttf.eot?#iefix') format('embedded-opentype');
|
||||
font-family: "Bit5x3";
|
||||
src:
|
||||
url("/fonts/Bit5x3.woff2") format("woff2"),
|
||||
local("Bit5x3"),
|
||||
url("/fonts/Bit5x3.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
||||
.selected {
|
||||
background-color: chocolate;
|
||||
.header div.center button.selected {
|
||||
text-decoration: underline;
|
||||
/* TMP so it's obvious but we need to pick good colors */
|
||||
background-color: #2B3A67;
|
||||
}
|
||||
|
||||
.header div.center button {
|
||||
background-color: #8c0000;
|
||||
border-color: #071013;
|
||||
color: white;
|
||||
font-family: "Bit5x3";
|
||||
border-width: 2px;
|
||||
font-size: 2vw;
|
||||
}
|
||||
|
||||
|
||||
/* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */
|
||||
|
||||
|
||||
header{
|
||||
/* background: #f7f7f7; */
|
||||
background: #618174;
|
||||
/* padding: 20px; */
|
||||
margin: 0;
|
||||
/* does nothing so far... */
|
||||
/* display: flex; */
|
||||
.header button.logout {
|
||||
background-color: #008c8c;
|
||||
border-color: #071013;
|
||||
color: white;
|
||||
font-family: "Bit5x3";
|
||||
border-width: 2px;
|
||||
font-size: 2vw;
|
||||
}
|
||||
|
||||
header{
|
||||
/* for some reason this doesn't do shit! */
|
||||
position: sticky;
|
||||
/* position: absolute; */
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
/* display: grid; */
|
||||
/* grid-template-columns: 1fr 1fr 1fr; */
|
||||
.header {
|
||||
resize: vertical;
|
||||
overflow: hidden;
|
||||
background: #FB8B24;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
border-bottom: 4px solid #071013;
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Headers */
|
||||
h1{
|
||||
font-family: 'Bondi';
|
||||
}
|
||||
|
||||
h1{
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
/* max-width: 40px; */
|
||||
/* this helped with the weird extra space under the image... */
|
||||
display: flex;
|
||||
.header div.center {
|
||||
width: fit-content;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
display: inline-block;
|
||||
-ms-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
/* Images */
|
||||
.header button.logout {
|
||||
float: right;
|
||||
}
|
||||
|
||||
img{
|
||||
.header img{
|
||||
cursor: pointer;
|
||||
max-width: 40px;
|
||||
padding: 7px 20px;
|
||||
justify-self: left;
|
||||
max-width: 10%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
header div {
|
||||
display: flex;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nav{
|
||||
display: flex;
|
||||
/* justify-content: flex-end; */
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
nav button{
|
||||
margin: 7px 20px;
|
||||
/* margin: 7px auto; */
|
||||
/* padding: 5px; */
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 350px) {
|
||||
nav button{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
header div{
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
|
||||
import Layouts from './Chat_layouts.svelte';
|
||||
import { init_socket } from './Socket_init';
|
||||
import { init_socket } from './Socket_chat';
|
||||
|
||||
export let color = "transparent";
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<script lang="ts">
|
||||
|
||||
import Debug from './tmp_debug.svelte';
|
||||
|
||||
import { layout } from './Store_chat';
|
||||
import ChatBox from './Chat_box_css.svelte';
|
||||
|
||||
@@ -11,10 +9,11 @@
|
||||
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 PasswordLayout from './Layout_password.svelte';
|
||||
import CreateLayout from './Layout_create.svelte';
|
||||
import MuteLayout from './Layout_mute.svelte';
|
||||
import UserLayout from './Layout_user.svelte';
|
||||
import InviteLayout from './Layout_invite.svelte';
|
||||
|
||||
import Button from './Element_button.svelte';
|
||||
|
||||
@@ -29,8 +28,8 @@
|
||||
*/
|
||||
function set_layouts($layout)
|
||||
{
|
||||
console.log("layouts:", layouts);
|
||||
console.log("layout:", $layout);
|
||||
//console.log("layouts:", layouts);
|
||||
//console.log("layout:", $layout);
|
||||
if ($layout.length === 0)
|
||||
layout.set(layouts[0]);
|
||||
else if ($layout === "close")
|
||||
@@ -41,7 +40,7 @@
|
||||
layouts = [$layout, "home"];
|
||||
else
|
||||
layouts = [$layout, layouts[0]];
|
||||
console.log("- layouts:", layouts);
|
||||
//console.log("- layouts:", layouts);
|
||||
}
|
||||
$: set_layouts($layout);
|
||||
|
||||
@@ -67,8 +66,17 @@
|
||||
{:else if $layout === "room_set"}
|
||||
<RoomsetLayout back={layouts[1]} />
|
||||
|
||||
{:else if $layout === "protected"}
|
||||
<ProtectedLayout back={layouts[1]} />
|
||||
{:else if $layout === "password"}
|
||||
<PasswordLayout back={layouts[1]} />
|
||||
|
||||
{:else if $layout === "add_password"}
|
||||
<PasswordLayout back={layouts[1]} mode="add" />
|
||||
|
||||
{:else if $layout === "change_password"}
|
||||
<PasswordLayout back={layouts[1]} mode="change" />
|
||||
|
||||
{:else if $layout === "remove_password"}
|
||||
<PasswordLayout back={layouts[1]} mode="remove" />
|
||||
|
||||
{:else if $layout === "create"}
|
||||
<CreateLayout back={layouts[1]} />
|
||||
@@ -79,12 +87,12 @@
|
||||
{:else if $layout === "user"}
|
||||
<UserLayout back={layouts[1]} />
|
||||
|
||||
{:else if $layout === "invite"}
|
||||
<InviteLayout back={layouts[1]} />
|
||||
|
||||
{/if}
|
||||
|
||||
</ChatBox>
|
||||
|
||||
<!-- TMP DEBUG -->
|
||||
<!-- <Debug bind:layouts /> -->
|
||||
|
||||
<style></style>
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<Button
|
||||
bind:layout
|
||||
new_layout=""
|
||||
on_click={}
|
||||
my_class=""
|
||||
my_title=""
|
||||
>
|
||||
@@ -17,7 +16,6 @@
|
||||
export let my_class = "";
|
||||
export let my_title = "";
|
||||
export let new_layout = "";
|
||||
export let on_click = "";
|
||||
|
||||
function update_layout() {
|
||||
layout.set(new_layout);
|
||||
@@ -25,7 +23,7 @@
|
||||
|
||||
</script>
|
||||
|
||||
<button on:click={update_layout} on:click={on_click} title={my_title} class={my_class}>
|
||||
<button on:click={update_layout} on:click title={my_title} class={my_class}>
|
||||
<p><slot></slot></p>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface Room
|
||||
{
|
||||
name: string;
|
||||
type: "public" | "protected" | "private" | "direct" | "user";
|
||||
users?: string[];
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
import { msgs, layout, allowed_chars } from './Store_chat';
|
||||
import { change_room, create_room } from './Request_rooms';
|
||||
import { onMount } from 'svelte';
|
||||
import { FetchResponse } from './Types_chat';
|
||||
import Button from './Element_button.svelte';
|
||||
import Warning from './Element_warning.svelte';
|
||||
|
||||
@@ -13,18 +14,16 @@
|
||||
onMount(async() => {
|
||||
let response = await fetch('/api/v2/chat/allowedchars');
|
||||
let data = await response.json();
|
||||
console.log("data:", data);
|
||||
allowed_chars = data.chars;
|
||||
//regex = new RegExp(`^[a-zA-Z0-9\\s${allowed_chars}]+$`);
|
||||
});
|
||||
|
||||
let room_name: string;
|
||||
let room_type: string;
|
||||
let is_protected = false;
|
||||
let room_password: string;
|
||||
let response = {
|
||||
status: 0,
|
||||
message: "",
|
||||
}
|
||||
let response: FetchResponse;
|
||||
let show_error = false;
|
||||
|
||||
async function handleSubmit(evt)
|
||||
{
|
||||
@@ -36,12 +35,18 @@
|
||||
let room = {
|
||||
name: room_name,
|
||||
type: room_type,
|
||||
protection: is_protected,
|
||||
};
|
||||
if (is_protected === true)
|
||||
room.password = room_password;
|
||||
|
||||
// send the new room
|
||||
response = await create_room(room);
|
||||
|
||||
// go to room
|
||||
if (response.status === 200)
|
||||
if (response.status >= 300 || response.error)
|
||||
show_error = response.error;
|
||||
else
|
||||
await change_room(response.room);
|
||||
}
|
||||
|
||||
@@ -67,7 +72,7 @@
|
||||
<!-- panel_create -->
|
||||
<div class="panel panel_create __border_top">
|
||||
<form on:submit|preventDefault={handleSubmit}>
|
||||
{#if response.status >= 300}
|
||||
{#if show_error}
|
||||
<Warning content={response.message}/>
|
||||
{/if}
|
||||
<!-- name: -->
|
||||
@@ -82,21 +87,19 @@
|
||||
<input id="chat_public" bind:group={room_type} type="radio" name="room_type" value="public" required>
|
||||
</label>
|
||||
<!-- [ ] private -->
|
||||
<label for="chat_private" class="_radio hide">
|
||||
<label for="chat_private" class="_radio">
|
||||
<p>private</p>
|
||||
<input id="chat_private" bind:group={room_type} type="radio" name="room_type" value="private" required>
|
||||
</label>
|
||||
<!-- [ ] protected -->
|
||||
<label for="chat_protected" class="_radio hide">
|
||||
<label for="chat_protected" class="_checkbox">
|
||||
<p>protected</p>
|
||||
<input id="chat_protected" bind:group={room_type} type="radio" name="room_type" value="protected" required>
|
||||
<input id="chat_protected" bind:checked={is_protected} type="checkbox" name="room_type" value="protected">
|
||||
</label>
|
||||
<!-- [x] protected -->
|
||||
{#if room_type === 'protected'}
|
||||
<div>
|
||||
<label for="chat_pswd"><p>choose a password :</p></label>
|
||||
<input id="chat_pswd" bind:value={room_password} type="password" placeholder="minimum 8 characters" minlength="8" name="password" required>
|
||||
</div>
|
||||
{#if is_protected === true}
|
||||
<label for="chat_pswd">choose a password :</label>
|
||||
<input id="chat_pswd" bind:value={room_password} type="password" placeholder="minimum 8 characters" minlength="8" name="password" required>
|
||||
{/if}
|
||||
<input type="submit" value="⮡">
|
||||
</form>
|
||||
@@ -119,24 +122,25 @@
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
/* temp
|
||||
*/
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* radio elements style check
|
||||
*/
|
||||
.panel label._radio {
|
||||
.panel label {
|
||||
display: inline;
|
||||
margin: 10px 0px 0px auto;
|
||||
padding-right: 10px;
|
||||
cursor: pointer;
|
||||
padding-right: 10px;
|
||||
margin: 10px 0px 10px auto;
|
||||
}
|
||||
.panel label._radio * {
|
||||
.panel label._radio {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.panel label._checkbox {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.panel label * {
|
||||
display: inline;
|
||||
}
|
||||
.panel label._radio p {
|
||||
.panel label p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
|
||||
import { layout, msgs, user } from './Store_chat';
|
||||
import { layout, msgs, user, current_room } from './Store_chat';
|
||||
import { change_room, get_room_messages, get_my_rooms } from './Request_rooms';
|
||||
import { onMount } from 'svelte';
|
||||
import Button from './Element_button.svelte';
|
||||
@@ -13,8 +13,16 @@
|
||||
console.log("inside go_to_room");
|
||||
|
||||
console.log("room:", room);
|
||||
await change_room(room);
|
||||
await get_room_messages();
|
||||
if (room.protection && !room.allowed)
|
||||
{
|
||||
await current_room.set(room);
|
||||
layout.set("password");
|
||||
}
|
||||
else
|
||||
{
|
||||
await change_room(room);
|
||||
await get_room_messages();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -47,8 +55,8 @@
|
||||
<p>rooms are loading...</p>
|
||||
{:then rooms}
|
||||
{#each rooms as room}
|
||||
<Button my_class="list" on_click={function() {go_to_room(room)}}>
|
||||
{room.name}
|
||||
<Button my_class="list" on:click={function() {go_to_room(room)}}>
|
||||
{room.client_name}
|
||||
</Button>
|
||||
{/each}
|
||||
{/await}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { layout, user, current_room } from './Store_chat';
|
||||
import { get_all_users, invite_user } from './Request_rooms';
|
||||
import Button from './Element_button.svelte';
|
||||
|
||||
export let back = "";
|
||||
|
||||
let users = get_all_users();
|
||||
|
||||
// invite user in this room
|
||||
async function invite_this_user(username: string)
|
||||
{
|
||||
console.log("inside invite_this_user");
|
||||
|
||||
invite_user(username);
|
||||
layout.set("room");
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- new -->
|
||||
<Button my_class="invite deactivate">
|
||||
invite
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
<Button my_class="room_name deactivate __border_top">
|
||||
{$current_room.name}
|
||||
</Button>
|
||||
|
||||
<!-- panel_new -->
|
||||
<div class="panel panel_invite __border_top">
|
||||
<p>invite someone in this room :</p>
|
||||
<div>
|
||||
<div class="__show_if_only_child">
|
||||
<p class="__center">/ there is no one to invite yet /</p>
|
||||
</div>
|
||||
{#await users}
|
||||
<p>users are loading...</p>
|
||||
{:then users}
|
||||
{#each users as user}
|
||||
<Button my_class="list" on:click={function() {invite_this_user(user.username)}}>
|
||||
{user.username}
|
||||
</Button>
|
||||
{/each}
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "new"
|
||||
*/
|
||||
.grid_box :global(.back ) {grid-area: back;}
|
||||
.grid_box :global(.invite ) {grid-area: invite;}
|
||||
.grid_box :global(.close ) {grid-area: close;}
|
||||
.grid_box :global(.room_name ) {grid-area: room_name;}
|
||||
.grid_box :global(.panel_invite) {grid-area: panel_invite;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back invite close ' auto
|
||||
' room_name room_name room_name ' auto
|
||||
' panel_invite panel_invite panel_invite ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { layout, msgs, user, socket } from './Store_chat';
|
||||
import { layout, msgs, user, socket, current_room } from './Store_chat';
|
||||
import { join_room, change_room, get_room_messages, get_all_rooms } from './Request_rooms';
|
||||
import Button from './Element_button.svelte';
|
||||
|
||||
@@ -13,10 +13,14 @@
|
||||
{
|
||||
console.log("inside join_room");
|
||||
|
||||
console.log("room:", room);
|
||||
const updated_room = await join_room(room);
|
||||
console.log("updated room:", updated_room);
|
||||
await change_room(updated_room);
|
||||
if (updated_room.protection)
|
||||
{
|
||||
current_room.set(updated_room);
|
||||
layout.set("password");
|
||||
}
|
||||
else
|
||||
await change_room(updated_room);
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -52,7 +56,7 @@
|
||||
<p>rooms are loading...</p>
|
||||
{:then rooms}
|
||||
{#each rooms as room}
|
||||
<Button my_class="list" on_click={function() {join_rooms(room)}}>
|
||||
<Button my_class="list" on:click={function() {join_rooms(room)}}>
|
||||
{room.name}
|
||||
</Button>
|
||||
{/each}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
<script lang="ts">
|
||||
|
||||
import { layout, current_room } from './Store_chat';
|
||||
import { change_room, validate_password, change_password, add_password, remove_password } from './Request_rooms';
|
||||
import { FetchResponse } from './Types_chat';
|
||||
import Button from './Element_button.svelte';
|
||||
import Warning from './Element_warning.svelte';
|
||||
|
||||
export let back = "";
|
||||
export let mode = "validate";
|
||||
|
||||
let password_state = "";
|
||||
if (mode === 'change')
|
||||
password_state = "new";
|
||||
if (mode === 'remove')
|
||||
password_state = "current";
|
||||
|
||||
let room_password: string;
|
||||
let room_old_password: string;
|
||||
let response: FetchResponse;
|
||||
let show_error = false;
|
||||
|
||||
async function handleSubmit(evt)
|
||||
{
|
||||
console.log("in handleSubmit");
|
||||
|
||||
let formIsValid = evt.target.checkValidity();
|
||||
|
||||
if (!formIsValid)
|
||||
return;
|
||||
|
||||
let room = {
|
||||
name: $current_room.name,
|
||||
type: $current_room.type,
|
||||
password: room_password,
|
||||
};
|
||||
room.protection = true;
|
||||
if (mode === 'remove')
|
||||
room.protection = false;
|
||||
|
||||
// send password
|
||||
if (mode === 'validate')
|
||||
response = await validate_password(room);
|
||||
if (mode === 'add')
|
||||
response = await add_password(room);
|
||||
if (mode === 'change')
|
||||
response = await change_password(room, room_old_password);
|
||||
if (mode === 'remove')
|
||||
response = await remove_password(room);
|
||||
|
||||
// go to room
|
||||
if (response.status >= 300 || response.error)
|
||||
show_error = response.error;
|
||||
else
|
||||
await change_room(response.room);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
<Button my_class="room_name deactivate">
|
||||
{$current_room.name}
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button new_layout="close" my_class="close icon">
|
||||
close
|
||||
</Button>
|
||||
|
||||
<!-- panel_password -->
|
||||
<div class="panel panel_password __border_top">
|
||||
<p class="title __center">this room is protected</p>
|
||||
<form on:submit|preventDefault={handleSubmit}>
|
||||
{#if show_error}
|
||||
<Warning content={response.message}/>
|
||||
{/if}
|
||||
{#if mode === 'change'}
|
||||
<label for="chat_old_pswd"><p>enter old password :</p></label>
|
||||
<input id="chat_old_pswd" bind:value={room_old_password} type="password" placeholder="minimum 8 characters" minlength="8" name="old_password" required>
|
||||
{/if}
|
||||
<label for="chat_pswd"><p>enter {password_state} password :</p></label>
|
||||
<input id="chat_pswd" bind:value={room_password} type="password" placeholder="minimum 8 characters" minlength="8" name="password" required>
|
||||
<input type="submit" value="⮡">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
/* grid layout "password"
|
||||
*/
|
||||
.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_password) {grid-area: panel_password;}
|
||||
.grid_box {
|
||||
grid:
|
||||
' back room_name close ' auto
|
||||
' panel_password panel_password panel_password ' 1fr
|
||||
/ auto 1fr auto ;
|
||||
}
|
||||
|
||||
|
||||
/* submit
|
||||
*/
|
||||
form input[type=submit] {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<script>
|
||||
|
||||
import { layout } from './Store_chat';
|
||||
import Button from './Element_button.svelte';
|
||||
|
||||
export let back = "";
|
||||
|
||||
</script>
|
||||
|
||||
<div class="grid_box">
|
||||
|
||||
<!-- back -->
|
||||
<Button new_layout={back} my_class="back icon" my_title="go back {back}">
|
||||
back
|
||||
</Button>
|
||||
|
||||
<!-- room_name -->
|
||||
<Button my_class="room_name deactivate">
|
||||
<room_name>
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
<Button 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="⮡">
|
||||
</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>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
|
||||
import { layout, socket, msgs, add_msg, current_room_name } from './Store_chat';
|
||||
import { layout, socket, msgs, add_msg, current_room } from './Store_chat';
|
||||
import Button from './Element_button.svelte';
|
||||
import Msg from './Element_msg.svelte';
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
<!-- room_name -->
|
||||
<Button new_layout="room_set" my_class="room_name transparent">
|
||||
{$current_room_name}
|
||||
{$current_room.name}
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
@@ -71,7 +71,7 @@
|
||||
</div>
|
||||
|
||||
<!-- send -->
|
||||
<Button my_class="send" on_click={send_msg}>
|
||||
<Button my_class="send" on:click={send_msg}>
|
||||
send
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
<script>
|
||||
|
||||
import { layout, current_room_name } from './Store_chat';
|
||||
import { get_room_users, user_leave_room } from './Request_rooms';
|
||||
import { layout, current_room } from './Store_chat';
|
||||
import { get_room_users, leave_room } from './Request_rooms';
|
||||
import Button from './Element_button.svelte';
|
||||
|
||||
export let back = "";
|
||||
|
||||
let users = get_room_users();
|
||||
|
||||
console.log("current_room:", $current_room);
|
||||
|
||||
function user_profile()
|
||||
{
|
||||
console/log("in user_profile");
|
||||
console.log("in user_profile");
|
||||
}
|
||||
|
||||
function leave_room()
|
||||
function user_leave_room()
|
||||
{
|
||||
console.log("in leave_room");
|
||||
user_leave_room();
|
||||
leave_room();
|
||||
layout.set("home");
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
|
||||
<!-- room_name -->
|
||||
<Button my_class="room_name deactivate">
|
||||
{$current_room_name}
|
||||
{$current_room.name}
|
||||
</Button>
|
||||
|
||||
<!-- close -->
|
||||
@@ -41,9 +43,27 @@
|
||||
|
||||
<!-- panel_room_set -->
|
||||
<div class="panel panel_room_set __border_top">
|
||||
<Button on_click={leave_room}>
|
||||
leave
|
||||
</Button>
|
||||
{#if $current_room.type !== "direct"}
|
||||
<Button on:click={user_leave_room}>
|
||||
leave
|
||||
</Button>
|
||||
<Button new_layout="invite">
|
||||
invite someone
|
||||
</Button>
|
||||
{/if}
|
||||
{#if $current_room.protection }
|
||||
<p class="__center">this room is password protected</p>
|
||||
<Button new_layout="change_password">
|
||||
change password
|
||||
</Button>
|
||||
<Button new_layout="remove_password">
|
||||
remove password
|
||||
</Button>
|
||||
{:else}
|
||||
<Button new_layout="add_password">
|
||||
add password
|
||||
</Button>
|
||||
{/if}
|
||||
<p>room users :</p>
|
||||
<div class="room_users">
|
||||
<div class="__show_if_only_child">
|
||||
@@ -53,7 +73,7 @@
|
||||
<p>list of users is loading...</p>
|
||||
{:then users}
|
||||
{#each users as user}
|
||||
<Button new_layout="user" my_class="list" on_click={user_profile}>
|
||||
<Button new_layout="user" my_class="list" on:click={user_profile}>
|
||||
{user}
|
||||
</Button>
|
||||
{/each}
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
let mute = "mute";
|
||||
let block = "block";
|
||||
|
||||
import { push } from "svelte-spa-router";
|
||||
import { invited_username } from '../store_invitation';
|
||||
function game_invitation()
|
||||
{
|
||||
const usernamePLACEHOLDER = "hulamy";
|
||||
invited_username.set(usernamePLACEHOLDER);
|
||||
push("/game");
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -41,7 +49,7 @@
|
||||
<Button>
|
||||
view profile
|
||||
</Button>
|
||||
<Button>
|
||||
<Button on_click={() => game_invitation()}>
|
||||
game invitation
|
||||
</Button>
|
||||
<Button>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { msgs, user, layout, socket, current_room_name } from './Store_chat';
|
||||
import type { Room } from './Interface_chat';
|
||||
import { msgs, user, layout, socket, current_room } from './Store_chat';
|
||||
import { Room, FetchResponse, FetchMethod } from './Types_chat';
|
||||
import { fetch_chat_request, set_client_name_on_room, fill_fetch_response } from './Request_utils';
|
||||
|
||||
export async function get_room_messages()
|
||||
{
|
||||
console.log("in get_room_messages");
|
||||
const response = await fetch('/api/v2/chat/messages');
|
||||
const data = await response.json();
|
||||
const messages = data.messages;
|
||||
|
||||
let response: FetchResponse = await fetch_chat_request('messages', FetchMethod.GET);
|
||||
|
||||
const messages = response.messages;
|
||||
|
||||
if (messages === null)
|
||||
return;
|
||||
@@ -24,102 +26,141 @@ export async function create_room(room: Room)
|
||||
{
|
||||
console.log("in create_room");
|
||||
|
||||
// send the new room
|
||||
const response = await fetch('/api/v2/chat/create', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(room),
|
||||
});
|
||||
console.log("room sent to create:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('create', FetchMethod.POST, room);
|
||||
console.log("room returned from create:", response.room);
|
||||
|
||||
// get response status and message
|
||||
let response_status = response.status;
|
||||
let data = await response.json();
|
||||
let response_message = "";
|
||||
|
||||
return {
|
||||
status: response_status,
|
||||
message: data.message,
|
||||
room: data.room,
|
||||
};
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function join_room(room: Room)
|
||||
{
|
||||
console.log("in join_room");
|
||||
|
||||
const response = await fetch('/api/v2/chat/join', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(room),
|
||||
});
|
||||
let data = await response.json();
|
||||
console.log("room sent to join:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('join', FetchMethod.POST, room);
|
||||
console.log("room returned from join:", response.room);
|
||||
|
||||
return data.room;
|
||||
return response.room;
|
||||
}
|
||||
|
||||
export async function change_room(room: Room)
|
||||
{
|
||||
console.log("in change_room");
|
||||
|
||||
console.log("room:", room);
|
||||
const response = await fetch('/api/v2/chat/change', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(room),
|
||||
});
|
||||
let data = await response.json();
|
||||
console.log("room sent to change:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('change', FetchMethod.POST, room);
|
||||
console.log("room returned from change:", response.room);
|
||||
|
||||
await get_room_messages();
|
||||
|
||||
let room_name = data.room.name;
|
||||
if (room.type === 'direct')
|
||||
{
|
||||
room_name === room.users[0];
|
||||
if (room_name === user.username)
|
||||
room_name === room.users[1];
|
||||
}
|
||||
current_room_name.set(room_name);
|
||||
set_client_name_on_room(room);
|
||||
|
||||
current_room.set(room);
|
||||
layout.set("room");
|
||||
}
|
||||
|
||||
export async function validate_password(room: Room)
|
||||
{
|
||||
console.log("in validate_password");
|
||||
|
||||
console.log("room sent to validate password:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('passwordauth', FetchMethod.POST, room);
|
||||
console.log("room returned from validate password:", response.room);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function add_password(room: Room)
|
||||
{
|
||||
console.log("in add_password");
|
||||
|
||||
console.log("room sent to add password:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('addpassword', FetchMethod.POST, room);
|
||||
console.log("room returned from add password:", response.room);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function change_password(room: Room, old_password: string)
|
||||
{
|
||||
console.log("in send_password");
|
||||
|
||||
let request_body =
|
||||
{
|
||||
room: room,
|
||||
old_password: old_password,
|
||||
}
|
||||
|
||||
console.log("room sent to change password:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('changepassword', FetchMethod.POST, request_body);
|
||||
console.log("room returned from change password:", response.room);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function remove_password(room: Room)
|
||||
{
|
||||
console.log("in send_password");
|
||||
|
||||
console.log("room sent to remove password:", room);
|
||||
let response: FetchResponse = await fetch_chat_request('removepassword', FetchMethod.DELETE, room);
|
||||
console.log("room returned from remove password:", response.room);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function invite_user(user_name: string)
|
||||
{
|
||||
console.log("in invite_user");
|
||||
|
||||
let response: FetchResponse = await fetch_chat_request('invite', FetchMethod.POST, {username: user_name});
|
||||
|
||||
await get_room_messages();
|
||||
}
|
||||
|
||||
export async function get_my_rooms()
|
||||
{
|
||||
console.log("in get_my_rooms");
|
||||
|
||||
const response = await fetch('/api/v2/chat/myrooms');
|
||||
const data = await response.json();
|
||||
console.log("data.rooms:", data.rooms);
|
||||
let response: FetchResponse = await fetch_chat_request('myrooms', FetchMethod.GET);
|
||||
|
||||
return data.rooms;
|
||||
let rooms = response.rooms.map(room => set_client_name_on_room(room));
|
||||
|
||||
return rooms;
|
||||
}
|
||||
|
||||
export async function get_all_rooms()
|
||||
{
|
||||
console.log("in get_all_rooms");
|
||||
|
||||
const response = await fetch('/api/v2/chat/allrooms');
|
||||
const data = await response.json();
|
||||
let response: FetchResponse = await fetch_chat_request('allrooms', FetchMethod.GET);
|
||||
|
||||
return data.rooms;
|
||||
return response.rooms;
|
||||
}
|
||||
|
||||
export async function get_room_users()
|
||||
{
|
||||
console.log("in get_room_users");
|
||||
|
||||
const response = await fetch('/api/v2/chat/roomusers');
|
||||
const data = await response.json();
|
||||
let response: FetchResponse = await fetch_chat_request('roomusers', FetchMethod.GET);
|
||||
|
||||
return data.users;
|
||||
return response.users;
|
||||
}
|
||||
|
||||
export async function user_leave_room()
|
||||
export async function get_all_users()
|
||||
{
|
||||
console.log("in get_all_users");
|
||||
|
||||
let response: FetchResponse = await fetch_chat_request('users', FetchMethod.GET);
|
||||
|
||||
return response.users;
|
||||
}
|
||||
|
||||
export async function leave_room()
|
||||
{
|
||||
console.log("in leave_room");
|
||||
|
||||
const response = await fetch('/api/v2/chat/removeuser', {
|
||||
method: 'DELETE',
|
||||
});
|
||||
let response: FetchResponse = await fetch_chat_request('leave', FetchMethod.DELETE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { user } from './Store_chat';
|
||||
import { Room, FetchResponse, FetchInit, FetchMethod } from './Types_chat';
|
||||
|
||||
export async function fetch_chat_request(route: string, fetchMethod: FetchMethod, param?: any)
|
||||
{
|
||||
console.log("in fetch_chat_request");
|
||||
|
||||
let response: FetchResponse = { status: 0 };
|
||||
|
||||
let fetch_params: FetchInit = {
|
||||
method: fetchMethod,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
}
|
||||
if (param)
|
||||
fetch_params.body = JSON.stringify(param);
|
||||
|
||||
try
|
||||
{
|
||||
const resp = await fetch(`/api/v2/chat/${route}`, fetch_params);
|
||||
response.status = resp.status;
|
||||
|
||||
let data = await resp.json();
|
||||
fill_fetch_response(response, data);
|
||||
|
||||
if (!resp.ok)
|
||||
throw new Error(data.message);
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
console.error(error.message);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export function set_client_name_on_room(room: Room)
|
||||
{
|
||||
console.log("in set_client_name_on_room");
|
||||
|
||||
if (room.type === 'direct')
|
||||
{
|
||||
room.client_name = room.users[0];
|
||||
if (room.client_name === user.username)
|
||||
room.client_name = room.users[1];
|
||||
}
|
||||
else
|
||||
room.client_name = room.name;
|
||||
return room;
|
||||
}
|
||||
|
||||
export function fill_fetch_response(response: FetchResponse, data: any)
|
||||
{
|
||||
console.log("in fill_fetch_response");
|
||||
|
||||
Object.keys(data).forEach(key =>
|
||||
{
|
||||
response[key] = data[key];
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import io from 'socket.io-client';
|
||||
import { set_socket, set_user } from './Store_chat';
|
||||
import { socket_events } from './Socket_events';
|
||||
import { user, msgs } from './Store_chat';
|
||||
|
||||
const address = `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}`;
|
||||
|
||||
@@ -21,6 +21,23 @@ export async function init_socket()
|
||||
});
|
||||
set_socket(socket);
|
||||
|
||||
socket_states(socket);
|
||||
socket_events(socket);
|
||||
}
|
||||
|
||||
function socket_events(socket)
|
||||
{
|
||||
socket.on('message', function(from, message)
|
||||
{
|
||||
console.log("received msg:", message, from);
|
||||
if (from === user.username)
|
||||
from = "me";
|
||||
msgs.update(msgs => [...msgs, { name: from, message: message }]);
|
||||
});
|
||||
}
|
||||
|
||||
function socket_states(socket)
|
||||
{
|
||||
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"); });
|
||||
@@ -33,7 +50,5 @@ export async function init_socket()
|
||||
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"); });
|
||||
|
||||
socket_events(socket);
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { user, msgs } from './Store_chat';
|
||||
|
||||
export function socket_events(socket)
|
||||
{
|
||||
socket.on('message', function(from, message)
|
||||
{
|
||||
console.log("received msg:", message, from);
|
||||
if (from === user.username)
|
||||
from = "me";
|
||||
msgs.update(msgs => [...msgs, { name: from, message: message }]);
|
||||
});
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import { Room } from './Types_chat';
|
||||
|
||||
export let msgs = writable([]);
|
||||
export let layout = writable("close");
|
||||
export let current_room_name = writable("");
|
||||
export let current_room: Room = writable({
|
||||
name: "",
|
||||
type: "",
|
||||
protection: false,
|
||||
});
|
||||
|
||||
export let user;
|
||||
export let socket;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
export interface Room
|
||||
{
|
||||
name: string;
|
||||
type: "public" | "private" | "direct" | "user";
|
||||
users?: string[];
|
||||
client_name?: string;
|
||||
protection: boolean;
|
||||
allowed?: boolean;
|
||||
}
|
||||
|
||||
export interface FetchResponse
|
||||
{
|
||||
status: number;
|
||||
error?: boolean;
|
||||
code?: string;
|
||||
message?: string;
|
||||
room?: Room;
|
||||
}
|
||||
|
||||
export interface FetchInit
|
||||
{
|
||||
method: string;
|
||||
headers: any;
|
||||
body?: string;
|
||||
}
|
||||
|
||||
export enum FetchMethod
|
||||
{
|
||||
POST = 'POST',
|
||||
GET = 'GET',
|
||||
DELETE = 'DELETE',
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<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>
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const invited_username = writable("");
|
||||
@@ -13,5 +13,42 @@ export async function fetchAvatar(username: string)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("catch fetchAvatar: ", error);
|
||||
return `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/img/default.png`;
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchUser()
|
||||
{
|
||||
return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("User not retrieved");
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((body) => {
|
||||
return body;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("catch fetchUser: ", error);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchAllUsers()
|
||||
{
|
||||
return fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("All Users not retrieved");
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((body) => {
|
||||
return body;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("catch fetchAllUsers: ", error);
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user