Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | 1x 1x 1x 1x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x 40x | /** * This script registers the service worker and exposes the requestNotificationPermissions() function, which will perform the necessary handshake to subscribe to push events */ export const notificationHandlerScript = (basePath: string) => ` window.addEventListener("load", function () { if(navigator.serviceWorker) { navigator.serviceWorker .register("/service-worker.js", { scope: "/" }) .then(function () { console.log("Service Worker Registered"); }); if (Notification.permission === "granted") { // If notifications are already granted, subscribe the user console.log("Notification permission already granted. Subscribing user to push notifications."); subscribeUserToPush(); } else { // If notifications are not granted, show the notification button console.log("Notification permission not granted. Showing notification button."); document.getElementById("notificationButton").style.display = "flex"; } } else { console.warn("Service Worker not supported in this browser."); } }); async function requestNotificationPermissions() { if (!("Notification" in window)) { // check if this is safari on iOS if (navigator.userAgent.includes("Safari") && !navigator.userAgent.includes("Chrome")) { alert("iOS devices only support notifications for applications added to the home screen. Please add this page to your home screen using the share button and try again."); return; } alert("This browser does not support notifications."); return; } const permission = await Notification.requestPermission(); if (permission === "granted") { // Hide the notification button after permission is granted document.getElementById("notificationButton").style.display = "none"; console.log("Notification permission granted. Subscribing user to push notifications."); alert("Notification permission granted. If you want to modify or revert this, do so in your system's notification settings."); subscribeUserToPush(); } else { console.log("Notification permission denied."); alert("Notification permission denied. If you weren't asked, you denied permission in the past and need to enable them in your system's notification settings."); } } async function subscribeUserToPush() { const registration = await navigator.serviceWorker.ready; try { const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array( await getVapidPublicKey() ), }); console.log("User is subscribed:", subscription); sendSubscriptionToServer(subscription); } catch (error) { if (!window.Notification || Notification.permission === 'denied') { console.warn('Notifications are blocked. Showing notification button.'); document.getElementById("notificationButton").style.display = "flex"; } else { if(error.code == 11) { // probably the server key has changed const subscription = await registration.pushManager.getSubscription(); if (subscription) { await subscription.unsubscribe(); console.log("Unsubscribed from push notifications due to InvalidStateError."); reload() } else { console.warn("No active subscription found to unsubscribe."); } return; } console.error("Failed to subscribe the user: ", error); } } } async function sendSubscriptionToServer(subscription) { console.log("Sending subscription to server: " + JSON.stringify(subscription)) try { const response = await fetch("${basePath}/api/subscribe", { method: "POST", body: JSON.stringify(subscription), headers: { "Content-Type": "application/json" } }); if (!response.ok) { throw new Error("Failed to send subscription to server."); } console.log("Subscription sent to server:", subscription); } catch (error) { console.error("Error sending subscription to server:", error); } } async function getVapidPublicKey() { try { const response = await fetch("${basePath}/api/vapid-public-key"); if (!response.ok) { throw new Error("Failed to fetch VAPID public key."); } const data = await response.json(); console.log("Fetched public key: " + data.publicKey) return data.publicKey; } catch (error) { console.error("Error fetching VAPID public key:", error); return null; } } function urlBase64ToUint8Array(base64String) { 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; } ` |