From cbc03c56bfbcf7ea2da7a1d593ef0213505651eb Mon Sep 17 00:00:00 2001 From: Tronax Date: Tue, 25 Aug 2026 19:12:12 +0200 Subject: [PATCH] feat: add PWA support and mobile-responsive layouts - Add web app manifest, maskable/apple-touch icons, and a production-only service worker that caches the app shell for offline start - Improve mobile UX: responsive breakpoints from ~320px, 44px touch targets, safe-area insets, dvh heights, 16px inputs to avoid iOS zoom - Serve .webmanifest with correct content type in the Go static handler - Document PWA behavior and mobile features in the README --- README.md | 19 ++++ backend/internal/httpapi/server.go | 3 + frontend/index.html | 8 +- frontend/public/icons/apple-touch-icon.svg | 14 +++ frontend/public/icons/icon-maskable.svg | 13 +++ frontend/public/icons/icon.svg | 13 +++ frontend/public/manifest.webmanifest | 22 +++++ .../src/components/SectionConnections.vue | 10 +- frontend/src/components/SectionRequests.vue | 13 +++ frontend/src/components/ShareLinkCard.vue | 9 ++ frontend/src/main.ts | 9 ++ frontend/src/styles/main.css | 37 +++++++- frontend/src/views/BookingView.vue | 14 ++- frontend/src/views/DashboardView.vue | 2 + frontend/src/views/LandingView.vue | 7 ++ frontend/src/views/LoginView.vue | 1 + frontend/src/views/RegisterView.vue | 1 + frontend/vite.config.ts | 91 ++++++++++++++++++- 18 files changed, 277 insertions(+), 9 deletions(-) create mode 100644 frontend/public/icons/apple-touch-icon.svg create mode 100644 frontend/public/icons/icon-maskable.svg create mode 100644 frontend/public/icons/icon.svg create mode 100644 frontend/public/manifest.webmanifest diff --git a/README.md b/README.md index d361d95..32130dc 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Kalender nie. - 📨 **Buchungsanfragen** annehmen/ablehnen; angenommene Zeiten werden belegt und verhindern Doppelbuchungen - ⚙️ Buchungsregeln: Zeitfenster, Slot-Raster (10–60 Min), Dauern, Wochentage, Horizont (1–120 Tage), Zeitzone - 🧊 **Liquid-Glass-UI** mit **Dark-/Light-Mode**: Umschalter (Auto / Dunkel / Hell) auf jeder Seite, automatische Systemerkennung (`prefers-color-scheme`) inkl. Live-Wechsel, Auswahl wird pro Browser gespeichert +- 📱 **Voll mobilfähig**: responsive Layouts ab ~320 px, 44px-Touch-Targets, kein iOS-Fokus-Zoom (16px-Inputs), Safe-Area-Unterstützung (Notch), `dvh`-Höhen, `touch-action` ohne Doppeltipp-Zoom +- 📲 **PWA**: installierbar (Android/Desktop: „App installieren“, iOS: „Zum Home-Bildschirm“), Manifest mit Maskable-Icons, App-Shortcuts; Service Worker cached die App-Shell → Startseite funktioniert offline (API-Aufrufe brauchen natürlich Netz) - 🔒 Provider-Tokens werden **AES-256-GCM-verschlüsselt** in der SQLite-DB gespeichert ## Tech Stack @@ -58,6 +60,13 @@ go run ./cmd/server Der Go-Server liefert dann das Frontend (`dist/`) **und** die API über einen Port. +### PWA-Hinweise + +- Der Service Worker wird nur im Production-Build registriert (`npm run build` + Auslieferung über `STATIC_DIR`), nicht im Vite-Dev-Modus. +- Die Cache-Version des Service Workers wird pro Build automatisch neu gesetzt (Build-Zeitstempel) — nach einem Deploy holen Clients die neue Version und alte Caches werden geräumt. +- `/api/*` wird niemals gecached; offline funktioniert die App-Shell (Startseite/Navigation), Kalender- und Buchungsdaten benötigen eine Verbindung. +- Icons liegen als SVG-Quellen in `frontend/public/icons/` und werden per `rsvg-convert` zu PNGs konvertiert (Neuerzeugung: siehe Skript unten im Abschnitt „Tests“). + ## Kalender-Anbindung einrichten ### Google @@ -130,3 +139,13 @@ frontend/ ```bash cd backend && go test ./... # ICS-Parser, Dauer-Handling, Interval-Clamping ``` + +PWA-Icons neu erzeugen (benötigt `rsvg-convert`): + +```bash +cd frontend/public/icons +rsvg-convert -w 192 -h 192 -o icon-192.png icon.svg +rsvg-convert -w 512 -h 512 -o icon-512.png icon.svg +rsvg-convert -w 512 -h 512 -o icon-maskable-512.png icon-maskable.svg +rsvg-convert -w 180 -h 180 -o apple-touch-icon.png apple-touch-icon.svg +``` diff --git a/backend/internal/httpapi/server.go b/backend/internal/httpapi/server.go index b884008..da9287d 100644 --- a/backend/internal/httpapi/server.go +++ b/backend/internal/httpapi/server.go @@ -78,6 +78,9 @@ func (s *Server) Router() http.Handler { static := s.Cfg.StaticDir r.Get("/*", func(w http.ResponseWriter, req *http.Request) { p := filepath.Join(static, filepath.Clean(req.URL.Path)) + if strings.HasSuffix(p, ".webmanifest") { + w.Header().Set("Content-Type", "application/manifest+json") + } if st, err := os.Stat(p); err == nil && !st.IsDir() { http.ServeFile(w, req, p) return diff --git a/frontend/index.html b/frontend/index.html index 6be70bb..ae46ef2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,8 +3,14 @@ - + + + + + + +