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

5.5 KiB

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 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.