// resources/js/composables/usePushNotifications.ts import { ref } from 'vue'; import axios from 'axios'; const STORAGE_KEY = 'push-permission-prompted'; export function usePushNotifications() { const isSupported = 'serviceWorker' in navigator && 'PushManager' in window; const showPrompt = ref(false); function shouldPrompt(): boolean { if (!isSupported) return false; if (Notification.permission !== 'default') return false; if (localStorage.getItem(STORAGE_KEY)) return false; return true; } function initPrompt() { showPrompt.value = shouldPrompt(); } // ← replace the old version with this one function urlBase64ToUint8Array(base64String: string): Uint8Array { const padding = '='.repeat((4 - (base64String.length % 4)) % 4); const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); const rawData = atob(base64); const buffer = new ArrayBuffer(rawData.length); const outputArray = new Uint8Array(buffer); for (let i = 0; i < rawData.length; i++) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; } async function enable() { localStorage.setItem(STORAGE_KEY, '1'); showPrompt.value = false; const permission = await Notification.requestPermission(); if (permission !== 'granted') return; const registration = await navigator.serviceWorker.ready; const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(window.vapidPublicKey), }); await axios.post('/push-subscriptions', subscription.toJSON()); } function dismiss() { localStorage.setItem(STORAGE_KEY, '1'); showPrompt.value = false; } return { isSupported, showPrompt, initPrompt, enable, dismiss }; }