v0.9.1 web ui fixes and improvements

This commit is contained in:
2026-02-25 10:22:24 -05:00
parent f9630dea3b
commit 99b37b5456

View File

@ -5,7 +5,8 @@ let gameState = {
turn: 'w', turn: 'w',
isPlayerWhite: true, isPlayerWhite: true,
isLocked: false, isLocked: false,
pollInterval: null, polling: false,
pollController: null,
apiUrl: '', apiUrl: '',
selectedSquare: null, selectedSquare: null,
healthCheckInterval: null, healthCheckInterval: null,
@ -672,9 +673,32 @@ async function triggerComputerMove() {
} }
function startPolling() { function startPolling() {
gameState.pollInterval = setInterval(async () => { gameState.polling = true;
pollOnce();
}
function stopPolling() {
gameState.polling = false;
if (gameState.pollController) {
gameState.pollController.abort();
gameState.pollController = null;
}
}
async function pollOnce() {
if (!gameState.polling || !gameState.gameId) return;
const moveCount = (gameState.moveList || []).length;
gameState.pollController = new AbortController();
try { try {
const response = await fetch(`${gameState.apiUrl}/api/v1/games/${gameState.gameId}`); const response = await fetch(
`${gameState.apiUrl}/api/v1/games/${gameState.gameId}?wait=true&moveCount=${moveCount}`,
{ signal: gameState.pollController.signal }
);
if (!gameState.polling) return;
if (!response.ok) { if (!response.ok) {
const errorInfo = handleApiError('poll game state', null, response); const errorInfo = handleApiError('poll game state', null, response);
if (response.status === 404) { if (response.status === 404) {
@ -684,29 +708,29 @@ function startPolling() {
gameState.gameId = null; gameState.gameId = null;
return; return;
} }
// Non-404: already displayed by handleApiError above, keep polling // Retry after delay for transient errors
setTimeout(pollOnce, 2000);
return; return;
} }
const game = await response.json(); const game = await response.json();
gameState.networkError = false;
updateServerIndicator('healthy');
if (game.state !== 'pending') { if (game.state !== 'pending') {
stopPolling(); stopPolling();
updateGameDisplay(game); updateGameDisplay(game);
unlockBoard(); unlockBoard();
} else {
// Still pending, long-poll again
pollOnce();
} }
gameState.networkError = false;
updateServerIndicator('healthy');
} catch (error) { } catch (error) {
if (error.name === 'AbortError') return;
handleApiError('poll game state', error); handleApiError('poll game state', error);
stopPolling(); stopPolling();
unlockBoard(); unlockBoard();
} }
}, 1500);
}
function stopPolling() {
clearInterval(gameState.pollInterval);
gameState.pollInterval = null;
} }
function lockBoard() { function lockBoard() {