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
This commit is contained in:
neon443
2025-08-17 14:14:55 +01:00
parent 56c5634d9a
commit 4f9055b58f
6 changed files with 91 additions and 7 deletions

View File

@@ -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 = "<group>"; };
A923172C2E07138000ECE1E6 /* SSHTerminalDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHTerminalDelegate.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>";
@@ -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 */,

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -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
)
}

View File

@@ -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) {

View File

@@ -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()
)
}