1/* 2 * CavoraAI Service Worker: nur Push-Meldungen (Konzept Meldungen und Lernen, Paket N3). 3 * Kein Offline-Cache und keine abgefangenen Anfragen: Updates der App laufen weiter über /version.json 4 * (UpdateToast), die App verhält sich mit und ohne diesen Worker gleich. 5 * 6 * Die Nachricht kommt verschlüsselt vom Server (RFC 8291) und trägt nur Titel, Ziel und Dringlichkeit; 7 * Details zeigt die App nach der Anmeldung (Sperrbildschirm ohne Beträge, Namen oder Kundentexte). 8 */ 9self.addEventListener('install', () => { self.skipWaiting(); }); 10self.addEventListener('activate', (event) => { event.waitUntil(self.clients.claim()); }); 11 12self.addEventListener('push', (event) => { 13 let d = {}; 14 try { d = event.data ? event.data.json() : {}; } catch (e) { d = {}; } 15 const urgent = d.severity === 'urgent'; 16 const options = { 17 body: '', 18 icon: '/icons/icon-192.png', 19 badge: '/icons/icon-192.png', 20 tag: typeof d.tag === 'string' ? d.tag : undefined, 21 renotify: urgent && typeof d.tag === 'string', 22 requireInteraction: urgent, 23 timestamp: typeof d.at === 'number' ? d.at : Date.now(), 24 data: { link: typeof d.link === 'string' ? d.link : '/' }, 25 }; 26 // Jede Push-Nachricht zeigt eine Meldung (Safari und Chrome verlangen das, sonst entziehen sie das Recht). 27 event.waitUntil(self.registration.showNotification(typeof d.title === 'string' && d.title ? d.title : 'CavoraAI', options)); 28}); 29 30self.addEventListener('notificationclick', (event) => { 31 event.notification.close(); 32 const target = new URL((event.notification.data && event.notification.data.link) || '/', self.location.origin); 33 // Nur Ziele innerhalb der App; alles andere öffnet die Startseite. 34 const url = target.origin === self.location.origin ? target.href : self.location.origin + '/'; 35 event.waitUntil((async () => { 36 const windows = await self.clients.matchAll({ type: 'window', includeUncontrolled: true }); 37 for (const w of windows) { 38 if (new URL(w.url).origin === self.location.origin) { 39 await w.focus(); 40 if ('navigate' in w) { try { await w.navigate(url); } catch (e) { /* fremder Zustand: nur fokussieren */ } } 41 return; 42 } 43 } 44 await self.clients.openWindow(url); 45 })()); 46});
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.