mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 21:36:17 +00:00
Added support for reconnecting to a server, using the same terminal
added reconnect() to sshhandler added support to go() and connect() to use an arbritrary sessionID redid readloop in sshterminaldelegate to use a timer, instead of a while loop in a Task, allowsfor one readloop per terminal instead updated the ui for the disconnected alert increased max read size from 1024 to added reconnecterror updated tracker to remove print statements and exit start/stop tracking funcs early if tracking/not tracking
This commit is contained in:
@@ -10,6 +10,7 @@ import CoreLocation
|
||||
|
||||
class Backgrounder: NSObject, CLLocationManagerDelegate, ObservableObject {
|
||||
private let manager = CLLocationManager()
|
||||
var tracking: Bool = false
|
||||
|
||||
@MainActor
|
||||
static var shared: Backgrounder = Backgrounder()
|
||||
@@ -23,17 +24,19 @@ class Backgrounder: NSObject, CLLocationManagerDelegate, ObservableObject {
|
||||
}
|
||||
|
||||
func startBgTracking() {
|
||||
// guard mana
|
||||
guard !tracking else { return }
|
||||
guard checkPermsStatus() else { return }
|
||||
manager.allowsBackgroundLocationUpdates = true
|
||||
manager.pausesLocationUpdatesAutomatically = false
|
||||
manager.startMonitoringSignificantLocationChanges()
|
||||
print("started tgracking")
|
||||
tracking = true
|
||||
}
|
||||
|
||||
func stopBgTracking() {
|
||||
guard tracking else { return }
|
||||
manager.stopUpdatingLocation()
|
||||
manager.allowsBackgroundLocationUpdates = false
|
||||
print("stopped tracking")
|
||||
tracking = false
|
||||
}
|
||||
|
||||
func requestPerms() {
|
||||
|
||||
@@ -25,3 +25,7 @@ enum KeyError: Error {
|
||||
case pubkeyRejected
|
||||
case privkeyRejected
|
||||
}
|
||||
|
||||
enum ReconnectError: Error {
|
||||
case alreadyConnected
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
return String(cString: cString)
|
||||
}
|
||||
|
||||
func go() {
|
||||
func go(id: UUID = UUID()) {
|
||||
guard !connected else { disconnect(); return }
|
||||
|
||||
do { try connect() } catch {
|
||||
do { try connect(id: id) } catch {
|
||||
print("error when connecting \(error.localizedDescription)")
|
||||
return
|
||||
}
|
||||
@@ -108,10 +108,10 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
setTitle("\(host.username)@\(host.address)")
|
||||
}
|
||||
|
||||
func connect() throws(SSHError) {
|
||||
func connect(id: UUID) throws(SSHError) {
|
||||
guard !host.address.isEmpty else { throw .connectionFailed("No address to connect to.") }
|
||||
withAnimation { state = .connecting }
|
||||
sessionID = UUID()
|
||||
sessionID = id
|
||||
|
||||
var verbosity: Int = 0
|
||||
// var verbosity: Int = SSH_LOG_FUNCTIONS
|
||||
@@ -139,6 +139,11 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
func reconnect() throws(ReconnectError) {
|
||||
guard !connected else { throw .alreadyConnected }
|
||||
go(id: sessionID!)
|
||||
}
|
||||
|
||||
func disconnect() {
|
||||
// Task {
|
||||
self.hostkeyChanged = false
|
||||
@@ -359,7 +364,7 @@ class SSHHandler: @unchecked Sendable, ObservableObject {
|
||||
return nil
|
||||
}
|
||||
|
||||
var buffer: [CChar] = Array(repeating: 0, count: 1024)
|
||||
var buffer: [CChar] = Array(repeating: 0, count: 4096)
|
||||
let nbytes = ssh_channel_read_nonblocking(channel, &buffer, UInt32(buffer.count), 0)
|
||||
|
||||
guard nbytes > 0 else { return nil }
|
||||
|
||||
@@ -14,6 +14,8 @@ final class SSHTerminalDelegate: TerminalView, Sendable, @preconcurrency Termina
|
||||
var handler: SSHHandler?
|
||||
var hostsManager: HostsManager?
|
||||
|
||||
var readTimer: Timer?
|
||||
|
||||
public convenience init(frame: CGRect, handler: SSHHandler, hostsManager: HostsManager) {
|
||||
self.init(frame: frame)
|
||||
|
||||
@@ -97,19 +99,18 @@ final class SSHTerminalDelegate: TerminalView, Sendable, @preconcurrency Termina
|
||||
}
|
||||
|
||||
func startFeedLoop() {
|
||||
Task {
|
||||
guard let handler else { return }
|
||||
while checkShell(handler.state) {
|
||||
guard readTimer == nil else { return }
|
||||
readTimer = Timer(timeInterval: 0.01, repeats: true) { timer in
|
||||
Task(priority: .high) {
|
||||
guard let handler = await self.handler else { return }
|
||||
if let read = handler.readFromChannel() {
|
||||
await MainActor.run {
|
||||
Task { @MainActor in
|
||||
self.feed(text: read)
|
||||
}
|
||||
} else {
|
||||
try? await Task.sleep(nanoseconds: 10_000_000) //10ms
|
||||
}
|
||||
}
|
||||
print("task end?")
|
||||
}
|
||||
RunLoop.main.add(readTimer!, forMode: .common)
|
||||
}
|
||||
|
||||
func applySelectedTheme() {
|
||||
|
||||
@@ -59,8 +59,9 @@ struct ShellView: View {
|
||||
if !checkShell(handler.state) {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 25)
|
||||
.fill(hostsManager.selectedTheme.foreground.suiColor.opacity(0.5))
|
||||
.blur(radius: 5)
|
||||
.fill(hostsManager.selectedTheme.foreground.suiColor)
|
||||
.opacity(0.5)
|
||||
.blur(radius: 2)
|
||||
.shadow(color: hostsManager.selectedTheme.foreground.suiColor, radius: 5)
|
||||
VStack {
|
||||
HStack {
|
||||
@@ -86,6 +87,8 @@ struct ShellView: View {
|
||||
.padding(10)
|
||||
}
|
||||
.fixedSize()
|
||||
.transition(.opacity)
|
||||
.animation(.spring, value: checkShell(handler.state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user