Commit graph

14 commits

Author SHA1 Message Date
Eddy
707638808c Teilen aus WhatsApp: Bilder UND Text landen jetzt wirklich im Auftrag [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Jeder Teilen-Vorgang endete bisher in einer Sackgasse — Login-Hinweis oder
"Keine geteilten Fotos gefunden", und danach war das Geteilte weg. Zwei Ursachen:

1. share.html prüfte api.getToken() — ein JWT in IndexedDB, das es seit der
   SSO-Umstellung nicht mehr gibt (api.login() legt nur noch 'user' ab, die
   Sitzung steckt im HttpOnly-Cookie awl_sso). Der Wert war immer leer, also kam
   IMMER "Bitte zuerst anmelden"; der Weg "Zur App" verwarf das Geteilte.
   Jetzt: Cookie-Prüfung über api/verify.php wie in ensureAuth(), und die
   Anmeldung (Passwort + Passkey) läuft IN der Teilen-Seite — das Geteilte bleibt
   dabei gesichert und der Ablauf geht danach direkt weiter.

2. Der Service Worker sicherte nur Dateien. Titel, Text und Link aus dem
   share_target wurden weggeworfen, ein reiner Text-Share schrieb gar nichts.
   Jetzt wird das ganze Paket gesichert und immer weitergeleitet (absolute
   Redirect-URL, leere File-Platzhalter fliegen raus).

Die Teilen-Seite zeigt Bildvorschau, Betreff und Text zum Nachbessern und eine
Auftragssuche (ohne Suchbegriff die offenen Aufträge, mit Suchbegriff alle).
Beim Ablegen gehen die Bilder über die normale Upload-Queue (Persist-First),
der Text wird als notiz_*.txt über api/note.php gespeichert. Scheitert die
Notiz (kein Netz), bleibt der Text gesichert und der Vorgang ist wiederholbar.

Dazu ein Banner in der App, wenn noch ein Paket unabgelegt bereitliegt —
abgebrochene Vorgänge findet sonst niemand wieder. share.html liest auch den
alten IndexedDB-Schlüssel, damit der erste Share nach dem Deploy (noch alter
Service Worker) nicht verlorengeht.

Lokal durchgespielt: Bild+Text, nur Text, und abgemeldet teilen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 18:03:46 +02:00
Eddy
c2bf4e7c30 Background Sync, volle Kameraqualitaet, Persist-First streng [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Drei Sachen, die zusammengehoeren — alle drei Ursachen dafuer, dass Fotos
fehlten oder nichts drauf zu erkennen war.

1. BACKGROUND SYNC (sw.js)
   Nachliefern lief bisher NUR in der offenen Seite: online-Ereignis,
   „wieder sichtbar", 15-Sekunden-Takt. Display aus oder App weggewischt =
   eingefrorene Timer, es passierte nichts. Der Service Worker haengt sich
   jetzt an dieselbe IndexedDB-Queue und laedt selbst hoch; die Anmeldung
   steckt im HttpOnly-Cookie awl_sso und geht bei same-origin automatisch mit,
   also braucht es dort kein Token-Handling.
   - geloescht wird nur bei bestaetigtem Upload: 2xx UND application/json UND
     relpath. 2xx mit HTML (Proxy/abgelaufene Anmeldung) gilt als Fehlschlag
   - bleibt etwas offen, wird das Sync-Versprechen abgelehnt -> der Browser
     stellt erneut zu
   - Erfolg meldet der SW per postMessage an die App (Badge/Miniaturen)
   - periodicSync zusaetzlich, falls der Browser ihn gewaehrt

2. VOLLE KAMERAQUALITAET (app.js)
   Ausgeloest wird jetzt ueber ImageCapture.takePhoto() — das liefert die
   native JPEG-Datei der Kamera in Sensoraufloesung samt EXIF, statt ein
   Standbild aus dem Video-Stream abzugreifen. Kann der Browser das nicht,
   bleibt das Standbild als Rueckfallebene (dann mit Qualitaet 0.95 statt 0.92).
   Verkleinert wird nur noch, wenn es im Admin eingestellt ist (Vorgabe: nein).

3. PERSIST-FIRST STRENG (app.js)
   Das Foto geht unveraendert und als allererstes in die Queue; Verkleinern
   passiert erst DANACH und ersetzt den Eintrag nur bei Erfolg
   (offline.replaceQueuedBlob). Vorher lag das Verkleinern davor — und weil es
   bei ausgeschaltetem Display haengen bleibt, war das Foto in dem Moment
   nirgends gesichert. Genau so gingen am 28.08. acht Fotos verloren. Jetzt
   kann nach dem Sichern nichts mehr passieren, was ein Foto kostet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 19:07:06 +02:00
Eddy
4a53ab0ebe Textnotizen, echte Thumbnails, eigene Dialoge, Bild-Cache
Textnotizen: neuer Punkt "Notizen (n)" am Auftrag, direkt unter der Sprachnotiz.
Liste mit Betreff, Vorschau und Zeitstempel; antippen oeffnet die Notiz zum Lesen und
Aendern, loeschen mit Rueckfrage. Gespeichert wird ueber api/note.php als
notiz_<betreff>_<datum>.txt im Auftragsordner - derselbe Weg wie bei der Sprachnotiz,
damit die Notiz auch im Dolibarr-Auftrag und in der Anhaenge-Spalte des Bericht-Editors
auftaucht. In "Weitere Dokumente" sind Notizen ausgefiltert, sie haetten dort doppelt
gestanden.

Fotokacheln laden jetzt serverseitige Thumbnails (photo.php?size=thumb) statt der
Originale: rund 10 KB statt mehrerer hundert KB je Kachel. Das <img> haengt direkt an
der URL statt an einer Blob-URL - damit greifen HTTP-Cache und loading="lazy"
tatsaechlich und der Browser laedt parallel. Vorher lief eine sequenzielle Schleife, die
jedes Foto komplett holte, bevor das naechste anfing, und im Fehlerfall ein zweites Mal.

Bericht-Seiten zeigen composite_path, wenn vorhanden - also das im Editor gebaute
Seitenbild mit Anmerkungen statt der Rohdatei. Raster-Layouts bekommen ein Kennzeichen
("4"); Seiten ohne Bildquelle zeigen keine Fehlerkachel mehr.

confirm/alert/prompt sind an allen zehn Stellen durch eigene Modale ersetzt
(confirmDialog/alertDialog/inputDialog). Browser-Dialoge zeigen in der installierten PWA
die Herkunfts-URL und wirken wie ein Systemfehler. Der Hardware-Zurueck-Button schliesst
sie als Abbruch.

Service Worker: eigener Cache baustelle-media (cache-first, LRU 300) fuer Thumbnails.
Vorher war ohne Netz kein einziges schon angesehenes Foto verfuegbar. Der Cache ueberlebt
Deploys bewusst und wird beim Abmelden geleert (CLEAR_MEDIA), damit keine Kundenfotos auf
dem Geraet zurueckbleiben.

Nebenbei behoben:
- .modal-header, .close-btn und .modal-body hatten ueberhaupt kein CSS, obwohl das Markup
  sie nutzt (u. a. beim Loeschen eines Berichts) - der Schliessen-Knopf sass unter der
  Ueberschrift statt daneben.
- Das Laden eines Thumbnails ueberschrieb den ganzen Kachel-Inhalt und nahm die Overlays
  mit: Auswahl-Haekchen und Seitennummer verschwanden, sobald das Bild da war.
- manifest.webmanifest: share_target.action war eine absolute URL auf den Prod-Host und
  lag damit ausserhalb des Scopes - der Browser verwarf das share_target komplett. Jetzt
  relativ ("share.html"), funktioniert lokal und auf Prod.

ROADMAP.md neu angelegt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 18:12:09 +02:00
7c9563ec90 feat: PWA Cache-Busting via filemtime (claude-db #201) — kein manuelles Hochzählen mehr
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Das bisherige 'CACHE = baustelle-vN' Pattern erforderte, dass ich bei
jeder Änderung drei Stellen synchron halte (sw.js, index.html ?v=,
manifest). Eddy hat klargestellt dass das nicht akzeptabel ist.

Fix nach KB #201 Pattern (referenz: dolibarr.stundenzettel v2.2.0):

1. index.html → index.php
   PHP berechnet bei jedem Request filemtime() von app.css, app.js,
   lib/*.js, manifest.webmanifest. Die mtimes kommen automatisch
   beim Deploy (rsync preserviert sie default) und werden als ?v=
   an alle Asset-URLs gehängt.

2. sw.js liest Version aus eigener URL-Query:
   const SW_VERSION = (new URL(self.location.href)).searchParams.get('v')
   const CACHE = 'baustelle-' + SW_VERSION
   activate() löscht alle caches die mit 'baustelle-' anfangen aber
   nicht der aktuelle sind.

3. Client-Registration mit Auto-Update:
   - setInterval 60s reg.update()
   - visibilitychange-Listener für Tab-Fokus
   - updatefound → SKIP_WAITING postMessage
   - controllerchange → einmaliger location.reload

4. SHELL pre-cache enthält nur statische Dateien (index.php, share.html,
   icons). CSS/JS werden beim ersten fetch dynamisch gecached — so
   gibt es keinen Mix zwischen alten und neuen ?v= Versionen.

5. manifest.webmanifest start_url auf /custom/baustelle/index.php

Ergebnis: Ich deploye → mtime ändert sich → neue URLs → Browser holt
frische Files → SW aktiviert automatisch beim nächsten Tab-Fokus.
Nie wieder manuelles Hochzählen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:26:26 +02:00
5e80d78f41 fix: Manifest-Installability-Kriterien für Chrome Android
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Chrome Android zeigte nur 'Zum Startbildschirm hinzufügen' statt
'App installieren', weil:
1. 'any maskable' als kombinierter purpose reicht Chrome nicht —
   braucht mindestens ein reines 'any'-Icon für den Install-Prompt
2. start_url/scope waren relativ (./) — mit absoluten Pfaden zum
   custom/baustelle/-Root ist der Scope eindeutig

Fixes:
- icons: je 192/512 als 'any' UND zusätzlich als 'maskable' (4 Einträge)
- id, start_url, scope auf '/custom/baustelle/' gesetzt (absolut)
- categories, dir: ltr dazu für vollständiges Manifest

Damit erfüllt die PWA die Chrome-Installability-Kriterien und der
Menü-Eintrag wird zu 'App installieren'. Erst dann funktioniert
auch Web Share Target.

Cache v10.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:21:59 +02:00
f2c41059a6 fix: Service Worker nach claude-db #31 Pattern (Network-First + Auto-Update)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Problem: User sehen alte Version weil der SW Cache-First ausliefert
und neue Versionen nur nach App-Neustart aktiv werden.

Fix (Pattern aus PWA Best Practices in claude-db #31):
- Network-First für alle eigenen Assets (fetch → ok → cache update,
  bei offline Fallback zum Cache). Vorher: Cache-First.
- self.skipWaiting() direkt nach Install
- self.clients.claim() nach Activate
- updatefound-Listener im index.html → bei neuem SW SKIP_WAITING
  senden, dann controllerchange-Event löst einmaligen Reload aus
- CSS/JS haben jetzt ?v=9 Query-String (Cache-Buster)
- Cache-Version 'baustelle-v9'

Damit zieht sich jede PWA beim nächsten Start automatisch die neueste
Version ohne manuellen Reinstall. Das Share-Target-Manifest-Caching
ist ein separates Android-Thema (dafür braucht's weiterhin Reinstall
der PWA beim ersten Mal).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:17:57 +02:00
bb02fb247e fix: share_target action als absolute URL (Android-Fix)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Laut martin.hjartmyr.se/articles/pwa-web-share-target-android/ ist
relativer action-Pfad ein bekannter Android-Stolperstein — der Share
Sheet zeigt die PWA nicht an obwohl das Manifest korrekt aussieht.

Fix: action auf volle URL setzen
(https://awl.data-it-solution.de/custom/baustelle/share.html).

Außerdem in params.files: explizite MIME-Types zusätzlich zu image/*
(image/jpeg, png, webp) — Chrome Android braucht MIME + Extension.

Service Worker v8 damit das neue Manifest geholt wird.

WICHTIG: PWA muss nach diesem Update komplett deinstalliert und neu
installiert werden, damit Android den Share-Target-Eintrag neu
registriert (Android cached hier sehr aggressiv).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:15:46 +02:00
91a6560f7e feat: Neues PWA-Logo — Klemmbrett mit Schraubenschlüssel (SVG + PNG)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Icon ersetzt das PHP/GD-generierte Placeholder durch ein echtes
Baustelle-Doku-Motiv:
- Dunkelblauer Radial-Gradient Hintergrund (rounded rectangle)
- Oranges Klemmbrett mit weißem Papier, Text-Zeilen und grüner
  Checkbox (symbolisiert fertige Arbeit)
- Metallische Klemme oben mit Riegel
- Blauer Schraubenschlüssel diagonal über dem Brett

SVG als Single-Source-of-Truth, PNG-Versionen in 192 und 512 px via
Chromium-Headless aus HTML-Wrapper gerendert (damit viewBox richtig
skaliert wird).

index.html verlinkt jetzt zusätzlich icon.svg als Favicon für Browser
die SVG-Favicons unterstützen.

SW-Cache auf v7.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:12:47 +02:00
391777fdb4 fix: Web Share Target akzeptiert mehr Feldnamen (Android Gallery Varianten)
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Verschiedene Android-Gallery-Apps senden geteilte Bilder unter
unterschiedlichen Feldnamen — photos, file, files, image, images.
- Manifest listet jetzt alle drei Haupt-Feldnamen mit image/* accept
- Service Worker iteriert alle bekannten Keys UND macht einen Fallback
  über alle FormData-Entries für unbekannte Gallery-Apps
- Cache-Version v6 damit Browser Manifest neu liest

Wichtig: PWA muss nach diesem Update einmal deinstalliert und neu
installiert werden, damit Android das neue share_target registriert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:10:05 +02:00
02ffdca57c feat: Phase 4 Block 1 — Seite bearbeiten, PDF-Vorschau, Unterschrift, Share Target
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Bericht-Detail-Ansicht:
- Tap auf Seiten-Thumb → openPageActionsModal mit:
  - Vorschaubild
  - Textarea für Seiten-Notiz (wird im PDF unter der Seite gedruckt)
  - '💾 Notiz speichern' → api.updatePageNote
  - 🗑️ im Header → api.deletePage mit Confirm
- Seiten-Thumbs haben Nummer-Badge oben links (1, 2, 3…)
- Neuer '👁 PDF-Vorschau'-Button öffnet openPdfModal (iframe mit
  Blob-URL) für Final-PDF oder on-the-fly Preview
- Neuer '✍️ Kunden-Unterschrift hinzufügen'-Button öffnet
  openSignatureModal: Touch-Canvas 2:1, Clear, Save → PNG wird als
  neue Bericht-Seite mit note='Unterschrift Kunde' angelegt

Web Share Target API:
- manifest.webmanifest: share_target mit photos array
- share.html: empfängt geteilte Fotos aus IDB (vom SW befüllt),
  zeigt Auftragsliste, Tap → Upload aller Fotos
- Service Worker v5: fängt POST /share.html ab, schreibt Files in
  IDB Key 'shared_files', redirected 303

Cache-Version bumpt damit neue Files geladen werden.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 01:00:24 +02:00
3f1b462105 feat: Hilfe-Button in Topbar mit kompletter Anleitung
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
-Button oben rechts öffnet ein Vollbild-Modal mit:
- Auftragsfindung und Suche
- Fotos aufnehmen (Kamera/Galerie), Hinweis auf Entwurf-Akkumulation
- Skizzen-Editor (Pen/Pfeil/Rect/Ellipse, Undo, speichern)
- Sprachnotizen aufnehmen + abspielen
- Berichte finalisieren + Status-Erklärung
- Offline-Modus + Status-Badge-Legende
- Installation auf Home-Screen (Android + iOS)
- Einstellungen

Service Worker v4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 00:46:52 +02:00
bd9580bd46 fix: Finalisieren-Button immer sichtbar + Sprachnotizen eigene Sektion
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
- Bericht-Detail: Button ist jetzt immer da, bei Final heißt er
  'PDF neu erzeugen'. Bei 0 Seiten disabled statt versteckt, mit
  Hinweis-Empty-State darüber.
- Auftrags-Detail: Audio-Files (webm/mp3/ogg/m4a/wav) werden aus
  'Weitere Dokumente' rausgefiltert und in eine eigene Sektion
  '🎙 Sprachnotizen' mit Play-Button je Eintrag gelegt. Tap auf ▶
  lädt die Datei als Blob (mit JWT) und setzt einen <audio>-Player
  inline ein.
- Service Worker v3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 00:43:27 +02:00
a1589a7ae2 feat: Phase 4 — Bericht-Liste, Detail, Foto-Vollbild, Voice, Sketch
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Der Reports-Tab listet alle Berichte des Users mit Status-Badge,
Quell-Referenz und Seitenzahl. Klick → Bericht-Detail mit:
- Meta (Titel, Format, Status, Seiten)
- Seiten-Thumbnails
- 'Bericht finalisieren' Button (triggert PDF-Generierung via API)
- 'Im Desktop-Editor öffnen' Link

Auftrags-Detail erweitert:
- Tap auf Foto-Thumb → Vollbild-Modal mit Löschen-Button und
  'Zeichnen'-Button (öffnet Skizzen-Editor)
- '🎙 Sprachnotiz aufnehmen' Button → Voice-Modal mit MediaRecorder,
  Live-Timer, Preview, Upload

Skizzen-Editor (Touch-fähig):
- Bild wird in canvas geladen, max 1600px
- Werkzeuge: Pen, Pfeil mit Spitze, Rechteck, Ellipse
- Farbe + Linienstärke
- Undo + Clear
- Speichern → rendert als JPEG und lädt als neue Bericht-Seite hoch

Service Worker Cache-Version auf v2 gebumpt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
[deploy]
2026-04-09 00:31:39 +02:00
7c0aefa793 feat: Initiales Release Baustelle PWA v1.0.0 [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 1s
Mobile Progressive Web App für Baustellen-Doku, spricht die REST-API
des Dolibarr-Bericht-Moduls.

MVP-Features:
- Vanilla JavaScript, kein Build-Step nötig
- Login mit Dolibarr-Credentials → JWT (7 Tage)
- Auftragsliste mit Suche und Multi-User-Filter
- Auftragsdetail mit Kunde, Adresse, Click-to-Call
- Foto-Aufnahme via Kamera oder Galerie (multiple)
- Clientseitige Bildverkleinerung (max 2000px, JPEG q=0.85)
- Offline-Queue in IndexedDB für Uploads ohne Netz
- Auto-Sync bei Online-Event mit Status-Badge
- Service Worker für App-Shell-Cache
- PWA-installierbar (Manifest, Icons, Theme-Color)

Hosting: awl.data-it-solution.de/baustelle/ via Apache-Alias

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:50:01 +02:00