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>
This commit is contained in:
Scarriffle
2026-09-12 13:37:24 +02:00
co-authored by Claude Opus 5
parent 9be772557e
commit 09a763a823
11 changed files with 508 additions and 56 deletions
+11 -23
View File
@@ -1,31 +1,8 @@
import SwiftUI
import CoreImage
import PhotosUI
import QuickLook
import UniformTypeIdentifiers
/// QR-Code als Bild (CoreImage). Inhalt ist der Link auf das Einzelstück, damit
/// ein Scan – auch mit der Systemkamera – die App/Weboberfläche öffnet.
enum QRImage {
static func make(_ text: String, scale: CGFloat = 8) -> UIImage? {
guard let data = text.data(using: .utf8),
let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
filter.setValue(data, forKey: "inputMessage")
filter.setValue("M", forKey: "inputCorrectionLevel")
guard let ci = filter.outputImage?
.transformed(by: CGAffineTransform(scaleX: scale, y: scale)) else { return nil }
let context = CIContext()
guard let cg = context.createCGImage(ci, from: ci.extent) else { return nil }
return UIImage(cgImage: cg)
}
}
func qrLink(forUid uid: String) -> String {
let base = Session.shared.baseURL?.absoluteString
.trimmingCharacters(in: CharacterSet(charactersIn: "/")) ?? ""
return base.isEmpty ? uid : "\(base)/i/\(uid)"
}
private func dateToString(_ d: Date) -> String {
let f = DateFormatter(); f.dateFormat = "yyyy-MM-dd"; return f.string(from: d)
}
@@ -217,6 +194,7 @@ struct ItemEditView: View {
@State private var pickerItem: PhotosPickerItem?
@State private var previewURL: URL?
@State private var locScanShown = false
@State private var nfcShown = false
var body: some View {
Form {
@@ -234,6 +212,13 @@ struct ItemEditView: View {
LabeledContent("Marke", value: brand)
}
LabeledContent("UID", value: item.uid)
// Für Kleidung: ein eingenähtes NFC-Tag hält, was ein aufgeklebter
// QR nicht übersteht. Auf dem iPad ausgeblendet – dort gibt es kein NFC.
if NFCTag.verfuegbar {
Button { nfcShown = true } label: {
Label("NFC-Tag beschreiben", systemImage: "wave.3.right")
}
}
}
Section {
@@ -337,6 +322,9 @@ struct ItemEditView: View {
LocationScannerView(locations: locations) { loc in locationId = loc.id }
.ignoresSafeArea()
}
.sheet(isPresented: $nfcShown) {
NavigationStack { NFCSchreibenView(item: item) }
}
.sheet(isPresented: $showRemove) {
NavigationStack { removeSheet }
}