97 lines
3.7 KiB
JavaScript
97 lines
3.7 KiB
JavaScript
(() => {
|
|
const getCsrfToken = () => {
|
|
const meta = document.querySelector('meta[name="csrf-token"]');
|
|
return meta ? meta.getAttribute("content") : "";
|
|
};
|
|
|
|
const getPushPublicKey = () => {
|
|
const meta = document.querySelector('meta[name="nouri-push-public-key"]');
|
|
return meta ? meta.getAttribute("content") : "";
|
|
};
|
|
|
|
const 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].map((character) => character.charCodeAt(0)));
|
|
};
|
|
|
|
const registerServiceWorker = async () => {
|
|
if (!("serviceWorker" in navigator)) return null;
|
|
return navigator.serviceWorker.register("/service-worker.js");
|
|
};
|
|
|
|
const subscribeToPush = async () => {
|
|
const publicKey = getPushPublicKey();
|
|
if (!publicKey || !("serviceWorker" in navigator) || !("PushManager" in window)) return;
|
|
const registration = await navigator.serviceWorker.ready;
|
|
const permission = await Notification.requestPermission();
|
|
if (permission !== "granted") return;
|
|
|
|
const existing = await registration.pushManager.getSubscription();
|
|
const subscription = existing || await registration.pushManager.subscribe({
|
|
userVisibleOnly: true,
|
|
applicationServerKey: urlBase64ToUint8Array(publicKey),
|
|
});
|
|
const subscriptionJson = subscription.toJSON();
|
|
const payload = new URLSearchParams({
|
|
csrf_token: getCsrfToken(),
|
|
endpoint: subscription.endpoint,
|
|
p256dh: subscriptionJson.keys && subscriptionJson.keys.p256dh ? subscriptionJson.keys.p256dh : "",
|
|
auth: subscriptionJson.keys && subscriptionJson.keys.auth ? subscriptionJson.keys.auth : "",
|
|
});
|
|
await fetch("/push/subscribe", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
},
|
|
body: payload.toString(),
|
|
});
|
|
window.location.reload();
|
|
};
|
|
|
|
const unsubscribeFromPush = async () => {
|
|
if (!("serviceWorker" in navigator)) return;
|
|
const registration = await navigator.serviceWorker.ready;
|
|
const subscription = await registration.pushManager.getSubscription();
|
|
const payload = new URLSearchParams({ csrf_token: getCsrfToken() });
|
|
if (subscription) {
|
|
payload.set("endpoint", subscription.endpoint);
|
|
await subscription.unsubscribe();
|
|
}
|
|
await fetch("/push/unsubscribe", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|
"X-Requested-With": "XMLHttpRequest",
|
|
},
|
|
body: payload.toString(),
|
|
});
|
|
window.location.reload();
|
|
};
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
registerServiceWorker();
|
|
|
|
const enableButton = document.querySelector("[data-push-enable]");
|
|
const disableButton = document.querySelector("[data-push-disable]");
|
|
|
|
if (enableButton) {
|
|
enableButton.addEventListener("click", () => {
|
|
subscribeToPush().catch(() => {
|
|
window.location.reload();
|
|
});
|
|
});
|
|
}
|
|
|
|
if (disableButton) {
|
|
disableButton.addEventListener("click", () => {
|
|
unsubscribeFromPush().catch(() => {
|
|
window.location.reload();
|
|
});
|
|
});
|
|
}
|
|
});
|
|
})();
|