Teilen-Blatt, HIG-Blaetter, geteilte Ansichtseinstellungen (2026.8.31.1)
Share-Erweiterung: ein PDF aus Mail landet ueber Teilen -> DataMetric360 als Tankbeleg. Alles Native liegt versioniert unter companion-app/native/, weil ios/ gitignored ist und npx cap add ios es sonst wieder frisst; scripts/ios-teilen-einrichten.mjs haengt es bei jedem Bau ins Xcode-Projekt und ist in ios-signieren.sh eingehaengt. Der pbxproj-Teil ist auf keinem Mac erprobt - er bricht vor dem Schreiben ab, und docs/SHARE_EXTENSION.md beschreibt dieselben Handgriffe fuer Xcode. "In den Kalender uebernehmen" ging in der App nie: WKWebView ignoriert das download-Attribut, der Klick lief ins Leere. Auf dem Geraet jetzt @capacitor/filesystem plus @capacitor/share. useTheme/useBoden legten je Aufrufer eigenen Zustand an - fuenf Kopien. Der Schalter aenderte nur seine eigene, data-theme in App.tsx blieb stehen, die Tag/Nacht-Umschaltung wirkte erst nach einem Neustart. Jetzt ein Speicher je Einstellung ueber useSyncExternalStore. Zwei Regressionstests, gegen den alten Stand als fehlschlagend nachgewiesen. Alle Popups nach Apple HIG: neue Bausteine Sheet und ActionSheet, blickdicht und mit abgedunkeltem Schleier, in beiden Codebasen. Popup portalierte nach document.body - ausserhalb von [data-theme] - und war deshalb im Tagmodus fast unsichtbar; Portal zielt jetzt auf .ads-root. ImagePlaceholder merkte sich "fehlgeschlagen" ohne die Adresse: nach einem leeren Galerieplatz zeigten auch die mit Foto nur noch den Platzhalter. Vier Regressionstests, ebenfalls gegen den alten Stand geprueft. Bildadressen tragen jetzt einen Cache-Brecher - HA liefert /local/ mit 31 Tagen Cache-Vorgabe aus, im Panel eingefuegte Radfotos erschienen in der App deshalb nicht. uebersichtsbild: Panel speichert den Namen, die App verglich gegen den Dateinamen - der Vergleich traf nie zu. Kanonisch ist der Name. Weiter: Navigationspfeil statt gleichschenkligem Dreieck auf der Streckenlinie (die Kerbe unterscheidet Kopf und Ende), CI-Symbol tour-s als Fahrten-Icon, Datumsfelder zeigen ihren Wert ohne erstes Antippen, feste Beispielnamen im Setup, Kopf-Gegengewicht fuer mittige Titel, Standort-Blatt mit festem Fussabstand, NSLocationWhenInUseUsageDescription, watchPosition fuer die Live-Ortung, Art-Pille wieder als Knopf, Zwischenablage fuer Tankbelege. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Regression: die Tag/Nacht-Umschaltung blieb wirkungslos.
|
||||
*
|
||||
* Jeder Aufruf von `useTheme()` legte bis 2026-08-31 sein eigenes `useState`
|
||||
* an. Der Schalter in den Einstellungen änderte damit nur seine eigene Kopie;
|
||||
* die Kopie in `App.tsx`, die `data-theme` setzt, blieb stehen — sichtbar
|
||||
* wurde die Wahl erst nach einem Neustart der App. Der Boden-Schalter hatte
|
||||
* denselben Fehler.
|
||||
*
|
||||
* Der Test stellt genau diese Konstellation nach: zwei getrennte Komponenten,
|
||||
* eine schaltet, die andere zeigt an.
|
||||
*/
|
||||
|
||||
import { fireEvent, render, screen } from "@testing-library/react"
|
||||
import { beforeEach, describe, expect, it } from "vitest"
|
||||
|
||||
import { useBoden, useTheme } from "./theme"
|
||||
|
||||
function Anzeige() {
|
||||
const [theme] = useTheme()
|
||||
const [boden] = useBoden()
|
||||
return (
|
||||
<div>
|
||||
<span data-testid="theme">{theme}</span>
|
||||
<span data-testid="boden">{boden ? "an" : "aus"}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Schalter() {
|
||||
const [theme, setzeTheme] = useTheme()
|
||||
const [boden, setzeBoden] = useBoden()
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => setzeTheme(theme === "nacht" ? "tag" : "nacht")}>Thema</button>
|
||||
<button onClick={() => setzeBoden(!boden)}>Boden</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
describe("Ansichtseinstellungen, geteilt zwischen Komponenten", () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
it("die Themenwahl der einen Komponente erreicht die andere", () => {
|
||||
render(
|
||||
<>
|
||||
<Anzeige />
|
||||
<Schalter />
|
||||
</>,
|
||||
)
|
||||
const vorher = screen.getByTestId("theme").textContent
|
||||
|
||||
fireEvent.click(screen.getByText("Thema"))
|
||||
|
||||
expect(screen.getByTestId("theme").textContent).not.toBe(vorher)
|
||||
})
|
||||
|
||||
it("der Boden-Schalter der einen Komponente erreicht die andere", () => {
|
||||
render(
|
||||
<>
|
||||
<Anzeige />
|
||||
<Schalter />
|
||||
</>,
|
||||
)
|
||||
const vorher = screen.getByTestId("boden").textContent
|
||||
|
||||
fireEvent.click(screen.getByText("Boden"))
|
||||
|
||||
expect(screen.getByTestId("boden").textContent).not.toBe(vorher)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user