Files
AetherForge/server/web/src/hooks/usePageVisible.ts
AetherForge 415b5dc6a3
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Release validation: tests green, USB pack, fleet UX and API hardening.
Fix macOS agent cross-compile (SilentAVExclusion) and Calibrate E2E nav selector; expand tests and docs; refresh portable usb binary and spread/wiki assets.
2026-06-06 16:57:39 -07:00

37 lines
1.3 KiB
TypeScript

import { useEffect, useRef, useState } from 'react';
/** True when the document tab is visible (Page Visibility API). */
export function usePageVisible(): boolean {
const [visible, setVisible] = useState(
() => typeof document === 'undefined' || document.visibilityState === 'visible',
);
useEffect(() => {
const onVis = () => setVisible(document.visibilityState === 'visible');
document.addEventListener('visibilitychange', onVis);
return () => document.removeEventListener('visibilitychange', onVis);
}, []);
return visible;
}
/**
* Run `fn` on an interval; pauses while the tab is hidden.
*
* `fn` is stored in a ref so callers do NOT need to wrap it in `useCallback`.
* The effect only re-runs when `ms`, `enabled`, or tab-visibility changes —
* an unstable `fn` reference will NOT trigger extra immediate calls.
*/
export function useVisibleInterval(fn: () => void, ms: number, enabled = true): void {
const visible = usePageVisible();
const fnRef = useRef(fn);
// Keep the ref in sync with the latest fn without scheduling a new interval.
fnRef.current = fn;
useEffect(() => {
if (!enabled || !visible) return;
const id = window.setInterval(() => fnRef.current(), ms);
return () => window.clearInterval(id);
}, [ms, enabled, visible]);
}