2026-04-10 16:45:57 +02:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import { Dispatch, SetStateAction, useEffect } from "react";
|
|
|
|
|
import { useSession } from "next-auth/react";
|
|
|
|
|
import type { Screen } from "./types";
|
|
|
|
|
import type { useSoloGame } from "./useSoloGame";
|
|
|
|
|
import type { useMultiGame } from "./useMultiGame";
|
|
|
|
|
import { loadSession, clearSession } from "./session";
|
|
|
|
|
import { saveGame } from "./utils";
|
|
|
|
|
import { useSoloKeyboard } from "./useSoloGame";
|
|
|
|
|
|
|
|
|
|
type UseSoloGame = ReturnType<typeof useSoloGame>;
|
|
|
|
|
type UseMultiGame = ReturnType<typeof useMultiGame>;
|
|
|
|
|
|
|
|
|
|
export function useGameEffects({
|
|
|
|
|
solo,
|
|
|
|
|
multi,
|
|
|
|
|
screen,
|
|
|
|
|
setScreen,
|
|
|
|
|
setPlayerName,
|
|
|
|
|
}: {
|
|
|
|
|
solo: UseSoloGame;
|
|
|
|
|
multi: UseMultiGame;
|
|
|
|
|
screen: Screen;
|
|
|
|
|
setScreen: Dispatch<SetStateAction<Screen>>;
|
|
|
|
|
setPlayerName: Dispatch<SetStateAction<string>>;
|
|
|
|
|
}) {
|
|
|
|
|
const { data: session } = useSession();
|
|
|
|
|
|
|
|
|
|
// Pré-remplir le pseudo avec le nom du compte connecté
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (session?.user?.name) setPlayerName(session.user.name);
|
|
|
|
|
}, [session]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
|
|
|
|
|
|
// Restaurer la session après F5
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const saved = loadSession();
|
|
|
|
|
if (!saved) return;
|
|
|
|
|
|
2026-04-11 22:25:34 +02:00
|
|
|
if (
|
|
|
|
|
saved.screen === "solo" &&
|
|
|
|
|
saved.soloPuzzle &&
|
|
|
|
|
saved.soloHistory?.length
|
|
|
|
|
) {
|
2026-04-10 16:45:57 +02:00
|
|
|
setScreen("solo");
|
2026-04-11 22:25:34 +02:00
|
|
|
solo
|
|
|
|
|
.restore(saved.soloPuzzle, saved.soloHistory, saved.soloClicks ?? 0)
|
|
|
|
|
.then((ok) => {
|
|
|
|
|
if (!ok) {
|
|
|
|
|
clearSession();
|
|
|
|
|
setScreen("home");
|
|
|
|
|
}
|
|
|
|
|
});
|
2026-04-10 16:45:57 +02:00
|
|
|
} else if (
|
|
|
|
|
(saved.screen === "lobby" || saved.screen === "game") &&
|
2026-04-11 22:25:34 +02:00
|
|
|
saved.multiRoomCode &&
|
|
|
|
|
saved.multiPlayerId
|
2026-04-10 16:45:57 +02:00
|
|
|
) {
|
|
|
|
|
if (saved.playerName) setPlayerName(saved.playerName);
|
|
|
|
|
multi.restore(saved.multiRoomCode, saved.multiPlayerId).then((ok) => {
|
|
|
|
|
if (ok) setScreen("lobby");
|
2026-04-11 22:25:34 +02:00
|
|
|
else {
|
|
|
|
|
clearSession();
|
|
|
|
|
setScreen("home");
|
|
|
|
|
}
|
2026-04-10 16:45:57 +02:00
|
|
|
});
|
|
|
|
|
}
|
2026-04-11 22:25:34 +02:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2026-04-10 16:45:57 +02:00
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
// Bloquer le bouton retour navigateur
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const onPop = () => history.pushState(null, "", window.location.href);
|
|
|
|
|
history.pushState(null, "", window.location.href);
|
|
|
|
|
window.addEventListener("popstate", onPop);
|
|
|
|
|
return () => window.removeEventListener("popstate", onPop);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
// Backspace = retour arrière en solo
|
|
|
|
|
useSoloKeyboard(screen === "solo" && solo.phase === "playing", solo.goBack);
|
|
|
|
|
|
|
|
|
|
// Sync écran quand la room change de phase
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!multi.room) return;
|
|
|
|
|
const { phase } = multi.room;
|
|
|
|
|
queueMicrotask(() => {
|
|
|
|
|
if (phase === "countdown" || phase === "playing") setScreen("game");
|
|
|
|
|
});
|
|
|
|
|
}, [multi.room]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
|
|
|
|
|
|
// Sauvegarder partie solo terminée
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (solo.phase !== "won" || !solo.puzzle) return;
|
|
|
|
|
saveGame({
|
|
|
|
|
mode: "solo",
|
|
|
|
|
startArticle: solo.puzzle.start,
|
|
|
|
|
targetArticle: solo.puzzle.target,
|
|
|
|
|
path: solo.history,
|
|
|
|
|
clicks: solo.clicks,
|
|
|
|
|
timeSeconds: solo.elapsed,
|
|
|
|
|
won: true,
|
|
|
|
|
});
|
|
|
|
|
}, [solo.phase]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
|
|
|
|
|
|
// Sauvegarder partie multi quand les résultats arrivent
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const room = multi.room;
|
|
|
|
|
const pid = multi.playerId;
|
|
|
|
|
if (!room || !pid || room.phase !== "results") return;
|
|
|
|
|
const me = room.players.find((p) => p.id === pid);
|
|
|
|
|
if (!me) return;
|
|
|
|
|
saveGame({
|
|
|
|
|
mode: "multi",
|
|
|
|
|
startArticle: room.startArticle,
|
|
|
|
|
targetArticle: room.targetArticle,
|
|
|
|
|
path: multi.history,
|
|
|
|
|
clicks: multi.clicks,
|
|
|
|
|
timeSeconds: multi.elapsed,
|
|
|
|
|
won: room.roundWinner === pid,
|
|
|
|
|
});
|
|
|
|
|
}, [multi.room?.phase]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
|
|
|
|
|
|
return { session };
|
|
|
|
|
}
|