Issue #3: First implementation of a DoH configuration setting.

This commit is contained in:
Benjamin Erhart 2026-04-14 18:57:37 +02:00
parent c25505dc5f
commit 822202e37d
2 changed files with 84 additions and 6 deletions

View file

@ -39,7 +39,6 @@ struct HomeView: View {
@EnvironmentObject
private var viewModel: ViewModel
@State private var isEnabled = false
@State private var serviceStatus: ServiceStatus = .operational
private let falsePositiveURL = URL(string: "https://www.sr2.uk/contact")!
@ -58,14 +57,14 @@ struct HomeView: View {
VStack(alignment: .leading, spacing: 4) {
Text("DNS Protection")
.font(.headline)
Text(isEnabled ? "Active" : "Inactive")
Text(viewModel.isDnsEnabled ? "Active" : "Inactive")
.font(.caption)
.foregroundStyle(isEnabled ? .green : .secondary)
.foregroundStyle(viewModel.isDnsEnabled ? .green : .secondary)
}
Spacer()
Toggle("", isOn: $isEnabled)
Toggle("", isOn: $viewModel.isDnsEnabled)
.labelsHidden()
.tint(.green)
}
@ -95,7 +94,7 @@ struct HomeView: View {
}
// Status section
if isEnabled {
if viewModel.isDnsEnabled {
Section {
HStack {
Label("Status", systemImage: "checkmark.circle.fill")
@ -213,7 +212,7 @@ struct HomeView: View {
}
}
.navigationTitle("SR2® Cloud DNS")
.animation(.default, value: isEnabled)
.animation(.default, value: viewModel.isDnsEnabled)
}
}
}

View file

@ -7,10 +7,89 @@
import Foundation
import Combine
import NetworkExtension
import OSLog
class ViewModel: NSObject, ObservableObject {
// TODO: Store this in UserDefaults
@Published
var blocklist: BlocklistOption = .secure
// TODO: Store this in UserDefaults
@Published
var isDnsEnabled = false {
didSet {
if !isProgrammaticChange {
toggleDns()
}
else {
// Reset, so next one is recognized as coming from the user again.
isProgrammaticChange = false
}
}
}
private var isProgrammaticChange = false
private let manager = NEDNSSettingsManager.shared()
private let log = Logger(subsystem: String(describing: ViewModel.self), category: String(describing: ViewModel.self))
func toggleDns() {
Task {
if isDnsEnabled {
do {
try await manager.loadFromPreferences()
}
catch {
log.error("Error loading preferences: \(error)")
delayedToggle(false)
return
}
let settings = NEDNSOverHTTPSSettings(servers: [blocklist.ipv4, blocklist.ipv6])
settings.serverURL = URL(string: "https://\(blocklist.server)")
settings.matchDomains = [""]
manager.dnsSettings = settings
manager.localizedDescription = blocklist.description
do {
try await manager.saveToPreferences()
}
catch {
log.error("Error storing preferences: \(error)")
delayedToggle(false)
}
}
else {
do {
try await manager.removeFromPreferences()
}
catch {
log.error("Error removing preferences: \(error)")
delayedToggle(true)
}
}
}
}
private func delayedToggle(_ enabled: Bool) {
Task {
try? await Task.sleep(nanoseconds: 500_000_000)
await MainActor.run {
isProgrammaticChange = true
isDnsEnabled = enabled
}
}
}
}