Files
openchamber/packages/ui/src/hooks/usePushVisibilityBeacon.ts
T
Bohdan Triapitsyn 71b9ec6e3d fix(ui): improve visibility condition and push notification handling (#199)
Resolve visibility state for beacon reporting to handle focus correctly
Normalize push subscriptions per UI session and send to each endpoint
Suppress push notifications when a visible window exists to avoid redundant alerts
2026-01-23 01:51:22 +02:00

63 lines
1.7 KiB
TypeScript

import React from 'react';
import { isWebRuntime } from '@/lib/desktop';
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
const HEARTBEAT_MS = 10000;
const resolveVisibilityState = (): 'visible' | 'hidden' => {
if (typeof document === 'undefined') return 'visible';
const state = document.visibilityState;
return state === 'hidden' && document.hasFocus() ? 'visible' : state;
};
const sendVisibility = (visible: boolean) => {
if (!isWebRuntime()) {
return;
}
const apis = getRegisteredRuntimeAPIs();
if (!apis?.push?.setVisibility) {
return;
}
void apis.push.setVisibility({ visible });
};
export const usePushVisibilityBeacon = () => {
React.useEffect(() => {
if (!isWebRuntime() || typeof document === 'undefined') {
return;
}
const report = () => {
sendVisibility(resolveVisibilityState() === 'visible');
};
const reportVisibleOnly = () => {
if (resolveVisibilityState() === 'visible') {
sendVisibility(true);
}
};
report();
// Heartbeat while visible so server TTL (30s) never expires.
const interval = window.setInterval(reportVisibleOnly, HEARTBEAT_MS);
document.addEventListener('visibilitychange', report);
window.addEventListener('pagehide', report);
window.addEventListener('pageshow', report);
window.addEventListener('focus', report);
window.addEventListener('blur', report);
return () => {
window.clearInterval(interval);
document.removeEventListener('visibilitychange', report);
window.removeEventListener('pagehide', report);
window.removeEventListener('pageshow', report);
window.removeEventListener('focus', report);
window.removeEventListener('blur', report);
};
}, []);
};