hostsview: add plus button

add more stuff to Host
prevent host from changin in debug
prettify the list - show uuid if no address set
save changes to Host when closing connectionView
fix connectionView button being disabled sometimes
use a different button to add a host instead of the toolbar one when its empty bc of ! unwrap crash
animations on adding/removing hosts
This commit is contained in:
neon443
2025-06-20 15:33:01 +01:00
parent be37c4efb9
commit 690d7ff95a
4 changed files with 77 additions and 31 deletions

View File

@@ -13,6 +13,9 @@ protocol HostPr: Codable, Identifiable, Equatable {
var port: Int { get set } var port: Int { get set }
var username: String { get set } var username: String { get set }
var password: String { get set } var password: String { get set }
var publicKey: Data? { get set }
var privateKey: Data? { get set }
var passphrase: String { get set }
var key: Data? { get set } var key: Data? { get set }
} }
@@ -22,28 +25,37 @@ struct Host: HostPr {
var port: Int var port: Int
var username: String var username: String
var password: String var password: String
var publicKey: Data?
var privateKey: Data?
var passphrase: String = ""
var key: Data? var key: Data?
init( init(
address: String, address: String,
port: Int = 22, port: Int = 22,
username: String, username: String = "",
password: String, password: String = "",
publicKey: Data? = nil,
privateKey: Data? = nil,
passphrase: String = "",
hostkey: Data? = nil hostkey: Data? = nil
) { ) {
self.address = address self.address = address
self.port = port self.port = port
self.username = username self.username = username
self.password = password self.password = password
self.publicKey = publicKey
self.privateKey = privateKey
self.passphrase = passphrase
self.key = hostkey self.key = hostkey
} }
} }
extension Host { extension Host {
static var blank: Host { static var blank: Host {
Host(address: "", port: 22, username: "", password: "") Host(address: "")
} }
static var debug: Host { static var debug: Host {
Host(address: "localhost", port: 22, username: "default", password: "") Host(address: "localhost", username: "default", password: "")
} }
} }

View File

@@ -19,19 +19,16 @@ class SSHHandler: ObservableObject {
@Published var authorized: Bool = false @Published var authorized: Bool = false
@Published var testSuceeded: Bool = false @Published var testSuceeded: Bool = false
@Published var host: HostPr @Published var host: Host
@Published var terminal: String = "" @Published var terminal: String = ""
private let userDefaults = NSUbiquitousKeyValueStore.default private let userDefaults = NSUbiquitousKeyValueStore.default
private let logger = Logger(subsystem: "xy", category: "sshHandler") private let logger = Logger(subsystem: "xy", category: "sshHandler")
init( init(
host: HostPr host: Host
) { ) {
self.host = host self.host = host
#if DEBUG
self.host = Host.debug
#endif
} }
func getHostkey() -> Data? { func getHostkey() -> Data? {

View File

@@ -79,11 +79,6 @@ struct ConnectionView: View {
.modifier(foregroundColorStyle(handler.authorized ? .green : .red)) .modifier(foregroundColorStyle(handler.authorized ? .green : .red))
} }
// if let testSucceded = testSucceded {
// Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle")
// .modifier(foregroundColorStyle(testSucceded ? .green : .red))
// }
if handler.host.key != nil { if handler.host.key != nil {
Text("Hostkey: \(handler.host.key!.base64EncodedString())") Text("Hostkey: \(handler.host.key!.base64EncodedString())")
} }
@@ -125,7 +120,7 @@ struct ConnectionView: View {
Label("Connect", systemImage: "powerplug.portrait") Label("Connect", systemImage: "powerplug.portrait")
} }
.disabled( .disabled(
pubkey == nil && privkey == nil || pubkey == nil && privkey == nil &&
handler.host.username.isEmpty && handler.host.password.isEmpty handler.host.username.isEmpty && handler.host.password.isEmpty
) )
} }
@@ -147,10 +142,16 @@ struct ConnectionView: View {
Label("Test Connection", systemImage: "checkmark") Label("Test Connection", systemImage: "checkmark")
} }
} }
.disabled(!(handler.connected && handler.authorized)) // .disabled(!(handler.connected && handler.authorized))
} }
.transition(.opacity) .transition(.opacity)
} }
.onDisappear {
if let index = hostsManager.savedHosts.firstIndex(where: { $0.id == handler.host.id }) {
hostsManager.savedHosts[index] = handler.host
hostsManager.saveSavedHosts()
}
}
} }
} }

View File

@@ -14,8 +14,23 @@ struct HostsView: View {
var body: some View { var body: some View {
NavigationStack { NavigationStack {
List { List {
Text("hi") if hostsManager.savedHosts.isEmpty {
Text("Add your first Host!")
Button() {
withAnimation { hostsManager.savedHosts.append(Host.blank) }
} label: {
Text("Create")
// .font()
}
.buttonStyle(.borderedProminent)
}
ForEach(hostsManager.savedHosts) { host in ForEach(hostsManager.savedHosts) { host in
HStack {
if host.address.isEmpty {
Text(host.id.uuidString)
} else {
Text(host.address)
}
NavigationLink() { NavigationLink() {
ConnectionView( ConnectionView(
handler: SSHHandler(host: host), handler: SSHHandler(host: host),
@@ -23,17 +38,37 @@ struct HostsView: View {
hostsManager: hostsManager hostsManager: hostsManager
) )
} label: { } label: {
Text(host.address) Image(systemName: "info.circle")
} }
.onChange(of: host) { _ in .onChange(of: host) { _ in
hostsManager.saveSavedHosts() hostsManager.saveSavedHosts()
} }
} }
.swipeActions(edge: .trailing) {
Button(role: .destructive) {
if let index = hostsManager.savedHosts.firstIndex(where: { $0.id == host.id }) {
let _ = withAnimation { hostsManager.savedHosts.remove(at: index) }
hostsManager.saveSavedHosts()
} }
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
.transition(.scale)
.toolbar { .toolbar {
ToolbarItem(placement: .confirmationAction) { ToolbarItem(placement: .confirmationAction) {
Button { if !hostsManager.savedHosts.isEmpty {
hostsManager.savedHosts.append(Host.blank) NavigationLink {
ConnectionView(
handler: SSHHandler(host: hostsManager.savedHosts.last!),
keyManager: keyManager,
hostsManager: hostsManager
)
.onAppear() {
withAnimation { hostsManager.savedHosts.append(Host.blank) }
}
} label: { } label: {
Label("Add", systemImage: "plus") Label("Add", systemImage: "plus")
} }
@@ -41,6 +76,7 @@ struct HostsView: View {
} }
} }
} }
}
} }
#Preview { #Preview {