// // ContentView.swift // DNSecure // // Created by Kenta Kubo on 7/1/20. // import NetworkExtension import SwiftUI struct ContentView { @Environment(\.scenePhase) var scenePhase @Binding var servers: Resolvers @Binding var usedID: String? @State var isEnabled = false @State var selection: Int? @State var alertIsPresented = false @State var alertTitle = "" @State var alertMessage = "" @State var guideIsPresented = false func addNewDoTServer() { self.servers.append( .init( name: "New", configuration: .dnsOverTLS(DoTConfiguration()) ) ) self.selection = self.servers.count - 1 } func addNewDoHServer() { self.servers.append( .init( name: "New", configuration: .dnsOverHTTPS(DoHConfiguration()) ) ) self.selection = self.servers.count - 1 } func removeServers(at indexSet: IndexSet) { if let current = self.selection, indexSet.contains(where: { $0 <= current }) { // FIXME: This is a workaround not to crash on deletion. self.selection = -1 } if indexSet.map({ self.servers[$0].id.uuidString }).contains(self.usedID) { self.removeSettings() } // FIXME: This is a workaround not to crash on deletion. // Wait for closing DetailView. DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) { self.servers.remove(atOffsets: indexSet) } } func moveServers(from src: IndexSet, to dst: Int) { // TODO: Change self.selection if needed self.servers.move(fromOffsets: src, toOffset: dst) } func updateStatus() { #if !targetEnvironment(simulator) let manager = NEDNSSettingsManager.shared() manager.loadFromPreferences { if let err = $0 { logger.error("\(err.localizedDescription)") self.alert("Load Error", err.localizedDescription) } else { self.isEnabled = manager.isEnabled } } #endif } func saveSettings(of server: Resolver) { if self.usedID != server.id.uuidString { self.usedID = server.id.uuidString } #if !targetEnvironment(simulator) let manager = NEDNSSettingsManager.shared() manager.dnsSettings = server.configuration.toDNSSettings() manager.onDemandRules = server.onDemandRules.toNEOnDemandRules() manager.saveToPreferences { saveError in if let saveError = saveError as NSError? { guard saveError.domain != "NEConfigurationErrorDomain" || saveError.code != 9 else { // Nothing was changed return } logger.error("\(saveError.localizedDescription)") self.alert("Save Error", saveError.localizedDescription) self.removeSettings() return } logger.debug("DNS settings was saved") } #endif } func removeSettings() { self.usedID = nil #if !targetEnvironment(simulator) let manager = NEDNSSettingsManager.shared() guard manager.dnsSettings != nil else { // Already removed return } manager.removeFromPreferences { removeError in self.updateStatus() if let removeError = removeError { logger.error("\(removeError.localizedDescription)") self.alert("Remove Error", removeError.localizedDescription) return } logger.debug("DNS settings was removed") } #endif } func alert(_ title: String, _ message: String) { self.alertTitle = title self.alertMessage = message self.alertIsPresented = true } } extension ContentView: View { var body: some View { NavigationView { List { NavigationLink( "Instructions", destination: HowToActivateView(isSheet: false), tag: -1, selection: self.$selection ) Section(header: Text("Servers")) { ForEach(0..