Files
ShhShell/ShhShell/Views/ConnectionView.swift
neon443 db36c56f29 improved disconnection - will dismiss terminal on exit
-- before you had to type more to exit
improved connection logic with a try catch
improved disconnection doesnt crash
fix [int] to [cchar] reduced mem usage
code cleanup
try? -> catch print(error.localizedDesc)
guard let var = var  else ---> guard let var else
removed file importers as it didnt eork
compbined guards in writetochannel
2025-06-25 11:40:25 +01:00

168 lines
4.5 KiB
Swift

//
// ConnectionView.swift
// ShhShell
//
// Created by neon443 on 20/06/2025.
//
import SwiftUI
struct ConnectionView: View {
@ObservedObject var handler: SSHHandler
@ObservedObject var hostsManager: HostsManager
@ObservedObject var keyManager: KeyManager
@State var passphrase: String = ""
@State var pubkeyStr: String = ""
@State var privkeyStr: String = ""
@State var showTerminal: Bool = false
@State var hostKeyChangedAlert: Bool = false
var body: some View {
NavigationStack {
List {
Section {
HStack {
Text(handler.connected ? "connected" : "not connected")
.modifier(foregroundColorStyle(handler.connected ? .green : .red))
Text(handler.authorized ? "authorized" : "unauthorized")
.modifier(foregroundColorStyle(handler.authorized ? .green : .red))
}
TextField("address", text: $handler.host.address)
.textFieldStyle(.roundedBorder)
TextField(
"port",
text: Binding(
get: { String(handler.host.port) },
set: {
if let input = Int($0) {
handler.host.port = input
}
}
)
)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
}
Section {
TextField("Username", text: $handler.host.username)
.textFieldStyle(.roundedBorder)
SecureField("Password", text: $handler.host.password)
.textFieldStyle(.roundedBorder)
HStack {
TextField("", text: $pubkeyStr, prompt: Text("Public Key"))
.onSubmit {
let newStr = pubkeyStr.replacingOccurrences(of: "\r\n", with: "")
handler.host.publicKey = Data(newStr.utf8)
}
}
HStack {
SecureField("", text: $privkeyStr, prompt: Text("Private Key"))
.onSubmit {
let newStr = privkeyStr.replacingOccurrences(of: "\r\n", with: "")
handler.host.privateKey = Data(newStr.utf8)
}
}
TextField("", text: $passphrase, prompt: Text("Passphrase (Optional)"))
}
if handler.host.key != nil {
Text("Hostkey: \(handler.host.key!.base64EncodedString())")
.onChange(of: handler.host.key) { _ in
guard let previousKnownHost = hostsManager.getHostMatching(handler.host) else { return }
guard handler.host.key == previousKnownHost.key else {
hostKeyChangedAlert = true
return
}
}
}
Button() {
showTerminal.toggle()
} label: {
Label("Show Terminal", systemImage: "apple.terminal")
}
.disabled(!handler.connected || !handler.authorized)
Button() {
if handler.authorized && handler.connected {
} else {
handler.go()
}
withAnimation { handler.testExec() }
} label: {
if let testResult = handler.testSuceeded {
Image(systemName: testResult ? "checkmark.circle" : "xmark.circle")
.modifier(foregroundColorStyle(testResult ? .green : .red))
} else {
Label("Test Connection", systemImage: "checkmark")
}
}
}
.alert("Hostkey changed", isPresented: $hostKeyChangedAlert) {
Button("Accept New Hostkey", role: .destructive) {
hostsManager.updateHost(handler.host)
}
Button("Disconnect", role: .cancel) {
Task {
await handler.disconnect()
handler.host.key = hostsManager.getHostMatching(handler.host)?.key
}
}
} message: {
Text("Expected \(hostsManager.getHostMatching(handler.host)?.key?.base64EncodedString() ?? "null")\nbut recieved \(handler.host.key?.base64EncodedString() ?? "null" ) from the server")
}
.transition(.opacity)
.toolbar {
ToolbarItem() {
Button() {
handler.go()
showTerminal = handler.connected && handler.authorized
} label: {
Label(
handler.connected ? "Disconnect" : "Connect",
systemImage: handler.connected ? "xmark.app.fill" : "power"
)
}
}
}
}
.fullScreenCover(isPresented: $showTerminal) {
ShellView(handler: handler)
}
.onDisappear {
guard hostsManager.getHostMatching(handler.host) == handler.host else {
hostsManager.updateHost(handler.host)
return
}
}
.task {
if let publicKeyData = handler.host.publicKey {
pubkeyStr = String(data: publicKeyData, encoding: .utf8) ?? ""
}
if let privateKeyData = handler.host.privateKey {
privkeyStr = String(data: privateKeyData, encoding: .utf8) ?? ""
}
}
}
}
#Preview {
ConnectionView(
handler: SSHHandler(host: Host.debug),
hostsManager: HostsManager(),
keyManager: KeyManager()
)
}