Navigation an iOS-Tabs angleichen, Benachrichtigungscenter, Einfacher Modus

Phase 2-4 der WebApp-Angleichung an die iOS-App:

- Navigation: Favoriten und Störungen sind jetzt eigene Top-Level-Tabs
  (Desktop-Tableiste + mobile Bottom-Nav) statt nur über das Mehr-Grid bzw.
  den Stern im Header erreichbar. Neue Header-Icons für Einstellungen (⚙)
  und Benachrichtigungen (🔔, mit rotem Punkt bei ungelesenen Einträgen).
  "Mehr" ist jetzt schlanker (In der Nähe, Tickets, Verlauf, App-Info mit
  Verbindungstest gegen /health/full) und die Sprachauswahl in einen neuen
  eigenen "Einstellungen"-Tab umgezogen.

- Benachrichtigungscenter (js/notifications.js, neu): persistenter
  Verlauf über IndexedDB, sowohl vom Service Worker (eingehende Web-Push-
  Nachrichten, auch bei geschlossenem Tab) als auch von der Seite selbst
  (Störungs-Matches bei Favoriten, Fahrtalarm) beschrieben. Neuer
  "Benachrichtigungen"-Tab zeigt den Verlauf, Badge am Glocken-Icon zeigt
  ungelesene Einträge, per postMessage vom Service Worker live aktualisiert.

- Einfacher Modus: neuer Toggle im Einstellungen-Tab, persistiert in
  localStorage, setzt eine .simple-mode-Klasse auf <html> - moderat
  größere Schrift plus Ausblenden von Verkehrsmittel-Filter/Fahrrad-Option/
  "Zwischenhalt hinzufügen" im Routenplaner, analog zur iOS-App (bewusst
  keine Accessibility-Schriftgrößenstufe, die ist für Screenreader gedacht).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01De7H8hR1Q9DdgyuS2ukN6y
This commit is contained in:
Claude committed 2026-09-28 11:58:15 +02:00
1 parent 32c594bc4d
commit 4da99c913c
8 files changed
+455 -12

No files matched your search

+22 -1
View File
@@ -7,6 +7,17 @@
// Service Workers ist standardmäßig auf sein eigenes Verzeichnis und alles
// darunter beschränkt.
// Schreibt jede eingehende Push-Nachricht zusätzlich in den persistenten
// Benachrichtigungsverlauf (js/notifications.js), damit sie im "Mehr" >
// "Benachrichtigungen"-Tab sichtbar ist - auch wenn sie ankam, während kein
// Tab offen war (der Store läuft über IndexedDB, nicht über die Seite).
try {
self.importScripts('./js/notifications.js');
} catch (err) {
// Sollte importScripts fehlschlagen, bleibt die Push-Zustellung selbst
// trotzdem funktionsfähig - nur der Verlauf fehlt dann.
}
self.addEventListener('install', () => {
self.skipWaiting();
});
@@ -32,7 +43,17 @@ self.addEventListener('push', (event) => {
data: { url: data.url || '/' },
};
event.waitUntil(self.registration.showNotification(title, options));
event.waitUntil(
Promise.all([
self.registration.showNotification(title, options),
(typeof NotificationStore !== 'undefined'
? NotificationStore.add({ title, body: options.body, url: options.data.url }).catch(() => {})
: Promise.resolve()),
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
clientList.forEach((client) => client.postMessage({ type: 'oepnv-navi:notification-added' }));
}),
]),
);
});
// Klick auf die Benachrichtigung: vorhandenen App-Tab in den Vordergrund