diff --git a/backend/main.py b/backend/main.py
index 64eb22b..0060e20 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -190,4 +190,8 @@ if config.FRONTEND_DIST.exists():
async def spa(pfad: str):
if pfad.startswith("api/"):
raise HTTPException(404, "Unbekannter API-Pfad")
+ # Statische Dateien des Frontends (Manifest, Icons) direkt ausliefern, alles andere ist die App
+ datei = (config.FRONTEND_DIST / pfad).resolve()
+ if pfad and datei.is_file() and config.FRONTEND_DIST.resolve() in datei.parents:
+ return FileResponse(datei)
return FileResponse(config.FRONTEND_DIST / "index.html")
diff --git a/frontend/index.html b/frontend/index.html
index 5d20fea..16c5ed3 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,6 +4,10 @@
buchwerk
+
+
+
+
diff --git a/frontend/public/icons/icon-192.png b/frontend/public/icons/icon-192.png
new file mode 100644
index 0000000..701acdb
Binary files /dev/null and b/frontend/public/icons/icon-192.png differ
diff --git a/frontend/public/icons/icon-512.png b/frontend/public/icons/icon-512.png
new file mode 100644
index 0000000..0f6e46e
Binary files /dev/null and b/frontend/public/icons/icon-512.png differ
diff --git a/frontend/public/manifest.webmanifest b/frontend/public/manifest.webmanifest
new file mode 100644
index 0000000..592c62f
--- /dev/null
+++ b/frontend/public/manifest.webmanifest
@@ -0,0 +1,16 @@
+{
+ "name": "buchwerk",
+ "short_name": "buchwerk",
+ "description": "Sachbücher lesen",
+ "lang": "de",
+ "start_url": "/",
+ "scope": "/",
+ "display": "fullscreen",
+ "orientation": "portrait",
+ "background_color": "#000000",
+ "theme_color": "#000000",
+ "icons": [
+ { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable" },
+ { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
+ ]
+}
diff --git a/frontend/src/components/Lesemodus.vue b/frontend/src/components/Lesemodus.vue
index 69252d4..54f1bb7 100644
--- a/frontend/src/components/Lesemodus.vue
+++ b/frontend/src/components/Lesemodus.vue
@@ -46,13 +46,19 @@ function html(s) {
return cache.get(key)
}
-function vor() { if (pos.value < screens.value.length - 1) pos.value++ }
+// Nach dem Sperren des Handys ist das Vollbild weg; ein Tippen darf es wieder anfordern. Als installierte App unnötig.
+function vollbildHolen() {
+ if (document.fullscreenElement || !document.documentElement.requestFullscreen) return
+ if (matchMedia('(display-mode: fullscreen), (display-mode: standalone)').matches) return
+ document.documentElement.requestFullscreen().catch(() => {})
+}
+function vor() { vollbildHolen(); if (pos.value < screens.value.length - 1) pos.value++ }
// Von vorn: auch die Buchansicht zurücksetzen, sonst zöge sie den Lesemodus wieder nach hinten
async function vonVorn() {
await api.positionSetzen(props.slug, props.version, { abschnitt: 'vorwort', lesemodus: 'vorwort', zuletzt: 'lesen' }).catch(() => {})
pos.value = 0
}
-function zurueck() { if (pos.value > 0) pos.value-- }
+function zurueck() { vollbildHolen(); if (pos.value > 0) pos.value-- }
let merkTimer = null
watch(pos, (p) => {
buehne.value?.scrollTo({ top: 0 })