Published your App

Replit-Commit-Author: Deployment
Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: f475857c-708a-4080-a0a0-ef301e469c0a
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/ICRgny1
Replit-Commit-Deployment-Build-Id: 19726b10-774b-4c9e-8a7a-421a5d549a3a
Replit-Helium-Checkpoint-Created: true
This commit is contained in:
sebastjanartic 2026-03-07 15:19:06 +00:00
parent f6478a7663
commit d5b8134b9d

View File

@ -0,0 +1,63 @@
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;
}
export function isPushSupported(): boolean {
return "serviceWorker" in navigator && "PushManager" in window;
}
export async function getExistingSubscription(): Promise<PushSubscription | null> {
if (!isPushSupported()) return null;
try {
const reg = await navigator.serviceWorker.getRegistration("/sw.js");
if (reg) return await reg.pushManager.getSubscription();
} catch {}
return null;
}
export async function subscribeToPush(): Promise<boolean> {
const keyRes = await fetch("/api/push/vapid-key");
const { publicKey } = await keyRes.json();
if (!publicKey) throw new Error("VAPID key not configured");
const reg = await navigator.serviceWorker.register("/sw.js");
await navigator.serviceWorker.ready;
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicKey),
});
const subJson = sub.toJSON();
const res = await fetch("/api/push/subscribe", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ endpoint: subJson.endpoint, keys: subJson.keys }),
});
if (!res.ok) throw new Error("Subscription save failed");
return true;
}
export async function unsubscribeFromPush(): Promise<boolean> {
const reg = await navigator.serviceWorker.getRegistration("/sw.js");
if (reg) {
const sub = await reg.pushManager.getSubscription();
if (sub) {
const res = await fetch("/api/push/unsubscribe", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ endpoint: sub.endpoint }),
});
if (!res.ok) throw new Error("Unsubscribe failed");
await sub.unsubscribe();
}
}
return true;
}