Show connection progress at app startup instead of flashing screens
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user