Files
Vorrania/ios
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
..

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)

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