diff --git a/ShhShell/Misc/Backgrounder.swift b/ShhShell/Misc/Backgrounder.swift index 4b07b3d..d0c56c3 100644 --- a/ShhShell/Misc/Backgrounder.swift +++ b/ShhShell/Misc/Backgrounder.swift @@ -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() { diff --git a/ShhShell/SSH/SSHError.swift b/ShhShell/SSH/SSHError.swift index dfcc04a..374f572 100644 --- a/ShhShell/SSH/SSHError.swift +++ b/ShhShell/SSH/SSHError.swift @@ -25,3 +25,7 @@ enum KeyError: Error { case pubkeyRejected case privkeyRejected } + +enum ReconnectError: Error { + case alreadyConnected +} diff --git a/ShhShell/SSH/SSHHandler.swift b/ShhShell/SSH/SSHHandler.swift index 01d9292..1272bb5 100644 --- a/ShhShell/SSH/SSHHandler.swift +++ b/ShhShell/SSH/SSHHandler.swift @@ -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 } diff --git a/ShhShell/Terminal/SSHTerminalDelegate.swift b/ShhShell/Terminal/SSHTerminalDelegate.swift index de668e2..1dd7450 100644 --- a/ShhShell/Terminal/SSHTerminalDelegate.swift +++ b/ShhShell/Terminal/SSHTerminalDelegate.swift @@ -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() { diff --git a/ShhShell/Views/Terminal/ShellView.swift b/ShhShell/Views/Terminal/ShellView.swift index e178c7e..d7456a2 100644 --- a/ShhShell/Views/Terminal/ShellView.swift +++ b/ShhShell/Views/Terminal/ShellView.swift @@ -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)) } } }