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
l10n
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
## Added
- Child Safe VPN provider.
## Changed
- Use active profile name in iOS settings.

View File

@ -1,18 +1,19 @@
// swiftlint:disable all
// Generated using SwiftGen https://github.com/SwiftGen/SwiftGen
#if os(OSX)
import AppKit.NSImage
internal typealias AssetColorTypeAlias = NSColor
internal typealias AssetImageTypeAlias = NSImage
#elseif os(iOS) || os(tvOS) || os(watchOS)
import UIKit.UIImage
internal typealias AssetColorTypeAlias = UIColor
internal typealias AssetImageTypeAlias = UIImage
#if os(macOS)
import AppKit
#elseif os(iOS)
import UIKit
#elseif os(tvOS) || os(watchOS)
import UIKit
#endif
// swiftlint:disable superfluous_disable_command
// swiftlint:disable file_length
// Deprecated typealiases
@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
@ -281,6 +282,7 @@ internal enum Asset {
internal static let zw = ImageAsset(name: "zw")
}
internal enum Providers {
internal static let csv = ImageAsset(name: "csv")
internal static let hideme = ImageAsset(name: "hideme")
internal static let mullvad = ImageAsset(name: "mullvad")
internal static let nordvpn = ImageAsset(name: "nordvpn")
@ -297,80 +299,39 @@ internal enum Asset {
// 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 fileprivate(set) var name: String
internal var image: AssetImageTypeAlias {
let bundle = Bundle(for: BundleToken.self)
#if os(macOS)
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)
let image = AssetImageTypeAlias(named: name, in: bundle, compatibleWith: nil)
#elseif os(OSX)
let image = Image(named: name, in: bundle, compatibleWith: nil)
#elseif os(macOS)
let image = bundle.image(forResource: NSImage.Name(name))
#elseif os(watchOS)
let image = AssetImageTypeAlias(named: name)
let image = Image(named: name)
#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
}
}
internal extension AssetImageTypeAlias {
@available(iOS 1.0, tvOS 1.0, watchOS 1.0, *)
@available(OSX, deprecated,
internal extension ImageAsset.Image {
@available(macOS, deprecated,
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
convenience init!(asset: ImageAsset) {
#if os(iOS) || os(tvOS)
let bundle = Bundle(for: BundleToken.self)
let bundle = BundleToken.bundle
self.init(named: asset.name, in: bundle, compatibleWith: nil)
#elseif os(OSX)
#elseif os(macOS)
self.init(named: NSImage.Name(asset.name))
#elseif os(watchOS)
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 {
static var storyboard: UIStoryboard {
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
// swiftlint:disable superfluous_disable_command
// swiftlint:disable file_length
// swiftlint:disable superfluous_disable_command file_length implicit_return
// MARK: - Strings
@ -98,8 +97,8 @@ internal enum L10n {
internal enum Cells {
internal enum FullVersion {
/// - All providers (including future ones)\n%@
internal static func extraDescription(_ p1: String) -> String {
return L10n.tr("App", "purchase.cells.full_version.extra_description", p1)
internal static func extraDescription(_ p1: Any) -> String {
return L10n.tr("App", "purchase.cells.full_version.extra_description", String(describing: p1))
}
}
internal enum Restore {
@ -264,8 +263,8 @@ internal enum L10n {
}
internal enum Signup {
/// Register with %@
internal static func caption(_ p1: String) -> String {
return L10n.tr("Core", "account.cells.signup.caption", p1)
internal static func caption(_ p1: Any) -> String {
return L10n.tr("Core", "account.cells.signup.caption", String(describing: p1))
}
}
internal enum Username {
@ -280,48 +279,48 @@ internal enum L10n {
internal enum Footer {
internal enum Infrastructure {
/// Use your %@ website credentials.
internal static func hideme(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.hideme", p1)
internal static func hideme(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.hideme", String(describing: p1))
}
/// Use your %@ website credentials. Your username is usually numeric (without spaces).
internal static func mullvad(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.mullvad", p1)
internal static func mullvad(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.mullvad", String(describing: p1))
}
/// Use your %@ website credentials. Your username is usually your e-mail.
internal static func nordvpn(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.nordvpn", p1)
internal static func nordvpn(_ p1: Any) -> String {
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.
internal static func pia(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.pia", p1)
internal static func pia(_ p1: Any) -> String {
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.
internal static func protonvpn(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.protonvpn", p1)
internal static func protonvpn(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.protonvpn", String(describing: p1))
}
/// Use your %@ service credentials, which may differ from website credentials.
internal static func torguard(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.torguard", p1)
internal static func torguard(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.torguard", String(describing: p1))
}
/// Use your %@ website credentials. Your username is usually your e-mail.
internal static func tunnelbear(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.tunnelbear", p1)
internal static func tunnelbear(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.tunnelbear", String(describing: p1))
}
/// Use your %@ website credentials. Your username is usually your e-mail.
internal static func vyprvpn(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.vyprvpn", p1)
internal static func vyprvpn(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.vyprvpn", String(describing: p1))
}
/// Find your %@ credentials in the OpenVPN Config Generator on the website.
internal static func windscribe(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.windscribe", p1)
internal static func windscribe(_ p1: Any) -> String {
return L10n.tr("Core", "account.sections.guidance.footer.infrastructure.windscribe", String(describing: p1))
}
}
}
}
internal enum Registration {
/// Go get an account on the %@ website.
internal static func footer(_ p1: String) -> String {
return L10n.tr("Core", "account.sections.registration.footer", p1)
internal static func footer(_ p1: Any) -> String {
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 enum Value {
/// after %@
internal static func after(_ p1: String) -> String {
return L10n.tr("Core", "configuration.cells.renegotiation_seconds.value.after", p1)
internal static func after(_ p1: Any) -> String {
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 Failure {
/// Unable to perform the donation. %@
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "donation.alerts.purchase.failure.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "donation.alerts.purchase.failure.message", String(describing: p1))
}
}
internal enum Success {
@ -628,8 +627,8 @@ internal enum L10n {
internal enum Cells {
internal enum About {
/// About %@
internal static func caption(_ p1: String) -> String {
return L10n.tr("Core", "organizer.cells.about.caption", p1)
internal static func caption(_ p1: Any) -> String {
return L10n.tr("Core", "organizer.cells.about.caption", String(describing: p1))
}
}
internal enum Donate {
@ -712,32 +711,32 @@ internal enum L10n {
}
internal enum Malformed {
/// The configuration file contains a malformed option (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.malformed.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.malformed.message", String(describing: p1))
}
}
internal enum Missing {
/// The configuration file lacks a required option (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.missing.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.missing.message", String(describing: p1))
}
}
internal enum Parsing {
/// Unable to parse the provided configuration file (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.parsing.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.parsing.message", String(describing: p1))
}
}
internal enum PotentiallyUnsupported {
/// 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 {
return L10n.tr("Core", "parsed_file.alerts.potentially_unsupported.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.potentially_unsupported.message", String(describing: p1))
}
}
internal enum Unsupported {
/// The configuration file contains an unsupported option (%@).
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "parsed_file.alerts.unsupported.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "parsed_file.alerts.unsupported.message", String(describing: p1))
}
}
}
@ -780,12 +779,12 @@ internal enum L10n {
}
internal enum Download {
/// Failed to download configuration files. %@
internal static func failed(_ p1: String) -> String {
return L10n.tr("Core", "service.alerts.download.failed", p1)
internal static func failed(_ p1: Any) -> String {
return L10n.tr("Core", "service.alerts.download.failed", String(describing: p1))
}
/// %@ requires the download of additional configuration files.\n\nConfirm to start the download.
internal static func message(_ p1: String) -> String {
return L10n.tr("Core", "service.alerts.download.message", p1)
internal static func message(_ p1: Any) -> String {
return L10n.tr("Core", "service.alerts.download.message", String(describing: p1))
}
/// Download required
internal static let title = L10n.tr("Core", "service.alerts.download.title")
@ -908,8 +907,8 @@ internal enum L10n {
}
internal enum ProviderInfrastructure {
/// Last updated on %@.
internal static func footer(_ p1: String) -> String {
return L10n.tr("Core", "service.sections.provider_infrastructure.footer", p1)
internal static func footer(_ p1: Any) -> String {
return L10n.tr("Core", "service.sections.provider_infrastructure.footer", String(describing: p1))
}
}
internal enum Trusted {
@ -1081,10 +1080,15 @@ internal enum L10n {
extension L10n {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
// swiftlint:disable:next nslocalizedstring_key
let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "")
let format = BundleToken.bundle.localizedString(forKey: key, value: nil, table: table)
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 {
var logo: UIImage? {
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 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:
- [Child Safe VPN][app-net-csv]
- [Hide.me][app-net-hideme]
- [Mullvad][app-net-mullvad]
- [NordVPN][app-net-nordvpn]
@ -177,6 +178,7 @@ Website: [passepartoutvpn.app][about-website]
[openvpn]: https://openvpn.net/index.php/open-source/overview.html
[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-mullvad]: https://mullvad.net/en/account/create/
[app-net-nordvpn]: https://go.nordvpn.net/SH21Z

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