Files
Vorrania/ios/README.md
T
ScarriffleandClaude Opus 5 09a763a823 NFC-Tags fuer Einzelstuecke: beschreiben und lesen
Ein aufgeklebtes QR-Etikett uebersteht keine Waesche. Kleidungsstuecke bekommen
deshalb eingenaehte NFC-Tags. Auf das Tag kommt genau das, was auch im QR steckt
(vorrania://i/<UID>) - damit bleibt das Einlesen inhaltlich unveraendert, nur die
Erfassungsart ist neu. Backend und Web brauchten nichts: die UID vergibt der
Server, und GET /items/by-uid/<UID> gibt es laengst.

Gelesen wird nur bei geoeffneter App. iOS startet Apps beim Antippen im
Hintergrund ausschliesslich ueber https-Universal-Links auf einer beanspruchten
Domain und ignoriert eigene Schemes dabei - eine feste Domain ist fuer einen
selbstgehosteten Dienst aber gerade der falsche Weg (siehe f981f41).

Die /i/-Zerlegung lag dreifach kopiert in CheckInView, LookupScanView und
AssignScanView und steckt jetzt in einzelstueckCode(aus:). Die nackte UID wird
nur fuer NFC akzeptiert: eine achtstellige EAN-8 kann zufaellig genau wie eine
UID aussehen, und die Kamera sieht fremde Barcodes - ein Tag haben wir selbst
beschrieben.

Zwei Altlasten in denselben Dateien mit erledigt:
- project.yml deklarierte die applinks-Domain weiter, obwohl f981f41 sie
  entfernt hat. XcodeGen erzeugt die Entitlements aus diesem Block und schrieb
  sie bei jedem "generate" zurueck; die Domain existiert laengst nicht mehr.
- AssignScanView sendete ItemUpdateRequest ohne priceCents/currency. Da encode
  immer alle Felder schreibt (auch null), hat ein Zuordnen per Scan Kaufpreis
  und Waehrung stillschweigend geloescht.

Ebenfalls raus: QRImage und qrLink(forUid:) in ItemViews - ungenutzt, und
qrLink baute noch das alte https-Format.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 13:37:24 +02:00

122 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Vorrania – iOS-App
Native SwiftUI-App für Lebensmittel **und** Gegenstände. Sie spricht dieselbe
REST-API wie die Web-Oberfläche.
> **Stand:** Voll nutzbar. Login; Scannen von Barcode, MHD/Datum (per
> Texterkennung, auch nur Tag+Monat ohne Jahr), Lagerort-QR und Name/Marke;
> Ein-/Auslagern mit mehreren Chargen bzw. Menge je Lagerort; Einzelstücke mit
> UID/QR, Kaufdatum, Garantie und Beleg; Verbrauchsgegenstände als Charge;
> Artikel anlegen (Open Food/Products Facts oder manuell, mit Foto); getrennte
> Listen für Lebensmittel/Gegenstände/Einzelstücke, Kategoriefilter, Sortierung;
> Einkaufsliste, Ablaufliste, Mindestbestände; Verlauf mit Sprung zum Produkt;
> lokale Dashboards und Push-Benachrichtigungen bei ablaufenden Produkten.
## Projekt in Xcode öffnen
### Variante A – mit XcodeGen (empfohlen)
```bash
brew install xcodegen
cd ios
xcodegen generate
open Vorrania.xcodeproj
```
`project.yml` beschreibt das Projekt vollständig (Bundle-ID, Info.plist,
Shortcuts, URL-Schema).
### Variante B – ohne XcodeGen
1. Xcode → *File ▸ New ▸ Project…* → **App**, Interface **SwiftUI**, Sprache **Swift**
2. Produktname `Vorrania`, Bundle-ID z. B. `com.scarriffle.vorrania`
3. Die von Xcode erzeugte `ContentView.swift` und `…App.swift` löschen
4. Den Ordner `Sources/` per Drag & Drop ins Projekt ziehen („Copy items if needed")
5. In den Target-Einstellungen die mitgelieferte `Sources/Info.plist` als Info.plist setzen
(*Build Settings ▸ Info.plist File*) und *Generate Info.plist File* auf **No** stellen
## Auf dem iPhone installieren
1. iPhone per Kabel verbinden, in Xcode als Ziel auswählen
2. *Signing & Capabilities* → dein Apple-Developer-Team wählen
3. ▶︎ Run. Beim ersten Start auf dem iPhone unter
*Einstellungen ▸ Allgemein ▸ VPN & Geräteverwaltung* dem Entwickler vertrauen
## Erste Schritte in der App
Beim Start nach der Server-Adresse fragen lassen, z. B. `http://192.168.1.50:8080`
(dieselbe Adresse wie im Browser), dann mit deinem Benutzer anmelden. Adresse und
Token bleiben gespeichert – das Token liegt im Keychain.
Hat der Server einen Anmeldedienst eingerichtet (Single Sign-on, siehe
[../README.md](../README.md#single-sign-on-optional)), erscheint darunter ein
Knopf „Mit … anmelden". Die Anmeldung läuft dann im System-Browser (AppAuth mit
PKCE, kein eingebettetes WebView); der Anmeldezustand samt Refresh-Token liegt
je Serverprofil getrennt im Keychain, und die App erneuert ein abgelaufenes
Token still im Hintergrund.
## Home-Screen-Shortcuts
Es gibt zwei Wege direkt in den Scan-Bildschirm:
**Schnellaktionen** – langer Druck auf das App-Symbol zeigt „Einlagern" und
„Auslagern" (funktioniert ohne weitere Einrichtung).
**Eigene Symbole auf dem Home-Bildschirm** – über die Apple-App *Kurzbefehle*:
1. Kurzbefehle ▸ **+** ▸ Aktion *URL öffnen*
2. URL `vorrania://checkin` (bzw. `vorrania://checkout`) eintragen
3. Kurzbefehl benennen, dann ▸ *Zum Home-Bildschirm hinzufügen*
Beide Wege öffnen die App **direkt in der Kamera**.
## NFC-Tags für Kleidung
Ein aufgeklebtes QR-Etikett übersteht keine Wäsche. Für Kleidungsstücke gibt es
deshalb eingenähte NFC-Tags: Einzelstück öffnen ▸ **NFC-Tag beschreiben** ▸ Tag
an die Oberseite des iPhones halten. Auf das Tag kommt derselbe Link, der auch im
QR steckt (`vorrania://i/<UID>`).
Gelesen wird es unter **Nachschlagen** oder **Ort zuordnen** über
*NFC-Tag lesen*. Das Antippen bei gesperrtem Handy startet die App bewusst
nicht: iOS macht das nur über Universal Links auf einer festen Domain, und die
gibt es bei einem selbst gehosteten Dienst nicht.
> Zum Bauen muss für die App-ID im Apple-Developer-Portal die Capability
> *Near Field Communication Tag Reading* aktiv sein, sonst schlägt das Signieren
> fehl. NFC gibt es nur auf dem iPhone – auf dem iPad sind die Knöpfe ausgeblendet.
## Aufbau der Quellen
| Datei | Inhalt |
|---|---|
| `VorraniaApp.swift` | App-Einstieg, Schnellaktionen, URL-Schema |
| `Session.swift` | Server-Adresse (UserDefaults) und Token (Keychain) |
| `APIClient.swift` | REST-Aufrufe gegen `/api/...` |
| `Models.swift` | Codable-Typen passend zu `backend/app/schemas.py` |
| `ScannerView.swift` | Kamera + Barcode-Erkennung (EAN-8/13, UPC-E, Code128, QR) |
| `RootView.swift` | Startbildschirm und Routing |
| `LoginView.swift` | Server + Anmeldung |
| `CheckInView.swift` / `CheckInFormView.swift` | Scan → Charge (MHD), Menge je Lagerort oder Einzelstück |
| `CheckOutView.swift` | Scan → Menge, Chargenauswahl oder FEFO |
| `ProductViews.swift` | Artikelsuche und Anlegen (mit OFF-Vorbefüllung, Foto, Text-Scan) |
| `ProductDetailView.swift` | Produkt bearbeiten, Verwaltungsart ändern, Chargen korrigieren |
| `ObjectStockView.swift` | Gegenstände: Menge je Lagerort (hinzufügen/umlagern/entfernen) |
| `ItemViews.swift` / `ItemListView.swift` | Einzelstücke anlegen, bearbeiten und auflisten |
| `AssignScanView.swift` | Einzelstück (Scan, NFC oder Liste) einem Lagerort-QR zuordnen |
| `NFCTag.swift` / `NFCViews.swift` | NFC-Tags lesen und beschreiben, Einzelstück-Code zerlegen |
| `ListViews.swift` | Produktlisten, Einkaufsliste, „bald ablaufend", Mindestbestände |
| `DashboardView.swift` / `DashboardCards.swift` / `ChartCards.swift` | Übersicht mit Karten und Diagrammen |
| `NotificationScheduler.swift` / `NotificationSettings*.swift` | Push-Benachrichtigungen bei Ablauf |
| `DateScanView.swift` / `BestBeforeText.swift` | MHD/Text per Texterkennung ablesen |
| `DisplaySettings.swift` | Datumsformat und Einheiten-Beschriftungen vom Server |
| `CategoryPicker.swift` | Kategorie-Auswahl und Gruppe anlegen |
## Gruppe und Kategorie – zwei verschiedene Dinge
**Gruppe** dient der *Bestandsrechnung*: Mehl von Rewe, Aldi und Migros zählen
zusammen, wichtig ist „ich habe 5 kg Mehl“. Eine Gruppe hat deshalb einen
gemeinsamen Mindestbestand mit Einheit und EAN-Codes. Ordnest du einen Artikel
einer Gruppe zu, erscheint sein EAN-Code automatisch dort; wechselt er die
Gruppe, wandert der Code mit.
**Kategorie** dient *allein dem Überblick* („Süßwaren“, „Molkereiprodukte“) und
ist verschachtelbar wie ein Lagerort (Süßwaren → Schokolade). Sie hat keinen
Bestand, keinen Mindestbestand und keine EAN-Codes. Filterst du auf eine
Oberkategorie, erscheinen die Artikel ihrer Unterkategorien mit. Beim Anlegen
schlägt der Server eine Kategorie aus der Open-Food-Facts-Einordnung vor.
## Weiteres
Push-Benachrichtigungen bei Ablauf und Lagerort je Charge beim Einlagern sind
umgesetzt. Weitere Ideen stehen in [../docs/ROADMAP.md](../docs/ROADMAP.md).