Frontend: Live-Updates pausieren im Hintergrund-Tab (Akku/Daten sparen)

Abfahrtstafel- und Favoriten-Polling (je 30s) liefen bisher die gesamte
Seitenlebensdauer weiter, egal ob der Tab überhaupt sichtbar war -
anders als LiveMap, das schon länger korrekt über den aktiven Tab
gesteuert wird. Über die Page Visibility API werden beide Intervalle
jetzt pausiert, sobald der Tab in den Hintergrund geht, und beim
Zurückkehren mit einer sofortigen Aktualisierung neu gestartet. Der
Fahrtalarm bleibt bewusst unangetastet, da er sicherheitsrelevant ist.

Zusätzlich: beim Entfernen eines Favoriten wird jetzt auch dessen
gemerkter Störungs-Stand aus dem localStorage entfernt (sonst bleibt
er dort für immer hängen - analog zum seenDisruptions-Leck, das
letzte Runde schon im Backend gefixt wurde).

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 14:45:56 +02:00
1 parent abab758a47
commit fb7da747ec
1 file changed
+47
+47
View File
@@ -135,6 +135,15 @@ const App = (() => {
const wasAdded = idx < 0; const wasAdded = idx < 0;
if (idx >= 0) { if (idx >= 0) {
favorites.splice(idx, 1); favorites.splice(idx, 1);
// Analog zum "seenDisruptions"-Aufräumen im Backend: ohne das hier würde
// der gemerkte Störungs-Stand für entfernte Favoriten für immer im
// localStorage hängen bleiben, weil er nur noch gepflegt (nicht mehr
// gelöscht) wird, sobald die Haltestelle nicht mehr abgefragt wird.
const seenMap = loadSeenDisruptions();
if (Object.prototype.hasOwnProperty.call(seenMap, station.id)) {
delete seenMap[station.id];
saveSeenDisruptions(seenMap);
}
} else { } else {
favorites.push(station); favorites.push(station);
} }
@@ -1063,9 +1072,46 @@ const App = (() => {
function restartDeparturesPolling() { function restartDeparturesPolling() {
if (departuresPollHandle) clearInterval(departuresPollHandle); if (departuresPollHandle) clearInterval(departuresPollHandle);
if (document.hidden) return; // läuft erst wieder los, sobald der Tab sichtbar wird (siehe initVisibilityPause)
departuresPollHandle = setInterval(loadDepartures, 30000); departuresPollHandle = setInterval(loadDepartures, 30000);
} }
function stopDeparturesPolling() {
if (departuresPollHandle) {
clearInterval(departuresPollHandle);
departuresPollHandle = null;
}
}
// Pausiert die Abfahrts- und Favoriten-Live-Aktualisierung, solange der
// Browser-Tab im Hintergrund ist (Seite gewechselt, Bildschirm aus,
// App minimiert) - vorher liefen diese beiden 30s-Intervalle die gesamte
// Seitenlebensdauer über weiter, unabhängig davon, ob überhaupt jemand
// hinschaut. Das kostet unnötig Akku/Datenvolumen, gerade auf dem Handy.
// LiveMap pausiert schon länger korrekt über activateTab(); der
// Fahrtalarm (tripalarm.js) bleibt bewusst ausgenommen, da er
// sicherheitsrelevant ist und auch im Hintergrund weiterprüfen soll.
function initVisibilityPause() {
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
stopDeparturesPolling();
stopFavoritesPolling();
} else {
// Direkt beim Zurückkehren einmal aktualisieren (die Daten sind ja
// ggf. seit längerem veraltet) und die Intervalle neu starten.
if (currentStop) {
loadDepartures();
restartDeparturesPolling();
}
const favorites = loadFavorites();
if (favorites.length > 0) {
loadFavoriteNextDepartures(favorites);
startFavoritesPolling();
}
}
});
}
function initTabs() { function initTabs() {
document.querySelectorAll('[data-tab]').forEach((tab) => { document.querySelectorAll('[data-tab]').forEach((tab) => {
tab.addEventListener('click', () => activateTab(tab.dataset.tab, { focusPanel: true })); tab.addEventListener('click', () => activateTab(tab.dataset.tab, { focusPanel: true }));
@@ -1910,6 +1956,7 @@ const App = (() => {
TripAlarm.load(); TripAlarm.load();
renderFavoriteChips(); renderFavoriteChips();
renderRecentSearches(); renderRecentSearches();
initVisibilityPause();
departuresModeFilter = ModeFilter.create( departuresModeFilter = ModeFilter.create(
document.getElementById('departures-mode-filter'), document.getElementById('departures-mode-filter'),