1"use strict"; 2 3const CACHE_NAME = "oohcams-v2457"; 4 5self.addEventListener("install", (evt) => { 6 self.skipWaiting(); 7}); 8 9self.addEventListener("activate", (evt) => { 10 evt.waitUntil( 11 caches.keys().then((keyList) => { 12 return Promise.all( 13 keyList.map((key) => { 14 if (key !== CACHE_NAME && key.startsWith("oohcams-")) { 15 return caches.delete(key); 16 } 17 }) 18 ); 19 }) 20 ); 21 self.clients.claim(); 22}); 23 24self.addEventListener("push", (evt) => { 25 const url = evt.data && evt.data.text(); 26 27 evt.waitUntil( 28 self.registration.pushManager.getSubscription() 29 .then(subscription => { 30 if (subscription) { 31 // Fire-and-forget: keep all sub docs for this endpoint fresh. 32 fetch("https://pwa.oohcams.com/api/subsync.php", { 33 method: "POST", 34 headers: { "Content-Type": "application/json" }, 35 body: JSON.stringify(subscription), 36 }).catch(() => {}); 37 } 38 const endpoint = subscription ? subscription.endpoint : ''; 39 return fetch(`https://pwa.oohcams.com/api/push-image.php?url=${encodeURIComponent(url || "")}&endpoint=${encodeURIComponent(endpoint)}`); 40 }) 41 .then(res => res.ok ? res.json() : null) 42 .then(data => { 43 if (!data) throw new Error("No data"); 44 45 const options = { 46 title: "ð´ Live now!", 47 body: "ð OohCams.com", 48 tag: data.url, 49 data: { track: data.track, isFallback: data.isFallback }, 50 icon: "https://pwa.oohcams.com/images/icons/icon-192x192.png?v=2457", 51 badge: "https://pwa.oohcams.com/images/icons/icon-72x72.png?v=2457", 52 }; 53 54 if (data.imageUrl) { 55 options.image = data.imageUrl; 56 } 57 58 if ('setAppBadge' in self.navigator) { 59 self.navigator.setAppBadge(1).catch(() => {}); 60 } 61 62 return Promise.all([ 63 self.registration.showNotification(options.title, options), 64 self.clients.matchAll({ type: "window", includeUncontrolled: true }).then((clients) => { 65 clients.forEach((client) => client.postMessage({ type: "update-sw" })); 66 }), 67 ]); 68 }) 69 .catch(err => { 70 console.error("Push notification failed:", err); 71 const fallbackOptions = { 72 title: "ð´ Live now!", 73 body: "ð OohCams.com", 74 tag: url || "/", 75 data: { track: "", isFallback: true }, 76 icon: "https://pwa.oohcams.com/images/icons/icon-192x192.png?v=2457", 77 badge: "https://pwa.oohcams.com/images/icons/icon-72x72.png?v=2457", 78 }; 79 return self.registration.showNotification(fallbackOptions.title, fallbackOptions); 80 }) 81 ); 82}); 83 84self.addEventListener("notificationclick", (evt) => { 85 const targetUrl = `https://pwa.oohcams.com${evt.notification.tag}`; 86 87 evt.notification.close(); 88 89 // Track click immediately in service worker 90 evt.waitUntil( 91 self.registration.pushManager.getSubscription() 92 .then(subscription => { 93 const endpoint = subscription ? subscription.endpoint : ''; 94 const url = evt.notification.tag; 95 const track = evt.notification.data?.track; 96 const isFallback = evt.notification.data?.isFallback ? 'true' : 'false'; 97 98 // Build URL with track appended if present 99 const clickUrl = track ? `${url}/${track}` : url; 100 101 // Fire and forget - same as push-image.php 102 if (endpoint && clickUrl) { 103 fetch(`https://pwa.oohcams.com/api/push_click.php?url=${encodeURIComponent(clickUrl)}&endpoint=${encodeURIComponent(endpoint)}&isFallback=${isFallback}`) 104 .catch(() => {}); // Ignore errors 105 } 106 107 // Open the page 108 return self.clients.matchAll({ type: "window", includeUncontrolled: true }); 109 }) 110 .then((clients) => { 111 // Check for an existing client to focus 112 const matchingClient = clients.find( 113 (client) => client.url.startsWith(targetUrl.split('?')[0]) && "focus" in client 114 ); 115 if (matchingClient) { 116 return matchingClient.focus(); 117 } else { 118 // Open new window (no need for from_push param anymore) 119 return clients.openWindow(targetUrl); 120 } 121 }) 122 .catch((err) => { 123 console.error("Error in notificationclick:", err); 124 return self.clients.openWindow(targetUrl); 125 }) 126 ); 127}); 128
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.