From 71403efafe9ef70929a2ab1c4243fede0d35b2af Mon Sep 17 00:00:00 2001 From: Tobi G Date: Sat, 5 Sep 2026 12:42:50 +0200 Subject: [PATCH] Speicherleiste ersatzlos gestrichen, Felder speichern beim Verlassen Auf Entscheidung des Eigentuemers nach der HIG-Pruefung. Gegen die Leiste sprach viererlei: iOS kennt kein solches Muster auf einer geschobenen Einstellungsseite; sie schwebte ueber der Tab-Leiste und deckte einen Knopf der Kachel dahinter zu (gemessen); sie war die Ursache des Datenverlusts bei der Erstzulassung; und das Panel hatte sie nie - dort schreibt jede Aenderung sofort ins Profil. Jetzt speichern Textfelder beim Verlassen, Auswahlfelder sofort. Die Meldung "Gespeichert." entfaellt mit. Der Regler "Fahrt beenden" behaelt seinen eigenen Bestaetigungsschritt - ihn bei jedem Zwischenschritt zu sichern hiesse ein Dutzend Schreibvorgaenge je Bedienung. Mit echten Eingabeereignissen am laufenden System geprueft: getippt, ins naechste Feld geklickt, Wert steht in fahrzeugprofil.json; danach der urspruengliche Wert wiederhergestellt. 299 Tests gruen, 0 Tracebacks. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 48 ++++++++++++++ companion-app/src/screens/Einstellungen.tsx | 61 +++++++++--------- .../audi_dashboard/frontend/app/bundle.json | 2 +- .../audi_dashboard/frontend/app/bundle.zip | Bin 324590 -> 324552 bytes .../audi_dashboard/manifest.json | 2 +- 5 files changed, 80 insertions(+), 33 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5c1ce0f..a2a647e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11854,3 +11854,51 @@ Gemessen in beiden: Farbe `rgb(52,199,89)` bzw. `rgb(48,209,88)` - das ist **Nachgezogen:** die Beschriftung heisst nur noch "Integration". "Home-Assistant-Integration" brach auf Telefonbreite in zwei Zeilen um; auf Entscheidung des Eigentuemers gekuerzt. Nachgemessen: einzeilig, 20px hoch. + +## CY. Die Speicherleiste ist ersatzlos entfallen (2026.9.5.21) + +Frage des Eigentuemers: *"entspricht Speichern/verwerfen anzeige bei Fahrzeug +einrichten der Apple HIG?"* - Antwort: nur teilweise. Entscheidung danach: +*"speichern: ersatzlos streichen"*. + +### Was dagegen sprach + +* **Das Muster.** iOS kennt keine dauerhafte Speichern/Verwerfen-Leiste auf + einer *geschobenen* Einstellungsseite. Apples zwei Muster sind: Aenderungen + wirken sofort (Einstellungen-App) oder das Bearbeiten laeuft in einem + **modalen Blatt** mit Abbrechen oben links und Fertig oben rechts. Eine + klebende Aktionsleiste unten ist ein Web-/Android-Idiom. +* **Sie verdeckte Inhalt.** Gemessen: Leiste bei y 577-670, Tab-Leiste ab 700; + `elementsFromPoint` direkt dahinter ein `BUTTON.ads-action--primary` in der + Kachel. Dazu Seitengrund `rgb(242,242,247)` auf weisser Kachel - ein grauer + Balken quer durch die Karte. +* **Sie war die Ursache eines Datenverlusts** (Abschnitt CU): wer nur die + Erstzulassung aenderte, bekam gar keinen Speichern-Knopf zu sehen. Eine + Leiste, die eine Eingabe erst gueltig macht, kann sie auch verschlucken. +* **Sie war eine Paritaetsabweichung.** Das Panel hat sie nie gehabt - dort + schreibt der `data-einrichten`-Handler bei jeder Aenderung sofort ins Profil. + +### Was jetzt gilt + +Textfelder (Modell, Kennzeichen, Erstzulassung, Ausfuehrung) speichern **beim +Verlassen des Feldes**, Auswahlfelder sofort. Genau wie im Panel. Die +Erfolgsmeldung "Gespeichert." entfaellt mit - eine sofort wirkende Aenderung +braucht keine Bestaetigung, und das Panel zeigt auch keine. + +**`speichern()` bleibt fuer den Regler "Fahrt beenden".** Ein Schieberegler bei +jedem Zwischenschritt zu sichern hiesse ein Dutzend Schreibvorgaenge je +Bedienung; er behaelt deshalb seinen eigenen Bestaetigungsschritt mit +Verwerfen/Speichern in der Kachel (`dm-speicherleiste--kachel`). Das ist die +einzige verbliebene Stelle mit dieser Klasse. + +### Zweimal am eigenen Testfehler vorbeigeschrammt + +Der erste Nachweis schlug fehl - Wert nicht gespeichert. Ursache war nicht der +Code, sondern mein Test: ein programmatisches `e.focus()` + Wertsetzer + +`e.blur()` loest React's `onBlur` hier nicht verlaesslich aus. Mit echten +Eingabeereignissen (Dreifachklick, Tippen, Klick ins naechste Feld) steht der +Wert sofort in `fahrzeugprofil.json`. + +Dasselbe Muster wie beim Koordinatenfehler in Abschnitt CS: **ein fehlgeschlagener +synthetischer Test ist kein Fehlerbeweis.** Erst mit echten Ereignissen pruefen, +dann urteilen. diff --git a/companion-app/src/screens/Einstellungen.tsx b/companion-app/src/screens/Einstellungen.tsx index 4d3839b..fb1fe69 100644 --- a/companion-app/src/screens/Einstellungen.tsx +++ b/companion-app/src/screens/Einstellungen.tsx @@ -80,7 +80,6 @@ export function Einstellungen({ Eigentuemers, 04.09.2026). `null` heisst: nichts angefasst. */ const [pausenzeitEntwurf, setzePausenzeitEntwurf] = useState(null) const [laeuft, setzeLaeuft] = useState(false) - const [gespeichert, setzeGespeichert] = useState(false) const [importOffen, setzeImportOffen] = useState(false) /* Abfrage "bis wann gilt der Rabatt", die das Einschalten des SmartDeals ausloest (sdpopup im Panel). */ @@ -236,18 +235,30 @@ export function Einstellungen({ eigenen Entwurf und uebergibt ihn erst beim Druck auf Speichern. Ohne den Umweg wuerde `entwurf` im selben Rendern noch den alten Wert tragen - setState wirkt erst beim naechsten Durchlauf. */ - /* `erstzulassung` fuehrt einen EIGENEN Entwurf, unabhaengig von - `entwurf` - es gehoert zum Fahrzeug, nicht zu den Einstellungen. Diese - Bedingung hat es dabei vergessen: wer nur die Erstzulassung aenderte, - kam hier nie vorbei, und weiter unten erschien auch die Speicherleiste - nicht (die haengt ebenfalls allein an `entwurf`). Der eingetippte Wert - war damit gar nicht speicherbar und beim Verlassen der Seite weg - - gemeldet vom Eigentuemer am 05.09.2026. Das Panel speichert an dieser - Stelle sofort bei jeder Aenderung und war deshalb nie betroffen. */ + /* Es gibt keine Speicherleiste mehr. Jedes Feld wirkt beim Verlassen, + Auswahlfelder sofort - wie im Panel, wo der `data-einrichten`-Handler + seit jeher bei jeder Aenderung ins Profil schreibt. + + Ansage des Eigentuemers am 05.09.2026: "speichern: ersatzlos streichen". + Drei Gruende sprachen dafuer: + + * iOS kennt keine dauerhafte Speichern/Verwerfen-Leiste auf einer + geschobenen Einstellungsseite. Apples Muster sind "wirkt sofort" + (Einstellungen-App) oder ein modales Blatt mit Abbrechen/Fertig in + der Navigationsleiste. + * Die Leiste schwebte ueber der Tab-Leiste und deckte dabei einen Knopf + der Kachel dahinter zu (gemessen 05.09.2026). + * Sie war die Ursache eines echten Datenverlusts: wer nur die + Erstzulassung aenderte, bekam gar keinen Speichern-Knopf zu sehen. + Eine Leiste, die eine Eingabe erst gueltig macht, kann sie auch + verschlucken. + + `speichern()` bleibt fuer den Regler "Fahrt beenden": ein Schieberegler + bei jedem Zwischenschritt zu sichern hiesse ein Dutzend Schreibvorgaenge + je Bedienung, deshalb behaelt er seinen eigenen Bestaetigungsschritt. */ const speichern = async (zusatz?: Partial) => { if (!entwurf && !zusatz && erstzulassung === null) return setzeLaeuft(true) - setzeGespeichert(false) try { await profilSpeichern({ einstellungen: { ...werte, ...(zusatz ?? {}) }, @@ -256,12 +267,15 @@ export function Einstellungen({ setzeEntwurf(null) setzeErstzulassung(null) setzePausenzeitEntwurf(null) - setzeGespeichert(true) } finally { setzeLaeuft(false) } } + /** Uebernimmt den aktuellen Stand des Bildschirms - beim Verlassen eines + Feldes oder sofort bei einem Auswahlfeld. Ohne Zusatz und ohne Knopf. */ + const sichern = (zusatz?: Partial) => void speichern(zusatz) + /* Zugaenge: je Dienst ein Entwurf im Eingabefeld. Der gespeicherte Token kommt NIE zurueck (siehe zugaenge.py), das Feld startet deshalb immer leer und zeigt als Platzhalter, ob schon einer hinterlegt ist. */ @@ -394,6 +408,7 @@ export function Einstellungen({ className="dm-eingabe dm-eingabe--fahrzeug" value={werte.fahrzeugtitel} onChange={(e) => aendern({ fahrzeugtitel: e.target.value })} + onBlur={() => sichern()} /> @@ -401,6 +416,7 @@ export function Einstellungen({ className="dm-eingabe dm-eingabe--fahrzeug" value={werte.kennzeichen} onChange={(e) => aendern({ kennzeichen: e.target.value })} + onBlur={() => sichern()} /> @@ -409,6 +425,7 @@ export function Einstellungen({ placeholder="TT.MM.JJJJ" value={erstzulassungWert} onChange={(e) => setzeErstzulassung(e.target.value)} + onBlur={() => sichern()} /> @@ -416,6 +433,7 @@ export function Einstellungen({ className="dm-eingabe dm-eingabe--fahrzeug" value={werte.ausfuehrung} onChange={(e) => aendern({ ausfuehrung: e.target.value })} + onBlur={() => sichern()} /> {/* „Setup — Sensoren zuordnen" bleibt dem Panel vorbehalten: die @@ -700,7 +718,7 @@ export function Einstellungen({