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>
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):
- Identifiers → App Groups:
group.app.datametric360anlegen. - Identifiers → App IDs:
app.datametric360.teilenanlegen, Capability App Groups aktivieren, die Gruppe zuordnen. - Bei der bestehenden App-ID
app.datametric360ebenfalls 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:
- File → New → Target… → Share Extension, Name
DataMetric360Share, Sprache Swift, „Activate scheme" verneinen. - Die von Xcode erzeugten
ShareViewController.swift,Info.plistund dasMainInterface.storyboardlöschen und stattdessen die Dateien ausnative/teilen/in das Ziel legen (Storyboard wird nicht gebraucht, die Erweiterung hat keine eigene Oberfläche). - Bundle-ID des Ziels auf
app.datametric360.teilensetzen. - Beide Ziele → Signing & Capabilities → + Capability → App Groups,
group.app.datametric360anhaken. - Ziel
DataMetric360Share→ Build Settings → Code Signing Entitlements aufDataMetric360Share/DataMetric360Share.entitlements; ZielAppaufApp/App.entitlements. - Ziel
App→ Build Phases → Embed App Extensions mussDataMetric360Share.appexenthalten. ios/App/App/Info.plist: URL-Schemadatametric360unterCFBundleURLTypeseintragen.
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
- In Mail ein PDF antippen → Teilen → DataMetric360 muss in der Liste stehen (nur bei genau einem PDF, sonst absichtlich nicht).
- Antippen → die App kommt nach vorn, springt auf Tanken, das Formular ist offen und liest den Beleg („Beleg wird gelesen …").
- 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.