import SwiftUI import UniformTypeIdentifiers struct BackupListView: View { @ObservedObject var connectionService: ConnectionService @StateObject private var viewModel = BackupViewModel() @State private var showFolderPicker = false @State private var showFactoryResetConfirmation = false var body: some View { NavigationStack { Group { if viewModel.backups.isEmpty { ContentUnavailableView( "Keine Sicherungen", systemImage: "clock.arrow.circlepath", description: Text("Erstelle eine Sicherung, bevor du Änderungen am Router vornimmst.") ) } else { List(viewModel.backups) { backup in VStack(alignment: .leading) { Text(backup.host).bold() Text(backup.createdAt.formatted(date: .abbreviated, time: .standard)) .font(.caption) .foregroundStyle(.secondary) } } } } .safeAreaInset(edge: .bottom) { VStack(alignment: .leading, spacing: 4) { Text("Speicherort") .font(.caption) .foregroundStyle(.secondary) Text(viewModel.backupDirectoryPath) .font(.caption) .lineLimit(1) .truncationMode(.middle) .help(viewModel.backupDirectoryPath) HStack { Button("Ordner wählen…") { showFolderPicker = true } .help("Wähle einen eigenen Ordner für neue Sicherungen, z.B. auf einer externen Festplatte oder in iCloud Drive.") Button("Standard verwenden") { viewModel.resetBackupDirectoryToDefault() } .help("Setzt den Speicherort zurück auf den App-eigenen Standardordner.") } Divider() .padding(.vertical, 4) Text("Gefahrenzone") .font(.caption.bold()) .foregroundStyle(.red) Text("Setzt den Router komplett auf die vom Hersteller mitgelieferte Standardkonfiguration zurück — alle bisherigen Änderungen (Internet, Heimnetz, VLANs, WLAN, Firewall) gehen verloren. Der Router startet danach neu.") .font(.caption) .foregroundStyle(.secondary) Button(role: .destructive) { showFactoryResetConfirmation = true } label: { if viewModel.isResettingToFactoryDefaults { HStack { ProgressView() Text("Setze zurück…") } } else { Label("Werkseinstellungen wiederherstellen", systemImage: "exclamationmark.triangle") } } .disabled(connectionService.credentials == nil || viewModel.isResettingToFactoryDefaults) .help("Stellt die vom Hersteller vorinstallierte Standardkonfiguration des Routers wieder her. Nur für den Notfall, falls etwas schiefgelaufen ist.") if viewModel.didSendFactoryReset { Label( "Befehl gesendet — der Router startet jetzt neu (kann 1-2 Minuten dauern). Verbinde dich danach im Tab \"Verbinden\" erneut.", systemImage: "arrow.clockwise" ) .font(.caption) } } .padding(8) .frame(maxWidth: .infinity, alignment: .leading) .background(.bar) } .fileImporter( isPresented: $showFolderPicker, allowedContentTypes: [.folder] ) { result in if case .success(let url) = result { viewModel.setBackupDirectory(url) } } .confirmationDialog( "Werkseinstellungen wirklich wiederherstellen?", isPresented: $showFactoryResetConfirmation, titleVisibility: .visible ) { Button("Zurücksetzen", role: .destructive) { if let credentials = connectionService.credentials { viewModel.resetToFactoryDefaults(for: credentials) } } Button("Abbrechen", role: .cancel) {} } message: { Text("Dies löscht ALLE bisherigen Einstellungen (Internet, Heimnetz, VLANs, WLAN, Firewall) und setzt den Router auf die Werks-Standardkonfiguration zurück. Der Router startet neu, diese App verliert danach die Verbindung. Vorher wird zusätzlich automatisch eine Sicherung erstellt.") } .onChange(of: viewModel.didSendFactoryReset) { _, didSend in if didSend { Task { await connectionService.disconnect() } } } .navigationTitle("Sicherungen") .toolbar { ToolbarItem { Button { if let credentials = connectionService.credentials { viewModel.createBackup(for: credentials) } } label: { if viewModel.isCreatingBackup { ProgressView() } else { Label("Jetzt sichern", systemImage: "square.and.arrow.down") } } .disabled(connectionService.credentials == nil || viewModel.isCreatingBackup) .help(connectionService.credentials == nil ? "Zuerst im Tab 'Verbinden' mit dem Router verbinden." : "Sicherung jetzt erstellen") } } .alert( "Sicherung fehlgeschlagen", isPresented: Binding( get: { viewModel.errorMessage != nil }, set: { _ in viewModel.errorMessage = nil } ), presenting: viewModel.errorMessage ) { _ in Button("OK") {} } message: { message in Text(message) } .alert( "Zurücksetzen fehlgeschlagen", isPresented: Binding( get: { viewModel.resetError != nil }, set: { _ in viewModel.resetError = nil } ), presenting: viewModel.resetError ) { _ in Button("OK") {} } message: { message in Text(message) } } .onAppear { viewModel.load() } } } #Preview { BackupListView(connectionService: ConnectionService()) }