Files
Sybil-2/ios/Packages/Sybil/Sources/Sybil/SybilConnectionView.swift
2026-05-02 16:23:00 -07:00

123 lines
4.6 KiB
Swift

import Observation
import SwiftUI
struct SybilConnectionView: View {
@Bindable var viewModel: SybilViewModel
var body: some View {
@Bindable var settings = viewModel.settings
VStack(spacing: 20) {
HStack {
SybilWordmark(size: 34)
Spacer()
}
HStack(alignment: .top, spacing: 12) {
Image(systemName: "shield.lefthalf.filled")
.font(.system(size: 20, weight: .semibold))
.foregroundStyle(SybilTheme.accent)
.frame(width: 34, height: 34)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(SybilTheme.accent.opacity(0.12))
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(SybilTheme.accent.opacity(0.28), lineWidth: 1)
)
)
VStack(alignment: .leading, spacing: 4) {
Text("Connect to Sybil")
.font(.sybil(.title3, weight: .semibold))
.foregroundStyle(SybilTheme.text)
Text("Point the app at your backend and sign in with ADMIN_TOKEN if token mode is enabled.")
.font(.sybil(.callout))
.foregroundStyle(SybilTheme.textMuted)
.fixedSize(horizontal: false, vertical: true)
}
}
VStack(alignment: .leading, spacing: 10) {
Text("API URL")
.font(.sybil(.caption, weight: .semibold))
.foregroundStyle(SybilTheme.textMuted)
TextField("http://127.0.0.1:8787", text: $settings.apiBaseURL)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.keyboardType(.URL)
.padding(12)
.background(
RoundedRectangle(cornerRadius: 12)
.fill(SybilTheme.surface.opacity(0.78))
)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(SybilTheme.border.opacity(0.88), lineWidth: 1)
)
Text("Admin Token")
.font(.sybil(.caption, weight: .semibold))
.foregroundStyle(SybilTheme.textMuted)
SecureField("ADMIN_TOKEN (optional in open mode)", text: $settings.adminToken)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.padding(12)
.background(
RoundedRectangle(cornerRadius: 12)
.fill(SybilTheme.surface.opacity(0.78))
)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(SybilTheme.border.opacity(0.88), lineWidth: 1)
)
}
VStack(spacing: 10) {
Button {
Task {
await viewModel.refreshAfterSettingsChange()
}
} label: {
Text("Connect")
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.tint(SybilTheme.primarySoft)
Button {
settings.adminToken = ""
Task {
await viewModel.refreshAfterSettingsChange()
}
} label: {
Text("Continue Without Token")
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
.tint(SybilTheme.textMuted)
}
if let authError = viewModel.authError {
Text(authError)
.font(.sybil(.footnote))
.foregroundStyle(SybilTheme.danger)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.padding(20)
.frame(maxWidth: 520)
.background(
RoundedRectangle(cornerRadius: 20)
.fill(SybilTheme.panelGradient)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(SybilTheme.border.opacity(0.9), lineWidth: 1)
)
)
}
}