diff --git a/css/boxes.css b/css/boxes.css index 9dee64a..bc8bf4c 100644 --- a/css/boxes.css +++ b/css/boxes.css @@ -1,6 +1,9 @@ .boxes-container { max-width: 800px; - margin: 100px auto; + margin: 0 auto; + border: #4a7c59 1px dotted; + border-radius: 4px; + } .boxes input{ margin: 0; diff --git a/js/boxes.js b/js/boxes.js index e3f972d..788487c 100644 --- a/js/boxes.js +++ b/js/boxes.js @@ -1,6 +1,6 @@ "use strict"; (() => { - const socket = getSocket("/boxes/ws"); + const socket = initSocket("/boxes/ws"); const deserializeBox = (msg) => { msg = msg.replaceAll("b:", ""); const parts = msg.split(":"); @@ -21,8 +21,8 @@ return; } }; - socket.addEventListener("message", (event) => { - const instructions = event.data.split("\n"); + socket.addMessageListener((data) => { + const instructions = data.split("\n"); instructions.forEach(handleInstruction); }); document.querySelectorAll(".boxes input").forEach((input) => { @@ -33,26 +33,25 @@ socket.send("b:" + id + ":" + value); }); }); - // const autoPlayEl = document.querySelector("#randomize"); + // const autoPlayEl = document.querySelector("#randomize") as CheckboxEl; // autoPlayEl?.addEventListener("click", (e) => socket.send("r:1000")); - // var golTimer = undefined; - // const handleGol = (el) => { - // if (el.checked) { - // golTimer = setInterval(() => { - // socket.send("gol"); - // }, 500); - // } - // else { - // clearInterval(golTimer); - // } + // 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"); + // const golEl = document.querySelector("#game-of-life") as CheckboxEl; // handleGol(golEl); - // golEl.addEventListener("change", (e) => handleGol(e.target)); - const container = document.querySelector('.boxes'); + // golEl.addEventListener("change", (e) => handleGol(e.target as CheckboxEl)); + const container = document.querySelector(".boxes"); const resizeObserver = new ResizeObserver((entries) => { const entry = entries.at(0); - container.style.height = String(entry?.contentRect.width ?? 500) + 'px'; + container.style.height = String(entry?.contentRect.width ?? 500) + "px"; }); resizeObserver.observe(container); })(); diff --git a/js/boxes.ts b/js/boxes.ts index 5b35853..395076d 100644 --- a/js/boxes.ts +++ b/js/boxes.ts @@ -5,7 +5,7 @@ type Box = { }; (() => { - const socket = getSocket("/boxes/ws"); + const socket = initSocket("/boxes/ws"); const deserializeBox = (msg: string): Box => { msg = msg.replaceAll("b:", ""); @@ -31,8 +31,8 @@ type Box = { } }; - socket.addEventListener("message", (event: MessageEvent) => { - const instructions = event.data.split("\n"); + socket.addMessageListener((data) => { + const instructions = data.split("\n"); instructions.forEach(handleInstruction); }); @@ -46,29 +46,28 @@ type Box = { }); }); - const autoPlayEl = document.querySelector("#randomize") as CheckboxEl; - autoPlayEl?.addEventListener("click", (e) => socket.send("r:1000")); + // 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); - } - }; + // 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 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 container = document.querySelector(".boxes") as HTMLDivElement; const resizeObserver = new ResizeObserver((entries) => { const entry = entries.at(0); - container.style.height = String(entry?.contentRect.width ?? 500) + 'px'; + container.style.height = String(entry?.contentRect.width ?? 500) + "px"; }); resizeObserver.observe(container); })(); diff --git a/js/draw.js b/js/draw.js index 3b064db..a36fe59 100644 --- a/js/draw.js +++ b/js/draw.js @@ -7,7 +7,7 @@ const emitter = mitt(); let drawing = false; let previous = null; - const socket = getSocket("/draw/ws"); + const socket = initSocket("/draw/ws"); const serializeDraw = ({ from, to }) => `${from.x},${from.y},${to.x},${to.y}`; const deserializeDraw = (message) => { const parts = message.split(","); @@ -69,10 +69,10 @@ }; emitter.on("mouseDraw", render); emitter.on("netDraw", render); - socket.addEventListener("message", (event) => { - if (event.data === "ping" || event.data.startsWith("pong")) + socket.addMessageListener((data) => { + if (data === "ping" || data.startsWith("pong")) return; - emitter.emit("netDraw", deserializeDraw(event.data)); + emitter.emit("netDraw", deserializeDraw(data)); }); const resizeObserver = new ResizeObserver((entries) => { const entry = entries.at(0); diff --git a/js/draw.ts b/js/draw.ts index 22639b1..1c7ca7f 100644 --- a/js/draw.ts +++ b/js/draw.ts @@ -24,7 +24,7 @@ let drawing = false; let previous: DrawPoint | null = null; - const socket = getSocket("/draw/ws"); + const socket = initSocket("/draw/ws"); const serializeDraw = ({ from, to }: DrawEvent) => `${from.x},${from.y},${to.x},${to.y}`; @@ -104,9 +104,9 @@ emitter.on("mouseDraw", render); emitter.on("netDraw", render); - socket.addEventListener("message", (event) => { - if (event.data === "ping" || event.data.startsWith("pong")) return; - emitter.emit("netDraw", deserializeDraw(event.data)); + socket.addMessageListener( (data) => { + if (data === "ping" || data.startsWith("pong")) return; + emitter.emit("netDraw", deserializeDraw(data)); }); const resizeObserver = new ResizeObserver((entries) => { diff --git a/js/ws.js b/js/ws.js index 8fde816..3c78cc9 100644 --- a/js/ws.js +++ b/js/ws.js @@ -1,7 +1,34 @@ "use strict"; -const getSocket = (url) => { - let ws = new WebSocket(url); - ws.onclose = () => setTimeout(() => (ws = getSocket(url)), 100); - ws.onerror = () => ws.close(); - return ws; +const sockets = {}; +const isSocketOpen = (url) => { + return sockets[url]?._ws?.readyState === WebSocket.OPEN; +}; +const initSocket = (url) => { + if (sockets[url]) { + if (isSocketOpen(url)) { + return sockets[url]; + } + else { + sockets[url]._ws.close(); + } + } + const ws = new WebSocket(url); + const socket = { + send: (data) => { + sockets[url]._ws.send(data); + }, + addMessageListener: (listener) => { + socket._listeners.push(listener); + }, + _listeners: sockets[url]?._listeners ?? [], + _ws: ws, + }; + ws.onerror = () => ws.close(); + ws.onclose = () => initSocket(url); + ws.onmessage = (event) => { + console; + sockets[url]._listeners.forEach((listener) => listener(event.data)); + }; + sockets[url] = socket; + return sockets[url]; }; diff --git a/js/ws.ts b/js/ws.ts index 5995bc1..3abcd8d 100644 --- a/js/ws.ts +++ b/js/ws.ts @@ -1,8 +1,46 @@ -const getSocket = (url: string): WebSocket => { - let ws = new WebSocket(url); +const sockets: Record = {}; - ws.onclose = () => setTimeout(() => (ws = getSocket(url)), 100); - ws.onerror = () => ws.close(); +type MySocket = { + send: (data: string) => void; + addMessageListener: (listener: (event: string) => void) => void; + _listeners: ((event: string) => void)[]; + _ws: WebSocket; +}; - return ws; - }; \ No newline at end of file +const isSocketOpen = (url: string): boolean => { + return sockets[url]?._ws?.readyState === WebSocket.OPEN; +}; + +const initSocket = (url: string): MySocket => { + if (sockets[url]) { + if (isSocketOpen(url)) { + return sockets[url]; + } else { + sockets[url]._ws.close(); + } + } + + const ws = new WebSocket(url); + const socket: MySocket = { + send: (data: string) => { + sockets[url]._ws.send(data); + }, + addMessageListener: (listener: (event: string) => void) => { + socket._listeners.push(listener); + }, + _listeners: sockets[url]?._listeners ?? [], + _ws: ws, + }; + + + ws.onerror = () => ws.close(); + ws.onclose = () => initSocket(url); + ws.onmessage = (event) => { + console + sockets[url]._listeners.forEach((listener) => listener(event.data)); + }; + + sockets[url] = socket; + + return sockets[url]; +};