mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-16 21:02:04 +00:00
Use block versions of Section header/footer
This commit is contained in:
parent
d8b19b952a
commit
48d499569b
@ -69,22 +69,20 @@ struct AboutView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var githubSubview: some View {
|
private var githubSubview: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.About.github)
|
|
||||||
) {
|
|
||||||
Button(Unlocalized.About.readme) {
|
Button(Unlocalized.About.readme) {
|
||||||
URL.openURL(readmeURL)
|
URL.openURL(readmeURL)
|
||||||
}
|
}
|
||||||
Button(Unlocalized.About.changelog) {
|
Button(Unlocalized.About.changelog) {
|
||||||
URL.openURL(changelogURL)
|
URL.openURL(changelogURL)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.About.github)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var webSubview: some View {
|
private var webSubview: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.About.Sections.Web.header)
|
|
||||||
) {
|
|
||||||
Button(L10n.About.Items.Website.caption) {
|
Button(L10n.About.Items.Website.caption) {
|
||||||
URL.openURL(readmeURL)
|
URL.openURL(readmeURL)
|
||||||
}
|
}
|
||||||
@ -97,6 +95,8 @@ struct AboutView: View {
|
|||||||
Button(L10n.About.Items.PrivacyPolicy.caption) {
|
Button(L10n.About.Items.PrivacyPolicy.caption) {
|
||||||
URL.openURL(privacyURL)
|
URL.openURL(privacyURL)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.About.Sections.Web.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,11 +63,7 @@ struct AccountView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
Section(
|
Section {
|
||||||
footer: metadata?.localizedGuidanceString.map {
|
|
||||||
Text($0)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
TextField(usernamePlaceholder ?? L10n.Account.Items.Username.placeholder, text: $liveAccount.username)
|
TextField(usernamePlaceholder ?? L10n.Account.Items.Username.placeholder, text: $liveAccount.username)
|
||||||
.textContentType(.username)
|
.textContentType(.username)
|
||||||
.disableAutocorrection(true)
|
.disableAutocorrection(true)
|
||||||
@ -85,6 +81,10 @@ struct AccountView: View {
|
|||||||
.disableAutocorrection(true)
|
.disableAutocorrection(true)
|
||||||
.autocapitalization(.none)
|
.autocapitalization(.none)
|
||||||
.withLeadingText(L10n.Account.Items.Password.caption)
|
.withLeadingText(L10n.Account.Items.Password.caption)
|
||||||
|
} footer: {
|
||||||
|
metadata?.localizedGuidanceString.map {
|
||||||
|
Text($0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if vpnProtocol == .openVPN {
|
if vpnProtocol == .openVPN {
|
||||||
metadata?.openVPNGuidanceURL.map { guidanceURL in
|
metadata?.openVPNGuidanceURL.map { guidanceURL in
|
||||||
|
@ -109,26 +109,27 @@ extension AddHostView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var encryptionSection: some View {
|
private var encryptionSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.encryption)
|
|
||||||
) {
|
|
||||||
SecureField(L10n.AddProfile.Host.Sections.Encryption.footer, text: $viewModel.encryptionPassphrase) {
|
SecureField(L10n.AddProfile.Host.Sections.Encryption.footer, text: $viewModel.encryptionPassphrase) {
|
||||||
processProfile(replacingExisting: false)
|
processProfile(replacingExisting: false)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.encryption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var completeSection: some View {
|
private var completeSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.AddProfile.Shared.title),
|
|
||||||
footer: themeErrorMessage(viewModel.errorMessage)
|
|
||||||
) {
|
|
||||||
Text(Unlocalized.Network.url)
|
Text(Unlocalized.Network.url)
|
||||||
.withTrailingText(url.lastPathComponent)
|
.withTrailingText(url.lastPathComponent)
|
||||||
viewModel.processedProfile.vpnProtocols.first.map {
|
viewModel.processedProfile.vpnProtocols.first.map {
|
||||||
Text(L10n.Global.Strings.protocol)
|
Text(L10n.Global.Strings.protocol)
|
||||||
.withTrailingText($0.description)
|
.withTrailingText($0.description)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.AddProfile.Shared.title)
|
||||||
|
} footer: {
|
||||||
|
themeErrorMessage(viewModel.errorMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +39,13 @@ enum AddProfileView {
|
|||||||
let onCommit: () -> Void
|
let onCommit: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.name),
|
|
||||||
footer: themeErrorMessage(errorMessage)
|
|
||||||
) {
|
|
||||||
TextField(L10n.Global.Placeholders.profileName, text: $profileName, onCommit: onCommit)
|
TextField(L10n.Global.Placeholders.profileName, text: $profileName, onCommit: onCommit)
|
||||||
.themeValidProfileName()
|
.themeValidProfileName()
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.name)
|
||||||
|
} footer: {
|
||||||
|
themeErrorMessage(errorMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,10 +56,10 @@ enum AddProfileView {
|
|||||||
@Binding var profileName: String
|
@Binding var profileName: String
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.AddProfile.Shared.Views.Existing.header)
|
|
||||||
) {
|
|
||||||
ForEach(headers, content: existingProfileButton)
|
ForEach(headers, content: existingProfileButton)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.AddProfile.Shared.Views.Existing.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,9 +84,7 @@ struct AddProviderView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var mainSection: some View {
|
private var mainSection: some View {
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.AddProfile.Provider.Sections.Vpn.footer)
|
|
||||||
) {
|
|
||||||
let protos = availableVPNProtocols
|
let protos = availableVPNProtocols
|
||||||
if !protos.isEmpty {
|
if !protos.isEmpty {
|
||||||
themeTextPicker(
|
themeTextPicker(
|
||||||
@ -97,14 +95,16 @@ struct AddProviderView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
updateListButton
|
updateListButton
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.AddProfile.Provider.Sections.Vpn.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var providersSection: some View {
|
private var providersSection: some View {
|
||||||
Section(
|
Section {
|
||||||
footer: themeErrorMessage(viewModel.errorMessage)
|
|
||||||
) {
|
|
||||||
ForEach(providers, content: providerRow)
|
ForEach(providers, content: providerRow)
|
||||||
|
} footer: {
|
||||||
|
themeErrorMessage(viewModel.errorMessage)
|
||||||
}.disabled(viewModel.isFetchingAnyProvider)
|
}.disabled(viewModel.isFetchingAnyProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,9 +110,7 @@ extension DiagnosticsView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var debugLogSection: some View {
|
private var debugLogSection: some View {
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.Diagnostics.Sections.DebugLog.footer)
|
|
||||||
) {
|
|
||||||
let url = debugLogURL
|
let url = debugLogURL
|
||||||
NavigationLink(L10n.DebugLog.title) {
|
NavigationLink(L10n.DebugLog.title) {
|
||||||
url.map {
|
url.map {
|
||||||
@ -123,6 +121,8 @@ extension DiagnosticsView {
|
|||||||
}
|
}
|
||||||
}.disabled(url == nil)
|
}.disabled(url == nil)
|
||||||
Toggle(L10n.Diagnostics.Items.MasksPrivateData.caption, isOn: $appManager.masksPrivateData)
|
Toggle(L10n.Diagnostics.Items.MasksPrivateData.caption, isOn: $appManager.masksPrivateData)
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Diagnostics.Sections.DebugLog.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,16 +95,17 @@ struct DonateView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var productsSection: some View {
|
private var productsSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Donate.Sections.OneTime.header),
|
|
||||||
footer: Text(L10n.Donate.Sections.OneTime.footer)
|
|
||||||
.xxxThemeTruncation()
|
|
||||||
) {
|
|
||||||
if !productManager.isRefreshingProducts {
|
if !productManager.isRefreshingProducts {
|
||||||
ForEach(productManager.donations, id: \.productIdentifier, content: productRow)
|
ForEach(productManager.donations, id: \.productIdentifier, content: productRow)
|
||||||
} else {
|
} else {
|
||||||
ProgressView()
|
ProgressView()
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Donate.Sections.OneTime.header)
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Donate.Sections.OneTime.footer)
|
||||||
|
.xxxThemeTruncation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +63,7 @@ extension EndpointAdvancedView {
|
|||||||
extension EndpointAdvancedView.OpenVPNView {
|
extension EndpointAdvancedView.OpenVPNView {
|
||||||
private var ipv4Section: some View {
|
private var ipv4Section: some View {
|
||||||
builder.ipv4.map { cfg in
|
builder.ipv4.map { cfg in
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.ipv4)
|
|
||||||
) {
|
|
||||||
themeLongContentLinkDefault(
|
themeLongContentLinkDefault(
|
||||||
L10n.Global.Strings.address,
|
L10n.Global.Strings.address,
|
||||||
content: .constant(builder.ipv4.localizedAddress)
|
content: .constant(builder.ipv4.localizedAddress)
|
||||||
@ -81,15 +79,15 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
content: .constant(route.localizedDescription)
|
content: .constant(route.localizedDescription)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.ipv4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var ipv6Section: some View {
|
private var ipv6Section: some View {
|
||||||
builder.ipv6.map { cfg in
|
builder.ipv6.map { cfg in
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.ipv6)
|
|
||||||
) {
|
|
||||||
themeLongContentLinkDefault(
|
themeLongContentLinkDefault(
|
||||||
L10n.Global.Strings.address,
|
L10n.Global.Strings.address,
|
||||||
content: .constant(builder.ipv6.localizedAddress)
|
content: .constant(builder.ipv6.localizedAddress)
|
||||||
@ -105,15 +103,15 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
content: .constant(route.localizedDescription)
|
content: .constant(route.localizedDescription)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.ipv6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func communicationSection(configuration: OpenVPN.Configuration) -> some View {
|
private func communicationSection(configuration: OpenVPN.Configuration) -> some View {
|
||||||
configuration.communicationSettings.map { settings in
|
configuration.communicationSettings.map { settings in
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Endpoint.Advanced.Openvpn.Sections.Communication.header)
|
|
||||||
) {
|
|
||||||
settings.cipher.map {
|
settings.cipher.map {
|
||||||
Text(L10n.Endpoint.Advanced.Openvpn.Items.Cipher.caption)
|
Text(L10n.Endpoint.Advanced.Openvpn.Items.Cipher.caption)
|
||||||
.withTrailingText($0.localizedDescription)
|
.withTrailingText($0.localizedDescription)
|
||||||
@ -126,14 +124,14 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
Text(Unlocalized.VPN.xor)
|
Text(Unlocalized.VPN.xor)
|
||||||
.withTrailingText($0.localizedDescriptionAsXOR)
|
.withTrailingText($0.localizedDescriptionAsXOR)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Endpoint.Advanced.Openvpn.Sections.Communication.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var communicationEditableSection: some View {
|
private var communicationEditableSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Endpoint.Advanced.Openvpn.Sections.Communication.header)
|
|
||||||
) {
|
|
||||||
themeTextPicker(
|
themeTextPicker(
|
||||||
L10n.Endpoint.Advanced.Openvpn.Items.Cipher.caption,
|
L10n.Endpoint.Advanced.Openvpn.Items.Cipher.caption,
|
||||||
selection: $builder.cipher ?? OpenVPN.Configuration.Fallback.cipher,
|
selection: $builder.cipher ?? OpenVPN.Configuration.Fallback.cipher,
|
||||||
@ -150,14 +148,14 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
Text(Unlocalized.VPN.xor)
|
Text(Unlocalized.VPN.xor)
|
||||||
.withTrailingText($0.localizedDescriptionAsXOR)
|
.withTrailingText($0.localizedDescriptionAsXOR)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Endpoint.Advanced.Openvpn.Sections.Communication.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func compressionSection(configuration: OpenVPN.Configuration) -> some View {
|
private func compressionSection(configuration: OpenVPN.Configuration) -> some View {
|
||||||
configuration.compressionSettings.map { settings in
|
configuration.compressionSettings.map { settings in
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Endpoint.Advanced.Openvpn.Sections.Compression.header)
|
|
||||||
) {
|
|
||||||
settings.framing.map {
|
settings.framing.map {
|
||||||
Text(L10n.Endpoint.Advanced.Openvpn.Items.CompressionFraming.caption)
|
Text(L10n.Endpoint.Advanced.Openvpn.Items.CompressionFraming.caption)
|
||||||
.withTrailingText($0.localizedDescription)
|
.withTrailingText($0.localizedDescription)
|
||||||
@ -166,14 +164,14 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
Text(L10n.Endpoint.Advanced.Openvpn.Items.CompressionAlgorithm.caption)
|
Text(L10n.Endpoint.Advanced.Openvpn.Items.CompressionAlgorithm.caption)
|
||||||
.withTrailingText($0.localizedDescription)
|
.withTrailingText($0.localizedDescription)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Endpoint.Advanced.Openvpn.Sections.Compression.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var compressionEditableSection: some View {
|
private var compressionEditableSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Endpoint.Advanced.Openvpn.Sections.Compression.header)
|
|
||||||
) {
|
|
||||||
themeTextPicker(
|
themeTextPicker(
|
||||||
L10n.Endpoint.Advanced.Openvpn.Items.CompressionFraming.caption,
|
L10n.Endpoint.Advanced.Openvpn.Items.CompressionFraming.caption,
|
||||||
selection: $builder.compressionFraming ?? OpenVPN.Configuration.Fallback.compressionFraming,
|
selection: $builder.compressionFraming ?? OpenVPN.Configuration.Fallback.compressionFraming,
|
||||||
@ -186,14 +184,14 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
values: OpenVPN.CompressionAlgorithm.available,
|
values: OpenVPN.CompressionAlgorithm.available,
|
||||||
description: \.localizedDescription
|
description: \.localizedDescription
|
||||||
).disabled(builder.compressionFraming == .disabled)
|
).disabled(builder.compressionFraming == .disabled)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Endpoint.Advanced.Openvpn.Sections.Compression.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dnsSection(configuration: OpenVPN.Configuration) -> some View {
|
private func dnsSection(configuration: OpenVPN.Configuration) -> some View {
|
||||||
configuration.dnsSettings.map { settings in
|
configuration.dnsSettings.map { settings in
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.dns)
|
|
||||||
) {
|
|
||||||
ForEach(settings.servers, id: \.self) {
|
ForEach(settings.servers, id: \.self) {
|
||||||
Text(L10n.Global.Strings.address)
|
Text(L10n.Global.Strings.address)
|
||||||
.withTrailingText($0, copyOnTap: true)
|
.withTrailingText($0, copyOnTap: true)
|
||||||
@ -202,15 +200,15 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
Text(L10n.Global.Strings.domain)
|
Text(L10n.Global.Strings.domain)
|
||||||
.withTrailingText($0, copyOnTap: true)
|
.withTrailingText($0, copyOnTap: true)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.dns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func proxySection(configuration: OpenVPN.Configuration) -> some View {
|
private func proxySection(configuration: OpenVPN.Configuration) -> some View {
|
||||||
configuration.proxySettings.map { settings in
|
configuration.proxySettings.map { settings in
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.proxy)
|
|
||||||
) {
|
|
||||||
settings.proxy.map {
|
settings.proxy.map {
|
||||||
Text(L10n.Global.Strings.address)
|
Text(L10n.Global.Strings.address)
|
||||||
.withTrailingText($0.rawValue, copyOnTap: true)
|
.withTrailingText($0.rawValue, copyOnTap: true)
|
||||||
@ -223,14 +221,14 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
Text(L10n.NetworkSettings.Items.ProxyBypass.caption)
|
Text(L10n.NetworkSettings.Items.ProxyBypass.caption)
|
||||||
.withTrailingText($0, copyOnTap: true)
|
.withTrailingText($0, copyOnTap: true)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.proxy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var tlsSection: some View {
|
private var tlsSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.tls)
|
|
||||||
) {
|
|
||||||
builder.ca.map { ca in
|
builder.ca.map { ca in
|
||||||
themeLongContentLink(
|
themeLongContentLink(
|
||||||
Unlocalized.VPN.certificateAuthority,
|
Unlocalized.VPN.certificateAuthority,
|
||||||
@ -258,14 +256,14 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
}
|
}
|
||||||
Text(L10n.Endpoint.Advanced.Openvpn.Items.Eku.caption)
|
Text(L10n.Endpoint.Advanced.Openvpn.Items.Eku.caption)
|
||||||
.withTrailingText(builder.checksEKU.localizedDescriptionAsEKU)
|
.withTrailingText(builder.checksEKU.localizedDescriptionAsEKU)
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.tls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func otherSection(configuration: OpenVPN.Configuration) -> some View {
|
private func otherSection(configuration: OpenVPN.Configuration) -> some View {
|
||||||
configuration.otherSettings.map { settings in
|
configuration.otherSettings.map { settings in
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Endpoint.Advanced.Openvpn.Sections.Other.header)
|
|
||||||
) {
|
|
||||||
settings.keepAlive.map {
|
settings.keepAlive.map {
|
||||||
Text(L10n.Global.Strings.keepalive)
|
Text(L10n.Global.Strings.keepalive)
|
||||||
.withTrailingText($0.localizedDescriptionAsKeepAlive)
|
.withTrailingText($0.localizedDescriptionAsKeepAlive)
|
||||||
@ -278,6 +276,8 @@ extension EndpointAdvancedView.OpenVPNView {
|
|||||||
Text(L10n.Endpoint.Advanced.Openvpn.Items.RandomEndpoint.caption)
|
Text(L10n.Endpoint.Advanced.Openvpn.Items.RandomEndpoint.caption)
|
||||||
.withTrailingText($0.localizedDescriptionAsRandomizeEndpoint)
|
.withTrailingText($0.localizedDescriptionAsRandomizeEndpoint)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Endpoint.Advanced.Openvpn.Sections.Other.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,27 +46,25 @@ extension EndpointAdvancedView {
|
|||||||
|
|
||||||
extension EndpointAdvancedView.WireGuardView {
|
extension EndpointAdvancedView.WireGuardView {
|
||||||
private var keySection: some View {
|
private var keySection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.interface)
|
|
||||||
) {
|
|
||||||
themeLongContentLink(L10n.Global.Strings.privateKey, content: .constant(builder.privateKey))
|
themeLongContentLink(L10n.Global.Strings.privateKey, content: .constant(builder.privateKey))
|
||||||
themeLongContentLink(L10n.Global.Strings.publicKey, content: .constant(builder.publicKey))
|
themeLongContentLink(L10n.Global.Strings.publicKey, content: .constant(builder.publicKey))
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.interface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var addressesSection: some View {
|
private var addressesSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.addresses)
|
|
||||||
) {
|
|
||||||
ForEach(builder.addresses, id: \.self, content: Text.init)
|
ForEach(builder.addresses, id: \.self, content: Text.init)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.addresses)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dnsSection(configuration: WireGuard.Configuration) -> some View {
|
private func dnsSection(configuration: WireGuard.Configuration) -> some View {
|
||||||
configuration.dnsSettings.map { settings in
|
configuration.dnsSettings.map { settings in
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.dns)
|
|
||||||
) {
|
|
||||||
ForEach(settings.servers, id: \.self) {
|
ForEach(settings.servers, id: \.self) {
|
||||||
Text(L10n.Global.Strings.address)
|
Text(L10n.Global.Strings.address)
|
||||||
.withTrailingText($0)
|
.withTrailingText($0)
|
||||||
@ -75,6 +73,8 @@ extension EndpointAdvancedView.WireGuardView {
|
|||||||
Text(L10n.Global.Strings.domain)
|
Text(L10n.Global.Strings.domain)
|
||||||
.withTrailingText($0)
|
.withTrailingText($0)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.dns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,12 +154,12 @@ extension EndpointView.OpenVPNView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var addressesSection: some View {
|
private var addressesSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.addresses)
|
|
||||||
) {
|
|
||||||
filteredRemotes.map {
|
filteredRemotes.map {
|
||||||
ForEach($0, content: button(forEndpoint:))
|
ForEach($0, content: button(forEndpoint:))
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.addresses)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +104,7 @@ extension EndpointView.WireGuardView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func section(forPeerAt peerIndex: Int) -> some View {
|
private func section(forPeerAt peerIndex: Int) -> some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Endpoint.Wireguard.Items.Peer.caption)
|
|
||||||
) {
|
|
||||||
themeLongContentLink(
|
themeLongContentLink(
|
||||||
L10n.Global.Strings.publicKey,
|
L10n.Global.Strings.publicKey,
|
||||||
content: .constant(builder.publicKey(ofPeer: peerIndex))
|
content: .constant(builder.publicKey(ofPeer: peerIndex))
|
||||||
@ -129,6 +127,8 @@ extension EndpointView.WireGuardView {
|
|||||||
Text(L10n.Global.Strings.keepalive)
|
Text(L10n.Global.Strings.keepalive)
|
||||||
.withTrailingText(TimeInterval($0).localizedDescriptionAsKeepAlive)
|
.withTrailingText(TimeInterval($0).localizedDescriptionAsKeepAlive)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Endpoint.Wireguard.Items.Peer.caption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,15 +97,15 @@ struct NetworkSettingsView: View {
|
|||||||
|
|
||||||
extension NetworkSettingsView {
|
extension NetworkSettingsView {
|
||||||
private var gatewayView: some View {
|
private var gatewayView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.NetworkSettings.Gateway.title)
|
|
||||||
) {
|
|
||||||
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticGateway.themeAnimation())
|
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticGateway.themeAnimation())
|
||||||
|
|
||||||
if !settings.isAutomaticGateway {
|
if !settings.isAutomaticGateway {
|
||||||
Toggle(Unlocalized.Network.ipv4, isOn: $settings.gateway.isDefaultIPv4)
|
Toggle(Unlocalized.Network.ipv4, isOn: $settings.gateway.isDefaultIPv4)
|
||||||
Toggle(Unlocalized.Network.ipv6, isOn: $settings.gateway.isDefaultIPv6)
|
Toggle(Unlocalized.Network.ipv6, isOn: $settings.gateway.isDefaultIPv6)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.NetworkSettings.Gateway.title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,9 +116,7 @@ extension NetworkSettingsView {
|
|||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var dnsView: some View {
|
private var dnsView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.dns)
|
|
||||||
) {
|
|
||||||
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticDNS.themeAnimation())
|
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticDNS.themeAnimation())
|
||||||
|
|
||||||
if !settings.isAutomaticDNS {
|
if !settings.isAutomaticDNS {
|
||||||
@ -143,6 +141,8 @@ extension NetworkSettingsView {
|
|||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.dns)
|
||||||
}
|
}
|
||||||
if !settings.isAutomaticDNS && settings.dns.configurationType != .disabled {
|
if !settings.isAutomaticDNS && settings.dns.configurationType != .disabled {
|
||||||
dnsManualServers
|
dnsManualServers
|
||||||
@ -209,9 +209,7 @@ extension NetworkSettingsView {
|
|||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var proxyView: some View {
|
private var proxyView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.proxy)
|
|
||||||
) {
|
|
||||||
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticProxy.themeAnimation())
|
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticProxy.themeAnimation())
|
||||||
|
|
||||||
if !settings.isAutomaticProxy {
|
if !settings.isAutomaticProxy {
|
||||||
@ -240,6 +238,8 @@ extension NetworkSettingsView {
|
|||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.proxy)
|
||||||
}
|
}
|
||||||
if !settings.isAutomaticProxy && settings.proxy.configurationType == .manual {
|
if !settings.isAutomaticProxy && settings.proxy.configurationType == .manual {
|
||||||
proxyManualBypassDomains
|
proxyManualBypassDomains
|
||||||
@ -272,9 +272,7 @@ extension NetworkSettingsView {
|
|||||||
|
|
||||||
extension NetworkSettingsView {
|
extension NetworkSettingsView {
|
||||||
private var mtuView: some View {
|
private var mtuView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.Network.mtu)
|
|
||||||
) {
|
|
||||||
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticMTU.themeAnimation())
|
Toggle(L10n.Global.Strings.automatic, isOn: $settings.isAutomaticMTU.themeAnimation())
|
||||||
|
|
||||||
if !settings.isAutomaticMTU {
|
if !settings.isAutomaticMTU {
|
||||||
@ -285,6 +283,8 @@ extension NetworkSettingsView {
|
|||||||
description: \.localizedDescriptionAsMTU
|
description: \.localizedDescriptionAsMTU
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.Network.mtu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,27 +79,27 @@ extension OnDemandView {
|
|||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var mainView: some View {
|
private var mainView: some View {
|
||||||
if Utils.hasCellularData() {
|
if Utils.hasCellularData() {
|
||||||
Section(
|
Section {
|
||||||
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
|
|
||||||
// header: Text(L10n.Profile.Sections.Trusted.header)
|
|
||||||
) {
|
|
||||||
Toggle(L10n.OnDemand.Items.Mobile.caption, isOn: $onDemand.withMobileNetwork)
|
Toggle(L10n.OnDemand.Items.Mobile.caption, isOn: $onDemand.withMobileNetwork)
|
||||||
|
} header: {
|
||||||
|
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
|
||||||
|
// Text(L10n.Profile.Sections.Trusted.header)
|
||||||
}
|
}
|
||||||
Section {
|
Section {
|
||||||
SSIDList(withSSIDs: $onDemand.withSSIDs)
|
SSIDList(withSSIDs: $onDemand.withSSIDs)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Section(
|
Section {
|
||||||
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
|
|
||||||
// header: Text(L10n.Profile.Sections.Trusted.header)
|
|
||||||
) {
|
|
||||||
SSIDList(withSSIDs: $onDemand.withSSIDs)
|
SSIDList(withSSIDs: $onDemand.withSSIDs)
|
||||||
|
} header: {
|
||||||
|
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
|
||||||
|
// Text(L10n.Profile.Sections.Trusted.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.OnDemand.Sections.Policy.footer)
|
|
||||||
) {
|
|
||||||
Toggle(L10n.OnDemand.Items.Policy.caption, isOn: $onDemand.disconnectsIfNotMatching)
|
Toggle(L10n.OnDemand.Items.Policy.caption, isOn: $onDemand.disconnectsIfNotMatching)
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.OnDemand.Sections.Policy.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,16 +109,17 @@ extension PaywallView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var productsSection: some View {
|
private var productsSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Paywall.title),
|
|
||||||
footer: Text(L10n.Paywall.Sections.Products.footer)
|
|
||||||
) {
|
|
||||||
if !productManager.isRefreshingProducts {
|
if !productManager.isRefreshingProducts {
|
||||||
ForEach(productRowModels, id: \.product.productIdentifier, content: productRow)
|
ForEach(productRowModels, id: \.product.productIdentifier, content: productRow)
|
||||||
} else {
|
} else {
|
||||||
ProgressView()
|
ProgressView()
|
||||||
}
|
}
|
||||||
restoreRow
|
restoreRow
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Paywall.title)
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Paywall.Sections.Products.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +49,7 @@ extension ProfileView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Global.Strings.configuration)
|
|
||||||
) {
|
|
||||||
if currentProfile.value.vpnProtocols.count > 1 {
|
if currentProfile.value.vpnProtocols.count > 1 {
|
||||||
themeTextPicker(
|
themeTextPicker(
|
||||||
L10n.Global.Strings.protocol,
|
L10n.Global.Strings.protocol,
|
||||||
@ -109,6 +107,8 @@ extension ProfileView {
|
|||||||
onDemandRow
|
onDemandRow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Global.Strings.configuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,9 +52,7 @@ extension ProfileView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Profile.Sections.Feedback.header)
|
|
||||||
) {
|
|
||||||
if isActiveProfile {
|
if isActiveProfile {
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
DiagnosticsView(
|
DiagnosticsView(
|
||||||
@ -70,6 +68,8 @@ extension ProfileView {
|
|||||||
} label: {
|
} label: {
|
||||||
Label(Unlocalized.About.faq, systemImage: themeFAQImage)
|
Label(Unlocalized.About.faq, systemImage: themeFAQImage)
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Profile.Sections.Feedback.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,22 +36,22 @@ extension ProfileView {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if currentProfile.value.isProvider {
|
if currentProfile.value.isProvider {
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.Profile.Sections.VpnResolvesHostname.footer)
|
|
||||||
) {
|
|
||||||
Toggle(
|
Toggle(
|
||||||
L10n.Profile.Items.VpnResolvesHostname.caption,
|
L10n.Profile.Items.VpnResolvesHostname.caption,
|
||||||
isOn: $currentProfile.value.networkSettings.resolvesHostname
|
isOn: $currentProfile.value.networkSettings.resolvesHostname
|
||||||
)
|
)
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Profile.Sections.VpnResolvesHostname.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.Profile.Sections.VpnSurvivesSleep.footer)
|
|
||||||
) {
|
|
||||||
Toggle(
|
Toggle(
|
||||||
L10n.Profile.Items.VpnSurvivesSleep.caption,
|
L10n.Profile.Items.VpnSurvivesSleep.caption,
|
||||||
isOn: $currentProfile.value.networkSettings.keepsAliveOnSleep
|
isOn: $currentProfile.value.networkSettings.keepsAliveOnSleep
|
||||||
)
|
)
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Profile.Sections.VpnSurvivesSleep.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,7 @@ extension ProfileView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var mainView: some View {
|
private var mainView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(currentProvider.fullName),
|
|
||||||
footer: lastInfrastructureUpdate.map {
|
|
||||||
Text(L10n.Profile.Sections.ProviderInfrastructure.footer($0))
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
NavigationLink(isActive: $isProviderLocationPresented) {
|
NavigationLink(isActive: $isProviderLocationPresented) {
|
||||||
ProviderLocationView(
|
ProviderLocationView(
|
||||||
currentProfile: currentProfile,
|
currentProfile: currentProfile,
|
||||||
@ -85,6 +80,12 @@ extension ProfileView {
|
|||||||
Button(action: refreshInfrastructure) {
|
Button(action: refreshInfrastructure) {
|
||||||
Text(L10n.Profile.Items.Provider.Refresh.caption)
|
Text(L10n.Profile.Items.Provider.Refresh.caption)
|
||||||
}.withTrailingProgress(when: isRefreshingInfrastructure)
|
}.withTrailingProgress(when: isRefreshingInfrastructure)
|
||||||
|
} header: {
|
||||||
|
Text(currentProvider.fullName)
|
||||||
|
} footer: {
|
||||||
|
lastInfrastructureUpdate.map {
|
||||||
|
Text(L10n.Profile.Sections.ProviderInfrastructure.footer($0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ extension ProfileView {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Profile.Alerts.Rename.title)
|
|
||||||
) {
|
|
||||||
TextField(L10n.Global.Placeholders.profileName, text: $newName, onCommit: commitRenaming)
|
TextField(L10n.Global.Placeholders.profileName, text: $newName, onCommit: commitRenaming)
|
||||||
.themeValidProfileName()
|
.themeValidProfileName()
|
||||||
.onAppear(perform: loadCurrentName)
|
.onAppear(perform: loadCurrentName)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Profile.Alerts.Rename.title)
|
||||||
}
|
}
|
||||||
}.themeSecondaryView()
|
}.themeSecondaryView()
|
||||||
.navigationTitle(currentProfile.value.header.name)
|
.navigationTitle(currentProfile.value.header.name)
|
||||||
|
@ -80,11 +80,7 @@ extension ProfileView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var activeView: some View {
|
private var activeView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: headerView,
|
|
||||||
footer: Text(L10n.Profile.Sections.Vpn.footer)
|
|
||||||
.xxxThemeTruncation()
|
|
||||||
) {
|
|
||||||
VPNToggle(rateLimit: Constants.RateLimit.vpnToggle) {
|
VPNToggle(rateLimit: Constants.RateLimit.vpnToggle) {
|
||||||
|
|
||||||
// eligibility: donate intents if eligible for Siri
|
// eligibility: donate intents if eligible for Siri
|
||||||
@ -105,13 +101,16 @@ extension ProfileView {
|
|||||||
withErrors: true,
|
withErrors: true,
|
||||||
dataCountIfAvailable: true
|
dataCountIfAvailable: true
|
||||||
))
|
))
|
||||||
|
} header: {
|
||||||
|
headerView
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Profile.Sections.Vpn.footer)
|
||||||
|
.xxxThemeTruncation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var inactiveSubview: some View {
|
private var inactiveSubview: some View {
|
||||||
Section(
|
Section {
|
||||||
header: headerView
|
|
||||||
) {
|
|
||||||
Button(L10n.Profile.Items.UseProfile.caption) {
|
Button(L10n.Profile.Items.UseProfile.caption) {
|
||||||
Task {
|
Task {
|
||||||
|
|
||||||
@ -127,14 +126,16 @@ extension ProfileView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
headerView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var loadingView: some View {
|
private var loadingView: some View {
|
||||||
Section(
|
Section {
|
||||||
header: headerView
|
|
||||||
) {
|
|
||||||
ProgressView()
|
ProgressView()
|
||||||
|
} header: {
|
||||||
|
headerView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,9 +134,7 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func categorySection(_ category: ProviderCategory) -> some View {
|
private func categorySection(_ category: ProviderCategory) -> some View {
|
||||||
Section(
|
Section {
|
||||||
header: !category.name.isEmpty ? Text(category.name) : nil
|
|
||||||
) {
|
|
||||||
ForEach(filteredLocations(for: category)) { location in
|
ForEach(filteredLocations(for: category)) { location in
|
||||||
if isEditable, #available(iOS 15, *) {
|
if isEditable, #available(iOS 15, *) {
|
||||||
locationRow(location)
|
locationRow(location)
|
||||||
@ -147,6 +145,8 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
|
|||||||
locationRow(location)
|
locationRow(location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
!category.name.isEmpty ? Text(category.name) : nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,9 +185,9 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var emptyFavoritesSection: some View {
|
private var emptyFavoritesSection: some View {
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.Provider.Location.Sections.EmptyFavorites.footer)
|
} footer: {
|
||||||
) {
|
Text(L10n.Provider.Location.Sections.EmptyFavorites.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +69,7 @@ struct ProviderPresetView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func presetSection(_ preset: ProviderServer.Preset) -> some View {
|
private func presetSection(_ preset: ProviderServer.Preset) -> some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(preset.name)
|
|
||||||
) {
|
|
||||||
Button {
|
Button {
|
||||||
selectedPreset = preset
|
selectedPreset = preset
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
@ -89,6 +87,8 @@ struct ProviderPresetView: View {
|
|||||||
).navigationTitle(preset.name)
|
).navigationTitle(preset.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} header: {
|
||||||
|
Text(preset.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,24 +49,24 @@ extension ShortcutsView {
|
|||||||
ZStack {
|
ZStack {
|
||||||
hiddenProviderLocationLink
|
hiddenProviderLocationLink
|
||||||
List {
|
List {
|
||||||
Section(
|
Section {
|
||||||
header: Text(Unlocalized.VPN.vpn)
|
|
||||||
) {
|
|
||||||
addConnectView
|
addConnectView
|
||||||
Button(L10n.Shortcuts.Add.Items.EnableVpn.caption, action: addEnableVPN)
|
Button(L10n.Shortcuts.Add.Items.EnableVpn.caption, action: addEnableVPN)
|
||||||
Button(L10n.Shortcuts.Add.Items.DisableVpn.caption, action: addDisableVPN)
|
Button(L10n.Shortcuts.Add.Items.DisableVpn.caption, action: addDisableVPN)
|
||||||
|
} header: {
|
||||||
|
Text(Unlocalized.VPN.vpn)
|
||||||
}
|
}
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Shortcuts.Add.Sections.Wifi.header)
|
|
||||||
) {
|
|
||||||
Button(L10n.Shortcuts.Add.Items.TrustCurrentWifi.caption, action: addTrustWiFi)
|
Button(L10n.Shortcuts.Add.Items.TrustCurrentWifi.caption, action: addTrustWiFi)
|
||||||
Button(L10n.Shortcuts.Add.Items.UntrustCurrentWifi.caption, action: addUntrustWiFi)
|
Button(L10n.Shortcuts.Add.Items.UntrustCurrentWifi.caption, action: addUntrustWiFi)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Shortcuts.Add.Sections.Wifi.header)
|
||||||
}
|
}
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Shortcuts.Add.Sections.Cellular.header)
|
|
||||||
) {
|
|
||||||
Button(L10n.Shortcuts.Add.Items.TrustCellular.caption, action: addTrustCellular)
|
Button(L10n.Shortcuts.Add.Items.TrustCellular.caption, action: addTrustCellular)
|
||||||
Button(L10n.Shortcuts.Add.Items.UntrustCellular.caption, action: addUntrustCellular)
|
Button(L10n.Shortcuts.Add.Items.UntrustCellular.caption, action: addUntrustCellular)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Shortcuts.Add.Sections.Cellular.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.navigationTitle(L10n.Shortcuts.Add.title)
|
}.navigationTitle(L10n.Shortcuts.Add.title)
|
||||||
|
@ -85,10 +85,10 @@ struct ShortcutsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var shortcutsSection: some View {
|
private var shortcutsSection: some View {
|
||||||
Section(
|
Section {
|
||||||
header: Text(L10n.Shortcuts.Edit.Sections.All.header)
|
|
||||||
) {
|
|
||||||
ForEach(relevantShortcuts, content: rowView)
|
ForEach(relevantShortcuts, content: rowView)
|
||||||
|
} header: {
|
||||||
|
Text(L10n.Shortcuts.Edit.Sections.All.header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,9 +99,7 @@ struct ShortcutsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var addSection: some View {
|
private var addSection: some View {
|
||||||
Section(
|
Section {
|
||||||
footer: Text(L10n.Shortcuts.Edit.Sections.Add.footer)
|
|
||||||
) {
|
|
||||||
NavigationLink(isActive: $isNavigationPresented) {
|
NavigationLink(isActive: $isNavigationPresented) {
|
||||||
AddView(
|
AddView(
|
||||||
target: target,
|
target: target,
|
||||||
@ -110,6 +108,8 @@ struct ShortcutsView: View {
|
|||||||
} label: {
|
} label: {
|
||||||
Text(L10n.Shortcuts.Edit.Items.AddShortcut.caption)
|
Text(L10n.Shortcuts.Edit.Items.AddShortcut.caption)
|
||||||
}
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(L10n.Shortcuts.Edit.Sections.Add.footer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user