import React from 'react'; import { registerSW } from 'virtual:pwa-register'; import { useTranslation } from '../i18n/useTranslation'; import { useToast } from './ToastHost'; export default function PwaManager() { const toast = useToast(); const { t } = useTranslation(); const toastRef = React.useRef(toast); const tRef = React.useRef(t); const updatePromptedRef = React.useRef(false); React.useEffect(() => { toastRef.current = toast; }, [toast]); React.useEffect(() => { tRef.current = t; }, [t]); React.useEffect(() => { if (!('serviceWorker' in navigator)) { return; } const updateSW = registerSW({ immediate: true, onNeedRefresh() { if (updatePromptedRef.current) { return; } updatePromptedRef.current = true; toastRef.current.push({ text: tRef.current('common.updateAvailable'), type: 'info', durationMs: 0, action: { label: tRef.current('common.updateAction'), onClick: () => updateSW(true), }, }); }, onOfflineReady() { toastRef.current.push({ text: tRef.current('common.offlineReady'), type: 'success', }); }, onRegisterError(error) { console.warn('Guest PWA registration failed', error); }, }); const runQueue = () => { void import('../queue/queue') .then((m) => m.processQueue().catch(() => {})) .catch(() => {}); }; const handleMessage = (event: MessageEvent) => { if (event.data?.type === 'sync-queue') { runQueue(); } }; navigator.serviceWorker.addEventListener('message', handleMessage); window.addEventListener('online', runQueue); runQueue(); return () => { navigator.serviceWorker.removeEventListener('message', handleMessage); window.removeEventListener('online', runQueue); }; }, []); return null; }