110 lines
2.5 KiB
TypeScript
110 lines
2.5 KiB
TypeScript
|
function notificationSupported() {
|
||
|
return (
|
||
|
import.meta.client
|
||
|
&& "serviceWorker" in navigator
|
||
|
&& "PushManager" in window
|
||
|
&& "showNotification" in ServiceWorkerRegistration.prototype
|
||
|
);
|
||
|
}
|
||
|
|
||
|
export const usePushNotification = () => {
|
||
|
const subscription = ref<PushSubscription | null>(null);
|
||
|
const supported = ref<boolean | undefined>(undefined);
|
||
|
const runtimeConfig = useRuntimeConfig();
|
||
|
|
||
|
function checkSupport() {
|
||
|
return supported.value = notificationSupported();
|
||
|
}
|
||
|
|
||
|
async function postSubscription(subscription: PushSubscriptionJSON) {
|
||
|
const result = await $fetch("/api/subscribe", {
|
||
|
method: "POST",
|
||
|
body: { subscription },
|
||
|
});
|
||
|
console.log("/api/subscribe returned", result);
|
||
|
}
|
||
|
|
||
|
async function postUnsubscription() {
|
||
|
const result = await $fetch("/api/unsubscribe", {
|
||
|
method: "POST",
|
||
|
});
|
||
|
console.log("/api/unsubscribe returned", result);
|
||
|
}
|
||
|
|
||
|
async function subscribe() {
|
||
|
if (!checkSupport())
|
||
|
return;
|
||
|
|
||
|
let registration;
|
||
|
try {
|
||
|
registration = await navigator.serviceWorker.register("/sw.js");
|
||
|
} catch (err) {
|
||
|
console.error("Failed to register service worker:", err);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Check if we already have a subscription.
|
||
|
if (!subscription.value) {
|
||
|
subscription.value = await registration.pushManager.getSubscription();
|
||
|
}
|
||
|
|
||
|
// Create a new push subscription if none exists.
|
||
|
if (!subscription.value) {
|
||
|
try {
|
||
|
subscription.value = await registration.pushManager.subscribe({
|
||
|
userVisibleOnly: true,
|
||
|
applicationServerKey: runtimeConfig.public.vapidPublicKey,
|
||
|
});
|
||
|
} catch (err) {
|
||
|
console.error("Failed to subscribe:" , err);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
console.log("Subscribing with", subscription.value);
|
||
|
|
||
|
// Tell server about the new subscription.
|
||
|
try {
|
||
|
await postSubscription(subscription.value.toJSON());
|
||
|
} catch (err) {
|
||
|
console.log("Failed to post subscription to server", err)
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function unsubscribe() {
|
||
|
if (!checkSupport())
|
||
|
return;
|
||
|
|
||
|
// Fetch subscription if it hasn't already been fetched.
|
||
|
if (!subscription.value) {
|
||
|
await getSubscription();
|
||
|
}
|
||
|
|
||
|
if (!subscription.value) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
await subscription.value.unsubscribe();
|
||
|
subscription.value = null;
|
||
|
await postUnsubscription();
|
||
|
}
|
||
|
|
||
|
async function getSubscription() {
|
||
|
if (!checkSupport())
|
||
|
return;
|
||
|
const registration = await navigator.serviceWorker.getRegistration("./sw.js");
|
||
|
if (!registration)
|
||
|
return;
|
||
|
return subscription.value = await registration.pushManager.getSubscription();
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
supported,
|
||
|
subscription,
|
||
|
getSubscription,
|
||
|
subscribe,
|
||
|
unsubscribe,
|
||
|
}
|
||
|
}
|