Files
RouterOS/RouterOSAssistant/Features/Wizard/Steps/Setup/SetupView.swift
T
KayandClaude Sonnet 5 f34fc0587a 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>
2026-09-16 09:34:03 +02:00

82 lines
3.5 KiB
Swift

import SwiftUI
struct SetupView: View {
@ObservedObject var connectionService: ConnectionService
@StateObject private var viewModel: SetupViewModel
@AppStorage("appLanguage") private var appLanguage: String = "de"
@State private var showCancelConfirmation = false
init(connectionService: ConnectionService) {
self.connectionService = connectionService
_viewModel = StateObject(wrappedValue: SetupViewModel(connectionService: connectionService))
}
var body: some View {
NavigationStack {
Group {
if connectionService.credentials == nil {
ContentUnavailableView(
LocalizedStringKey(L10n.t("Nicht verbunden", appLanguage)),
systemImage: "network.slash",
description: Text(L10n.t("Verbinde dich zuerst im Tab \"Verbinden\" mit deinem Router.", appLanguage))
)
} else {
switch viewModel.step {
case .mode:
ModeStepView(viewModel: viewModel)
case .wan:
WanStepView(viewModel: viewModel, availableInterfaces: configurableInterfaces)
case .lan:
LanStepView(viewModel: viewModel, availableInterfaces: configurableInterfaces)
case .vlan:
VlanStepView(viewModel: viewModel, availableInterfaces: configurableInterfaces)
case .wifi:
WifiStepView(viewModel: viewModel)
case .firewall:
FirewallStepView(viewModel: viewModel)
case .review:
ReviewApplyView(viewModel: viewModel, credentials: connectionService.credentials)
}
}
}
.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 {
viewModel.prepareDefaults(from: configurableInterfaces)
}
}
/// Loopback is never something a person should pick as WAN/LAN/VLAN base interface —
/// excluded here (not just via defaults) so a parsing hiccup elsewhere can't offer it as
/// a selectable option, which on a real hEX device caused every WAN/firewall command to
/// silently reference "lo" instead of the real WAN port. Found via live testing.
private var configurableInterfaces: [NetworkInterface] {
connectionService.interfaces.filter { $0.type.lowercased() != "loopback" }
}
}
#Preview {
SetupView(connectionService: ConnectionService())
}