From 7c28cc79da7a674193b43c7fcbba9a8d1aea7f58 Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Mon, 1 Sep 2025 17:46:43 +0100 Subject: [PATCH] added full expand and full close buttons, with new symbols that support ios 13+ added historylimitdisplay computed property made disconnect synchronous --- ShhShell/SSH/SSHHandler.swift | 8 +- ShhShell/Views/Hosts/RecentsView.swift | 113 +++++++++++++++---------- 2 files changed, 72 insertions(+), 49 deletions(-) diff --git a/ShhShell/SSH/SSHHandler.swift b/ShhShell/SSH/SSHHandler.swift index 1835afe..fac0621 100644 --- a/ShhShell/SSH/SSHHandler.swift +++ b/ShhShell/SSH/SSHHandler.swift @@ -140,11 +140,9 @@ class SSHHandler: @unchecked Sendable, ObservableObject { } func disconnect() { - Task { @MainActor in - self.hostkeyChanged = false - withAnimation { self.state = .idle } - withAnimation { self.testSuceeded = nil } - } + self.hostkeyChanged = false + withAnimation { self.state = .idle } + withAnimation { self.testSuceeded = nil } if let sessionID { Task { @MainActor in diff --git a/ShhShell/Views/Hosts/RecentsView.swift b/ShhShell/Views/Hosts/RecentsView.swift index 849d362..7461392 100644 --- a/ShhShell/Views/Hosts/RecentsView.swift +++ b/ShhShell/Views/Hosts/RecentsView.swift @@ -11,12 +11,22 @@ struct RecentsView: View { @ObservedObject var hostsManager: HostsManager @ObservedObject var keyManager: KeyManager - @State var historyCount: Int = 1 + @State var historyLimit: Int = 1 + var historyLimitDisplay: String { + let count = hostsManager.history.count + if historyLimit == 0 { + return "\(count) item\(plural(count))" + } else if historyLimit > count { + return "\(count)/\(count)" + } else { + return "\(historyLimit)/\(count)" + } + } - var body: some View { + var body: some View { if !hostsManager.history.isEmpty { Section("Recents") { - ForEach(hostsManager.history.reversed().prefix(historyCount)) { history in + ForEach(hostsManager.history.reversed().prefix(historyLimit)) { history in NavigationLink() { ConnectionView( handler: SSHHandler( @@ -46,51 +56,66 @@ struct RecentsView: View { .tint(.red) } } -// if historyCount <= hostsManager.history.count { - HStack(alignment: .center) { - Button() { - var increment = 2 - if historyCount+2 > hostsManager.history.count { - increment = 1 - } - withAnimation(.spring) { historyCount += increment } - } label: { - Image(systemName: "chevron.down") - .resizable().scaledToFit() - .frame(width: 20) - .foregroundStyle(hostsManager.tint) - } - .buttonStyle(.plain) - .disabled(historyCount == hostsManager.history.count) - - Spacer() - Text( - historyCount == 0 ? - "\(hostsManager.history.count) item\(plural(hostsManager.history.count))" : - "\(historyCount)/\(hostsManager.history.count)" - ) - .foregroundStyle(.gray) - .font(.caption) - .contentTransition(.numericText()) - Spacer() - - Button { - withAnimation(.spring) { historyCount = 0 } - } label: { - Image(systemName: "chevron.up.2") - .resizable().scaledToFit() - .frame(width: 20) - .foregroundStyle(hostsManager.tint) - } - .buttonStyle(.plain) - .disabled(historyCount == 0) + HStack(alignment: .center) { + Button() { + var decrement: Int = 2 + if historyLimit < 2 { decrement = 1 } + withAnimation(.spring) { historyLimit -= decrement } + } label: { + Image(systemName: "chevron.up") + .resizable().scaledToFit() + .frame(width: 20) + .foregroundStyle(hostsManager.tint) } -// } - + .buttonStyle(.plain) + .disabled(historyLimit == 0) + .padding(.trailing, 10) + + Button() { + withAnimation(.spring) { historyLimit += 2 } + } label: { + Image(systemName: "chevron.down") + .resizable().scaledToFit() + .frame(width: 20) + .foregroundStyle(hostsManager.tint) + } + .buttonStyle(.plain) + .disabled(historyLimit >= hostsManager.history.count) + + Spacer() + Text(historyLimitDisplay) + .foregroundStyle(.gray) + .font(.caption) + .contentTransition(.numericText()) + Spacer() + + Button { + withAnimation(.spring) { historyLimit = Int.max } + } label: { + Image(systemName: "rectangle.expand.vertical") + .resizable().scaledToFit() + .frame(width: 20) + .foregroundStyle(hostsManager.tint) + } + .buttonStyle(.plain) + .disabled(historyLimit != 0) + .padding(.trailing, 10) + + Button { + withAnimation(.spring) { historyLimit = 0 } + } label: { + Image(systemName: "rectangle.compress.vertical") + .resizable().scaledToFit() + .frame(width: 20) + .foregroundStyle(hostsManager.tint) + } + .buttonStyle(.plain) + .disabled(historyLimit == 0) + } } .transition(.opacity) } - } + } } #Preview {