249 lines
7.6 KiB
Swift
249 lines
7.6 KiB
Swift
//
|
||
// 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: {}
|
||
)
|
||
}
|