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:
parent
f6478a7663
commit
d5b8134b9d
63
client/src/lib/push-utils.ts
Normal file
63
client/src/lib/push-utils.ts
Normal 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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user