From 4f9055b58f7ff528463e0e00c77c5a21e9da664b Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Sun, 17 Aug 2025 14:14:55 +0100 Subject: [PATCH] added hostpreview to preview hosts added a thingy in hostsmanager to load test data if inited with previews = true added a context menu to hosts with a nice preview --- ShhShell.xcodeproj/project.pbxproj | 6 +- ShhShell/Host/HostsManager.swift | 8 ++- ShhShell/Views/Hosts/ConnectionView.swift | 2 +- ShhShell/Views/Hosts/HostPreview.swift | 66 +++++++++++++++++++ .../{Misc => Hosts}/HostSymbolPreview.swift | 6 +- ShhShell/Views/Hosts/HostsView.swift | 10 ++- 6 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 ShhShell/Views/Hosts/HostPreview.swift rename ShhShell/Views/{Misc => Hosts}/HostSymbolPreview.swift (93%) diff --git a/ShhShell.xcodeproj/project.pbxproj b/ShhShell.xcodeproj/project.pbxproj index 23649a7..fd3009e 100644 --- a/ShhShell.xcodeproj/project.pbxproj +++ b/ShhShell.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ A923172A2E07113100ECE1E6 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92317292E07113100ECE1E6 /* TerminalController.swift */; }; A923172D2E07138000ECE1E6 /* SSHTerminalDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */; }; A923172F2E08851200ECE1E6 /* ShellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A923172E2E08851200ECE1E6 /* ShellView.swift */; }; + A9231A572E52041500974753 /* HostPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9231A562E52041500974753 /* HostPreview.swift */; }; A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538C52DEE0742007E0A18 /* ContentView.swift */; }; A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538C62DEE0742007E0A18 /* ShhShellApp.swift */; }; A92538CA2DEE0742007E0A18 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A92538C42DEE0742007E0A18 /* Assets.xcassets */; }; @@ -151,6 +152,7 @@ A92317292E07113100ECE1E6 /* TerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalController.swift; sourceTree = ""; }; A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHTerminalDelegate.swift; sourceTree = ""; }; A923172E2E08851200ECE1E6 /* ShellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ShellView.swift; path = ShhShell/Views/Terminal/ShellView.swift; sourceTree = SOURCE_ROOT; }; + A9231A562E52041500974753 /* HostPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostPreview.swift; sourceTree = ""; }; A925389A2DEE06DC007E0A18 /* ShhShell.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShhShell.app; sourceTree = BUILT_PRODUCTS_DIR; }; A92538A72DEE06DE007E0A18 /* ShhShellTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShhShellTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A92538B12DEE06DE007E0A18 /* ShhShellUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShhShellUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -513,7 +515,6 @@ A96C6B012E0C49E800F377FE /* CenteredLabel.swift */, A93143C52DF61FE300FCD5DB /* ViewModifiers.swift */, A96C90A02E12B87900724253 /* TextBox.swift */, - A9DA97722E0D40C100142DDC /* HostSymbolPreview.swift */, A9835C3B2E17CCA500969508 /* TrafficLights.swift */, ); path = Misc; @@ -526,6 +527,8 @@ A985545C2E055D4D009051BD /* ConnectionView.swift */, A98CAB432E4229F7005E4C42 /* HostSymbolPicker.swift */, A9CC786A2E4E681400FAEE58 /* RecentsView.swift */, + A9231A562E52041500974753 /* HostPreview.swift */, + A9DA97722E0D40C100142DDC /* HostSymbolPreview.swift */, ); path = Hosts; sourceTree = ""; @@ -805,6 +808,7 @@ A9C060ED2E3FBCD000CA9374 /* SnippetPicker.swift in Sources */, A96BE6A62E113DB000C0FEE9 /* ColorCodable.swift in Sources */, A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */, + A9231A572E52041500974753 /* HostPreview.swift in Sources */, A96BE6A42E113D9400C0FEE9 /* ThemeCodable.swift in Sources */, A9FD375F2E14648E005319A8 /* KeyImporterView.swift in Sources */, A93143C02DF61B3200FCD5DB /* Host.swift in Sources */, diff --git a/ShhShell/Host/HostsManager.swift b/ShhShell/Host/HostsManager.swift index 0e25ef7..62ecd89 100644 --- a/ShhShell/Host/HostsManager.swift +++ b/ShhShell/Host/HostsManager.swift @@ -30,12 +30,18 @@ class HostsManager: ObservableObject, @unchecked Sendable { selectedTheme.ansi[selectedAnsi].suiColor } - init() { + init(previews: Bool = false) { loadHosts() loadThemes() loadFonts() loadSnippets() loadHistory() + if previews { + self.hosts = [Host.debug, Host.blank] + self.themes = [Theme.defaultTheme] + self.snippets = [Snippet(name: "kys", content: "ls\npwd\n")] + self.history = [History(host: Host.debug, count: 3)] + } } func loadHistory() { diff --git a/ShhShell/Views/Hosts/ConnectionView.swift b/ShhShell/Views/Hosts/ConnectionView.swift index f8d7df1..e463790 100644 --- a/ShhShell/Views/Hosts/ConnectionView.swift +++ b/ShhShell/Views/Hosts/ConnectionView.swift @@ -131,7 +131,7 @@ Hostkey fingerprint is \(handler.getHostkey() ?? "nil") Button() { withAnimation { showIconPicker.toggle() } } label: { - HostSymbolPreview(symbol: handler.host.symbol, label: handler.host.label, small: true) + HostSymbolPreview(symbol: handler.host.symbol, label: handler.host.label, horizontal: true) .id(handler.host) } .popover(isPresented: $showIconPicker) { diff --git a/ShhShell/Views/Hosts/HostPreview.swift b/ShhShell/Views/Hosts/HostPreview.swift new file mode 100644 index 0000000..4750b7a --- /dev/null +++ b/ShhShell/Views/Hosts/HostPreview.swift @@ -0,0 +1,66 @@ +// +// HostPreview.swift +// ShhShell +// +// Created by neon443 on 17/08/2025. +// + +import SwiftUI + +struct HostPreview: View { + @ObservedObject var hostsManager: HostsManager + @ObservedObject var keyManager: KeyManager + @State var host: Host + + var body: some View { + List { + HStack { + Image(systemName: "info.circle") + Text("Info for \"\(host.description)\"") + .monospaced() + Spacer() + HostSymbolPreview(symbol: host.symbol, label: host.label) + .frame(maxHeight: 30) + } + + Section { + TextBox(label: "Name", text: $host.name, prompt: "") + + TextBox(label: "Address", text: $host.address, prompt: "") + + TextBox(label: "Port", text: Binding( + get: { String(host.port) }, + set: { + if let input = Int($0) { + host.port = input + } + }), + prompt: "", + keyboardType: .numberPad + ) + } + + Section { + TextBox(label: "Username", text: $host.username, prompt: "") + + TextBox(label: "Password", text: $host.password, prompt: "", secure: true) + + let keypair = keyManager.keypairs.first(where: { $0.id == host.privateKeyID }) + TextBox(label: "Private key", text: .constant(keypair?.name ?? "None"), prompt: "") + } + + Section() { + let startupSnip = hostsManager.snippets.first(where: { $0.id == host.startupSnippetID }) + TextBox(label: "Startup Snippet", text: .constant(startupSnip?.name ?? "None"), prompt: "") + } + } + } +} + +#Preview { + HostPreview( + hostsManager: HostsManager(), + keyManager: KeyManager(), + host: Host.debug + ) +} diff --git a/ShhShell/Views/Misc/HostSymbolPreview.swift b/ShhShell/Views/Hosts/HostSymbolPreview.swift similarity index 93% rename from ShhShell/Views/Misc/HostSymbolPreview.swift rename to ShhShell/Views/Hosts/HostSymbolPreview.swift index 5c3cc62..ac86fb3 100644 --- a/ShhShell/Views/Misc/HostSymbolPreview.swift +++ b/ShhShell/Views/Hosts/HostSymbolPreview.swift @@ -10,15 +10,15 @@ import SwiftUI struct HostSymbolPreview: View { @State var symbol: HostSymbol @State var label: String - @State var small: Bool = false + @State var horizontal: Bool = false var body: some View { - if small { + if horizontal { HStack(alignment: .center, spacing: 5) { - Text(label) symbol.image .resizable().scaledToFit() .symbolRenderingMode(.monochrome) + Text(label) } } else { ZStack(alignment: .center) { diff --git a/ShhShell/Views/Hosts/HostsView.swift b/ShhShell/Views/Hosts/HostsView.swift index 97d6f17..286df70 100644 --- a/ShhShell/Views/Hosts/HostsView.swift +++ b/ShhShell/Views/Hosts/HostsView.swift @@ -33,6 +33,14 @@ struct HostsView: View { } .id(host) .animation(.default, value: host) + .contextMenu { + Button() { + hostsManager.removeHost(host) + } label: { Label("Delete", systemImage: "trash") } + .tint(.red) + } preview: { + HostPreview(hostsManager: hostsManager, keyManager: keyManager, host: host) + } .swipeActions(edge: .trailing) { Button(role: .destructive) { hostsManager.removeHost(host) @@ -61,7 +69,7 @@ struct HostsView: View { #Preview { HostsView( handler: SSHHandler(host: Host.debug, keyManager: nil), - hostsManager: HostsManager(), + hostsManager: HostsManager(previews: true), keyManager: KeyManager() ) }