Show startup as one step checklist and re-check tools on the Server tab
This commit is contained in:
@@ -3,9 +3,6 @@ import Network
|
||||
import Observation
|
||||
import SwiftUI
|
||||
import TailscaleKit
|
||||
#if os(iOS)
|
||||
import SafariServices
|
||||
#endif
|
||||
|
||||
func slug(_ text: String) -> String {
|
||||
var out = ""
|
||||
@@ -242,102 +239,3 @@ final class Tailnet {
|
||||
}
|
||||
}
|
||||
|
||||
struct TailnetLoginView: View {
|
||||
var body: some View {
|
||||
let tailnet = Tailnet.shared
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text("Sign in to Tailscale")
|
||||
.font(Fonts.font(17, weight: 700))
|
||||
Text("byre reaches its servers through Tailscale. Sign each of these nodes in to the tailnet your byre servers are on.")
|
||||
.foregroundStyle(Palette.muted)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom, 4)
|
||||
NodeLoginRow(hostname: tailnetNode.hostname, role: "this app", state: tailnet.state, authURL: tailnet.authURL)
|
||||
if let service = tailnet.service {
|
||||
NodeLoginRow(hostname: service.hostname, role: "this Mac's server", state: service.state, authURL: URL(string: service.authUrl))
|
||||
}
|
||||
}
|
||||
.padding(20)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(Palette.raised, in: RoundedRectangle(cornerRadius: 10))
|
||||
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Palette.border))
|
||||
.frame(maxWidth: 460)
|
||||
.padding(16)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.onAppear {
|
||||
Tailnet.shared.serviceWatchers += 1
|
||||
}
|
||||
.onDisappear {
|
||||
Tailnet.shared.serviceWatchers -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct NodeLoginRow: View {
|
||||
let hostname: String
|
||||
let role: String
|
||||
let state: String
|
||||
let authURL: URL?
|
||||
@State private var signingIn = false
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center, spacing: 12) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 8) {
|
||||
Text(hostname).font(Fonts.font(13, weight: 700))
|
||||
Text(role).foregroundStyle(Palette.muted)
|
||||
}
|
||||
if state == "Running" {
|
||||
Text("Signed in").foregroundStyle(Palette.ok)
|
||||
} else {
|
||||
Text(authURL == nil ? "Waiting for Tailscale (\(state))…" : "Waiting for the sign-in (\(state))…")
|
||||
.font(Fonts.font(12))
|
||||
.foregroundStyle(Palette.muted)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
if state != "Running" {
|
||||
Button("Sign in") {
|
||||
#if os(macOS)
|
||||
if let authURL {
|
||||
openExternal(authURL)
|
||||
}
|
||||
#else
|
||||
signingIn = true
|
||||
#endif
|
||||
}
|
||||
.buttonStyle(WebButtonStyle(primary: true))
|
||||
.disabled(authURL == nil)
|
||||
.fixedSize()
|
||||
}
|
||||
}
|
||||
.padding(12)
|
||||
.background(Palette.bg, in: RoundedRectangle(cornerRadius: 8))
|
||||
.overlay(RoundedRectangle(cornerRadius: 8).stroke(Palette.border))
|
||||
#if os(iOS)
|
||||
.sheet(isPresented: $signingIn) {
|
||||
if let authURL {
|
||||
SafariView(url: authURL)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
}
|
||||
.onChange(of: state) {
|
||||
if state == "Running" {
|
||||
signingIn = false
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
private struct SafariView: UIViewControllerRepresentable {
|
||||
let url: URL
|
||||
|
||||
func makeUIViewController(context: Context) -> SFSafariViewController {
|
||||
SFSafariViewController(url: url)
|
||||
}
|
||||
|
||||
func updateUIViewController(_ controller: SFSafariViewController, context: Context) {}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user