Issue #3: First implementation of a DoH configuration setting.
This commit is contained in:
parent
c25505dc5f
commit
822202e37d
2 changed files with 84 additions and 6 deletions
|
|
@ -39,7 +39,6 @@ struct HomeView: View {
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
private var viewModel: ViewModel
|
private var viewModel: ViewModel
|
||||||
|
|
||||||
@State private var isEnabled = false
|
|
||||||
@State private var serviceStatus: ServiceStatus = .operational
|
@State private var serviceStatus: ServiceStatus = .operational
|
||||||
|
|
||||||
private let falsePositiveURL = URL(string: "https://www.sr2.uk/contact")!
|
private let falsePositiveURL = URL(string: "https://www.sr2.uk/contact")!
|
||||||
|
|
@ -58,14 +57,14 @@ struct HomeView: View {
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
Text("DNS Protection")
|
Text("DNS Protection")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Text(isEnabled ? "Active" : "Inactive")
|
Text(viewModel.isDnsEnabled ? "Active" : "Inactive")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.foregroundStyle(isEnabled ? .green : .secondary)
|
.foregroundStyle(viewModel.isDnsEnabled ? .green : .secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Toggle("", isOn: $isEnabled)
|
Toggle("", isOn: $viewModel.isDnsEnabled)
|
||||||
.labelsHidden()
|
.labelsHidden()
|
||||||
.tint(.green)
|
.tint(.green)
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +94,7 @@ struct HomeView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status section
|
// Status section
|
||||||
if isEnabled {
|
if viewModel.isDnsEnabled {
|
||||||
Section {
|
Section {
|
||||||
HStack {
|
HStack {
|
||||||
Label("Status", systemImage: "checkmark.circle.fill")
|
Label("Status", systemImage: "checkmark.circle.fill")
|
||||||
|
|
@ -213,7 +212,7 @@ struct HomeView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("SR2® Cloud DNS")
|
.navigationTitle("SR2® Cloud DNS")
|
||||||
.animation(.default, value: isEnabled)
|
.animation(.default, value: viewModel.isDnsEnabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,89 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Combine
|
import Combine
|
||||||
|
import NetworkExtension
|
||||||
|
import OSLog
|
||||||
|
|
||||||
class ViewModel: NSObject, ObservableObject {
|
class ViewModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
|
// TODO: Store this in UserDefaults
|
||||||
@Published
|
@Published
|
||||||
var blocklist: BlocklistOption = .secure
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue