Files
SystemsMonitor/PegasusMonitor/SettingsView.swift
T
2026-10-21 14:39:25 +01:00

102 lines
4.4 KiB
Swift

import SwiftUI
struct SettingsView: View {
@ObservedObject var monitor: ServerMonitor
@State private var draft = ServerProfile()
@State private var editingID: UUID?
@State private var validation = ""
@State private var interval = 5
@State private var notifications = true
var body: some View {
HStack(spacing: 0) {
VStack(spacing: 8) {
Text("Servers").font(.headline).frame(maxWidth: .infinity, alignment: .leading)
List(selection: $editingID) {
ForEach(monitor.servers) { server in
HStack {
Image(systemName: "server.rack")
Text(server.name)
if !server.enabled { Image(systemName: "pause.circle") }
}.tag(server.id)
}
.onMove { monitor.move(from: $0, to: $1) }
}
HStack {
Button { newProfile() } label: { Image(systemName: "plus") }
Button { if let id = editingID { monitor.remove(id); editingID = monitor.servers.first?.id } } label: { Image(systemName: "minus") }
.disabled(editingID == nil)
Spacer()
}
.buttonStyle(.borderless)
}
.frame(width: 205)
.padding()
Divider()
VStack(alignment: .leading, spacing: 14) {
Text(editingID == nil ? "Add a server" : "Connection details")
.font(.title3.bold())
Form {
TextField("Display name", text: $draft.name)
TextField("Host / SSH alias", text: $draft.host)
TextField("SSH username", text: $draft.user)
TextField("SSH port", text: $draft.port)
TextField("SSH key path (optional)", text: $draft.keyFile)
TextField("Remote health command", text: $draft.remoteCommand)
Toggle("Monitoring enabled", isOn: $draft.enabled)
}
Text("Use the Pegasus adapter for Pegasus, or install server/remote-health-json on other Linux servers. SSH must work without interactive prompts. SSH known_hosts is enforced.")
.font(.caption).foregroundStyle(.secondary)
if !validation.isEmpty { Text(validation).foregroundStyle(.red).font(.caption) }
HStack {
Button("New Server") { newProfile() }
Spacer()
Button("Save and Refresh") { save() }
.buttonStyle(.borderedProminent)
}
Divider()
HStack {
Picker("Refresh every", selection: $interval) {
ForEach([1, 5, 10, 15, 30], id: \.self) { value in
Text("\(value) min").tag(value)
}
}
Toggle("Notifications", isOn: $notifications)
}
}
.padding(20)
}
.onAppear {
interval = monitor.intervalMinutes
notifications = monitor.notifications
editingID = monitor.selectedID
if let selected = monitor.selected { draft = selected }
}
.onChange(of: editingID) { _, newValue in
if let id = newValue, let server = monitor.servers.first(where: { $0.id == id }) { draft = server }
validation = ""
}
.onChange(of: interval) { _, value in monitor.intervalMinutes = value }
.onChange(of: notifications) { _, value in monitor.notifications = value }
}
private func newProfile() {
editingID = nil
draft = ServerProfile()
validation = ""
}
private func save() {
guard !draft.name.trimmingCharacters(in: .whitespaces).isEmpty,
!draft.host.trimmingCharacters(in: .whitespaces).isEmpty,
!draft.user.trimmingCharacters(in: .whitespaces).isEmpty,
let port = Int(draft.port), (1...65535).contains(port),
!draft.remoteCommand.trimmingCharacters(in: .whitespaces).isEmpty else {
validation = "Enter a name, host, SSH username, valid port and remote command."
return
}
monitor.save(draft)
editingID = draft.id
validation = ""
}
}