const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1"; if (!isLocalhost) { const STATIC_CACHE = "construction-delivery-static-v114"; const RUNTIME_CACHE = "construction-delivery-runtime-v114"; const APP_SHELL_URLS = ["/", "/client", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"]; self.addEventListener("install", (event) => { event.waitUntil( caches.open(STATIC_CACHE).then((cache) => cache.addAll(APP_SHELL_URLS)).then(() => self.skipWaiting()), ); }); self.addEventListener("activate", (event) => { event.waitUntil( caches .keys() .then((keys) => Promise.all( keys .filter((key) => ![STATIC_CACHE, RUNTIME_CACHE].includes(key)) .map((key) => caches.delete(key)), ), ) .then(() => self.clients.claim()) .then(async () => { const clients = await self.clients.matchAll({ includeUncontrolled: true }); clients.forEach((client) => client.postMessage({ type: "PWA_OFFLINE_READY" })); }), ); }); self.addEventListener("fetch", (event) => { if (event.request.method !== "GET") { return; } const requestUrl = new URL(event.request.url); const isSameOrigin = requestUrl.origin === self.location.origin; if (event.request.mode === "navigate") { event.respondWith( fetch(event.request) .then((response) => { const responseClone = response.clone(); caches.open(RUNTIME_CACHE).then((cache) => cache.put(event.request, responseClone)); return response; }) .catch(async () => { const cachedPage = await caches.match(event.request); return cachedPage || caches.match("/index.html"); }), ); return; } if (!isSameOrigin) { return; } event.respondWith( caches.match(event.request).then((cachedResponse) => { if (cachedResponse) { return cachedResponse; } return fetch(event.request).then((response) => { if (!response || response.status !== 200) { return response; } const responseClone = response.clone(); caches.open(RUNTIME_CACHE).then((cache) => cache.put(event.request, responseClone)); return response; }); }), ); }); } else { self.addEventListener("install", (event) => self.skipWaiting()); self.addEventListener("activate", (event) => self.clients.claim()); } // Push notification handler self.addEventListener("push", (event) => { let data = {}; try { data = event.data ? event.data.json() : {}; } catch { data = { title: "Уведомление", body: "" }; } const { title, body, url } = data; const targetUrl = (() => { if (!url) return "/client"; try { const parsed = new URL(url, self.location.origin); if (parsed.origin !== self.location.origin) return "/client"; const legacyMatch = parsed.pathname.match(/^\/delivery\/([^/]+)$/); if (legacyMatch) return `/client/${legacyMatch[1]}${parsed.search}${parsed.hash}`; return parsed.pathname.startsWith("/client") ? `${parsed.pathname}${parsed.search}${parsed.hash}` : "/client"; } catch { return "/client"; } })(); event.waitUntil( self.registration.showNotification(title || "Уведомление", { body: body || "", icon: "/icons/icon-512.png", data: { url: targetUrl }, }), ); }); // Notification click handler self.addEventListener("notificationclick", (event) => { event.notification.close(); const targetPath = (event.notification.data && event.notification.data.url) || "/client"; const targetUrl = new URL(targetPath, self.location.origin).href; event.waitUntil( self.clients.matchAll({ type: "window", includeUncontrolled: true }).then(async (clientList) => { const sameOriginClient = clientList.find((client) => { try { return new URL(client.url).origin === self.location.origin; } catch { return false; } }); if (sameOriginClient) { if ("navigate" in sameOriginClient) await sameOriginClient.navigate(targetUrl); return "focus" in sameOriginClient ? sameOriginClient.focus() : undefined; } return self.clients.openWindow(targetUrl); }), ); });