PWA-Unterstützung hinzugefügt: manifest.webmanifest, Service Worker, Installierbarkeit auf Homescreen/Desktop

This commit is contained in:
2025-08-19 12:58:47 +02:00
parent b2cd91b970
commit c93a813c96
4 changed files with 78 additions and 1 deletions

13
app.py
View File

@@ -1,7 +1,7 @@
from pathlib import Path
import json
from typing import Tuple, Dict, List
from flask import Flask, render_template, request
from flask import Flask, render_template, request, send_from_directory
app = Flask(__name__)
@@ -77,5 +77,16 @@ def index():
)
@app.route('/manifest.webmanifest')
def manifest_file():
return send_from_directory(Path(__file__).parent / 'static', 'manifest.webmanifest', mimetype='application/manifest+json')
@app.route('/sw.js')
def service_worker():
# Service Worker muss auf Top-Level liegen
return send_from_directory(Path(__file__).parent / 'static', 'sw.js', mimetype='application/javascript')
if __name__ == "__main__":
app.run(debug=True)

View File

@@ -0,0 +1,18 @@
{
"name": "WordleCheater",
"short_name": "WCheater",
"description": "Hilft bei der Lösung deutschsprachiger WordleRätsel mit Positions- und Buchstabenfiltern.",
"start_url": "/",
"scope": "/",
"display": "standalone",
"background_color": "#0b1220",
"theme_color": "#0b1220",
"icons": [
{
"src": "/static/favicon.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "any maskable"
}
]
}

39
static/sw.js Normal file
View File

@@ -0,0 +1,39 @@
const CACHE_NAME = 'wordle-cheater-v1';
const APP_SHELL = [
'/',
'/static/favicon.svg',
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => cache.addAll(APP_SHELL))
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) => Promise.all(
keys.map((k) => (k === CACHE_NAME ? null : caches.delete(k)))
))
);
});
self.addEventListener('fetch', (event) => {
const { request } = event;
// Netzwerk zuerst für HTML, sonst Cache-First
if (request.mode === 'navigate') {
event.respondWith(
fetch(request).catch(() => caches.match('/'))
);
return;
}
event.respondWith(
caches.match(request).then((cached) =>
cached || fetch(request).then((resp) => {
const copy = resp.clone();
caches.open(CACHE_NAME).then((cache) => cache.put(request, copy));
return resp;
})
)
);
});

View File

@@ -15,6 +15,8 @@
<meta name="twitter:title" content="WordleCheater (DE)" />
<meta name="twitter:description" content="Finde deutsche 5BuchstabenWörter mit Positions- und Buchstabenfiltern. Quellen: OpenThesaurus & wordfreq." />
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='favicon.svg') }}" />
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="theme-color" content="#0b1220" />
<meta name="color-scheme" content="light dark" />
<script>
(function() {
@@ -183,5 +185,12 @@
});
})();
</script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js');
});
}
</script>
</body>
</html>