Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 8165ec5baec56b34656ee12ee5a59b6bd91d7b2a Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com> Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com> Reviewed-by: @mbelinky
114 lines
4.7 KiB
Swift
114 lines
4.7 KiB
Swift
import SwiftUI
|
||
|
||
struct GatewayQuickSetupSheet: View {
|
||
@Environment(NodeAppModel.self) private var appModel
|
||
@Environment(GatewayConnectionController.self) private var gatewayController
|
||
@Environment(\.dismiss) private var dismiss
|
||
|
||
@AppStorage("onboarding.quickSetupDismissed") private var quickSetupDismissed: Bool = false
|
||
@State private var connecting: Bool = false
|
||
@State private var connectError: String?
|
||
|
||
var body: some View {
|
||
NavigationStack {
|
||
VStack(alignment: .leading, spacing: 16) {
|
||
Text("Connect to a Gateway?")
|
||
.font(.title2.bold())
|
||
|
||
if let candidate = self.bestCandidate {
|
||
VStack(alignment: .leading, spacing: 6) {
|
||
Text(verbatim: candidate.name)
|
||
.font(.headline)
|
||
Text(verbatim: candidate.debugID)
|
||
.font(.footnote)
|
||
.foregroundStyle(.secondary)
|
||
|
||
VStack(alignment: .leading, spacing: 2) {
|
||
// Use verbatim strings so Bonjour-provided values can't be interpreted as
|
||
// localized format strings (which can crash with Objective-C exceptions).
|
||
Text(verbatim: "Discovery: \(self.gatewayController.discoveryStatusText)")
|
||
Text(verbatim: "Status: \(self.appModel.gatewayStatusText)")
|
||
Text(verbatim: "Node: \(self.appModel.nodeStatusText)")
|
||
Text(verbatim: "Operator: \(self.appModel.operatorStatusText)")
|
||
}
|
||
.font(.footnote)
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
.padding(12)
|
||
.background(.thinMaterial)
|
||
.clipShape(RoundedRectangle(cornerRadius: 14))
|
||
|
||
Button {
|
||
self.connectError = nil
|
||
self.connecting = true
|
||
Task {
|
||
let err = await self.gatewayController.connectWithDiagnostics(candidate)
|
||
await MainActor.run {
|
||
self.connecting = false
|
||
self.connectError = err
|
||
// If we kicked off a connect, leave the sheet up so the user can see status evolve.
|
||
}
|
||
}
|
||
} label: {
|
||
Group {
|
||
if self.connecting {
|
||
HStack(spacing: 8) {
|
||
ProgressView().progressViewStyle(.circular)
|
||
Text("Connecting…")
|
||
}
|
||
} else {
|
||
Text("Connect")
|
||
}
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
}
|
||
.buttonStyle(.borderedProminent)
|
||
.disabled(self.connecting)
|
||
|
||
if let connectError {
|
||
Text(connectError)
|
||
.font(.footnote)
|
||
.foregroundStyle(.secondary)
|
||
.textSelection(.enabled)
|
||
}
|
||
|
||
Button {
|
||
self.dismiss()
|
||
} label: {
|
||
Text("Not now")
|
||
.frame(maxWidth: .infinity)
|
||
}
|
||
.buttonStyle(.bordered)
|
||
.disabled(self.connecting)
|
||
|
||
Toggle("Don’t show this again", isOn: self.$quickSetupDismissed)
|
||
.padding(.top, 4)
|
||
} else {
|
||
Text("No gateways found yet. Make sure your gateway is running and Bonjour discovery is enabled.")
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
|
||
Spacer()
|
||
}
|
||
.padding()
|
||
.navigationTitle("Quick Setup")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
.toolbar {
|
||
ToolbarItem(placement: .topBarTrailing) {
|
||
Button {
|
||
self.quickSetupDismissed = true
|
||
self.dismiss()
|
||
} label: {
|
||
Text("Close")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private var bestCandidate: GatewayDiscoveryModel.DiscoveredGateway? {
|
||
// Prefer whatever discovery says is first; the list is already name-sorted.
|
||
self.gatewayController.gateways.first
|
||
}
|
||
}
|