Add Child Safe VPN provider

This commit is contained in:
Davide De Rosa 2020-07-07 23:34:42 +02:00
parent 32ea6a9cfd
commit 7c6a404e4a
12 changed files with 138 additions and 126 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ templates/
Preview.html Preview.html
l10n l10n
passepartout-translations.zip passepartout-translations.zip
default.profraw

View File

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased ## Unreleased
## Added
- Child Safe VPN provider.
## Changed ## Changed
- Use active profile name in iOS settings. - Use active profile name in iOS settings.

View File

@ -1,18 +1,19 @@
// swiftlint:disable all // swiftlint:disable all
// Generated using SwiftGen https://github.com/SwiftGen/SwiftGen // Generated using SwiftGen https://github.com/SwiftGen/SwiftGen
#if os(OSX) #if os(macOS)
import AppKit.NSImage import AppKit
internal typealias AssetColorTypeAlias = NSColor #elseif os(iOS)
internal typealias AssetImageTypeAlias = NSImage import UIKit
#elseif os(iOS) || os(tvOS) || os(watchOS) #elseif os(tvOS) || os(watchOS)
import UIKit.UIImage import UIKit
internal typealias AssetColorTypeAlias = UIColor
internal typealias AssetImageTypeAlias = UIImage
#endif #endif
// swiftlint:disable superfluous_disable_command // Deprecated typealiases
// swiftlint:disable file_length @available(*, deprecated, renamed: "ImageAsset.Image", message: "This typealias will be removed in SwiftGen 7.0")
internal typealias AssetImageTypeAlias = ImageAsset.Image
// swiftlint:disable superfluous_disable_command file_length implicit_return
// MARK: - Asset Catalogs // MARK: - Asset Catalogs
@ -281,6 +282,7 @@ internal enum Asset {
internal static let zw = ImageAsset(name: "zw") internal static let zw = ImageAsset(name: "zw")
} }
internal enum Providers { internal enum Providers {
internal static let csv = ImageAsset(name: "csv")
internal static let hideme = ImageAsset(name: "hideme") internal static let hideme = ImageAsset(name: "hideme")
internal static let mullvad = ImageAsset(name: "mullvad") internal static let mullvad = ImageAsset(name: "mullvad")
internal static let nordvpn = ImageAsset(name: "nordvpn") internal static let nordvpn = ImageAsset(name: "nordvpn")
@ -297,80 +299,39 @@ internal enum Asset {
// MARK: - Implementation Details // MARK: - Implementation Details
internal struct ColorAsset {
internal fileprivate(set) var name: String
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, OSX 10.13, *)
internal var color: AssetColorTypeAlias {
return AssetColorTypeAlias(asset: self)
}
}
internal extension AssetColorTypeAlias {
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, OSX 10.13, *)
convenience init!(asset: ColorAsset) {
let bundle = Bundle(for: BundleToken.self)
#if os(iOS) || os(tvOS)
self.init(named: asset.name, in: bundle, compatibleWith: nil)
#elseif os(OSX)
self.init(named: NSColor.Name(asset.name), bundle: bundle)
#elseif os(watchOS)
self.init(named: asset.name)
#endif
}
}
internal struct DataAsset {
internal fileprivate(set) var name: String
#if os(iOS) || os(tvOS) || os(OSX)
@available(iOS 9.0, tvOS 9.0, OSX 10.11, *)
internal var data: NSDataAsset {
return NSDataAsset(asset: self)
}
#endif
}
#if os(iOS) || os(tvOS) || os(OSX)
@available(iOS 9.0, tvOS 9.0, OSX 10.11, *)
internal extension NSDataAsset {
convenience init!(asset: DataAsset) {
let bundle = Bundle(for: BundleToken.self)
#if os(iOS) || os(tvOS)
self.init(name: asset.name, bundle: bundle)
#elseif os(OSX)
self.init(name: NSDataAsset.Name(asset.name), bundle: bundle)
#endif
}
}
#endif
internal struct ImageAsset { internal struct ImageAsset {
internal fileprivate(set) var name: String internal fileprivate(set) var name: String
internal var image: AssetImageTypeAlias { #if os(macOS)
let bundle = Bundle(for: BundleToken.self) internal typealias Image = NSImage
#elseif os(iOS) || os(tvOS) || os(watchOS)
internal typealias Image = UIImage
#endif
internal var image: Image {
let bundle = BundleToken.bundle
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS)
let image = AssetImageTypeAlias(named: name, in: bundle, compatibleWith: nil) let image = Image(named: name, in: bundle, compatibleWith: nil)
#elseif os(OSX) #elseif os(macOS)
let image = bundle.image(forResource: NSImage.Name(name)) let image = bundle.image(forResource: NSImage.Name(name))
#elseif os(watchOS) #elseif os(watchOS)
let image = AssetImageTypeAlias(named: name) let image = Image(named: name)
#endif #endif
guard let result = image else { fatalError("Unable to load image named \(name).") } guard let result = image else {
fatalError("Unable to load image named \(name).")
}
return result return result
} }
} }
internal extension AssetImageTypeAlias { internal extension ImageAsset.Image {
@available(iOS 1.0, tvOS 1.0, watchOS 1.0, *) @available(macOS, deprecated,
@available(OSX, deprecated,
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property") message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
convenience init!(asset: ImageAsset) { convenience init!(asset: ImageAsset) {
#if os(iOS) || os(tvOS) #if os(iOS) || os(tvOS)
let bundle = Bundle(for: BundleToken.self) let bundle = BundleToken.bundle
self.init(named: asset.name, in: bundle, compatibleWith: nil) self.init(named: asset.name, in: bundle, compatibleWith: nil)
#elseif os(OSX) #elseif os(macOS)
self.init(named: NSImage.Name(asset.name)) self.init(named: NSImage.Name(asset.name))
#elseif os(watchOS) #elseif os(watchOS)
self.init(named: asset.name) self.init(named: asset.name)
@ -378,4 +339,10 @@ internal extension AssetImageTypeAlias {
} }
} }
private final class BundleToken {} // swiftlint:disable convenience_type
private final class BundleToken {
static let bundle: Bundle = {
Bundle(for: BundleToken.self)
}()
}
// swiftlint:enable convenience_type

View File

@ -65,7 +65,7 @@ internal protocol StoryboardType {
internal extension StoryboardType { internal extension StoryboardType {
static var storyboard: UIStoryboard { static var storyboard: UIStoryboard {
let name = self.storyboardName let name = self.storyboardName
return UIStoryboard(name: name, bundle: Bundle(for: BundleToken.self)) return UIStoryboard(name: name, bundle: BundleToken.bundle)
} }
} }
@ -93,4 +93,10 @@ internal struct InitialSceneType<T: UIViewController> {
} }
} }
private final class BundleToken {} // swiftlint:disable convenience_type
private final class BundleToken {
static let bundle: Bundle = {
Bundle(for: BundleToken.self)
}()
}
// swiftlint:enable convenience_type

View File

@ -57,4 +57,10 @@ internal extension SegueType where RawValue == String {
} }
} }
private final class BundleToken {} // swiftlint:disable convenience_type
private final class BundleToken {
static let bundle: Bundle = {
Bundle(for: BundleToken.self)
}()
}
// swiftlint:enable convenience_type

View File

@ -3,8 +3,7 @@
import Foundation import Foundation
// swiftlint:disable superfluous_disable_command // swiftlint:disable superfluous_disable_command file_length implicit_return
// swiftlint:disable file_length
// MARK: - Strings // MARK: - Strings
@ -98,8 +97,8 @@ internal enum L10n {
internal enum Cells { internal enum Cells {
internal enum FullVersion { internal enum FullVersion {
/// - All providers (including future ones)\n%@ /// - All providers (including future ones)\n%@
internal static func extraDescription(_ p1: String) -> String { internal static func extraDescription(_ p1: Any) -> String {
return L10n.tr("App", "purchase.cells.full_version.extra_description", p1) return L10n.tr("App", "purchase.cells.full_version.extra_description", String(describing: p1))
} }
} }
internal enum Restore { internal enum Restore {
@ -264,8 +263,8 @@ internal enum L10n {
} }
internal enum Signup { internal enum Signup {
/// Register with %@ /// Register with %@
internal static func caption(_ p1: String) -> String { internal static func caption(_ p1: Any) -> String {
return L10n.tr("Core", "account.cells.signup.caption", p1) return L10n.tr("Core", "account.cells.signup.caption", String(describing: p1))
} }
} }
internal enum Username { internal enum Username {
@ -280,48 +279,48 @@ internal enum L10n {
internal enum Footer { internal enum Footer {
internal enum Infrastructure { internal enum Infrastructure {
/// Use your %@ website credentials. /// Use your %@ website credentials.
internal static func hideme(_ p1: String) -> String { internal static func hideme(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.hideme", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.hideme", String(describing: p1))
} }
/// Use your %@ website credentials. Your username is usually numeric (without spaces). /// Use your %@ website credentials. Your username is usually numeric (without spaces).
internal static func mullvad(_ p1: String) -> String { internal static func mullvad(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.mullvad", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.mullvad", String(describing: p1))
} }
/// Use your %@ website credentials. Your username is usually your e-mail. /// Use your %@ website credentials. Your username is usually your e-mail.
internal static func nordvpn(_ p1: String) -> String { internal static func nordvpn(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.nordvpn", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.nordvpn", String(describing: p1))
} }
/// Use your %@ website credentials. Your username is usually numeric with a "p" prefix. /// Use your %@ website credentials. Your username is usually numeric with a "p" prefix.
internal static func pia(_ p1: String) -> String { internal static func pia(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.pia", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.pia", String(describing: p1))
} }
/// Find your %@ credentials in the "Account > OpenVPN / IKEv2 Username" section of the website. /// Find your %@ credentials in the "Account > OpenVPN / IKEv2 Username" section of the website.
internal static func protonvpn(_ p1: String) -> String { internal static func protonvpn(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.protonvpn", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.protonvpn", String(describing: p1))
} }
/// Use your %@ service credentials, which may differ from website credentials. /// Use your %@ service credentials, which may differ from website credentials.
internal static func torguard(_ p1: String) -> String { internal static func torguard(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.torguard", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.torguard", String(describing: p1))
} }
/// Use your %@ website credentials. Your username is usually your e-mail. /// Use your %@ website credentials. Your username is usually your e-mail.
internal static func tunnelbear(_ p1: String) -> String { internal static func tunnelbear(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.tunnelbear", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.tunnelbear", String(describing: p1))
} }
/// Use your %@ website credentials. Your username is usually your e-mail. /// Use your %@ website credentials. Your username is usually your e-mail.
internal static func vyprvpn(_ p1: String) -> String { internal static func vyprvpn(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.vyprvpn", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.vyprvpn", String(describing: p1))
} }
/// Find your %@ credentials in the OpenVPN Config Generator on the website. /// Find your %@ credentials in the OpenVPN Config Generator on the website.
internal static func windscribe(_ p1: String) -> String { internal static func windscribe(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.windscribe", p1) return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.windscribe", String(describing: p1))
} }
} }
} }
} }
internal enum Registration { internal enum Registration {
/// Go get an account on the %@ website. /// Go get an account on the %@ website.
internal static func footer(_ p1: String) -> String { internal static func footer(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.registration.footer", p1) return L10n.tr("Core", "account.sections.registration.footer", String(describing: p1))
} }
} }
} }
@ -393,8 +392,8 @@ internal enum L10n {
internal static let caption = L10n.tr("Core", "configuration.cells.renegotiation_seconds.caption") internal static let caption = L10n.tr("Core", "configuration.cells.renegotiation_seconds.caption")
internal enum Value { internal enum Value {
/// after %@ /// after %@
internal static func after(_ p1: String) -> String { internal static func after(_ p1: Any) -> String {
return L10n.tr("Core", "configuration.cells.renegotiation_seconds.value.after", p1) return L10n.tr("Core", "configuration.cells.renegotiation_seconds.value.after", String(describing: p1))
} }
} }
} }
@ -479,8 +478,8 @@ internal enum L10n {
internal enum Purchase { internal enum Purchase {
internal enum Failure { internal enum Failure {
/// Unable to perform the donation. %@ /// Unable to perform the donation. %@
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "donation.alerts.purchase.failure.message", p1) return L10n.tr("Core", "donation.alerts.purchase.failure.message", String(describing: p1))
} }
} }
internal enum Success { internal enum Success {
@ -628,8 +627,8 @@ internal enum L10n {
internal enum Cells { internal enum Cells {
internal enum About { internal enum About {
/// About %@ /// About %@
internal static func caption(_ p1: String) -> String { internal static func caption(_ p1: Any) -> String {
return L10n.tr("Core", "organizer.cells.about.caption", p1) return L10n.tr("Core", "organizer.cells.about.caption", String(describing: p1))
} }
} }
internal enum Donate { internal enum Donate {
@ -712,32 +711,32 @@ internal enum L10n {
} }
internal enum Malformed { internal enum Malformed {
/// The configuration file contains a malformed option (%@). /// The configuration file contains a malformed option (%@).
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.malformed.message", p1) return L10n.tr("Core", "parsed_file.alerts.malformed.message", String(describing: p1))
} }
} }
internal enum Missing { internal enum Missing {
/// The configuration file lacks a required option (%@). /// The configuration file lacks a required option (%@).
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.missing.message", p1) return L10n.tr("Core", "parsed_file.alerts.missing.message", String(describing: p1))
} }
} }
internal enum Parsing { internal enum Parsing {
/// Unable to parse the provided configuration file (%@). /// Unable to parse the provided configuration file (%@).
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.parsing.message", p1) return L10n.tr("Core", "parsed_file.alerts.parsing.message", String(describing: p1))
} }
} }
internal enum PotentiallyUnsupported { internal enum PotentiallyUnsupported {
/// The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings. /// The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings.
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.potentially_unsupported.message", p1) return L10n.tr("Core", "parsed_file.alerts.potentially_unsupported.message", String(describing: p1))
} }
} }
internal enum Unsupported { internal enum Unsupported {
/// The configuration file contains an unsupported option (%@). /// The configuration file contains an unsupported option (%@).
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.unsupported.message", p1) return L10n.tr("Core", "parsed_file.alerts.unsupported.message", String(describing: p1))
} }
} }
} }
@ -780,12 +779,12 @@ internal enum L10n {
} }
internal enum Download { internal enum Download {
/// Failed to download configuration files. %@ /// Failed to download configuration files. %@
internal static func failed(_ p1: String) -> String { internal static func failed(_ p1: Any) -> String {
return L10n.tr("Core", "service.alerts.download.failed", p1) return L10n.tr("Core", "service.alerts.download.failed", String(describing: p1))
} }
/// %@ requires the download of additional configuration files.\n\nConfirm to start the download. /// %@ requires the download of additional configuration files.\n\nConfirm to start the download.
internal static func message(_ p1: String) -> String { internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "service.alerts.download.message", p1) return L10n.tr("Core", "service.alerts.download.message", String(describing: p1))
} }
/// Download required /// Download required
internal static let title = L10n.tr("Core", "service.alerts.download.title") internal static let title = L10n.tr("Core", "service.alerts.download.title")
@ -908,8 +907,8 @@ internal enum L10n {
} }
internal enum ProviderInfrastructure { internal enum ProviderInfrastructure {
/// Last updated on %@. /// Last updated on %@.
internal static func footer(_ p1: String) -> String { internal static func footer(_ p1: Any) -> String {
return L10n.tr("Core", "service.sections.provider_infrastructure.footer", p1) return L10n.tr("Core", "service.sections.provider_infrastructure.footer", String(describing: p1))
} }
} }
internal enum Trusted { internal enum Trusted {
@ -1081,10 +1080,15 @@ internal enum L10n {
extension L10n { extension L10n {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
// swiftlint:disable:next nslocalizedstring_key let format = BundleToken.bundle.localizedString(forKey: key, value: nil, table: table)
let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "")
return String(format: format, locale: Locale.current, arguments: args) return String(format: format, locale: Locale.current, arguments: args)
} }
} }
private final class BundleToken {} // swiftlint:disable convenience_type
private final class BundleToken {
static let bundle: Bundle = {
Bundle(for: BundleToken.self)
}()
}
// swiftlint:enable convenience_type

View File

@ -194,7 +194,7 @@ extension MFMailComposeViewController {
extension Infrastructure.Metadata { extension Infrastructure.Metadata {
var logo: UIImage? { var logo: UIImage? {
let bundle = Bundle(for: AppDelegate.self) let bundle = Bundle(for: AppDelegate.self)
guard let image = AssetImageTypeAlias(named: name, in: bundle, compatibleWith: nil) else { guard let image = ImageAsset.Image(named: name, in: bundle, compatibleWith: nil) else {
return Asset.Providers.placeholder.image return Asset.Providers.placeholder.image
} }
return image return image

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "csv@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "csv@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -60,6 +60,7 @@ Passepartout is a VPN client and does absolutely nothing else without your conse
Passepartout can connect to a few well-known VPN providers with an existing account: Passepartout can connect to a few well-known VPN providers with an existing account:
- [Child Safe VPN][app-net-csv]
- [Hide.me][app-net-hideme] - [Hide.me][app-net-hideme]
- [Mullvad][app-net-mullvad] - [Mullvad][app-net-mullvad]
- [NordVPN][app-net-nordvpn] - [NordVPN][app-net-nordvpn]
@ -177,6 +178,7 @@ Website: [passepartoutvpn.app][about-website]
[openvpn]: https://openvpn.net/index.php/open-source/overview.html [openvpn]: https://openvpn.net/index.php/open-source/overview.html
[app-api]: https://github.com/passepartoutvpn/passepartout-api [app-api]: https://github.com/passepartoutvpn/passepartout-api
[app-net-csv]: https://childsafevpn.com
[app-net-hideme]: https://member.hide.me/en/checkout?plan=new_default_prices&coupon=6CB-BDB-802&duration=24 [app-net-hideme]: https://member.hide.me/en/checkout?plan=new_default_prices&coupon=6CB-BDB-802&duration=24
[app-net-mullvad]: https://mullvad.net/en/account/create/ [app-net-mullvad]: https://mullvad.net/en/account/create/
[app-net-nordvpn]: https://go.nordvpn.net/SH21Z [app-net-nordvpn]: https://go.nordvpn.net/SH21Z

@ -1 +1 @@
Subproject commit 52d86ee536c84d9f440fa6a2914c54cea4563c73 Subproject commit ccc00bf1f0f2b497cc68b18be92cc521a78dfb52