124 lines
5.5 KiB
Swift
124 lines
5.5 KiB
Swift
import SwiftUI
|
|
|
|
struct ProfileEditorView: View {
|
|
@Environment(\.dismiss) var dismiss
|
|
@EnvironmentObject var store: ProfileStore
|
|
@State var profile: ConnectionProfile
|
|
var isNew: Bool
|
|
var onSave: (ConnectionProfile) -> Void
|
|
@State private var password: String = ""
|
|
@State private var savePassword: Bool = false
|
|
@State private var storedPasswordPresent: Bool = false
|
|
|
|
init(profile: ConnectionProfile, isNew: Bool, onSave: @escaping (ConnectionProfile) -> Void) {
|
|
_profile = State(initialValue: profile)
|
|
self.isNew = isNew
|
|
self.onSave = onSave
|
|
}
|
|
|
|
var liveWarnings: [String] { ProfileValidation.warnings(for: profile) }
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
Text(isNew ? "Neues Profil" : "Profil bearbeiten").font(.headline).padding()
|
|
Form {
|
|
Section("Allgemein") {
|
|
TextField("Name", text: $profile.name)
|
|
TextField("Gruppe", text: $profile.group)
|
|
Picker("Protokoll", selection: $profile.proto) {
|
|
ForEach(ProtocolType.allCases) { p in Text(p.rawValue).tag(p) }
|
|
}
|
|
.onChange(of: profile.proto) { _, new in
|
|
if profile.port == 0 { profile.port = new.defaultPort }
|
|
}
|
|
Picker("Farb-Tag", selection: $profile.colorTag) {
|
|
Text("Blau").tag("blue"); Text("Rot").tag("red")
|
|
Text("Grün").tag("green"); Text("Orange").tag("orange")
|
|
Text("Lila").tag("purple")
|
|
}
|
|
}
|
|
Section("Verbindung") {
|
|
TextField("Host", text: $profile.host)
|
|
.autocorrectionDisabled()
|
|
TextField("Port", value: $profile.port, format: .number)
|
|
TextField("Benutzername", text: $profile.username)
|
|
.autocorrectionDisabled()
|
|
// Passwort direkt unter dem Benutzernamen (Keychain-gespeichert)
|
|
if storedPasswordPresent && password.isEmpty {
|
|
HStack {
|
|
Image(systemName: "checkmark.circle.fill").foregroundStyle(.green)
|
|
Text("Passwort gespeichert")
|
|
Spacer()
|
|
Button("Löschen", role: .destructive) { deleteStoredPassword() }
|
|
}
|
|
}
|
|
SecureField(storedPasswordPresent ? "Neues Passwort …" : "Passwort", text: $password)
|
|
Toggle("Passwort in Keychain speichern", isOn: $savePassword)
|
|
TextField("Auflösung (RDP, z. B. 1920x1080 oder Automatisch)", text: $profile.resolution)
|
|
TextField("Extra-Argumente", text: $profile.extraArgs)
|
|
if !liveWarnings.isEmpty {
|
|
ForEach(liveWarnings, id: \.self) { w in
|
|
HStack(spacing: 6) {
|
|
Image(systemName: "exclamationmark.triangle").foregroundStyle(.orange)
|
|
Text(w).font(.caption).foregroundStyle(.orange)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Section("SSH-Key (optional)") {
|
|
Picker("SSH-Key", selection: $profile.sshKeyID) {
|
|
Text("Kein Key (Passwort-Login)").tag(UUID?.none)
|
|
ForEach(store.sshKeys) { k in Text(k.name).tag(UUID?.some(k.id)) }
|
|
}
|
|
Text(sshpassHint).font(.caption).foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
.formStyle(.grouped)
|
|
|
|
HStack {
|
|
Button("Abbrechen", role: .cancel) { dismiss() }
|
|
Spacer()
|
|
Button("Speichern") {
|
|
var toSave = ProfileValidation.cleaned(profile)
|
|
if toSave.port == 0 { toSave.port = toSave.proto.defaultPort }
|
|
if toSave.passwordAccount == nil { toSave.passwordAccount = "profile-\(toSave.id.uuidString)" }
|
|
if savePassword, !password.isEmpty, let acct = toSave.passwordAccount {
|
|
_ = KeychainHelper.save(password, account: acct)
|
|
}
|
|
onSave(toSave)
|
|
dismiss()
|
|
}
|
|
.keyboardShortcut(.defaultAction)
|
|
.disabled(profile.name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
|| profile.host.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
|
}
|
|
.padding()
|
|
}
|
|
.frame(width: 520, height: 680)
|
|
.onAppear {
|
|
if let acct = profile.passwordAccount,
|
|
let stored = KeychainHelper.load(account: acct), !stored.isEmpty {
|
|
storedPasswordPresent = true
|
|
savePassword = true
|
|
}
|
|
}
|
|
}
|
|
|
|
var sshpassHint: String {
|
|
if SSHService.findSshpass() != nil {
|
|
return "sshpass gefunden → Auto-Login mit Keychain-Passwort aktiv, kein Tippen nötig."
|
|
} else {
|
|
return "Ohne sshpass: Passwort wird beim Verbinden im Terminal abgefragt. Für Auto-Login: brew install sshpass."
|
|
}
|
|
}
|
|
|
|
func deleteStoredPassword() {
|
|
if let acct = profile.passwordAccount {
|
|
KeychainHelper.delete(account: acct)
|
|
}
|
|
password = ""
|
|
savePassword = false
|
|
storedPasswordPresent = false
|
|
}
|
|
}
|