fix: handle server behavior around reconnects, fix fetching reservations

This commit is contained in:
2026-04-23 14:24:32 -04:00
Unverified
parent f11c1c7de1
commit 7f52da0d62
5 changed files with 49 additions and 9 deletions

View File

@@ -23,6 +23,8 @@ export default function PlayPage() {
role,
username,
status,
isInMatch,
shouldGoFirst,
send,
subscribe,
reconnectAttempts,
@@ -86,13 +88,25 @@ export default function PlayPage() {
}
if (status === "connected" && gamePhase === "idle") {
setGamePhase("connected");
// Mid-match reconnect can remount with phase idle while still in a match; avoid
// the pre-queue "connected" / Ready Up state until we know we are not in-game.
setGamePhase(isInMatch ? "playing" : "connected");
if (isInMatch) {
const color: 1 | 2 = shouldGoFirst ? 1 : 2;
setMyColor(color);
myColorRef.current = color;
setIsMyTurn(shouldGoFirst);
isMyTurnRef.current = shouldGoFirst;
}
}
}, [
role,
status,
router,
gamePhase,
isInMatch,
shouldRedirectToConnect,
clearRedirectFlag,
]);
@@ -102,7 +116,11 @@ export default function PlayPage() {
switch (msg.type) {
case "CONNECT_ACK":
case "RECONNECT_ACK":
setGamePhase((prev) => (prev === "idle" ? "connected" : prev));
setGamePhase((prev) => {
if (prev !== "idle") return prev;
if (isInMatch) return "playing";
return "connected";
});
break;
case "ERROR":
@@ -193,7 +211,7 @@ export default function PlayPage() {
});
return unsubscribe;
}, [resetGame, send, subscribe]);
}, [resetGame, send, subscribe, isInMatch, username]);
const handleColumnClick = useCallback(
(col: number) => {

View File

@@ -152,6 +152,7 @@ export default function AdminSettingsPanel() {
break;
case "RESERVATION_LIST":
setReservations(message.reservations);
setActionFeedback("Loaded reservations.");
break;
case "RESERVATION_ADD":
setReservations((prev) => {

View File

@@ -40,6 +40,7 @@ interface ConnectionContextValue {
username: string;
status: ConnectionStatus;
isInMatch: boolean;
shouldGoFirst: boolean;
isAdmin: boolean;
reconnectAttempts: number;
shouldRedirectToConnect: boolean;
@@ -70,6 +71,7 @@ export function ConnectionProvider({
const [username, setUsername] = useState("");
const [status, setStatus] = useState<ConnectionStatus>("idle");
const [isInMatch, setIsInMatch] = useState(false);
const [shouldGoFirst, setShouldGoFirst] = useState(false);
const [isAdmin, setIsAdmin] = useState(false);
const [reconnectAttempts, setReconnectAttempts] = useState(0);
const [shouldRedirectToConnect, setShouldRedirectToConnect] = useState(false);
@@ -81,6 +83,7 @@ export function ConnectionProvider({
const reconnectDeadlineRef = useRef<number | null>(null);
const reconnectActiveRef = useRef(false);
const isInMatchRef = useRef(false);
const shouldGoFirstRef = useRef(false);
const sessionRef = useRef<SessionState | null>(null);
const clearReconnectTimer = useCallback(() => {
@@ -202,6 +205,8 @@ export function ConnectionProvider({
if (parsed.type === "GAME_START") {
isInMatchRef.current = true;
setIsInMatch(true);
shouldGoFirstRef.current = parsed.goesFirst;
setShouldGoFirst(parsed.goesFirst);
}
if (
@@ -377,6 +382,7 @@ export function ConnectionProvider({
username,
status,
isInMatch,
shouldGoFirst,
isAdmin,
reconnectAttempts,
shouldRedirectToConnect,
@@ -394,6 +400,7 @@ export function ConnectionProvider({
username,
status,
isInMatch,
shouldGoFirst,
isAdmin,
reconnectAttempts,
shouldRedirectToConnect,

2
next-env.d.ts vendored
View File

@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />
import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -1,6 +1,10 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -10,7 +14,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -18,10 +22,20 @@
}
],
"paths": {
"@/*": ["./*"]
"@/*": [
"./*"
]
},
"target": "ES2017"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}