feat: add optional server groups

This commit is contained in:
2026-04-21 00:15:08 +02:00
parent 08db74f397
commit 44cc620d3d
6 changed files with 519 additions and 84 deletions

View File

@@ -16,9 +16,11 @@ struct ServerFormView: View {
var mode: Mode
@Binding var servers: [Server]
@Binding var groups: [ServerGroup]
@State private var hostname: String
@State private var apiKey: String
@State private var selectedGroupID: UUID?
@State private var connectionOK: Bool = false
@State private var testingConnection: Bool = false
@State private var connectionError: String = ""
@@ -29,25 +31,30 @@ struct ServerFormView: View {
init(
mode: Mode,
servers: Binding<[Server]>,
groups: Binding<[ServerGroup]>,
dismiss: @escaping () -> Void
) {
self.mode = mode
self._servers = servers
self._groups = groups
switch mode {
case .add:
self._hostname = State(initialValue: "")
self._apiKey = State(initialValue: "")
self._selectedGroupID = State(initialValue: nil)
case .edit(let server):
self._hostname = State(initialValue: server.hostname)
self._apiKey = State(initialValue: KeychainHelper.loadApiKey(for: server.hostname) ?? "")
self._selectedGroupID = State(initialValue: server.groupID)
self._connectionOK = State(initialValue: true)
}
}
var body: some View {
VStack {
Text("Edit Server")
Text(modeTitle)
.font(.headline)
TextField("Hostname", text: $hostname)
@@ -57,6 +64,14 @@ struct ServerFormView: View {
SecureField("API Key", text: $apiKey)
.textFieldStyle(RoundedBorderTextFieldStyle())
Picker("Group", selection: $selectedGroupID) {
Text("No Group").tag(nil as UUID?)
ForEach(groups) { group in
Text(group.name).tag(Optional(group.id))
}
}
.pickerStyle(.menu)
if !connectionError.isEmpty {
Text(connectionError)
.foregroundColor(.red)
@@ -77,8 +92,6 @@ struct ServerFormView: View {
Button("Save") {
saveServer()
updateServer()
saveServers()
dismiss()
}
.disabled(hostname.isEmpty || apiKey.isEmpty || !connectionOK)
@@ -93,6 +106,8 @@ struct ServerFormView: View {
print("serve \(server)")
hostname = server.hostname
apiKey = KeychainHelper.loadApiKey(for: server.hostname) ?? ""
selectedGroupID = server.groupID
connectionOK = true
print("💡 Loaded server: \(hostname)")
}
}
@@ -205,40 +220,22 @@ struct ServerFormView: View {
switch mode {
case .add:
print("adding server")
let newServer = Server(hostname: trimmedHost)
let newServer = Server(hostname: trimmedHost, groupID: selectedGroupID)
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
servers[index].groupID = selectedGroupID
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()
}
saveServers()
}
private func saveServers() {
@@ -265,6 +262,9 @@ struct ServerFormView: View {
servers: .constant([
Server(hostname: "example.com")
]),
groups: .constant([
ServerGroup(name: "Production")
]),
dismiss: {}
)
}