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 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 21:15:50 +02:00
parent d889353cbe
commit 36a6c21bfd
8 changed files with 162 additions and 37 deletions
+23 -1
View File
@@ -33,9 +33,31 @@ interface AusstattungGruppe {
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 }) {
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
const aktiverSatz =
+26 -2
View File
@@ -79,8 +79,29 @@ function hash(text: string): number {
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 {
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(
@@ -102,7 +123,10 @@ export async function kalenderDateiLaden(
directory: Directory.Cache,
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
}
+28 -16
View File
@@ -1092,27 +1092,39 @@ button.dm-sicherheitszeile:active { background: var(--tile-2); }
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
16px) und Farbe - beim Lesen wirkte die Liste dadurch zweistufig statt
dreistufig, und genau danach hat der Eigentümer gefragt (02.09.2026).
Versalien plus Sperrung sind die Form, die iOS für Abschnittsköpfe
benutzt und die in dieser Oberfläche schon über dem Seitentitel steht
(.ads-eyebrow).
In der Liste standen drei Elemente in drei Formaten: 2026 in 16px weiß,
September in 11px grau gesperrt in Versalien, der Ortsname wieder in 16px
weiß. Der Eigentümer hat das am 02.09.2026 als unprofessionell bezeichnet -
zu Recht: zwei Köpfe, die dasselbe tun, sollen auch gleich aussehen.
11px und nicht 10: das ist die Untergrenze, die dieses Projekt aus den
Apple-Richtlinien übernommen hat. In beiden Oberflächen dieselben Werte,
damit der Kopf nicht je Gerät anders aussieht. */
.dm-liste .ads-accordion--lvl2 .ads-acc-h__k {
font-size: 11px;
letter-spacing: .18em;
text-transform: uppercase;
color: var(--fg3);
Beide jetzt 13px in der Zweitfarbe, gemischt geschrieben und ohne Sperrung.
Das ist zugleich die heutige Apple-Form: Abschnittsköpfe klein und in
Sekundärfarbe, aber gemischt - Versalien sind der Stil vor iOS 13. Der
Inhalt bleibt größer als sein Kopf, wie es die Richtlinien verlangen.
Unterschieden werden die beiden Ebenen über die Position, nicht über die
Schrift.
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 {
padding-left: 0;
padding-left: 20px;
}
.dm-blatt {