Show connection progress at app startup instead of flashing screens

This commit is contained in:
Ian Gulliver
2026-10-20 14:20:35 -07:00
parent da7f952855
commit a2571763b4
3 changed files with 80 additions and 26 deletions
+45 -11
View File
@@ -130,14 +130,15 @@ final class Tailnet {
private(set) var state = "Starting"
private(set) var authURL: URL?
private(set) var service: TailnetInfo?
private(set) var searched = false
@ObservationIgnored private var servers: [URL] = []
var running: Bool {
state == "Running"
}
var signedIn: Bool {
running && service?.state != "NeedsLogin"
var needsLogin: Bool {
state == "NeedsLogin" || state == "NeedsMachineAuth" || service?.state == "NeedsLogin"
}
private init() {
@@ -181,19 +182,52 @@ final class Tailnet {
private func discover() async {
while true {
if running {
for origin in servers where !Servers.shared.origins.contains(origin.absoluteString) {
let api = API(origin: origin)
if (try? await api.client.getStatus().ok) != nil {
log.notice("found \(origin.absoluteString, privacy: .public) on the tailnet")
Servers.shared.add(origin)
}
api.session.finishTasksAndInvalidate()
}
guard running else {
try? await Task.sleep(for: .milliseconds(500))
continue
}
let candidates = servers.filter { !Servers.shared.origins.contains($0.absoluteString) }
let found = await withTaskGroup(of: URL?.self) { group in
for origin in candidates {
group.addTask {
await Self.probe(origin) ? origin : nil
}
}
var found: [URL] = []
for await origin in group {
if let origin {
found.append(origin)
}
}
return found
}
for origin in found {
log.notice("found \(origin.absoluteString, privacy: .public) on the tailnet")
Servers.shared.add(origin)
}
searched = true
try? await Task.sleep(for: .seconds(10))
}
}
private nonisolated static func probe(_ origin: URL) async -> Bool {
let api = API(origin: origin)
defer {
api.session.invalidateAndCancel()
}
return await withTaskGroup(of: Bool.self) { group in
group.addTask {
(try? await api.client.getStatus().ok) != nil
}
group.addTask {
try? await Task.sleep(for: .seconds(5))
return false
}
let ok = await group.next() ?? false
group.cancelAll()
return ok
}
}
}
struct TailnetLoginView: View {