Listenkoepfe vereinheitlicht, Zeilen mit Luft, Kalenderdateien mit Namen (2026.9.2.21-.23)
KOEPFE. Jahr und Monat tragen dasselbe Format (13px, Zweitfarbe, gemischt) - vorher drei Elemente in drei Formaten. Die Versalien aus .20 waren falsch: das ist der iOS-Stil vor 13. Vom Eigentuemer aus drei gerenderten Vorschlaegen gewaehlt. ZEILEN. padding-left 20px statt 0 - die Spalte des Aufklapp-Pfeils, damit die Zeilen auf derselben Kante stehen wie der Text der Koepfe. Nachgemessen bei 375px: Beschriftungsspalte 157px, laengster Ortsname 142,7px. GALERIE. Der gezeigte Platz ueberlebt den Seitenwechsel - er lag in der Komponente und starb mit ihr. Im Panel ist er seit jeher modulweit. KALENDER. Jeder Termin hiess "-.ics": in dateiname() fehlte das \w in der Zeichenklasse, es ueberlebten nur w/ae/oe/ue/ss und der Bindestrich. Zwei Termine ueberschrieben einander damit. Jetzt mit Umschrift und Rueckfall, und ueber Share.files statt Share.url. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -8284,3 +8284,57 @@ Projekts aus den Apple-Richtlinien.
|
|||||||
- **Hochladen über einen eigenen HTTP-Endpunkt** statt über den Dienst: hebt die 3-MB-Grenze des
|
- **Hochladen über einen eigenen HTTP-Endpunkt** statt über den Dienst: hebt die 3-MB-Grenze des
|
||||||
Panels auf (WebSocket, aiohttp-Vorgabe 4 MiB) und spart die Base64-Aufblähung. Gemessen: über
|
Panels auf (WebSocket, aiohttp-Vorgabe 4 MiB) und spart die Base64-Aufblähung. Gemessen: über
|
||||||
REST gehen 12 MB durch, über den WebSocket bricht die Verbindung ab 3,2 MB Rohbild wortlos ab.
|
REST gehen 12 MB durch, über den WebSocket bricht die Verbindung ab 3,2 MB Rohbild wortlos ab.
|
||||||
|
|
||||||
|
### Nachtrag .21-.23: gleiche Köpfe, Luft an den Zeilen, und `-.ics`
|
||||||
|
|
||||||
|
**Die Listenköpfe tragen jetzt dasselbe Format** (Vorschlag B von dreien, vom Eigentümer gewählt):
|
||||||
|
Jahr und Monat beide 13px in der Zweitfarbe, gemischt geschrieben, ohne Sperrung; die Fahrtzeile
|
||||||
|
bleibt 16px. Vorher standen drei Elemente in drei Formaten — 16px weiß, 11px grau gesperrt in
|
||||||
|
Versalien, wieder 16px weiß. Die Versalien aus .20 waren mein Fehlgriff: sie sind der iOS-Stil vor
|
||||||
|
13, heute schreibt Apple Abschnittsköpfe gemischt. Unterschieden werden die Ebenen über die
|
||||||
|
Position, nicht über die Schrift. Tanken teilt die Regel; seine rechte Spalte bleibt bewusst
|
||||||
|
anders (Ansage des Eigentümers).
|
||||||
|
|
||||||
|
Die drei Vorschläge lagen als gerendertes Muster vor (echte App-CSS, Audi Type, eigenständige HTML)
|
||||||
|
— das ist der Weg, der bei Gestaltungsfragen zu einer Entscheidung führt, statt sie zu beschreiben.
|
||||||
|
|
||||||
|
**Die Zeilen haben wieder Luft**: `padding-left: 20px` statt 0. Das ist nicht geraten, sondern die
|
||||||
|
Spalte des Aufklapp-Pfeils — die Zeilen stehen damit auf derselben Kante wie der Text der
|
||||||
|
Kopfzeilen, wie iOS es in gruppierten Listen macht. Bei 375px behält die Beschriftungsspalte 157px,
|
||||||
|
der längste Ortsname der Testdaten braucht 142,7px. Von den 58px aus .19 bleiben 38 gewonnen.
|
||||||
|
|
||||||
|
**Die Galerie merkt sich ihren Platz.** `useState(0)` setzte ihn bei jeder Rückkehr auf die
|
||||||
|
Seitenansicht zurück. Im Panel war das nie aufgefallen, weil `bild` dort eine modulweite Variable
|
||||||
|
ist und den Seitenwechsel überlebt; in der App lag der Zustand in der Komponente und starb mit ihr.
|
||||||
|
|
||||||
|
**Jeder Kalendertermin hieß `-.ics`.** In `dateiname()` stand `[^wäöüÄÖÜß-]`, gemeint war
|
||||||
|
`[^\wäöüÄÖÜß-]` — ohne das `\w` überlebten nur w, ä, ö, ü, ß und der Bindestrich:
|
||||||
|
|
||||||
|
| Titel | vorher | jetzt |
|
||||||
|
|---|---|---|
|
||||||
|
| RS4 Avant competition: Ölwechsel | `-ö-w-.ics` | `rs4-avant-competition-oelwechsel.ics` |
|
||||||
|
| Audi RS4: Inspektion | `-.ics` | `audi-rs4-inspektion.ics` |
|
||||||
|
| Wechseltermin | `-.ics` | `wechseltermin.ics` |
|
||||||
|
|
||||||
|
Zwei verschiedene Termine überschrieben einander damit im Zwischenspeicher. Umlaute werden jetzt
|
||||||
|
umgeschrieben statt weggeworfen (ein „ö" im Dateinamen muss über die Teilen-Kette prozentkodiert
|
||||||
|
werden — eine Fehlerquelle weniger), und die Übergabe läuft über `files` statt `url`.
|
||||||
|
|
||||||
|
**Nicht bestätigt ist, dass das den Kalender-Export repariert.** Der Verdacht bleibt, dass iOS
|
||||||
|
„Kalender" im Teilen-Blatt gar nicht als Ziel führt; der verlässliche Weg wäre EventKit, also
|
||||||
|
nativ. Steht zur Prüfung beim Eigentümer.
|
||||||
|
|
||||||
|
### Was am 02.09. abends offen blieb
|
||||||
|
|
||||||
|
- **Fahrt bleibt offen, wenn das Trip-Signal ihr Ende nie meldet.** Im Testcontainer nachgewiesen:
|
||||||
|
Trip-Status ging 16:33:15 auf `on` und nie wieder auf `off`, Zündung ging 16:54:21 aus, der
|
||||||
|
Kilometerstand stand ab 16:52 (209.480 → 209.490, also 10 km). Im Laufzeitspeicher steht seither
|
||||||
|
`fahrt_start_ts: 2026-09-02T16:32:18` — die Fahrt ist nie in der Liste gelandet. Der FMM003 hätte
|
||||||
|
`trip=false` nach seinem eigenen 900-s-Timeout senden müssen. **Vorschlag, noch nicht gebaut**
|
||||||
|
(der Eigentümer prüft zuerst den Dongle): bleibt das Trip-Signal an, während die Zündung länger
|
||||||
|
als 900s + Puffer aus ist und der Kilometerstand steht, die Fahrt zum Zündungsende schließen.
|
||||||
|
- **Zwischenablage:** `navigator.clipboard.read()` gibt in WebKit nur Text, HTML und Bilder heraus.
|
||||||
|
Ein PDF ist dort nie zu holen — der Knopf kann nicht funktionieren. Entweder nativ über
|
||||||
|
`UIPasteboard` oder er verschwindet auf dem Telefon.
|
||||||
|
- **Teilen legt keinen Tankvorgang an** (Abschnitt BQ) — die drei OTA-Teile und der native Umbau
|
||||||
|
stehen weiter aus.
|
||||||
|
|||||||
@@ -33,9 +33,31 @@ interface AusstattungGruppe {
|
|||||||
serie?: string[]
|
serie?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Zuletzt gezeigter Galerieplatz - modulweit, damit er den Seitenwechsel
|
||||||
|
ueberlebt (siehe Begruendung in der Komponente). */
|
||||||
|
let gemerkterBildIndex = 0
|
||||||
|
|
||||||
export function MeinAudi({ geheZu }: { geheZu: (name: SeitenName, id?: string) => void }) {
|
export function MeinAudi({ geheZu }: { geheZu: (name: SeitenName, id?: string) => void }) {
|
||||||
const { fahrzeug, einstellungen } = useDaten()
|
const { fahrzeug, einstellungen } = useDaten()
|
||||||
const [bildIndex, setzeBildIndex] = useState(0)
|
/* Der Platz in der Galerie ueberlebt den Seitenwechsel.
|
||||||
|
|
||||||
|
useState(0) setzte ihn bei jeder Rueckkehr auf die Seitenansicht zurueck
|
||||||
|
- wer sich das Cockpit ansah, im Menue wechselte und zurueckkam, fing
|
||||||
|
wieder vorn an (gemeldet vom Eigentuemer, 02.09.2026). Im Panel ist das
|
||||||
|
nie aufgefallen, weil `bild` dort eine modulweite Variable ist und den
|
||||||
|
Seitenwechsel deshalb ueberlebt; hier liegt der Zustand in der
|
||||||
|
Komponente und stirbt mit ihr.
|
||||||
|
|
||||||
|
Modulweit statt im Speicher: der Platz ist eine Ansichtssache, kein
|
||||||
|
Datum. Er soll die Sitzung ueberleben, nicht den Neustart. */
|
||||||
|
const [bildIndex, setzeBildIndexIntern] = useState(gemerkterBildIndex)
|
||||||
|
const setzeBildIndex = (naechster: number | ((vorher: number) => number)) => {
|
||||||
|
setzeBildIndexIntern((vorher) => {
|
||||||
|
const wert = typeof naechster === "function" ? naechster(vorher) : naechster
|
||||||
|
gemerkterBildIndex = wert
|
||||||
|
return wert
|
||||||
|
})
|
||||||
|
}
|
||||||
if (!fahrzeug || !einstellungen) return null
|
if (!fahrzeug || !einstellungen) return null
|
||||||
|
|
||||||
const aktiverSatz =
|
const aktiverSatz =
|
||||||
|
|||||||
@@ -79,8 +79,29 @@ function hash(text: string): number {
|
|||||||
return wert
|
return wert
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dateiname für den Termin.
|
||||||
|
*
|
||||||
|
* Hier stand `[^wäöüÄÖÜß-]` - gemeint war `[^\\wäöüÄÖÜß-]`, also "alles
|
||||||
|
* außer Wortzeichen". Ohne das `\\w` überlebten nur w, ä, ö, ü, ß und der
|
||||||
|
* Bindestrich: aus "Wechseltermin" wurde `-.ics`, aus "Audi RS4: Inspektion"
|
||||||
|
* ebenfalls `-.ics`. Ein Name ohne Stamm, und zwei verschiedene Termine
|
||||||
|
* überschrieben einander im Zwischenspeicher.
|
||||||
|
*
|
||||||
|
* Jetzt mit Umlaut-Umschrift statt Wegwerfen (ein "ö" im Dateinamen muss über
|
||||||
|
* die Teilen-Kette prozentkodiert werden und ist eine Fehlerquelle mehr),
|
||||||
|
* zusammengefassten Bindestrichen und einem Rückfall, falls vom Titel nichts
|
||||||
|
* übrig bleibt.
|
||||||
|
*/
|
||||||
function dateiname(titel: string): string {
|
function dateiname(titel: string): string {
|
||||||
return `${titel.replace(/[^wäöüÄÖÜß-]+/g, "-").toLowerCase()}.ics`
|
const stamm = titel
|
||||||
|
.replace(/ä/g, "ae").replace(/ö/g, "oe").replace(/ü/g, "ue")
|
||||||
|
.replace(/Ä/g, "Ae").replace(/Ö/g, "Oe").replace(/Ü/g, "Ue")
|
||||||
|
.replace(/ß/g, "ss")
|
||||||
|
.replace(/[^A-Za-z0-9]+/g, "-")
|
||||||
|
.replace(/^-+|-+$/g, "")
|
||||||
|
.toLowerCase()
|
||||||
|
return `${stamm || "termin"}.ics`
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function kalenderDateiLaden(
|
export async function kalenderDateiLaden(
|
||||||
@@ -102,7 +123,10 @@ export async function kalenderDateiLaden(
|
|||||||
directory: Directory.Cache,
|
directory: Directory.Cache,
|
||||||
encoding: Encoding.UTF8,
|
encoding: Encoding.UTF8,
|
||||||
})
|
})
|
||||||
await Share.share({ title: titel, url: geschrieben.uri })
|
/* files statt url: beides landet im Plugin als URL in den activityItems,
|
||||||
|
aber `files` ist der dokumentierte Weg für lokale Dateien - `url` ist
|
||||||
|
für Links gedacht. dialogTitle ist Android-only und schadet hier nicht. */
|
||||||
|
await Share.share({ title: titel, files: [geschrieben.uri], dialogTitle: titel })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1092,27 +1092,39 @@ button.dm-sicherheitszeile:active { background: var(--tile-2); }
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Der Monat ist ein Abschnittskopf, kein kleingeratener Eintrag.
|
/* Jahr und Monat tragen DENSELBEN Kopf, die Fahrtzeile trägt den Inhalt.
|
||||||
|
|
||||||
Vorher unterschied er sich von der Fahrtzeile nur durch Größe (13 gegen
|
In der Liste standen drei Elemente in drei Formaten: 2026 in 16px weiß,
|
||||||
16px) und Farbe - beim Lesen wirkte die Liste dadurch zweistufig statt
|
September in 11px grau gesperrt in Versalien, der Ortsname wieder in 16px
|
||||||
dreistufig, und genau danach hat der Eigentümer gefragt (02.09.2026).
|
weiß. Der Eigentümer hat das am 02.09.2026 als unprofessionell bezeichnet -
|
||||||
Versalien plus Sperrung sind die Form, die iOS für Abschnittsköpfe
|
zu Recht: zwei Köpfe, die dasselbe tun, sollen auch gleich aussehen.
|
||||||
benutzt und die in dieser Oberfläche schon über dem Seitentitel steht
|
|
||||||
(.ads-eyebrow).
|
|
||||||
|
|
||||||
11px und nicht 10: das ist die Untergrenze, die dieses Projekt aus den
|
Beide jetzt 13px in der Zweitfarbe, gemischt geschrieben und ohne Sperrung.
|
||||||
Apple-Richtlinien übernommen hat. In beiden Oberflächen dieselben Werte,
|
Das ist zugleich die heutige Apple-Form: Abschnittsköpfe klein und in
|
||||||
damit der Kopf nicht je Gerät anders aussieht. */
|
Sekundärfarbe, aber gemischt - Versalien sind der Stil vor iOS 13. Der
|
||||||
.dm-liste .ads-accordion--lvl2 .ads-acc-h__k {
|
Inhalt bleibt größer als sein Kopf, wie es die Richtlinien verlangen.
|
||||||
font-size: 11px;
|
Unterschieden werden die beiden Ebenen über die Position, nicht über die
|
||||||
letter-spacing: .18em;
|
Schrift.
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--fg3);
|
Von drei Vorschlägen (Monat als eigener Abschnitt ohne Aufklappen / beide
|
||||||
|
Köpfe gleich / Jahr als Seitenüberschrift) hat der Eigentümer diesen
|
||||||
|
gewählt: das Zusammenklappen ganzer Jahre bleibt erhalten. */
|
||||||
|
.dm-liste .ads-acc-h__k {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--fg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 20px statt 0: die Zeilen standen sonst 34px vom Bildschirmrand entfernt und
|
||||||
|
damit sichtbar enger als alles andere in der Kachel (gemeldet 02.09.2026).
|
||||||
|
20px ist nicht geraten, sondern die Spalte des Aufklapp-Pfeils - die Zeilen
|
||||||
|
stehen damit auf derselben Kante wie der Text der Kopfzeilen, so wie iOS es
|
||||||
|
in gruppierten Listen macht.
|
||||||
|
|
||||||
|
Nachgemessen bei 375px: die Beschriftungsspalte behält 157px, der längste
|
||||||
|
Ortsname der Testdaten ("Ingolstadt → Adelschlag") braucht 142,7px. Von den
|
||||||
|
58px, die vorher verschenkt waren, bleiben 38 gewonnen. */
|
||||||
.dm-liste .dm-blatt {
|
.dm-liste .dm-blatt {
|
||||||
padding-left: 0;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dm-blatt {
|
.dm-blatt {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":"2026.9.2.20","sha256":"04aa82b37c019eadf0c9c23bc27e4931b9371dba512ddd979adc1ea70f482924","bytes":266578,"gebaut":"2026-09-02T14:34:34Z"}
|
{"version":"2026.9.2.23","sha256":"a4b55f9576980ea8f52a5c7782bc0879ff7e4c6561e19f844c44dad903bb87c5","bytes":266680,"gebaut":"2026-09-02T19:03:48Z"}
|
||||||
Binary file not shown.
@@ -917,25 +917,38 @@ img.carfix.klein { aspect-ratio: auto; height: auto; }
|
|||||||
ohne Platz zu kosten. Beschränkt auf .liste, weil das linke Polster von
|
ohne Platz zu kosten. Beschränkt auf .liste, weil das linke Polster von
|
||||||
.leaf anderswo (Batteriewerte, Servicebuch) gewollt ist. */
|
.leaf anderswo (Batteriewerte, Servicebuch) gewollt ist. */
|
||||||
.liste .lvl2 { margin-left: 0; }
|
.liste .lvl2 { margin-left: 0; }
|
||||||
/* Der Monat ist ein Abschnittskopf, kein kleingeratener Eintrag.
|
/* Jahr und Monat tragen DENSELBEN Kopf, die Fahrtzeile traegt den Inhalt.
|
||||||
|
|
||||||
Vorher unterschied er sich von der Fahrtzeile nur durch Groesse (13 gegen
|
In der Liste standen drei Elemente in drei Formaten: 2026 in 16px weiss,
|
||||||
16px) und Farbe - beim Lesen wirkte die Liste dadurch zweistufig statt
|
September in 11px grau gesperrt in Versalien, der Ortsname wieder in 16px
|
||||||
dreistufig, und genau danach hat der Eigentuemer gefragt (02.09.2026).
|
weiss. Der Eigentuemer hat das am 02.09.2026 als unprofessionell
|
||||||
Versalien plus Sperrung sind die Form, die iOS fuer Abschnittskoepfe
|
bezeichnet - zu Recht: zwei Koepfe, die dasselbe tun, sollen auch gleich
|
||||||
benutzt und die in dieser Oberflaeche schon ueber dem Seitentitel steht
|
aussehen.
|
||||||
(.eyebrow).
|
|
||||||
|
|
||||||
11px und nicht 10: das ist die Untergrenze, die dieses Projekt aus den
|
Beide jetzt 13px in der Zweitfarbe, gemischt geschrieben und ohne
|
||||||
Apple-Richtlinien uebernommen hat. In beiden Oberflaechen dieselben
|
Sperrung. Das ist zugleich die heutige Apple-Form: Abschnittskoepfe
|
||||||
Werte, damit der Kopf nicht je Geraet anders aussieht. */
|
klein und in Sekundaerfarbe, aber gemischt - Versalien sind der Stil vor
|
||||||
.liste .lvl2 .acc-h .k {
|
iOS 13. Der Inhalt bleibt groesser als sein Kopf, wie es die Richtlinien
|
||||||
font-size: 11px;
|
verlangen. Unterschieden werden die beiden Ebenen ueber die Position,
|
||||||
letter-spacing: .18em;
|
nicht ueber die Schrift.
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--fg3);
|
Von drei Vorschlaegen (Monat als eigener Abschnitt ohne Aufklappen /
|
||||||
|
beide Koepfe gleich / Jahr als Seitenueberschrift) hat der Eigentuemer
|
||||||
|
diesen gewaehlt: das Zusammenklappen ganzer Jahre bleibt erhalten. */
|
||||||
|
.liste .acc-h .k {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--fg2);
|
||||||
}
|
}
|
||||||
.liste .leaf { padding-left: 0; }
|
/* 20px statt 0: die Zeilen standen sonst 34px vom Bildschirmrand entfernt und
|
||||||
|
damit sichtbar enger als alles andere in der Kachel (gemeldet 02.09.2026).
|
||||||
|
20px ist nicht geraten, sondern die Spalte des Aufklapp-Pfeils - die
|
||||||
|
Zeilen stehen damit auf derselben Kante wie der Text der Kopfzeilen, so
|
||||||
|
wie iOS es in gruppierten Listen macht.
|
||||||
|
|
||||||
|
Nachgemessen bei 375px: die Beschriftungsspalte behaelt 157px, der
|
||||||
|
laengste Ortsname der Testdaten ("Ingolstadt -> Adelschlag") braucht
|
||||||
|
142,7px. Von den 58px, die vorher verschenkt waren, bleiben 38 gewonnen. */
|
||||||
|
.liste .leaf { padding-left: 20px; }
|
||||||
|
|
||||||
.tile-h {
|
.tile-h {
|
||||||
display: block; width: 100%;
|
display: block; width: 100%;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"domain": "audi_dashboard",
|
"domain": "audi_dashboard",
|
||||||
"name": "Audi Dashboard",
|
"name": "Audi Dashboard",
|
||||||
"version": "2026.9.2.20",
|
"version": "2026.9.2.23",
|
||||||
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
"documentation": "https://gitea.nothaft.cloud/paul/audi-app/src/branch/main/README.md",
|
||||||
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
"issue_tracker": "https://gitea.nothaft.cloud/paul/audi-app/issues",
|
||||||
"codeowners": ["@paul"],
|
"codeowners": ["@paul"],
|
||||||
|
|||||||
Reference in New Issue
Block a user