From 5b0b415240f76d4128012f3f0e42e1a94c9e179d Mon Sep 17 00:00:00 2001 From: Geoffrey Allott Date: Sat, 6 Feb 2021 00:32:04 +0000 Subject: [PATCH] site has login box and displays list of games --- site/index.html | 43 ++++++++++++- site/main.js | 51 ++++++++-------- site/modules/auth.js | 20 ++++++ site/modules/socket.js | 134 +++++++++++++++++++++++++++++++++++++++++ site/style.css | 96 +++++++++++++++++++++++++++++ 5 files changed, 318 insertions(+), 26 deletions(-) create mode 100644 site/modules/auth.js create mode 100644 site/modules/socket.js create mode 100644 site/style.css diff --git a/site/index.html b/site/index.html index da7e8f7..5dee3ab 100644 --- a/site/index.html +++ b/site/index.html @@ -2,9 +2,48 @@ - + + -

Pokerwave

+
+
+ + + + + +

+
+
+
+ +
diff --git a/site/main.js b/site/main.js index a99a9ff..662230a 100644 --- a/site/main.js +++ b/site/main.js @@ -1,35 +1,38 @@ -"use strict"; +import { Auth } from "./modules/auth.js"; +import { Socket } from "./modules/socket.js"; -var socket; +var sockets = []; -function socket_open() { - let proto = window.location.protocol === "https:" ? "wss:" : "ws:"; - let uri = proto + "//" + window.location.host + "/api"; - socket = new WebSocket(uri); - socket.onopen = socket_onopen; - socket.onmessage = socket_onmessage; +function hide_login() { + document.getElementById("login-background").classList.add("hidden"); } -function socket_onopen() { - console.log("WebSocket connected"); - socket_send({type: "Login", username: "geoff"}); -} - -function socket_send(object) { - console.log(">>", object); - socket.send(JSON.stringify(object)); +function show_login(error) { + if (error) { + document.getElementById("login-error").classList.remove("hidden"); + document.getElementById("login-error").innerText = error; + } else { + document.getElementById("login-error").classList.add("hidden"); + document.getElementById("login-error").innerText = ""; + } + document.getElementById("login-background").classList.remove("hidden"); + document.getElementById("login-button").onclick = login; + document.getElementById("password-input").onchange = login; } -function socket_onmessage(msg) { - var message = JSON.parse(msg.data); - console.log("<<", message); - switch (message.type) { - case "LoginAuthChallenge": - socket_send({type: "LoginAuthResponse", signature: "hunter2"}); - break; +function login() { + var username = document.getElementById("username-input").value; + var password = document.getElementById("password-input").value; + delete document.getElementById("login-button").onclick; + delete document.getElementById("password-input").onchange; + var auth = new Auth(username, password); + for (var socket of sockets) { + socket.login(auth); } } window.onload = function() { - socket_open(); + var container = document.getElementById("game-tile-background"); + sockets.push(new Socket(container)); + show_login(); }; diff --git a/site/modules/auth.js b/site/modules/auth.js new file mode 100644 index 0000000..0a6d7cb --- /dev/null +++ b/site/modules/auth.js @@ -0,0 +1,20 @@ +export class Auth { + constructor(username, password) { + this.username = username; + this.password = password; + } + + login_message() { + return { + type: "Login", + username: this.username + }; + } + + challenge_response(challenge) { + return { + type: "LoginAuthResponse", + signature: this.password + }; + } +} diff --git a/site/modules/socket.js b/site/modules/socket.js new file mode 100644 index 0000000..342677f --- /dev/null +++ b/site/modules/socket.js @@ -0,0 +1,134 @@ +export class Socket { + constructor(container) { + this.container = container; + let proto = window.location.protocol === "https:" ? "wss:" : "ws:"; + let uri = proto + "//" + window.location.host + "/api"; + this.socket = new WebSocket(uri); + this.socket.onopen = this.onopen.bind(this); + this.socket.onmessage = this.onmessage.bind(this); + this.socket.onclose = this.onclose.bind(this); + this.state = "Connecting"; + } + + onopen() { + console.log("WebSocket connected"); + this.state = "Connected"; + } + + send(object) { + console.log(">>", object); + this.socket.send(JSON.stringify(object)); + } + + login(auth) { + this.auth = auth; + this.send(auth.login_message()); + this.state = "LoginSent"; + } + + onmessage(msg) { + var message = JSON.parse(msg.data); + console.log("<<", message); + switch (message.type) { + case "LoginAuthChallenge": + this.send(this.auth.challenge_response(message.challenge)); + this.state = "LoginAuthResponseSent"; + break; + case "LoginFailure": + this.auth = null; + this.show_login(message.reason); + this.state = "Connected"; + break; + case "LoginSuccess": + this.hide_login(); + this.send({type: "JoinLobby", filter: ""}); + this.state = "JoinLobbySent"; + break; + case "JoinLobbySuccess": + this.create_game_list(); + this.games = message.games; + this.redraw_games(); + this.state = "InLobby"; + break; + case "AddGame": + this.add_game(message.game); + break; + case "LogoutSuccess": + this.auth = null; + this.show_login(); + this.state = "Connected"; + break; + } + } + + hide_login() { + document.getElementById("login-background").classList.add("hidden"); + } + + show_login(error) { + if (error) { + document.getElementById("login-error").classList.remove("hidden"); + document.getElementById("login-error").innerText = error; + } else { + document.getElementById("login-error").classList.add("hidden"); + document.getElementById("login-error").innerText = ""; + } + document.getElementById("login-background").classList.remove("hidden"); + document.getElementById("login-button").onclick = login; + document.getElementById("password-input").onchange = login; + } + + game_element(game) { + console.log("getting game element for ", game); + var game_element = document.createElement("div"); + game_element.classList.add("game-summary"); + var id = document.createElement("div"); + id.innerText = "#" + game.id; + id.classList.add("game-id"); + game_element.appendChild(id); + var title = document.createElement("div"); + title.innerText = game.settings.format; // TODO + title.classList.add("game-title"); + game_element.appendChild(title); + var format = document.createElement("div"); + format.innerText = game.settings.format; + format.classList.add("game-format"); + game_element.appendChild(format); + var settings = document.createElement("ul"); + settings.classList.add("game-settings"); + for (var setting of Object.keys(game.settings)) { + if (setting !== "id" && setting !== "title" && setting !== "format") { + var li = document.createElement("li"); + li.innerText = setting + ": " + game.settings[setting]; + settings.appendChild(li); + } + } + game_element.appendChild(settings); + return game_element; + } + + add_game(game) { + this.games.push(game); + var game_element = this.game_element(game); + this.game_list.prepend(game_element); + } + + create_game_list() { + this.container.textContent = ""; + this.game_list = document.createElement("div"); + this.game_list.classList.add("game-list"); + this.container.append(this.game_list); + } + + redraw_games() { + for (var game of this.games) { + var game_element = this.game_element(game); + this.game_list.prepend(game_element); + } + } + + onclose() { + console.error("Websocket closed unexpectedly"); + this.state = "Disconnected"; + } +} diff --git a/site/style.css b/site/style.css new file mode 100644 index 0000000..3d9d22a --- /dev/null +++ b/site/style.css @@ -0,0 +1,96 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; +} + +.hidden { + display: none !important; +} + +#login-background { + background-color: rgba(0, 0, 100, 0.5); + width: 100%; + height: 100%; + position: fixed; + display: grid; + grid: 1fr 1fr 1fr / 1fr 1fr 1fr; +} + +#login { + grid-column: 2 / 3; + grid-row: 2 / 3; + background-color: skyblue; + border-radius: 2vmax; + padding: 4vmax; + display: grid; + grid: 1fr; + font-size: 4vmax; +} + +#login > label { + font-family: monospace; +} + +#login > input { + font-size: inherit; + margin-bottom: 1vmax; +} + +#login > button { + font-size: inherit; + margin-top: 2vmax; +} + +#login > #login-error { + font-size: 2vmax; + color: red; + margin-bottom: 0; +} + +#game-tile-background { + width: 100%; + height: 100%; + display: grid; + grid: 1fr / 1fr; +} + +.game-list { + width: 100%; + display: grid; + grid-auto-rows: 30vw; +} + +.game-summary { + border: 1px solid grey; + border-bottom: none; + font-family: sans; + font-size: 4vw; + display: grid; + grid: 'id title blank' + 'format format format' + 'settings settings settings' + 'settings settings settings'; +} + +.game-id { + font-style: italic; + color: grey; + grid-area: id; +} + +.game-title { + text-align: center; + font-weight: bold; + grid-area: title; +} + +.game-format { + text-align: left; + margin-left: 5vw; + grid-area: format; +} + +.game-settings { + grid-area: settings; +} -- 2.34.1