Editor: Passwort unter Benutzername, Live-Validierung, Fehlerbericht kopieren, Doku

This commit is contained in:
x3
2026-09-21 23:29:39 +02:00
parent 4fd711474c
commit ebb838b6b1
5 changed files with 98 additions and 16 deletions
@@ -16,6 +16,8 @@ struct ProfileEditorView: View {
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()
@@ -37,26 +39,37 @@ struct ProfileEditorView: View {
}
Section("Verbindung") {
TextField("Host", text: $profile.host)
.autocorrectionDisabled()
TextField("Port", value: $profile.port, format: .number)
TextField("Benutzername", text: $profile.username)
TextField("Auflösung (RDP, z. B. 1920x1080 oder Automatisch)", text: $profile.resolution)
TextField("Extra-Argumente", text: $profile.extraArgs)
}
Section("Authentifizierung") {
Picker("SSH-Key", selection: $profile.sshKeyID) {
Text("Kein Key").tag(UUID?.none)
ForEach(store.sshKeys) { k in Text(k.name).tag(UUID?.some(k.id)) }
}
.autocorrectionDisabled()
// Passwort direkt unter dem Benutzernamen (Keychain-gespeichert)
if storedPasswordPresent && password.isEmpty {
HStack {
Image(systemName: "checkmark.circle.fill").foregroundStyle(.green)
Text("Passwort in Keychain gespeichert")
Text("Passwort gespeichert")
Spacer()
Button("Löschen", role: .destructive) { deleteStoredPassword() }
}
}
SecureField(storedPasswordPresent ? "Neues Passwort …" : "Passwort (optional, Keychain)", text: $password)
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)
}
}
@@ -66,7 +79,7 @@ struct ProfileEditorView: View {
Button("Abbrechen", role: .cancel) { dismiss() }
Spacer()
Button("Speichern") {
var toSave = profile
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 {
@@ -76,11 +89,12 @@ struct ProfileEditorView: View {
dismiss()
}
.keyboardShortcut(.defaultAction)
.disabled(profile.host.isEmpty || profile.name.isEmpty)
.disabled(profile.name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|| profile.host.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
}
.padding()
}
.frame(width: 520, height: 640)
.frame(width: 520, height: 680)
.onAppear {
if let acct = profile.passwordAccount,
let stored = KeychainHelper.load(account: acct), !stored.isEmpty {