// // EditServerView.swift // iKeyMon // // Created by tracer on 30.03.25. // import SwiftUI struct ServerFormView: View { enum Mode { case add case edit(Server) } var mode: Mode @Binding var servers: [Server] @State private var hostname: String @State private var apiKey: String @State private var connectionOK: Bool = false @Environment(\.dismiss) private var dismiss init( mode: Mode, servers: Binding<[Server]>, dismiss: @escaping () -> Void ) { self.mode = mode self._servers = servers switch mode { case .add: self._hostname = State(initialValue: "") self._apiKey = State(initialValue: "") case .edit(let server): self._hostname = State(initialValue: server.hostname) self._apiKey = State(initialValue: KeychainHelper.loadApiKey(for: server.hostname) ?? "") } } var body: some View { VStack { Text("Edit Server") .font(.headline) TextField("Hostname", text: $hostname) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding(.top) SecureField("API Key", text: $apiKey) .textFieldStyle(RoundedBorderTextFieldStyle()) HStack { Button("Cancel") { dismiss() } Spacer() Button("Test connection") { Task { await testConnection() } } Button("Save") { saveServer() updateServer() saveServers() dismiss() } .disabled(hostname.isEmpty || apiKey.isEmpty || !connectionOK) } .padding(.top) } .padding() .frame(width: 300) .onAppear { print("on appear") if case let .edit(server) = mode { print("serve \(server)") hostname = server.hostname apiKey = KeychainHelper.loadApiKey(for: server.hostname) ?? "" print("💡 Loaded server: \(hostname)") } } } private var modeTitle: String { switch mode { case .add: return "Add Server" case .edit(let server): return "Edit \(server.hostname)" } } private func testConnection() async { let host = hostname.trimmingCharacters(in: .whitespacesAndNewlines) let key = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) let reachable = await PingService.ping(hostname: host, apiKey: key) await MainActor.run { connectionOK = reachable } // // guard let url = URL(string: "https://\(host)/api/v2/ping") else { // print("❌ Invalid URL") // return // } // // var request = URLRequest(url: url) // request.httpMethod = "GET" // request.setValue(key, forHTTPHeaderField: "X-API-KEY") // request.setValue("application/json", forHTTPHeaderField: "Content-Type") // // print("🔍 Headers: \(request.allHTTPHeaderFields ?? [:])") // // Task { // do { // let (data, response) = try await URLSession.shared.data(for: request) // if let httpResponse = response as? HTTPURLResponse { // print("🔄 Status: \(httpResponse.statusCode)") // } // // if let result = try? JSONDecoder().decode([String: String].self, from: data), // result["response"] == "pong" { // print("✅ Pong received") // connectionOK = true // } else { // print("⚠️ Unexpected response") // connectionOK = false // } // } catch { // print("❌ Error: \(error)") // connectionOK = false // } // } } // func testKeyHelpConnection() { // let url = URL(string: "https://keyhelp.lab.24unix.net/api/v2/ping")! // var request = URLRequest(url: url) // request.httpMethod = "GET" // // // @State is no reliable source // let key = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) // request.setValue(key, forHTTPHeaderField: "X-API-KEY") // // request.setValue("application/json", forHTTPHeaderField: "Content-Type") // // print("🔍 Headers: \(request.allHTTPHeaderFields ?? [:])") // // let task = URLSession.shared.dataTask(with: request) { data, response, error in // if let error = error { // print("❌ Error: \(error.localizedDescription)") // return // } // // if let httpResponse = response as? HTTPURLResponse { // print("🔄 Status Code: \(httpResponse.statusCode)") // } // // if let data = data, // let json = try? JSONSerialization.jsonObject(with: data) { // print("✅ Response: \(json)") // } else { // print("⚠️ No JSON response") // } // } // // task.resume() // } private func saveServer() { print("in save server") let trimmedHost = hostname.trimmingCharacters(in: .whitespacesAndNewlines) let trimmedKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines) switch mode { case .add: print("adding server") let newServer = Server(hostname: trimmedHost) servers.append(newServer) KeychainHelper.saveApiKey(trimmedKey, for: trimmedHost) saveServers() case .edit(let oldServer): if let index = servers.firstIndex(where: { $0.id == oldServer.id }) { let oldHostname = servers[index].hostname servers[index].hostname = trimmedHost if oldHostname != trimmedHost { KeychainHelper.deleteApiKey(for: oldHostname) } KeychainHelper.saveApiKey(trimmedKey, for: trimmedHost) } } } private func updateServer() { print ("in edit server") guard case let .edit(server) = mode else { return } if let index = servers.firstIndex(where: { $0.id == server.id }) { // Only replace hostname if changed let oldHostname = servers[index].hostname servers[index].hostname = hostname // Update Keychain if oldHostname != hostname { KeychainHelper.deleteApiKey(for: oldHostname) } KeychainHelper.saveApiKey(apiKey, for: hostname) saveServers() } } private func saveServers() { if let data = try? JSONEncoder().encode(servers) { UserDefaults.standard.set(data, forKey: "storedServers") } } static func delete(server: Server, from servers: inout [Server]) { if let index = servers.firstIndex(where: { $0.id == server.id }) { servers.remove(at: index) if let data = try? JSONEncoder().encode(servers) { UserDefaults.standard.set(data, forKey: "storedServers") } } } } #Preview { ServerFormView( mode: .edit(Server(hostname: "example.com")), servers: .constant([ Server(hostname: "example.com") ]), dismiss: {} ) }