https://checkmate.social
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix routing

jcalabro 2f8005a9 b9aa029b

+25 -5
+25 -5
client/src/hooks/useGame.ts
··· 6 6 * re-renders when subscriptions push updates. 7 7 */ 8 8 9 - import { useMemo } from 'react'; 9 + import { useEffect, useMemo, useRef } from 'react'; 10 10 import { useSpacetimeDB, useTable, useReducer } from 'spacetimedb/react'; 11 11 import { tables, reducers } from '../module_bindings'; 12 12 ··· 116 116 117 117 const isQueued = queuedTimeControlSecs !== null; 118 118 119 + // Track game IDs that were active at some point during this browser session. 120 + // This lets us show the outcome overlay when a game ends mid-session, without 121 + // resurrecting stale ended games on a fresh page load / refresh. 122 + const witnessedActiveIds = useRef(new Set<bigint>()); 123 + 124 + useEffect(() => { 125 + if (!identityHex) return; 126 + for (const g of allGames) { 127 + if (g.status !== 'active') continue; 128 + const isPlayer = 129 + g.whiteIdentity.toHexString() === identityHex || 130 + g.blackIdentity.toHexString() === identityHex; 131 + if (isPlayer) { 132 + witnessedActiveIds.current.add(g.id); 133 + } 134 + } 135 + }, [allGames, identityHex]); 136 + 119 137 const activeGame = useMemo(() => { 120 138 if (!identityHex) return null; 121 139 122 - // Find the most recent game this player is in. Prefer 'active' games, 123 - // but also return recently-ended games so the GameStatus overlay can 124 - // render (checkmate/resign/draw/timeout screen). Without this, ending a 125 - // game would instantly route back to the lobby with no outcome shown. 140 + // Find the most recent game this player is in. Active games always win. 141 + // Ended games are only returned if we witnessed them as active during this 142 + // session — this is what lets the outcome overlay render after a game ends 143 + // without showing a stale "game ended" screen on every page refresh. 126 144 let best: (typeof allGames)[number] | null = null; 127 145 for (const g of allGames) { 128 146 const isPlayer = ··· 135 153 best = g; 136 154 break; 137 155 } 156 + // Only consider ended games we witnessed as active in this session 157 + if (!witnessedActiveIds.current.has(g.id)) continue; 138 158 // Keep the most recently ended game (highest id = newest) 139 159 if (!best || g.id > best.id) { 140 160 best = g;