All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Der Reports-Tab listet alle Berichte des Users mit Status-Badge, Quell-Referenz und Seitenzahl. Klick → Bericht-Detail mit: - Meta (Titel, Format, Status, Seiten) - Seiten-Thumbnails - 'Bericht finalisieren' Button (triggert PDF-Generierung via API) - 'Im Desktop-Editor öffnen' Link Auftrags-Detail erweitert: - Tap auf Foto-Thumb → Vollbild-Modal mit Löschen-Button und 'Zeichnen'-Button (öffnet Skizzen-Editor) - '🎙 Sprachnotiz aufnehmen' Button → Voice-Modal mit MediaRecorder, Live-Timer, Preview, Upload Skizzen-Editor (Touch-fähig): - Bild wird in canvas geladen, max 1600px - Werkzeuge: Pen, Pfeil mit Spitze, Rechteck, Ellipse - Farbe + Linienstärke - Undo + Clear - Speichern → rendert als JPEG und lädt als neue Bericht-Seite hoch Service Worker Cache-Version auf v2 gebumpt. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> [deploy]
65 lines
1.8 KiB
JavaScript
65 lines
1.8 KiB
JavaScript
/* Baustelle PWA Service Worker.
|
|
* Cache-Strategie:
|
|
* - App-Shell (HTML/CSS/JS): cache-first, network update
|
|
* - API-Calls: network-first, kein offline-cache (da auth-pflichtig)
|
|
*/
|
|
|
|
const CACHE = 'baustelle-v2';
|
|
const SHELL = [
|
|
'./',
|
|
'./index.html',
|
|
'./app.css',
|
|
'./app.js',
|
|
'./manifest.webmanifest',
|
|
'./lib/idb.js',
|
|
'./lib/api.js',
|
|
'./lib/offline.js',
|
|
'./lib/router.js',
|
|
'./icons/icon-192.png',
|
|
'./icons/icon-512.png',
|
|
];
|
|
|
|
self.addEventListener('install', (e) => {
|
|
e.waitUntil(caches.open(CACHE).then(c => c.addAll(SHELL).catch(() => null)));
|
|
self.skipWaiting();
|
|
});
|
|
|
|
self.addEventListener('activate', (e) => {
|
|
e.waitUntil(
|
|
caches.keys().then(keys => Promise.all(
|
|
keys.filter(k => k !== CACHE).map(k => caches.delete(k))
|
|
))
|
|
);
|
|
self.clients.claim();
|
|
});
|
|
|
|
self.addEventListener('fetch', (e) => {
|
|
const url = new URL(e.request.url);
|
|
|
|
// API-Requests: nicht cachen, durchreichen
|
|
if (url.pathname.includes('/custom/bericht/api/')) {
|
|
return; // default network
|
|
}
|
|
|
|
// App-Shell: cache-first
|
|
if (e.request.method === 'GET' && url.origin === location.origin) {
|
|
e.respondWith(
|
|
caches.match(e.request).then(hit => {
|
|
if (hit) {
|
|
// Background-Update
|
|
fetch(e.request).then(r => {
|
|
if (r.ok) caches.open(CACHE).then(c => c.put(e.request, r.clone()));
|
|
}).catch(() => null);
|
|
return hit;
|
|
}
|
|
return fetch(e.request).then(r => {
|
|
if (r.ok) {
|
|
const clone = r.clone();
|
|
caches.open(CACHE).then(c => c.put(e.request, clone));
|
|
}
|
|
return r;
|
|
});
|
|
})
|
|
);
|
|
}
|
|
});
|