import React from "react"; import { supabase, hasSupabaseConfig } from "../supabaseClient"; const VAPID_PUBLIC_KEY = "BBHRiMfIGQf3EjnnPQ6QS-jS2oset-YMmufJSvw-0a974ULxLaxQqZkfB0ldz-tqH6B9WAIh9Et86i0ezjuedmU"; function 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, (c) => c.charCodeAt(0)); } export async function subscribeUserToPush(userId) { if (!hasSupabaseConfig || !userId) return null; if (!("serviceWorker" in navigator) || !("PushManager" in window)) { console.warn("Push notifications not supported"); return null; } const registration = await navigator.serviceWorker.ready; let subscription = await registration.pushManager.getSubscription(); if (!subscription) { try { subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY), }); } catch (err) { console.error("Push subscription failed:", err); return null; } } const { data: { session } } = await supabase.auth.getSession(); if (!session?.access_token) return null; const res = await fetch(`${supabase.supabaseUrl}/functions/v1/subscribe-push`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${session.access_token}`, }, body: JSON.stringify({ subscription: subscription.toJSON() }), }); if (!res.ok) { console.error("Failed to save push subscription:", await res.text()); return null; } return subscription; } export async function unsubscribeUserFromPush() { if (!("serviceWorker" in navigator)) return; const registration = await navigator.serviceWorker.ready; const subscription = await registration.pushManager.getSubscription(); if (!subscription) return; const endpoint = subscription.endpoint; await subscription.unsubscribe(); const { data: { session } } = await supabase.auth.getSession(); if (session?.access_token) { await fetch(`${supabase.supabaseUrl}/functions/v1/unsubscribe-push`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${session.access_token}`, }, body: JSON.stringify({ endpoint }), }); } } export function usePushNotifications(userId) { const [isSupported, setIsSupported] = React.useState(false); const [isSubscribed, setIsSubscribed] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false); React.useEffect(() => { const supported = "serviceWorker" in navigator && "PushManager" in window && "Notification" in window; setIsSupported(supported); if (!supported) return; navigator.serviceWorker.ready.then((reg) => { reg.pushManager.getSubscription().then((sub) => { setIsSubscribed(!!sub); }); }); }, []); const subscribe = React.useCallback(async () => { if (!isSupported || !userId) return; setIsLoading(true); try { const permission = await Notification.requestPermission(); if (permission !== "granted") { setIsSubscribed(false); return; } const sub = await subscribeUserToPush(userId); setIsSubscribed(!!sub); } finally { setIsLoading(false); } }, [isSupported, userId]); const unsubscribe = React.useCallback(async () => { setIsLoading(true); try { await unsubscribeUserFromPush(); setIsSubscribed(false); } finally { setIsLoading(false); } }, []); return { isSupported, isSubscribed, isLoading, subscribe, unsubscribe }; }