101 lines
3.9 KiB
Swift
101 lines
3.9 KiB
Swift
import SwiftUI
|
|
import NucleicProtocol
|
|
|
|
struct SettingsView: View {
|
|
@EnvironmentObject var store: RemoteStore
|
|
@State private var showScanner = false
|
|
@AppStorage("nucleic.showRawEvents") private var showRaw = false
|
|
@AppStorage("nucleic.showLockEvents") private var showLockEvents = true
|
|
@AppStorage(HeartbeatSettings.shareAnonymousUsageKey) private var shareAnonymousUsage = true
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
Form {
|
|
Section("Connection") {
|
|
LabeledContent("Status", value: store.connectivity.label)
|
|
if !store.hostName.isEmpty {
|
|
LabeledContent("Mac", value: store.hostName)
|
|
}
|
|
Button("Reconnect") { store.reconnect() }
|
|
.disabled(!store.isPaired)
|
|
}
|
|
|
|
Section("This device") {
|
|
LabeledContent("Scope", value: store.grantedScope.rawValue.capitalized)
|
|
LabeledContent("Key fingerprint", value: store.deviceFingerprint)
|
|
.font(.footnote.monospaced())
|
|
}
|
|
|
|
Section {
|
|
Toggle("Show lock events", isOn: $showLockEvents)
|
|
Toggle("Show raw events", isOn: $showRaw)
|
|
} header: {
|
|
Text("Transcript")
|
|
} footer: {
|
|
Text("Raw events are unrecognized backend output, shown for debugging.")
|
|
}
|
|
|
|
Section {
|
|
Toggle("Share anonymous usage", isOn: $shareAnonymousUsage)
|
|
} header: {
|
|
Text("Privacy")
|
|
} footer: {
|
|
Text("A once-a-day anonymous ping — a random install ID, app version, iOS version, and language — so we can count active installs. No account, no IP, no content.")
|
|
}
|
|
|
|
Section {
|
|
Button {
|
|
showScanner = true
|
|
} label: {
|
|
Label("Pair with a Mac", systemImage: "qrcode.viewfinder")
|
|
}
|
|
if store.isPaired {
|
|
Button(role: .destructive) { store.unpair() } label: {
|
|
Label("Unpair this device", systemImage: "minus.circle")
|
|
}
|
|
}
|
|
} footer: {
|
|
Text("Code and diffs are end-to-end encrypted. A relay (later) can't read them.")
|
|
}
|
|
}
|
|
.navigationTitle("Settings")
|
|
.sheet(isPresented: $showScanner) {
|
|
PairingScannerView { payload in
|
|
showScanner = false
|
|
store.pair(with: payload)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Shown before pairing (UX_IOS §7): explain the flow and launch the scanner.
|
|
struct PairingIntroView: View {
|
|
@EnvironmentObject var store: RemoteStore
|
|
@State private var showScanner = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: 24) {
|
|
Image(systemName: "qrcode.viewfinder").font(.system(size: 72)).foregroundStyle(.tint)
|
|
Text("Pair with your Mac").font(.title2.weight(.semibold))
|
|
Text("On your Mac, open Nucleic ▸ Settings ▸ Add iPhone to show a QR code, then scan it here.")
|
|
.multilineTextAlignment(.center)
|
|
.foregroundStyle(.secondary)
|
|
.padding(.horizontal, 32)
|
|
Button {
|
|
showScanner = true
|
|
} label: {
|
|
Label("Scan QR code", systemImage: "camera").font(.headline).padding(.horizontal)
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
}
|
|
.padding()
|
|
.sheet(isPresented: $showScanner) {
|
|
PairingScannerView { payload in
|
|
showScanner = false
|
|
store.pair(with: payload)
|
|
}
|
|
}
|
|
}
|
|
}
|