MULTI SESSIONS!!!

terminalviewcontainer has a dict of [handler, terminalView] with a uuid key
each session gets a new uuid, and on disconnect, the session is removed from terminalviewcontainer
sessions list view to reopen sessions
remove multiview
extracted terminalviewcontainer
This commit is contained in:
neon443
2025-06-29 15:40:46 +01:00
parent 870ebb6fcc
commit 331a921499
10 changed files with 133 additions and 20 deletions

View File

@@ -9,11 +9,14 @@ import Foundation
import LibSSH
import OSLog
import SwiftUI
import SwiftTerm
class SSHHandler: @unchecked Sendable, ObservableObject {
private var session: ssh_session?
private var channel: ssh_channel?
var sessionID: UUID?
var scrollback: [String] = []
var scrollbackSize = 0.0
@@ -101,6 +104,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
func connect() throws(SSHError) {
guard !host.address.isEmpty else { throw .connectionFailed("No address to connect to.") }
withAnimation { state = .connecting }
sessionID = UUID()
var verbosity: Int = 0
// var verbosity: Int = SSH_LOG_FUNCTIONS
@@ -134,6 +138,12 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
withAnimation { self.testSuceeded = nil }
}
if let sessionID {
Task { @MainActor in
TerminalViewContainer.shared.removeValue(forKey: sessionID)
self.sessionID = nil
}
}
scrollback = []
scrollbackSize = 0

View File

@@ -15,6 +15,12 @@ struct ContentView: View {
var body: some View {
NavigationStack {
List {
SessionsListView(
handler: handler,
hostsManager: hostsManager,
keyManager: keyManager
)
HostsView(
handler: handler,
hostsManager: hostsManager,

View File

@@ -147,7 +147,6 @@ struct ConnectionView: View {
Button() {
handler.go()
showTerminal = checkShell(handler.state)
TerminalController.TerminalViewContainer.shared = nil
} label: {
Label(
handler.connected ? "Disconnect" : "Connect",

View File

@@ -17,17 +17,6 @@ struct HostsView: View {
Text("Add your first Host!")
}
//proves that u can connect to multiple at the same time
NavigationLink() {
ForEach(hostsManager.hosts) { host in
let miniHandler = SSHHandler(host: host)
TerminalController(handler: miniHandler, hostsManager: hostsManager)
.onAppear { miniHandler.go() }
}
} label: {
Label("multiview", systemImage: "square.split.2x2")
}
ForEach(hostsManager.hosts) { host in
NavigationLink() {
ConnectionView(

View File

@@ -0,0 +1,34 @@
//
// SessionView.swift
// ShhShell
//
// Created by neon443 on 29/06/2025.
//
import SwiftUI
struct SessionView: View {
@ObservedObject var hostsManager: HostsManager
@State var key: UUID
@State var shellPresented: Bool = false
var body: some View {
Text(key.uuidString)
.onTapGesture {
shellPresented.toggle()
}
.fullScreenCover(isPresented: $shellPresented) {
ShellView(
handler: TerminalViewContainer.shared[key]!.handler,
hostsManager: hostsManager
)
}
}
}
#Preview {
SessionView(
hostsManager: HostsManager(),
key: UUID()
)
}

View File

@@ -0,0 +1,31 @@
//
// SessionsView.swift
// ShhShell
//
// Created by neon443 on 29/06/2025.
//
import SwiftUI
import SwiftTerm
struct SessionsListView: View {
@ObservedObject var handler: SSHHandler
@ObservedObject var hostsManager: HostsManager
@ObservedObject var keyManager: KeyManager
var body: some View {
Section("Sessions") {
ForEach(TerminalViewContainer.shared.map {$0.key}, id: \.self) { key in
SessionView(hostsManager: hostsManager, key: key)
}
}
}
}
#Preview {
SessionsListView(
handler: SSHHandler(host: Host.debug),
hostsManager: HostsManager(),
keyManager: KeyManager()
)
}

View File

@@ -18,7 +18,9 @@ struct ShellView: View {
ZStack {
TerminalController(handler: handler, hostsManager: hostsManager)
.onAppear {
TerminalController.TerminalViewContainer.shared?.restoreScrollback()
if let sessionID = handler.sessionID {
TerminalViewContainer.shared[sessionID]?.terminalView.restoreScrollback()
}
}
Group {

View File

@@ -14,13 +14,11 @@ struct TerminalController: UIViewRepresentable {
@ObservedObject var handler: SSHHandler
@ObservedObject var hostsManager: HostsManager
final class TerminalViewContainer {
@MainActor static var shared: SSHTerminalDelegate?
}
func makeUIView(context: Context) -> TerminalView {
if let existing = TerminalViewContainer.shared {
return existing
if let sessionID = handler.sessionID {
if let existing = TerminalViewContainer.shared[sessionID] {
return existing.terminalView
}
}
let tv = SSHTerminalDelegate(
@@ -31,7 +29,12 @@ struct TerminalController: UIViewRepresentable {
tv.translatesAutoresizingMaskIntoConstraints = false
tv.autoresizingMask = [.flexibleWidth, .flexibleHeight]
TerminalViewContainer.shared = tv
if let sessionID = handler.sessionID {
TerminalViewContainer.shared[sessionID] = TerminalContainer(
handler: handler,
terminalView: tv
)
}
return tv
}

View File

@@ -0,0 +1,19 @@
//
// TerminalViewContainer.swift
// ShhShell
//
// Created by neon443 on 29/06/2025.
//
import Foundation
public final class TerminalViewContainer {
@MainActor static var shared: [
UUID: TerminalContainer
] = [:]
}
struct TerminalContainer {
var handler: SSHHandler
var terminalView: SSHTerminalDelegate
}