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/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/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 + } + } +} 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 4ec1ada..775184e 100644 --- a/dns/ViewModel.swift +++ b/dns/ViewModel.swift @@ -12,24 +12,27 @@ 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 { + var blocklist: BlocklistOption = .secure { didSet { - if !isProgrammaticChange { + Settings.blocklist = blocklist + + if isDnsEnabled { toggleDns() } else { - // Reset, so next one is recognized as coming from the user again. isProgrammaticChange = false } } } + @Published + var isDnsEnabled = false { + didSet { + toggleDns() + } + } + private var isProgrammaticChange = false @@ -38,26 +41,51 @@ 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. + isProgrammaticChange = false + + return + } + 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 {