This commit is contained in:
Peter Steinberger 2025-06-19 14:31:34 +02:00
parent 978205da76
commit e281ce7d72
8 changed files with 30 additions and 32 deletions

View file

@ -12,13 +12,13 @@ final class DockIconManager: NSObject {
private static let _shared = DockIconManager()
static var shared: DockIconManager {
return _shared
_shared
}
private var windowsObservation: NSKeyValueObservation?
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "VibeTunnel", category: "DockIconManager")
private override init() {
override private init() {
super.init()
setupObservers()
// Initial update after a small delay to ensure app state is ready

View file

@ -53,7 +53,7 @@ final class AppleScriptPermissionManager: ObservableObject {
/// This returns the cached state which may not be 100% accurate if user changed
/// permissions in System Preferences, but avoids triggering the dialog.
func checkPermissionStatus() -> Bool {
return hasPermission
hasPermission
}
/// Performs a silent permission check that won't trigger the dialog.

View file

@ -243,11 +243,14 @@ final class RustServer: ServerProtocol {
do {
try await processHandler.runProcess(process)
isRunning = true
await MainActor.run {
self.isRunning = true
}
// Immediately check for early exit (e.g., port binding failure)
try await Task.sleep(for: .milliseconds(100))
// Check for early exit on background thread
try await Task.detached(priority: .userInitiated) {
try await Task.sleep(for: .milliseconds(100))
}.value
// Try to read any immediate error output
if let stderrPipe = self.stderrPipe {
let errorHandle = stderrPipe.fileHandleForReading
@ -261,7 +264,7 @@ final class RustServer: ServerProtocol {
// Extract port number if possible
let portPattern = #"Address already in use.*?(\d+)"#
if let regex = try? NSRegularExpression(pattern: portPattern),
let match = regex.firstMatch(in: errorString, range: NSRange(errorString.startIndex..., in: errorString)) {
regex.firstMatch(in: errorString, range: NSRange(errorString.startIndex..., in: errorString)) != nil {
// Port conflict detected
logContinuation?.yield(ServerLogEntry(
level: .error,
@ -282,9 +285,11 @@ final class RustServer: ServerProtocol {
}
}
}
// Give the server more time to fully start
try await Task.sleep(for: .milliseconds(900))
// Give the server more time to fully start on background thread
try await Task.detached(priority: .userInitiated) {
try await Task.sleep(for: .milliseconds(900))
}.value
// Check if process is still running
if !process.isRunning {
@ -316,10 +321,6 @@ final class RustServer: ServerProtocol {
}
}
// Log command that failed
logger.error("Failed command: /bin/zsh -l -c \"\(ttyFwdCommand)\"")
errorDetails += "\nCommand: \(ttyFwdCommand)"
logContinuation?.yield(ServerLogEntry(
level: .error,
message: "Server process failed to start - \(errorDetails)",

View file

@ -557,7 +557,7 @@ class ServerManager {
extension PortConflictError {
static func portInUseByApp(appName: String, port: Int, alternatives: [Int]) -> Error {
return NSError(
NSError(
domain: "com.steipete.VibeTunnel.ServerManager",
code: 1001,
userInfo: [

View file

@ -1857,20 +1857,18 @@ public final class TunnelServer {
let sessions = try? JSONDecoder().decode([String: TtyFwdSession].self, from: sessionData)
{
// Start streaming for new sessions
for (sessionId, _) in sessions {
if !activeSessions.contains(sessionId) {
activeSessions.insert(sessionId)
logger.info("Starting stream for new session: \(sessionId)")
for (sessionId, _) in sessions where !activeSessions.contains(sessionId) {
activeSessions.insert(sessionId)
logger.info("Starting stream for new session: \(sessionId)")
// Create task for this session
let task = Task {
await self.streamSessionForMultiplex(
sessionId: sessionId,
continuation: continuation
)
}
await sessionTasks.add(sessionId: sessionId, task: task)
// Create task for this session
let task = Task {
await self.streamSessionForMultiplex(
sessionId: sessionId,
continuation: continuation
)
}
await sessionTasks.add(sessionId: sessionId, task: task)
}
// Clean up completed sessions

View file

@ -22,7 +22,7 @@ struct ProcessDetails {
/// Check if this is one of our managed servers
var isManagedServer: Bool {
return name == "tty-fwd" || name.contains("node") && (path?.contains("VibeTunnel") ?? false)
name == "tty-fwd" || name.contains("node") && (path?.contains("VibeTunnel") ?? false)
}
}
@ -344,4 +344,4 @@ enum PortConflictError: LocalizedError {
return "This conflict requires user action to resolve"
}
}
}
}

View file

@ -127,7 +127,7 @@ struct WelcomeView: View {
welcomeVersion = AppConstants.currentWelcomeVersion
// Close the window properly through the window controller
if let window = NSApp.windows.first(where: { $0.contentViewController is NSHostingController<WelcomeView> }) {
if let window = NSApp.windows.first(where: { $0.contentViewController is NSHostingController<Self> }) {
window.close()
}

View file

@ -89,7 +89,6 @@ final class WelcomeWindowController: NSWindowController, NSWindowDelegate {
try? await Task.sleep(for: .milliseconds(100))
}
}
}
// MARK: - Notification Extension