Browse Source

* Frontend: made forward/back buttons functional

* Frontend: removed spectate button from navbar
master
vvandenb 2 years ago
parent
commit
d3fce0ae5c
  1. 134
      front/volume/src/App.svelte
  2. 6
      front/volume/src/components/NavBar.svelte
  3. 48
      front/volume/src/components/Pong/Pong.svelte
  4. 55
      front/volume/src/components/Spectate.svelte

134
front/volume/src/App.svelte

@ -1,3 +1,19 @@
<script lang="ts" context="module">
export enum APPSTATE {
HOME = "/",
PROFILE = "/profile",
HISTORY = "/history",
FRIENDS = "/friends",
SPECTATE = "/spectate",
CHANNELS = "/channels",
LEADERBOARD = "/leaderboard",
SPECTATE_GAME = "/spectate_game",
CREATE_GAME = "/create-game",
MATCHMAKING = "/matchmaking",
PROFILE_ID = "/profile_id",
}
</script>
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import Navbar from "./components/NavBar.svelte"; import Navbar from "./components/NavBar.svelte";
@ -5,7 +21,6 @@
import Profile from "./components/Profile.svelte"; import Profile from "./components/Profile.svelte";
import MatchHistory from "./components/MatchHistory.svelte"; import MatchHistory from "./components/MatchHistory.svelte";
import Friends, { addFriend } from "./components/Friends.svelte"; import Friends, { addFriend } from "./components/Friends.svelte";
import Spectate from "./components/Spectate.svelte";
import Chat from "./components/Chat.svelte"; import Chat from "./components/Chat.svelte";
import Channels from "./components/Channels.svelte"; import Channels from "./components/Channels.svelte";
import Leaderboard from "./components/Leaderboard.svelte"; import Leaderboard from "./components/Leaderboard.svelte";
@ -14,12 +29,31 @@
import type { Player } from "./components/Profile.svelte"; import type { Player } from "./components/Profile.svelte";
import type { Match } from "./components/MatchHistory.svelte"; import type { Match } from "./components/MatchHistory.svelte";
import type { Friend } from "./components/Friends.svelte"; import type { Friend } from "./components/Friends.svelte";
import type { SpectateType } from "./components/Spectate.svelte";
import type { ChannelsType } from "./components/Channels.svelte"; import type { ChannelsType } from "./components/Channels.svelte";
import { store, getUser, login, API_URL } from "./Auth"; import { store, getUser, login, API_URL } from "./Auth";
import FakeLogin from "./FakeLogin.svelte"; import FakeLogin from "./FakeLogin.svelte";
// Single Page Application config
let appState: string = APPSTATE.HOME;
history.replaceState({ appState: "" }, "", "/");
window.onpopstate = (e: PopStateEvent) => {
if (e.state) {
appState = e.state.appState;
}
};
function resetAppState() {
setAppState(APPSTATE.HOME);
}
function setAppState(newState: APPSTATE | string) {
if (newState === appState) return;
appState = newState;
history.pushState({ appState }, "", appState);
}
// PROFILE // PROFILE
onMount(() => { onMount(() => {
getUser(); getUser();
@ -27,16 +61,13 @@
setInterval(() => { setInterval(() => {
getUser(); getUser();
}, 15000); }, 15000);
let isProfileOpen = false;
function clickProfile() { function clickProfile() {
isProfileOpen = true; setAppState(APPSTATE.PROFILE);
} }
let userProfile: Player; let userProfile: Player;
let isIdProfileOpen = false;
async function openIdProfile(event: CustomEvent<string>) { async function openIdProfile(event: CustomEvent<string>) {
console.log("Opening profile: " + event.detail); console.log("Opening profile: " + event.detail);
isIdProfileOpen = true;
const res = await fetch(API_URL + "/user/" + event.detail, { const res = await fetch(API_URL + "/user/" + event.detail, {
method: "get", method: "get",
mode: "cors", mode: "cors",
@ -45,13 +76,13 @@
referrerPolicy: "no-referrer", referrerPolicy: "no-referrer",
}); });
userProfile = await res.json(); userProfile = await res.json();
setAppState(APPSTATE.PROFILE_ID);
} }
// HISTORY // HISTORY
let matches: Array<Match>; let matches: Array<Match>;
let isHistoryOpen = false;
async function clickHistory() { async function clickHistory() {
isHistoryOpen = true; setAppState(APPSTATE.HISTORY);
matches = await getHistory(); matches = await getHistory();
} }
@ -83,9 +114,8 @@
return await response.json(); return await response.json();
} }
let isFriendOpen = false;
async function clickFriends() { async function clickFriends() {
isFriendOpen = true; setAppState(APPSTATE.FRIENDS);
friends = await getFriends(); friends = await getFriends();
invits = await getInvits(); invits = await getInvits();
friendsInterval = setInterval(async () => { friendsInterval = setInterval(async () => {
@ -94,24 +124,9 @@
}, 5000); }, 5000);
} }
// SPECTATE
let isSpectateOpen = false;
function clickSpectate() {
isSpectateOpen = true;
}
let spectate: Array<SpectateType> = [
{ player1: "Alice", player2: "Bob", id: "1" },
{ player1: "Alice", player2: "Bob", id: "4" },
{ player1: "Alice", player2: "Bob", id: "6" },
{ player1: "Alice", player2: "Bob", id: "8" },
{ player1: "Alice", player2: "Bob", id: "2" },
{ player1: "Alice", player2: "Bob", id: "3" },
];
// CHANNELS // CHANNELS
let isChannelsOpen = false;
function clickChannels() { function clickChannels() {
isChannelsOpen = true; setAppState(APPSTATE.CHANNELS);
} }
let channels: Array<ChannelsType> = [ let channels: Array<ChannelsType> = [
{ id: "1", name: "General", messages: [], privacy: "public", password: "" }, { id: "1", name: "General", messages: [], privacy: "public", password: "" },
@ -127,8 +142,10 @@
let selectedChannel: ChannelsType; let selectedChannel: ChannelsType;
const handleSelectChannel = (channel: ChannelsType) => { const handleSelectChannel = (channel: ChannelsType) => {
selectedChannel = channel; selectedChannel = channel;
setAppState(APPSTATE.CHANNELS + "#" + channel.name);
}; };
// LEADERBOARD
let leaderboard: Array<Player> = []; let leaderboard: Array<Player> = [];
export async function getLeader(): Promise<Player[]> { export async function getLeader(): Promise<Player[]> {
@ -139,11 +156,9 @@
return await response.json(); return await response.json();
} }
// LEADERBOARD
let isLeaderboardOpen = false;
async function clickLeaderboard() { async function clickLeaderboard() {
isLeaderboardOpen = true;
leaderboard = await getLeader(); leaderboard = await getLeader();
setAppState(APPSTATE.LEADERBOARD);
} }
// GAME // GAME
@ -174,15 +189,14 @@
{clickProfile} {clickProfile}
{clickHistory} {clickHistory}
{clickFriends} {clickFriends}
{clickSpectate}
{clickChannels} {clickChannels}
{clickLeaderboard} {clickLeaderboard}
/> />
{#if isChannelsOpen} {#if appState.includes(APPSTATE.CHANNELS)}
{#if selectedChannel} {#if appState.replace(APPSTATE.CHANNELS, "") !== ""}
<div <div
on:click={() => (selectedChannel = undefined)} on:click={() => setAppState(APPSTATE.CHANNELS)}
on:keydown={() => (selectedChannel = undefined)} on:keydown={() => setAppState(APPSTATE.CHANNELS)}
> >
<Chat <Chat
chatMessages={selectedChannel.messages} chatMessages={selectedChannel.messages}
@ -191,67 +205,43 @@
on:invite-to-game={pong.inviteToGame} on:invite-to-game={pong.inviteToGame}
/> />
</div> </div>
{/if} {:else}
{#if !selectedChannel} <div on:click={resetAppState} on:keydown={resetAppState}>
<div
on:click={() => (isChannelsOpen = false)}
on:keydown={() => (isChannelsOpen = false)}
>
<Channels {channels} onSelectChannel={handleSelectChannel} /> <Channels {channels} onSelectChannel={handleSelectChannel} />
</div> </div>
{/if} {/if}
{/if} {/if}
{#if isSpectateOpen} {#if appState === APPSTATE.LEADERBOARD}
<div <div on:click={resetAppState} on:keydown={resetAppState}>
on:click={() => (isSpectateOpen = false)}
on:keydown={() => (isSpectateOpen = false)}
>
<Spectate {spectate} />
</div>
{/if}
{#if isLeaderboardOpen}
<div
on:click={() => (isLeaderboardOpen = false)}
on:keydown={() => (isLeaderboardOpen = false)}
>
<Leaderboard {leaderboard} /> <Leaderboard {leaderboard} />
</div> </div>
{/if} {/if}
{#if isFriendOpen} {#if appState === APPSTATE.FRIENDS}
<div <div
on:click={() => { on:click={() => {
isFriendOpen = false; resetAppState();
clearInterval(friendsInterval); clearInterval(friendsInterval);
}} }}
on:keydown={() => { on:keydown={() => {
isFriendOpen = false; resetAppState();
clearInterval(friendsInterval); clearInterval(friendsInterval);
}} }}
> >
<Friends {friends} {invits} /> <Friends {friends} {invits} />
</div> </div>
{/if} {/if}
{#if isHistoryOpen} {#if appState === APPSTATE.HISTORY}
<div <div on:click={resetAppState} on:keydown={resetAppState}>
on:click={() => (isHistoryOpen = false)}
on:keydown={() => (isHistoryOpen = false)}
>
<MatchHistory {matches} /> <MatchHistory {matches} />
</div> </div>
{/if} {/if}
{#if isProfileOpen} {#if appState === APPSTATE.PROFILE}
<div <div on:click={resetAppState} on:keydown={resetAppState}>
on:click={() => (isProfileOpen = false)}
on:keydown={() => (isProfileOpen = false)}
>
<Profile user={$store} edit={1} /> <Profile user={$store} edit={1} />
</div> </div>
{/if} {/if}
{#if isIdProfileOpen} {#if appState === APPSTATE.PROFILE_ID}
<div <div on:click={resetAppState} on:keydown={resetAppState}>
on:click={() => (isIdProfileOpen = false)}
on:keydown={() => (isIdProfileOpen = false)}
>
<Profile user={userProfile} edit={0} /> <Profile user={userProfile} edit={0} />
</div> </div>
{/if} {/if}
@ -261,7 +251,7 @@
<button on:click={impersonate}>Impersonate</button> <button on:click={impersonate}>Impersonate</button>
<button on:click={() => (fakemenu = false)}>No impersonate</button> <button on:click={() => (fakemenu = false)}>No impersonate</button>
{:else} {:else}
<Pong bind:this={pong} {fakeUser} /> <Pong bind:this={pong} {appState} {setAppState} {fakeUser} />
{/if} {/if}
{/if} {/if}
</div> </div>

6
front/volume/src/components/NavBar.svelte

@ -16,7 +16,6 @@
export let clickProfile = () => {}; export let clickProfile = () => {};
export let clickHistory = () => {}; export let clickHistory = () => {};
export let clickFriends = () => {}; export let clickFriends = () => {};
export let clickSpectate = () => {};
export let clickChannels = () => {}; export let clickChannels = () => {};
export let clickLeaderboard = () => {}; export let clickLeaderboard = () => {};
</script> </script>
@ -29,11 +28,6 @@
<button on:click={clickLeaderboard}> Leaderboard </button> <button on:click={clickLeaderboard}> Leaderboard </button>
</li> </li>
{/if} {/if}
{#if link.text === "Spectate"}
<li>
<button on:click={clickSpectate}> Spectate </button>
</li>
{/if}
{#if link.text === "Channels"} {#if link.text === "Channels"}
<li> <li>
<button on:click={clickChannels}> Channels </button> <button on:click={clickChannels}> Channels </button>

48
front/volume/src/components/Pong/Pong.svelte

@ -10,22 +10,22 @@
import type { MatchmakingDto } from "./dtos/MatchmakingDto"; import type { MatchmakingDto } from "./dtos/MatchmakingDto";
import { getUser, store } from "../../Auth"; import { getUser, store } from "../../Auth";
import ColorPicker from "./ColorPicker.svelte"; import ColorPicker from "./ColorPicker.svelte";
import { APPSTATE } from "../../App.svelte";
export function inviteToGame(event: CustomEvent<string>) { export function inviteToGame(event: CustomEvent<string>) {
createMatchWindow = true; setAppState(APPSTATE.CREATE_GAME);
invitedUsername = event.detail; invitedUsername = event.detail;
} }
export let fakeUser: boolean; export let fakeUser: boolean;
export let appState: string;
export let setAppState: (newState: APPSTATE | string) => void;
const SERVER_URL = `ws://${import.meta.env.VITE_HOST}:${ const SERVER_URL = `ws://${import.meta.env.VITE_HOST}:${
import.meta.env.VITE_BACK_PORT import.meta.env.VITE_BACK_PORT
}`; }`;
let createMatchWindow: boolean = false;
let spectateWindow: boolean = false;
let gamePlaying: boolean = false; let gamePlaying: boolean = false;
let matchmaking: boolean = false;
let connected: boolean = false; let connected: boolean = false;
let loggedIn: boolean = false; let loggedIn: boolean = false;
let failedLogIn: boolean = false; let failedLogIn: boolean = false;
@ -87,7 +87,11 @@
} else if (event == GAME_EVENTS.CREATE_GAME) { } else if (event == GAME_EVENTS.CREATE_GAME) {
if (data) gamePlaying = true; if (data) gamePlaying = true;
} else if (event == GAME_EVENTS.MATCHMAKING) { } else if (event == GAME_EVENTS.MATCHMAKING) {
matchmaking = data.matchmaking; if (data.matchmaking && appState !== APPSTATE.MATCHMAKING) {
setAppState(APPSTATE.MATCHMAKING);
} else if (!data.matchmaking && appState === APPSTATE.MATCHMAKING) {
setAppState(APPSTATE.HOME);
}
} else if (event == GAME_EVENTS.SPECTATE) { } else if (event == GAME_EVENTS.SPECTATE) {
if (data) { if (data) {
gamePlaying = true; gamePlaying = true;
@ -141,9 +145,7 @@
} }
function resetMenus() { function resetMenus() {
createMatchWindow = false; setAppState(APPSTATE.HOME);
spectateWindow = false;
matchmaking = false;
game.youAreReady = false; game.youAreReady = false;
} }
@ -152,6 +154,16 @@
game.updateColors(elementsColor, backgroundColor); game.updateColors(elementsColor, backgroundColor);
} }
} }
$: {
if (socket && socket.readyState) {
if (appState === APPSTATE.MATCHMAKING) {
startMatchmaking();
} else if (appState !== APPSTATE.MATCHMAKING) {
stopMatchmaking();
}
}
}
</script> </script>
<main> <main>
@ -161,30 +173,32 @@
{:else if loggedIn} {:else if loggedIn}
<h1>Choose a gamemode</h1> <h1>Choose a gamemode</h1>
<button on:click={startMatchmaking}>Matchmaking</button> <button on:click={startMatchmaking}>Matchmaking</button>
<button on:click={() => (createMatchWindow = true)} <button on:click={() => setAppState(APPSTATE.CREATE_GAME)}
>Play with a friend</button >Play with a friend</button
> >
<button on:click={() => (spectateWindow = true)}>Spectate a friend</button> <button on:click={() => setAppState(APPSTATE.SPECTATE_GAME)}
>Spectate a friend</button
>
<label for="colorPicker">Elements color:</label> <label for="colorPicker">Elements color:</label>
<ColorPicker bind:color={elementsColor} /> <ColorPicker bind:color={elementsColor} />
<label for="colorPicker">Background color:</label> <label for="colorPicker">Background color:</label>
<ColorPicker bind:color={backgroundColor} /> <ColorPicker bind:color={backgroundColor} />
{#if matchmaking} {#if appState === APPSTATE.MATCHMAKING}
<div on:click={stopMatchmaking} on:keydown={stopMatchmaking}> <div on:click={stopMatchmaking} on:keydown={stopMatchmaking}>
<Matchmaking {stopMatchmaking} /> <Matchmaking {stopMatchmaking} />
</div> </div>
{:else if createMatchWindow} {:else if appState === APPSTATE.CREATE_GAME}
<div <div
on:click={() => (createMatchWindow = false)} on:click={() => setAppState(APPSTATE.HOME)}
on:keydown={() => (createMatchWindow = false)} on:keydown={() => setAppState(APPSTATE.HOME)}
> >
<GameCreation {socket} {invitedUsername} /> <GameCreation {socket} {invitedUsername} />
</div> </div>
{:else if spectateWindow} {:else if appState === APPSTATE.SPECTATE_GAME}
<div <div
on:click={() => (spectateWindow = false)} on:click={() => setAppState(APPSTATE.HOME)}
on:keydown={() => (spectateWindow = false)} on:keydown={() => setAppState(APPSTATE.HOME)}
> >
<SpectateFriend {socket} /> <SpectateFriend {socket} />
</div> </div>

55
front/volume/src/components/Spectate.svelte

@ -1,55 +0,0 @@
<script lang="ts" context="module">
export interface SpectateType {
id: string;
player1: string;
player2: string;
}
</script>
<script lang="ts">
export let spectate: Array<SpectateType> = [];
export let watch = (id: string) => {
console.log(id);
};
</script>
<div class="overlay">
<div class="spectate" on:click|stopPropagation on:keydown|stopPropagation>
<div>
{#if spectate.length > 0}
<h2>Monkey spectating</h2>
{#each spectate.slice(0, 10) as _spectate}
<li>
<span>{_spectate.player1} VS {_spectate.player2}</span>
<button on:click={() => watch(_spectate.id)}>Spectate</button>
</li>
{/each}
{:else}
<p>No matches to spectate</p>
{/if}
</div>
</div>
</div>
<style>
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9998;
display: flex;
justify-content: center;
align-items: center;
}
.spectate {
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
padding: 1rem;
width: 300px;
}
</style>
Loading…
Cancel
Save