import Foundation import Network #if os(macOS) import AppKit #endif private let networkChanged = Notification.Name("run.fc.byre.networkChanged") @MainActor final class NetworkWatch { static let shared = NetworkWatch() private let monitor = NWPathMonitor() private var seen = false private init() { monitor.pathUpdateHandler = { [weak self] path in let summary = "\(path.status) \(path.availableInterfaces.map(\.name).joined(separator: " "))" Task { @MainActor in self?.pathChanged(summary) } } monitor.start(queue: .main) #if os(macOS) NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.didWakeNotification, object: nil, queue: .main) { [weak self] _ in Task { @MainActor in log.notice("woke from sleep, reconnecting") self?.post() } } #endif } func observe(_ handler: @escaping @MainActor () -> Void) -> any NSObjectProtocol { NotificationCenter.default.addObserver(forName: networkChanged, object: self, queue: .main) { _ in MainActor.assumeIsolated { handler() } } } private func pathChanged(_ summary: String) { guard seen else { seen = true return } log.notice("network changed (\(summary, privacy: .public)), reconnecting") post() } private func post() { NotificationCenter.default.post(name: networkChanged, object: self) } }