From cd21e4e8bd21d5c7bda4f48f81dd72094edc72b1 Mon Sep 17 00:00:00 2001 From: sepia Date: Fri, 18 Jul 2025 18:34:50 -0500 Subject: [PATCH] Refactor index.html to use separate files for scripts and style --- index.html | 154 +----------------------- public/scripts/copy-game-link.js | 13 ++ public/scripts/display-ws-connection.js | 41 +++++++ public/scripts/send-ws-messages.js | 13 ++ public/style.css | 55 +++++++++ src/index.ts | 11 +- 6 files changed, 129 insertions(+), 158 deletions(-) create mode 100644 public/scripts/copy-game-link.js create mode 100644 public/scripts/display-ws-connection.js create mode 100644 public/scripts/send-ws-messages.js create mode 100644 public/style.css diff --git a/index.html b/index.html index 2f457d5..886f33c 100644 --- a/index.html +++ b/index.html @@ -14,63 +14,7 @@ src="https://cdn.jsdelivr.net/npm/htmx-ext-ws@2.0.2" crossorigin="anonymous" > - +
@@ -86,98 +30,8 @@
Connecting...
- + + + diff --git a/public/scripts/copy-game-link.js b/public/scripts/copy-game-link.js new file mode 100644 index 0000000..b432bbf --- /dev/null +++ b/public/scripts/copy-game-link.js @@ -0,0 +1,13 @@ +function copyGameLink() { + const gameLinkInput = document.getElementById('game-link'); + if (gameLinkInput) { + navigator.clipboard + .writeText(gameLinkInput.value) + .then(() => { + alert('Game link copied to clipboard!'); + }) + .catch((err) => { + console.error('Failed to copy link: ', err); + }); + } +} \ No newline at end of file diff --git a/public/scripts/display-ws-connection.js b/public/scripts/display-ws-connection.js new file mode 100644 index 0000000..7e3ccf7 --- /dev/null +++ b/public/scripts/display-ws-connection.js @@ -0,0 +1,41 @@ +// Get gameId and playerId from meta tags generated by the server +const gameIdMeta = document.querySelector('meta[name="gameId"]'); +const playerIdMeta = document.querySelector('meta[name="playerId"]'); +if (!gameIdMeta || !playerIdMeta) { + console.error('Game ID or Player ID meta tags not found.'); +} +const gameId = gameIdMeta.content; +const playerId = playerIdMeta.content; + +// Dynamically construct WebSocket URL +const wsUrl = `ws://${window.location.host}/ws?gameId=${gameId}&playerId=${playerId}`; + +// Get the game container element +const gameContainer = document.getElementById('game-container'); + +// Set the ws-connect attribute +gameContainer.setAttribute('ws-connect', wsUrl); + +// Tell HTMX to connect the WebSocket +htmx.trigger(gameContainer, ' and connect'); + +// Update the game link input +const gameLinkInput = document.getElementById('game-link'); +if (!gameLinkInput) { + console.error('Missing game-link element.') +} +gameLinkInput.value = + window.location.origin + + window.location.pathname + + `?gameId=${gameId}`; + +// Update the WebSocket status indicator +const wsStatusDiv = document.getElementById('ws-status'); + +gameContainer.addEventListener('htmx:wsClose', function () { + if (wsStatusDiv) wsStatusDiv.textContent = 'Disconnected'; +}); + +gameContainer.addEventListener('htmx:wsError', function () { + if (wsStatusDiv) wsStatusDiv.textContent = 'Connection Error'; +}); diff --git a/public/scripts/send-ws-messages.js b/public/scripts/send-ws-messages.js new file mode 100644 index 0000000..a03fcd4 --- /dev/null +++ b/public/scripts/send-ws-messages.js @@ -0,0 +1,13 @@ +document.addEventListener('htmx:wsConfigSend', function(e) { + if (e.target.classList.contains('board-cell')) { + const row = parseInt(e.target.dataset.row); + const col = parseInt(e.target.dataset.col); + + // Set the custom JSON data + e.detail.parameters = { + type: "make_move", + row: row, + col: col + }; + } +}); \ No newline at end of file diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..7ecfb04 --- /dev/null +++ b/public/style.css @@ -0,0 +1,55 @@ +body { + font-family: Arial, sans-serif; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; + margin: 0; + background-color: #f0f0f0; +} +#game-container { + background-color: white; + padding: 20px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + text-align: center; +} +.game-board-grid { + display: grid; + grid-template-columns: repeat(15, 1fr); + width: 450px; /* 15 * 30px */ + height: 450px; /* 15 * 30px */ + border: 1px solid black; + margin-top: 20px; +} +.board-cell { + width: 30px; + height: 30px; + border: 1px solid #ccc; + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +} +.board-cell:hover { + background-color: #e0e0e0; +} +.board-cell > div { + width: 24px; + height: 24px; + border-radius: 50%; + border: 1px solid #333; +} +.last-move { + box-shadow: 0 0 5px 3px rgba(255, 255, 0, 0.7); /* Yellow glow */ +} +#messages { + margin-top: 10px; + font-size: 0.9em; + color: #555; +} +#player-info { + margin-top: 10px; + font-weight: bold; +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index b3b7fc8..bdc0ff4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,20 +22,15 @@ const app = new Elysia() }), open(ws) { const { gameId, playerId } = ws.data.query; - if (!gameId || !playerId) { console.error( 'WebSocket connection missing gameId or playerId in query params.', ); - ws.send( - JSON.stringify({ - type: 'error', - error: 'Missing gameId or playerId.', - }), - ); + ws.send('Error: missing gameId or playerId.'); ws.close(); return; } + wsHandler.handleConnection(ws, gameId, playerId); const game = wsHandler.getGame(gameId); @@ -47,7 +42,7 @@ const app = new Elysia() } else if (game.getPlayerCount() === 1 && game.status === 'waiting') { message = `You are ${playerId}. Waiting for another player to join.`; } - wsHandler.sendMessage(game.id, 'message', message, ws); + wsHandler.sendMessage(game.id, message, ws); } else { ws.send( JSON.stringify({