Offlinehandling hinzugefügt
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
{
|
||||
"name": "DoMiLi",
|
||||
"name": "DoMiLi - Dönerstag-Runde",
|
||||
"short_name": "DoMiLi",
|
||||
"description": "Dönerstag-Runde",
|
||||
"start_url": "index.php",
|
||||
"description": "Die Dönerstag-Runde des Domili Treffs",
|
||||
"start_url": "/",
|
||||
"scope": "./",
|
||||
"display": "standalone",
|
||||
"orientation": "portrait",
|
||||
"theme_color": "#212529",
|
||||
"background_color": "#212529",
|
||||
"icons": [
|
||||
@@ -16,6 +18,17 @@
|
||||
"src": "img/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "img/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"serviceworker": {
|
||||
"src": "sw.js",
|
||||
"scope": "/",
|
||||
"update_via_cache": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
65
offline.html
Executable file
65
offline.html
Executable file
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DoMiLi - Offline</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 60px;
|
||||
}
|
||||
.offline-content {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.center-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 70vh;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand d-flex align-items-center" href="index.php">
|
||||
<img src="img/icon-192.png" alt="Logo" width="32" height="32" class="me-2">
|
||||
DoMiLi
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Offline Content -->
|
||||
<div class="center-content">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body p-4">
|
||||
<div class="text-center mb-4">
|
||||
<span class="material-icons" style="font-size: 4rem; color: #6c757d;">cloud_off</span>
|
||||
</div>
|
||||
<h2 class="text-center mb-3">Keine Internetverbindung</h2>
|
||||
<p class="text-center text-muted mb-4">
|
||||
Bitte überprüfe deine Netzwerkverbindung und versuche es erneut.
|
||||
</p>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-primary" onclick="location.reload()">
|
||||
<span class="material-icons me-1">refresh</span>
|
||||
Erneut versuchen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
77
sw.js
Executable file
77
sw.js
Executable file
@@ -0,0 +1,77 @@
|
||||
const CACHE_NAME = 'domili-v' + new Date().getTime();
|
||||
const urlsToCache = [
|
||||
'/',
|
||||
//'/index.php',
|
||||
//'/login.php',
|
||||
'/offline.html',
|
||||
'/css/style.css',
|
||||
'/img/icon-192.png',
|
||||
'/img/icon-512.png'
|
||||
];
|
||||
|
||||
// Installation - immer neue Version
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME)
|
||||
.then(cache => {
|
||||
return cache.addAll(urlsToCache);
|
||||
})
|
||||
);
|
||||
self.skipWaiting(); // Sofort aktivieren
|
||||
});
|
||||
|
||||
// Aktivierung - alte Caches automatisch löschen
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(cacheNames => {
|
||||
return Promise.all(
|
||||
cacheNames
|
||||
.filter(name => name !== CACHE_NAME)
|
||||
.map(name => caches.delete(name))
|
||||
);
|
||||
})
|
||||
);
|
||||
return self.clients.claim(); // Sofort Kontrolle übernehmen
|
||||
});
|
||||
|
||||
// Fetch mit Network First für PHP, Cache First für statische Dateien
|
||||
self.addEventListener('fetch', event => {
|
||||
if (!event.request.url.startsWith('http')) return;
|
||||
|
||||
const url = new URL(event.request.url);
|
||||
|
||||
// Statische Ressourcen - Cache First
|
||||
if (url.pathname.endsWith('.css') ||
|
||||
url.pathname.endsWith('.png') ||
|
||||
url.pathname.endsWith('.jpg') ||
|
||||
url.pathname.endsWith('.js')) {
|
||||
event.respondWith(
|
||||
caches.match(event.request)
|
||||
.then(response => response || fetch(event.request))
|
||||
);
|
||||
}
|
||||
// Dynamische Seiten - Network First mit Offline-Fallback
|
||||
else {
|
||||
event.respondWith(
|
||||
fetch(event.request)
|
||||
.then(response => {
|
||||
// Bei erfolgreicher Antwort: in Cache speichern
|
||||
if (response && response.status === 200) {
|
||||
const responseToCache = response.clone();
|
||||
caches.open(CACHE_NAME).then(cache => {
|
||||
cache.put(event.request, responseToCache);
|
||||
});
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(() => caches.match('/offline.html'))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Nachrichten vom Client empfangen
|
||||
self.addEventListener('message', event => {
|
||||
if (event.data.action === 'skipWaiting') {
|
||||
self.skipWaiting();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user