mirror of
https://github.com/kkebo/DNSecure.git
synced 2026-03-11 08:54:36 +00:00
Fix the issue that saving configuration doesn't work
This commit is contained in:
parent
3047ff690d
commit
7366d3c588
4 changed files with 251 additions and 169 deletions
|
|
@ -26,6 +26,8 @@
|
|||
894958AD2548405E009691D5 /* RuleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 894958AC2548405E009691D5 /* RuleView.swift */; };
|
||||
8963FDFB251DF1BC00E3DFE7 /* Bundle+displayName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8963FDFA251DF1BC00E3DFE7 /* Bundle+displayName.swift */; };
|
||||
8986CDCF251D9B3400D947CD /* Resolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8986CDCE251D9B3400D947CD /* Resolver.swift */; };
|
||||
8998041628DCDED800C8B421 /* DoTSections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8998041528DCDED800C8B421 /* DoTSections.swift */; };
|
||||
8998041828DCDEEF00C8B421 /* DoHSections.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8998041728DCDEEF00C8B421 /* DoHSections.swift */; };
|
||||
89CB922125209DD100B6983C /* HowToActivateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89CB922025209DD100B6983C /* HowToActivateView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
|
@ -74,6 +76,8 @@
|
|||
894958AC2548405E009691D5 /* RuleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleView.swift; sourceTree = "<group>"; };
|
||||
8963FDFA251DF1BC00E3DFE7 /* Bundle+displayName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+displayName.swift"; sourceTree = "<group>"; };
|
||||
8986CDCE251D9B3400D947CD /* Resolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Resolver.swift; sourceTree = "<group>"; };
|
||||
8998041528DCDED800C8B421 /* DoTSections.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoTSections.swift; sourceTree = "<group>"; };
|
||||
8998041728DCDEEF00C8B421 /* DoHSections.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoHSections.swift; sourceTree = "<group>"; };
|
||||
89CB922025209DD100B6983C /* HowToActivateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HowToActivateView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
|
@ -110,6 +114,8 @@
|
|||
89CB922025209DD100B6983C /* HowToActivateView.swift */,
|
||||
890B80D4251DC3A20046BAA0 /* DetailView.swift */,
|
||||
894958AC2548405E009691D5 /* RuleView.swift */,
|
||||
8998041528DCDED800C8B421 /* DoTSections.swift */,
|
||||
8998041728DCDEEF00C8B421 /* DoHSections.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -346,9 +352,11 @@
|
|||
893AA85D258F997A0060B022 /* NEOnDemandRuleInterfaceType+Codable.swift in Sources */,
|
||||
8940023E24ACBD2700EBE74B /* ContentView.swift in Sources */,
|
||||
894958AD2548405E009691D5 /* RuleView.swift in Sources */,
|
||||
8998041828DCDEEF00C8B421 /* DoHSections.swift in Sources */,
|
||||
890B80DF251DC6B50046BAA0 /* Presets.swift in Sources */,
|
||||
893AA858258F996F0060B022 /* NEOnDemandRuleInterfaceType+CustomStringConvertible.swift in Sources */,
|
||||
8940023C24ACBD2700EBE74B /* DNSecureApp.swift in Sources */,
|
||||
8998041628DCDED800C8B421 /* DoTSections.swift in Sources */,
|
||||
893AA862258F998C0060B022 /* NEOnDemandRuleInterfaceType+ssidIsUsed.swift in Sources */,
|
||||
893AA867258F99990060B022 /* NEOnDemandRuleAction+CaseIterable.swift in Sources */,
|
||||
893AA86C258F99A10060B022 /* NEOnDemandRuleAction+CustomStringConvertible.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -7,17 +7,9 @@
|
|||
|
||||
import SwiftUI
|
||||
|
||||
private enum FocusedField {
|
||||
case dotAddress
|
||||
case dotServerName
|
||||
case dohAddress
|
||||
case dohServerURL
|
||||
}
|
||||
|
||||
struct DetailView {
|
||||
@Binding var server: Resolver
|
||||
@Binding var isOn: Bool
|
||||
@FocusState private var focusedField: FocusedField?
|
||||
|
||||
private func binding(for rule: OnDemandRule) -> Binding<OnDemandRule> {
|
||||
guard let index = self.server.onDemandRules.firstIndex(of: rule) else {
|
||||
|
|
@ -68,168 +60,9 @@ extension DetailView: View {
|
|||
@ViewBuilder private var serverConfigurationSections: some View {
|
||||
switch self.server.configuration {
|
||||
case .dnsOverTLS(let configuration):
|
||||
self.dnsOverTLSSections(configuration)
|
||||
DoTSections(server: self.$server, configuration: configuration)
|
||||
case .dnsOverHTTPS(let configuration):
|
||||
self.dnsOverHTTPSSections(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func dnsOverTLSSections(
|
||||
_ configuration: DoTConfiguration
|
||||
) -> some View {
|
||||
var configuration = configuration
|
||||
Section {
|
||||
ForEach(0..<configuration.servers.count, id: \.self) { i in
|
||||
TextField(
|
||||
"IP address",
|
||||
text: .init(
|
||||
get: { configuration.servers[i] },
|
||||
set: {
|
||||
configuration.servers[i] = $0
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .dotAddress)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.numbersAndPunctuation)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
.onDelete {
|
||||
configuration.servers.remove(atOffsets: $0)
|
||||
self.server.configuration = .dnsOverTLS(configuration)
|
||||
}
|
||||
.onMove {
|
||||
configuration.servers.move(fromOffsets: $0, toOffset: $1)
|
||||
self.server.configuration = .dnsOverTLS(configuration)
|
||||
}
|
||||
Button("Add New Server") {
|
||||
configuration.servers.append("")
|
||||
self.server.configuration = .dnsOverTLS(configuration)
|
||||
}
|
||||
} header: {
|
||||
EditButton()
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
.overlay(alignment: .leading) {
|
||||
Text("Servers")
|
||||
}
|
||||
} footer: {
|
||||
Text("The DNS server IP addresses.")
|
||||
}
|
||||
Section {
|
||||
HStack {
|
||||
Text("Server Name")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Server Name",
|
||||
text: .init(
|
||||
get: {
|
||||
configuration.serverName ?? ""
|
||||
},
|
||||
set: {
|
||||
configuration.serverName = $0
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .dotServerName)
|
||||
.multilineTextAlignment(.trailing)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
} header: {
|
||||
Text("DNS-over-TLS Settings")
|
||||
} footer: {
|
||||
Text("The TLS name of a DNS-over-TLS server.")
|
||||
}
|
||||
.onChange(of: self.focusedField) { newValue in
|
||||
if newValue == nil {
|
||||
self.server.configuration = .dnsOverTLS(configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func dnsOverHTTPSSections(
|
||||
_ configuration: DoHConfiguration
|
||||
) -> some View {
|
||||
var configuration = configuration
|
||||
Section {
|
||||
ForEach(0..<configuration.servers.count, id: \.self) { i in
|
||||
TextField(
|
||||
"IP address",
|
||||
text: .init(
|
||||
get: { configuration.servers[i] },
|
||||
set: {
|
||||
configuration.servers[i] = $0
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .dohAddress)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.numbersAndPunctuation)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
.onDelete {
|
||||
configuration.servers.remove(atOffsets: $0)
|
||||
self.server.configuration = .dnsOverHTTPS(configuration)
|
||||
}
|
||||
.onMove {
|
||||
configuration.servers.move(fromOffsets: $0, toOffset: $1)
|
||||
self.server.configuration = .dnsOverHTTPS(configuration)
|
||||
}
|
||||
Button("Add New Server") {
|
||||
configuration.servers.append("")
|
||||
self.server.configuration = .dnsOverHTTPS(configuration)
|
||||
}
|
||||
} header: {
|
||||
EditButton()
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
.overlay(alignment: .leading) {
|
||||
Text("Servers")
|
||||
}
|
||||
} footer: {
|
||||
Text("The DNS server IP addresses.")
|
||||
}
|
||||
Section {
|
||||
HStack {
|
||||
Text("Server URL")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Server URL",
|
||||
text: .init(
|
||||
get: {
|
||||
configuration.serverURL?.absoluteString ?? ""
|
||||
},
|
||||
set: {
|
||||
configuration.serverURL = URL(
|
||||
string: $0.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .dohServerURL)
|
||||
.multilineTextAlignment(.trailing)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
} header: {
|
||||
Text("DNS-over-HTTPS Settings")
|
||||
} footer: {
|
||||
Text("The URL of a DNS-over-HTTPS server.")
|
||||
}
|
||||
.onChange(of: self.focusedField) { newValue in
|
||||
if newValue == nil {
|
||||
self.server.configuration = .dnsOverHTTPS(configuration)
|
||||
}
|
||||
DoHSections(server: self.$server, configuration: configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
122
DNSecure/Views/DoHSections.swift
Normal file
122
DNSecure/Views/DoHSections.swift
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// DoHSections.swift
|
||||
// DNSecure
|
||||
//
|
||||
// Created by Kenta Kubo on 9/23/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
private enum FocusedField {
|
||||
case address
|
||||
case serverURL
|
||||
}
|
||||
|
||||
struct DoHSections {
|
||||
@Binding var server: Resolver
|
||||
@State var configuration: DoHConfiguration
|
||||
@FocusState private var focusedField: FocusedField?
|
||||
|
||||
private func commit() {
|
||||
self.server.configuration = .dnsOverHTTPS(self.configuration)
|
||||
}
|
||||
}
|
||||
|
||||
extension DoHSections: View {
|
||||
var body: some View {
|
||||
Section {
|
||||
ForEach(0..<self.configuration.servers.count, id: \.self) { i in
|
||||
TextField(
|
||||
"IP address",
|
||||
text: .init(
|
||||
get: { self.configuration.servers[i] },
|
||||
set: {
|
||||
self.configuration.servers[i] = $0
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .address)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.numbersAndPunctuation)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
.onDelete {
|
||||
self.configuration.servers.remove(atOffsets: $0)
|
||||
self.commit()
|
||||
}
|
||||
.onMove {
|
||||
self.configuration.servers.move(fromOffsets: $0, toOffset: $1)
|
||||
self.commit()
|
||||
}
|
||||
Button("Add New Server") {
|
||||
configuration.servers.append("")
|
||||
self.commit()
|
||||
}
|
||||
} header: {
|
||||
EditButton()
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
.overlay(alignment: .leading) {
|
||||
Text("Servers")
|
||||
}
|
||||
} footer: {
|
||||
Text("The DNS server IP addresses.")
|
||||
}
|
||||
Section {
|
||||
HStack {
|
||||
Text("Server URL")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Server URL",
|
||||
text: .init(
|
||||
get: {
|
||||
configuration.serverURL?.absoluteString ?? ""
|
||||
},
|
||||
set: {
|
||||
configuration.serverURL = URL(
|
||||
string: $0.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .serverURL)
|
||||
.multilineTextAlignment(.trailing)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
} header: {
|
||||
Text("DNS-over-HTTPS Settings")
|
||||
} footer: {
|
||||
Text("The URL of a DNS-over-HTTPS server.")
|
||||
}
|
||||
.onChange(of: self.focusedField) { newValue in
|
||||
if newValue == nil {
|
||||
self.commit()
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
self.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DoHSections_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let configuration = DoHConfiguration(
|
||||
servers: [
|
||||
"1.1.1.1",
|
||||
"1.0.0.1",
|
||||
"2606:4700:4700::1111",
|
||||
"2606:4700:4700::1001",
|
||||
],
|
||||
serverURL: URL(string: "https://cloudflare-dns.com/dns-query")
|
||||
)
|
||||
let resolver = Resolver(name: "1.1.1.1", configuration: .dnsOverHTTPS(configuration))
|
||||
Form {
|
||||
DoHSections(server: .constant(resolver), configuration: configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
119
DNSecure/Views/DoTSections.swift
Normal file
119
DNSecure/Views/DoTSections.swift
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
//
|
||||
// DoTSections.swift
|
||||
// DNSecure
|
||||
//
|
||||
// Created by Kenta Kubo on 9/23/22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
private enum FocusedField {
|
||||
case address
|
||||
case serverName
|
||||
}
|
||||
|
||||
struct DoTSections {
|
||||
@Binding var server: Resolver
|
||||
@State var configuration: DoTConfiguration
|
||||
@FocusState private var focusedField: FocusedField?
|
||||
|
||||
private func commit() {
|
||||
self.server.configuration = .dnsOverTLS(self.configuration)
|
||||
}
|
||||
}
|
||||
|
||||
extension DoTSections: View {
|
||||
var body: some View {
|
||||
Section {
|
||||
ForEach(0..<self.configuration.servers.count, id: \.self) { i in
|
||||
TextField(
|
||||
"IP address",
|
||||
text: .init(
|
||||
get: { self.configuration.servers[i] },
|
||||
set: {
|
||||
self.configuration.servers[i] = $0
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .address)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.numbersAndPunctuation)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
.onDelete {
|
||||
self.configuration.servers.remove(atOffsets: $0)
|
||||
self.commit()
|
||||
}
|
||||
.onMove {
|
||||
self.configuration.servers.move(fromOffsets: $0, toOffset: $1)
|
||||
self.commit()
|
||||
}
|
||||
Button("Add New Server") {
|
||||
self.configuration.servers.append("")
|
||||
self.commit()
|
||||
}
|
||||
} header: {
|
||||
EditButton()
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
.overlay(alignment: .leading) {
|
||||
Text("Servers")
|
||||
}
|
||||
} footer: {
|
||||
Text("The DNS server IP addresses.")
|
||||
}
|
||||
Section {
|
||||
HStack {
|
||||
Text("Server Name")
|
||||
Spacer()
|
||||
TextField(
|
||||
"Server Name",
|
||||
text: .init(
|
||||
get: { self.configuration.serverName ?? "" },
|
||||
set: {
|
||||
self.configuration.serverName = $0
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
)
|
||||
)
|
||||
.focused(self.$focusedField, equals: .serverName)
|
||||
.multilineTextAlignment(.trailing)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
}
|
||||
} header: {
|
||||
Text("DNS-over-TLS Settings")
|
||||
} footer: {
|
||||
Text("The TLS name of a DNS-over-TLS server.")
|
||||
}
|
||||
.onChange(of: self.focusedField) { newValue in
|
||||
if newValue == nil {
|
||||
self.commit()
|
||||
}
|
||||
}
|
||||
.onDisappear {
|
||||
self.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DoTSections_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let configuration = DoTConfiguration(
|
||||
servers: [
|
||||
"1.1.1.1",
|
||||
"1.0.0.1",
|
||||
"2606:4700:4700::1111",
|
||||
"2606:4700:4700::1001",
|
||||
],
|
||||
serverName: "cloudflare-dns.com"
|
||||
)
|
||||
let resolver = Resolver(name: "1.1.1.1", configuration: .dnsOverTLS(configuration))
|
||||
Form {
|
||||
DoTSections(server: .constant(resolver), configuration: configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue