From c350501f296176c1cf00a94f4588bfee3aa7e06b Mon Sep 17 00:00:00 2001 From: JurajKubrican Date: Mon, 4 Aug 2025 20:05:08 +0200 Subject: [PATCH] live users --- css/boxes.css | 6 ++++-- js/boxes.js | 36 +++++++++++++++--------------------- js/boxes.ts | 43 ++++++++++++++++++------------------------- src/boxes/boxes.go | 11 ++++++++--- views/boxes.html | 5 +++++ 5 files changed, 50 insertions(+), 51 deletions(-) diff --git a/css/boxes.css b/css/boxes.css index bc8bf4c..1d8031d 100644 --- a/css/boxes.css +++ b/css/boxes.css @@ -10,8 +10,6 @@ appearance: none; -webkit-appearance: none; -moz-appearance: none; - width: 20px; - height: 20px; background: transparent; border: none; position: relative; @@ -50,4 +48,8 @@ display: grid; grid-template-columns: repeat(32, 1fr); /* 32 equal columns */ grid-template-rows: repeat(32, 1fr); /* 32 equal rows */ +} + +.counter-label { + color: #4a7c59; } \ No newline at end of file diff --git a/js/boxes.js b/js/boxes.js index 788487c..ceb6948 100644 --- a/js/boxes.js +++ b/js/boxes.js @@ -20,34 +20,28 @@ }); return; } + if (instruction.startsWith("u:")) { + const items = instruction.split(":"); + const el = document.getElementById("counter"); + el.innerText = items[1]; + const el2 = document.getElementById("ips"); + el2.innerText = items[2].replaceAll(",", "\n"); + return; + } }; socket.addMessageListener((data) => { const instructions = data.split("\n"); instructions.forEach(handleInstruction); }); + const handleBoxChange = (event) => { + const target = event.target; + const id = target?.id.split("-")[1]; + const value = target.checked ? "+" : "-"; + socket.send("b:" + id + ":" + value); + }; document.querySelectorAll(".boxes input").forEach((input) => { - input.addEventListener("change", (event) => { - const target = event.target; - const id = target?.id.split("-")[1]; - const value = target.checked ? "+" : "-"; - socket.send("b:" + id + ":" + value); - }); + input.addEventListener("change", handleBoxChange); }); - // const autoPlayEl = document.querySelector("#randomize") as CheckboxEl; - // autoPlayEl?.addEventListener("click", (e) => socket.send("r:1000")); - // var golTimer: number | undefined = undefined; - // const handleGol = (el: CheckboxEl) => { - // if (el.checked) { - // golTimer = setInterval(() => { - // socket.send("gol"); - // }, 500); - // } else { - // clearInterval(golTimer); - // } - // }; - // const golEl = document.querySelector("#game-of-life") as CheckboxEl; - // handleGol(golEl); - // golEl.addEventListener("change", (e) => handleGol(e.target as CheckboxEl)); const container = document.querySelector(".boxes"); const resizeObserver = new ResizeObserver((entries) => { const entry = entries.at(0); diff --git a/js/boxes.ts b/js/boxes.ts index 395076d..d260c1d 100644 --- a/js/boxes.ts +++ b/js/boxes.ts @@ -29,6 +29,16 @@ type Box = { }); return; } + if (instruction.startsWith("u:")) { + const items = instruction.split(":"); + + const el = document.getElementById("counter") as CheckboxEl; + el.innerText = items[1]; + const el2 = document.getElementById("ips") as CheckboxEl; + el2.innerText = items[2].replaceAll(",", "
"); + + return; + } }; socket.addMessageListener((data) => { @@ -36,34 +46,17 @@ type Box = { instructions.forEach(handleInstruction); }); + const handleBoxChange = (event: Event) => { + const target = event.target as CheckboxEl; + const id = target?.id.split("-")[1]; + const value = target.checked ? "+" : "-"; + socket.send("b:" + id + ":" + value); + } + document.querySelectorAll(".boxes input").forEach((input) => { - input.addEventListener("change", (event) => { - const target = event.target as CheckboxEl; - - const id = target?.id.split("-")[1]; - const value = target.checked ? "+" : "-"; - socket.send("b:" + id + ":" + value); - }); + input.addEventListener("change", handleBoxChange); }); - // const autoPlayEl = document.querySelector("#randomize") as CheckboxEl; - // autoPlayEl?.addEventListener("click", (e) => socket.send("r:1000")); - - // var golTimer: number | undefined = undefined; - // const handleGol = (el: CheckboxEl) => { - // if (el.checked) { - // golTimer = setInterval(() => { - // socket.send("gol"); - // }, 500); - // } else { - // clearInterval(golTimer); - // } - // }; - - // const golEl = document.querySelector("#game-of-life") as CheckboxEl; - // handleGol(golEl); - // golEl.addEventListener("change", (e) => handleGol(e.target as CheckboxEl)); - const container = document.querySelector(".boxes") as HTMLDivElement; const resizeObserver = new ResizeObserver((entries) => { const entry = entries.at(0); diff --git a/src/boxes/boxes.go b/src/boxes/boxes.go index 45e2ef2..022a0d5 100644 --- a/src/boxes/boxes.go +++ b/src/boxes/boxes.go @@ -12,7 +12,7 @@ import ( ) var ( - wsConnections = make(map[*websocket.Conn]bool) + wsConnections = make(map[*websocket.Conn]string) wsMutex sync.Mutex ) @@ -161,11 +161,16 @@ func handleMessage(msg string, ws *websocket.Conn) error { func InitWs(c echo.Context) error { websocket.Handler(func(ws *websocket.Conn) { wsMutex.Lock() - wsConnections[ws] = true + wsConnections[ws] = c.RealIP() wsMutex.Unlock() boxes := GetBoxes() - msg := "" + msg := "u:" + strconv.Itoa(len(wsConnections)) + ":" + for _, addr := range wsConnections { + msg += addr + "," + } + msg += "\n" + for _, box := range boxes { msg += box.serialize() } diff --git a/views/boxes.html b/views/boxes.html index 7be9f47..8dc2385 100644 --- a/views/boxes.html +++ b/views/boxes.html @@ -1,5 +1,10 @@ {{block "boxes" .}} + + +Currently Online: +
+
{{range .Boxes}}