diff --git a/ios/Sources/Baum.swift b/ios/Sources/Baum.swift index c0335d9..f59a731 100644 --- a/ios/Sources/Baum.swift +++ b/ios/Sources/Baum.swift @@ -1,4 +1,4 @@ -import Foundation +import SwiftUI /// Eine Zeile einer flach ausgelegten Baumliste, mit ihrer Tiefe. /// @@ -12,11 +12,33 @@ struct Baumzeile: Identifiable { var id: T.ID { item.id } - /// Name mit Einrueckung je Ebene. Macht die Hierarchie in einer flachen - /// Auswahl sichtbar, ohne jede Zeile mit dem vollen Pfad zu ueberladen. + /// Name mit Einrueckung aus fuehrenden Leerzeichen. + /// + /// Nur fuer aufklappende Menues, wo man ausser Text nichts abliefern kann. + /// Der Nachteil bleibt dort bestehen: Bricht ein langer Name um, faengt die + /// zweite Zeile ganz links an. Wo es geht, `BaumZeile` nehmen. var label: String { String(repeating: " ", count: tiefe) + item.name } } +/// Auswahlzeile mit echter Einrueckung. +/// +/// Fuehrende Leerzeichen verschieben nur die erste Zeile - ein langer Name +/// bricht um und die Fortsetzung steht wieder ganz links, womit die Hierarchie +/// verloren geht. Ein Innenabstand rueckt dagegen den ganzen Block ein. +/// +/// Verlangt eine Auswahl, die als Liste erscheint (`.pickerStyle(.navigationLink)`): +/// In einem aufklappenden Menue zeigt das System nur den Text und ignoriert +/// jedes Layout. +struct BaumZeile: View { + let zeile: Baumzeile + + var body: some View { + Text(zeile.item.name) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.leading, CGFloat(zeile.tiefe) * 16) + } +} + /// Bringt eine flache Eltern-Kind-Liste in Baumreihenfolge, mit Tiefe. /// /// Waisen - deren Elternteil weggefiltert oder geloescht ist - gelten als diff --git a/ios/Sources/CategoryPicker.swift b/ios/Sources/CategoryPicker.swift index 5472077..71be21e 100644 --- a/ios/Sources/CategoryPicker.swift +++ b/ios/Sources/CategoryPicker.swift @@ -14,9 +14,12 @@ struct CategoryPicker: View { Picker("Kategorie", selection: $selection) { Text("– keine –").tag(Int?.none) ForEach(baum(gefiltert)) { eintrag in - Text(eintrag.label).tag(Int?.some(eintrag.item.id)) + BaumZeile(zeile: eintrag).tag(Int?.some(eintrag.item.id)) } } + // Als Liste statt als Menue: Nur so rueckt ein umbrechender langer + // Name auch in der zweiten Zeile ein. + .pickerStyle(.navigationLink) } private var gefiltert: [CategoryItem] { diff --git a/ios/Sources/CheckInFormView.swift b/ios/Sources/CheckInFormView.swift index e71150c..9f64764 100644 --- a/ios/Sources/CheckInFormView.swift +++ b/ios/Sources/CheckInFormView.swift @@ -212,9 +212,10 @@ struct CheckInFormView: View { Picker("Lagerort", selection: $locationId) { Text("– keiner –").tag(String?.none) ForEach(baum(locations)) { eintrag in - Text(eintrag.label).tag(String?.some(eintrag.item.id)) + BaumZeile(zeile: eintrag).tag(String?.some(eintrag.item.id)) } } + .pickerStyle(.navigationLink) Button { locScanError = nil locScanPaused = false diff --git a/ios/Sources/ItemViews.swift b/ios/Sources/ItemViews.swift index 05f0cd0..ce6721c 100644 --- a/ios/Sources/ItemViews.swift +++ b/ios/Sources/ItemViews.swift @@ -340,8 +340,9 @@ struct ItemEditView: View { Section { Picker("Lagerort", selection: $locationId) { Text("– ohne –").tag(String?.none) - ForEach(baum(locations)) { e in Text(e.label).tag(String?.some(e.item.id)) } + ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) } } + .pickerStyle(.navigationLink) // Lagerort per QR setzen – ohne den (evtl. nicht vorhandenen) QR // des Einzelstücks. Praktisch z.B. bei Kleidung. Button { locScanShown = true } label: { @@ -876,8 +877,9 @@ struct ItemAddSheet: View { Stepper("Anzahl: \(count)", value: $count, in: 1...200) Picker("Lagerort", selection: $locationId) { Text("– ohne –").tag(String?.none) - ForEach(baum(locations)) { e in Text(e.label).tag(String?.some(e.item.id)) } + ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) } } + .pickerStyle(.navigationLink) Button { locScanShown = true } label: { Label("Lagerort scannen", systemImage: "qrcode.viewfinder") } diff --git a/ios/Sources/MasterDataViews.swift b/ios/Sources/MasterDataViews.swift index 0d40890..35c2b33 100644 --- a/ios/Sources/MasterDataViews.swift +++ b/ios/Sources/MasterDataViews.swift @@ -447,9 +447,10 @@ struct LocationEditor: View { Picker("Übergeordnet", selection: $parentId) { Text("– oberste Ebene –").tag(String?.none) ForEach(baum(parentOptions)) { eintrag in - Text(eintrag.label).tag(String?.some(eintrag.item.id)) + BaumZeile(zeile: eintrag).tag(String?.some(eintrag.item.id)) } } + .pickerStyle(.navigationLink) } header: { Text("Übergeordneter Lagerort (optional)") } @@ -786,9 +787,10 @@ struct CategoryEditor: View { Picker("Übergeordnet", selection: $parentId) { Text("– oberste Ebene –").tag(Int?.none) ForEach(baum(all)) { eintrag in - Text(eintrag.label).tag(Int?.some(eintrag.item.id)) + BaumZeile(zeile: eintrag).tag(Int?.some(eintrag.item.id)) } } + .pickerStyle(.navigationLink) } header: { Text("Übergeordnete Kategorie (optional)") } footer: { diff --git a/ios/Sources/ObjectStockView.swift b/ios/Sources/ObjectStockView.swift index 5510eae..0000fa3 100644 --- a/ios/Sources/ObjectStockView.swift +++ b/ios/Sources/ObjectStockView.swift @@ -152,8 +152,9 @@ private struct LocationPicker: View { var body: some View { Picker(title, selection: $selection) { Text("– ohne Lagerort –").tag(String?.none) - ForEach(baum(locations)) { e in Text(e.label).tag(String?.some(e.item.id)) } + ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) } } + .pickerStyle(.navigationLink) } } diff --git a/ios/Sources/ProductDetailView.swift b/ios/Sources/ProductDetailView.swift index aacc8f2..59e7840 100644 --- a/ios/Sources/ProductDetailView.swift +++ b/ios/Sources/ProductDetailView.swift @@ -349,8 +349,9 @@ struct ProductDetailView: View { Text("Änderungen an Name/Marke/Kategorie sind noch nicht gespeichert. " + "Foto und Lagerort-Bedarf werden sofort gespeichert.") } - .confirmationDialog("„\(current.name)“ löschen?", isPresented: $pendingDelete, - titleVisibility: .visible) { + // alert und nicht confirmationDialog: Letzteres faehrt als Blase von + // unten herein. Ein Loeschen will mittig stehen und gelesen werden. + .alert("„\(current.name)“ löschen?", isPresented: $pendingDelete) { Button("Löschen", role: .destructive) { Task { await loeschen() } } Button("Abbrechen", role: .cancel) {} } message: { @@ -725,8 +726,9 @@ struct LotEditView: View { Section("Lagerort") { Picker("Lagerort", selection: $locationId) { Text("– ohne –").tag(String?.none) - ForEach(baum(locations)) { e in Text(e.label).tag(String?.some(e.item.id)) } + ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) } } + .pickerStyle(.navigationLink) // Ort per QR am Regal/Fach setzen, statt in der Liste zu suchen. Button { locScanShown = true } label: { Label("Lagerort scannen", systemImage: "qrcode.viewfinder")