Skip to content

Commit 021cc7e

Browse files
committed
feat: add SSH profile editor with create, edit, save-as, and delete
1 parent 61b1ab3 commit 021cc7e

2 files changed

Lines changed: 509 additions & 0 deletions

File tree

TablePro/Views/Connection/ConnectionFormView.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ struct ConnectionFormView: View { // swiftlint:disable:this type_body_length
5858
// SSH Configuration
5959
@State private var sshProfileId: UUID?
6060
@State private var sshProfiles: [SSHProfile] = []
61+
@State private var showingCreateProfile = false
62+
@State private var editingProfile: SSHProfile?
63+
@State private var showingSaveAsProfile = false
6164
@State private var sshEnabled: Bool = false
6265
@State private var sshHost: String = ""
6366
@State private var sshPort: String = "22"
@@ -482,10 +485,73 @@ struct ConnectionFormView: View { // swiftlint:disable:this type_body_length
482485
Text("\(profile.name) (\(profile.username)@\(profile.host))").tag(UUID?.some(profile.id))
483486
}
484487
}
488+
489+
HStack(spacing: 12) {
490+
Button("Create New Profile...") {
491+
showingCreateProfile = true
492+
}
493+
494+
if sshProfileId != nil {
495+
Button("Edit Profile...") {
496+
if let profileId = sshProfileId {
497+
editingProfile = SSHProfileStorage.shared.profile(for: profileId)
498+
}
499+
}
500+
}
501+
502+
if sshProfileId == nil && sshEnabled && !sshHost.isEmpty {
503+
Button("Save Current as Profile...") {
504+
showingSaveAsProfile = true
505+
}
506+
}
507+
}
508+
.controlSize(.small)
485509
}
486510
.onAppear {
487511
sshProfiles = SSHProfileStorage.shared.loadProfiles()
488512
}
513+
.sheet(isPresented: $showingCreateProfile) {
514+
SSHProfileEditorView(existingProfile: nil) { _ in
515+
reloadProfiles()
516+
}
517+
}
518+
.sheet(item: $editingProfile) { profile in
519+
SSHProfileEditorView(existingProfile: profile) { _ in
520+
reloadProfiles()
521+
}
522+
}
523+
.sheet(isPresented: $showingSaveAsProfile) {
524+
SSHProfileEditorView(existingProfile: buildProfileFromInlineConfig()) { savedProfile in
525+
sshProfileId = savedProfile.id
526+
reloadProfiles()
527+
}
528+
}
529+
}
530+
531+
private func reloadProfiles() {
532+
sshProfiles = SSHProfileStorage.shared.loadProfiles()
533+
// If the edited/deleted profile no longer exists, clear the selection
534+
if let id = sshProfileId, !sshProfiles.contains(where: { $0.id == id }) {
535+
sshProfileId = nil
536+
}
537+
}
538+
539+
private func buildProfileFromInlineConfig() -> SSHProfile {
540+
SSHProfile(
541+
name: "",
542+
host: sshHost,
543+
port: Int(sshPort) ?? 22,
544+
username: sshUsername,
545+
authMethod: sshAuthMethod,
546+
privateKeyPath: sshPrivateKeyPath,
547+
useSSHConfig: !selectedSSHConfigHost.isEmpty,
548+
agentSocketPath: resolvedSSHAgentSocketPath,
549+
jumpHosts: jumpHosts,
550+
totpMode: totpMode,
551+
totpAlgorithm: totpAlgorithm,
552+
totpDigits: totpDigits,
553+
totpPeriod: totpPeriod
554+
)
489555
}
490556

491557
private func sshProfileSummarySection(_ profile: SSHProfile) -> some View {

0 commit comments

Comments
 (0)