zitare-native/Sources/Core/Submit/ReachabilityWatcher.swift
Till JS f5a26b2392 chore(format): disable redundantSelf + redundantSendable in swiftformat
Default `--self remove` strippt `self.` aus @autoclosure-Calls (Logger.info)
und Closure-Captures, was Swift-6-strict-concurrency dann als "implicit
use of self in closure" rejected. Default `redundantSendable` strippt
`Sendable` von Codable-DTOs, die über actor-Grenzen wandern müssen.

Beide Regeln aus. Zusätzlich Lauf über alle Files: harmlose Whitespace-/
Trailing-Comma-/Optional-Init-Normalisierung in 5 Files. `self.` und
`Sendable` bleiben überall erhalten. Build grün.

Hintergrund: η-0-Lauf hat das aktiv gemacht und Submit-DTOs zerschossen,
die ich dann von Hand revertieren musste. Dieser Commit verhindert die
Wiederholung in η-1+.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:37:46 +02:00

40 lines
1.5 KiB
Swift

import Foundation
import Network
import OSLog
/// Wrapper um `NWPathMonitor`. Feuert das übergebene Closure bei jedem
/// Wechsel von "kein Pfad" "Pfad da" (= Wifi/Mobil wieder verfügbar
/// nach Offline). Ein wechselnder Pfad (Wifi Mobil) feuert nicht
/// erneut wir wollen nur die Reconnect-Flanke.
///
/// Lebenszyklus liegt beim App-Root. Stop-Methode existiert, aber
/// reale App startet Watcher einmal beim Launch und lässt ihn bis
/// zum Prozess-Ende laufen.
final class ReachabilityWatcher: @unchecked Sendable {
private let monitor = NWPathMonitor()
private let queue = DispatchQueue(label: "ev.mana.zitare.reachability")
private let log = Logger(subsystem: "ev.mana.zitare", category: "reachability")
private var wasReachable: Bool?
private var onReconnect: @Sendable () -> Void = {}
func start(onReconnect: @escaping @Sendable () -> Void) {
self.onReconnect = onReconnect
monitor.pathUpdateHandler = { [weak self] path in
guard let self else { return }
let reachable = path.status == .satisfied
let prev = self.wasReachable
self.wasReachable = reachable
if prev == false, reachable {
self.log.info("Reachable again — triggering reconnect-hook")
self.onReconnect()
} else if prev == nil {
self.log.info("Initial reachability: \(reachable ? "yes" : "no", privacy: .public)")
}
}
monitor.start(queue: queue)
}
func stop() {
monitor.cancel()
}
}