Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework "Trusted networks" to be a generic "On-demand" #333

Merged
merged 4 commits into from
Jul 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- OpenVPN: Endpoint UX. [#332](https://github.com/passepartoutvpn/passepartout-apple/pull/332)
- Convert trusted networks to on-demand activation. [#119](https://github.com/passepartoutvpn/passepartout-apple/issues/119)

## 2.1.2 (2023-07-06)

Expand Down
46 changes: 42 additions & 4 deletions Passepartout/App/L10n/Core+L10n.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,56 @@ extension Profile.Header: Comparable {
}
}

extension Profile.OpenVPNSettings {
var endpointDescription: String? {
extension Profile.OpenVPNSettings: StyledOptionalLocalizableEntity {
public enum OptionalStyle {
case endpoint
}

public func localizedDescription(optionalStyle: OptionalStyle) -> String? {
switch optionalStyle {
case .endpoint:
return endpointDescription
}
}

private var endpointDescription: String? {
customEndpoint?.address ?? configuration.remotes?.first?.address
}
}

extension Profile.WireGuardSettings {
var endpointDescription: String? {
extension Profile.WireGuardSettings: StyledOptionalLocalizableEntity {
public enum OptionalStyle {
case endpoint
}

public func localizedDescription(optionalStyle: OptionalStyle) -> String? {
switch optionalStyle {
case .endpoint:
return endpointDescription
}
}

private var endpointDescription: String? {
configuration.tunnelConfiguration.peers.first?.endpoint?.stringRepresentation
}
}

extension Profile.OnDemand.Policy: LocalizableEntity {
public var localizedDescription: String {
// FIXME: l10n, on-demand
switch self {
case .any:
return L10n.OnDemand.Policy.any

case .including:
return L10n.OnDemand.Policy.including

case .excluding:
return L10n.OnDemand.Policy.excluding
}
}
}

extension Network.Choice: LocalizableEntity {
public var localizedDescription: String {
switch self {
Expand Down
66 changes: 42 additions & 24 deletions Passepartout/App/Views/OnDemandView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ struct OnDemandView: View {
var body: some View {
debugChanges()
return List {
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
// enabledView
// if onDemand.isEnabled {
enabledView
if onDemand.isEnabled && onDemand.policy != .any {
mainView
// }
}
}.navigationTitle(L10n.OnDemand.title)
.toolbar {
CopySavingButton(
Expand All @@ -68,43 +67,62 @@ private extension OnDemandView {
var enabledView: some View {
Section {
Toggle(L10n.Global.Strings.enabled, isOn: $onDemand.isEnabled.themeAnimation())
if onDemand.isEnabled {
themeTextPicker(
// FIXME: l10n, on-demand
L10n.Global.Strings.policy,
selection: $onDemand.policy,
values: [.any, .including, .excluding],
description: \.localizedDescription
)
}
} footer: {
Text(policyFooterDescription)
}
}

// FIXME: l10n, on-demand
var policyFooterDescription: String {
let suffix: String
switch onDemand.policy {
case .any:
suffix = L10n.OnDemand.Sections.Policy.Footer.any

case .including, .excluding:
let arg: String
if onDemand.policy == .including {
arg = L10n.OnDemand.Sections.Policy.Footer.including
} else {
arg = L10n.OnDemand.Sections.Policy.Footer.excluding
}
suffix = L10n.OnDemand.Sections.Policy.Footer.matching(arg)
}
return L10n.OnDemand.Sections.Policy.footer(suffix)
}

@ViewBuilder
var mainView: some View {
if Utils.hasCellularData() {
Section {
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 {
SSIDList(withSSIDs: $onDemand.withSSIDs)
// FIXME: l10n, on-demand
Text(L10n.Global.Strings.networks)
}
} else if Utils.hasEthernet() {
Section {
Toggle(L10n.OnDemand.Items.Ethernet.caption, isOn: $onDemand.withEthernetNetwork)
} header: {
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
// Text(L10n.Profile.Sections.Trusted.header)
}
Section {
SSIDList(withSSIDs: $onDemand.withSSIDs)
}
} else {
Section {
SSIDList(withSSIDs: $onDemand.withSSIDs)
} header: {
// TODO: on-demand, restore when "trusted networks" -> "on-demand"
// Text(L10n.Profile.Sections.Trusted.header)
// FIXME: l10n, on-demand
Text(L10n.Global.Strings.networks)
}
}
Section {
Toggle(L10n.OnDemand.Items.Policy.caption, isOn: $onDemand.disconnectsIfNotMatching)
} footer: {
Text(L10n.OnDemand.Sections.Policy.footer)
SSIDList(withSSIDs: $onDemand.withSSIDs)
} header: {
if !Utils.hasCellularData() && !Utils.hasEthernet() {
Text(L10n.Global.Strings.networks)
}
}
}

Expand Down
20 changes: 14 additions & 6 deletions Passepartout/App/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
"global.strings.disconnect" = "Disconnect";
"global.strings.download" = "Download";
"global.strings.authentication" = "Authentication";
"global.strings.policy" = "Policy";
"global.strings.networks" = "Networks";
"global.messages.unlock_app" = "Passepartout is locked";
"global.messages.email_not_configured" = "No e-mail account is configured.";
"global.messages.share" = "Passepartout is a user-friendly, open source OpenVPN / WireGuard client for iOS and macOS";
Expand Down Expand Up @@ -251,14 +253,20 @@

/* MARK: ProfileView -> OnDemandView */

"on_demand.title" = "Trusted networks";
"on_demand.sections.policy.footer" = "When entering a trusted network, the VPN is normally shut down and kept disconnected. Disable this option to not enforce such behavior.";
"on_demand.title" = "On-demand";
"on_demand.sections.policy.footer" = "Activate the VPN %@.";
"on_demand.sections.policy.footer.any" = "in any network";
"on_demand.sections.policy.footer.matching" = "%@ the networks below";
"on_demand.sections.policy.footer.including" = "only in";
"on_demand.sections.policy.footer.excluding" = "except in";
"on_demand.items.add_ssid.caption" = "Add Wi-Fi";
"on_demand.items.active.caption" = "Trust";
"on_demand.items.mobile.caption" = "Cellular network";
"on_demand.items.ethernet.caption" = "Trust wired connections";
"on_demand.items.ethernet.description" = "Check to trust any wired cable connection.";
"on_demand.items.policy.caption" = "Trust disables VPN";
"on_demand.items.ethernet.caption" = "Wired connections";
"on_demand.items.ethernet.description" = "Check to match any wired cable connection.";

"on_demand.policy.any" = "All networks";
"on_demand.policy.including" = "Include";
"on_demand.policy.excluding" = "Exclude";

/* MARK: ProfileView -> DiagnosticsView */

Expand Down
48 changes: 33 additions & 15 deletions Passepartout/AppShared/Constants/SwiftGen+Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -506,12 +506,16 @@ internal enum L10n {
internal static let manual = L10n.tr("Localizable", "global.strings.manual", fallback: "Manual")
/// Name
internal static let name = L10n.tr("Localizable", "global.strings.name", fallback: "Name")
/// Networks
internal static let networks = L10n.tr("Localizable", "global.strings.networks", fallback: "Networks")
/// Next
internal static let next = L10n.tr("Localizable", "global.strings.next", fallback: "Next")
/// None
internal static let `none` = L10n.tr("Localizable", "global.strings.none", fallback: "None")
/// MARK: Global
internal static let ok = L10n.tr("Localizable", "global.strings.ok", fallback: "OK")
/// Policy
internal static let policy = L10n.tr("Localizable", "global.strings.policy", fallback: "Policy")
/// Port
internal static let port = L10n.tr("Localizable", "global.strings.port", fallback: "Port")
/// Private key
Expand Down Expand Up @@ -640,35 +644,49 @@ internal enum L10n {
}
internal enum OnDemand {
/// MARK: ProfileView -> OnDemandView
internal static let title = L10n.tr("Localizable", "on_demand.title", fallback: "Trusted networks")
internal static let title = L10n.tr("Localizable", "on_demand.title", fallback: "On-demand")
internal enum Items {
internal enum Active {
/// Trust
internal static let caption = L10n.tr("Localizable", "on_demand.items.active.caption", fallback: "Trust")
}
internal enum AddSsid {
/// Add Wi-Fi
internal static let caption = L10n.tr("Localizable", "on_demand.items.add_ssid.caption", fallback: "Add Wi-Fi")
}
internal enum Ethernet {
/// Trust wired connections
internal static let caption = L10n.tr("Localizable", "on_demand.items.ethernet.caption", fallback: "Trust wired connections")
/// Check to trust any wired cable connection.
internal static let description = L10n.tr("Localizable", "on_demand.items.ethernet.description", fallback: "Check to trust any wired cable connection.")
/// Wired connections
internal static let caption = L10n.tr("Localizable", "on_demand.items.ethernet.caption", fallback: "Wired connections")
/// Check to match any wired cable connection.
internal static let description = L10n.tr("Localizable", "on_demand.items.ethernet.description", fallback: "Check to match any wired cable connection.")
}
internal enum Mobile {
/// Cellular network
internal static let caption = L10n.tr("Localizable", "on_demand.items.mobile.caption", fallback: "Cellular network")
}
internal enum Policy {
/// Trust disables VPN
internal static let caption = L10n.tr("Localizable", "on_demand.items.policy.caption", fallback: "Trust disables VPN")
}
}
internal enum Policy {
/// All networks
internal static let any = L10n.tr("Localizable", "on_demand.policy.any", fallback: "All networks")
/// Exclude
internal static let excluding = L10n.tr("Localizable", "on_demand.policy.excluding", fallback: "Exclude")
/// Include
internal static let including = L10n.tr("Localizable", "on_demand.policy.including", fallback: "Include")
}
internal enum Sections {
internal enum Policy {
/// When entering a trusted network, the VPN is normally shut down and kept disconnected. Disable this option to not enforce such behavior.
internal static let footer = L10n.tr("Localizable", "on_demand.sections.policy.footer", fallback: "When entering a trusted network, the VPN is normally shut down and kept disconnected. Disable this option to not enforce such behavior.")
/// Activate the VPN %@.
internal static func footer(_ p1: Any) -> String {
return L10n.tr("Localizable", "on_demand.sections.policy.footer", String(describing: p1), fallback: "Activate the VPN %@.")
}
internal enum Footer {
/// in any network
internal static let any = L10n.tr("Localizable", "on_demand.sections.policy.footer.any", fallback: "in any network")
/// except in
internal static let excluding = L10n.tr("Localizable", "on_demand.sections.policy.footer.excluding", fallback: "except in")
/// only in
internal static let including = L10n.tr("Localizable", "on_demand.sections.policy.footer.including", fallback: "only in")
/// %@ the networks below
internal static func matching(_ p1: Any) -> String {
return L10n.tr("Localizable", "on_demand.sections.policy.footer.matching", String(describing: p1), fallback: "%@ the networks below")
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,14 @@ extension Profile {
case ethernet
}

// hardcode this to keep "Trusted networks" semantics
public var isEnabled = true

// hardcode this to keep "Trusted networks" semantics
public var policy: Policy = .excluding

public var withSSIDs: [String: Bool] = [:]

public var withOtherNetworks: Set<OtherNetwork> = []

public var disconnectsIfNotMatching = true
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropping this prevented downgrade from 2.2.0

See #338 for explanations.


public init() {
}
}
Expand Down
Loading
Loading