Files
RouterOS/RouterOSAssistant/Features/Wizard/Steps/Setup/SetupViewModel.swift
T
KayandClaude Sonnet 5 582eced109 Fix: Picker-Warnungen durch ungültige WAN/LAN-Interface-Vorgaben
wanConfig/lanConfig starteten mit festen Platzhaltern ("ether1"/
"bridge"), die nicht zwangsläufig zu den tatsächlichen Interfaces des
verbundenen Geräts passen -> SwiftUI-Picker meldete ungültige
Selection. prepareDefaults() korrigiert jetzt beide (vorher nur WAN)
anhand eines allgemeinen "ist der Wert überhaupt in der Liste"-Checks
statt nur "ist es noch der Platzhalter", und läuft bereits im init
statt erst bei onAppear, damit der erste Render schon die echten
Werte zeigt.

Aufgefallen beim Live-Test gegen echtes Testgerät (Konsolenwarnung
"the selection ... is invalid and does not have an associated tag").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HReLXMbmPvtQ23p1iWiJNW
2026-09-11 21:57:36 +02:00

93 lines
3.1 KiB
Swift

import Foundation
enum SetupStep: Int, CaseIterable {
case wan
case lan
case review
}
@MainActor
final class SetupViewModel: ObservableObject {
@Published var step: SetupStep = .wan
@Published var wanConfig = WanConfig(interfaceName: "ether1")
@Published var lanConfig = LanDhcpConfig()
@Published private(set) var isApplying = false
@Published private(set) var applyLog: [String] = []
@Published private(set) var applyError: String?
@Published private(set) var didApplySuccessfully = false
private let connectionService: ConnectionService
private let backupService: BackupService
init(connectionService: ConnectionService, backupService: BackupService = BackupService()) {
self.connectionService = connectionService
self.backupService = backupService
prepareDefaults(from: connectionService.interfaces)
}
var plannedCommands: [RouterOSCommand] {
wanConfig.buildCommands() + lanConfig.buildCommands()
}
/// Replaces the placeholder WAN/LAN interface names ("ether1"/"bridge") with real ones
/// from the connected device, whenever the current value isn't actually one of its
/// interfaces — otherwise the Picker selections don't match any of their tags.
func prepareDefaults(from interfaces: [NetworkInterface]) {
guard !interfaces.isEmpty else { return }
let names = Set(interfaces.map(\.name))
if !names.contains(wanConfig.interfaceName) {
if let firstEthernet = interfaces.first(where: { $0.type.lowercased().contains("ether") }) {
wanConfig.interfaceName = firstEthernet.name
} else {
wanConfig.interfaceName = interfaces[0].name
}
}
if !names.contains(lanConfig.interfaceName) {
if let bridge = interfaces.first(where: { $0.type.lowercased().contains("bridge") }) {
lanConfig.interfaceName = bridge.name
} else if let fallback = interfaces.first(where: { $0.name != wanConfig.interfaceName }) {
lanConfig.interfaceName = fallback.name
} else {
lanConfig.interfaceName = interfaces[0].name
}
}
}
func goNext() {
guard let next = SetupStep(rawValue: step.rawValue + 1) else { return }
step = next
}
func goBack() {
guard let previous = SetupStep(rawValue: step.rawValue - 1) else { return }
step = previous
}
func apply(credentials: RouterOSCredentials) {
isApplying = true
applyError = nil
applyLog = []
didApplySuccessfully = false
Task {
do {
applyLog.append("Sichere aktuelle Konfiguration…")
_ = try await backupService.createBackup(for: credentials)
for command in plannedCommands {
applyLog.append(command.summary)
try await connectionService.apply(command)
}
didApplySuccessfully = true
} catch {
applyError = error.localizedDescription
}
isApplying = false
}
}
}