/** * Service Worker for Web Push Notifications * * Handles incoming push notifications and displays them to the user. */ // Listen for push events self.addEventListener('push', function(event) { console.log('[Service Worker] Push received', event); if (!event.data) { console.log('[Service Worker] Push event but no data'); return; } let notificationData; try { notificationData = event.data.json(); } catch (e) { console.error('[Service Worker] Failed to parse push data', e); notificationData = { title: 'Notification', body: event.data.text() }; } const title = notificationData.title || 'Notification'; const options = { body: notificationData.body || '', icon: notificationData.icon || '/assets/icons/notification-icon.png', badge: notificationData.badge || '/assets/icons/notification-badge.png', image: notificationData.image, tag: notificationData.tag || 'default-tag', requireInteraction: notificationData.requireInteraction || false, silent: notificationData.silent || false, actions: notificationData.actions || [], data: notificationData.data || {} }; event.waitUntil( self.registration.showNotification(title, options) ); }); // Listen for notification clicks self.addEventListener('notificationclick', function(event) { console.log('[Service Worker] Notification clicked', event); event.notification.close(); // Handle action button clicks if (event.action) { console.log('[Service Worker] Action clicked:', event.action); // You can handle different actions here switch (event.action) { case 'open': event.waitUntil(clients.openWindow('/')); break; case 'dismiss': // Just close, no action break; default: event.waitUntil(clients.openWindow('/')); } } else { // Regular notification click (not action button) const urlToOpen = event.notification.data?.url || '/'; event.waitUntil( clients.matchAll({ type: 'window', includeUncontrolled: true }) .then(function(windowClients) { // Check if there is already a window/tab open for (let i = 0; i < windowClients.length; i++) { const client = windowClients[i]; if (client.url === urlToOpen && 'focus' in client) { return client.focus(); } } // If not, open new window/tab if (clients.openWindow) { return clients.openWindow(urlToOpen); } }) ); } }); // Listen for notification close self.addEventListener('notificationclose', function(event) { console.log('[Service Worker] Notification closed', event); // You can track notification dismissals here // e.g., send analytics event }); // Service Worker Installation self.addEventListener('install', function(event) { console.log('[Service Worker] Installing'); self.skipWaiting(); // Activate immediately }); // Service Worker Activation self.addEventListener('activate', function(event) { console.log('[Service Worker] Activating'); event.waitUntil(clients.claim()); // Take control of all pages }); // Optional: Handle background sync for failed pushes self.addEventListener('sync', function(event) { console.log('[Service Worker] Background sync', event); if (event.tag === 'push-sync') { event.waitUntil( // Retry failed push operations Promise.resolve() ); } });