mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
b97b6c545b
- Type `window.__psyHidden` once via global declaration; drop 6 `(window as any)` casts. - `WindowVisibilityProvider` now ORs `window.__psyHidden` into the hidden state (and into the initial state). On WebView2 `document.hidden` does not always flip when `win.hide()` is called, so effects gated by `useWindowVisibility()` can now actually skip creating intervals/rAF instead of relying solely on the per-tick fallback check. - Slow visible-poll from 200 ms to 500 ms (5 → 2 wakeups/s for visibility alone). - Fix stray leading-space indent in `App.tsx` `window:close-requested` comment. Co-authored-by: Psychotoxical <dev@psysonic.app>
67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
import {
|
|
createContext,
|
|
useContext,
|
|
useState,
|
|
useRef,
|
|
useEffect,
|
|
type ReactNode,
|
|
} from 'react';
|
|
|
|
const WindowVisibilityContext = createContext(false);
|
|
|
|
/**
|
|
* Tracks whether the Tauri window is hidden.
|
|
*
|
|
* On Windows WebView2, `visibilitychange` and `blur`/`focus` events do not
|
|
* fire when `win.hide()` is called. We fall back to polling `document.hidden`
|
|
* OR-ed with `window.__psyHidden` (set from Rust before/after `win.hide()` /
|
|
* `show()`) — the latter is the reliable signal on WebView2 where
|
|
* `document.hidden` may stay false. Adaptive interval: slow while hidden
|
|
* (minimize wakeups), 500 ms while visible (catch show without burning CPU).
|
|
*/
|
|
function isWindowHidden() {
|
|
return document.hidden || !!window.__psyHidden;
|
|
}
|
|
|
|
export function WindowVisibilityProvider({ children }: { children: ReactNode }) {
|
|
const [hidden, setHidden] = useState(isWindowHidden);
|
|
const hiddenRef = useRef(hidden);
|
|
|
|
useEffect(() => {
|
|
hiddenRef.current = isWindowHidden();
|
|
let cancelled = false;
|
|
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
const schedule = () => {
|
|
if (cancelled) return;
|
|
const interval = hiddenRef.current ? 1000 : 500;
|
|
timeoutId = setTimeout(() => {
|
|
timeoutId = null;
|
|
if (cancelled) return;
|
|
const current = isWindowHidden();
|
|
if (current !== hiddenRef.current) {
|
|
hiddenRef.current = current;
|
|
setHidden(current);
|
|
}
|
|
schedule();
|
|
}, interval);
|
|
};
|
|
|
|
schedule();
|
|
return () => {
|
|
cancelled = true;
|
|
if (timeoutId !== null) clearTimeout(timeoutId);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<WindowVisibilityContext.Provider value={hidden}>
|
|
{children}
|
|
</WindowVisibilityContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useWindowVisibility() {
|
|
return useContext(WindowVisibilityContext);
|
|
}
|