34 lines
2.2 KiB
TypeScript
34 lines
2.2 KiB
TypeScript
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) };
|
|
}
|