Private
Public Access
1
0

chg: dev: more, massive refactor for front-end #4

This commit is contained in:
2026-04-10 19:09:05 +02:00
parent b57442bec1
commit d186a96f0d
13 changed files with 402 additions and 296 deletions

View File

@@ -0,0 +1,26 @@
import { useRef } from 'react';
import { PLAYER_DEF } from '../utils/constants';
const useGameRefs = () => {
const webPlayerRef = useRef(null);
const activePlayerRef = useRef(false);
const bombSelectedRef = useRef(false);
const connectionLostRef = useRef(false);
const redRef = useRef({ ...PLAYER_DEF });
const blueRef = useRef({ ...PLAYER_DEF });
const lastClickedRef = useRef({ red: null, blue: null });
const endRef = useRef(false);
return {
webPlayerRef,
activePlayerRef,
bombSelectedRef,
connectionLostRef,
redRef,
blueRef,
lastClickedRef,
endRef,
};
};
export default useGameRefs;

View File

@@ -0,0 +1,36 @@
import { useState } from 'react';
import { initCells, PLAYER_DEF } from '../utils/constants';
const useGameState = () => {
const [webPlayer, setWebPlayer] = useState(null);
const [activePlayer, setActivePlayer] = useState(false);
const [overlay, setOverlay] = useState(true);
const [overlayTitle, setOverlayTitle] = useState('');
const [overlaySubTitle, setOverlaySubTitle] = useState('');
const [mines, setMines] = useState(51);
const [bombSelected, setBombSelected] = useState(false);
const [foundMines, setFoundMines] = useState(false);
const [red, setRed] = useState({ ...PLAYER_DEF });
const [blue, setBlue] = useState({ ...PLAYER_DEF });
const [cells, setCells] = useState(initCells);
const [gridReady, setGridReady] = useState(false);
const [connectionLost, setConnectionLost] = useState(false);
return {
webPlayer, setWebPlayer,
activePlayer, setActivePlayer,
overlay, setOverlay,
overlayTitle, setOverlayTitle,
overlaySubTitle, setOverlaySubTitle,
mines, setMines,
bombSelected, setBombSelected,
foundMines, setFoundMines,
red, setRed,
blue, setBlue,
cells, setCells,
gridReady, setGridReady,
connectionLost, setConnectionLost,
};
};
export default useGameState;

View File

@@ -1,26 +1,22 @@
import React, { useEffect, useRef } from 'react';
import { useQuery, useMutation } from '@tanstack/react-query';
import { useMutation, useQuery } from '@tanstack/react-query';
import { useGame } from '../contexts/GameContext';
import { DESC } from '../constants';
import { DESC } from '../utils/constants';
/**
* Handles all server communication: SSE (Mercure), REST calls, and the
* initialization lifecycle. Exposes only the UI-facing callbacks the
* component needs: onClick, resign.
*/
const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
/** Handles all server communication: SSE (Mercure), REST calls, and the initialization lifecycle. */
const useServerCommunication = (gameAssoc, gameInherited, isEnvDev) => {
const {
// Async-safe refs
/** Async-safe refs */
webPlayerRef, activePlayerRef, bombSelectedRef, connectionLostRef, endRef,
// State setters
/** State setters */
setGridReady,
// Sync helpers
/** Sync helpers */
syncWebPlayer, syncActivePlayer, syncBombSelected, syncConnLost, syncRed, syncBlue,
// Game logic
/** Game logic */
showOverlay, hideOverlay,
applyRevealedCell, applyStep,
makeGameEndIfItEnds, resignProcess,
// Current cells snapshot (for active-check in onClick)
/** Current cells snapshot (for active-check in onClick) */
cells,
} = useGame();
@@ -28,7 +24,7 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
const rpcUsersRef = useRef(null);
const stepCacheRef = useRef([]);
// Helpers
/** HELPERS */
const correctGridSize = () => {
let $f = $('#mine-wrapper .grid');
@@ -38,7 +34,7 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
$('#mine-wrapper .grid .field-wrapper .field').height($f.width()).css('line-height', ($f.width() - 2) + 'px');
};
// REST mutations / queries
/** REST mutations / queries */
const connectQuery = useQuery({
queryKey: ['game-connect', gameAssoc],
@@ -72,7 +68,7 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
}).then(r => r.json()),
});
// Game-start helpers (triggered by server events)
/** Game-start helpers (triggered by server events) */
const wInit = (revealedCells = []) => {
setGridReady(true);
@@ -91,17 +87,20 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
const makeGameStart = payload => {
syncActivePlayer(1);
syncRed(p => ({ ...p, name: payload.users.red || payload.users.redAnon || p.name }));
syncRed(p => ({
...p,
name: payload.users.red || payload.users.redAnon || p.name,
}));
syncBlue(p => ({
...p,
name: payload.users.blue || payload.users.blueAnon || p.name,
desc: 'blue' === webPlayerRef.current ? DESC.you : DESC.buddy,
name: payload.users.blue || payload.users.blueAnon || p.name,
desc: 'blue' === webPlayerRef.current ? DESC.you : DESC.buddy,
active: true,
}));
hideOverlay();
};
// Mercure / SSE message handlers
/** Mercure / SSE message handlers */
const wSubscribe = (payload, rpcUsers = null) => {
isEnvDev && console.info((payload.user ?? 'user') + ' subscribed');
@@ -174,17 +173,26 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
es.onmessage = e => handleMercureMessage(JSON.parse(e.data));
es.onopen = () => {
isEnvDev && console.info('SSE opened');
if (connectionLostRef.current) { isEnvDev && console.info('SSE reconnected'); joinMutation.mutate(); }
if (connectionLostRef.current) {
isEnvDev && console.info('SSE reconnected');
joinMutation.mutate();
}
};
es.onerror = () => {
isEnvDev && console.error('SSE error');
syncConnLost(true);
};
es.onerror = () => { isEnvDev && console.error('SSE error'); syncConnLost(true); };
eventSourceRef.current = es;
};
// Initialization
/** Initialization */
useEffect(() => {
(async () => {
if (connectionLostRef.current) { openEventSource(); return; }
if (connectionLostRef.current) {
openEventSource();
return;
}
try {
if (gameInherited) {
const serverData = await connectQuery.refetch().then(r => {
@@ -219,7 +227,7 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// UI-facing callbacks
/** UI-facing callbacks */
const onClick = async coords => {
const activeColor = activePlayerRef.current ? 'blue' : 'red';
@@ -230,7 +238,10 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
const dataPack = { coords, player: activeColor, bomb: bombSelectedRef.current, resign: null };
if (connectionLostRef.current) { stepCacheRef.current.push(dataPack); return; }
if (connectionLostRef.current) {
stepCacheRef.current.push(dataPack);
return;
}
try {
const result = await stepMutation.mutateAsync(dataPack);
@@ -261,4 +272,4 @@ const useServerComm = (gameAssoc, gameInherited, isEnvDev) => {
return { onClick, resign };
};
export default useServerComm;
export default useServerCommunication;