forked from phenom/healer-man
41 lines
1.5 KiB
TypeScript
41 lines
1.5 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from "react";
|
|
import { fetchDungeonReports, type DungeonReportSnapshot } from "../app/dungeonReports";
|
|
|
|
export function useDungeonReports() {
|
|
const [snapshot, setSnapshot] = useState<DungeonReportSnapshot | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState("");
|
|
const sequence = useRef(0);
|
|
|
|
const refresh = useCallback(async () => {
|
|
const request = ++sequence.current;
|
|
setLoading(true);
|
|
try {
|
|
const next = await fetchDungeonReports();
|
|
if (request !== sequence.current) return;
|
|
setSnapshot(next);
|
|
setError("");
|
|
} catch (failure) {
|
|
if (request === sequence.current) setError(failure instanceof Error ? failure.message : "Reports could not be loaded.");
|
|
} finally {
|
|
if (request === sequence.current) setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const refreshVisible = () => { if (document.visibilityState === "visible") void refresh(); };
|
|
void refresh();
|
|
const timer = window.setInterval(refreshVisible, 30_000);
|
|
window.addEventListener("focus", refreshVisible);
|
|
document.addEventListener("visibilitychange", refreshVisible);
|
|
return () => {
|
|
sequence.current += 1;
|
|
window.clearInterval(timer);
|
|
window.removeEventListener("focus", refreshVisible);
|
|
document.removeEventListener("visibilitychange", refreshVisible);
|
|
};
|
|
}, [refresh]);
|
|
|
|
return { snapshot, loading, error, refresh };
|
|
}
|