Fixed notifications VAPID
Build and Publish / Build and Publish Docker Image (push) Successful in 5m11s

This commit is contained in:
Ultradesu
2026-08-08 11:45:29 +01:00
parent d6e6075469
commit 2d43600066
5 changed files with 116 additions and 33 deletions
+33 -10
View File
@@ -460,12 +460,14 @@ async fn client_portal(
.await
.map(|config| config.public_key)
.unwrap_or_default();
let notifications_enabled = !vapid_public_key.is_empty()
&& query!(Setting, $key == notification_key)
.get(&db)
.await?
.map(|setting| setting.value == "true")
.unwrap_or(false);
// The administrator setting controls whether the client can see notification
// controls. Keep this independent from VAPID validation so a configuration
// error is visible in the modal instead of silently removing the button.
let notifications_enabled = query!(Setting, $key == notification_key)
.get(&db)
.await?
.map(|setting| setting.value == "true")
.unwrap_or(false);
let turnstile_site_key = crate::turnstile::get_site_key(&db).await?;
let body = ClientPortalTemplate {
@@ -624,6 +626,12 @@ async fn web_manifest(_request: Request, Path(token): Path<String>) -> cot::Resu
async fn service_worker(_request: Request) -> cot::Result<Response> {
let script = r#"
self.addEventListener('install', function(event) {
self.skipWaiting();
});
self.addEventListener('activate', function(event) {
event.waitUntil(self.clients.claim());
});
self.addEventListener('push', function(event) {
var data = event.data ? event.data.json() : {};
event.waitUntil(self.registration.showNotification(data.title || 'Pet Visits', {
@@ -634,12 +642,23 @@ self.addEventListener('push', function(event) {
self.addEventListener('notificationclick', function(event) {
event.notification.close();
var target = new URL(event.notification.data.url || '/', self.location.origin).href;
event.waitUntil(clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(list) {
event.waitUntil((async function() {
var list = await clients.matchAll({ type: 'window', includeUncontrolled: true });
for (var i = 0; i < list.length; i++) {
if ('focus' in list[i]) { list[i].navigate(target); return list[i].focus(); }
if (list[i].url === target && 'focus' in list[i]) {
return list[i].focus();
}
}
return clients.openWindow ? clients.openWindow(target) : undefined;
}));
for (var j = 0; j < list.length; j++) {
if ('navigate' in list[j] && 'focus' in list[j]) {
try {
var navigated = await list[j].navigate(target);
return navigated ? navigated.focus() : list[j].focus();
} catch (_) {}
}
}
if (clients.openWindow) return clients.openWindow(target);
})());
});
"#;
let mut response = Response::new(cot::Body::fixed(script));
@@ -649,6 +668,10 @@ self.addEventListener('notificationclick', function(event) {
response
.headers_mut()
.insert("service-worker-allowed", "/".parse().unwrap());
response.headers_mut().insert(
"cache-control",
"no-cache, no-store, must-revalidate".parse().unwrap(),
);
Ok(response)
}