Einrichten-Tab: "Abbrechen"-Button ergänzt
Vorher kein Weg aus dem Wizard außer schrittweise "Zurück" bis zu Modus. Zentral als Toolbar-Button in SetupView (nicht pro Schritt dupliziert), mit Bestätigungsdialog gegen Datenverlust, deaktiviert während eines laufenden Apply. SetupViewModel.finish() in gemeinsame resetToInitialState() plus benannte finish()/cancel()-Wrapper aufgeteilt. Live bestätigt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+15
@@ -1308,6 +1308,21 @@ später dazukommen könnte, da MikroTik-Router in ärmeren Ländern
|
|||||||
(Brasilien, spanischsprachige Länder) stark verbreitet sind — siehe
|
(Brasilien, spanischsprachige Länder) stark verbreitet sind — siehe
|
||||||
Claude-Memory `future-language-support.md` für Details.
|
Claude-Memory `future-language-support.md` für Details.
|
||||||
|
|
||||||
|
**"Abbrechen"-Button im Einrichten-Tab ergänzt** (2026-09-16, Nutzerwunsch:
|
||||||
|
"mir fehlt im einrichte-tab (einfach und experte) noch ein
|
||||||
|
\"Abbrechen\"-Button") — vorher gab es keinen Weg aus dem Wizard außer
|
||||||
|
sich Schritt für Schritt per "Zurück" bis zu Modus vorzuklicken. Zentral
|
||||||
|
in `SetupView.swift` als Toolbar-Button gelöst (nicht in jedem der sieben
|
||||||
|
Schritt-Views einzeln dupliziert), sichtbar auf jedem Schritt in beiden
|
||||||
|
Modi, mit `.confirmationDialog` ("Einrichten abbrechen?" /
|
||||||
|
"Weiter ausfüllen") gegen versehentlichen Datenverlust bereits
|
||||||
|
eingegebener Werte, deaktiviert während `isApplying` (ein laufendes
|
||||||
|
Apply soll nicht mitten im Ablauf abreißen). `SetupViewModel.finish()`
|
||||||
|
in eine private `resetToInitialState()` plus zwei benannte Wrapper
|
||||||
|
(`finish()`/neues `cancel()`) aufgeteilt — gleicher Reset, aber je nach
|
||||||
|
Aufrufkontext (erfolgreicher Apply vs. Nutzer bricht ab) unter dem
|
||||||
|
passenden Namen lesbar. Live bestätigt ("sieht gut aus").
|
||||||
|
|
||||||
## Nächste Schritte
|
## Nächste Schritte
|
||||||
|
|
||||||
1. ~~M16: restliche `RouterOSSchemaCatalog.swift`-Sektionen übersetzen~~,
|
1. ~~M16: restliche `RouterOSSchemaCatalog.swift`-Sektionen übersetzen~~,
|
||||||
|
|||||||
@@ -764,6 +764,9 @@ enum L10n {
|
|||||||
"Details anzeigen (RouterOS-Befehle)": "Show Details (RouterOS Commands)",
|
"Details anzeigen (RouterOS-Befehle)": "Show Details (RouterOS Commands)",
|
||||||
"Vor dem Anwenden wird automatisch eine Sicherung der aktuellen Konfiguration erstellt (Tab \"Sicherungen\"). Ein garantiertes automatisches Zurückrollen bei Verbindungsabbruch gibt es nicht — bei Problemen die Sicherung im Tab \"Sicherungen\" verwenden oder den Router lokal (Ethernet/Konsole) wiederherstellen.":
|
"Vor dem Anwenden wird automatisch eine Sicherung der aktuellen Konfiguration erstellt (Tab \"Sicherungen\"). Ein garantiertes automatisches Zurückrollen bei Verbindungsabbruch gibt es nicht — bei Problemen die Sicherung im Tab \"Sicherungen\" verwenden oder den Router lokal (Ethernet/Konsole) wiederherstellen.":
|
||||||
"Before applying, a backup of the current configuration is automatically created (\"Backups\" tab). There's no guaranteed automatic rollback if the connection drops — if there are problems, use the backup in the \"Backups\" tab, or restore the router locally (Ethernet/console).",
|
"Before applying, a backup of the current configuration is automatically created (\"Backups\" tab). There's no guaranteed automatic rollback if the connection drops — if there are problems, use the backup in the \"Backups\" tab, or restore the router locally (Ethernet/console).",
|
||||||
|
"Einrichten abbrechen?": "Cancel Setup?",
|
||||||
|
"Weiter ausfüllen": "Keep Going",
|
||||||
|
"Alle in diesem Assistenten eingegebenen Werte gehen verloren.": "All values entered in this wizard will be lost.",
|
||||||
"Ablauf": "Progress",
|
"Ablauf": "Progress",
|
||||||
"Änderungen erfolgreich angewendet": "Changes Applied Successfully",
|
"Änderungen erfolgreich angewendet": "Changes Applied Successfully",
|
||||||
"Jetzt anwenden": "Apply Now",
|
"Jetzt anwenden": "Apply Now",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ struct SetupView: View {
|
|||||||
@ObservedObject var connectionService: ConnectionService
|
@ObservedObject var connectionService: ConnectionService
|
||||||
@StateObject private var viewModel: SetupViewModel
|
@StateObject private var viewModel: SetupViewModel
|
||||||
@AppStorage("appLanguage") private var appLanguage: String = "de"
|
@AppStorage("appLanguage") private var appLanguage: String = "de"
|
||||||
|
@State private var showCancelConfirmation = false
|
||||||
|
|
||||||
init(connectionService: ConnectionService) {
|
init(connectionService: ConnectionService) {
|
||||||
self.connectionService = connectionService
|
self.connectionService = connectionService
|
||||||
@@ -38,6 +39,28 @@ struct SetupView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.toolbar {
|
||||||
|
if connectionService.credentials != nil {
|
||||||
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
|
Button(L10n.t("Abbrechen", appLanguage)) {
|
||||||
|
showCancelConfirmation = true
|
||||||
|
}
|
||||||
|
.disabled(viewModel.isApplying)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.confirmationDialog(
|
||||||
|
L10n.t("Einrichten abbrechen?", appLanguage),
|
||||||
|
isPresented: $showCancelConfirmation,
|
||||||
|
titleVisibility: .visible
|
||||||
|
) {
|
||||||
|
Button(L10n.t("Abbrechen", appLanguage), role: .destructive) {
|
||||||
|
viewModel.cancel()
|
||||||
|
}
|
||||||
|
Button(L10n.t("Weiter ausfüllen", appLanguage), role: .cancel) {}
|
||||||
|
} message: {
|
||||||
|
Text(L10n.t("Alle in diesem Assistenten eingegebenen Werte gehen verloren.", appLanguage))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
viewModel.prepareDefaults(from: configurableInterfaces)
|
viewModel.prepareDefaults(from: configurableInterfaces)
|
||||||
|
|||||||
@@ -254,6 +254,19 @@ final class SetupViewModel: ObservableObject {
|
|||||||
/// LAN afterwards) starts from the router's actual current state rather than this session's
|
/// LAN afterwards) starts from the router's actual current state rather than this session's
|
||||||
/// now-outdated in-memory one.
|
/// now-outdated in-memory one.
|
||||||
func finish() {
|
func finish() {
|
||||||
|
resetToInitialState()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// User-initiated abort from any step (per explicit request: no "Abbrechen" button existed
|
||||||
|
/// anywhere in the wizard before this — the only way out was clicking through every remaining
|
||||||
|
/// step to "Zurück" back to Mode, or force-quitting the app). Same reset as `finish()` — the
|
||||||
|
/// distinction is purely which caller/label makes sense in context (a successful apply vs. a
|
||||||
|
/// user backing out mid-way) — kept as separate names so each call site reads correctly.
|
||||||
|
func cancel() {
|
||||||
|
resetToInitialState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func resetToInitialState() {
|
||||||
step = .mode
|
step = .mode
|
||||||
mode = .simple
|
mode = .simple
|
||||||
wanConfig = WanConfig(interfaceName: "ether1")
|
wanConfig = WanConfig(interfaceName: "ether1")
|
||||||
|
|||||||
Reference in New Issue
Block a user