import SwiftUI struct SettingsView: View { @Bindable var settings: SettingsStore var body: some View { Form { Section("Backend") { TextField("Backend URL", text: $settings.backendURLString) .onSubmit { settings.saveBackendURL() } .platformCredentialField() Button("Apply Backend URL") { settings.saveBackendURL() } } Section("Session") { if let user = settings.currentUser { LabeledContent("Signed in as", value: user.displayName) LabeledContent("Username", value: user.username) Button("Sign out", role: .destructive) { Task { await settings.signOut() } } } else { Picker("Mode", selection: $settings.authMode) { ForEach(SettingsStore.AuthMode.allCases) { mode in Text(mode == .login ? "Log in" : "Register").tag(mode) } } .pickerStyle(.segmented) if settings.authMode == .register { TextField("Display name", text: $settings.displayName) } TextField("Username", text: $settings.username) .platformCredentialField() SecureField("Password", text: $settings.password) Button(settings.authMode == .login ? "Authenticate" : "Create account") { Task { await settings.authenticate() } } .disabled(settings.isBusy) Button("Use access key") { Task { await settings.signInWithAccessKey() } } .disabled(settings.isBusy) } } Section("Access Keys") { if settings.currentUser == nil { Text("Sign in before registering or listing access keys.") .foregroundStyle(.secondary) } else { TextField("New access key label", text: $settings.accessKeyLabel) Button("Register access key") { Task { await settings.registerAccessKey() } } .disabled(settings.isBusy) if settings.accessKeys.isEmpty { Text("No access keys registered yet.") .foregroundStyle(.secondary) } else { ForEach(settings.accessKeys) { key in VStack(alignment: .leading, spacing: 4) { Text(key.label) .font(.headline) Text("Device: \(key.deviceType)\(key.backedUp ? " / backed up" : "")") .font(.subheadline) .foregroundStyle(.secondary) Text("Transports: \(key.transports.isEmpty ? "unspecified" : key.transports.joined(separator: ", "))") .font(.footnote) .foregroundStyle(.secondary) } .padding(.vertical, 4) } } } } if let infoMessage = settings.infoMessage { Section("Status") { Text(infoMessage) .foregroundStyle(.secondary) } } if let errorMessage = settings.errorMessage { Section("Error") { Text(errorMessage) .foregroundStyle(.red) } } } .formStyle(.grouped) .padding() .frame(minWidth: 420, minHeight: 520) } } private extension View { @ViewBuilder func platformCredentialField() -> some View { #if os(iOS) textInputAutocapitalization(.never) .autocorrectionDisabled() #else self #endif } }