Run a full Apple HIG audit; fix silent save failures and popup polish

Read Tab Bars, Sidebars, Sheets, Alerts, Action Sheets, Toolbars, Buttons,
Pickers, Loading, Feedback, Privacy, and Undo/Redo off developer.apple.com
and cross-checked each against the actual code. profilSpeichern() (the
shared save path for ~25 fields) had no error handling at any call site,
so a failed backend write was an unhandled promise rejection with zero
user feedback - fixed centrally, plus the same for serviceRufen(). Also
added a spinner to the "Ladt ..." bootstrap screen and gave the
Anzugsmoment/km-correction popups the same primary-button styling the
Setup popup already used.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 23:53:02 +02:00
parent 6bf7435434
commit 8a751fe441
7 changed files with 117 additions and 13 deletions
+45 -1
View File
@@ -23,7 +23,13 @@ intended 96x96 square, moved the "Montiert" pill to match, added `color-scheme`
popups stop rendering in the browser's default light palette against the dark app, root-caused and
fixed a JS crash in the "Mein Audi" image-cycle click handler, merged the separate "Fahrzeugbilder"
upload grid into "Bild der Übersicht" (pick a view, tap its photo to upload), and turned the back
arrow from red to the neutral headline color — see section C). This file is the entry point for every new agent
arrow from red to the neutral headline color; a tenth round the same day ran a real full Apple HIG
audit (Navigation/Presentation/Selection & Input/Patterns categories, not just the sixth round's
5-page pass) and fixed the three findings that survived: closed a second, larger silent-failure gap
in `profilSpeichern()` itself (the shared save path for ~25 fields, previously an unhandled promise
rejection with zero user feedback), added a spinner to the "Lädt …" bootstrap screen, and gave the
Anzugsmoment/km-correction popups the same primary-button styling the Setup popup already used —
see section C). This file is the entry point for every new agent
session: what this repo is, what is finished, what is missing, and how to work here. Detail lives in
the linked documents — this file points, it does not duplicate.
@@ -1082,6 +1088,44 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed
confirmed the pyscript service ran via the container's HA log, then did a full page reload
(forces a real backend re-fetch, not just optimistic local UI state) and the corrected value
was still there.
- [x] Tenth round the same day (2026-08-16) — a real full Apple HIG audit, not just the sixth
round's 5-page pass: read Tab Bars, Sidebars, Sheets, Alerts, Action Sheets, Toolbars/
Navigation Bars, Buttons, Pickers, Loading, Feedback, Privacy, and Undo/Redo directly off
developer.apple.com and cross-checked each against the actual code (not just CSS) — most of
the app already held up (5-tab bar, destructive-button placement, 44pt tap targets,
`prefers-reduced-motion` support, confirm-sheet button ordering all already correct). Three
real findings surfaced, all fixed and user-approved via `AskUserQuestion` before implementing:
(1) **A second, larger silent-failure gap than the one already fixed for receipt upload.**
`profilSpeichern()` — the shared save path for roughly 25 editable fields across the app
(Anzugsmoment, service book, SmartDeal, tax, insurance, oil change, pause time, backup
interval, start image, ...) — was `async` with no `try`/`catch` at any of its ~25 call sites,
so a failed backend write was an unhandled promise rejection with zero user feedback; the
popup had already closed and the UI already updated optimistically, so the change looked
saved when it silently wasn't. Wrapped the one call inside `profilSpeichern()` itself in
`try`/`catch`, reusing the existing `hinweis()` error-sheet pattern — one central fix instead
of ~25 call-site patches. `serviceRufen()` (the separate wrapper used by km-correction, manual
trip/fuel entry, tire-set switching, deletions, restart, ...) got the identical treatment.
Verified live by monkey-patching `hass.callService` to reject inside the running app (via
`host.hass.callService = () => Promise.reject(...)`), then triggering a real Anzugsmoment save
through the actual UI: before the fix, the popup silently closed with a stale "Uncaught (in
promise)" console entry and no user-visible sign anything went wrong; after the fix, a
"Speichern fehlgeschlagen" sheet appears with the real error text. A follow-up full reload
confirmed the failed test write never reached the backend (value reverted to the real stored
120 Nm) — the fix only adds feedback, it doesn't change persistence behavior.
(2) **"Lädt …" bootstrap screen got a progress indicator** (new `.lade-spinner` CSS, a plain
rotating ring) instead of bare static text, per HIG Loading guidance to show something moving
while content loads — notable here because this exact screen has a documented history of
genuinely hanging, so a spinner also helps a user tell "still loading" apart from "stuck".
Respects the existing global `prefers-reduced-motion` override (`*, *::before, *::after`
block already forces `animation-duration:.01ms` app-wide) with no extra code.
(3) **Anzugsmoment and km-correction popups now use `.aktion.primaer` on Speichern**, matching
the Setup and SmartDeal popups, which already distinguished their primary action — these two
were the only popups in the app stacking two visually-identical plain buttons.
All three verified live in `audi_ha_test` (version `1786916894`): spinner CSS confirmed via
`getComputedStyle` (16×16px, `border-radius:50%`, `animation-name:lade-spin`) since a genuine
race-condition-timed screenshot proved too fast to catch reliably; Speichern/Abbrechen
hierarchy confirmed via screenshot on both popups; error-sheet fix confirmed via the
monkey-patch test above. Synced to `installationspaket/`.
- [ ] Fix remaining documentation drift (statistics claim, README gaps, obsolete TODO comment) —
text-only changes; INSTALL.md's WLAN/TommiG1 drift and stale variable names were fixed
2026-08-12 (see section B); `DESIGN_REVIEW_2026-08-13.md` and `REVIEW_main_2026-08-13.md`