/** * Push Notifications Global Plugin * Ensures push subscriptions are maintained across all pages * This runs on app load to restore push subscriptions for users who already granted permission */ export default defineNuxtPlugin(() => { // Only run in browser if (!process.client) return // Run asynchronously without blocking app initialization // This ensures the app loads even if push setup fails or takes time setTimeout(async () => { // Check if push notifications are supported if (!('Notification' in window) || !('serviceWorker' in navigator)) { console.log('[Push Plugin] Push notifications not supported') return } try { // Wait for service worker to be ready const registration = await navigator.serviceWorker.ready console.log('[Push Plugin] Service Worker ready') // Check if we already have notification permission if (Notification.permission !== 'granted') { console.log('[Push Plugin] No notification permission yet') return } // Check if we have an active push subscription const existingSub = await registration.pushManager.getSubscription() if (existingSub) { console.log('[Push Plugin] ✅ Push subscription active') // Subscription exists, we're good return } // Permission granted but no subscription - recreate it console.log('[Push Plugin] Permission granted but no subscription, resubscribing...') // Get VAPID public key const config = useRuntimeConfig() const vapidPublicKey = config.public.vapidPublicKey if (!vapidPublicKey) { console.error('[Push Plugin] VAPID public key not configured') return } // Helper to convert base64 to Uint8Array const urlBase64ToUint8Array = (base64String: string) => { const padding = '='.repeat((4 - base64String.length % 4) % 4) const base64 = (base64String + padding) .replace(/-/g, '+') .replace(/_/g, '/') const rawData = window.atob(base64) const outputArray = new Uint8Array(rawData.length) for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i) } return outputArray } // Subscribe to push notifications const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(vapidPublicKey) }) console.log('[Push Plugin] ✅ Push subscription created') // Save subscription to server await $fetch('/api/push/subscribe', { method: 'POST', body: { subscription: subscription.toJSON() } }) console.log('[Push Plugin] ✅ Subscription saved to server') } catch (error) { console.error('[Push Plugin] Error setting up push notifications:', error) } }, 1000) // Delay 1 second to let app load first })