import { useEffect } from "preact/hooks"; // Simple safe storage functions to avoid errorHandling.ts dependency function safeLocalStorage() { try { if (typeof localStorage === "undefined") { return null; } // Test if localStorage is accessible const testKey = "__test__"; localStorage.setItem(testKey, "test"); localStorage.removeItem(testKey); return localStorage; } catch { return null; } } function safeSessionStorage() { try { if (typeof sessionStorage === "undefined") { return null; } // Test if sessionStorage is accessible const testKey = "__test__"; sessionStorage.setItem(testKey, "test"); sessionStorage.removeItem(testKey); return sessionStorage; } catch { return null; } } /** * Custom hook to manage Service Worker registration * Handles registration, unregistration, and session-based updates * Includes robust error handling for network issues and broken pipes * * @example * ```tsx * function MyComponent() { * useServiceWorker(); * return
Component content
; * } * ``` */ export function useServiceWorker() { useEffect(() => { if ("serviceWorker" in navigator) { // Check if this is a new user experience (session start) const storage = safeSessionStorage(); const isNewSession = !storage?.getItem("sw_registered"); // Add timeout for service worker operations // const registrationTimeout = setTimeout(() => { // console.warn("Service Worker registration taking longer than expected"); // }, 10000); navigator.serviceWorker.getRegistrations().then((registrations) => { const activeSW = registrations.find((reg) => reg.active?.scriptURL.includes("fetch_sw.js") ); if (activeSW && !isNewSession) { // Service worker already active and not a new session - skip registration // console.log("Service Worker already active."); // clearTimeout(registrationTimeout); return; } // New session or no active SW - unregister old versions and register new const unregisterPromises = registrations.map((registration) => registration.unregister().catch((err) => { // Log but don't fail if unregistration fails // console.warn("Failed to unregister old service worker:", err); return Promise.resolve(); }) ); return Promise.all(unregisterPromises).then(() => { // Register the new service worker after unregistering old ones return navigator.serviceWorker.register("/fetch_sw.js"); }).then(() => { // console.log("Service Worker registered."); const swStorage = safeSessionStorage(); swStorage?.setItem("sw_registered", "true"); // clearTimeout(registrationTimeout); }).catch((regError) => { // Handle registration errors gracefully // console.error("Service Worker registration failed:", regError); // clearTimeout(registrationTimeout); // Don't throw - allow app to continue without service worker }); }).catch((error) => { //clearTimeout(registrationTimeout); // Handle different error types // const errorMessage = error instanceof Error ? error.message : String(error); // if (error instanceof TypeError || errorMessage.includes("network")) { // console.error("Network error during service worker setup:", error); // } else if (errorMessage.includes("broken pipe")) { // console.error("Connection broken during service worker setup:", error); // } else { // console.error("Service Worker registration failed:", error); // } // App should continue functioning without service worker }); } // else { // console.log("Service Worker not supported in this browser."); // } // Cleanup function return () => { // No cleanup needed for service worker registration }; }, []); } /** * Custom hook to manage logout button state * Handles post-logout redirect cleanup * Includes error handling for localStorage access issues */ export function useLogoutCleanup() { useEffect(() => { try { // Use safe localStorage access const storage = safeLocalStorage(); if (!storage) { console.warn("localStorage not available"); return; } const lastClickedButton = storage.getItem("lastClickedButton"); if (lastClickedButton === "logout") { storage.removeItem("lastClickedButton"); // Add try-catch for URL manipulation and redirect try { const url = new URL(globalThis.location.href); globalThis.location.href = url.origin + "?popstate=true"; } catch (urlError) { console.error("Error during logout redirect:", urlError); // Fallback to simple redirect globalThis.location.href = "/"; } } } catch (error) { // Handle localStorage access errors (quota exceeded, privacy mode, etc.) console.error("Error during logout cleanup:", error); } }, []); }