"use client"; import { useEffect, useState } from "react"; export function PwaRegister() { const [showUpdate, setShowUpdate] = useState(false); const [isOffline, setIsOffline] = useState(false); const [mutationFailed, setMutationFailed] = useState(false); useEffect(() => { const handleOffline = () => setIsOffline(true); const handleOnline = () => setIsOffline(false); window.addEventListener("offline", handleOffline); window.addEventListener("online", handleOnline); // Re-sync after listeners are registered in case the online/offline event // fired between page load and this effect running (e.g. DevTools toggle). const syncId = setTimeout(() => setIsOffline(!navigator.onLine), 0); if (!("serviceWorker" in navigator)) { return () => { window.removeEventListener("offline", handleOffline); window.removeEventListener("online", handleOnline); }; } // Capture whether a SW already controls this page before registering. // If true and the controller later changes, a new build has deployed. const hadController = !!navigator.serviceWorker.controller; navigator.serviceWorker .register("/sw.js", { scope: "/" }) .catch((err) => console.warn("[famapp] SW registration failed:", err)); const handleControllerChange = () => { if (hadController) setShowUpdate(true); }; navigator.serviceWorker.addEventListener("controllerchange", handleControllerChange); const handleMessage = (e: MessageEvent) => { if (e.data?.type === "OFFLINE_MUTATION") { setMutationFailed(true); setTimeout(() => setMutationFailed(false), 4000); } }; navigator.serviceWorker.addEventListener("message", handleMessage); return () => { clearTimeout(syncId); window.removeEventListener("offline", handleOffline); window.removeEventListener("online", handleOnline); navigator.serviceWorker.removeEventListener("controllerchange", handleControllerChange); navigator.serviceWorker.removeEventListener("message", handleMessage); }; }, []); return ( <> {isOffline && (
You’re offline — showing cached content
)} {mutationFailed && !isOffline && (
Changes can’t be saved while offline
)} {showUpdate && (
New version available
)} ); }