55 lines
1.6 KiB
Swift
55 lines
1.6 KiB
Swift
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)
|
|
}
|
|
}
|