Add files via upload

This commit is contained in:
Serverlele30 authored and GitHub committed 2026-02-10 10:23:54 +01:00
1 parent 2ce0531216
commit fbd97dc9d5
8 files changed
+4617 -4943

No files matched your search

+56 -390
View File
@@ -1,404 +1,70 @@
# VBB Netz Status # VBB Netz Status - Getrennte Dateien
> **Live-Nahverkehr für Berlin & Brandenburg** ## 📁 Dateistruktur
> Eine Progressive Web App (PWA) für Echtzeit-Abfahrten, Routenplanung und Live-Fahrzeugverfolgung im VBB-Gebiet
[![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) Die App wurde jetzt in separate Dateien aufgeteilt:
[![Version](https://img.shields.io/badge/Version-29.0-blue.svg)](https://github.com/Serverlele30/VBB-Status-Web-App)
**Live-Demo:** [VBB-Status-Web-App](https://github.com/Serverlele30/VBB-Status-Web-App)
---
## 📱 Features
### 🚇 **Echtzeit-Abfahrten**
- **Live-Daten** für alle Stationen im VBB-Netz (Berlin + Brandenburg)
- **GPS-Standort** - Automatische Stationserkennung
- **Intelligente Suche** mit Autocomplete
- **Detaillierte Infos** - Verspätungen, Ausfälle, Gleis/Steig
- **Auto-Refresh** - Alle 30 Sekunden (optional)
- **Offline-Modus** - Gespeicherte Daten anzeigen
### 🗺️ **Intelligenter Routenplaner**
- **Start/Ziel-Suche** mit GPS-Unterstützung
- **5 Min. Umstiegszeit** garantiert
- **Detaillierte Fußwege** mit Gehzeit
- **Alternative Routen** - Mehrere Optionen
- **Robuste Stationserkennung** - Funktioniert auch bei unvollständigen Eingaben
### 🌍 **Live-Map**
- **Echtzeit-Fahrzeugverfolgung** auf Dark-Mode Karte
- **Authentische BVG-Farben** für alle Linien (U-Bahn, S-Bahn, Tram, Bus)
- **Dynamische Bounds** - Nur sichtbare Fahrzeuge laden (bis zu 69% weniger Daten)
- **Filter nach Fahrzeugtyp** - U-Bahn, S-Bahn, Tram, Bus, Fähre
- **API-optimiert** - Intelligentes Caching
### 📱 **Progressive Web App (PWA)**
- **Installierbar** - Als App auf Home-Screen
- **Offline-Fähig** - Service Worker mit Caching
- **Touch-optimiert** - Pull-to-Refresh, Wischgesten
- **Responsive** - Funktioniert auf Mobile & Desktop
- **Dark-Mode** - Schont die Augen
---
## 🚀 Quick Start
### **Option 1: Direkt nutzen**
Öffne die App einfach im Browser - keine Installation nötig!
### **Option 2: Als PWA installieren**
**Mobile (iOS/Android):**
1. Öffne die App im Browser
2. Tippe auf "Teilen" → "Zum Home-Bildschirm"
3. Fertig! App ist jetzt auf deinem Home-Screen
**Desktop (Chrome/Edge):**
1. Öffne die App im Browser
2. Klicke auf das Install-Icon in der Adressleiste
3. Fertig! App ist jetzt in deinen Apps
---
## 🛠️ Installation (für Entwickler)
### **Voraussetzungen**
- Node.js (v16+)
- npm oder yarn
- HTTPS-Server (für PWA-Features)
### **Setup**
```bash
# Repository klonen
git clone https://github.com/Serverlele30/VBB-Status-Web-App.git
cd VBB-Status-Web-App
# Dependencies installieren
npm install
# HTTPS-Server starten
npm start
```
Die App ist jetzt verfügbar unter: `https://localhost:3000`
### **HTTPS-Server**
Die App benötigt HTTPS für PWA-Features (Service Worker, GPS, etc.).
**Server-Skript (`server.js`):**
```javascript
const https = require('https');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const mimeTypes = require('mime-types');
// Auto-generiert SSL-Zertifikate falls nicht vorhanden
// Nutzt OpenSSL für self-signed certificates
```
**SSL-Zertifikate werden automatisch generiert!**
---
## 📂 Projekt-Struktur
``` ```
VBB-Status-Web-App/ vbb-netz-status/
├── index.html # Haupt-HTML (Single-Page App) ├── index.html # HTML-Struktur
├── service-worker.js # PWA Service Worker ├── styles.css # Alle CSS-Styles
├── manifest.json # PWA Manifest ├── script.js # Alle JavaScript-Funktionen
├── server.js # HTTPS Development Server ├── server.js # HTTPS-Entwicklungsserver
├── package.json # Node.js Dependencies ├── service-worker.js # PWA Service Worker
├── icons/ # App-Icons (verschiedene Größen) ├── manifest.json # PWA Manifest
│ ├── icon-192.png ├── package.json # Node.js Dependencies
│ ├── icon-512.png └── LICENSE # MIT Lizenz
│ └── icon-maskable.png
├── fonts/ # Custom Fonts
│ └── DotMatrix.ttf # BVG-Schriftart
└── data/ # Statische Daten
└── station_lines.json # Station-zu-Linie Mappings
``` ```
--- ## 🚀 Installation & Start
## 🎨 Design 1. **Abhängigkeiten installieren:**
```bash
npm install
```
### **Farbschema** 2. **Server starten:**
- **Primär:** `#FFED00` (BVG-Gelb) ```bash
- **Background:** `#000000` (Schwarz) npm start
- **Sekundär:** `#1a1a1a` (Dunkelgrau) ```
- **Text:** `#ffffff` / `#cccccc`
- **Borders:** `#333333`
### **Typografie** 3. **Browser öffnen:**
- **Haupt-Font:** DotMatrix (BVG-Stil) ```
- **Fallback:** Courier New, monospace https://localhost:3000
```
### **Icons & Emojis** ## 📝 Änderungen
- 🚇 U-Bahn
- 🚊 S-Bahn
- 🚋 Tram
- 🚌 Bus
- ⛴️ Fähre
### **BVG-Linienfarben** **Vorher:**
Authentische Farben für alle 40+ Linien: - Alles in einer `index.html` (4698 Zeilen)
- **U-Bahnen:** U1-U9 mit Original-Farben
- **S-Bahnen:** S-Bahn Grün + Ringbahn Orange **Nachher:**
- **Trams:** Metro-Tram Rot + Tram Gelb - `index.html` - Nur HTML-Struktur (~380 Zeilen)
- **Busse:** Gelb + Metro-Bus Rot - `styles.css` - Alle CSS-Regeln (~2300 Zeilen)
- `script.js` - Alle JavaScript-Funktionen (~1990 Zeilen)
## ✅ Vorteile der Trennung
- 📦 **Bessere Organisation** - Jede Datei hat einen klaren Zweck
- 🔧 **Einfachere Wartung** - CSS und JS können unabhängig bearbeitet werden
- ⚡ **Caching** - Browser können CSS/JS separat cachen
- 🎨 **Entwicklung** - Einfacher zu debuggen und zu bearbeiten
- 👥 **Teamarbeit** - Mehrere Entwickler können parallel arbeiten
## 🛠️ Technische Details
- **CSS**: Enthält alle Styles inkl. Dark Mode, Responsive Design, Animationen
- **JavaScript**: Enthält alle Funktionen für Abfahrten, Routen, Live-Map
- **HTML**: Referenziert CSS (`<link>`) und JS (`<script src>`)
## 📱 PWA Unterstützung
Die App funktioniert weiterhin als Progressive Web App:
- Service Worker für Offline-Funktionalität
- Manifest für Installation auf dem Homescreen
- HTTPS-Server für sichere Verbindung
--- ---
## 🔧 Technische Details **Entwickelt von:** Aaron K. & Claude (Anthropic)
**Lizenz:** MIT
### **APIs**
- **VBB Transport REST API v6**
- Endpoint: `https://v6.vbb.transport.rest`
- Rate Limit: 100 Requests/Minute
- [Dokumentation](https://v6.vbb.transport.rest/api.html)
### **Libraries**
- **Leaflet.js** - Interaktive Karten
- **CartoDB Dark Matter** - Karten-Tiles (Dark-Mode)
- Vanilla JavaScript (kein Framework!)
### **Browser-Support**
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile Browser (iOS Safari, Chrome Mobile)
### **Performance**
- **First Contentful Paint:** < 1s
- **Time to Interactive:** < 2s
- **Lighthouse Score:** 95+
- **Bundle Size:** ~150KB (unkomprimiert)
---
## 🗺️ Datenquellen
### **Station-Line Mappings**
Präzise Station-zu-Linie Zuordnungen für 1000+ Stationen:
- Extrahiert via custom Node.js Script
- Analysiert echte Trip-Routen statt generische Location-Searches
- Deckt alle U-Bahn, S-Bahn, Tram und Metro-Linien ab
**Extraktion:**
```bash
node extract_station_lines.js
```
Generiert `data/station_lines.json` mit Format:
```json
{
"900000017101": {
"name": "U Spichernstr.",
"lines": ["U3", "U9"]
}
}
```
---
## 📱 PWA-Features
### **Manifest.json**
```json
{
"name": "VBB Netz Status",
"short_name": "VBB Status",
"start_url": "/",
"display": "standalone",
"theme_color": "#FFED00",
"background_color": "#000000",
"icons": [...]
}
```
### **Service Worker**
- **Cache-First-Strategie** für statische Assets
- **Network-First** für API-Calls
- **Offline-Fallback** für alle Seiten
- **Auto-Update** bei neuer Version
**Cache-Versioning:**
```javascript
const CACHE_NAME = 'vbb-status-v27';
```
### **Offline-Features**
- ✅ Gespeicherte Abfahrten anzeigen
- ✅ Letzte Suchanfragen speichern
- ✅ Offline-Indikator
- ✅ Cached Karten-Tiles
---
## 🎯 Features im Detail
### **GPS-Standort**
```javascript
navigator.geolocation.getCurrentPosition(
(position) => {
const { latitude, longitude } = position.coords;
findNearbyStops(latitude, longitude);
}
);
```
### **Auto-Refresh**
- **Standard:** 30 Sekunden
- **Togglebar:** An/Aus im Header
- **Smart:** Nur sichtbare Values aktualisieren (kein Re-Render)
### **Pull-to-Refresh**
```javascript
// Touch-basiert, nur auf Mobile
// Haptic Feedback via navigator.vibrate()
```
### **Autocomplete-Suche**
- **Debounced:** 300ms Verzögerung
- **Min. 2 Zeichen** für Suche
- **Keyboard-Navigation:** ↑↓ + Enter
- **Touch-optimiert:** Große Tap-Targets
### **Modal-Details**
- **Trip-Details** per Tap auf Abfahrt
- **Route-Details** mit Zwischenstopps
- **Fußweg-Anleitung** mit Distanz/Zeit
- **Swipe-to-Close** auf Mobile
---
## 🔒 Datenschutz
- ✅ **Keine Cookies**
- ✅ **Kein Tracking**
- ✅ **Keine Werbung**
- ✅ **Kein Analytics**
- ✅ **GPS nur auf Anfrage** (Browser-Permission)
- ✅ **Lokale Speicherung** (localStorage, keine Server)
**Alle Daten bleiben auf deinem Gerät!**
---
## 🐛 Bekannte Probleme
### **API-Limits**
- VBB API: 100 Requests/Minute
- Bei Überschreitung: 429 Error → Retry nach 60s
### **GPS-Genauigkeit**
- Abhängig von Gerät & Standort
- Indoor oft ungenau
- Fallback: Manuelle Suche
### **Browser-Kompatibilität**
- Service Worker: Nur HTTPS
- GPS: Nur Secure Context (HTTPS oder localhost)
- Ältere Browser: Eingeschränkte Features
---
## 🤝 Contributing
Contributions sind willkommen! 🎉
### **Workflow**
1. Fork das Repository
2. Erstelle einen Feature-Branch (`git checkout -b feature/AmazingFeature`)
3. Commit deine Änderungen (`git commit -m 'Add some AmazingFeature'`)
4. Push zum Branch (`git push origin feature/AmazingFeature`)
5. Öffne einen Pull Request
### **Code-Style**
- **Vanilla JavaScript** (kein TypeScript)
- **Kommentare** für komplexe Logik
- **Konsistente Formatierung** (2 Spaces, Semikolons)
- **BVG-Farbschema** beibehalten
---
## 📝 Changelog
Siehe [CHANGELOG.md](CHANGELOG.md) für Details zu allen Updates.
**Latest:** v27.0 - Credits & Header Update
---
## 📄 Lizenz
Dieses Projekt ist unter der **MIT License** lizenziert - siehe [LICENSE](LICENSE) für Details.
**Das bedeutet:**
- ✅ Kostenlos nutzbar
- ✅ Für private & kommerzielle Projekte
- ✅ Modifizierbar
- ✅ Weitergabe erlaubt
**Aber:**
- ⚠️ Ohne Garantie
- ⚠️ Auf eigene Verantwortung
---
## 🙏 Credits
### **Entwicklung**
- **Aaron K.** - Initial Development & Design
- **Claude (Anthropic)** - AI-Assisted Development
### **Daten & APIs**
- **VBB Transport REST API v6** - [v6.vbb.transport.rest](https://v6.vbb.transport.rest)
- **OpenStreetMap Contributors** - Kartendaten
- **CartoDB** - Dark Matter Map Tiles
### **Schriftart**
- **DotMatrix** by [@NikBLN](https://github.com/NikBLN)
### **Inspiration**
- **BVG** - Design & Farbschema
- **VBB** - Verkehrsverbund Berlin-Brandenburg
---
## 📬 Kontakt
**Repository:** [github.com/Serverlele30/VBB-Status-Web-App](https://github.com/Serverlele30/VBB-Status-Web-App)
**Issues:** [GitHub Issues](https://github.com/Serverlele30/VBB-Status-Web-App/issues)
---
## ⚠️ Disclaimer
Diese App ist ein **inoffizielles Projekt** und wird **nicht** von VBB oder BVG betrieben oder unterstützt.
Alle Daten stammen von der öffentlichen VBB Transport REST API.
**Keine Garantie für:**
- Richtigkeit der Daten
- Verfügbarkeit der API
- Fehlerfreien Betrieb
**Nutze die App auf eigene Verantwortung!**
---
<div align="center">
Made with ❤️ for Berlin & Brandenburg
**[⬆ Back to Top](#vbb-netz-status)**
</div>
+3 -4301
View File
File diff suppressed because it is too large. Load diff
+26 -26
View File
@@ -1,26 +1,26 @@
{ {
"name": "VBB Netz Status", "name": "VBB Netz Status",
"short_name": "VBB Status", "short_name": "VBB Status",
"description": "Echtzeit-Abfahrtsmonitor für den Verkehrsverbund Berlin-Brandenburg - by Aaron K.", "description": "Echtzeit-Abfahrtsmonitor für den Verkehrsverbund Berlin-Brandenburg - by Aaron K.",
"start_url": "/", "start_url": "/",
"display": "standalone", "display": "standalone",
"background_color": "#000000", "background_color": "#000000",
"theme_color": "#000000", "theme_color": "#000000",
"orientation": "portrait", "orientation": "portrait",
"icons": [ "icons": [
{ {
"src": "images/favicon.png", "src": "images/favicon.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png", "type": "image/png",
"purpose": "any maskable" "purpose": "any maskable"
}, },
{ {
"src": "images/favicon.png", "src": "images/favicon.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png", "type": "image/png",
"purpose": "any maskable" "purpose": "any maskable"
} }
], ],
"categories": ["travel", "navigation"], "categories": ["travel", "navigation"],
"lang": "de-DE" "lang": "de-DE"
} }
+41 -41
View File
@@ -1,41 +1,41 @@
{ {
"name": "vbb-netz-status", "name": "vbb-netz-status",
"version": "29.0.0", "version": "29.0.0",
"description": "Live-Nahverkehr für Berlin & Brandenburg - Progressive Web App (PWA) für Echtzeit-Abfahrten, Routenplanung und Live-Fahrzeugverfolgung im VBB-Gebiet", "description": "Live-Nahverkehr für Berlin & Brandenburg - Progressive Web App (PWA) für Echtzeit-Abfahrten, Routenplanung und Live-Fahrzeugverfolgung im VBB-Gebiet",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
"start": "node server.js", "start": "node server.js",
"dev": "node server.js" "dev": "node server.js"
}, },
"keywords": [ "keywords": [
"vbb", "vbb",
"bvg", "bvg",
"berlin", "berlin",
"brandenburg", "brandenburg",
"transit", "transit",
"public-transport", "public-transport",
"pwa", "pwa",
"real-time", "real-time",
"departures", "departures",
"route-planner", "route-planner",
"live-map" "live-map"
], ],
"author": "Aaron K. & Claude (Anthropic)", "author": "Aaron K. & Claude (Anthropic)",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/Serverlele30/VBB-Status-Web-App.git" "url": "https://github.com/Serverlele30/VBB-Status-Web-App.git"
}, },
"bugs": { "bugs": {
"url": "https://github.com/Serverlele30/VBB-Status-Web-App/issues" "url": "https://github.com/Serverlele30/VBB-Status-Web-App/issues"
}, },
"homepage": "https://github.com/Serverlele30/VBB-Status-Web-App#readme", "homepage": "https://github.com/Serverlele30/VBB-Status-Web-App#readme",
"dependencies": { "dependencies": {
"mime-types": "^2.1.35" "mime-types": "^2.1.35"
}, },
"devDependencies": {}, "devDependencies": {},
"engines": { "engines": {
"node": ">=16.0.0", "node": ">=16.0.0",
"npm": ">=8.0.0" "npm": ">=8.0.0"
} }
} }
+1992
View File
File diff suppressed because it is too large. Load diff
+116 -116
View File
@@ -1,116 +1,116 @@
const https = require('https'); const https = require('https');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { execSync } = require('child_process'); const { execSync } = require('child_process');
const mimeTypes = require('mime-types'); const mimeTypes = require('mime-types');
const PORT = 3000; const PORT = 3000;
const CERT_DIR = path.join(__dirname, 'certs'); const CERT_DIR = path.join(__dirname, 'certs');
const CERT_FILE = path.join(CERT_DIR, 'cert.pem'); const CERT_FILE = path.join(CERT_DIR, 'cert.pem');
const KEY_FILE = path.join(CERT_DIR, 'key.pem'); const KEY_FILE = path.join(CERT_DIR, 'key.pem');
// Create certs directory if it doesn't exist // Create certs directory if it doesn't exist
if (!fs.existsSync(CERT_DIR)) { if (!fs.existsSync(CERT_DIR)) {
fs.mkdirSync(CERT_DIR); fs.mkdirSync(CERT_DIR);
} }
// Generate self-signed certificate if it doesn't exist // Generate self-signed certificate if it doesn't exist
if (!fs.existsSync(CERT_FILE) || !fs.existsSync(KEY_FILE)) { if (!fs.existsSync(CERT_FILE) || !fs.existsSync(KEY_FILE)) {
console.log('🔐 Generating self-signed SSL certificate...'); console.log('🔐 Generating self-signed SSL certificate...');
try { try {
execSync(`openssl req -x509 -newkey rsa:4096 -keyout "${KEY_FILE}" -out "${CERT_FILE}" -days 365 -nodes -subj "/CN=localhost"`, { execSync(`openssl req -x509 -newkey rsa:4096 -keyout "${KEY_FILE}" -out "${CERT_FILE}" -days 365 -nodes -subj "/CN=localhost"`, {
stdio: 'inherit' stdio: 'inherit'
}); });
console.log('✅ Certificate generated successfully!'); console.log('✅ Certificate generated successfully!');
} catch (error) { } catch (error) {
console.error('❌ Error generating certificate:', error.message); console.error('❌ Error generating certificate:', error.message);
console.log('📝 Please install OpenSSL or create certificates manually.'); console.log('📝 Please install OpenSSL or create certificates manually.');
process.exit(1); process.exit(1);
} }
} }
// HTTPS server options // HTTPS server options
const options = { const options = {
key: fs.readFileSync(KEY_FILE), key: fs.readFileSync(KEY_FILE),
cert: fs.readFileSync(CERT_FILE) cert: fs.readFileSync(CERT_FILE)
}; };
// Create HTTPS server // Create HTTPS server
const server = https.createServer(options, (req, res) => { const server = https.createServer(options, (req, res) => {
// Remove query parameters and get clean path // Remove query parameters and get clean path
let filePath = req.url.split('?')[0]; let filePath = req.url.split('?')[0];
// Default to index.html for root // Default to index.html for root
if (filePath === '/') { if (filePath === '/') {
filePath = '/index.html'; filePath = '/index.html';
} }
// Construct full file path // Construct full file path
const fullPath = path.join(__dirname, filePath); const fullPath = path.join(__dirname, filePath);
// Security check: prevent directory traversal // Security check: prevent directory traversal
const normalizedPath = path.normalize(fullPath); const normalizedPath = path.normalize(fullPath);
if (!normalizedPath.startsWith(__dirname)) { if (!normalizedPath.startsWith(__dirname)) {
res.writeHead(403); res.writeHead(403);
res.end('Forbidden'); res.end('Forbidden');
return; return;
} }
// Check if file exists // Check if file exists
fs.access(fullPath, fs.constants.F_OK, (err) => { fs.access(fullPath, fs.constants.F_OK, (err) => {
if (err) { if (err) {
res.writeHead(404); res.writeHead(404);
res.end('File not found'); res.end('File not found');
return; return;
} }
// Get MIME type // Get MIME type
const mimeType = mimeTypes.lookup(fullPath) || 'application/octet-stream'; const mimeType = mimeTypes.lookup(fullPath) || 'application/octet-stream';
// Read and serve file // Read and serve file
fs.readFile(fullPath, (err, data) => { fs.readFile(fullPath, (err, data) => {
if (err) { if (err) {
res.writeHead(500); res.writeHead(500);
res.end('Error reading file'); res.end('Error reading file');
return; return;
} }
// Set appropriate headers // Set appropriate headers
res.writeHead(200, { res.writeHead(200, {
'Content-Type': mimeType, 'Content-Type': mimeType,
'Cache-Control': 'no-cache' 'Cache-Control': 'no-cache'
}); });
res.end(data); res.end(data);
}); });
}); });
}); });
// Start server // Start server
server.listen(PORT, () => { server.listen(PORT, () => {
console.log(''); console.log('');
console.log('🚀 VBB Netz Status - HTTPS Development Server'); console.log('🚀 VBB Netz Status - HTTPS Development Server');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(`✅ Server running at: https://localhost:${PORT}`); console.log(`✅ Server running at: https://localhost:${PORT}`);
console.log(''); console.log('');
console.log('📱 To test on mobile:'); console.log('📱 To test on mobile:');
console.log(' 1. Find your local IP: ipconfig (Windows) or ifconfig (Mac/Linux)'); console.log(' 1. Find your local IP: ipconfig (Windows) or ifconfig (Mac/Linux)');
console.log(' 2. Open https://YOUR_IP:3000 on your mobile device'); console.log(' 2. Open https://YOUR_IP:3000 on your mobile device');
console.log(' 3. Accept the self-signed certificate warning'); console.log(' 3. Accept the self-signed certificate warning');
console.log(''); console.log('');
console.log('⚠️ Note: Your browser will show a security warning.'); console.log('⚠️ Note: Your browser will show a security warning.');
console.log(' This is normal for self-signed certificates in development.'); console.log(' This is normal for self-signed certificates in development.');
console.log(' Click "Advanced" → "Proceed to localhost" to continue.'); console.log(' Click "Advanced" → "Proceed to localhost" to continue.');
console.log(''); console.log('');
console.log('🛑 Press Ctrl+C to stop the server'); console.log('🛑 Press Ctrl+C to stop the server');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(''); console.log('');
}); });
// Graceful shutdown // Graceful shutdown
process.on('SIGINT', () => { process.on('SIGINT', () => {
console.log('\n\n👋 Shutting down server...'); console.log('\n\n👋 Shutting down server...');
server.close(() => { server.close(() => {
console.log('✅ Server stopped'); console.log('✅ Server stopped');
process.exit(0); process.exit(0);
}); });
}); });
+69 -69
View File
@@ -1,69 +1,69 @@
const CACHE_NAME = 'vbb-status-v29'; const CACHE_NAME = 'vbb-status-v29';
const urlsToCache = [ const urlsToCache = [
'/', '/',
'/index.html', '/index.html',
'/manifest.json', '/manifest.json',
'/DotMatrix.ttf', '/DotMatrix.ttf',
'/images/favicon.png' '/images/favicon.png'
]; ];
// Installation // Installation
self.addEventListener('install', event => { self.addEventListener('install', event => {
event.waitUntil( event.waitUntil(
caches.open(CACHE_NAME) caches.open(CACHE_NAME)
.then(cache => { .then(cache => {
console.log('Cache geöffnet'); console.log('Cache geöffnet');
return cache.addAll(urlsToCache); return cache.addAll(urlsToCache);
}) })
); );
self.skipWaiting(); self.skipWaiting();
}); });
// Aktivierung // Aktivierung
self.addEventListener('activate', event => { self.addEventListener('activate', event => {
event.waitUntil( event.waitUntil(
caches.keys().then(cacheNames => { caches.keys().then(cacheNames => {
return Promise.all( return Promise.all(
cacheNames.map(cacheName => { cacheNames.map(cacheName => {
if (cacheName !== CACHE_NAME) { if (cacheName !== CACHE_NAME) {
console.log('Alter Cache wird gelöscht:', cacheName); console.log('Alter Cache wird gelöscht:', cacheName);
return caches.delete(cacheName); return caches.delete(cacheName);
} }
}) })
); );
}) })
); );
self.clients.claim(); self.clients.claim();
}); });
// Fetch // Fetch
self.addEventListener('fetch', event => { self.addEventListener('fetch', event => {
event.respondWith( event.respondWith(
caches.match(event.request) caches.match(event.request)
.then(response => { .then(response => {
// Cache hit - return response // Cache hit - return response
if (response) { if (response) {
return response; return response;
} }
return fetch(event.request).then( return fetch(event.request).then(
response => { response => {
// Check if valid response // Check if valid response
if (!response || response.status !== 200 || response.type !== 'basic') { if (!response || response.status !== 200 || response.type !== 'basic') {
return response; return response;
} }
// Clone the response // Clone the response
const responseToCache = response.clone(); const responseToCache = response.clone();
caches.open(CACHE_NAME) caches.open(CACHE_NAME)
.then(cache => { .then(cache => {
cache.put(event.request, responseToCache); cache.put(event.request, responseToCache);
}); });
return response; return response;
} }
); );
}) })
); );
}); });
+2314
View File
File diff suppressed because it is too large. Load diff