vibetunnel/VibeTunnel/Core/Services/ServerMonitor.swift
Peter Steinberger 70a8da5235 feat: enhance UI and automatic update handling
- Fix session count display to show on single line in menu bar
- Add conditional compilation to disable automatic updates in DEBUG mode
- Add "Open Dashboard" menu item that opens internal server URL
- Convert Help menu from popover to native macOS submenu style
- Enable automatic update downloads in Sparkle configuration
- Increase Advanced Settings tab height from 400 to 500 pixels
- Add Tailscale recommendation with clickable markdown link
- Fix Sendable protocol conformance issues throughout codebase
- Add ApplicationMover utility for app installation location management

These changes improve the overall user experience by making the UI more
intuitive and ensuring automatic updates work correctly in production
while being disabled during development.
2025-06-16 05:53:08 +02:00

73 lines
2 KiB
Swift

import Foundation
import Observation
/// Monitors the HTTP server status and provides observable state for the UI
@MainActor
@Observable
public final class ServerMonitor {
public static let shared = ServerMonitor()
// Observable properties
public private(set) var isRunning = false
public private(set) var port: Int = 4_020
public private(set) var lastError: Error?
/// Reference to the actual server
private weak var server: TunnelServer?
private init() {}
/// Updates the monitor with the current server instance
public func setServer(_ server: TunnelServer?) {
self.server = server
updateStatus()
}
/// Updates the current status from the server
public func updateStatus() {
guard let server else {
isRunning = false
return
}
isRunning = server.isRunning
port = server.port
lastError = server.lastError
}
/// Starts the server if not already running
public func startServer() async throws {
guard let server else {
throw ServerError.failedToStart("No server instance available")
}
try await server.start()
updateStatus()
}
/// Stops the server if running
public func stopServer() async throws {
guard let server else { return }
try await server.stop()
updateStatus()
}
/// Checks if the server is healthy by making a health check request
public func checkHealth() async -> Bool {
guard isRunning else { return false }
do {
let url = URL(string: "http://127.0.0.1:\(port)/health")!
let request = URLRequest(url: url, timeoutInterval: 2.0)
let (_, response) = try await URLSession.shared.data(for: request)
if let httpResponse = response as? HTTPURLResponse {
return httpResponse.statusCode == 200
}
} catch {
// Server not responding
}
return false
}
}