diff --git a/index.html b/index.html index 81b2f59..c3096ad 100644 --- a/index.html +++ b/index.html @@ -18,7 +18,7 @@
-
+
diff --git a/public/icons/disconnected.svg b/public/icons/disconnected.svg new file mode 100755 index 0000000..d78a8f7 --- /dev/null +++ b/public/icons/disconnected.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/public/style.css b/public/style.css index c39e1c0..95d497b 100644 --- a/public/style.css +++ b/public/style.css @@ -1,6 +1,6 @@ :root { --color-background-light-pink: #ffe0f0; - --color-text-dark: #333; + --color-text: #333; --color-game-container-bg: white; --color-game-container-shadow: rgba(0, 0, 0, 0.1); --color-board-bg: #ffefff; @@ -23,7 +23,7 @@ body { min-height: 100vh; margin: 0; background-color: var(--color-background-light-pink); - color: var(--color-text-dark); + color: var(--color-text); } #game-container { @@ -122,13 +122,12 @@ body { #messages { margin-top: 10px; font-size: 0.9em; - color: var(--color-text-dark); + color: var(--color-text); } -#player-info { - margin-top: 10px; +#title-box { font-weight: bold; - color: var(--color-text-dark); + color: var(--color-text); } #game-link-container { @@ -140,25 +139,20 @@ body { margin-top: 20px; } -#copy-link-button, -#copy-success-message { +#copy-link-button { position: absolute; - left: 50%; - transform: translateX(-50%); display: flex; justify-content: center; align-items: center; - top: 0; bottom: 0; transition: opacity 0.3s ease; padding: 8px 15px; border-radius: 5px; white-space: nowrap; - box-sizing: border-box; } #copy-link-button { background-color: var(--color-board-border); - color: var(--color-text-dark); + color: var(--color-text); border: none; cursor: pointer; gap: 8px; @@ -173,7 +167,8 @@ body { background-color: var(--color-success-purple); } -#copy-link-button img.icon { - width: 20px; - height: 20px; +img.icon { + width: 1em; + height: 1em; + vertical-align: middle; } diff --git a/src/view/board-renderer.ts b/src/view/board-renderer.ts index c3468ae..92b0abe 100644 --- a/src/view/board-renderer.ts +++ b/src/view/board-renderer.ts @@ -52,6 +52,6 @@ export function renderGameBoardHtml( return boardHtml; } -export function renderPlayerInfoHtml(gameId: string, playerId: string): string { - return `
You are: ${playerId}
Game ID: ${gameId}
`; +export function renderTitleBoxHtml(gameId: string, playerId: string): string { + return `
You are: ${playerId}
Game ID: ${gameId}
`; } diff --git a/src/web-socket-handler.ts b/src/web-socket-handler.ts index 82083f2..0cd58c0 100644 --- a/src/web-socket-handler.ts +++ b/src/web-socket-handler.ts @@ -2,7 +2,6 @@ import { ElysiaWS } from 'elysia/dist/ws'; import { GameInstance } from './game/game-instance'; import { renderGameBoardHtml, - renderPlayerInfoHtml, } from './view/board-renderer'; interface MakeMoveMessage { @@ -109,7 +108,7 @@ export class WebSocketHandler { } this.connections.set( gameId, - connectionsInGame.filter((conn) => conn !== ws), + connectionsInGame.filter((conn) => conn.data.query.playerId !== ws.data.query.playerId), ); if (this.connections.get(gameId)?.length === 0) { this.connections.delete(gameId); @@ -119,6 +118,9 @@ export class WebSocketHandler { // Notify remaining players about disconnect this.sendMessageToGame(gameId, `${playerId} disconnected.`); } + + this.sendTitleBoxesForGame(gameId); + console.log(`${playerId} disconnected from game ${gameId}`); } @@ -138,8 +140,6 @@ export class WebSocketHandler { const updatedBoardHtml = renderGameBoardHtml(game, playerId); ws.send(updatedBoardHtml); - const updatedPlayerInfoHtml = renderPlayerInfoHtml(game.id, playerId); - ws.send(updatedPlayerInfoHtml); if (game.status === 'finished') { if (game.winner === 'draw') { @@ -166,13 +166,15 @@ export class WebSocketHandler { } else { console.log(`No connections to update for game ${gameId}.`); } + + this.sendTitleBoxesForGame(gameId); } public sendMessageToGame(gameId: string, message: string): void { const connections = this.connections.get(gameId); if (connections) { connections.forEach((ws) => { - ws.send('
' + message + '
'); + this.sendMessage(ws, message); }); } } @@ -181,6 +183,64 @@ export class WebSocketHandler { targetWs.send('
' + message + '
'); } + private sendTitleBox(targetWs: WS, message: string): void { + targetWs.send('
' + message + '
'); + } + + private sendTitleBoxesForGame(gameId: string): void { + const game = this.games.get(gameId); + if (!game) { + console.error(`Tried to send title boxes for game ${gameId}, but it doesn't exist!`) + return; + } + const connections = this.connections.get(gameId); + if (!connections) { + console.log(`Attempted to send title boxes for game ${gameId}, but no players are connected.`) + return; + } + + var message = ""; + switch (game.status) { + case 'waiting': { + message = "Waiting for players..."; + } + case 'playing': { + const blackTag = game.players.black ? this.playerTag(gameId, game.players.black) : 'Unknown'; + const whiteTag = game.players.white ? this.playerTag(gameId, game.players.white) : 'Unknown'; + message = `${blackTag} vs ${whiteTag}`; + } + case 'finished': { + switch (game.winner) { + case 'draw': { + message = "Game ended in draw."; + } + case 'black': { + message = `${game.players.black} wins!`; + } + case 'white': { + message = `${game.players.white} wins!`; + } + } + } + } + + connections.forEach((connection) => {this.sendTitleBox(connection, message)}); + } + + private playerTag(gameId: string, playerId: string) { + var connectionIcon = `Disconnected` + const connections = this.connections.get(gameId); + if (connections) { + connections.forEach((ws) => { + if (ws.data.query.playerId === playerId) { + console.log(`Connection exists for player ${playerId}`); + connectionIcon = ''; + } + }); + } + return `${playerId}${connectionIcon}` + } + public getGame(gameId: string): GameInstance | undefined { return this.games.get(gameId); }