Add Child Safe VPN provider
This commit is contained in:
parent
32ea6a9cfd
commit
7c6a404e4a
|
@ -18,3 +18,4 @@ templates/
|
|||
Preview.html
|
||||
l10n
|
||||
passepartout-translations.zip
|
||||
default.profraw
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 |
|
@ -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
|
Loading…
Reference in New Issue