import Foundation import AppKit public enum PingQuality { case good(ms: Int) // < 450 ms -> Emerald Green case medium(ms: Int) // 450 - 750 ms -> Warm Yellow/Lime case high(ms: Int) // 750 - 1500 ms -> Amber Orange case disconnected(ms: Int?) // > 1500 ms or Timeout/Error -> Crimson Red public var labelText: String { switch self { case .good(let ms): return "\(ms)ms" case .medium(let ms): return "\(ms)ms" case .high(let ms): return "\(ms)ms" case .disconnected(let ms): if let ms = ms { return "\(ms)ms" } else { return "OFF" } } } } public final class PingMonitor { public static let shared = PingMonitor() private let targetURL = URL(string: "https://translate.compare.soniox.com/")! private var session: URLSession! private var timer: Timer? private var isRunning = false private var isMeasuring = false public var onPingUpdate: ((PingQuality) -> Void)? public private(set) var currentQuality: PingQuality = .medium(ms: 380) private init() { let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = 2.5 config.timeoutIntervalForResource = 2.5 config.waitsForConnectivity = false config.requestCachePolicy = .reloadIgnoringLocalCacheData self.session = URLSession(configuration: config) setupSleepWakeObservers() } private func setupSleepWakeObservers() { NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.willSleepNotification, object: nil, queue: .main) { [weak self] _ in print("PingMonitor: Mac entering sleep. Pausing ping measurements.") self?.stop() } NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.didWakeNotification, object: nil, queue: .main) { [weak self] _ in print("PingMonitor: Mac woke from sleep. Resuming ping in 2.5s after network settles...") DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) { self?.start() } } } public func start() { guard !isRunning else { return } isRunning = true measurePing() DispatchQueue.main.async { [weak self] in self?.timer?.invalidate() self?.timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in self?.measurePing() } } } public func stop() { isRunning = false isMeasuring = false timer?.invalidate() timer = nil } private func measurePing() { guard isRunning, !isMeasuring else { return } isMeasuring = true var req = URLRequest(url: targetURL) req.httpMethod = "HEAD" let t0 = Date() let task = session.dataTask(with: req) { [weak self] _, resp, _ in defer { self?.isMeasuring = false } let elapsed = Date().timeIntervalSince(t0) * 1000.0 let ms = Int(elapsed) let quality: PingQuality if let http = resp as? HTTPURLResponse, (200...399).contains(http.statusCode) { if ms < 450 { quality = .good(ms: ms) } else if ms <= 750 { quality = .medium(ms: ms) } else if ms <= 1500 { quality = .high(ms: ms) } else { quality = .disconnected(ms: ms) } } else { quality = .disconnected(ms: nil) } DispatchQueue.main.async { self?.currentQuality = quality self?.onPingUpdate?(quality) } } task.resume() } }