From 6ca509f7fb105534dd8db2e44481a29d2f66f79c Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 15 Apr 2026 12:51:00 +0200 Subject: [PATCH 1/5] Added support for iOS 15. --- dns.xcodeproj/project.pbxproj | 4 ++-- dns/HomeView.swift | 2 +- dns/NavigationCompat.swift | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 dns/NavigationCompat.swift diff --git a/dns.xcodeproj/project.pbxproj b/dns.xcodeproj/project.pbxproj index 1e2384a..8fdd3ee 100644 --- a/dns.xcodeproj/project.pbxproj +++ b/dns.xcodeproj/project.pbxproj @@ -269,7 +269,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -305,7 +305,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/dns/HomeView.swift b/dns/HomeView.swift index 765a48c..36b4b63 100644 --- a/dns/HomeView.swift +++ b/dns/HomeView.swift @@ -48,7 +48,7 @@ struct HomeView: View { private let privacyPolicyURL = URL(string: "https://www.sr2.uk/privacy")! var body: some View { - NavigationStack { + NavigationCompat { List { // Main toggle section diff --git a/dns/NavigationCompat.swift b/dns/NavigationCompat.swift new file mode 100644 index 0000000..494bb6a --- /dev/null +++ b/dns/NavigationCompat.swift @@ -0,0 +1,32 @@ +// +// NavigationCompat.swift +// dns +// +// Created by Benjamin Erhart on 15.04.26. +// +import SwiftUI + +struct NavigationCompat: View { + + let content: () -> Content + + init(@ViewBuilder content: @escaping () -> Content) { + self.content = content + } + + var body: some View { + if #available(iOS 16.0, macOS 13.0, *) { + NavigationStack { + content() + } + } + else { + NavigationView { + content() + } +#if !os(macOS) + .navigationViewStyle(StackNavigationViewStyle()) +#endif + } + } +} From 807176f0b563d9a494ce8a51d1c824cb920bd367 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 15 Apr 2026 13:38:25 +0200 Subject: [PATCH 2/5] Issue #3: Fixed DoH server URL. Moved settings creation to BlocklistOption. --- dns/BlocklistOption.swift | 9 +++++++++ dns/ViewModel.swift | 18 +----------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/dns/BlocklistOption.swift b/dns/BlocklistOption.swift index 649a286..38e582d 100644 --- a/dns/BlocklistOption.swift +++ b/dns/BlocklistOption.swift @@ -6,6 +6,7 @@ // import Foundation +import NetworkExtension enum BlocklistOption: String, CaseIterable, Identifiable { case secure = "Secure" @@ -66,4 +67,12 @@ enum BlocklistOption: String, CaseIterable, Identifiable { return "2001:db8::1" } } + + var settings: NEDNSOverHTTPSSettings { + let settings = NEDNSOverHTTPSSettings(servers: [ipv4, ipv6]) + settings.serverURL = URL(string: "https://\(server)/dns-query") + settings.matchDomains = [""] + + return settings + } } diff --git a/dns/ViewModel.swift b/dns/ViewModel.swift index 4ec1ada..c39d5b3 100644 --- a/dns/ViewModel.swift +++ b/dns/ViewModel.swift @@ -41,23 +41,7 @@ class ViewModel: NSObject, ObservableObject { 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.dnsSettings = blocklist.settings manager.localizedDescription = blocklist.description do { From 6cbad66a8768536b0b153563095b1267689755b1 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 15 Apr 2026 13:40:29 +0200 Subject: [PATCH 3/5] Issue #3: Added Settings class to store selected BlocklistOption. Update system DoH settings, when user selects another blocklist. --- dns/Settings.swift | 24 ++++++++++++++++++++++++ dns/ViewModel.swift | 25 +++++++++++++++---------- 2 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 dns/Settings.swift diff --git a/dns/Settings.swift b/dns/Settings.swift new file mode 100644 index 0000000..1d4a914 --- /dev/null +++ b/dns/Settings.swift @@ -0,0 +1,24 @@ +// +// Settings.swift +// dns +// +// Created by Benjamin Erhart on 15.04.26. +// + +import Foundation + +class Settings { + + private static let blocklistKey = "blocklist" + + private static let defaults = UserDefaults.standard + + class var blocklist: BlocklistOption { + get { + BlocklistOption(rawValue: defaults.string(forKey: blocklistKey) ?? BlocklistOption.secure.rawValue) ?? .secure + } + set { + defaults.set(newValue.rawValue, forKey: blocklistKey) + } + } +} diff --git a/dns/ViewModel.swift b/dns/ViewModel.swift index c39d5b3..72497bd 100644 --- a/dns/ViewModel.swift +++ b/dns/ViewModel.swift @@ -12,21 +12,19 @@ import OSLog class ViewModel: NSObject, ObservableObject { - // TODO: Store this in UserDefaults @Published - var blocklist: BlocklistOption = .secure + var blocklist: BlocklistOption = .secure { + didSet { + Settings.blocklist = blocklist + + toggleDns() + } + } - // 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 - } + toggleDns() } } @@ -39,6 +37,13 @@ class ViewModel: NSObject, ObservableObject { func toggleDns() { + guard !isProgrammaticChange else { + // Reset, so next one is recognized as coming from the user again. + isProgrammaticChange = false + + return + } + Task { if isDnsEnabled { manager.dnsSettings = blocklist.settings From 8c1716de77f9285672ec2b28ae86b366b3049d4f Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 15 Apr 2026 13:41:38 +0200 Subject: [PATCH 4/5] Issue #3: Load selected blocklist from Settings. Load configured DoH from system. Update UI accordingly. --- dns/ViewModel.swift | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/dns/ViewModel.swift b/dns/ViewModel.swift index 72497bd..c5f8b3b 100644 --- a/dns/ViewModel.swift +++ b/dns/ViewModel.swift @@ -36,6 +36,40 @@ class ViewModel: NSObject, ObservableObject { private let log = Logger(subsystem: String(describing: ViewModel.self), category: String(describing: ViewModel.self)) + override init() { + super.init() + + isProgrammaticChange = true + blocklist = Settings.blocklist + + Task { + do { + try await manager.loadFromPreferences() + } + catch { + log.error("Error loading preferences: \(error)") + + return + } + + if let settings = manager.dnsSettings { + for dnsServer in BlocklistOption.allCases { + if settings.servers.contains(dnsServer.ipv4) { + await MainActor.run { + isProgrammaticChange = true + blocklist = dnsServer + isProgrammaticChange = true + isDnsEnabled = true + } + + break + } + } + } + } + } + + func toggleDns() { guard !isProgrammaticChange else { // Reset, so next one is recognized as coming from the user again. From 603a23a1a8a3a969b607e48db1bf8bd99bdfb5b8 Mon Sep 17 00:00:00 2001 From: Benjamin Erhart Date: Wed, 15 Apr 2026 13:47:36 +0200 Subject: [PATCH 5/5] Issue #3: Only change system setting immediately, if isDnsEnabled. --- dns/ViewModel.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dns/ViewModel.swift b/dns/ViewModel.swift index c5f8b3b..775184e 100644 --- a/dns/ViewModel.swift +++ b/dns/ViewModel.swift @@ -17,7 +17,12 @@ class ViewModel: NSObject, ObservableObject { didSet { Settings.blocklist = blocklist - toggleDns() + if isDnsEnabled { + toggleDns() + } + else { + isProgrammaticChange = false + } } }