Files
audi-app/companion-app/docs/SHARE_EXTENSION.md
T
tobias b1411625aa 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 <noreply@anthropic.com>
2026-08-31 14:24:52 +02:00

121 lines
5.5 KiB
Markdown

# Tankbeleg aus dem Teilen-Blatt
Ein PDF aus Mail (oder einer anderen App) über **Teilen → DataMetric360** direkt
als Tankbeleg übernehmen.
## Wie es zusammenhängt
```
Mail ──Teilen──► DataMetric360Share (eigener Prozess)
│ PDF → Base64 → UserDefaults der App-Gruppe
│ group.app.datametric360
datametric360://beleg (öffnet die App)
App.tsx ──holt ab──► Tanken-Seite ──► belegLesen()
```
Eine Erweiterung ist ein eigener Prozess mit eigenem Dateibereich; der einzige
gemeinsame Boden mit der App ist die **App-Gruppe**. Der Beleg reist deshalb
Base64-kodiert durch die geteilten `UserDefaults` — die liest
`@capacitor/preferences` ohnehin schon, sobald man ihm die Gruppe nennt. Eine
Datei im Gruppen-Container wäre der sauberere Ort, bräuchte auf der App-Seite
aber eigenen nativen Code, also ein zusätzliches Plugin für einen Weg, den es
sonst nicht gäbe.
Der Preis ist eine Größengrenze von 4 MB (`grenzeBytes` im
`ShareViewController`). Ein Tankbeleg liegt bei einigen Dutzend Kilobyte; ein
gescanntes Mehrseiten-PDF kann darüber liegen — dann sagt die Erweiterung das,
und der Weg über **Beleg hochladen → Datei auswählen** in der App bleibt.
## Wo was liegt
| Datei | Rolle |
|---|---|
| `native/teilen/ShareViewController.swift` | nimmt das PDF entgegen, legt es ab, öffnet die App |
| `native/teilen/Info.plist` | wann DataMetric360 im Teilen-Blatt erscheint (genau ein PDF) |
| `native/teilen/DataMetric360Share.entitlements` | App-Gruppe für die Erweiterung |
| `native/App.entitlements` | dieselbe App-Gruppe für die App |
| `scripts/ios-teilen-einrichten.mjs` | hängt das alles ins erzeugte Xcode-Projekt |
| `src/daten/geteilterBeleg.ts` | holt den Beleg ab, räumt ihn weg |
| `src/App.tsx` | prüft beim Start und bei jeder Rückkehr, springt auf Tanken |
| `src/screens/Tanken.tsx` | nimmt ihn auf und lädt ihn hoch |
**`companion-app/ios/` ist gitignored** und wird von `npx cap add ios` neu
gebaut. Alles Native muss deshalb unter `native/` liegen und bei jedem Bau
eingespielt werden — dieselbe Regel, die schon die Team-Kennung und den
Standort-Schlüssel in `ios-signieren.sh` getrieben hat.
## Einmalig im Apple-Entwicklerportal
Ohne diese drei Schritte schlägt das Signieren fehl (die App-Gruppe muss
existieren, bevor ein Profil sie enthalten kann):
1. **Identifiers → App Groups**: `group.app.datametric360` anlegen.
2. **Identifiers → App IDs**: `app.datametric360.teilen` anlegen, Capability
*App Groups* aktivieren, die Gruppe zuordnen.
3. Bei der bestehenden App-ID `app.datametric360` ebenfalls *App Groups*
aktivieren und dieselbe Gruppe zuordnen.
Danach in Xcode einmal die Profile neu ziehen lassen — oder schlicht
`ios-signieren.sh` laufen lassen, das macht `-allowProvisioningUpdates`
selbst. **Merkposten aus Abschnitt AI:** ein zwischengespeichertes altes
Profil wird stillschweigend weiterverwendet. Ändert sich etwas an den
Berechtigungen, das passende `.mobileprovision` unter
`~/Library/Developer/Xcode/UserData/Provisioning Profiles` löschen und neu
exportieren.
## Bauen
```bash
bash scripts/ios-signieren.sh
```
Der Schritt „Share-Erweiterung einrichten" läuft dort automatisch, vor dem
Archivieren.
## Wenn das Skript abbricht
`ios-teilen-einrichten.mjs` bearbeitet die `project.pbxproj` über das
npm-Paket `xcode`. **Das ist auf keinem Mac erprobt** — geschrieben ohne
Zugriff auf macOS. Bricht es ab, ist nichts halb eingerichtet (es bricht vor
dem Schreiben ab), und dasselbe lässt sich in Xcode von Hand erledigen:
1. **File → New → Target… → Share Extension**, Name `DataMetric360Share`,
Sprache Swift, „Activate scheme" verneinen.
2. Die von Xcode erzeugten `ShareViewController.swift`, `Info.plist` und das
`MainInterface.storyboard` **löschen** und stattdessen die Dateien aus
`native/teilen/` in das Ziel legen (Storyboard wird nicht gebraucht, die
Erweiterung hat keine eigene Oberfläche).
3. Bundle-ID des Ziels auf `app.datametric360.teilen` setzen.
4. Beide Ziele → **Signing & Capabilities → + Capability → App Groups**,
`group.app.datametric360` anhaken.
5. Ziel `DataMetric360Share` → Build Settings → *Code Signing Entitlements* auf
`DataMetric360Share/DataMetric360Share.entitlements`; Ziel `App` auf
`App/App.entitlements`.
6. Ziel `App` → Build Phases → **Embed App Extensions** muss
`DataMetric360Share.appex` enthalten.
7. `ios/App/App/Info.plist`: URL-Schema `datametric360` unter
`CFBundleURLTypes` eintragen.
Schritt 7 ist der leiseste: fehlt er, wird der Beleg abgelegt, die App aber
nicht geöffnet — er taucht dann erst auf, wenn man die App das nächste Mal von
Hand startet.
## Prüfen, ob es wirkt
1. In Mail ein PDF antippen → **Teilen** → DataMetric360 muss in der Liste
stehen (nur bei genau einem PDF, sonst absichtlich nicht).
2. Antippen → die App kommt nach vorn, springt auf **Tanken**, das Formular ist
offen und liest den Beleg („Beleg wird gelesen …").
3. Danach ist der Eintrag weg: dieselbe Datei ein zweites Mal zu teilen muss
wieder funktionieren, ein bloßes Wechseln in die App darf den Beleg **nicht**
erneut verarbeiten.
## Was hier nicht steht
Android. Der Ablauf ist dort ein anderer (`intent-filter` statt App-Gruppe),
und die Android-Hülle dieses Projekts ist ohnehin nicht in Gebrauch.