import { useEffect, useState } from "react"; import { fetchDungeonLeaderboard, localDungeonLeaderboard, subscribeDungeonLeaderboard, type LeaderboardScope } from "../app/dungeonLeaderboardClient"; import type { DungeonClearFilter, DungeonLeaderboard } from "../game/dungeonRunTypes"; export function useDungeonLeaderboard(dungeonId: string, difficultyId: string, filter: DungeonClearFilter, bossDifficulty = 1, bossId?: string, spotId?: string, spotRevision?: number) { const [offset, setOffset] = useState(0); const [revision, setRevision] = useState(0); const [state, setState] = useState<{ data: DungeonLeaderboard; scope: LeaderboardScope; loading: boolean }>({ data: { entries: [], total: 0 }, scope: "world", loading: true, }); useEffect(() => { setOffset(0); }, [dungeonId, difficultyId, filter, bossDifficulty, bossId, spotId, spotRevision]); useEffect(() => subscribeDungeonLeaderboard(() => setRevision((value) => value + 1)), []); useEffect(() => { const refresh = () => setRevision((value) => value + 1); window.addEventListener("focus", refresh); return () => window.removeEventListener("focus", refresh); }, []); useEffect(() => { const controller = new AbortController(); let live = true; const timeout = setTimeout(() => controller.abort(), 8000); setState({ data: { entries: [], total: 0 }, scope: "world", loading: true }); if (dungeonId) void fetchDungeonLeaderboard(dungeonId, difficultyId, filter, offset, controller.signal, bossDifficulty, bossId, spotId, spotRevision) .then((data) => { if (live) setState({ data, scope: "world", loading: false }); }) .catch(() => { if (live) setState({ data: localDungeonLeaderboard(dungeonId, difficultyId, filter, offset, bossDifficulty, bossId, spotId, spotRevision), scope: "device", loading: false }); }); else setState({ data: { entries: [], total: 0 }, scope: "world", loading: false }); return () => { live = false; controller.abort(); clearTimeout(timeout); }; }, [dungeonId, difficultyId, filter, offset, revision, bossDifficulty, bossId, spotId, spotRevision]); return { ...state, offset, setOffset, refresh: () => setRevision((value) => value + 1) }; }