ok so now you can minimize an ssh session
 - it will remember the scrollback,
- if u uminimixe it and then reconnect, it works
it uses a shared static var in TerminalViewContainer to keep SSHTerminal instances
scrollback restoration works and everything
This commit is contained in:
neon443
2025-06-26 16:25:35 +01:00
parent 747406df5d
commit 09fd4a10fd
4 changed files with 31 additions and 21 deletions

View File

@@ -12,6 +12,8 @@ struct ConnectionView: View {
@ObservedObject var hostsManager: HostsManager @ObservedObject var hostsManager: HostsManager
@ObservedObject var keyManager: KeyManager @ObservedObject var keyManager: KeyManager
@State private var shellView: ShellView? = nil
@State var passphrase: String = "" @State var passphrase: String = ""
@State var pubkeyStr: String = "" @State var pubkeyStr: String = ""
@@ -145,6 +147,7 @@ struct ConnectionView: View {
Button() { Button() {
handler.go() handler.go()
showTerminal = checkShell(handler.state) showTerminal = checkShell(handler.state)
TerminalController.TerminalViewContainer.shared = nil
} label: { } label: {
Label( Label(
handler.connected ? "Disconnect" : "Connect", handler.connected ? "Disconnect" : "Connect",
@@ -156,7 +159,11 @@ struct ConnectionView: View {
} }
} }
.fullScreenCover(isPresented: $showTerminal) { .fullScreenCover(isPresented: $showTerminal) {
ShellView(handler: handler) if let shellView {
shellView
} else {
Text("no shellview")
}
} }
.onChange(of: handler.host.key) { _ in .onChange(of: handler.host.key) { _ in
guard let previousKnownHost = hostsManager.getHostMatching(handler.host) else { return } guard let previousKnownHost = hostsManager.getHostMatching(handler.host) else { return }
@@ -176,6 +183,11 @@ struct ConnectionView: View {
privkeyStr = String(data: privateKeyData, encoding: .utf8) ?? "" privkeyStr = String(data: privateKeyData, encoding: .utf8) ?? ""
} }
} }
.onAppear {
if shellView == nil {
shellView = ShellView(handler: handler)
}
}
} }
} }

View File

@@ -18,8 +18,6 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
self.init(frame: frame) self.init(frame: frame)
self.handler = handler self.handler = handler
restoreScrollback()
DispatchQueue.main.async { DispatchQueue.main.async {
Task { Task {
guard let handler = self.handler else { return } guard let handler = self.handler else { return }
@@ -88,8 +86,10 @@ final class SSHTerminalView: TerminalView, Sendable, @preconcurrency TerminalVie
func restoreScrollback() { func restoreScrollback() {
guard let scrollback = handler?.scrollback else { return } guard let scrollback = handler?.scrollback else { return }
guard !scrollback.isEmpty else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
self.getTerminal().resetToInitialState()
for line in scrollback { for line in scrollback {
self.feed(text: line) self.feed(text: line)
} }

View File

@@ -12,12 +12,14 @@ struct ShellView: View {
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
@State private var terminalControllerRef: TerminalController?
var body: some View { var body: some View {
NavigationStack { NavigationStack {
ZStack { ZStack {
terminalControllerRef TerminalController(handler: handler)
.onAppear {
print("asd\(handler.scrollback.count)")
TerminalController.TerminalViewContainer.shared?.restoreScrollback()
}
Group { Group {
Color.gray.opacity(0.2) Color.gray.opacity(0.2)
@@ -31,9 +33,6 @@ struct ShellView: View {
DialogView(handler: handler, showDialog: !handler.connected) DialogView(handler: handler, showDialog: !handler.connected)
} }
} }
.task {
terminalControllerRef = TerminalController(handler: handler)
}
.toolbar { .toolbar {
ToolbarItem { ToolbarItem {
Button() { Button() {

View File

@@ -13,18 +13,21 @@ import SwiftTerm
struct TerminalController: UIViewRepresentable { struct TerminalController: UIViewRepresentable {
@ObservedObject var handler: SSHHandler @ObservedObject var handler: SSHHandler
final class TerminalViewContainer {
@MainActor static var shared: SSHTerminalView?
}
func makeUIView(context: Context) -> TerminalView { func makeUIView(context: Context) -> TerminalView {
let tv = SSHTerminalView( if let existing = TerminalViewContainer.shared {
frame: CGRect( return existing
origin: CGPoint(x: 0, y: 0), }
size: .zero
),
handler: handler
)
let tv = SSHTerminalView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: .zero), handler: handler)
tv.translatesAutoresizingMaskIntoConstraints = false tv.translatesAutoresizingMaskIntoConstraints = false
tv.autoresizingMask = [.flexibleWidth, .flexibleHeight] tv.autoresizingMask = [.flexibleWidth, .flexibleHeight]
TerminalViewContainer.shared = tv
return tv return tv
} }
@@ -32,8 +35,4 @@ struct TerminalController: UIViewRepresentable {
tv.setNeedsLayout() tv.setNeedsLayout()
tv.layoutIfNeeded() tv.layoutIfNeeded()
} }
static func dismantleUIView(_ uiView: SSHTerminalView, coordinator: ()) {
uiView.handler?.disconnect()
}
} }