aboutsummaryrefslogtreecommitdiff
path: root/Hutch/Networking/NetworkMonitor.swift
blob: 4d5d36491828f79b474900367165a95d24edc9d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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()
    }
}