- Fix: Notifiable-Trait zum User-Model hinzugefuegt (behebt notify()-500er) - Installer: SMTP-Verbindungstest mit EsmtpTransport + Ueberspringen-Link - Admin: Neuer E-Mail-Tab mit SMTP-Konfiguration + Verbindungstest - Admin: Lazy Quill-Initialisierung (nur sichtbare Locale wird geladen) - Uebersetzungen: 17 neue Mail-Keys in allen 6 Sprachen Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
96 lines
2.6 KiB
JavaScript
96 lines
2.6 KiB
JavaScript
// ============================================================
|
||
// Service Worker – SG Wölfe Handball WebApp
|
||
// Strategie: Lokale Assets cachen, HTML Network-First
|
||
// ============================================================
|
||
|
||
const CACHE_NAME = 'handball-v3';
|
||
const OFFLINE_URL = '/offline';
|
||
|
||
// Lokale Assets, die beim Install gecached werden
|
||
// (CDN-Assets wie Tailwind/Alpine werden nicht gecached –
|
||
// sie kommen extern und sind zu groß/dynamisch)
|
||
const PRECACHE_ASSETS = [
|
||
'/offline',
|
||
'/images/icon-192x192.png',
|
||
'/images/icon-512x512.png',
|
||
'/manifest.json',
|
||
'/images/logo_woelfe.png'
|
||
];
|
||
|
||
// ---- INSTALL ----
|
||
self.addEventListener('install', (event) => {
|
||
event.waitUntil(
|
||
caches.open(CACHE_NAME).then((cache) => {
|
||
// Einzeln cachen, damit ein 404 nicht den gesamten Install blockiert
|
||
return Promise.all(
|
||
PRECACHE_ASSETS.map((url) =>
|
||
cache.add(url).catch((err) => {
|
||
console.warn('SW: Precache fehlgeschlagen für', url, err);
|
||
})
|
||
)
|
||
);
|
||
})
|
||
);
|
||
self.skipWaiting();
|
||
});
|
||
|
||
// ---- ACTIVATE ----
|
||
self.addEventListener('activate', (event) => {
|
||
event.waitUntil(
|
||
caches.keys().then((cacheNames) => {
|
||
return Promise.all(
|
||
cacheNames
|
||
.filter((name) => name !== CACHE_NAME)
|
||
.map((name) => caches.delete(name))
|
||
);
|
||
})
|
||
);
|
||
self.clients.claim();
|
||
});
|
||
|
||
// ---- FETCH ----
|
||
self.addEventListener('fetch', (event) => {
|
||
const { request } = event;
|
||
|
||
// Nur GET-Requests behandeln (keine Formulare/POST)
|
||
if (request.method !== 'GET') return;
|
||
|
||
// Keine externen Requests behandeln (CDN, Leaflet-Tiles, Nominatim)
|
||
if (!request.url.startsWith(self.location.origin)) return;
|
||
|
||
// Statische Assets: Cache-First
|
||
if (isStaticAsset(request.url)) {
|
||
event.respondWith(
|
||
caches.match(request).then((cached) => {
|
||
return cached || fetch(request).then((response) => {
|
||
if (response.ok) {
|
||
const clone = response.clone();
|
||
caches.open(CACHE_NAME).then((cache) => cache.put(request, clone));
|
||
}
|
||
return response;
|
||
});
|
||
})
|
||
);
|
||
return;
|
||
}
|
||
|
||
// HTML-Seiten: Network-First mit Offline-Fallback
|
||
if (request.headers.get('Accept')?.includes('text/html')) {
|
||
event.respondWith(
|
||
fetch(request)
|
||
.then((response) => {
|
||
return response;
|
||
})
|
||
.catch(() => {
|
||
return caches.match(OFFLINE_URL);
|
||
})
|
||
);
|
||
return;
|
||
}
|
||
});
|
||
|
||
// ---- HILFSFUNKTIONEN ----
|
||
function isStaticAsset(url) {
|
||
return /\.(css|js|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|eot|webp)(\?.*)?$/.test(url);
|
||
}
|