App: Listendarstellung der Auswahl zurueckgenommen - sie warf aus dem Formular

Beim Anlegen eines Artikels fuehrte die Kategoriewahl zurueck in die
Artikelliste: Das Formular steht in einem Blatt, und die geschobene Auswahl
riss beim Zurueckspringen den ganzen Navigationsstapel mit - das Blatt also
gleich dazu. Der Artikel liess sich so nicht mehr anlegen.

Damit ist .pickerStyle(.navigationLink) an allen acht Stellen wieder
draussen. Die Auswahl ist wieder ein Menue und rueckt mit fuehrenden
Leerzeichen ein, wie vor d7002e2.

Der Umbruch langer Namen bleibt damit ungeloest: Faellt "Schublade Links
Unten" auf eine zweite Zeile, faengt die wieder ganz links an. Die Grenze
steht jetzt als Kommentar an Baumzeile.label, damit der naechste Versuch
nicht wieder in dieselbe Falle laeuft. Funktionierendes Anlegen wiegt
schwerer als saubere Einrueckung.

Der mittige Loeschdialog aus demselben Commit bleibt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-15 21:37:11 +02:00
co-authored by Claude Opus 5
parent 38489a5217
commit 75899714b3
7 changed files with 16 additions and 42 deletions
+8 -24
View File
@@ -1,4 +1,4 @@
import SwiftUI
import Foundation
/// Eine Zeile einer flach ausgelegten Baumliste, mit ihrer Tiefe.
///
@@ -12,33 +12,17 @@ struct Baumzeile<T: TreeItem>: Identifiable {
var id: T.ID { item.id }
/// Name mit Einrueckung aus fuehrenden Leerzeichen.
/// Name mit Einrueckung je Ebene.
///
/// 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.
/// Eingerueckt wird mit fuehrenden Leerzeichen, weil ein aufklappendes
/// Auswahlmenue ausser Text nichts annimmt - Layout ignoriert es.
/// Bekannte Grenze: Bricht ein langer Name auf eine zweite Zeile um,
/// faengt die wieder ganz links an. Eine Listendarstellung
/// (`.pickerStyle(.navigationLink)`) koennte das, riss aber im Blatt den
/// ganzen Navigationsstapel mit und ist deshalb wieder draussen.
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<T: TreeItem>: View {
let zeile: Baumzeile<T>
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
+1 -4
View File
@@ -14,12 +14,9 @@ struct CategoryPicker: View {
Picker("Kategorie", selection: $selection) {
Text("– keine –").tag(Int?.none)
ForEach(baum(gefiltert)) { eintrag in
BaumZeile(zeile: eintrag).tag(Int?.some(eintrag.item.id))
Text(eintrag.label).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] {
+1 -2
View File
@@ -212,10 +212,9 @@ struct CheckInFormView: View {
Picker("Lagerort", selection: $locationId) {
Text("– keiner –").tag(String?.none)
ForEach(baum(locations)) { eintrag in
BaumZeile(zeile: eintrag).tag(String?.some(eintrag.item.id))
Text(eintrag.label).tag(String?.some(eintrag.item.id))
}
}
.pickerStyle(.navigationLink)
Button {
locScanError = nil
locScanPaused = false
+2 -4
View File
@@ -340,9 +340,8 @@ struct ItemEditView: View {
Section {
Picker("Lagerort", selection: $locationId) {
Text("– ohne –").tag(String?.none)
ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) }
ForEach(baum(locations)) { e in Text(e.label).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: {
@@ -879,9 +878,8 @@ 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 BaumZeile(zeile: e).tag(String?.some(e.item.id)) }
ForEach(baum(locations)) { e in Text(e.label).tag(String?.some(e.item.id)) }
}
.pickerStyle(.navigationLink)
Button { locScanShown = true } label: {
Label("Lagerort scannen", systemImage: "qrcode.viewfinder")
}
+2 -4
View File
@@ -447,10 +447,9 @@ struct LocationEditor: View {
Picker("Übergeordnet", selection: $parentId) {
Text("– oberste Ebene –").tag(String?.none)
ForEach(baum(parentOptions)) { eintrag in
BaumZeile(zeile: eintrag).tag(String?.some(eintrag.item.id))
Text(eintrag.label).tag(String?.some(eintrag.item.id))
}
}
.pickerStyle(.navigationLink)
} header: {
Text("Übergeordneter Lagerort (optional)")
}
@@ -787,10 +786,9 @@ struct CategoryEditor: View {
Picker("Übergeordnet", selection: $parentId) {
Text("– oberste Ebene –").tag(Int?.none)
ForEach(baum(all)) { eintrag in
BaumZeile(zeile: eintrag).tag(Int?.some(eintrag.item.id))
Text(eintrag.label).tag(Int?.some(eintrag.item.id))
}
}
.pickerStyle(.navigationLink)
} header: {
Text("Übergeordnete Kategorie (optional)")
} footer: {
+1 -2
View File
@@ -152,9 +152,8 @@ private struct LocationPicker: View {
var body: some View {
Picker(title, selection: $selection) {
Text("– ohne Lagerort –").tag(String?.none)
ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) }
ForEach(baum(locations)) { e in Text(e.label).tag(String?.some(e.item.id)) }
}
.pickerStyle(.navigationLink)
}
}
+1 -2
View File
@@ -726,9 +726,8 @@ struct LotEditView: View {
Section("Lagerort") {
Picker("Lagerort", selection: $locationId) {
Text("– ohne –").tag(String?.none)
ForEach(baum(locations)) { e in BaumZeile(zeile: e).tag(String?.some(e.item.id)) }
ForEach(baum(locations)) { e in Text(e.label).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")