import { Capacitor } from '@capacitor/core'; let started = false; /** * Register the app-shell service worker on the web only. * * The same worker also handles Web Push, so registering it unconditionally does * not conflict with the push opt-in path. Native Capacitor uses its local asset * server instead — a service worker there would only add a second cache. */ export function registerAppServiceWorker(): void { if (started || typeof window === 'undefined' || !('serviceWorker' in navigator)) return; if (Capacitor.isNativePlatform()) { // The native shell must never inherit an old web app-shell worker. Some // Android WebViews expose a partial/absent Service Worker API, so every // call is feature-checked and wrapped — this cleanup must never abort React // boot (that produced a black screen after the native splash). try { if (navigator.serviceWorker && typeof navigator.serviceWorker.getRegistrations === 'function') { void navigator.serviceWorker.getRegistrations() .then((regs) => regs.forEach((reg) => { try { reg.unregister(); } catch { /* ignore */ } })) .catch(() => undefined); } if (typeof caches !== 'undefined' && typeof caches.keys === 'function') { void caches.keys() .then((keys) => keys.filter((key) => key.startsWith('skate-spots-shell-')) .forEach((key) => { void caches.delete(key).catch(() => undefined); })) .catch(() => undefined); } } catch { // Best-effort only; boot must continue. } return; } started = true; const register = () => { navigator.serviceWorker.register('/push-sw.js', { updateViaCache: 'none' }).catch(() => { // Private mode / unsupported browser — the app works without it. }); }; if (document.readyState === 'complete') register(); else window.addEventListener('load', register, { once: true }); }