(() => { const getCsrfToken = () => { const meta = document.querySelector('meta[name="csrf-token"]'); return meta ? meta.getAttribute("content") : ""; }; const getPushPublicKey = () => { const meta = document.querySelector('meta[name="nouri-push-public-key"]'); return meta ? meta.getAttribute("content") : ""; }; const urlBase64ToUint8Array = (base64String) => { const padding = "=".repeat((4 - (base64String.length % 4)) % 4); const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/"); const rawData = window.atob(base64); return Uint8Array.from([...rawData].map((character) => character.charCodeAt(0))); }; const registerServiceWorker = async () => { if (!("serviceWorker" in navigator)) return null; return navigator.serviceWorker.register("/service-worker.js"); }; const subscribeToPush = async () => { const publicKey = getPushPublicKey(); if (!publicKey || !("serviceWorker" in navigator) || !("PushManager" in window)) return; const registration = await navigator.serviceWorker.ready; const permission = await Notification.requestPermission(); if (permission !== "granted") return; const existing = await registration.pushManager.getSubscription(); const subscription = existing || await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicKey), }); const subscriptionJson = subscription.toJSON(); const payload = new URLSearchParams({ csrf_token: getCsrfToken(), endpoint: subscription.endpoint, p256dh: subscriptionJson.keys && subscriptionJson.keys.p256dh ? subscriptionJson.keys.p256dh : "", auth: subscriptionJson.keys && subscriptionJson.keys.auth ? subscriptionJson.keys.auth : "", }); await fetch("/push/subscribe", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", "X-Requested-With": "XMLHttpRequest", }, body: payload.toString(), }); window.location.reload(); }; const unsubscribeFromPush = async () => { if (!("serviceWorker" in navigator)) return; const registration = await navigator.serviceWorker.ready; const subscription = await registration.pushManager.getSubscription(); const payload = new URLSearchParams({ csrf_token: getCsrfToken() }); if (subscription) { payload.set("endpoint", subscription.endpoint); await subscription.unsubscribe(); } await fetch("/push/unsubscribe", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", "X-Requested-With": "XMLHttpRequest", }, body: payload.toString(), }); window.location.reload(); }; document.addEventListener("DOMContentLoaded", () => { registerServiceWorker(); const enableButton = document.querySelector("[data-push-enable]"); const disableButton = document.querySelector("[data-push-disable]"); if (enableButton) { enableButton.addEventListener("click", () => { subscribeToPush().catch(() => { window.location.reload(); }); }); } if (disableButton) { disableButton.addEventListener("click", () => { unsubscribeFromPush().catch(() => { window.location.reload(); }); }); } }); })();