Update-Knopf: Seitensprung im Großbild-Layout behoben

Auf Update prüfen/Update installieren ließ die Seite im Seitenleisten-Layout
sichtbar nach oben springen - render()s eigene Scroll-Wiederherstellung
reichte hier nicht, vermutlich weil die Zustandsänderung des
Update-Sensors zusätzlich über HAs eigenes set-hass-Durchreichen an das
eingebettete Panel einen zweiten Render-Pfad anstößt. Statt die genaue
Ursache weiter zu jagen: fester Scroll-Merkwert vor dem Klick, per
requestAnimationFrame nach jedem eigenen render()-Aufruf dieses Ablaufs
erneut erzwungen. Live bei 1280x800 verifiziert: kein Sprung mehr.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 18:18:51 +02:00
parent 7276d06a18
commit 0354ab8768
3 changed files with 46 additions and 2 deletions
+29
View File
@@ -2681,6 +2681,35 @@ the OTA bundle's embedded version aligned with the manifest (no further companio
after the "Licht ausgeschaltet" text fix earlier in this same round, so this rebuild only updates the
stamped version number, not the bundle contents).
**A third same-day fix (2026.8.24.12): the update-button scroll jump, specifically in wide/desktop
mode.** The owner reported the page visibly jumps when pressing "Auf Update prüfen"/"Update
installieren" on a large screen. Reproduced live at `1280×800`: clicking the button while scrolled deep
into "Einstellungen" (`scrollTop` ~1773) landed at `scrollTop` ~1517 after the click resolved — a real,
non-zero shift, not the element being replaced (`main#view` stayed `isConnected: true` throughout, so
it wasn't a full re-mount either) and not simply `scrollTop` reset to 0 the way section L's
narrow-mode work had assumed for this kind of bug. `render()`'s own scroll-preservation
(`v.scrollTop = gleicheAnsicht ? merkeScroll : 0`) should apply here (same route, same id) and normally
does — the update flow specifically still lost position, most likely because the service call also
triggers a *separate*, second re-render path outside `render()`'s own bookkeeping (`sensor.audi_dashboard_app_version`
changing state reaches the embedded panel through Home Assistant's own `set hass()` plumbing, not
through this app's `route`/`letzteAnsicht` mechanism at all) — plausible but not conclusively traced
before the owner asked to move on rather than keep chasing the exact mechanism. Fixed pragmatically
instead of surgically: the `data-update` click handler for `pruefen`/`installieren` now captures
`$("#view").scrollTop` once before acting, and re-asserts it via `requestAnimationFrame` after *each*
of its own `render()` calls (both the immediate one and the one in `.finally()`) — this corrects the
position regardless of what else might be moving it, without needing to identify or touch whatever the
second path turns out to be. Verified live at `1280×800`: repeated the exact same scroll-deep-then-click
sequence that reproduced the bug: **no visible jump**, page stayed on the same section
before and after. (Separately noticed, not fixed, not in scope of what was asked: the check's *result*
only shows up in the currently-open tab after a full page reload, even though it's correctly persisted
server-side immediately — confirmed via `docker logs` showing the check completed and a subsequent
fresh page load showing the right "Verfügbare Version" — likely because nothing in this flow re-reads
`sensor.audi_dashboard_app_version`'s `daten` attribute into `INTEGRATION_UPDATE` and re-renders when
that entity's state changes out from under the open tab. Pre-existing, not caused by this fix, not
reported by the owner as a problem — worth a look if it ever is.)
Manifest bumped to `2026.8.24.12` for this fix.
---
## Working conventions (observed — keep them)
@@ -4669,7 +4669,22 @@ function ereignisseVerdrahten() {
// diese drei Aktionen brauchen einen sichtbaren Ladezustand, siehe
// INTEGRATION_UPDATE_LAEUFT's Kommentar an der Deklaration.
if (aktion === "pruefen" || aktion === "installieren") {
// Im Großbild-Layout (Seitenleiste statt Tableiste) sprang die Seite
// beim Klick sichtbar nach oben, obwohl render() den Scroll eigentlich
// wiederherstellt (v.scrollTop = merkeScroll) - die Zustandsänderung
// an sensor.audi_dashboard_app_version, die dieser Aufruf auslöst,
// verschiebt scrollTop zusätzlich über einen zweiten, äußeren Pfad
// (HA reicht jede Zustandsänderung an das eingebettete Panel durch).
// Statt die Ursache dort zu jagen: fester Merkwert vor dem Klick, per
// rAF nach jedem render() dieses Ablaufs erneut erzwungen - wirkt
// gegen render()s eigene Wiederherstellung UND gegen den äußeren Pfad.
const merkeScrollUpdate = $("#view").scrollTop;
const scrollWiederherstellen = () => requestAnimationFrame(() => {
const view = $("#view");
if (view) view.scrollTop = merkeScrollUpdate;
});
INTEGRATION_UPDATE_LAEUFT = aktion; render();
scrollWiederherstellen();
HASS.callService(DOMAIN, `update_${aktion}`, {})
.catch((err) => {
hinweis(
@@ -4677,7 +4692,7 @@ function ereignisseVerdrahten() {
err && err.message ? err.message : "Der Dienst konnte nicht ausgeführt werden.",
);
})
.finally(() => { INTEGRATION_UPDATE_LAEUFT = null; render(); });
.finally(() => { INTEGRATION_UPDATE_LAEUFT = null; render(); scrollWiederherstellen(); });
} else if (aktion === "neustart") {
INTEGRATION_UPDATE_LAEUFT = "neustart"; render();
HASS.callService("homeassistant", "restart", {}).catch((err) => {
@@ -1,7 +1,7 @@
{
"domain": "audi_dashboard",
"name": "Audi Dashboard",
"version": "2026.8.24.11",
"version": "2026.8.24.12",
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
"codeowners": ["@paul"],