// Web Push registration + subscription helpers. import { getVapidKey, subscribePush } from "./api" export function pushSupported() { return "serviceWorker" in navigator && "PushManager" in window } export async function registerSW() { if (!("serviceWorker" in navigator)) return null return navigator.serviceWorker.register("/sw.js") } function urlBase64ToUint8Array(base64String) { const padding = "=".repeat((4 - (base64String.length % 4)) % 4) const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/") const raw = window.atob(base64) const arr = new Uint8Array(raw.length) for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i) return arr } // Triggered from a user gesture (the Profile "Enable reminders" button). export async function enableReminders() { if (!pushSupported()) { throw new Error("Push notifications are not supported in this browser.") } // If already blocked, requestPermission() returns "denied" without a prompt. if (Notification.permission === "denied") { throw new Error("Notifications are blocked for this site. Click the lock/info icon at the left of the address bar → Site settings → set Notifications to Allow → reload and try again.") } const permission = await Notification.requestPermission() if (permission !== "granted") { throw new Error("Please choose 'Allow' on the notification prompt to enable reminders.") } const registration = await registerSW() await navigator.serviceWorker.ready const publicKey = await getVapidKey() if (!publicKey) { throw new Error("Server is missing VAPID keys. Set VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY in .env.") } const existing = await registration.pushManager.getSubscription() const subscription = existing || (await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(publicKey), })) const json = subscription.toJSON() await subscribePush({ endpoint: json.endpoint, keys: { p256dh: json.keys.p256dh, auth: json.keys.auth }, }) return true }