/* Web Push service worker for CRM offline notifications. * * Receives push payloads from IIOS (WebPushDelivery), shows a system notification, and on click * focuses an open CRM tab (or opens one) and posts the thread to deep-link to. The payload shape is * IIOS's NotificationPayload: { title, body, data: { threadId, interactionId? } }. * * Served from /public at /push-sw.js → root scope ('/'), so it controls the whole app. */ self.addEventListener("push", (event) => { let payload = {}; try { payload = event.data ? event.data.json() : {}; } catch { payload = { title: "New notification", body: event.data ? event.data.text() : "" }; } const title = payload.title || "New message"; const threadId = payload.data && payload.data.threadId; event.waitUntil( self.registration.showNotification(title, { body: payload.body || "", // Coalesce repeated pings for the same thread into one notification. tag: threadId ? `thread:${threadId}` : undefined, renotify: Boolean(threadId), data: payload.data || {}, icon: "/icons/i_bell.svg", }), ); }); self.addEventListener("notificationclick", (event) => { event.notification.close(); const threadId = event.notification.data && event.notification.data.threadId; event.waitUntil( (async () => { const all = await self.clients.matchAll({ type: "window", includeUncontrolled: true }); // Prefer an already-open CRM tab: focus it and tell the app which thread to open. for (const client of all) { if ("focus" in client) { await client.focus(); client.postMessage({ type: "notif-click", threadId: threadId || null }); return; } } // No tab open — launch one deep-linked via the query string. const url = threadId ? `/dashboard?thread=${encodeURIComponent(threadId)}` : "/dashboard"; if (self.clients.openWindow) await self.clients.openWindow(url); })(), ); });