summaryrefslogtreecommitdiff
path: root/Hutch/Networking/NetworkMonitor.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-03-17 23:19:43 -0500
committerChristian Cleberg <[email protected]>2026-03-17 23:19:43 -0500
commit32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5 (patch)
treeee36d421d704e508d5617d803b4c8cbdb4804fe1 /Hutch/Networking/NetworkMonitor.swift
parent8f2057c53e9009c2529c9c4849c914666c0e4b40 (diff)
downloadhutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.tar.gz
hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.tar.bz2
hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.zip
v1.0
Diffstat (limited to 'Hutch/Networking/NetworkMonitor.swift')
-rw-r--r--Hutch/Networking/NetworkMonitor.swift48
1 files changed, 48 insertions, 0 deletions
diff --git a/Hutch/Networking/NetworkMonitor.swift b/Hutch/Networking/NetworkMonitor.swift
new file mode 100644
index 0000000..4d5d364
--- /dev/null
+++ b/Hutch/Networking/NetworkMonitor.swift
@@ -0,0 +1,48 @@
+import Foundation
+import Network
+
+/// Observes network connectivity using `NWPathMonitor`.
+/// Shared singleton injected into the environment.
+@Observable
+@MainActor
+final class NetworkMonitor {
+
+ private(set) var isConnected = true
+ private(set) var connectionType: ConnectionType = .unknown
+
+ enum ConnectionType: Sendable {
+ case wifi
+ case cellular
+ case wiredEthernet
+ case unknown
+ }
+
+ private let monitor = NWPathMonitor()
+ private let queue = DispatchQueue(label: "net.cleberg.Hutch.NetworkMonitor")
+
+ init() {
+ startMonitoring()
+ }
+
+ private func startMonitoring() {
+ monitor.pathUpdateHandler = { [weak self] path in
+ Task { @MainActor [weak self] in
+ guard let self else { return }
+ self.isConnected = path.status == .satisfied
+ self.connectionType = self.resolveConnectionType(path)
+ }
+ }
+ monitor.start(queue: queue)
+ }
+
+ private nonisolated func resolveConnectionType(_ path: NWPath) -> ConnectionType {
+ if path.usesInterfaceType(.wifi) { return .wifi }
+ if path.usesInterfaceType(.cellular) { return .cellular }
+ if path.usesInterfaceType(.wiredEthernet) { return .wiredEthernet }
+ return .unknown
+ }
+
+ deinit {
+ monitor.cancel()
+ }
+}