Der Geraetesuchlauf legt "Benachrichtigungen" an (benachrichtigung_module.py), ein Kommando je Kanal. Damit kann jede Automatik melden, ohne dass Editor, Zeitleiste oder Datenbank etwas davon wissen muessten. Fuer die Meldung aufs Handy braucht es keine App: Der Browser meldet sich unter Einstellungen -> Meldungen selbst an (sw.js, ajax/push.php), das Abo steht in homeMesh.push_abos, verschickt wird vom Runner. Auf dem iPhone geht es erst ab der Ablage auf dem Home-Bildschirm - der Reiter sagt das auch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
55 lines
2.2 KiB
JavaScript
55 lines
2.2 KiB
JavaScript
/*
|
|
* Service Worker - nur für Benachrichtigungen.
|
|
*
|
|
* Er liegt bewusst im Wurzelverzeichnis der Anwendung: Ein Service Worker
|
|
* gilt nur für Adressen unterhalb seines eigenen Ortes, und die Abos sollen
|
|
* für die ganze Seite gelten, nicht nur für /js/.
|
|
*
|
|
* Was er NICHT tut: Seiten zwischenspeichern. Das Dashboard lebt von
|
|
* aktuellen Werten, und ein Cache, der eine alte Fassung ausliefert, wäre
|
|
* hier kein Vorteil, sondern eine Fehlerquelle. Deshalb gibt es kein
|
|
* fetch-Ereignis - der Browser holt alles wie ohne Service Worker.
|
|
*
|
|
* Geschickt wird vom Runner (BenachrichtigungTransport in
|
|
* SolarManager/autoActions/transports.py), verschlüsselt und mit dem
|
|
* VAPID-Schlüssel unterschrieben.
|
|
*/
|
|
|
|
self.addEventListener("install", () => self.skipWaiting());
|
|
self.addEventListener("activate", (e) => e.waitUntil(self.clients.claim()));
|
|
|
|
self.addEventListener("push", (ereignis) => {
|
|
let daten = { titel: "Smart controller", text: "", url: "index.php" };
|
|
try {
|
|
if (ereignis.data) Object.assign(daten, ereignis.data.json());
|
|
} catch (fehler) {
|
|
// Kein JSON: dann ist die Nutzlast der Text.
|
|
if (ereignis.data) daten.text = ereignis.data.text();
|
|
}
|
|
ereignis.waitUntil(self.registration.showNotification(daten.titel, {
|
|
body: daten.text,
|
|
icon: "assets/img/favicon.png",
|
|
badge: "assets/img/favicon.png",
|
|
// Gleiche Kennung ersetzt die vorherige Meldung, statt sie zu stapeln -
|
|
// eine Automatik, die dreimal meldet, soll nicht dreimal im Schirm stehen.
|
|
tag: daten.kennung || undefined,
|
|
timestamp: Date.now(),
|
|
data: { url: daten.url },
|
|
}));
|
|
});
|
|
|
|
self.addEventListener("notificationclick", (ereignis) => {
|
|
ereignis.notification.close();
|
|
const ziel = new URL((ereignis.notification.data && ereignis.notification.data.url) || "index.php",
|
|
self.registration.scope).href;
|
|
ereignis.waitUntil(self.clients.matchAll({ type: "window", includeUncontrolled: true })
|
|
.then((fenster) => {
|
|
// Ist die Seite schon offen, wird sie nach vorn geholt statt ein
|
|
// zweites Mal geöffnet.
|
|
for (const f of fenster) {
|
|
if (f.url.startsWith(self.registration.scope) && "focus" in f) return f.focus();
|
|
}
|
|
return self.clients.openWindow(ziel);
|
|
}));
|
|
});
|