import SwiftUI import VoiceCatCore struct ServerIdentityView: View { @Environment(AppState.self) private var appState @Environment(\.dismiss) private var dismiss let identity: PendingIdentity var body: some View { NavigationStack { ScrollView { VStack(alignment: .leading, spacing: 16) { if identity.tofuStatus == .mismatch { Label("Server Identity Mismatch", systemImage: "exclamationmark.triangle.fill") .font(.headline) .foregroundStyle(.red) .accessibilityLabel("Warning: server identity mismatch") Text("The server's identity has changed since your last connection. This may indicate a man-in-the-middle attack, or that the server was reinstalled. Do NOT accept unless you know why the identity changed.") .foregroundStyle(.primary) } else { Label("New Server Identity", systemImage: "lock.badge.questionmark") .font(.headline) .accessibilityLabel("New server identity") Text("This is the first time you are connecting to this server. Verify the fingerprint below with the server administrator before accepting.") .foregroundStyle(.primary) } Divider() VStack(alignment: .leading, spacing: 4) { Text("Server fingerprint") .font(.caption) .foregroundStyle(.secondary) Text(identity.displayText.isEmpty ? "(not available)" : identity.displayText) .font(.system(.caption, design: .monospaced)) .textSelection(.enabled) .accessibilityLabel("Server fingerprint: \(identity.displayText)") } .padding() .background(Color(.secondarySystemBackground), in: RoundedRectangle(cornerRadius: 8)) Spacer(minLength: 24) VStack(spacing: 12) { Button { dismiss() appState.confirmServerIdentity(accept: true) } label: { Text("Accept") .frame(maxWidth: .infinity) } .buttonStyle(.borderedProminent) .tint(identity.tofuStatus == .mismatch ? .orange : .blue) .accessibilityLabel("Accept server identity and continue") Button(role: .destructive) { dismiss() appState.confirmServerIdentity(accept: false) } label: { Text("Reject — Disconnect") .frame(maxWidth: .infinity) } .buttonStyle(.bordered) .accessibilityLabel("Reject server identity and disconnect") } } .padding() } .navigationTitle("Server Identity") .navigationBarTitleDisplayMode(.inline) } .interactiveDismissDisabled() } }