Commit graph

20 commits

Author SHA1 Message Date
Eddy
afc6ca7046 Große Knöpfe mit Symbol linksbündig [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Eddy: „im Auftrag … die Symbole alle linksbündig" — die farbigen Kreise
stehen in einer Spalte, der Text beginnt immer an derselben Stelle.
Gilt für alle Knöpfe mit Symbol; der kleine „Auswählen"-Knopf bleibt mittig.
Im Android-Emulator angesehen, Eddy: „lass das mal so".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:25:15 +02:00
Eddy
5a54a64b7e Farbige Symbole statt Emojis auf allen Knöpfen [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Eddy: „so dass es gut aussieht", zu rein weißen Symbolen dann
„viel zu schlicht". Emojis erscheinen je nach Handy als Kästchen.

- icon() in app.js (Material-Symbole), Farbe je Symbol in app.css
  (.ikon-<name>): große Knöpfe = weißes Symbol im farbigen runden
  Feld (Kamera blau, Galerie grün, Sprachnotiz rot, Notizen gelb,
  Material orange, Bericht lila, Lieferungen türkis …), kleine
  Knöpfe = farbiges Symbol (Teilen blau, Löschen rot, Stift/Blitz/
  Hilfe gelb, Download/Telefon grün).
- Untere Leiste: farbiges Symbol über dem Wort, Heute als Sonne,
  Zahnrad heißt „Einstellungen".
- Titel und Überschriften ohne Emoji; Telefonnummer lesbar.
- .icon-btn[hidden] bleibt versteckt (inline-flex hätte hidden ausgehebelt).

Im Android-Emulator angesehen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 16:48:14 +02:00
Eddy
73a481fa8f Videos aufnehmen, Emulator-Prüfungen nachgeholt, keine Versalien [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Eddy: „Bei Fotos aufnehmen auch Videos unterstützen bitte".

- Kamera: Umschalter Foto | Video, roter Aufnahmeknopf, Laufzeit mit
  Höchstlänge (5 min bzw. passend zur Servergrenze), Ton, Licht/Zoom/
  Antippen-Fokus auch beim Filmen; MP4 (H.264/AAC), sonst WebM.
  Schließen oder App-Wechsel während der Aufnahme sichert das Video.
- Warteschlange: Videos wie Fotos (Persist-First). Gesichert wird der
  Blob statt eines ArrayBuffers; Zeitlimit und Lease wachsen mit der
  Größe (api.js/sw.js gleiche Formel); 413 → sofort Quarantäne.
- Auftrag: Abschnitt „Videos" mit erstem Bild, Player (spult per Range),
  Teilen, Löschen; „Warten auf Upload" zeigt Videos mit.
- Galerie und Teilen nehmen Videos, zu große lehnt die App gleich ab.
- Überschriften fett in normaler Schreibweise statt Versalien.
- ROADMAP: Funkloch, Display aus, 10 Fotos aus der Galerie und
  PDF-Zoom im Emulator geprüft und abgehakt.

Braucht Bericht 1.8.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:54:20 +02:00
Eddy
3028ff5731 Kamera: Zoom mit zwei Fingern, Antippen belichtet auch dort [deploy]
- Zwei Finger im Sucher zoomen (nur wenn die Kamera Zoom meldet), Anzeige
  „1×"/„2,5×" unten im Sucher, Antippen der Anzeige setzt auf 1× zurück.
  Während der Geste geht immer nur ein Aufruf an die Kamera; das Ende
  der Geste zählt nicht als Fokus-Tipp.
- Hinweis beim Öffnen: „Antippen stellt dort scharf · zwei Finger zoomen".
- Kein eigener Helligkeitsregler: Chrome setzt mit der Tippstelle auch
  Belichtung und Weißabgleich (im Emulator gemessen).

Im Android-Emulator mit echter Zwei-Finger-Geste geprüft; das Foto bei
2,5× zeigt genau den Sucher-Ausschnitt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:22:04 +02:00
Eddy
7c8a3c4bc0 Kamera: Antippen stellt an der richtigen Stelle scharf, Wechselknopf als Symbol [deploy]
Im Android-Emulator (Chrome 153, echter Camera2-Weg, dumpsys media.camera)
gegengeprüft: Blitz Aus/Auto/An und Licht kommen richtig bei der Kamera an.
Beim Antippen-Fokus waren zwei Fehler:

- Chrome rechnet pointsOfInterest ungedreht auf den quer liegenden Sensor um,
  das Sucherbild steht aber hochkant. Ein Tipp rechts unten landete an
  falscher Stelle. sensorPunkt() dreht die Tippstelle jetzt in Sensorlage
  zurück (hochkant, quer 90° und 270° gemessen).
- focusMode single-shot nimmt Chrome auf Android an, setzt es aber nicht um
  (kein AF-Trigger). Der Hinweis „Fokus fest“ war damit falsch und ist weg;
  Antippen = Dauer-Autofokus auf die Tippstelle.

Knopf „Kamera wechseln“: weißes Symbol statt 🔄-Emoji (blaues Kästchen),
nur sichtbar, wenn das Gerät mindestens zwei Kameras hat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:12:34 +02:00
Eddy
2bf5852147 Doku: Kamera-Gegenprobe am Rechner nicht möglich (Emulator, Webcam)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:26:16 +02:00
Eddy
85a64c237a Kamera: Blitz (Aus/Auto/An/Licht) und Scharfstellen per Antippen [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 14s
Eddy: „beim Fotografieren kann man den Blitz nicht einstellen und den Fokus auch nicht".
Knopf oben schaltet reihum, was das Gerät meldet (fillLightMode über takePhoto, Dauerlicht über
torch); Auswahl bleibt gemerkt. Antippen stellt an der Stelle scharf (pointsOfInterest +
focusMode single-shot) und hält den Fokus, „Fokus fest · zurück auf Auto" löst ihn wieder.
Ohne gemeldete Fähigkeiten (Frontkamera, Tablet-Webcam) bleibt alles wie bisher.
Lokal mit nachgebildeter Kamera geprüft, Gegenprobe am Handy steht in ROADMAP Punkt 9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:09:35 +02:00
0d2f485ecc „Geteiltes ablegen" als Leiste über der Navigation statt schwebend über den Aufträgen [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Eddy: der Knopf soll unten am Rand liegen und die Aufträge nicht
überdecken. Er steht jetzt in der App-Spalte direkt über der Navigation
(sticky am unteren Rand), der FAB rückt solange eine Leistenhöhe hoch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:53:11 +02:00
c7cd2fa461 Knopf „Geteiltes ablegen" blieb dauerhaft stehen: leere Pakete wegräumen, Verwerfen [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Ein leeres Teilen-Paket in IndexedDB hielt den Knopf für immer stehen
(share.html meldete „Es kam nichts an" und ließ den Rest liegen). Die
App räumt leere Pakete jetzt selbst weg, share.html ebenso; der Knopf
nennt „(Notiz)" bei reinem Text; share.html bietet „Verwerfen" mit
Rückfrage in der Seite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:49:01 +02:00
Eddy
76592435a3 Doku: Stand 15.10.2026 nachgezogen (README, Roadmap abgehakt)
All checks were successful
Deploy baustelle-pwa / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 22:55:36 +02:00
Eddy
8e984fca44 Doku: Galerie-Einlesen in README, ROADMAP Punkt 7 als live markiert
All checks were successful
Deploy baustelle-pwa / deploy (push) Has been skipped
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 20:24:47 +02:00
Eddy
b824e95c88 Galerie-Auswahl: alle Fotos sofort einlesen, bevor hochgeladen wird [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Ab dem dritten Foto warf Chrome/Android NotReadableError ("permission problems"),
weil jede Datei erst nach dem Upload der vorigen gelesen wurde. Die Fotos kamen
nie in die Queue (Prod-Log 30.09.2026, Auftrag 114: nur 2 von N Uploads).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-30 20:23:19 +02:00
Eddy
aaed48682e Doku: README auf Code-Stand, ROADMAP entruempelt
All checks were successful
Deploy baustelle-pwa / deploy (push) Has been skipped
README:
- "Verkleinerung auf 2000px" war veraltet - seit Bericht 1.7.0 im Admin
  einstellbar, Vorgabe 1:1
- fehlten: Background Sync / Periodic Sync, volle Kameraaufloesung ueber
  ImageCapture, Wake Lock, idempotenter Wiederhol-Upload (duplicate:true)
- Verzeichnisstruktur: Rollen von idb.js/offline.js/router.js/sw.js,
  icon.svg, Workflow, Hinweis auf Symlink der lokalen Testinstanz
- API-Liste geprueft: alle 18 Endpunkte stimmen

ROADMAP: Offenes nach oben, Abschnitt 6 (18.09.) bleibt ausfuehrlich,
Abschnitte 1-5 (alle erledigt) zu einer Tabelle mit Commit + KB-Verweis
gekuerzt. Bewusst-nicht-gebaut-Entscheidungen bleiben erhalten.
Gegenstueck Bericht 1.5.1 -> 1.7.1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 23:57:47 +02:00
Eddy
30202f8f28 Keine Doppel-Uploads mehr, App-Update laedt nicht mitten in der Arbeit neu
Doppel-Uploads (Prod-Log 17.09.: reihenweise duplicate:true): Seite
(syncQueue) und Service Worker (Background Sync) arbeiteten dieselbe
IndexedDB-Queue ab, ohne voneinander zu wissen. Dank md5-Abgleich
folgenlos, aber doppeltes Datenvolumen. Mit eingestelltem Verkleinern
sogar zwei verschiedene Dateien im Auftrag: der Worker lud das
Original, die Seite danach die kleine Fassung.

- idb.js: queueKeys/queuePatch/queueClaim/queueRelease - Lesen-Aendern-
  Schreiben in einer readwrite-Transaktion, ueber Kontexte atomar
- syncQueue (Seite) und drainQueue (Worker) belegen jedes Foto vor dem
  Upload (Lease 90 s > laengster Upload-Timeout); belegt = ueberspringen,
  abgelaufen = uebernehmen. Nur noch ein Foto gleichzeitig im Speicher
- enqueuePhoto({hold:true}) + releaseHold: waehrend des Verkleinerns
  bleibt das Foto belegt
- Versuchszaehler, retryFailed und replaceQueuedBlob per Patch statt
  ganzes Item zurueckschreiben

Reload nach App-Update: controllerchange lud sofort neu - offene Kamera,
getippte Notiz, halbe Unterschrift weg; mit Fotos in der Warteschlange
kam dazu der Browserdialog "Seite verlassen?".

- window.appBusy(): Modal, Auswahl, laufender Upload, Eingabe im Fokus,
  laufende Sprachnotiz. PIN-Sperre zaehlt bewusst nicht
- index.php holt den Reload nach, sobald nichts mehr offen ist; eigener
  Reload setzt __selfReload, beforeunload warnt dann nicht

Verifiziert lokal in Chromium: echte Kamera-Oberflaeche mit Canvas-
Stream offline, paralleler Zugriff Seite+Worker (3 Fotos = 3 POSTs im
Serverlog, kein duplicate), Verkleinern (eine Datei, kleine Fassung),
fremde Lease frisch/abgelaufen, aufgeschobener Reload ohne Dialog.
Nicht getestet: Kamera-Hardware und Background Sync bei Display aus am
Handy. Kein Deploy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 23:49:02 +02:00
Eddy
64ebbf7850 Rauswurf aus dem Auftrag behoben, wartende Fotos am Auftrag sichtbar
Gemeldet 18.09.2026: nach "Fertig" in der Kamera stand die App auf der
Auftragsliste, und im Auftrag war von den Fotos nichts zu sehen.

Ursache Rauswurf (Prod-Log 17.09., Auftrag 111): closeModal() ruft
history.back() (asynchron), direkt danach setzt router.go() den Hash.
Der Ruecksprung laeuft erst nach dem Hash-Wechsel und springt hinter
den neuen Eintrag zurueck - angezeigt wird der Auftrag, in der Adresse
steht '#/orders'. Das naechste router.navigate() (Kamera "Fertig")
zeichnet dann die Liste. Betraf nur in derselben Sitzung ueber den
Plus-Knopf angelegte Auftraege.

- closeModal(): Zaehler _pendingBacks statt Boolean (KB #1209), History-
  Eintrag wird vor dem Cleanup zurueckgenommen
- router.go() und pushModal() warten ueber historySettled() auf
  ausstehende Ruecksprunge (Schutzzeit 1,5 s)
- Kamera und Galerie-Auswahl steuern nach dem Sichern ausdruecklich
  '#/orders/<id>' an statt den Hash der Adresszeile
- Auftragsseite: Block "Warten auf Upload (n)" mit Vorschaubildern aus
  der Warteschlange und Klartext; zieht nach photo-uploaded selbst nach
- Hinweis-Toast beim Schliessen der Kamera, wenn noch Fotos warten

Verifiziert lokal in Chromium mit echtem Offline-Modus; die Kamera
selbst (getUserMedia) am Handy ist noch nicht getestet. Kein Deploy.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 23:36:14 +02:00
6bfe2e8824 Doku: ROADMAP-Stand auf 31.08.2026 nachgezogen 2026-08-31 19:13:38 +02:00
a108664854 App ohne Netz lesbar statt "Failed to fetch"
Gemeldet: die App zeigte beim Oeffnen nur "Failed to fetch", waehrend das
Teilen aus WhatsApp weiter ging. Deploy und API waren in Ordnung — die
Meldung ist die rohe Browserausgabe eines fetch(), das gar nicht bis zum
Server kam, und stand 1:1 im UI, weil die Routen im catch e.message
anzeigten. Das Teilen fiel nicht auf, weil share.html sich die letzten
Auftraege seit eaad796 lokal merkt; die Hauptapp hatte fuer die Listen
keinen Offline-Fallback.

- api.js uebersetzt Netzfehler in einen eigenen Fehler mit offline=true
  und deutschem Text; 4xx/5xx bleiben Serverfehler
- isTransient() in offline.js erkannte Netzfehler an "instanceof TypeError".
  Ohne Anpassung waere ein Foto aus dem Funkloch als dauerhaft
  fehlgeschlagen gewertet und nach sechs Versuchen in Quarantaene gelandet
- Datenspiegel in IndexedDB: Auftrags-, Kunden- und Berichtsliste sowie
  geoeffnete Details (letzte 30). Ohne Netz wird der Stand angezeigt,
  mit Band "Kein Netz — Stand von HH:MM Uhr", und die Suche filtert darin
- beim Abmelden wird der Spiegel geloescht (geteiltes Geraet)
- sw.js: der Same-Origin-Zweig endete auf caches.match(); fand der Cache
  nichts, wurde respondWith(undefined) aufgerufen und die Anfrage
  scheiterte erneut mit genau der Meldung, die verhindert werden sollte.
  Jetzt immer eine echte Response, nur vollstaendige Antworten im Cache
- Precache nach Deploy: die Seite meldet dem Worker ihre echten Asset-URLs,
  sonst ist der Cache direkt nach einem Deploy leer (?v=<mtime>)

Muster aus KB #1037 und #1041. Verifiziert auf der lokalen Testinstanz
inklusive echtem Funkloch (setOffline + reload): App startet aus dem
Cache, zeigt Band und Auftragsliste, keine JS-Fehler.
2026-08-31 19:07:09 +02:00
Eddy
eaad796ab6 Teilen-Seite merkt sich die letzten Aufträge — Serie kostet nur noch einen Tipp [deploy]
All checks were successful
Deploy baustelle-pwa / deploy (push) Successful in 13s
Wenn die Kundin drei Nachrichten hintereinander schickt, musste man den Auftrag
bisher jedes Mal neu heraussuchen. Jetzt stehen die letzten drei benutzten
Aufträge unter "Zuletzt benutzt" ganz oben.

Wurde einer davon in den letzten 30 Minuten benutzt, ist er vorausgewählt und
der Knopf ist sofort scharf ("In SO2608-0044 ablegen") — die zweite und dritte
Ladung kosten damit einen einzigen Tipp. Nach Ablauf der 30 Minuten steht der
Auftrag nur noch als Schnellzugriff da, ohne Vorauswahl: eine dauerhafte
Vorauswahl würde irgendwann still im Auftrag von vorgestern landen, und die
Auftragsnummer steht deshalb auch immer im Knopftext.

Die Merkliste (IndexedDB 'share_recent_orders') wird beim erfolgreichen Ablegen
fortgeschrieben, neuester zuerst, ohne Duplikate, maximal drei Einträge.
Kartenaufbau und Auswahl-Logik liegen jetzt in gemeinsamen Helfern
(karteHtml/bindeKarten/waehleAuftrag), damit Schnellzugriff und Suchtreffer
denselben Auftrag synchron markieren.

Lokal durchgespielt: erste Ladung ohne Merkliste (keine Vorauswahl), zweite
direkt danach (vorausgewählt, ein Tipp, landet im selben Auftrag), und ein
drei Stunden alter Eintrag (Schnellzugriff sichtbar, aber Knopf grau).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 20:19:37 +02:00
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
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