Migrate game master client to alpine

This commit is contained in:
Oliver Rümpelein 2021-09-26 14:59:37 +02:00
parent b4c0fa9c66
commit 814d2885ed
9 changed files with 114 additions and 79 deletions

View file

@ -0,0 +1,14 @@
package de.pheerai.buzzer.alpine
import kotlinx.html.*
open class TEMPLATE(
initialAttributes: Map<String, String>,
override val consumer: TagConsumer<*>,
) : HTMLTag("template", consumer, initialAttributes, null, false, false),
HtmlBlockTag
@HtmlTagMarker
inline fun FlowContent.template(classes: String? = null, crossinline block: TEMPLATE.() -> Unit = {}): Unit = TEMPLATE(
attributesMapOf("class", classes), consumer
).visit(block)

View file

@ -1,21 +0,0 @@
package de.pheerai.buzzer.clients
import kotlinx.html.*
fun HTML.createAdminDocument() {
head {
meta { charset = "UTF-8" }
title { +"JS Client" }
script { src = "https://code.jquery.com/jquery-3.6.0.min.js" }
script { src = "/assets/adminClient.js" }
}
body {
ol {
id = "usernames"
}
button {
onClick = "resetReceived()"
+"Reset"
}
}
}

View file

@ -0,0 +1,47 @@
package de.pheerai.buzzer.clients
import de.pheerai.buzzer.alpine.*
import kotlinx.html.*
fun HTML.createGameMasterDocument() {
head {
meta { charset = "UTF-8" }
title { +"JS Client" }
link(
href = "/assets/colors.css",
rel = "stylesheet",
type = "text/css"
)
script {
src = "https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
defer = true
}
script { src = "/assets/gameMasterClient.js" }
script { src = "/assets/buzzerWebSocket.js" }
}
body {
xData("{receivedNames: [], buzzerWebSocket: null}")
xInit(
//language=JavaScript
"""
() => {
startWebSocket('/socket/master', (ev) => {
receivedNames.push(ev.data)
});
}
""".trimIndent()
)
div(classes = "parent") {
button {
xOn("click", "receivedNames = []")
+"Reset"
}
ol {
template {
attributes["x-for"] = "name in receivedNames"
this@ol.li { xText("name") }
}
}
}
}
}

View file

@ -21,13 +21,23 @@ fun HTML.createPlayerDocument() {
src = "https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" src = "https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
defer = true defer = true
} }
script {
src = "/assets/buzzerWebSocket.js"
}
script { script {
src = "/assets/playerClient.js" src = "/assets/playerClient.js"
} }
} }
body { body {
div(classes = "parent") { div(classes = "parent") {
xInit("startWebSocket()") xInit(
"""
() => {
Alpine.data('buzzerWebSocket', null)
startWebSocket('/socket/player')
}
""".trimIndent()
)
xData("{playerName: \"\"}") xData("{playerName: \"\"}")
div(classes = "input") { div(classes = "input") {
label { +"Player" } label { +"Player" }

View file

@ -1,6 +1,6 @@
package de.pheerai.buzzer.routing package de.pheerai.buzzer.routing
import de.pheerai.buzzer.clients.createAdminDocument import de.pheerai.buzzer.clients.createGameMasterDocument
import de.pheerai.buzzer.clients.createPlayerDocument import de.pheerai.buzzer.clients.createPlayerDocument
import de.pheerai.buzzer.handlers.handleGameMasterSocket import de.pheerai.buzzer.handlers.handleGameMasterSocket
import de.pheerai.buzzer.handlers.handlePlayerSocket import de.pheerai.buzzer.handlers.handlePlayerSocket
@ -39,7 +39,7 @@ private fun Routing.clientRoutes() {
get("/client/master") { get("/client/master") {
call.respondHtml { call.respondHtml {
createAdminDocument() createGameMasterDocument()
} }
} }
} }

View file

@ -1,21 +0,0 @@
'use strict';
let adminSocket;
$.when($.ready).then(function () {
let protocolPrefix = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
adminSocket = new WebSocket(`${protocolPrefix}//${location.host}/socket/master`);
adminSocket.addEventListener('message', (ev) => {
console.log(`Received: ${ev.data}`)
appendUsername(ev.data)
});
});
function appendUsername(username) {
$('ol#usernames').append(`<li>${username}</li>`)
}
function resetReceived() {
$('ol#usernames').empty()
}

View file

@ -0,0 +1,34 @@
'use strict';
function startWebSocket(socketPath, messageHandler) {
const protocolPrefix = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
const webSocket = new WebSocket(`${protocolPrefix}//${location.host}${socketPath}`);
webSocket.onerror = (ev) => {
switch (ev.code) {
case 1000:
console.log("[WS]: Closed normally")
break
default:
console.log("[WS]: Closed abnormally")
reconnectWebSocket(socketPath, messageHandler);
}
};
webSocket.onclose = (ev) => {
switch (ev.code) {
case 'ECONNREFUSED':
reconnectWebSocket(socketPath, messageHandler);
break
default:
webSocket.onerror(ev);
}
};
webSocket.onmessage = messageHandler ? messageHandler : () => {};
Alpine.data.buzzerWebSocket = webSocket
}
function reconnectWebSocket(socketPath, messageHandler) {
setTimeout(() => {
console.log("[WS]: Reconnecting...")
startWebSocket(socketPath, messageHandler)
}, 2000)
}

View file

@ -0,0 +1,5 @@
'use strict';
function appendUsername(username) {
$('ol#usernames').append(`<li>${username}</li>`)
}

View file

@ -1,38 +1,5 @@
'use strict'; 'use strict';
let webSocket;
function startWebSocket() {
let protocolPrefix = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
webSocket = new WebSocket(`${protocolPrefix}//${location.host}/socket/player`);
webSocket.onerror = (ev) => {
switch (ev.code) {
case 1000:
console.log("[WS]: Closed normally")
break
default:
console.log("[WS]: Closed abnormally")
reconnectWebSocket();
}
};
webSocket.onclose = (ev) => {
switch (ev.code) {
case 'ECONNREFUSED':
reconnectWebSocket();
break
default:
webSocket.onerror(ev);
}
};
}
function reconnectWebSocket() {
setTimeout(() => {
console.log("[WS]: Reconnecting...")
startWebSocket()
}, 2000)
}
function sendUsername(username) { function sendUsername(username) {
if ( if (
username !== undefined username !== undefined
@ -40,7 +7,7 @@ function sendUsername(username) {
&& username !== '' && username !== ''
) { ) {
console.log(`Username: ${username}`); console.log(`Username: ${username}`);
webSocket.send(username); Alpine.data.buzzerWebSocket.send(username);
} else { } else {
alert("Please enter a name!"); alert("Please enter a name!");
} }