Bug 39: "Weitere Parameter"-Liste im Experte-Sheet zweispaltig + lesbarer

Bei Menüs mit vielen ungekuratierten RouterOS-Feldern (z.B. "Alle
Interfaces (generisch)", Ethernet-Ports mit 30+ Extra-Parametern) war
das Edit-Sheet eine lange Einspalten-Liste mit viel Scrollen. Jetzt
echte Grid-Spalten für Parameter/Wert (statt TextField(titleKey:) mit
fest eingeblendetem Zeilenlabel, das auf macOS Platz frisst), einmalige
Kopfzeile, Sheet-Breite 420→900, horizontale Trennlinie pro Zeile,
Abstand zum "Parameter hinzufügen"-Button. Betrifft jedes Menü mit
ungekuratierten Feldern, nicht nur Interfaces. Live gegen echten
Router bestätigt (mehrere Nachbesserungsrunden anhand Screenshots).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kay
2026-09-16 20:06:45 +02:00
co-authored by Claude Sonnet 5
parent 0875d7c3a4
commit 684e1c184a
2 changed files with 78 additions and 10 deletions
@@ -131,17 +131,47 @@ struct ExpertItemEditView: View {
Text(L10n.t("Für alles, was oben nicht als eigenes Feld aufgeführt ist — RouterOS-Parametername genau wie in der Dokumentation.", appLanguage))
.font(.caption)
.foregroundStyle(.secondary)
ForEach($viewModel.extraFields) { $extra in
HStack {
TextField(L10n.t("Parameter", appLanguage), text: $extra.key)
TextField(L10n.t("Wert", appLanguage), text: $extra.value)
Button(role: .destructive) {
viewModel.extraFields.removeAll { $0.id == extra.id }
} label: {
Image(systemName: "minus.circle")
// Zwei Spalten statt einer Zeile pro Parameter bei Menüs mit vielen ungekuratierten
// RouterOS-Feldern (z.B. "Alle Interfaces (generisch)", wo Ethernet-Ports gut 30+
// Extra-Parameter mitbringen) halbiert das die Scroll-Länge dieses Formulars.
// Eigene Grid-Spalten für Parameter/Wert (statt eines TextFields pro Zeilenhälfte):
// `TextField(titleKey:text:)` zeigt den Titel auf macOS als feste Beschriftung vor
// dem Wert an (kein iOS-Platzhalter, der beim Tippen verschwindet) bei 30+ Zeilen
// fraß "Parameter"/"Wert" so bei jeder Zeile erneut Breite, während an den äußeren
// Rändern Platz ungenutzt blieb (live per Screenshot bestätigt). Jetzt eine einmalige
// Kopfzeile statt Pro-Zeile-Label, leere TextField-Titel, Wert-Spalten mit
// `maxWidth: .infinity` gemäß Inhalt.
Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 14) {
GridRow {
extraColumnHeader("Parameter")
extraColumnHeader("Wert")
Color.clear.gridCellUnsizedAxes(.horizontal)
extraColumnHeader("Parameter")
extraColumnHeader("Wert")
}
ForEach(Array(stride(from: 0, to: viewModel.extraFields.count, by: 2)), id: \.self) { start in
GridRow {
extraKeyField(at: start)
extraValueField(at: start)
if start + 1 < viewModel.extraFields.count {
Rectangle()
.fill(Color.secondary.opacity(0.25))
.frame(width: 1)
.frame(maxHeight: .infinity)
extraKeyField(at: start + 1)
extraValueField(at: start + 1)
} else {
Color.clear
Color.clear
Color.clear
}
}
Divider()
.gridCellColumns(5)
}
}
.frame(maxWidth: .infinity)
.padding(.bottom, 12)
Button(L10n.t("Parameter hinzufügen", appLanguage)) {
viewModel.extraFields.append(.init())
}
@@ -174,7 +204,7 @@ struct ExpertItemEditView: View {
}
}
.formStyle(.grouped)
.frame(minWidth: 420, minHeight: 480)
.frame(minWidth: 900, idealWidth: 900, minHeight: 480, idealHeight: 620)
.confirmationDialog(
L10n.t("Jetzt am Router anwenden?", appLanguage),
isPresented: $showApplyConfirmation,
@@ -194,6 +224,34 @@ struct ExpertItemEditView: View {
}
}
private func extraColumnHeader(_ key: String) -> some View {
Text(L10n.t(key, appLanguage))
.font(.caption)
.foregroundStyle(.secondary)
}
private func extraKeyField(at index: Int) -> some View {
TextField("", text: $viewModel.extraFields[index].key)
.textFieldStyle(.plain)
}
@ViewBuilder
private func extraValueField(at index: Int) -> some View {
HStack {
TextField("", text: $viewModel.extraFields[index].value)
.textFieldStyle(.plain)
.frame(maxWidth: .infinity)
Button(role: .destructive) {
let id = viewModel.extraFields[index].id
viewModel.extraFields.removeAll { $0.id == id }
} label: {
Image(systemName: "minus.circle")
}
.buttonStyle(.plain)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
@ViewBuilder
private func fieldEditor(for field: RouterOSFieldSchema) -> some View {
let binding = Binding<String>(
+11 -1
View File
@@ -16,6 +16,16 @@ Ursache 1 (behoben): Experte-Schema PATCHte `servers` als kommagetrenntes Textfe
Ursache 2 (behoben): Live-Test meldete beim Anlegen eines Server-Eintrags `HTTP 400: unknown parameter enabled` — Listen-Einträge in RouterOS nutzen durchgängig `disabled` (nicht `enabled`) zum Ein-/Ausschalten, wie der Rest des Schemas es auch macht. Feld in `RouterOSSchemaCatalog.swift` von `enabled`/"yes" auf `disabled`/"no" korrigiert. Build grün, noch nicht erneut live getestet.
### 2. Interfaces-Ansicht zu unübersichtlich
**Status:** offen
**Status:** fixed (live bestätigt)
Interfaces-Einträge sehr umfangreich beim Öffnen. Zweispaltige Ansicht gewünscht, um Scrollen zu reduzieren.
Ursache: Der eigentliche Umfang kommt nicht von den kuratierten Feldern (bei "Alle Interfaces (generisch)" nur 3: Name/Kommentar/Deaktiviert), sondern vom "Weitere Parameter (frei)"-Block — jedes von RouterOS zurückgelieferte Feld, das nicht kuratiert ist, landet dort als eigene Zeile. Bei einem Ethernet-Port sind das leicht 30+ Zeilen. Fix: `ExpertMenuDetailView.swift` — dieser Block ist jetzt ein zweispaltiges `Grid` statt einer Liste (halbiert die Zeilenzahl), Sheet-Breite von 420 auf 640 erhöht. Betrifft alle Menüs mit vielen ungekuratierten Feldern, nicht nur Interfaces.
Nachbesserung 1 (User-Feedback: Zeilen zu eng, Spalten-Trennlinie gewünscht): verticalSpacing 8→16, horizontalSpacing 12→20, dünne vertikale Trennlinie zwischen den Spalten ergänzt.
Nachbesserung 2 (User-Feedback: Zeilen jetzt abgeschnitten, Fenster breiter machen und voll ausnutzen): Sheet-Breite minWidth 640→900 + idealWidth 900.
Nachbesserung 3 (User-Screenshot: an den äußeren Rändern noch viel ungenutzter Platz). Ursache gefunden: `TextField(titleKey:text:)` zeigt auf macOS den Titel als feste Beschriftung vor dem Wert an (kein iOS-Platzhalter, der beim Tippen verschwindet) — bei 30+ Zeilen fraß "Parameter"/"Wert" so bei jeder einzelnen Zeile erneut Breite. Fix: echte Grid-Spalten für Parameter/Wert mit einmaliger Kopfzeile statt Pro-Zeile-Label, leere TextField-Titel (`.textFieldStyle(.plain)`), Wert-Spalte mit `maxWidth: .infinity`.
Nachbesserung 4 (User-Feedback: letzte Zeile überschneidet sich mit dem Button "Parameter hinzufügen", zwischen Zeilen soll eine Trennlinie sein): horizontale `Divider()` nach jeder Zeile ergänzt (spannt alle 5 Grid-Spalten), 12pt Abstand unter dem Grid vor dem Button. Build grün, noch nicht visuell/live geprüft (kein Router hier erreichbar).