ledgerrz/resources/js/composables/usePushNotifications.ts
Daan Meijer 98dc8659ba
Some checks failed
linter / quality (push) Failing after 1m5s
tests / ci (8.3) (push) Failing after 48s
tests / ci (8.4) (push) Failing after 1m3s
tests / ci (8.5) (push) Failing after 1m2s
web push notifications
2026-06-21 23:17:33 +02:00

55 lines
1.6 KiB
TypeScript

import { ref } from 'vue';
export function usePushNotifications() {
const isSubscribed = ref(false);
async function subscribe() {
if (!('serviceWorker' in navigator)) {
return;
}
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(import.meta.env.VITE_VAPID_PUBLIC_KEY),
});
await axios.post('/subscriptions', subscription);
isSubscribed.value = true;
}
async function unsubscribe() {
if (!('serviceWorker' in navigator)) {
return;
}
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
await axios.post('/subscriptions/delete', { endpoint: subscription.endpoint });
await subscription.unsubscribe();
}
isSubscribed.value = false;
}
function 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;
}
return {
isSubscribed,
subscribe,
unsubscribe,
};
}