finish push message functionality in web client

This commit is contained in:
murdle 2025-12-12 11:46:20 +02:00
parent 42bcfd0a6d
commit f3fc612c99
7 changed files with 58 additions and 26 deletions

View File

@ -1,18 +1,18 @@
function checkServiceWorkerSupport() {
if (!"serviceWorker" in navigator || !"PushManager" in window)
if (!("serviceWorker" in navigator) || !("PushManager" in window))
throw new Error("Your browser does not have Service Worker support")
}
async function unregisterPush() {
checkServiceWorkerSupport();
const registration = await navigator.serviceWorker.getRegistration();
if (!registration) return;
const registrations = await navigator.serviceWorker.getRegistrations();
const subscription = await reg.pushManager.getSubscription();
if (!subscription) return;
await subscription.unsubscribe();
for (const reg of registrations) {
const sub = await reg.pushManager.getSubscription();
if (sub) await sub.unsubscribe();
await reg.unregister();
}
}
async function registerPush(publicKey) {
@ -36,7 +36,7 @@ async function registerPush(publicKey) {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": localStorage.token
"Authorization": getToken()
},
body: JSON.stringify({
provider: "webpush",
@ -52,18 +52,18 @@ async function registerPush(publicKey) {
}
}
function urlBase64ToUint8Array(base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
async function isPushRegistered() {
checkServiceWorkerSupport();
const rawData = atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; i++) {
outputArray[i] = rawData.charCodeAt(i);
const registrations = await navigator.serviceWorker.getRegistrations();
if (!registrations || registrations.length === 0) {
return false;
}
return outputArray;
for (const reg of registrations) {
const sub = await reg.pushManager.getSubscription();
if (sub) return true;
}
return false;
}

View File

@ -2,6 +2,8 @@ self.addEventListener("push", (event) => {
if (!event.data) return;
const payload = event.data.json();
if (payload.type !== "message") return;
const channel = payload.data?.channel || {};
const isInGuild = channel.type === "GUILD_TEXT" || channel.type === "GUILD_VOICE";

View File

@ -0,0 +1,29 @@
let authToken = null;
function getToken() {
return authToken;
}
function urlBase64ToUint8Array(base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
const rawData = atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; i++) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
let proxied = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function() {
if (arguments[0] === "Authorization") {
authToken = arguments[1];
}
return proxied.apply(this, [].slice.call(arguments));
};

View File

@ -16,20 +16,20 @@
<div id="${SWITCH_CONTAINER_ID}"></div>
`;
function addSwitches(container) {
async function addSwitches(container) {
container.appendChild(createSwitch(
"Push Notifications",
"Sends you notifications even when you close the app",
"push-notifications",
false,
async () => {
await isPushRegistered(),
async (checked) => {
const publicKey = window.GLOBAL_ENV.VAPID_KEY;
if (!publicKey) {
alert("Server has not enabled push notifications")
return false;
}
try {
await registerPush(publicKey);
checked ? await registerPush(publicKey) : await unregisterPush();
return true;
} catch(err) {
alert(err.message);

View File

@ -68,6 +68,7 @@
};
const customScripts = [
"/assets/custom/utils.js",
"/assets/custom/pushMessages.js",
"/assets/custom/rtcPatcher.js",
"/assets/custom/web/switch.js",

View File

@ -54,7 +54,7 @@ router.post(
throw new HTTPError("Endpoint is not a valid url", 400);
}
await webpush.sendNotification(subscription, JSON.stringify({ body: "Swoosh. Notifications are a go!" })).catch(async (err) => {
await webpush.sendNotification(subscription, JSON.stringify({ type: "test" })).catch(async (err) => {
console.error("[WebPush] Failed to send test notification:", err.message);
throw new HTTPError("Failed to send test notification", 400);
});

View File

@ -1,4 +1,4 @@
export interface Notification {
type: "message";
data: object;
type: "message" | "test";
data?: object;
}