import SwiftUI import ProxyCore import GRDB struct DNSSpoofingView: View { @State private var isEnabled = IPCManager.shared.isDNSSpoofingEnabled @State private var rules: [DNSSpoofRule] = [] @State private var showAddRule = false @State private var observation: AnyDatabaseCancellable? private let rulesRepo = RulesRepository() var body: some View { List { Section { ToggleHeaderView( title: "DNS Spoofing", description: "Redirect domain resolution to a different target. Useful for routing production domains to development servers.", isEnabled: $isEnabled ) .onChange(of: isEnabled) { _, newValue in IPCManager.shared.isDNSSpoofingEnabled = newValue IPCManager.shared.post(.configurationChanged) } } .listRowInsets(EdgeInsets()) Section("Rules") { if rules.isEmpty { EmptyStateView( icon: "network", title: "No DNS Spoofing Rules", subtitle: "Tap + to create a new rule." ) } else { ForEach(rules) { rule in VStack(alignment: .leading, spacing: 4) { HStack { Text(rule.sourceDomain) .font(.subheadline) Image(systemName: "arrow.right") .font(.caption) .foregroundStyle(.secondary) Text(rule.targetDomain) .font(.subheadline) .foregroundStyle(.blue) } } } .onDelete { indexSet in for index in indexSet { if let id = rules[index].id { try? rulesRepo.deleteDNSSpoofRule(id: id) } } } } } } .navigationTitle("DNS Spoofing") .toolbar { ToolbarItem(placement: .topBarTrailing) { Button { showAddRule = true } label: { Image(systemName: "plus") } } } .sheet(isPresented: $showAddRule) { NavigationStack { Form { // TODO: Add DNS spoof rule creation form Text("DNS Spoofing rule creation") } .navigationTitle("New DNS Rule") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { showAddRule = false } } } } } .task { observation = rulesRepo.observeDNSSpoofRules() .start(in: DatabaseManager.shared.dbPool) { error in print("DNS Spoof observation error: \(error)") } onChange: { newRules in rules = newRules } } } }