4a58021670
Drei zusammenhaengende Runden, alle live bei 375x812 gegen audi_ha_test geprueft und in beiden Codebasen angewandt. Paritaetsrunde 2: der gemeinsame Rahmen war das eigentliche Problem - Seitenrand, Kachelabstaende, Kopfleiste, Tableiste und vier Bausteine des Design-Systems trugen noch den Stand vor der iOS-Entscheidung. Dazu sieben Bildschirme neu aufgebaut. Zwei Panel-Fehler dabei mitbehoben: teaser() zeigte unter "Letzte Fahrt" den aeltesten Datensatz, und "Daten bearbeiten" war ein toter Knopf. Paritaetsrunde 3: das Panel hat nie Audi Type gerendert. @font-face in einem Shadow Root wird ignoriert - Schriftschnitte registriert der Browser pro Dokument, nie pro Shadow Tree. Die drei Schnitte liegen jetzt in audi-dashboard-schriften.css und werden ins Dokument gehaengt. Damit erledigt sich eine ganze Reihe von "die Schrift sieht anders aus"-Eindruecken: die beiden Anwendungen zeigten tatsaechlich verschiedene Schriften. Ausserdem "Daten bearbeiten" im Panel gebaut und portiert, das Zeilenmenue entfernt und die letzten neun Bildschirme angeglichen. Designpruefung: die fuenf Punkte der Reihenfolge. Beim vierten hat das Messen den Befund veraendert - gezaehlt waren die deklarierten Groessen, wirksam war laengst eine saubere Sieben-Schritt-Skala mit 27 Ausreissern; die sind jetzt auf den naechsten Schritt gezogen, keiner verschiebt sich um mehr als 1px. Zuletzt: die Standortvorschau zeichnete die falsche Nadel (das Panel wechselt den Icon-Satz ab 34px, die App nahm immer den grossen), und der Kopfabstand der App ist auf den sicheren Bereich reduziert - die 56px des Panels liegen dort unter der Kopfleiste von Home Assistant, in der nativen Huelle steht darueber nichts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
/**
|
|
* Tag/Nacht-Umschaltung, übernommen aus dem alten Panel (A6 des Design-Audits):
|
|
* gespeicherte Wahl schlägt Systemeinstellung, Standard ist "nacht".
|
|
* Alle localStorage-Zugriffe sind abgesichert, weil sie im Privatmodus mancher
|
|
* Browser werfen.
|
|
*/
|
|
|
|
import { useCallback, useEffect, useState } from "react"
|
|
|
|
export type Theme = "nacht" | "tag"
|
|
|
|
const SCHLUESSEL = "dm360.theme"
|
|
|
|
function gespeichertLesen(): Theme | null {
|
|
try {
|
|
const wert = localStorage.getItem(SCHLUESSEL)
|
|
return wert === "nacht" || wert === "tag" ? wert : null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
function gespeichertSchreiben(theme: Theme): void {
|
|
try {
|
|
localStorage.setItem(SCHLUESSEL, theme)
|
|
} catch {
|
|
// Privatmodus — die Wahl gilt dann nur für diese Sitzung
|
|
}
|
|
}
|
|
|
|
export function themeStartwert(): Theme {
|
|
const gespeichert = gespeichertLesen()
|
|
if (gespeichert) return gespeichert
|
|
const hell =
|
|
typeof window !== "undefined" &&
|
|
typeof window.matchMedia === "function" &&
|
|
window.matchMedia("(prefers-color-scheme: light)").matches
|
|
return hell ? "tag" : "nacht"
|
|
}
|
|
|
|
export function useTheme(): [Theme, (theme: Theme) => void] {
|
|
const [theme, setzeTheme] = useState<Theme>(themeStartwert)
|
|
|
|
const setzen = useCallback((neu: Theme) => {
|
|
setzeTheme(neu)
|
|
gespeichertSchreiben(neu)
|
|
}, [])
|
|
|
|
// Farbe der Systemleisten mitziehen, damit auf dem Handy kein heller
|
|
// Balken über einer dunklen App steht.
|
|
useEffect(() => {
|
|
const marke = document.querySelector('meta[name="theme-color"]')
|
|
// Werte des Panels (--canvas in audi-dashboard-ios.css). Hier standen noch
|
|
// #161b23/#ffffff aus dem Basis-Stylesheet, das im Panel nie greift —
|
|
// die Systemleiste hatte damit einen anderen Ton als die App darunter.
|
|
if (marke) marke.setAttribute("content", theme === "nacht" ? "#0C1014" : "#F2F2F7")
|
|
}, [theme])
|
|
|
|
return [theme, setzen]
|
|
}
|
|
|
|
/**
|
|
* Bodenschatten unter dem Fahrzeugbild — im Panel der Schalter „Boden" in den
|
|
* Einstellungen (`bodenAn`). Dort lebt er nur im Speicher und ist nach einem
|
|
* Neuladen wieder an; hier folgt er dem Muster der übrigen Ansichtsschalter
|
|
* und bleibt erhalten, Standard wie im Panel: an.
|
|
*/
|
|
const BODEN_SCHLUESSEL = "dm360.boden"
|
|
|
|
export function useBoden(): [boolean, (an: boolean) => void] {
|
|
const [an, setzeAn] = useState<boolean>(() => {
|
|
try {
|
|
return localStorage.getItem(BODEN_SCHLUESSEL) !== "aus"
|
|
} catch {
|
|
return true
|
|
}
|
|
})
|
|
|
|
const setzen = useCallback((neu: boolean) => {
|
|
setzeAn(neu)
|
|
try {
|
|
localStorage.setItem(BODEN_SCHLUESSEL, neu ? "an" : "aus")
|
|
} catch {
|
|
// Privatmodus
|
|
}
|
|
}, [])
|
|
|
|
return [an, setzen]
|
|
}
|
|
|
|
/** Sichtbarkeit der Tab-Beschriftungen, ebenfalls dauerhaft gespeichert. */
|
|
const BESCHRIFTUNG_SCHLUESSEL = "dm360.tabbeschriftung"
|
|
|
|
export function useTabBeschriftung(): [boolean, (an: boolean) => void] {
|
|
const [an, setzeAn] = useState<boolean>(() => {
|
|
try {
|
|
return localStorage.getItem(BESCHRIFTUNG_SCHLUESSEL) !== "aus"
|
|
} catch {
|
|
return true
|
|
}
|
|
})
|
|
|
|
const setzen = useCallback((neu: boolean) => {
|
|
setzeAn(neu)
|
|
try {
|
|
localStorage.setItem(BESCHRIFTUNG_SCHLUESSEL, neu ? "an" : "aus")
|
|
} catch {
|
|
// Privatmodus
|
|
}
|
|
}, [])
|
|
|
|
return [an, setzen]
|
|
}
|