implement web push
This commit is contained in:
117
web/summary.js
117
web/summary.js
@@ -1,39 +1,104 @@
|
||||
const KEY_UPDATES_ENABLED = "updatesEnabled"
|
||||
const KEY_SUBSCRIPTION = "subscription"
|
||||
|
||||
const canReceiveUpdates = "Notification" in window && "serviceWorker" in navigator
|
||||
const getSummaryButton = document.getElementById("get-summary-btn")
|
||||
const loc = getSummaryButton.dataset.loc
|
||||
getSummaryButton.style.display = "none"
|
||||
|
||||
console.log("can receive updates?", canReceiveUpdates)
|
||||
|
||||
if (canReceiveUpdates) {
|
||||
async function main() {
|
||||
window.addEventListener("load", () => {
|
||||
navigator.serviceWorker.register("/sw.js")
|
||||
})
|
||||
|
||||
navigator.serviceWorker.ready.then((reg) => {
|
||||
if (Notification.permission === "granted" && localStorage.getItem(KEY_UPDATES_ENABLED) === "true") {
|
||||
getSummaryButton.innerText = "Stop updates"
|
||||
reg.active.postMessage(loc)
|
||||
} else {
|
||||
getSummaryButton.innerText = "Get daily updates at 7am"
|
||||
}
|
||||
const reg = await navigator.serviceWorker.ready
|
||||
|
||||
getSummaryButton.addEventListener("click", async () => {
|
||||
const currentlyEnabled = localStorage.getItem(KEY_UPDATES_ENABLED) === "true"
|
||||
const worker = await navigator.serviceWorker.ready
|
||||
if (currentlyEnabled) {
|
||||
localStorage.removeItem(KEY_UPDATES_ENABLED)
|
||||
worker.active.postMessage("cancel")
|
||||
} else if (await Notification.requestPermission()) {
|
||||
localStorage.setItem(KEY_UPDATES_ENABLED, "true")
|
||||
worker.active.postMessage(loc)
|
||||
} else {
|
||||
console.log("notification denied")
|
||||
}
|
||||
})
|
||||
const existingSubscriptionJson = localStorage.getItem(KEY_SUBSCRIPTION)
|
||||
const existingSubscription = existingSubscriptionJson ? JSON.parse(existingSubscriptionJson) : null
|
||||
|
||||
getSummaryButton.style.display = "block"
|
||||
})
|
||||
if (existingSubscription?.locations?.includes(loc) ?? false) {
|
||||
getSummaryButton.innerText = "Stop updates"
|
||||
reg.active.postMessage(loc)
|
||||
} else {
|
||||
getSummaryButton.innerText = "Get daily updates at 7am"
|
||||
}
|
||||
|
||||
getSummaryButton.addEventListener("click", onButtonClick)
|
||||
getSummaryButton.style.display = "block"
|
||||
}
|
||||
|
||||
async function onButtonClick() {
|
||||
const reg = await navigator.serviceWorker.ready
|
||||
|
||||
const existingSubscriptionJson = localStorage.getItem(KEY_SUBSCRIPTION)
|
||||
const existingSubscription = existingSubscriptionJson ? JSON.parse(existingSubscriptionJson) : null
|
||||
const currentlyEnabled = existingSubscription?.locations?.includes(loc) ?? false
|
||||
|
||||
if (currentlyEnabled) {
|
||||
await reg.pushManager.getSubscription().then((sub) => sub?.unsubscribe())
|
||||
localStorage.removeItem(KEY_SUBSCRIPTION)
|
||||
getSummaryButton.innerText = "Get daily updates at 7am"
|
||||
} else {
|
||||
const worker = await navigator.serviceWorker.ready
|
||||
|
||||
try {
|
||||
const publicKey = await fetch("/vapid").then((res) => {
|
||||
if (res.status === 200) {
|
||||
return res.text()
|
||||
}
|
||||
throw new Error(`${res.status}`)
|
||||
})
|
||||
const pushSub = await worker.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: publicKey
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
|
||||
let newSubscription
|
||||
if (existingSubscription) {
|
||||
newSubscription = await fetch(`/registrations/${existingSubscription.id}`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: pushSub,
|
||||
locations: [...existingSubscription.locations, loc]
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.status === 200) {
|
||||
return res.json()
|
||||
}
|
||||
throw new Error(`${res.status}`)
|
||||
})
|
||||
} else {
|
||||
newSubscription = await fetch("/registrations", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription: pushSub,
|
||||
locations: [loc]
|
||||
})
|
||||
}).then((res) => {
|
||||
if (res.status === 200) {
|
||||
return res.json()
|
||||
}
|
||||
throw new Error(`${res.status}`)
|
||||
})
|
||||
}
|
||||
|
||||
localStorage.setItem(KEY_SUBSCRIPTION, JSON.stringify(newSubscription))
|
||||
|
||||
getSummaryButton.innerText = "Stop updates"
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (canReceiveUpdates) {
|
||||
main()
|
||||
}
|
||||
|
58
web/sw.js
58
web/sw.js
@@ -1,47 +1,17 @@
|
||||
let ws
|
||||
let shouldRetry = false
|
||||
self.addEventListener('install', function (event) {
|
||||
event.waitUntil(self.skipWaiting());
|
||||
});
|
||||
|
||||
function start(location) {
|
||||
shouldRetry = true
|
||||
const port = self.location.port ? `:${self.location.port}` : ""
|
||||
const socket = new WebSocket(`ws://${self.location.hostname}${port}/ws?location=${location}`)
|
||||
socket.onopen = () => {
|
||||
ws = socket
|
||||
}
|
||||
socket.onclose = () => {
|
||||
reconnect()
|
||||
}
|
||||
socket.onerror = () => {
|
||||
reconnect()
|
||||
}
|
||||
socket.onmessage = (event) => {
|
||||
self.registration.showNotification("7am weather summary", {
|
||||
body: event.data
|
||||
})
|
||||
}
|
||||
}
|
||||
self.addEventListener('activate', function (event) {
|
||||
event.waitUntil(self.clients.claim());
|
||||
});
|
||||
|
||||
function cancel() {
|
||||
shouldRetry = false
|
||||
if (ws) {
|
||||
ws.close()
|
||||
ws = null
|
||||
self.addEventListener("push", (event) => {
|
||||
if (event.data) {
|
||||
event.waitUntil(
|
||||
self.registration.showNotification("7am weather summary", {
|
||||
body: event.data.text()
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async function reconnect() {
|
||||
while (shouldRetry) {
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(resolve, 5 * 60 * 1000)
|
||||
})
|
||||
start(location)
|
||||
}
|
||||
}
|
||||
|
||||
self.addEventListener("message", (event) => {
|
||||
if (event.data === "cancel") {
|
||||
cancel()
|
||||
} else {
|
||||
start(event.data)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user