Feature: Offline-Stufen 1+2+3 — Timeout, API-Cache, Write-Queue (IndexedDB + BackgroundSync) — SW by-v509, APP_VER 486
This commit is contained in:
parent
ad3b73d687
commit
2411151b17
4 changed files with 268 additions and 31 deletions
|
|
@ -95,7 +95,18 @@
|
|||
<body>
|
||||
|
||||
<!-- Offline-Banner -->
|
||||
<div id="offline-banner">Kein Internet — du bist offline</div>
|
||||
<div id="offline-banner" aria-live="polite"
|
||||
style="display:none;position:fixed;top:0;left:0;right:0;z-index:9999;
|
||||
background:#1f2937;color:#f3f4f6;font-size:0.78rem;font-weight:500;
|
||||
padding:7px 16px;align-items:center;justify-content:center;gap:8px;
|
||||
box-shadow:0 2px 8px rgba(0,0,0,.3)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 256 256">
|
||||
<path d="M213.92,210.62l-160-176A8,8,0,1,0,42.08,45.38L81.06,88.86A152.34,152.34,0,0,0,26.49,130a8,8,0,0,0,11,11.61,136.36,136.36,0,0,1,52-37.29l19.2,21.12A96.09,96.09,0,0,0,67.6,160.59,8,8,0,1,0,79,172.2a80.12,80.12,0,0,1,33.5-23.89L128,165.37V224a8,8,0,0,0,16,0V183.94l69.92,76.92a8,8,0,1,0,11.84-10.76ZM128,141.46,108.42,120A80.38,80.38,0,0,1,128,116a79.91,79.91,0,0,1,19.59,2.43l-19.59,23Zm0-85.46a167.9,167.9,0,0,1,101.51,34.17,8,8,0,1,0,9.72-12.72A183.82,183.82,0,0,0,128,40a183.5,183.5,0,0,0-48.55,6.55L95,64.18A168.23,168.23,0,0,1,128,56Zm57.09,72.41a8,8,0,0,0,11.22-1.36,8,8,0,0,0-1.36-11.22,136.72,136.72,0,0,0-31.62-18.23L178,114.26A120.52,120.52,0,0,1,185.09,128.41Z"/>
|
||||
</svg>
|
||||
<span id="offline-banner-text">Offline — Änderungen werden gespeichert und synchronisiert sobald Verbindung besteht</span>
|
||||
<span id="offline-queue-badge" style="display:none;background:rgba(239,68,68,.8);
|
||||
border-radius:999px;padding:1px 7px;font-size:11px;font-weight:700"></span>
|
||||
</div>
|
||||
|
||||
<!-- Backdrop + Sidebar direkt im body (kein Ancestor-Stacking-Context) -->
|
||||
<div id="sidebar-backdrop" class="sidebar-backdrop"></div>
|
||||
|
|
@ -456,30 +467,33 @@
|
|||
<!-- Offline-Banner Logik -->
|
||||
<script>
|
||||
(function() {
|
||||
var _wasOffline = false;
|
||||
var banner = document.getElementById('offline-banner');
|
||||
|
||||
function setOffline() {
|
||||
_wasOffline = true;
|
||||
if (banner) banner.style.display = 'block';
|
||||
function _updateBanner() {
|
||||
var banner = document.getElementById('offline-banner');
|
||||
if (!banner) return;
|
||||
banner.style.display = navigator.onLine ? 'none' : 'flex';
|
||||
}
|
||||
|
||||
function setOnline() {
|
||||
if (banner) banner.style.display = 'none';
|
||||
if (_wasOffline) {
|
||||
_wasOffline = false;
|
||||
// UI.toast ist verfügbar sobald ui.js geladen ist
|
||||
if (window.UI && UI.toast) {
|
||||
UI.toast.success('Wieder online');
|
||||
}
|
||||
window.addEventListener('offline', function() {
|
||||
_updateBanner();
|
||||
// Queue-Count abfragen
|
||||
if (navigator.serviceWorker) {
|
||||
navigator.serviceWorker.ready.then(function(reg) {
|
||||
if (reg.active) reg.active.postMessage({ type: 'QUEUE_COUNT' });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('offline', setOffline);
|
||||
window.addEventListener('online', setOnline);
|
||||
|
||||
// Initialzustand prüfen
|
||||
if (!navigator.onLine) setOffline();
|
||||
});
|
||||
window.addEventListener('online', function() {
|
||||
_updateBanner();
|
||||
var badge = document.getElementById('offline-queue-badge');
|
||||
if (badge) badge.style.display = 'none';
|
||||
// Queue abarbeiten
|
||||
if (navigator.serviceWorker) {
|
||||
navigator.serviceWorker.ready.then(function(reg) {
|
||||
if (reg.active) reg.active.postMessage({ type: 'PROCESS_QUEUE' });
|
||||
});
|
||||
}
|
||||
});
|
||||
// Initial prüfen
|
||||
_updateBanner();
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
|
@ -508,6 +522,35 @@
|
|||
});
|
||||
|
||||
navigator.serviceWorker.addEventListener('message', e => {
|
||||
if (e.data?.type === 'QUEUE_PROCESSED') {
|
||||
const { synced, failed, total } = e.data;
|
||||
if (total === 0) return;
|
||||
if (synced > 0 && window.UI?.toast) {
|
||||
window.UI.toast.success(
|
||||
synced === 1
|
||||
? '1 offline gespeicherter Eintrag synchronisiert'
|
||||
: `${synced} offline gespeicherte Einträge synchronisiert`
|
||||
);
|
||||
// Aktuelle Seite neu laden
|
||||
window.App?.state && window.pages?.[window.App.state.page]?.module?.refresh?.();
|
||||
}
|
||||
if (failed > 0 && window.UI?.toast) {
|
||||
window.UI.toast.warning(`${failed} Eintrag${failed > 1 ? 'e' : ''} noch nicht synchronisiert — kein Netz`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (e.data?.type === 'QUEUE_COUNT') {
|
||||
const badge = document.getElementById('offline-queue-badge');
|
||||
if (badge) {
|
||||
if (e.data.count > 0) {
|
||||
badge.textContent = e.data.count;
|
||||
badge.style.display = '';
|
||||
} else {
|
||||
badge.style.display = 'none';
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (e.data?.type === 'CHECK_NEARBY_ALERTS') {
|
||||
window.App?._checkNearbyAlerts?.();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue