diff --git a/.env b/.env deleted file mode 100644 index 81c9e5f2..00000000 --- a/.env +++ /dev/null @@ -1,12 +0,0 @@ -PLATFORM="ios" -APP_NAME="Passepartout" -PROJECT="Passepartout-iOS" - -GYM_SCHEME="Passepartout-iOS" -MATCH_READONLY="true" -BUILD_PATH="build" -DIST_PATH="dist" - -# constant (fastlane) -LC_ALL="en_US.UTF-8" -LANG="en_US.UTF-8" diff --git a/.env.beta-archive b/.env.beta-archive deleted file mode 100644 index 64a23f6a..00000000 --- a/.env.beta-archive +++ /dev/null @@ -1,2 +0,0 @@ -MATCH_TYPE="appstore" -GYM_EXPORT_METHOD="app-store" diff --git a/.env.beta-deploy b/.env.beta-deploy deleted file mode 100644 index 97ab8c80..00000000 --- a/.env.beta-deploy +++ /dev/null @@ -1,3 +0,0 @@ -PILOT_IPA="$DIST_PATH/$TARGET/$APP_NAME.ipa" -PILOT_DISTRIBUTE_EXTERNAL="true" -DEMO_ACCOUNT_REQUIRED="true" diff --git a/.env.dev-archive b/.env.dev-archive deleted file mode 100644 index cc2fad4a..00000000 --- a/.env.dev-archive +++ /dev/null @@ -1,2 +0,0 @@ -MATCH_TYPE="adhoc" -GYM_EXPORT_METHOD="ad-hoc" diff --git a/.env.dev-deploy b/.env.dev-deploy deleted file mode 100644 index deaf7dc9..00000000 --- a/.env.dev-deploy +++ /dev/null @@ -1,3 +0,0 @@ -APPCENTER_APP_NAME=$GYM_SCHEME -APPCENTER_DISTRIBUTE_IPA="$DIST_PATH/$TARGET/$APP_NAME.ipa" -APPCENTER_DISTRIBUTE_DESTINATION_TYPE="group" diff --git a/.env.template.secret-codesign b/.env.template.secret-codesign deleted file mode 100644 index c8924c7d..00000000 --- a/.env.template.secret-codesign +++ /dev/null @@ -1,2 +0,0 @@ -MATCH_GIT_URL= -MATCH_PASSWORD= diff --git a/.env.template.secret-deploy b/.env.template.secret-deploy deleted file mode 100644 index 7544df2e..00000000 --- a/.env.template.secret-deploy +++ /dev/null @@ -1,10 +0,0 @@ -APPLE_ID= -FASTLANE_USERNAME= -FASTLANE_PASSWORD= -APPCENTER_OWNER_NAME= -APPCENTER_API_TOKEN= -APPCENTER_DISTRIBUTE_DESTINATIONS= -PILOT_GROUPS= -PILOT_USERNAME= -DELIVER_USERNAME= -PROJECT_ROOT= diff --git a/.gitignore b/.gitignore index e6ed1d5b..af3553e3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,12 +5,12 @@ **/*.xcodeproj/project.xcworkspace **/*.xcodeproj/xcuserdata Pods -fastlane/**/*.html -fastlane/README.md -fastlane/report.xml -fastlane/test_output -fastlane/metadata/review_information -fastlane/metadata/trade_representative_contact_information +**/fastlane/**/*.html +**/fastlane/README.md +**/fastlane/report.xml +**/fastlane/test_output +**/fastlane/metadata/review_information +**/fastlane/metadata/trade_representative_contact_information build/ dist/ templates/ diff --git a/.gitmodules b/.gitmodules index 7848bb5c..c92abb84 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "Submodules/API"] path = Submodules/API url = https://github.com/passepartoutvpn/api -[submodule "Submodules/Core"] - path = Submodules/Core - url = https://github.com/passepartoutvpn/passepartout-core-apple [submodule "Submodules/fastlane-ci-templates"] path = Submodules/fastlane-ci-templates url = https://github.com/keeshux/fastlane-ci-templates diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9dffc5e6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: objective-c +osx_image: xcode12 +xcode_workspace: Passepartout.xcworkspace +xcode_scheme: PassepartoutCore-iOS +xcode_destination: platform=iOS Simulator,OS=12.4,name=iPhone Xʀ +cache: + - bundler + - cocoapods +install: + - bundle install --jobs=3 --deployment --path=${BUNDLE_PATH:-vendor/bundle} + - bundle exec pod repo update + - travis_wait 40 bundle exec pod install + +branches: + only: + - master diff --git a/Passepartout-iOS/Config.xcconfig b/Config.xcconfig similarity index 74% rename from Passepartout-iOS/Config.xcconfig rename to Config.xcconfig index 0da0e235..92c98ff2 100644 --- a/Passepartout-iOS/Config.xcconfig +++ b/Config.xcconfig @@ -27,6 +27,13 @@ // https://help.apple.com/xcode/#/dev745c5c974 CFG_TEAM_ID = DTDYD63ZX9 -CFG_APP_ID = com.algoritmico.ios.Passepartout +CFG_APP_IOS_ID = com.algoritmico.ios.Passepartout +CFG_APP_MACOS_ID = com.algoritmico.macos.Passepartout +CFG_APP_LAUNCHER_ID = com.algoritmico.macos.Passepartout.Launcher CFG_GROUP_ID = com.algoritmico.Passepartout -CFG_APPSTORE_ID = 1433648537 +CFG_APP_VERSION = 1.14.0 +CFG_APPSTORE_IOS_ID = 1433648537 +CFG_APPSTORE_MACOS_ID = 1433645014 +CFG_COPYRIGHT = Copyright © 2021 Davide De Rosa. All rights reserved. + +#include? "Secret.xcconfig" diff --git a/Libraries/API b/Libraries/API deleted file mode 120000 index b4015434..00000000 --- a/Libraries/API +++ /dev/null @@ -1 +0,0 @@ -../Submodules/API/ \ No newline at end of file diff --git a/Libraries/Core b/Libraries/Core deleted file mode 120000 index 01be531a..00000000 --- a/Libraries/Core +++ /dev/null @@ -1 +0,0 @@ -../Submodules/Core/ \ No newline at end of file diff --git a/Passepartout-iOS/Scenes/About/CreditsViewController.swift b/Passepartout-iOS/Scenes/About/CreditsViewController.swift deleted file mode 100644 index 71509aa4..00000000 --- a/Passepartout-iOS/Scenes/About/CreditsViewController.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// CreditsViewController.swift -// Passepartout-iOS -// -// Created by Davide De Rosa on 11/26/18. -// Copyright (c) 2019 Davide De Rosa. All rights reserved. -// -// https://github.com/passepartoutvpn -// -// This file is part of Passepartout. -// -// Passepartout is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Passepartout is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Passepartout. If not, see . -// - -import UIKit -import PassepartoutCore -import Convenience - -//class CreditsViewController: Convenience.CreditsViewController { -// override func viewDidLoad() { -// title = L10n.Core.Credits.title -// licensesHeader = L10n.Core.Credits.Sections.Licenses.header -// noticesHeader = L10n.Core.Credits.Sections.Notices.header -// translationsHeader = L10n.Core.Credits.Sections.Translations.header -// software = AppConstants.Credits.software -// translators = AppConstants.Translations.translators -// accentColor = Theme.current.palette.accent1 -// -// super.viewDidLoad() -// } -//} - -// override func prepare(for segue: UIStoryboardSegue, sender: Any?) { -// guard let vc = segue.destination as? LabelViewController else { -// return -// } -// guard let cell = sender as? SettingTableViewCell, let indexPath = tableView.indexPath(for: cell) else { -// return -// } -// vc.title = cell.leftText -// switch model.row(at: indexPath) { -// case .license: -// vc.license = licenses[indexPath.row] -// -// case .notice: -// vc.text = notices[indexPath.row].statement -// -// default: -// break -// } -// } -//} -// -//extension CreditsViewController { -// enum SectionType: Int { -// case licenses -// -// case notices -// -// case translations -// } -// -// enum RowType: Int { -// case license -// -// case notice -// -// case translation -// } -// -// override func numberOfSections(in tableView: UITableView) -> Int { -// return model.numberOfSections -// } -// -// override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { -// return model.header(forSection: section) -// } -// -// override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { -// return model.numberOfRows(forSection: section) -// } -// -// override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { -// let cell = Cells.setting.dequeue(from: tableView, for: indexPath) -// switch model.row(at: indexPath) { -// case .license: -// let obj = licenses[indexPath.row] -// cell.leftText = obj.name -// cell.rightText = obj.type -// -// case .notice: -// let obj = notices[indexPath.row] -// cell.leftText = obj.name -// cell.rightText = nil -// -// } -// return cell -// } -//} diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 592b6a9e..90714d33 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -3,10 +3,12 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ + 051985241A3ABE44EB09DFF5 /* Pods_ios_PassepartoutTunnel_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FF7D2E624A2979425A6F7B7A /* Pods_ios_PassepartoutTunnel_iOS.framework */; }; + 0774835EE25EEA07495A98AA /* Pods_macos_PassepartoutTunnel_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 35380A14E9FF6F0250C171CD /* Pods_macos_PassepartoutTunnel_macOS.framework */; }; 0E05C5D420D1645F006EE732 /* FieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05C5CE20D139AF006EE732 /* FieldTableViewCell.swift */; }; 0E05C5D520D1645F006EE732 /* SettingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED824CD20D12DBE00F2FE9E /* SettingTableViewCell.swift */; }; 0E05C5D620D1645F006EE732 /* SwiftGen+Scenes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DE320C89028004C739C /* SwiftGen+Scenes.swift */; }; @@ -15,7 +17,6 @@ 0E0C0729236087A100155AAC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E0C072B236087A100155AAC /* InfoPlist.strings */; }; 0E1066C920E0F84A004F98B7 /* Cells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1066C820E0F84A004F98B7 /* Cells.swift */; }; 0E158ADA20E11B0B00C85A82 /* EndpointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */; }; - 0E1C0A4F238FC7A5009FC087 /* InfrastructureFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1C0A4E238FC7A5009FC087 /* InfrastructureFactory.swift */; }; 0E1D72B2213BFFCF00BA1586 /* ProviderPresetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1D72B1213BFFCF00BA1586 /* ProviderPresetViewController.swift */; }; 0E1D72B4213C118500BA1586 /* ConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1D72B3213C118500BA1586 /* ConfigurationViewController.swift */; }; 0E24273A225950450064A1A3 /* About.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E24273C225950450064A1A3 /* About.storyboard */; }; @@ -59,13 +60,116 @@ 0E3CAFC4229AAF8E0008E5C8 /* API in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAFC3229AAF8E0008E5C8 /* API */; }; 0E45E6E022BD793800F19312 /* App.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E45E6E222BD793800F19312 /* App.strings */; }; 0E45E6E422BD799700F19312 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E45E6E322BD799700F19312 /* SwiftGen+Strings.swift */; }; - 0E45E6FA22BD8FC500F19312 /* Core.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAF98229AAE760008E5C8 /* Core.strings */; }; 0E45E71022BE108100F19312 /* OpenVPNOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E45E70F22BE108100F19312 /* OpenVPNOptions.swift */; }; 0E4B0D6B2366E3C100C890B4 /* PurchaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4B0D6A2366E3C000C890B4 /* PurchaseViewController.swift */; }; 0E4B0D742366E6C800C890B4 /* Purchase.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E4B0D762366E6C800C890B4 /* Purchase.storyboard */; }; 0E4C9CBB20DCF0D600A0C59C /* DestructiveTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */; }; 0E4FD7F120D58618002221FF /* Macros.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7F020D58618002221FF /* Macros.swift */; }; + 0E52031D259F58BF00CBAB56 /* Providers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F7D259F41690022DFB8 /* Providers.xcassets */; }; + 0E52031E259F58BF00CBAB56 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F7F259F41690022DFB8 /* Assets.xcassets */; }; + 0E52031F259F58BF00CBAB56 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E569FA7259F41690022DFB8 /* Flags.xcassets */; }; + 0E520320259F58BF00CBAB56 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F8B259F41690022DFB8 /* AppDelegate.swift */; }; + 0E52032B259F58DD00CBAB56 /* TextTableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F5A259F41690022DFB8 /* TextTableView.xib */; }; + 0E52032C259F58DD00CBAB56 /* TextTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F5B259F41690022DFB8 /* TextTableView.swift */; }; + 0E520333259F58F500CBAB56 /* OrganizerProfileTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F69259F41690022DFB8 /* OrganizerProfileTableView.swift */; }; + 0E520334259F58F500CBAB56 /* OrganizerProfileTableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F6B259F41690022DFB8 /* OrganizerProfileTableView.xib */; }; + 0E520335259F58F500CBAB56 /* HostServiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F7A259F41690022DFB8 /* HostServiceView.swift */; }; + 0E520336259F58F500CBAB56 /* HostServiceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F7B259F41690022DFB8 /* HostServiceView.xib */; }; + 0E520337259F58F500CBAB56 /* ProviderServiceView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F79259F41690022DFB8 /* ProviderServiceView.xib */; }; + 0E520338259F58F500CBAB56 /* ProviderServiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F6E259F41690022DFB8 /* ProviderServiceView.swift */; }; + 0E520339259F58F500CBAB56 /* ServiceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F6D259F41690022DFB8 /* ServiceViewController.swift */; }; + 0E52033A259F58F500CBAB56 /* AccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F7C259F41690022DFB8 /* AccountViewController.swift */; }; + 0E52033B259F58F500CBAB56 /* OrganizerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F6A259F41690022DFB8 /* OrganizerViewController.swift */; }; + 0E520342259F58FE00CBAB56 /* EndpointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F71259F41690022DFB8 /* EndpointViewController.swift */; }; + 0E520343259F58FE00CBAB56 /* ProfileCustomizationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F73259F41690022DFB8 /* ProfileCustomizationViewController.swift */; }; + 0E520344259F58FE00CBAB56 /* TrustedNetworksAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F75259F41690022DFB8 /* TrustedNetworksAddViewController.swift */; }; + 0E520345259F58FE00CBAB56 /* DNSViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F76259F41690022DFB8 /* DNSViewController.swift */; }; + 0E520346259F58FE00CBAB56 /* TrustedNetworksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F78259F41690022DFB8 /* TrustedNetworksViewController.swift */; }; + 0E520347259F58FE00CBAB56 /* ProxyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F74259F41690022DFB8 /* ProxyViewController.swift */; }; + 0E520348259F58FE00CBAB56 /* MTUViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F70259F41690022DFB8 /* MTUViewController.swift */; }; + 0E520349259F58FE00CBAB56 /* ConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F72259F41690022DFB8 /* ConfigurationViewController.swift */; }; + 0E52034A259F58FE00CBAB56 /* DefaultGatewayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F77259F41690022DFB8 /* DefaultGatewayViewController.swift */; }; + 0E520354259F590600CBAB56 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F67259F41690022DFB8 /* PreferencesViewController.swift */; }; + 0E520355259F590600CBAB56 /* DebugLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F66259F41690022DFB8 /* DebugLogViewController.swift */; }; + 0E520356259F590600CBAB56 /* PreferencesGeneralViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F68259F41690022DFB8 /* PreferencesGeneralViewController.swift */; }; + 0E52035D259F591300CBAB56 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F8A259F41690022DFB8 /* MainMenu.xib */; }; + 0E52035E259F591300CBAB56 /* StatusMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F89259F41690022DFB8 /* StatusMenu.swift */; }; + 0E52035F259F591300CBAB56 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F88259F41690022DFB8 /* MainMenu.swift */; }; + 0E520379259F593B00CBAB56 /* Macros.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569FA6259F41690022DFB8 /* Macros.swift */; }; + 0E52037A259F593B00CBAB56 /* WindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F92259F41690022DFB8 /* WindowManager.swift */; }; + 0E52037B259F593B00CBAB56 /* IssueReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F8F259F41690022DFB8 /* IssueReporter.swift */; }; + 0E52037C259F593B00CBAB56 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569FA1259F41690022DFB8 /* Theme.swift */; }; + 0E52037D259F593B00CBAB56 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F9C259F41690022DFB8 /* SwiftGen+Strings.swift */; }; + 0E52037E259F593B00CBAB56 /* SwiftGen+Segues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569FA5259F41690022DFB8 /* SwiftGen+Segues.swift */; }; + 0E52037F259F593B00CBAB56 /* Theme+Views.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F9A259F41690022DFB8 /* Theme+Views.swift */; }; + 0E520380259F593B00CBAB56 /* AppConstants+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569FA3259F41690022DFB8 /* AppConstants+App.swift */; }; + 0E520381259F593B00CBAB56 /* NSTextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F94259F41690022DFB8 /* NSTextView+Search.swift */; }; + 0E520382259F593B00CBAB56 /* SwiftGen+Scenes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F9D259F41690022DFB8 /* SwiftGen+Scenes.swift */; }; + 0E520383259F593B00CBAB56 /* SwiftGen+Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F98259F41690022DFB8 /* SwiftGen+Assets.swift */; }; + 0E520384259F593B00CBAB56 /* Donation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F99259F41690022DFB8 /* Donation.swift */; }; + 0E520385259F593B00CBAB56 /* Credits.html in Resources */ = {isa = PBXBuildFile; fileRef = 0E569FA4259F41690022DFB8 /* Credits.html */; }; + 0E520386259F593B00CBAB56 /* ProductManager+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F9E259F41690022DFB8 /* ProductManager+App.swift */; }; + 0E520387259F593B00CBAB56 /* TextInputViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F97259F41690022DFB8 /* TextInputViewController.swift */; }; + 0E520388259F593B00CBAB56 /* HostImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F93259F41690022DFB8 /* HostImporter.swift */; }; + 0E52038F259F593F00CBAB56 /* App.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F8D259F41690022DFB8 /* App.strings */; }; + 0E5203B6259F5F3F00CBAB56 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ED31C3920CF39510027975F /* NetworkExtension.framework */; }; + 0E5203BE259F5F3F00CBAB56 /* PassepartoutTunnel.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0E5203B5259F5F3F00CBAB56 /* PassepartoutTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0E5203F1259F60D600CBAB56 /* PassepartoutCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E5203EA259F60D600CBAB56 /* PassepartoutCore.framework */; }; + 0E5203F2259F60D600CBAB56 /* PassepartoutCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0E5203EA259F60D600CBAB56 /* PassepartoutCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 0E52041F259F62B200CBAB56 /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; }; + 0E52047B259F642600CBAB56 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F85259F41690022DFB8 /* Main.storyboard */; }; + 0E52047C259F642600CBAB56 /* Service.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F83259F41690022DFB8 /* Service.storyboard */; }; + 0E52047D259F642600CBAB56 /* Preferences.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F81259F41690022DFB8 /* Preferences.storyboard */; }; + 0E5204A7259F66F700CBAB56 /* PassepartoutCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E31529D223F9EF500F61841 /* PassepartoutCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0E5204A9259F673000CBAB56 /* Core.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAF98229AAE760008E5C8 /* Core.strings */; }; + 0E5204AA259F673100CBAB56 /* Core.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAF98229AAE760008E5C8 /* Core.strings */; }; + 0E5204AF259F673D00CBAB56 /* ApplicationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */; }; + 0E5204B0259F673D00CBAB56 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F14259F2D3E0022DFB8 /* Issue.swift */; }; + 0E5204B1259F673D00CBAB56 /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; }; + 0E5204B2259F673D00CBAB56 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7ED20D539A0002221FF /* Utils.swift */; }; + 0E5204B7259F674000CBAB56 /* AppConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E39BCF2214DA9310035E9DE /* AppConstants.swift */; }; + 0E5204BC259F674400CBAB56 /* TrustedNetworksUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F30259F2DC10022DFB8 /* TrustedNetworksUI.swift */; }; + 0E5204C1259F675400CBAB56 /* Infrastructure+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F29259F2DB10022DFB8 /* Infrastructure+Metadata.swift */; }; + 0E5204C2259F675400CBAB56 /* PoolCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E66A26F225FE25800F9C779 /* PoolCategory.swift */; }; + 0E5204C3259F675400CBAB56 /* InfrastructureFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F2A259F2DB10022DFB8 /* InfrastructureFactory.swift */; }; + 0E5204C4259F675400CBAB56 /* TrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3A8F213C6F4000BFA2F5 /* TrustPolicy.swift */; }; + 0E5204C5259F675400CBAB56 /* ProviderConnectionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3AA4213DC1B000BFA2F5 /* ProviderConnectionProfile.swift */; }; + 0E5204C6259F675400CBAB56 /* Pool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED31C0F20CF09A30027975F /* Pool.swift */; }; + 0E5204C7259F675400CBAB56 /* Product.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F1B259F2D8F0022DFB8 /* Product.swift */; }; + 0E5204C8259F675400CBAB56 /* PoolGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E533B152258E03B00EF94FC /* PoolGroup.swift */; }; + 0E5204C9259F675400CBAB56 /* ConnectionService+Configurations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E2D11B9217DBEDE0096822C /* ConnectionService+Configurations.swift */; }; + 0E5204CA259F675400CBAB56 /* ProfileNetworkSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFB901722764689006405E4 /* ProfileNetworkSettings.swift */; }; + 0E5204CB259F675400CBAB56 /* EndpointDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED38AE621404F100004D387 /* EndpointDataSource.swift */; }; + 0E5204CC259F675400CBAB56 /* HostConnectionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3AA3213DC1B000BFA2F5 /* HostConnectionProfile.swift */; }; + 0E5204CD259F675400CBAB56 /* Infrastructure+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F28259F2DB10022DFB8 /* Infrastructure+Name.swift */; }; + 0E5204CE259F675400CBAB56 /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DE620C93945004C739C /* Credentials.swift */; }; + 0E5204CF259F675400CBAB56 /* TrustedNetworks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4C9CB820DB9BC600A0C59C /* TrustedNetworks.swift */; }; + 0E5204D0259F675400CBAB56 /* Infrastructure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED31C1120CF0ABA0027975F /* Infrastructure.swift */; }; + 0E5204D1259F675400CBAB56 /* PlaceholderConnectionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79D13E21919EC900BB5FB2 /* PlaceholderConnectionProfile.swift */; }; + 0E5204D2259F675400CBAB56 /* ConnectionProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3A9E213DC1A100BFA2F5 /* ConnectionProfile.swift */; }; + 0E5204D3259F675400CBAB56 /* ConnectionService+Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBBE8F42182361700106008 /* ConnectionService+Migration.swift */; }; + 0E5204D4259F675400CBAB56 /* ConnectionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3A9F213DC1A100BFA2F5 /* ConnectionService.swift */; }; + 0E5204D5259F675400CBAB56 /* ProfileKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E79D14021919F5600BB5FB2 /* ProfileKey.swift */; }; + 0E5204D6259F675400CBAB56 /* DataUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECEB109224FECEA00E9E551 /* DataUnit.swift */; }; + 0E5204D7259F675400CBAB56 /* DebugLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC7F20420E24308004EA58E /* DebugLog.swift */; }; + 0E5204D9259F675400CBAB56 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC4213DF7AE00741BA1 /* Preferences.swift */; }; + 0E5204DA259F675400CBAB56 /* ProductManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F1A259F2D8F0022DFB8 /* ProductManager.swift */; }; + 0E5204DB259F675400CBAB56 /* TransientStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E2B494120FD16540094784C /* TransientStore.swift */; }; + 0E5204DC259F675400CBAB56 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F19259F2D8F0022DFB8 /* GracefulVPN.swift */; }; + 0E5204DD259F675400CBAB56 /* InfrastructurePreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */; }; + 0E5204DE259F675400CBAB56 /* OpenVPNOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E45E70F22BE108100F19312 /* OpenVPNOptions.swift */; }; + 0E5204DF259F675400CBAB56 /* SessionProxy+Communication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */; }; + 0E5204E0259F675400CBAB56 /* WebServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E39BCEF214B9EF10035E9DE /* WebServices.swift */; }; + 0E5204E5259F67A000CBAB56 /* API in Resources */ = {isa = PBXBuildFile; fileRef = 0E3CAFC3229AAF8E0008E5C8 /* API */; }; 0E533B162258E03B00EF94FC /* PoolGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E533B152258E03B00EF94FC /* PoolGroup.swift */; }; + 0E569F15259F2D3E0022DFB8 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F14259F2D3E0022DFB8 /* Issue.swift */; }; + 0E569F1C259F2D8F0022DFB8 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F19259F2D8F0022DFB8 /* GracefulVPN.swift */; }; + 0E569F1E259F2D8F0022DFB8 /* ProductManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F1A259F2D8F0022DFB8 /* ProductManager.swift */; }; + 0E569F20259F2D8F0022DFB8 /* Product.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F1B259F2D8F0022DFB8 /* Product.swift */; }; + 0E569F2B259F2DB10022DFB8 /* Infrastructure+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F28259F2DB10022DFB8 /* Infrastructure+Name.swift */; }; + 0E569F2C259F2DB10022DFB8 /* Infrastructure+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F29259F2DB10022DFB8 /* Infrastructure+Metadata.swift */; }; + 0E569F2D259F2DB10022DFB8 /* InfrastructureFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F2A259F2DB10022DFB8 /* InfrastructureFactory.swift */; }; + 0E569F31259F2DC10022DFB8 /* TrustedNetworksUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F30259F2DC10022DFB8 /* TrustedNetworksUI.swift */; }; 0E57F63C20C83FC5008323CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E57F63B20C83FC5008323CF /* AppDelegate.swift */; }; 0E57F63E20C83FC5008323CF /* ServiceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E57F63D20C83FC5008323CF /* ServiceViewController.swift */; }; 0E57F64120C83FC5008323CF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E57F63F20C83FC5008323CF /* Main.storyboard */; }; @@ -77,20 +181,32 @@ 0E773BF8224BF37600CDDC8E /* ShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E773BF7224BF37600CDDC8E /* ShortcutsViewController.swift */; }; 0E776642229D0DAE0023FA76 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0E3CAFAD229AAE760008E5C8 /* Intents.intentdefinition */; settings = {ATTRIBUTES = (no_codegen, ); }; }; 0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; }; + 0E9AA978259F756A003FAFF1 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA977259F756A003FAFF1 /* PacketTunnelProvider.swift */; }; + 0E9AA979259F756A003FAFF1 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA977259F756A003FAFF1 /* PacketTunnelProvider.swift */; }; + 0E9AA992259F779F003FAFF1 /* PassepartoutCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E31529B223F9EF400F61841 /* PassepartoutCore.framework */; platformFilter = ios; }; + 0E9AA9BF259F7821003FAFF1 /* PassepartoutCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E5203EA259F60D600CBAB56 /* PassepartoutCore.framework */; }; + 0E9AA9EF259F799B003FAFF1 /* ConnectionServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA987259F777B003FAFF1 /* ConnectionServiceTests.swift */; }; + 0E9AA9F0259F799B003FAFF1 /* ConnectionService.json in Resources */ = {isa = PBXBuildFile; fileRef = 0E9AA988259F777B003FAFF1 /* ConnectionService.json */; }; + 0E9AA9F1259F799B003FAFF1 /* UtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA986259F777B003FAFF1 /* UtilsTests.swift */; }; + 0E9AA9F2259F799B003FAFF1 /* InfrastructureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA985259F777B003FAFF1 /* InfrastructureTests.swift */; }; + 0E9AA9F9259F799C003FAFF1 /* ConnectionServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA987259F777B003FAFF1 /* ConnectionServiceTests.swift */; }; + 0E9AA9FA259F799C003FAFF1 /* ConnectionService.json in Resources */ = {isa = PBXBuildFile; fileRef = 0E9AA988259F777B003FAFF1 /* ConnectionService.json */; }; + 0E9AA9FB259F799C003FAFF1 /* UtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA986259F777B003FAFF1 /* UtilsTests.swift */; }; + 0E9AA9FC259F799C003FAFF1 /* InfrastructureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA985259F777B003FAFF1 /* InfrastructureTests.swift */; }; + 0E9AAA7F259F7DB7003FAFF1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F5E259F41690022DFB8 /* Assets.xcassets */; }; + 0E9AAA80259F7DB7003FAFF1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E569F62259F41690022DFB8 /* AppDelegate.swift */; }; + 0E9AAA89259F7DCA003FAFF1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E569F5F259F41690022DFB8 /* Main.storyboard */; }; + 0E9AAABE259F7FFF003FAFF1 /* PassepartoutLauncher.app in Resources */ = {isa = PBXBuildFile; fileRef = 0E9AAA61259F7D7E003FAFF1 /* PassepartoutLauncher.app */; }; + 0E9AAACB259F808B003FAFF1 /* PassepartoutLauncher.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0E9AAA61259F7D7E003FAFF1 /* PassepartoutLauncher.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0E9AAAD4259F809F003FAFF1 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E9AAAD3259F809F003FAFF1 /* ServiceManagement.framework */; }; 0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD7862257462800D033B4 /* Providers.xcassets */; }; 0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E9CD788225746B300D033B4 /* Flags.xcassets */; }; 0E9CDB6723604AD5006733B4 /* ServerNetworkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */; }; - 0EA84515238A9B5200EFC500 /* Infrastructure+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */; }; - 0EA8451A238C2AB500EFC500 /* Infrastructure+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */; }; 0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; }; - 0EAC572F249426E200D0FCE0 /* GracefulVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAC572E249426E200D0FCE0 /* GracefulVPN.swift */; }; 0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */; }; 0EB67D6B2184581E00BA6200 /* ImportedHostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */; }; - 0EB9EB7323867E7F009C0A1C /* TrustedNetworksUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB9EB7223867E7F009C0A1C /* TrustedNetworksUI.swift */; }; 0EBE3A79213C4E5500BFA2F5 /* OrganizerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */; }; 0ECA7E2225967BB90095F369 /* ProductManager+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECA7E2125967BB90095F369 /* ProductManager+App.swift */; }; - 0ECA7E2D25967BF40095F369 /* Product.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECA7E2525967BDB0095F369 /* Product.swift */; }; - 0ECA7E3025967BFB0095F369 /* ProductManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECA7E2625967BDB0095F369 /* ProductManager.swift */; }; 0ECC60DE2256B68A0020BEAC /* SwiftGen+Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */; }; 0ECEB10A224FECEA00E9E551 /* DataUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECEB109224FECEA00E9E551 /* DataUnit.swift */; }; 0ECEE45020E1182E00A6BB43 /* Theme+Cells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECEE44F20E1182E00A6BB43 /* Theme+Cells.swift */; }; @@ -102,18 +218,18 @@ 0ED38ADA213F44D00004D387 /* Organizer.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0ED38ADC213F44D00004D387 /* Organizer.storyboard */; }; 0ED38AEC2141260D0004D387 /* ConfigurationModificationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED38AEB2141260D0004D387 /* ConfigurationModificationDelegate.swift */; }; 0ED993B1223FF8C700B0F9C9 /* IntentDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED993B0223FF8C700B0F9C9 /* IntentDispatcher.swift */; }; - 0EDE8DC420C86910004C739C /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DC320C86910004C739C /* PacketTunnelProvider.swift */; }; - 0EDE8DC820C86910004C739C /* Passepartout-Tunnel.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0EDE8DBF20C86910004C739C /* Passepartout-Tunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 0EDE8DC820C86910004C739C /* PassepartoutTunnel.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0EDE8DBF20C86910004C739C /* PassepartoutTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 0EE3BBB2215ED3A900F30952 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE3BBB1215ED3A900F30952 /* AboutViewController.swift */; }; - 0EEF23412321AC55000AEBE3 /* Issue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EEF23402321AC55000AEBE3 /* Issue.swift */; }; + 0EEDC551C74496360E09994F /* Pods_ios_Passepartout_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E070D15674A07F40A22BFA7E /* Pods_ios_Passepartout_iOS.framework */; }; 0EF56BBB2185AC8500B0C8AB /* SwiftGen+Segues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF56BBA2185AC8500B0C8AB /* SwiftGen+Segues.swift */; }; - 0EF5CF292141F31F004FF1BD /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4FD7ED20D539A0002221FF /* Utils.swift */; }; 0EFB901822764689006405E4 /* ProfileNetworkSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFB901722764689006405E4 /* ProfileNetworkSettings.swift */; }; 0EFB901A2276D7F1006405E4 /* NetworkSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFB90192276D7F1006405E4 /* NetworkSettingsViewController.swift */; }; 0EFD943E215BE10800529B64 /* IssueReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFD943D215BE10800529B64 /* IssueReporter.swift */; }; - 577B90392A4798F63461B0B5 /* Pods_Passepartout_iOS_Tunnel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA4CE55A94366C45DDB1E624 /* Pods_Passepartout_iOS_Tunnel.framework */; }; - 87121F7216E808EE79925040 /* Pods_Passepartout_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D32B24AA7767AB2E7FB6E0F /* Pods_Passepartout_iOS.framework */; }; - 91AF81613E19B47C06EBD447 /* Pods_PassepartoutCore_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 276375A4CF0313B033CD8B5A /* Pods_PassepartoutCore_iOS.framework */; }; + 23B30D087357F9AC3130E01F /* Pods_macos_Passepartout_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23D4C05138CFBC311ED76548 /* Pods_macos_Passepartout_macOS.framework */; }; + 254BDBF29F7A1FC54C52B302 /* Pods_ios_PassepartoutCore_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B93E25644660446940471003 /* Pods_ios_PassepartoutCore_iOS.framework */; }; + 339DAF589F7BEBC11A09F350 /* Pods_ios_PassepartoutCoreTests_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F661C42E70315D0788B19EDC /* Pods_ios_PassepartoutCoreTests_iOS.framework */; }; + 52F5904C9D386AFF8437468F /* Pods_macos_PassepartoutCoreTests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9BA8850A89C4680A6A23A65 /* Pods_macos_PassepartoutCoreTests_macOS.framework */; }; + B78AF882395541F93658B1AC /* Pods_macos_PassepartoutCore_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 555477CACFC266802E4C2FF2 /* Pods_macos_PassepartoutCore_macOS.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -124,6 +240,48 @@ remoteGlobalIDString = 0E31529A223F9EF400F61841; remoteInfo = "Passepartout-Core"; }; + 0E5203BC259F5F3F00CBAB56 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E57F63020C83FC5008323CF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E5203B4259F5F3F00CBAB56; + remoteInfo = "Passepartout-macOS-Tunnel"; + }; + 0E5203EF259F60D600CBAB56 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E57F63020C83FC5008323CF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E5203E9259F60D600CBAB56; + remoteInfo = "PassepartoutCore-macOS"; + }; + 0E9AA993259F779F003FAFF1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E57F63020C83FC5008323CF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E31529A223F9EF400F61841; + remoteInfo = "PassepartoutCore-iOS"; + }; + 0E9AA9C0259F7821003FAFF1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E57F63020C83FC5008323CF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E5203E9259F60D600CBAB56; + remoteInfo = "PassepartoutCore-macOS"; + }; + 0E9AAABF259F7FFF003FAFF1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E57F63020C83FC5008323CF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E9AAA60259F7D7E003FAFF1; + remoteInfo = "PassepartoutLauncher-macOS"; + }; + 0E9AAAC1259F800B003FAFF1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0E57F63020C83FC5008323CF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E9AAA60259F7D7E003FAFF1; + remoteInfo = "PassepartoutLauncher-macOS"; + }; 0EDE8DC620C86910004C739C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0E57F63020C83FC5008323CF /* Project object */; @@ -145,13 +303,45 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + 0E5203C2259F5F3F00CBAB56 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 0E5203BE259F5F3F00CBAB56 /* PassepartoutTunnel.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203F6259F60D600CBAB56 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 0E5203F2259F60D600CBAB56 /* PassepartoutCore.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AAACA259F806B003FAFF1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = Contents/Library/LoginItems; + dstSubfolderSpec = 1; + files = ( + 0E9AAACB259F808B003FAFF1 /* PassepartoutLauncher.app in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 0EDE8DCC20C86910004C739C /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( - 0EDE8DC820C86910004C739C /* Passepartout-Tunnel.appex in Embed App Extensions */, + 0EDE8DC820C86910004C739C /* PassepartoutTunnel.appex in Embed App Extensions */, ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -159,6 +349,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0376B8FDB39F81CA072C3F37 /* Pods-ios-PassepartoutCore-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-PassepartoutCore-iOS.debug.xcconfig"; path = "Target Support Files/Pods-ios-PassepartoutCore-iOS/Pods-ios-PassepartoutCore-iOS.debug.xcconfig"; sourceTree = ""; }; + 055AC72673D0F12546CAEEA6 /* Pods-macos-Passepartout-macOS-Tunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-Passepartout-macOS-Tunnel.release.xcconfig"; path = "Target Support Files/Pods-macos-Passepartout-macOS-Tunnel/Pods-macos-Passepartout-macOS-Tunnel.release.xcconfig"; sourceTree = ""; }; 09CB728874F1553EF27BAAB9 /* Pods-Passepartout-iOS-Tunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passepartout-iOS-Tunnel.debug.xcconfig"; path = "Target Support Files/Pods-Passepartout-iOS-Tunnel/Pods-Passepartout-iOS-Tunnel.debug.xcconfig"; sourceTree = ""; }; 0E05C5CE20D139AF006EE732 /* FieldTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FieldTableViewCell.swift; sourceTree = ""; }; 0E05C61C20D27C82006EE732 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; @@ -166,7 +358,6 @@ 0E0C072C236087C800155AAC /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; 0E1066C820E0F84A004F98B7 /* Cells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cells.swift; sourceTree = ""; }; 0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = ""; }; - 0E1C0A4E238FC7A5009FC087 /* InfrastructureFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InfrastructureFactory.swift; path = Submodules/Core/Passepartout/Sources/Services/InfrastructureFactory.swift; sourceTree = SOURCE_ROOT; }; 0E1C0A50238FFF97009FC087 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Intents.strings; sourceTree = ""; }; 0E1C0A51238FFF97009FC087 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/App.strings; sourceTree = ""; }; 0E1C0A52238FFF97009FC087 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -221,7 +412,76 @@ 0E4C9CBA20DCF0D600A0C59C /* DestructiveTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestructiveTableViewCell.swift; sourceTree = ""; }; 0E4FD7ED20D539A0002221FF /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 0E4FD7F020D58618002221FF /* Macros.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Macros.swift; sourceTree = ""; }; + 0E5202F7259F573500CBAB56 /* Passepartout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passepartout.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E5203B5259F5F3F00CBAB56 /* PassepartoutTunnel.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = PassepartoutTunnel.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E5203EA259F60D600CBAB56 /* PassepartoutCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PassepartoutCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0E533B152258E03B00EF94FC /* PoolGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PoolGroup.swift; sourceTree = ""; }; + 0E569F14259F2D3E0022DFB8 /* Issue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Issue.swift; sourceTree = ""; }; + 0E569F19259F2D8F0022DFB8 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GracefulVPN.swift; sourceTree = ""; }; + 0E569F1A259F2D8F0022DFB8 /* ProductManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductManager.swift; sourceTree = ""; }; + 0E569F1B259F2D8F0022DFB8 /* Product.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Product.swift; sourceTree = ""; }; + 0E569F28259F2DB10022DFB8 /* Infrastructure+Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Infrastructure+Name.swift"; sourceTree = ""; }; + 0E569F29259F2DB10022DFB8 /* Infrastructure+Metadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Infrastructure+Metadata.swift"; sourceTree = ""; }; + 0E569F2A259F2DB10022DFB8 /* InfrastructureFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InfrastructureFactory.swift; sourceTree = ""; }; + 0E569F30259F2DC10022DFB8 /* TrustedNetworksUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksUI.swift; sourceTree = ""; }; + 0E569F5A259F41690022DFB8 /* TextTableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TextTableView.xib; sourceTree = ""; }; + 0E569F5B259F41690022DFB8 /* TextTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextTableView.swift; sourceTree = ""; }; + 0E569F5E259F41690022DFB8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 0E569F60259F41690022DFB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 0E569F61259F41690022DFB8 /* Launcher.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Launcher.entitlements; sourceTree = ""; }; + 0E569F62259F41690022DFB8 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 0E569F63259F41690022DFB8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0E569F66259F41690022DFB8 /* DebugLogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugLogViewController.swift; sourceTree = ""; }; + 0E569F67259F41690022DFB8 /* PreferencesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = ""; }; + 0E569F68259F41690022DFB8 /* PreferencesGeneralViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesGeneralViewController.swift; sourceTree = ""; }; + 0E569F69259F41690022DFB8 /* OrganizerProfileTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganizerProfileTableView.swift; sourceTree = ""; }; + 0E569F6A259F41690022DFB8 /* OrganizerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganizerViewController.swift; sourceTree = ""; }; + 0E569F6B259F41690022DFB8 /* OrganizerProfileTableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OrganizerProfileTableView.xib; sourceTree = ""; }; + 0E569F6D259F41690022DFB8 /* ServiceViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceViewController.swift; sourceTree = ""; }; + 0E569F6E259F41690022DFB8 /* ProviderServiceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderServiceView.swift; sourceTree = ""; }; + 0E569F70259F41690022DFB8 /* MTUViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MTUViewController.swift; sourceTree = ""; }; + 0E569F71259F41690022DFB8 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = ""; }; + 0E569F72259F41690022DFB8 /* ConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationViewController.swift; sourceTree = ""; }; + 0E569F73259F41690022DFB8 /* ProfileCustomizationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileCustomizationViewController.swift; sourceTree = ""; }; + 0E569F74259F41690022DFB8 /* ProxyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProxyViewController.swift; sourceTree = ""; }; + 0E569F75259F41690022DFB8 /* TrustedNetworksAddViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksAddViewController.swift; sourceTree = ""; }; + 0E569F76259F41690022DFB8 /* DNSViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DNSViewController.swift; sourceTree = ""; }; + 0E569F77259F41690022DFB8 /* DefaultGatewayViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultGatewayViewController.swift; sourceTree = ""; }; + 0E569F78259F41690022DFB8 /* TrustedNetworksViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksViewController.swift; sourceTree = ""; }; + 0E569F79259F41690022DFB8 /* ProviderServiceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProviderServiceView.xib; sourceTree = ""; }; + 0E569F7A259F41690022DFB8 /* HostServiceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HostServiceView.swift; sourceTree = ""; }; + 0E569F7B259F41690022DFB8 /* HostServiceView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HostServiceView.xib; sourceTree = ""; }; + 0E569F7C259F41690022DFB8 /* AccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = ""; }; + 0E569F7D259F41690022DFB8 /* Providers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Providers.xcassets; sourceTree = ""; }; + 0E569F7E259F41690022DFB8 /* App.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; + 0E569F7F259F41690022DFB8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 0E569F82259F41690022DFB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Preferences.storyboard; sourceTree = ""; }; + 0E569F84259F41690022DFB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Service.storyboard; sourceTree = ""; }; + 0E569F86259F41690022DFB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 0E569F88259F41690022DFB8 /* MainMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = ""; }; + 0E569F89259F41690022DFB8 /* StatusMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusMenu.swift; sourceTree = ""; }; + 0E569F8A259F41690022DFB8 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + 0E569F8B259F41690022DFB8 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 0E569F8F259F41690022DFB8 /* IssueReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IssueReporter.swift; sourceTree = ""; }; + 0E569F91259F41690022DFB8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/App.strings; sourceTree = ""; }; + 0E569F92259F41690022DFB8 /* WindowManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowManager.swift; sourceTree = ""; }; + 0E569F93259F41690022DFB8 /* HostImporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HostImporter.swift; sourceTree = ""; }; + 0E569F94259F41690022DFB8 /* NSTextView+Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSTextView+Search.swift"; sourceTree = ""; }; + 0E569F97259F41690022DFB8 /* TextInputViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextInputViewController.swift; sourceTree = ""; }; + 0E569F98259F41690022DFB8 /* SwiftGen+Assets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Assets.swift"; sourceTree = ""; }; + 0E569F99259F41690022DFB8 /* Donation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Donation.swift; sourceTree = ""; }; + 0E569F9A259F41690022DFB8 /* Theme+Views.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Theme+Views.swift"; sourceTree = ""; }; + 0E569F9C259F41690022DFB8 /* SwiftGen+Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Strings.swift"; sourceTree = ""; }; + 0E569F9D259F41690022DFB8 /* SwiftGen+Scenes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Scenes.swift"; sourceTree = ""; }; + 0E569F9E259F41690022DFB8 /* ProductManager+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ProductManager+App.swift"; sourceTree = ""; }; + 0E569FA1259F41690022DFB8 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + 0E569FA3259F41690022DFB8 /* AppConstants+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppConstants+App.swift"; sourceTree = ""; }; + 0E569FA4259F41690022DFB8 /* Credits.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = Credits.html; sourceTree = ""; }; + 0E569FA5259F41690022DFB8 /* SwiftGen+Segues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Segues.swift"; sourceTree = ""; }; + 0E569FA6259F41690022DFB8 /* Macros.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Macros.swift; sourceTree = ""; }; + 0E569FA7259F41690022DFB8 /* Flags.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flags.xcassets; sourceTree = ""; }; + 0E569FA8259F41690022DFB8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0E569FAA259F41690022DFB8 /* Tunnel-macOS.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Tunnel-macOS.entitlements"; sourceTree = ""; }; 0E57F63820C83FC5008323CF /* Passepartout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passepartout.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0E57F63B20C83FC5008323CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 0E57F63D20C83FC5008323CF /* ServiceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceViewController.swift; sourceTree = ""; }; @@ -250,15 +510,21 @@ 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+Communication.swift"; sourceTree = ""; }; 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardProviderViewController.swift; sourceTree = ""; }; 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfrastructurePreset.swift; sourceTree = ""; }; + 0E9AA977259F756A003FAFF1 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = ""; }; + 0E9AA985259F777B003FAFF1 /* InfrastructureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfrastructureTests.swift; sourceTree = ""; }; + 0E9AA986259F777B003FAFF1 /* UtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilsTests.swift; sourceTree = ""; }; + 0E9AA987259F777B003FAFF1 /* ConnectionServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionServiceTests.swift; sourceTree = ""; }; + 0E9AA988259F777B003FAFF1 /* ConnectionService.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ConnectionService.json; sourceTree = ""; }; + 0E9AA98D259F779F003FAFF1 /* PassepartoutCoreTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PassepartoutCoreTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E9AA991259F779F003FAFF1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0E9AA9BA259F7821003FAFF1 /* PassepartoutCoreTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PassepartoutCoreTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E9AAA61259F7D7E003FAFF1 /* PassepartoutLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PassepartoutLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0E9AAAD3259F809F003FAFF1 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/ServiceManagement.framework; sourceTree = DEVELOPER_DIR; }; 0E9CD7862257462800D033B4 /* Providers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Providers.xcassets; sourceTree = ""; }; 0E9CD788225746B300D033B4 /* Flags.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flags.xcassets; sourceTree = ""; }; 0E9CDB6623604AD5006733B4 /* ServerNetworkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerNetworkViewController.swift; sourceTree = ""; }; - 0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Infrastructure+Name.swift"; path = "Submodules/Core/Passepartout/Sources/Services/Infrastructure+Name.swift"; sourceTree = SOURCE_ROOT; }; - 0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Infrastructure+Metadata.swift"; path = "Submodules/Core/Passepartout/Sources/Services/Infrastructure+Metadata.swift"; sourceTree = SOURCE_ROOT; }; - 0EAC572E249426E200D0FCE0 /* GracefulVPN.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GracefulVPN.swift; path = Submodules/Core/Passepartout/Sources/Model/GracefulVPN.swift; sourceTree = SOURCE_ROOT; }; 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+Search.swift"; sourceTree = ""; }; 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportedHostsViewController.swift; sourceTree = ""; }; - 0EB9EB7223867E7F009C0A1C /* TrustedNetworksUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrustedNetworksUI.swift; sourceTree = ""; }; 0EBBE8F42182361700106008 /* ConnectionService+Migration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConnectionService+Migration.swift"; sourceTree = ""; }; 0EBE2FD02360F88C00F0D5AB /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; 0EBE2FD12360F88E00F0D5AB /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -277,8 +543,6 @@ 0EBE3AA4213DC1B000BFA2F5 /* ProviderConnectionProfile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderConnectionProfile.swift; sourceTree = ""; }; 0EC7F20420E24308004EA58E /* DebugLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugLog.swift; sourceTree = ""; }; 0ECA7E2125967BB90095F369 /* ProductManager+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ProductManager+App.swift"; sourceTree = ""; }; - 0ECA7E2525967BDB0095F369 /* Product.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Product.swift; path = Submodules/Core/Passepartout/Sources/Model/Product.swift; sourceTree = SOURCE_ROOT; }; - 0ECA7E2625967BDB0095F369 /* ProductManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProductManager.swift; path = Submodules/Core/Passepartout/Sources/Model/ProductManager.swift; sourceTree = SOURCE_ROOT; }; 0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Assets.swift"; sourceTree = ""; }; 0ECEB105224FE51400E9E551 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 0ECEB106224FE51400E9E551 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Organizer.storyboard; sourceTree = ""; }; @@ -291,38 +555,58 @@ 0ED31C2820CF2A340027975F /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = ""; }; 0ED31C2B20CF2D6F0027975F /* ProviderPoolViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderPoolViewController.swift; sourceTree = ""; }; 0ED31C3920CF39510027975F /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; - 0ED31C3B20CF39510027975F /* Tunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Tunnel.entitlements; sourceTree = ""; }; + 0ED31C3B20CF39510027975F /* Tunnel-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Tunnel-iOS.entitlements"; sourceTree = ""; }; 0ED38AD8213F33150004D387 /* WizardHostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardHostViewController.swift; sourceTree = ""; }; 0ED38AE621404F100004D387 /* EndpointDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndpointDataSource.swift; sourceTree = ""; }; 0ED38AEB2141260D0004D387 /* ConfigurationModificationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationModificationDelegate.swift; sourceTree = ""; }; 0ED824C920D12B8700F2FE9E /* ToggleTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleTableViewCell.swift; sourceTree = ""; }; 0ED824CD20D12DBE00F2FE9E /* SettingTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingTableViewCell.swift; sourceTree = ""; }; - 0ED993B0223FF8C700B0F9C9 /* IntentDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IntentDispatcher.swift; path = Submodules/Core/Passepartout/Sources/Intents/IntentDispatcher.swift; sourceTree = SOURCE_ROOT; }; - 0EDE8DBF20C86910004C739C /* Passepartout-Tunnel.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Passepartout-Tunnel.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0EDE8DC320C86910004C739C /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = ""; }; - 0EDE8DC520C86910004C739C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0ED993B0223FF8C700B0F9C9 /* IntentDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentDispatcher.swift; sourceTree = ""; }; + 0EDE8DBF20C86910004C739C /* PassepartoutTunnel.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = PassepartoutTunnel.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 0EDE8DC320C86910004C739C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 0EDE8DD220C86978004C739C /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; }; - 0EDE8DE220C86A13004C739C /* Passepartout.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Passepartout.entitlements; sourceTree = ""; }; + 0EDE8DE220C86A13004C739C /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; 0EDE8DE320C89028004C739C /* SwiftGen+Scenes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Scenes.swift"; sourceTree = ""; }; 0EDE8DE620C93945004C739C /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupConstants.swift; sourceTree = ""; }; 0EE3BBB1215ED3A900F30952 /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; - 0EEF23402321AC55000AEBE3 /* Issue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Issue.swift; path = Submodules/Core/Passepartout/Sources/Issue.swift; sourceTree = SOURCE_ROOT; }; 0EF56BBA2185AC8500B0C8AB /* SwiftGen+Segues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Segues.swift"; sourceTree = ""; }; 0EFB901722764689006405E4 /* ProfileNetworkSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileNetworkSettings.swift; sourceTree = ""; }; 0EFB90192276D7F1006405E4 /* NetworkSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSettingsViewController.swift; sourceTree = ""; }; 0EFD943D215BE10800529B64 /* IssueReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueReporter.swift; sourceTree = ""; }; 0FD7B360EE444EF1CDBFDF1C /* Pods-PassepartoutCoreTests-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PassepartoutCoreTests-iOS.debug.xcconfig"; path = "Target Support Files/Pods-PassepartoutCoreTests-iOS/Pods-PassepartoutCoreTests-iOS.debug.xcconfig"; sourceTree = ""; }; + 0FDF9B1E8EC63CCF4A2C9694 /* Pods-ios-Passepartout-iOS-Tunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-Passepartout-iOS-Tunnel.debug.xcconfig"; path = "Target Support Files/Pods-ios-Passepartout-iOS-Tunnel/Pods-ios-Passepartout-iOS-Tunnel.debug.xcconfig"; sourceTree = ""; }; + 155FC78114E324E01093F98C /* Pods-ios-Passepartout-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-Passepartout-iOS.debug.xcconfig"; path = "Target Support Files/Pods-ios-Passepartout-iOS/Pods-ios-Passepartout-iOS.debug.xcconfig"; sourceTree = ""; }; 234D3C887F46AD64480495BB /* Pods-PassepartoutCoreTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PassepartoutCoreTests-iOS.release.xcconfig"; path = "Target Support Files/Pods-PassepartoutCoreTests-iOS/Pods-PassepartoutCoreTests-iOS.release.xcconfig"; sourceTree = ""; }; - 276375A4CF0313B033CD8B5A /* Pods_PassepartoutCore_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PassepartoutCore_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 23D4C05138CFBC311ED76548 /* Pods_macos_Passepartout_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_macos_Passepartout_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 329F34FAC963CE4BEA3013D6 /* Pods-macos-PassepartoutCore-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-PassepartoutCore-macOS.debug.xcconfig"; path = "Target Support Files/Pods-macos-PassepartoutCore-macOS/Pods-macos-PassepartoutCore-macOS.debug.xcconfig"; sourceTree = ""; }; + 35380A14E9FF6F0250C171CD /* Pods_macos_PassepartoutTunnel_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_macos_PassepartoutTunnel_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4BD12523ABCBF7ED941FC270 /* Pods-Passepartout-iOS-Tunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passepartout-iOS-Tunnel.release.xcconfig"; path = "Target Support Files/Pods-Passepartout-iOS-Tunnel/Pods-Passepartout-iOS-Tunnel.release.xcconfig"; sourceTree = ""; }; + 50DD79FBBBBF400F3BFE8912 /* Pods-macos-PassepartoutTunnel-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-PassepartoutTunnel-macOS.debug.xcconfig"; path = "Target Support Files/Pods-macos-PassepartoutTunnel-macOS/Pods-macos-PassepartoutTunnel-macOS.debug.xcconfig"; sourceTree = ""; }; 53B773C4BAE7EDB38C7AFCD1 /* Pods-Passepartout-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passepartout-iOS.release.xcconfig"; path = "Target Support Files/Pods-Passepartout-iOS/Pods-Passepartout-iOS.release.xcconfig"; sourceTree = ""; }; - 6D32B24AA7767AB2E7FB6E0F /* Pods_Passepartout_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Passepartout_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 992C366F272FAA643335F68C /* Pods_PassepartoutCoreTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PassepartoutCoreTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 555477CACFC266802E4C2FF2 /* Pods_macos_PassepartoutCore_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_macos_PassepartoutCore_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5C7F674900185F5DD24DA481 /* Pods-macos-Passepartout-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-Passepartout-macOS.release.xcconfig"; path = "Target Support Files/Pods-macos-Passepartout-macOS/Pods-macos-Passepartout-macOS.release.xcconfig"; sourceTree = ""; }; + 5CC1FDDBA184F8548D814E9D /* Pods-ios-PassepartoutCore-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-PassepartoutCore-iOS.release.xcconfig"; path = "Target Support Files/Pods-ios-PassepartoutCore-iOS/Pods-ios-PassepartoutCore-iOS.release.xcconfig"; sourceTree = ""; }; + 7E007C60601AFBB8A2C34DC4 /* Pods-ios-PassepartoutTunnel-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-PassepartoutTunnel-iOS.debug.xcconfig"; path = "Target Support Files/Pods-ios-PassepartoutTunnel-iOS/Pods-ios-PassepartoutTunnel-iOS.debug.xcconfig"; sourceTree = ""; }; + 80A0C78A127E8CE9CB8E658D /* Pods-macos-PassepartoutCoreTests-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-PassepartoutCoreTests-macOS.release.xcconfig"; path = "Target Support Files/Pods-macos-PassepartoutCoreTests-macOS/Pods-macos-PassepartoutCoreTests-macOS.release.xcconfig"; sourceTree = ""; }; + 9FB2CA39113427B15C824FE0 /* Pods-ios-PassepartoutTunnel-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-PassepartoutTunnel-iOS.release.xcconfig"; path = "Target Support Files/Pods-ios-PassepartoutTunnel-iOS/Pods-ios-PassepartoutTunnel-iOS.release.xcconfig"; sourceTree = ""; }; A1C4E67627603307808F2FFC /* Pods-PassepartoutCore-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PassepartoutCore-iOS.debug.xcconfig"; path = "Target Support Files/Pods-PassepartoutCore-iOS/Pods-PassepartoutCore-iOS.debug.xcconfig"; sourceTree = ""; }; + A8E3B69460648EA46C1BF850 /* Pods-ios-PassepartoutCoreTests-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-PassepartoutCoreTests-iOS.debug.xcconfig"; path = "Target Support Files/Pods-ios-PassepartoutCoreTests-iOS/Pods-ios-PassepartoutCoreTests-iOS.debug.xcconfig"; sourceTree = ""; }; + B7018254471DA72DF7939A01 /* Pods-macos-Passepartout-macOS-Tunnel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-Passepartout-macOS-Tunnel.debug.xcconfig"; path = "Target Support Files/Pods-macos-Passepartout-macOS-Tunnel/Pods-macos-Passepartout-macOS-Tunnel.debug.xcconfig"; sourceTree = ""; }; + B93E25644660446940471003 /* Pods_ios_PassepartoutCore_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_PassepartoutCore_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C3D09D9270939FC37BE7101E /* Pods-macos-PassepartoutCore-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-PassepartoutCore-macOS.release.xcconfig"; path = "Target Support Files/Pods-macos-PassepartoutCore-macOS/Pods-macos-PassepartoutCore-macOS.release.xcconfig"; sourceTree = ""; }; + C9BA8850A89C4680A6A23A65 /* Pods_macos_PassepartoutCoreTests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_macos_PassepartoutCoreTests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CFF79E4C42220C649C2259D2 /* Pods-ios-Passepartout-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-Passepartout-iOS.release.xcconfig"; path = "Target Support Files/Pods-ios-Passepartout-iOS/Pods-ios-Passepartout-iOS.release.xcconfig"; sourceTree = ""; }; + D2AF3AFC3418E6800D8A70E8 /* Pods-macos-PassepartoutTunnel-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-PassepartoutTunnel-macOS.release.xcconfig"; path = "Target Support Files/Pods-macos-PassepartoutTunnel-macOS/Pods-macos-PassepartoutTunnel-macOS.release.xcconfig"; sourceTree = ""; }; + D5D3FFA0392EA5F818646CD9 /* Pods-ios-PassepartoutCoreTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-PassepartoutCoreTests-iOS.release.xcconfig"; path = "Target Support Files/Pods-ios-PassepartoutCoreTests-iOS/Pods-ios-PassepartoutCoreTests-iOS.release.xcconfig"; sourceTree = ""; }; + E070D15674A07F40A22BFA7E /* Pods_ios_Passepartout_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_Passepartout_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E08D99B2FCC4478BB24A57B0 /* Pods-macos-Passepartout-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-Passepartout-macOS.debug.xcconfig"; path = "Target Support Files/Pods-macos-Passepartout-macOS/Pods-macos-Passepartout-macOS.debug.xcconfig"; sourceTree = ""; }; + E69B5CF79639B3D24F2AFFC9 /* Pods-macos-PassepartoutCoreTests-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macos-PassepartoutCoreTests-macOS.debug.xcconfig"; path = "Target Support Files/Pods-macos-PassepartoutCoreTests-macOS/Pods-macos-PassepartoutCoreTests-macOS.debug.xcconfig"; sourceTree = ""; }; + E9433B826E8B47C325FD6B8F /* Pods-ios-Passepartout-iOS-Tunnel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ios-Passepartout-iOS-Tunnel.release.xcconfig"; path = "Target Support Files/Pods-ios-Passepartout-iOS-Tunnel/Pods-ios-Passepartout-iOS-Tunnel.release.xcconfig"; sourceTree = ""; }; F1BECEC1D93FEBDB17B714D8 /* Pods-PassepartoutCore-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PassepartoutCore-iOS.release.xcconfig"; path = "Target Support Files/Pods-PassepartoutCore-iOS/Pods-PassepartoutCore-iOS.release.xcconfig"; sourceTree = ""; }; F4959B5F3CB1BBC2C46EA639 /* Pods-Passepartout-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passepartout-iOS.debug.xcconfig"; path = "Target Support Files/Pods-Passepartout-iOS/Pods-Passepartout-iOS.debug.xcconfig"; sourceTree = ""; }; - FA4CE55A94366C45DDB1E624 /* Pods_Passepartout_iOS_Tunnel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Passepartout_iOS_Tunnel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F661C42E70315D0788B19EDC /* Pods_ios_PassepartoutCoreTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_PassepartoutCoreTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FF7D2E624A2979425A6F7B7A /* Pods_ios_PassepartoutTunnel_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ios_PassepartoutTunnel_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -330,7 +614,34 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 91AF81613E19B47C06EBD447 /* Pods_PassepartoutCore_iOS.framework in Frameworks */, + 254BDBF29F7A1FC54C52B302 /* Pods_ios_PassepartoutCore_iOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5202F4259F573500CBAB56 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AAAD4259F809F003FAFF1 /* ServiceManagement.framework in Frameworks */, + 0E5203F1259F60D600CBAB56 /* PassepartoutCore.framework in Frameworks */, + 23B30D087357F9AC3130E01F /* Pods_macos_Passepartout_macOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203B2259F5F3F00CBAB56 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E5203B6259F5F3F00CBAB56 /* NetworkExtension.framework in Frameworks */, + 0774835EE25EEA07495A98AA /* Pods_macos_PassepartoutTunnel_macOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203E7259F60D600CBAB56 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B78AF882395541F93658B1AC /* Pods_macos_PassepartoutCore_macOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -340,7 +651,32 @@ files = ( 0E3152B0223F9EF500F61841 /* PassepartoutCore.framework in Frameworks */, 0ED31C3D20CF396E0027975F /* NetworkExtension.framework in Frameworks */, - 87121F7216E808EE79925040 /* Pods_Passepartout_iOS.framework in Frameworks */, + 0EEDC551C74496360E09994F /* Pods_ios_Passepartout_iOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AA98A259F779F003FAFF1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA992259F779F003FAFF1 /* PassepartoutCore.framework in Frameworks */, + 339DAF589F7BEBC11A09F350 /* Pods_ios_PassepartoutCoreTests_iOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AA9B7259F7821003FAFF1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA9BF259F7821003FAFF1 /* PassepartoutCore.framework in Frameworks */, + 52F5904C9D386AFF8437468F /* Pods_macos_PassepartoutCoreTests_macOS.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AAA5E259F7D7E003FAFF1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; }; @@ -349,7 +685,7 @@ buildActionMask = 2147483647; files = ( 0ED31C3A20CF39510027975F /* NetworkExtension.framework in Frameworks */, - 577B90392A4798F63461B0B5 /* Pods_Passepartout_iOS_Tunnel.framework in Frameworks */, + 051985241A3ABE44EB09DFF5 /* Pods_ios_PassepartoutTunnel_iOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -387,13 +723,15 @@ path = Shortcuts; sourceTree = ""; }; - 0E31529C223F9EF500F61841 /* PassepartoutCore-iOS */ = { + 0E31529C223F9EF500F61841 /* Core */ = { isa = PBXGroup; children = ( + 0E3CAF97229AAE760008E5C8 /* Resources */, + 0EDE8DF020C93EBB004C739C /* Sources */, 0E31529D223F9EF500F61841 /* PassepartoutCore.h */, 0E31529E223F9EF500F61841 /* Info.plist */, ); - path = "PassepartoutCore-iOS"; + path = Core; sourceTree = ""; }; 0E3CAF97229AAE760008E5C8 /* Resources */ = { @@ -422,13 +760,140 @@ path = Intents; sourceTree = ""; }; + 0E569F58259F41690022DFB8 /* macOS */ = { + isa = PBXGroup; + children = ( + 0E569F8C259F41690022DFB8 /* Global */, + 0E569F5C259F41690022DFB8 /* Launcher */, + 0E569F87259F41690022DFB8 /* Menu */, + 0E569F64259F41690022DFB8 /* Scenes */, + 0E569F59259F41690022DFB8 /* Tables */, + 0E569F7E259F41690022DFB8 /* App.entitlements */, + 0E569FA8259F41690022DFB8 /* Info.plist */, + 0E569F8D259F41690022DFB8 /* App.strings */, + 0E569F8B259F41690022DFB8 /* AppDelegate.swift */, + 0E569F7F259F41690022DFB8 /* Assets.xcassets */, + 0E569FA7259F41690022DFB8 /* Flags.xcassets */, + 0E569F7D259F41690022DFB8 /* Providers.xcassets */, + 0E569F85259F41690022DFB8 /* Main.storyboard */, + 0E569F81259F41690022DFB8 /* Preferences.storyboard */, + 0E569F83259F41690022DFB8 /* Service.storyboard */, + ); + path = macOS; + sourceTree = ""; + }; + 0E569F59259F41690022DFB8 /* Tables */ = { + isa = PBXGroup; + children = ( + 0E569F5B259F41690022DFB8 /* TextTableView.swift */, + 0E569F5A259F41690022DFB8 /* TextTableView.xib */, + ); + path = Tables; + sourceTree = ""; + }; + 0E569F5C259F41690022DFB8 /* Launcher */ = { + isa = PBXGroup; + children = ( + 0E569F61259F41690022DFB8 /* Launcher.entitlements */, + 0E569F63259F41690022DFB8 /* Info.plist */, + 0E569F62259F41690022DFB8 /* AppDelegate.swift */, + 0E569F5E259F41690022DFB8 /* Assets.xcassets */, + 0E569F5F259F41690022DFB8 /* Main.storyboard */, + ); + path = Launcher; + sourceTree = ""; + }; + 0E569F64259F41690022DFB8 /* Scenes */ = { + isa = PBXGroup; + children = ( + 0E569F65259F41690022DFB8 /* Preferences */, + 0E569F6C259F41690022DFB8 /* Service */, + 0E569F69259F41690022DFB8 /* OrganizerProfileTableView.swift */, + 0E569F6A259F41690022DFB8 /* OrganizerViewController.swift */, + 0E569F6B259F41690022DFB8 /* OrganizerProfileTableView.xib */, + ); + path = Scenes; + sourceTree = ""; + }; + 0E569F65259F41690022DFB8 /* Preferences */ = { + isa = PBXGroup; + children = ( + 0E569F66259F41690022DFB8 /* DebugLogViewController.swift */, + 0E569F68259F41690022DFB8 /* PreferencesGeneralViewController.swift */, + 0E569F67259F41690022DFB8 /* PreferencesViewController.swift */, + ); + path = Preferences; + sourceTree = ""; + }; + 0E569F6C259F41690022DFB8 /* Service */ = { + isa = PBXGroup; + children = ( + 0E569F6F259F41690022DFB8 /* Customization */, + 0E569F7C259F41690022DFB8 /* AccountViewController.swift */, + 0E569F7A259F41690022DFB8 /* HostServiceView.swift */, + 0E569F6E259F41690022DFB8 /* ProviderServiceView.swift */, + 0E569F6D259F41690022DFB8 /* ServiceViewController.swift */, + 0E569F7B259F41690022DFB8 /* HostServiceView.xib */, + 0E569F79259F41690022DFB8 /* ProviderServiceView.xib */, + ); + path = Service; + sourceTree = ""; + }; + 0E569F6F259F41690022DFB8 /* Customization */ = { + isa = PBXGroup; + children = ( + 0E569F72259F41690022DFB8 /* ConfigurationViewController.swift */, + 0E569F77259F41690022DFB8 /* DefaultGatewayViewController.swift */, + 0E569F76259F41690022DFB8 /* DNSViewController.swift */, + 0E569F71259F41690022DFB8 /* EndpointViewController.swift */, + 0E569F70259F41690022DFB8 /* MTUViewController.swift */, + 0E569F73259F41690022DFB8 /* ProfileCustomizationViewController.swift */, + 0E569F74259F41690022DFB8 /* ProxyViewController.swift */, + 0E569F75259F41690022DFB8 /* TrustedNetworksAddViewController.swift */, + 0E569F78259F41690022DFB8 /* TrustedNetworksViewController.swift */, + ); + path = Customization; + sourceTree = ""; + }; + 0E569F87259F41690022DFB8 /* Menu */ = { + isa = PBXGroup; + children = ( + 0E569F88259F41690022DFB8 /* MainMenu.swift */, + 0E569F8A259F41690022DFB8 /* MainMenu.xib */, + 0E569F89259F41690022DFB8 /* StatusMenu.swift */, + ); + path = Menu; + sourceTree = ""; + }; + 0E569F8C259F41690022DFB8 /* Global */ = { + isa = PBXGroup; + children = ( + 0E569FA4259F41690022DFB8 /* Credits.html */, + 0E569FA3259F41690022DFB8 /* AppConstants+App.swift */, + 0E569F99259F41690022DFB8 /* Donation.swift */, + 0E569F93259F41690022DFB8 /* HostImporter.swift */, + 0E569F8F259F41690022DFB8 /* IssueReporter.swift */, + 0E569FA6259F41690022DFB8 /* Macros.swift */, + 0E569F94259F41690022DFB8 /* NSTextView+Search.swift */, + 0E569F9E259F41690022DFB8 /* ProductManager+App.swift */, + 0E569F98259F41690022DFB8 /* SwiftGen+Assets.swift */, + 0E569F9D259F41690022DFB8 /* SwiftGen+Scenes.swift */, + 0E569FA5259F41690022DFB8 /* SwiftGen+Segues.swift */, + 0E569F9C259F41690022DFB8 /* SwiftGen+Strings.swift */, + 0E569F97259F41690022DFB8 /* TextInputViewController.swift */, + 0E569FA1259F41690022DFB8 /* Theme.swift */, + 0E569F9A259F41690022DFB8 /* Theme+Views.swift */, + 0E569F92259F41690022DFB8 /* WindowManager.swift */, + ); + path = Global; + sourceTree = ""; + }; 0E57F62F20C83FC5008323CF = { isa = PBXGroup; children = ( - 0E31529C223F9EF500F61841 /* PassepartoutCore-iOS */, - 0E57F63A20C83FC5008323CF /* Passepartout-iOS */, - 0EDE8DC020C86910004C739C /* Passepartout-iOS-Tunnel */, - 0EE4EB2C229A71BB000E4BA1 /* Libraries */, + 0E23B4A12298559800304C30 /* Config.xcconfig */, + 0E9AA982259F7674003FAFF1 /* Passepartout */, + 0EE4EB2C229A71BB000E4BA1 /* Submodules */, 0E57F63920C83FC5008323CF /* Products */, 374B9F085E1148C37CF9117A /* Frameworks */, ECB6C4CA315B2CB2AFE7ACBB /* Pods */, @@ -439,35 +904,41 @@ isa = PBXGroup; children = ( 0E57F63820C83FC5008323CF /* Passepartout.app */, - 0EDE8DBF20C86910004C739C /* Passepartout-Tunnel.appex */, + 0EDE8DBF20C86910004C739C /* PassepartoutTunnel.appex */, 0E31529B223F9EF400F61841 /* PassepartoutCore.framework */, + 0E5202F7259F573500CBAB56 /* Passepartout.app */, + 0E5203B5259F5F3F00CBAB56 /* PassepartoutTunnel.appex */, + 0E5203EA259F60D600CBAB56 /* PassepartoutCore.framework */, + 0E9AA98D259F779F003FAFF1 /* PassepartoutCoreTests-iOS.xctest */, + 0E9AA9BA259F7821003FAFF1 /* PassepartoutCoreTests-macOS.xctest */, + 0E9AAA61259F7D7E003FAFF1 /* PassepartoutLauncher.app */, ); name = Products; sourceTree = ""; }; - 0E57F63A20C83FC5008323CF /* Passepartout-iOS */ = { + 0E57F63A20C83FC5008323CF /* iOS */ = { isa = PBXGroup; children = ( - 0EDE8DEC20C93E3B004C739C /* Global */, 0E1066CA20E0F85C004F98B7 /* Cells */, + 0EDE8DEC20C93E3B004C739C /* Global */, 0EDE8DF120C93ED8004C739C /* Scenes */, - 0E23B4A12298559800304C30 /* Config.xcconfig */, - 0EDE8DE220C86A13004C739C /* Passepartout.entitlements */, + 0E2AC24422EC3AC10037B4B0 /* Settings.bundle */, + 0EDE8DE220C86A13004C739C /* App.entitlements */, + 0E57F64720C83FC7008323CF /* Info.plist */, + 0E45E6E222BD793800F19312 /* App.strings */, + 0E0C072B236087A100155AAC /* InfoPlist.strings */, 0E57F63B20C83FC5008323CF /* AppDelegate.swift */, + 0E57F64220C83FC7008323CF /* Assets.xcassets */, + 0E9CD788225746B300D033B4 /* Flags.xcassets */, + 0E9CD7862257462800D033B4 /* Providers.xcassets */, 0E24273C225950450064A1A3 /* About.storyboard */, + 0E57F64420C83FC7008323CF /* LaunchScreen.storyboard */, 0E57F63F20C83FC5008323CF /* Main.storyboard */, 0ED38ADC213F44D00004D387 /* Organizer.storyboard */, 0E4B0D762366E6C800C890B4 /* Purchase.storyboard */, 0E36D25A22403469006AF062 /* Shortcuts.storyboard */, - 0E57F64220C83FC7008323CF /* Assets.xcassets */, - 0E9CD788225746B300D033B4 /* Flags.xcassets */, - 0E9CD7862257462800D033B4 /* Providers.xcassets */, - 0E57F64420C83FC7008323CF /* LaunchScreen.storyboard */, - 0E2AC24422EC3AC10037B4B0 /* Settings.bundle */, - 0E57F64720C83FC7008323CF /* Info.plist */, - 0E0C072B236087A100155AAC /* InfoPlist.strings */, ); - path = "Passepartout-iOS"; + path = iOS; sourceTree = ""; }; 0E89DFCC213EEDE700741BA1 /* Organizer */ = { @@ -482,14 +953,45 @@ path = Organizer; sourceTree = ""; }; + 0E9AA982259F7674003FAFF1 /* Passepartout */ = { + isa = PBXGroup; + children = ( + 0E9AA983259F76C5003FAFF1 /* App */, + 0E31529C223F9EF500F61841 /* Core */, + 0E9AA984259F777B003FAFF1 /* Tests */, + 0EDE8DC020C86910004C739C /* Tunnel */, + ); + path = Passepartout; + sourceTree = ""; + }; + 0E9AA983259F76C5003FAFF1 /* App */ = { + isa = PBXGroup; + children = ( + 0E57F63A20C83FC5008323CF /* iOS */, + 0E569F58259F41690022DFB8 /* macOS */, + ); + path = App; + sourceTree = ""; + }; + 0E9AA984259F777B003FAFF1 /* Tests */ = { + isa = PBXGroup; + children = ( + 0E9AA991259F779F003FAFF1 /* Info.plist */, + 0E9AA988259F777B003FAFF1 /* ConnectionService.json */, + 0E9AA987259F777B003FAFF1 /* ConnectionServiceTests.swift */, + 0E9AA985259F777B003FAFF1 /* InfrastructureTests.swift */, + 0E9AA986259F777B003FAFF1 /* UtilsTests.swift */, + ); + path = Tests; + sourceTree = ""; + }; 0EB9EB7123867E7F009C0A1C /* UI */ = { isa = PBXGroup; children = ( - 0EB9EB7223867E7F009C0A1C /* TrustedNetworksUI.swift */, + 0E569F30259F2DC10022DFB8 /* TrustedNetworksUI.swift */, ); - name = UI; - path = Submodules/Core/Passepartout/Sources/UI; - sourceTree = SOURCE_ROOT; + path = UI; + sourceTree = ""; }; 0EBE3AA2213DC1B000BFA2F5 /* Profiles */ = { isa = PBXGroup; @@ -514,11 +1016,11 @@ 0ECEB109224FECEA00E9E551 /* DataUnit.swift */, 0EC7F20420E24308004EA58E /* DebugLog.swift */, 0ED38AE621404F100004D387 /* EndpointDataSource.swift */, - 0EAC572E249426E200D0FCE0 /* GracefulVPN.swift */, + 0E569F19259F2D8F0022DFB8 /* GracefulVPN.swift */, 0E45E70F22BE108100F19312 /* OpenVPNOptions.swift */, 0E89DFC4213DF7AE00741BA1 /* Preferences.swift */, - 0ECA7E2525967BDB0095F369 /* Product.swift */, - 0ECA7E2625967BDB0095F369 /* ProductManager.swift */, + 0E569F1B259F2D8F0022DFB8 /* Product.swift */, + 0E569F1A259F2D8F0022DFB8 /* ProductManager.swift */, 0EFB901722764689006405E4 /* ProfileNetworkSettings.swift */, 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */, 0E2B494120FD16540094784C /* TransientStore.swift */, @@ -532,9 +1034,9 @@ isa = PBXGroup; children = ( 0ED31C1120CF0ABA0027975F /* Infrastructure.swift */, - 0EA84519238C2AB500EFC500 /* Infrastructure+Metadata.swift */, - 0EA84514238A9B5100EFC500 /* Infrastructure+Name.swift */, - 0E1C0A4E238FC7A5009FC087 /* InfrastructureFactory.swift */, + 0E569F29259F2DB10022DFB8 /* Infrastructure+Metadata.swift */, + 0E569F28259F2DB10022DFB8 /* Infrastructure+Name.swift */, + 0E569F2A259F2DB10022DFB8 /* InfrastructureFactory.swift */, 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */, 0ED31C0F20CF09A30027975F /* Pool.swift */, 0E66A26F225FE25800F9C779 /* PoolCategory.swift */, @@ -544,20 +1046,20 @@ path = Services; sourceTree = ""; }; - 0EDE8DC020C86910004C739C /* Passepartout-iOS-Tunnel */ = { + 0EDE8DC020C86910004C739C /* Tunnel */ = { isa = PBXGroup; children = ( - 0ED31C3B20CF39510027975F /* Tunnel.entitlements */, - 0EDE8DC320C86910004C739C /* PacketTunnelProvider.swift */, - 0EDE8DC520C86910004C739C /* Info.plist */, + 0ED31C3B20CF39510027975F /* Tunnel-iOS.entitlements */, + 0E569FAA259F41690022DFB8 /* Tunnel-macOS.entitlements */, + 0EDE8DC320C86910004C739C /* Info.plist */, + 0E9AA977259F756A003FAFF1 /* PacketTunnelProvider.swift */, ); - path = "Passepartout-iOS-Tunnel"; + path = Tunnel; sourceTree = ""; }; 0EDE8DEC20C93E3B004C739C /* Global */ = { isa = PBXGroup; children = ( - 0E45E6E222BD793800F19312 /* App.strings */, 0E2EB062236D8E1E0079DB53 /* AppConstants+App.swift */, 0E3262D8235EE8DA00B5E470 /* HostImporter.swift */, 0EFD943D215BE10800529B64 /* IssueReporter.swift */, @@ -575,15 +1077,6 @@ path = Global; sourceTree = ""; }; - 0EDE8DEF20C93EBB004C739C /* Passepartout */ = { - isa = PBXGroup; - children = ( - 0E3CAF97229AAE760008E5C8 /* Resources */, - 0EDE8DF020C93EBB004C739C /* Sources */, - ); - path = Passepartout; - sourceTree = ""; - }; 0EDE8DF020C93EBB004C739C /* Sources */ = { isa = PBXGroup; children = ( @@ -594,7 +1087,7 @@ 0E39BCF2214DA9310035E9DE /* AppConstants.swift */, 0E6BE13920CFB76800A6DD36 /* ApplicationError.swift */, 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */, - 0EEF23402321AC55000AEBE3 /* Issue.swift */, + 0E569F14259F2D3E0022DFB8 /* Issue.swift */, 0E4FD7ED20D539A0002221FF /* Utils.swift */, ); path = Sources; @@ -621,32 +1114,28 @@ path = Scenes; sourceTree = ""; }; - 0EE4EB2C229A71BB000E4BA1 /* Libraries */ = { + 0EE4EB2C229A71BB000E4BA1 /* Submodules */ = { isa = PBXGroup; children = ( 0E3CAFC3229AAF8E0008E5C8 /* API */, - 0EE4EB2E229A71DA000E4BA1 /* Core */, ); - path = Libraries; - sourceTree = ""; - }; - 0EE4EB2E229A71DA000E4BA1 /* Core */ = { - isa = PBXGroup; - children = ( - 0EDE8DEF20C93EBB004C739C /* Passepartout */, - ); - path = Core; + path = Submodules; sourceTree = ""; }; 374B9F085E1148C37CF9117A /* Frameworks */ = { isa = PBXGroup; children = ( + 0E9AAAD3259F809F003FAFF1 /* ServiceManagement.framework */, 0ED31C3920CF39510027975F /* NetworkExtension.framework */, 0EDE8DD220C86978004C739C /* NotificationCenter.framework */, - 6D32B24AA7767AB2E7FB6E0F /* Pods_Passepartout_iOS.framework */, - FA4CE55A94366C45DDB1E624 /* Pods_Passepartout_iOS_Tunnel.framework */, - 276375A4CF0313B033CD8B5A /* Pods_PassepartoutCore_iOS.framework */, - 992C366F272FAA643335F68C /* Pods_PassepartoutCoreTests_iOS.framework */, + E070D15674A07F40A22BFA7E /* Pods_ios_Passepartout_iOS.framework */, + B93E25644660446940471003 /* Pods_ios_PassepartoutCore_iOS.framework */, + F661C42E70315D0788B19EDC /* Pods_ios_PassepartoutCoreTests_iOS.framework */, + FF7D2E624A2979425A6F7B7A /* Pods_ios_PassepartoutTunnel_iOS.framework */, + 23D4C05138CFBC311ED76548 /* Pods_macos_Passepartout_macOS.framework */, + 555477CACFC266802E4C2FF2 /* Pods_macos_PassepartoutCore_macOS.framework */, + C9BA8850A89C4680A6A23A65 /* Pods_macos_PassepartoutCoreTests_macOS.framework */, + 35380A14E9FF6F0250C171CD /* Pods_macos_PassepartoutTunnel_macOS.framework */, ); name = Frameworks; sourceTree = ""; @@ -662,6 +1151,26 @@ F1BECEC1D93FEBDB17B714D8 /* Pods-PassepartoutCore-iOS.release.xcconfig */, 0FD7B360EE444EF1CDBFDF1C /* Pods-PassepartoutCoreTests-iOS.debug.xcconfig */, 234D3C887F46AD64480495BB /* Pods-PassepartoutCoreTests-iOS.release.xcconfig */, + 155FC78114E324E01093F98C /* Pods-ios-Passepartout-iOS.debug.xcconfig */, + CFF79E4C42220C649C2259D2 /* Pods-ios-Passepartout-iOS.release.xcconfig */, + 0FDF9B1E8EC63CCF4A2C9694 /* Pods-ios-Passepartout-iOS-Tunnel.debug.xcconfig */, + E9433B826E8B47C325FD6B8F /* Pods-ios-Passepartout-iOS-Tunnel.release.xcconfig */, + 0376B8FDB39F81CA072C3F37 /* Pods-ios-PassepartoutCore-iOS.debug.xcconfig */, + 5CC1FDDBA184F8548D814E9D /* Pods-ios-PassepartoutCore-iOS.release.xcconfig */, + E08D99B2FCC4478BB24A57B0 /* Pods-macos-Passepartout-macOS.debug.xcconfig */, + 5C7F674900185F5DD24DA481 /* Pods-macos-Passepartout-macOS.release.xcconfig */, + B7018254471DA72DF7939A01 /* Pods-macos-Passepartout-macOS-Tunnel.debug.xcconfig */, + 055AC72673D0F12546CAEEA6 /* Pods-macos-Passepartout-macOS-Tunnel.release.xcconfig */, + 329F34FAC963CE4BEA3013D6 /* Pods-macos-PassepartoutCore-macOS.debug.xcconfig */, + C3D09D9270939FC37BE7101E /* Pods-macos-PassepartoutCore-macOS.release.xcconfig */, + A8E3B69460648EA46C1BF850 /* Pods-ios-PassepartoutCoreTests-iOS.debug.xcconfig */, + D5D3FFA0392EA5F818646CD9 /* Pods-ios-PassepartoutCoreTests-iOS.release.xcconfig */, + 7E007C60601AFBB8A2C34DC4 /* Pods-ios-PassepartoutTunnel-iOS.debug.xcconfig */, + 9FB2CA39113427B15C824FE0 /* Pods-ios-PassepartoutTunnel-iOS.release.xcconfig */, + E69B5CF79639B3D24F2AFFC9 /* Pods-macos-PassepartoutCoreTests-macOS.debug.xcconfig */, + 80A0C78A127E8CE9CB8E658D /* Pods-macos-PassepartoutCoreTests-macOS.release.xcconfig */, + 50DD79FBBBBF400F3BFE8912 /* Pods-macos-PassepartoutTunnel-macOS.debug.xcconfig */, + D2AF3AFC3418E6800D8A70E8 /* Pods-macos-PassepartoutTunnel-macOS.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -677,6 +1186,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E5203E5259F60D600CBAB56 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E5204A7259F66F700CBAB56 /* PassepartoutCore.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -699,6 +1216,69 @@ productReference = 0E31529B223F9EF400F61841 /* PassepartoutCore.framework */; productType = "com.apple.product-type.framework"; }; + 0E5202F6259F573500CBAB56 /* Passepartout-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E520304259F573800CBAB56 /* Build configuration list for PBXNativeTarget "Passepartout-macOS" */; + buildPhases = ( + 6D65C9B23CEAFE3755C8BC2B /* [CP] Check Pods Manifest.lock */, + 0E5202F3259F573500CBAB56 /* Sources */, + 0E5202F4259F573500CBAB56 /* Frameworks */, + 0E5202F5259F573500CBAB56 /* Resources */, + 0E9AAACA259F806B003FAFF1 /* CopyFiles */, + 0E5203C2259F5F3F00CBAB56 /* Embed App Extensions */, + 0E5203F6259F60D600CBAB56 /* Embed Frameworks */, + 5F0C817F8E72ADCEDA44DBC5 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0E5203BD259F5F3F00CBAB56 /* PBXTargetDependency */, + 0E5203F0259F60D600CBAB56 /* PBXTargetDependency */, + 0E9AAAC0259F7FFF003FAFF1 /* PBXTargetDependency */, + 0E9AAAC2259F800B003FAFF1 /* PBXTargetDependency */, + ); + name = "Passepartout-macOS"; + productName = "Passepartout-macOS"; + productReference = 0E5202F7259F573500CBAB56 /* Passepartout.app */; + productType = "com.apple.product-type.application"; + }; + 0E5203B4259F5F3F00CBAB56 /* PassepartoutTunnel-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E5203BF259F5F3F00CBAB56 /* Build configuration list for PBXNativeTarget "PassepartoutTunnel-macOS" */; + buildPhases = ( + A6026405EC7F053B50C8BFF4 /* [CP] Check Pods Manifest.lock */, + 0E5203B1259F5F3F00CBAB56 /* Sources */, + 0E5203B2259F5F3F00CBAB56 /* Frameworks */, + 0E5203B3259F5F3F00CBAB56 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PassepartoutTunnel-macOS"; + productName = "Passepartout-macOS-Tunnel"; + productReference = 0E5203B5259F5F3F00CBAB56 /* PassepartoutTunnel.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 0E5203E9259F60D600CBAB56 /* PassepartoutCore-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E5203F3259F60D600CBAB56 /* Build configuration list for PBXNativeTarget "PassepartoutCore-macOS" */; + buildPhases = ( + 6D3E350F59230E4C94ED9FDA /* [CP] Check Pods Manifest.lock */, + 0E5203E5259F60D600CBAB56 /* Headers */, + 0E5203E6259F60D600CBAB56 /* Sources */, + 0E5203E7259F60D600CBAB56 /* Frameworks */, + 0E5203E8259F60D600CBAB56 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PassepartoutCore-macOS"; + productName = "PassepartoutCore-macOS"; + productReference = 0E5203EA259F60D600CBAB56 /* PassepartoutCore.framework */; + productType = "com.apple.product-type.framework"; + }; 0E57F63720C83FC5008323CF /* Passepartout-iOS */ = { isa = PBXNativeTarget; buildConfigurationList = 0E57F65520C83FC7008323CF /* Build configuration list for PBXNativeTarget "Passepartout-iOS" */; @@ -722,9 +1302,66 @@ productReference = 0E57F63820C83FC5008323CF /* Passepartout.app */; productType = "com.apple.product-type.application"; }; - 0EDE8DBE20C86910004C739C /* Passepartout-iOS-Tunnel */ = { + 0E9AA98C259F779F003FAFF1 /* PassepartoutCoreTests-iOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 0EDE8DC920C86910004C739C /* Build configuration list for PBXNativeTarget "Passepartout-iOS-Tunnel" */; + buildConfigurationList = 0E9AA995259F779F003FAFF1 /* Build configuration list for PBXNativeTarget "PassepartoutCoreTests-iOS" */; + buildPhases = ( + 5CCA3608E9249955B3DEA5BF /* [CP] Check Pods Manifest.lock */, + 0E9AA989259F779F003FAFF1 /* Sources */, + 0E9AA98A259F779F003FAFF1 /* Frameworks */, + 0E9AA98B259F779F003FAFF1 /* Resources */, + F4BF37883BF513DD4EF79789 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0E9AA994259F779F003FAFF1 /* PBXTargetDependency */, + ); + name = "PassepartoutCoreTests-iOS"; + productName = "PassepartoutCoreTests-iOS"; + productReference = 0E9AA98D259F779F003FAFF1 /* PassepartoutCoreTests-iOS.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 0E9AA9B9259F7821003FAFF1 /* PassepartoutCoreTests-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E9AA9C2259F7821003FAFF1 /* Build configuration list for PBXNativeTarget "PassepartoutCoreTests-macOS" */; + buildPhases = ( + 1BFBF587EFF0D8EFB44539C5 /* [CP] Check Pods Manifest.lock */, + 0E9AA9B6259F7821003FAFF1 /* Sources */, + 0E9AA9B7259F7821003FAFF1 /* Frameworks */, + 0E9AA9B8259F7821003FAFF1 /* Resources */, + 07E82DB4E76B85853FE611FC /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 0E9AA9C1259F7821003FAFF1 /* PBXTargetDependency */, + ); + name = "PassepartoutCoreTests-macOS"; + productName = "PassepartoutCoreTests-macOS"; + productReference = 0E9AA9BA259F7821003FAFF1 /* PassepartoutCoreTests-macOS.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 0E9AAA60259F7D7E003FAFF1 /* PassepartoutLauncher-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0E9AAA70259F7D81003FAFF1 /* Build configuration list for PBXNativeTarget "PassepartoutLauncher-macOS" */; + buildPhases = ( + 0E9AAA5D259F7D7E003FAFF1 /* Sources */, + 0E9AAA5E259F7D7E003FAFF1 /* Frameworks */, + 0E9AAA5F259F7D7E003FAFF1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "PassepartoutLauncher-macOS"; + productName = "PassepartoutLauncher-macOS"; + productReference = 0E9AAA61259F7D7E003FAFF1 /* PassepartoutLauncher.app */; + productType = "com.apple.product-type.application"; + }; + 0EDE8DBE20C86910004C739C /* PassepartoutTunnel-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0EDE8DC920C86910004C739C /* Build configuration list for PBXNativeTarget "PassepartoutTunnel-iOS" */; buildPhases = ( 4316D2F30EA7143E6BB85EDE /* [CP] Check Pods Manifest.lock */, 0EDE8DBB20C86910004C739C /* Sources */, @@ -735,9 +1372,9 @@ ); dependencies = ( ); - name = "Passepartout-iOS-Tunnel"; + name = "PassepartoutTunnel-iOS"; productName = "Passepartout-iOS-Tunnel"; - productReference = 0EDE8DBF20C86910004C739C /* Passepartout-Tunnel.appex */; + productReference = 0EDE8DBF20C86910004C739C /* PassepartoutTunnel.appex */; productType = "com.apple.product-type.app-extension"; }; /* End PBXNativeTarget section */ @@ -746,7 +1383,7 @@ 0E57F63020C83FC5008323CF /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1010; + LastSwiftUpdateCheck = 1230; LastUpgradeCheck = 1220; ORGANIZATIONNAME = "Davide De Rosa"; TargetAttributes = { @@ -754,6 +1391,15 @@ CreatedOnToolsVersion = 10.1; LastSwiftMigration = 1020; }; + 0E5202F6259F573500CBAB56 = { + CreatedOnToolsVersion = 12.3; + }; + 0E5203B4259F5F3F00CBAB56 = { + CreatedOnToolsVersion = 12.3; + }; + 0E5203E9259F60D600CBAB56 = { + CreatedOnToolsVersion = 12.3; + }; 0E57F63720C83FC5008323CF = { CreatedOnToolsVersion = 9.4; LastSwiftMigration = 1020; @@ -772,6 +1418,15 @@ }; }; }; + 0E9AA98C259F779F003FAFF1 = { + CreatedOnToolsVersion = 12.3; + }; + 0E9AA9B9259F7821003FAFF1 = { + CreatedOnToolsVersion = 12.3; + }; + 0E9AAA60259F7D7E003FAFF1 = { + CreatedOnToolsVersion = 12.3; + }; 0EDE8DBE20C86910004C739C = { CreatedOnToolsVersion = 10.0; LastSwiftMigration = 1020; @@ -811,8 +1466,14 @@ projectRoot = ""; targets = ( 0E31529A223F9EF400F61841 /* PassepartoutCore-iOS */, + 0E9AA98C259F779F003FAFF1 /* PassepartoutCoreTests-iOS */, + 0EDE8DBE20C86910004C739C /* PassepartoutTunnel-iOS */, 0E57F63720C83FC5008323CF /* Passepartout-iOS */, - 0EDE8DBE20C86910004C739C /* Passepartout-iOS-Tunnel */, + 0E5203E9259F60D600CBAB56 /* PassepartoutCore-macOS */, + 0E9AA9B9259F7821003FAFF1 /* PassepartoutCoreTests-macOS */, + 0E9AAA60259F7D7E003FAFF1 /* PassepartoutLauncher-macOS */, + 0E5203B4259F5F3F00CBAB56 /* PassepartoutTunnel-macOS */, + 0E5202F6259F573500CBAB56 /* Passepartout-macOS */, ); }; /* End PBXProject section */ @@ -826,17 +1487,54 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E5202F5259F573500CBAB56 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E520337259F58F500CBAB56 /* ProviderServiceView.xib in Resources */, + 0E520336259F58F500CBAB56 /* HostServiceView.xib in Resources */, + 0E52031D259F58BF00CBAB56 /* Providers.xcassets in Resources */, + 0E52047D259F642600CBAB56 /* Preferences.storyboard in Resources */, + 0E52038F259F593F00CBAB56 /* App.strings in Resources */, + 0E520385259F593B00CBAB56 /* Credits.html in Resources */, + 0E52047C259F642600CBAB56 /* Service.storyboard in Resources */, + 0E52032B259F58DD00CBAB56 /* TextTableView.xib in Resources */, + 0E52047B259F642600CBAB56 /* Main.storyboard in Resources */, + 0E5204AA259F673100CBAB56 /* Core.strings in Resources */, + 0E520334259F58F500CBAB56 /* OrganizerProfileTableView.xib in Resources */, + 0E9AAABE259F7FFF003FAFF1 /* PassepartoutLauncher.app in Resources */, + 0E52031E259F58BF00CBAB56 /* Assets.xcassets in Resources */, + 0E52031F259F58BF00CBAB56 /* Flags.xcassets in Resources */, + 0E52035D259F591300CBAB56 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203B3259F5F3F00CBAB56 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203E8259F60D600CBAB56 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E5204E5259F67A000CBAB56 /* API in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 0E57F63620C83FC5008323CF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0E5204A9259F673000CBAB56 /* Core.strings in Resources */, 0E36D25822403469006AF062 /* Shortcuts.storyboard in Resources */, 0E0C0729236087A100155AAC /* InfoPlist.strings in Resources */, 0ED38ADA213F44D00004D387 /* Organizer.storyboard in Resources */, 0E24273A225950450064A1A3 /* About.storyboard in Resources */, 0E57F64620C83FC7008323CF /* LaunchScreen.storyboard in Resources */, 0E57F64320C83FC7008323CF /* Assets.xcassets in Resources */, - 0E45E6FA22BD8FC500F19312 /* Core.strings in Resources */, 0E9CD7872257462800D033B4 /* Providers.xcassets in Resources */, 0E9CD789225746B300D033B4 /* Flags.xcassets in Resources */, 0E57F64120C83FC5008323CF /* Main.storyboard in Resources */, @@ -846,6 +1544,31 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E9AA98B259F779F003FAFF1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA9FA259F799C003FAFF1 /* ConnectionService.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AA9B8259F7821003FAFF1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA9F0259F799B003FAFF1 /* ConnectionService.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AAA5F259F7D7E003FAFF1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AAA7F259F7DB7003FAFF1 /* Assets.xcassets in Resources */, + 0E9AAA89259F7DCA003FAFF1 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 0EDE8DBD20C86910004C739C /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -856,6 +1579,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 07E82DB4E76B85853FE611FC /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-macos-PassepartoutCoreTests-macOS/Pods-macos-PassepartoutCoreTests-macOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-macos-PassepartoutCoreTests-macOS/Pods-macos-PassepartoutCoreTests-macOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-macos-PassepartoutCoreTests-macOS/Pods-macos-PassepartoutCoreTests-macOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 0A0A35FE311454E07CF67743 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -871,7 +1611,29 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-PassepartoutCore-iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-ios-PassepartoutCore-iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 1BFBF587EFF0D8EFB44539C5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-macos-PassepartoutCoreTests-macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -893,7 +1655,90 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Passepartout-iOS-Tunnel-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-ios-PassepartoutTunnel-iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 5CCA3608E9249955B3DEA5BF /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ios-PassepartoutCoreTests-iOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 5F0C817F8E72ADCEDA44DBC5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-macos-Passepartout-macOS/Pods-macos-Passepartout-macOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-macos-Passepartout-macOS/Pods-macos-Passepartout-macOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-macos-Passepartout-macOS/Pods-macos-Passepartout-macOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 6D3E350F59230E4C94ED9FDA /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-macos-PassepartoutCore-macOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 6D65C9B23CEAFE3755C8BC2B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-macos-Passepartout-macOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -906,15 +1751,15 @@ files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Passepartout-iOS/Pods-Passepartout-iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-ios-Passepartout-iOS/Pods-ios-Passepartout-iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Passepartout-iOS/Pods-Passepartout-iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-ios-Passepartout-iOS/Pods-ios-Passepartout-iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Passepartout-iOS/Pods-Passepartout-iOS-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ios-Passepartout-iOS/Pods-ios-Passepartout-iOS-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 8598326924C7B7B17B82A427 /* [CP] Check Pods Manifest.lock */ = { @@ -932,13 +1777,52 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Passepartout-iOS-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-ios-Passepartout-iOS-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + A6026405EC7F053B50C8BFF4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-macos-PassepartoutTunnel-macOS-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + F4BF37883BF513DD4EF79789 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ios-PassepartoutCoreTests-iOS/Pods-ios-PassepartoutCoreTests-iOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ios-PassepartoutCoreTests-iOS/Pods-ios-PassepartoutCoreTests-iOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ios-PassepartoutCoreTests-iOS/Pods-ios-PassepartoutCoreTests-iOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -953,8 +1837,8 @@ 0E3152D2223FA05400F61841 /* DebugLog.swift in Sources */, 0E45E71022BE108100F19312 /* OpenVPNOptions.swift in Sources */, 0E3152DA223FA05800F61841 /* PlaceholderConnectionProfile.swift in Sources */, + 0E569F1E259F2D8F0022DFB8 /* ProductManager.swift in Sources */, 0E3152D0223FA05400F61841 /* ConnectionService+Migration.swift in Sources */, - 0E1C0A4F238FC7A5009FC087 /* InfrastructureFactory.swift in Sources */, 0E3152D5223FA05400F61841 /* SessionProxy+Communication.swift in Sources */, 0E3152D7223FA05400F61841 /* TrustedNetworks.swift in Sources */, 0E3152DB223FA05800F61841 /* ProfileKey.swift in Sources */, @@ -962,29 +1846,126 @@ 0E3152C8223FA04D00F61841 /* Infrastructure.swift in Sources */, 0E3152D8223FA05400F61841 /* TrustPolicy.swift in Sources */, 0E3152DC223FA05800F61841 /* ProviderConnectionProfile.swift in Sources */, + 0E569F2B259F2DB10022DFB8 /* Infrastructure+Name.swift in Sources */, 0E3152D9223FA05800F61841 /* HostConnectionProfile.swift in Sources */, 0E3152D6223FA05400F61841 /* TransientStore.swift in Sources */, 0E3152CC223FA04D00F61841 /* WebServices.swift in Sources */, - 0ECA7E2D25967BF40095F369 /* Product.swift in Sources */, 0E3152BB223FA03D00F61841 /* AppConstants.swift in Sources */, 0E3152CA223FA04D00F61841 /* InfrastructurePreset.swift in Sources */, 0E3152CE223FA05400F61841 /* ConnectionService.swift in Sources */, 0ED993B1223FF8C700B0F9C9 /* IntentDispatcher.swift in Sources */, - 0EA84515238A9B5200EFC500 /* Infrastructure+Name.swift in Sources */, - 0EAC572F249426E200D0FCE0 /* GracefulVPN.swift in Sources */, - 0EEF23412321AC55000AEBE3 /* Issue.swift in Sources */, + 0E569F31259F2DC10022DFB8 /* TrustedNetworksUI.swift in Sources */, + 0E569F1C259F2D8F0022DFB8 /* GracefulVPN.swift in Sources */, + 0E569F2C259F2DB10022DFB8 /* Infrastructure+Metadata.swift in Sources */, 0E3152D1223FA05400F61841 /* Credentials.swift in Sources */, 0E3152CD223FA05400F61841 /* ConnectionProfile.swift in Sources */, 0E3152BC223FA03D00F61841 /* ApplicationError.swift in Sources */, + 0E569F15259F2D3E0022DFB8 /* Issue.swift in Sources */, 0E3152D3223FA05400F61841 /* EndpointDataSource.swift in Sources */, + 0E569F2D259F2DB10022DFB8 /* InfrastructureFactory.swift in Sources */, 0E3152D4223FA05400F61841 /* Preferences.swift in Sources */, 0EFB901822764689006405E4 /* ProfileNetworkSettings.swift in Sources */, 0E3152C0223FA03D00F61841 /* Utils.swift in Sources */, 0E3152CB223FA04D00F61841 /* Pool.swift in Sources */, - 0EA8451A238C2AB500EFC500 /* Infrastructure+Metadata.swift in Sources */, - 0EB9EB7323867E7F009C0A1C /* TrustedNetworksUI.swift in Sources */, - 0ECA7E3025967BFB0095F369 /* ProductManager.swift in Sources */, 0E3CAFC0229AAE770008E5C8 /* Intents.intentdefinition in Sources */, + 0E569F20259F2D8F0022DFB8 /* Product.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5202F3259F573500CBAB56 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E520388259F593B00CBAB56 /* HostImporter.swift in Sources */, + 0E520379259F593B00CBAB56 /* Macros.swift in Sources */, + 0E520387259F593B00CBAB56 /* TextInputViewController.swift in Sources */, + 0E52033B259F58F500CBAB56 /* OrganizerViewController.swift in Sources */, + 0E520382259F593B00CBAB56 /* SwiftGen+Scenes.swift in Sources */, + 0E52032C259F58DD00CBAB56 /* TextTableView.swift in Sources */, + 0E520355259F590600CBAB56 /* DebugLogViewController.swift in Sources */, + 0E52034A259F58FE00CBAB56 /* DefaultGatewayViewController.swift in Sources */, + 0E520345259F58FE00CBAB56 /* DNSViewController.swift in Sources */, + 0E52037D259F593B00CBAB56 /* SwiftGen+Strings.swift in Sources */, + 0E520320259F58BF00CBAB56 /* AppDelegate.swift in Sources */, + 0E520344259F58FE00CBAB56 /* TrustedNetworksAddViewController.swift in Sources */, + 0E52033A259F58F500CBAB56 /* AccountViewController.swift in Sources */, + 0E520356259F590600CBAB56 /* PreferencesGeneralViewController.swift in Sources */, + 0E520348259F58FE00CBAB56 /* MTUViewController.swift in Sources */, + 0E52037E259F593B00CBAB56 /* SwiftGen+Segues.swift in Sources */, + 0E52037C259F593B00CBAB56 /* Theme.swift in Sources */, + 0E52035E259F591300CBAB56 /* StatusMenu.swift in Sources */, + 0E52035F259F591300CBAB56 /* MainMenu.swift in Sources */, + 0E520342259F58FE00CBAB56 /* EndpointViewController.swift in Sources */, + 0E520339259F58F500CBAB56 /* ServiceViewController.swift in Sources */, + 0E520383259F593B00CBAB56 /* SwiftGen+Assets.swift in Sources */, + 0E52037A259F593B00CBAB56 /* WindowManager.swift in Sources */, + 0E520381259F593B00CBAB56 /* NSTextView+Search.swift in Sources */, + 0E520349259F58FE00CBAB56 /* ConfigurationViewController.swift in Sources */, + 0E520354259F590600CBAB56 /* PreferencesViewController.swift in Sources */, + 0E520343259F58FE00CBAB56 /* ProfileCustomizationViewController.swift in Sources */, + 0E520346259F58FE00CBAB56 /* TrustedNetworksViewController.swift in Sources */, + 0E520338259F58F500CBAB56 /* ProviderServiceView.swift in Sources */, + 0E520347259F58FE00CBAB56 /* ProxyViewController.swift in Sources */, + 0E520380259F593B00CBAB56 /* AppConstants+App.swift in Sources */, + 0E52037B259F593B00CBAB56 /* IssueReporter.swift in Sources */, + 0E520335259F58F500CBAB56 /* HostServiceView.swift in Sources */, + 0E520384259F593B00CBAB56 /* Donation.swift in Sources */, + 0E520333259F58F500CBAB56 /* OrganizerProfileTableView.swift in Sources */, + 0E52037F259F593B00CBAB56 /* Theme+Views.swift in Sources */, + 0E520386259F593B00CBAB56 /* ProductManager+App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203B1259F5F3F00CBAB56 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA979259F756A003FAFF1 /* PacketTunnelProvider.swift in Sources */, + 0E52041F259F62B200CBAB56 /* GroupConstants.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E5203E6259F60D600CBAB56 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E5204D3259F675400CBAB56 /* ConnectionService+Migration.swift in Sources */, + 0E5204C1259F675400CBAB56 /* Infrastructure+Metadata.swift in Sources */, + 0E5204BC259F674400CBAB56 /* TrustedNetworksUI.swift in Sources */, + 0E5204D9259F675400CBAB56 /* Preferences.swift in Sources */, + 0E5204DD259F675400CBAB56 /* InfrastructurePreset.swift in Sources */, + 0E5204CE259F675400CBAB56 /* Credentials.swift in Sources */, + 0E5204E0259F675400CBAB56 /* WebServices.swift in Sources */, + 0E5204DF259F675400CBAB56 /* SessionProxy+Communication.swift in Sources */, + 0E5204D7259F675400CBAB56 /* DebugLog.swift in Sources */, + 0E5204C4259F675400CBAB56 /* TrustPolicy.swift in Sources */, + 0E5204CA259F675400CBAB56 /* ProfileNetworkSettings.swift in Sources */, + 0E5204C8259F675400CBAB56 /* PoolGroup.swift in Sources */, + 0E5204DB259F675400CBAB56 /* TransientStore.swift in Sources */, + 0E5204D6259F675400CBAB56 /* DataUnit.swift in Sources */, + 0E5204DA259F675400CBAB56 /* ProductManager.swift in Sources */, + 0E5204C6259F675400CBAB56 /* Pool.swift in Sources */, + 0E5204B1259F673D00CBAB56 /* GroupConstants.swift in Sources */, + 0E5204D5259F675400CBAB56 /* ProfileKey.swift in Sources */, + 0E5204D1259F675400CBAB56 /* PlaceholderConnectionProfile.swift in Sources */, + 0E5204AF259F673D00CBAB56 /* ApplicationError.swift in Sources */, + 0E5204B0259F673D00CBAB56 /* Issue.swift in Sources */, + 0E5204CB259F675400CBAB56 /* EndpointDataSource.swift in Sources */, + 0E5204DE259F675400CBAB56 /* OpenVPNOptions.swift in Sources */, + 0E5204C5259F675400CBAB56 /* ProviderConnectionProfile.swift in Sources */, + 0E5204D0259F675400CBAB56 /* Infrastructure.swift in Sources */, + 0E5204D4259F675400CBAB56 /* ConnectionService.swift in Sources */, + 0E5204DC259F675400CBAB56 /* GracefulVPN.swift in Sources */, + 0E5204C2259F675400CBAB56 /* PoolCategory.swift in Sources */, + 0E5204C3259F675400CBAB56 /* InfrastructureFactory.swift in Sources */, + 0E5204C9259F675400CBAB56 /* ConnectionService+Configurations.swift in Sources */, + 0E5204B2259F673D00CBAB56 /* Utils.swift in Sources */, + 0E5204CF259F675400CBAB56 /* TrustedNetworks.swift in Sources */, + 0E5204D2259F675400CBAB56 /* ConnectionProfile.swift in Sources */, + 0E5204CD259F675400CBAB56 /* Infrastructure+Name.swift in Sources */, + 0E5204CC259F675400CBAB56 /* HostConnectionProfile.swift in Sources */, + 0E5204B7259F674000CBAB56 /* AppConstants.swift in Sources */, + 0E5204C7259F675400CBAB56 /* Product.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1037,13 +2018,40 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0E9AA989259F779F003FAFF1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA9FC259F799C003FAFF1 /* InfrastructureTests.swift in Sources */, + 0E9AA9F9259F799C003FAFF1 /* ConnectionServiceTests.swift in Sources */, + 0E9AA9FB259F799C003FAFF1 /* UtilsTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AA9B6259F7821003FAFF1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AA9F2259F799B003FAFF1 /* InfrastructureTests.swift in Sources */, + 0E9AA9EF259F799B003FAFF1 /* ConnectionServiceTests.swift in Sources */, + 0E9AA9F1259F799B003FAFF1 /* UtilsTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0E9AAA5D259F7D7E003FAFF1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E9AAA80259F7DB7003FAFF1 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 0EDE8DBB20C86910004C739C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0EDE8DC420C86910004C739C /* PacketTunnelProvider.swift in Sources */, 0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */, - 0EF5CF292141F31F004FF1BD /* Utils.swift in Sources */, + 0E9AA978259F756A003FAFF1 /* PacketTunnelProvider.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1055,9 +2063,40 @@ target = 0E31529A223F9EF400F61841 /* PassepartoutCore-iOS */; targetProxy = 0E3152AE223F9EF500F61841 /* PBXContainerItemProxy */; }; + 0E5203BD259F5F3F00CBAB56 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E5203B4259F5F3F00CBAB56 /* PassepartoutTunnel-macOS */; + targetProxy = 0E5203BC259F5F3F00CBAB56 /* PBXContainerItemProxy */; + }; + 0E5203F0259F60D600CBAB56 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E5203E9259F60D600CBAB56 /* PassepartoutCore-macOS */; + targetProxy = 0E5203EF259F60D600CBAB56 /* PBXContainerItemProxy */; + }; + 0E9AA994259F779F003FAFF1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + platformFilter = ios; + target = 0E31529A223F9EF400F61841 /* PassepartoutCore-iOS */; + targetProxy = 0E9AA993259F779F003FAFF1 /* PBXContainerItemProxy */; + }; + 0E9AA9C1259F7821003FAFF1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E5203E9259F60D600CBAB56 /* PassepartoutCore-macOS */; + targetProxy = 0E9AA9C0259F7821003FAFF1 /* PBXContainerItemProxy */; + }; + 0E9AAAC0259F7FFF003FAFF1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E9AAA60259F7D7E003FAFF1 /* PassepartoutLauncher-macOS */; + targetProxy = 0E9AAABF259F7FFF003FAFF1 /* PBXContainerItemProxy */; + }; + 0E9AAAC2259F800B003FAFF1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E9AAA60259F7D7E003FAFF1 /* PassepartoutLauncher-macOS */; + targetProxy = 0E9AAAC1259F800B003FAFF1 /* PBXContainerItemProxy */; + }; 0EDE8DC720C86910004C739C /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 0EDE8DBE20C86910004C739C /* Passepartout-iOS-Tunnel */; + target = 0EDE8DBE20C86910004C739C /* PassepartoutTunnel-iOS */; targetProxy = 0EDE8DC620C86910004C739C /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -1164,6 +2203,46 @@ name = Purchase.storyboard; sourceTree = ""; }; + 0E569F5F259F41690022DFB8 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 0E569F60259F41690022DFB8 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 0E569F81259F41690022DFB8 /* Preferences.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 0E569F82259F41690022DFB8 /* Base */, + ); + name = Preferences.storyboard; + sourceTree = ""; + }; + 0E569F83259F41690022DFB8 /* Service.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 0E569F84259F41690022DFB8 /* Base */, + ); + name = Service.storyboard; + sourceTree = ""; + }; + 0E569F85259F41690022DFB8 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 0E569F86259F41690022DFB8 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 0E569F8D259F41690022DFB8 /* App.strings */ = { + isa = PBXVariantGroup; + children = ( + 0E569F91259F41690022DFB8 /* en */, + ); + name = App.strings; + sourceTree = ""; + }; 0E57F63F20C83FC5008323CF /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -1193,7 +2272,7 @@ /* Begin XCBuildConfiguration section */ 0E3152B2223F9EF500F61841 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A1C4E67627603307808F2FFC /* Pods-PassepartoutCore-iOS.debug.xcconfig */; + baseConfigurationReference = 0376B8FDB39F81CA072C3F37 /* Pods-ios-PassepartoutCore-iOS.debug.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; CODE_SIGN_IDENTITY = ""; @@ -1204,7 +2283,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "PassepartoutCore-iOS/Info.plist"; + INFOPLIST_FILE = Passepartout/Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1217,6 +2296,7 @@ PRODUCT_NAME = PassepartoutCore; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1225,7 +2305,7 @@ }; 0E3152B3223F9EF500F61841 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F1BECEC1D93FEBDB17B714D8 /* Pods-PassepartoutCore-iOS.release.xcconfig */; + baseConfigurationReference = 5CC1FDDBA184F8548D814E9D /* Pods-ios-PassepartoutCore-iOS.release.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; CODE_SIGN_IDENTITY = ""; @@ -1236,7 +2316,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "PassepartoutCore-iOS/Info.plist"; + INFOPLIST_FILE = Passepartout/Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1248,12 +2328,186 @@ PRODUCT_NAME = PassepartoutCore; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; + 0E520305259F573800CBAB56 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E08D99B2FCC4478BB24A57B0 /* Pods-macos-Passepartout-macOS.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Passepartout/App/macOS/App.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Passepartout/App/macOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_MACOS_ID)"; + PRODUCT_NAME = Passepartout; + PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.macos.Passepartout macos"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 0E520306259F573800CBAB56 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5C7F674900185F5DD24DA481 /* Pods-macos-Passepartout-macOS.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Passepartout/App/macOS/App.entitlements; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Passepartout/App/macOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_MACOS_ID)"; + PRODUCT_NAME = Passepartout; + PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.macos.Passepartout macos"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 0E5203C0259F5F3F00CBAB56 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 50DD79FBBBBF400F3BFE8912 /* Pods-macos-PassepartoutTunnel-macOS.debug.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "Passepartout/Tunnel/Tunnel-macOS.entitlements"; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Passepartout/Tunnel/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_MACOS_ID).Tunnel"; + PRODUCT_NAME = PassepartoutTunnel; + PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.macos.Passepartout.Tunnel macos"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 0E5203C1259F5F3F00CBAB56 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D2AF3AFC3418E6800D8A70E8 /* Pods-macos-PassepartoutTunnel-macOS.release.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = "Passepartout/Tunnel/Tunnel-macOS.entitlements"; + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Passepartout/Tunnel/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_MACOS_ID).Tunnel"; + PRODUCT_NAME = PassepartoutTunnel; + PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.macos.Passepartout.Tunnel macos"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 0E5203F4259F60D600CBAB56 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 329F34FAC963CE4BEA3013D6 /* Pods-macos-PassepartoutCore-macOS.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 974; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = DTDYD63ZX9; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Passepartout/Core/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.PassepartoutCore; + PRODUCT_NAME = PassepartoutCore; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0E5203F5259F60D600CBAB56 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C3D09D9270939FC37BE7101E /* Pods-macos-PassepartoutCore-macOS.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 974; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = DTDYD63ZX9; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Passepartout/Core/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.PassepartoutCore; + PRODUCT_NAME = PassepartoutCore; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; 0E57F65320C83FC7008323CF /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0E23B4A12298559800304C30 /* Config.xcconfig */; @@ -1310,12 +2564,14 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,6"; }; name = Debug; }; @@ -1369,31 +2625,33 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,6"; VALIDATE_PRODUCT = YES; }; name = Release; }; 0E57F65620C83FC7008323CF /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F4959B5F3CB1BBC2C46EA639 /* Pods-Passepartout-iOS.debug.xcconfig */; + baseConfigurationReference = 155FC78114E324E01093F98C /* Pods-ios-Passepartout-iOS.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = "Passepartout-iOS/Passepartout.entitlements"; + CODE_SIGN_ENTITLEMENTS = Passepartout/App/iOS/App.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = DTDYD63ZX9; - INFOPLIST_FILE = "Passepartout-iOS/Info.plist"; + INFOPLIST_FILE = Passepartout/App/iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID)"; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_IOS_ID)"; PRODUCT_NAME = Passepartout; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -1403,43 +2661,182 @@ }; 0E57F65720C83FC7008323CF /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 53B773C4BAE7EDB38C7AFCD1 /* Pods-Passepartout-iOS.release.xcconfig */; + baseConfigurationReference = CFF79E4C42220C649C2259D2 /* Pods-ios-Passepartout-iOS.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = "Passepartout-iOS/Passepartout.entitlements"; + CODE_SIGN_ENTITLEMENTS = Passepartout/App/iOS/App.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = DTDYD63ZX9; - INFOPLIST_FILE = "Passepartout-iOS/Info.plist"; + INFOPLIST_FILE = Passepartout/App/iOS/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID)"; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_IOS_ID)"; PRODUCT_NAME = Passepartout; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; + 0E9AA996259F779F003FAFF1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A8E3B69460648EA46C1BF850 /* Pods-ios-PassepartoutCoreTests-iOS.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = Passepartout/Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0E9AA997259F779F003FAFF1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D5D3FFA0392EA5F818646CD9 /* Pods-ios-PassepartoutCoreTests-iOS.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = Passepartout/Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.ios.Passepartout.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 0E9AA9C3259F7821003FAFF1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E69B5CF79639B3D24F2AFFC9 /* Pods-macos-PassepartoutCoreTests-macOS.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = Passepartout/Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.Passepartout.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 0E9AA9C4259F7821003FAFF1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 80A0C78A127E8CE9CB8E658D /* Pods-macos-PassepartoutCoreTests-macOS.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = Passepartout/Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.Passepartout.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 0E9AAA6E259F7D81003FAFF1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Passepartout/App/macOS/Launcher/Launcher.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Passepartout/App/macOS/Launcher/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.Passepartout.Launcher; + PRODUCT_NAME = PassepartoutLauncher; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 0E9AAA6F259F7D81003FAFF1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Passepartout/App/macOS/Launcher/Launcher.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEVELOPMENT_TEAM = DTDYD63ZX9; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = Passepartout/App/macOS/Launcher/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.algoritmico.macos.Passepartout.Launcher; + PRODUCT_NAME = PassepartoutLauncher; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; 0EDE8DCA20C86910004C739C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 09CB728874F1553EF27BAAB9 /* Pods-Passepartout-iOS-Tunnel.debug.xcconfig */; + baseConfigurationReference = 7E007C60601AFBB8A2C34DC4 /* Pods-ios-PassepartoutTunnel-iOS.debug.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = "Passepartout-iOS-Tunnel/Tunnel.entitlements"; + CODE_SIGN_ENTITLEMENTS = "Passepartout/Tunnel/Tunnel-iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = DTDYD63ZX9; - INFOPLIST_FILE = "Passepartout-iOS-Tunnel/Info.plist"; + INFOPLIST_FILE = Passepartout/Tunnel/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID).Tunnel"; - PRODUCT_NAME = "Passepartout-Tunnel"; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_IOS_ID).Tunnel"; + PRODUCT_NAME = PassepartoutTunnel; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout.Tunnel"; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1448,20 +2845,20 @@ }; 0EDE8DCB20C86910004C739C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4BD12523ABCBF7ED941FC270 /* Pods-Passepartout-iOS-Tunnel.release.xcconfig */; + baseConfigurationReference = 9FB2CA39113427B15C824FE0 /* Pods-ios-PassepartoutTunnel-iOS.release.xcconfig */; buildSettings = { - CODE_SIGN_ENTITLEMENTS = "Passepartout-iOS-Tunnel/Tunnel.entitlements"; + CODE_SIGN_ENTITLEMENTS = "Passepartout/Tunnel/Tunnel-iOS.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = DTDYD63ZX9; - INFOPLIST_FILE = "Passepartout-iOS-Tunnel/Info.plist"; + INFOPLIST_FILE = Passepartout/Tunnel/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_ID).Tunnel"; - PRODUCT_NAME = "Passepartout-Tunnel"; + PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_APP_IOS_ID).Tunnel"; + PRODUCT_NAME = PassepartoutTunnel; PROVISIONING_PROFILE_SPECIFIER = "match Development com.algoritmico.ios.Passepartout.Tunnel"; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1480,6 +2877,33 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 0E520304259F573800CBAB56 /* Build configuration list for PBXNativeTarget "Passepartout-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E520305259F573800CBAB56 /* Debug */, + 0E520306259F573800CBAB56 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0E5203BF259F5F3F00CBAB56 /* Build configuration list for PBXNativeTarget "PassepartoutTunnel-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E5203C0259F5F3F00CBAB56 /* Debug */, + 0E5203C1259F5F3F00CBAB56 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0E5203F3259F60D600CBAB56 /* Build configuration list for PBXNativeTarget "PassepartoutCore-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E5203F4259F60D600CBAB56 /* Debug */, + 0E5203F5259F60D600CBAB56 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 0E57F63320C83FC5008323CF /* Build configuration list for PBXProject "Passepartout" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1498,7 +2922,34 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0EDE8DC920C86910004C739C /* Build configuration list for PBXNativeTarget "Passepartout-iOS-Tunnel" */ = { + 0E9AA995259F779F003FAFF1 /* Build configuration list for PBXNativeTarget "PassepartoutCoreTests-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E9AA996259F779F003FAFF1 /* Debug */, + 0E9AA997259F779F003FAFF1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0E9AA9C2259F7821003FAFF1 /* Build configuration list for PBXNativeTarget "PassepartoutCoreTests-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E9AA9C3259F7821003FAFF1 /* Debug */, + 0E9AA9C4259F7821003FAFF1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0E9AAA70259F7D81003FAFF1 /* Build configuration list for PBXNativeTarget "PassepartoutLauncher-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0E9AAA6E259F7D81003FAFF1 /* Debug */, + 0E9AAA6F259F7D81003FAFF1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0EDE8DC920C86910004C739C /* Build configuration list for PBXNativeTarget "PassepartoutTunnel-iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 0EDE8DCA20C86910004C739C /* Debug */, diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-iOS.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-iOS.xcscheme index 92a99058..d4340d16 100644 --- a/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-iOS.xcscheme +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-iOS.xcscheme @@ -29,8 +29,8 @@ diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-macOS.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-macOS.xcscheme new file mode 100644 index 00000000..dc026fed --- /dev/null +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-macOS.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-Core.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCore-iOS.xcscheme similarity index 98% rename from Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-Core.xcscheme rename to Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCore-iOS.xcscheme index 144c7c64..5ec35ab6 100644 --- a/Passepartout.xcodeproj/xcshareddata/xcschemes/Passepartout-Core.xcscheme +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCore-iOS.xcscheme @@ -41,7 +41,7 @@ skipped = "NO"> diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCore-macOS.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCore-macOS.xcscheme new file mode 100644 index 00000000..8440fccb --- /dev/null +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCore-macOS.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCoreTests-iOS.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCoreTests-iOS.xcscheme new file mode 100644 index 00000000..a7685ae4 --- /dev/null +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCoreTests-iOS.xcscheme @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCoreTests-macOS.xcscheme b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCoreTests-macOS.xcscheme new file mode 100644 index 00000000..4b4d29e2 --- /dev/null +++ b/Passepartout.xcodeproj/xcshareddata/xcschemes/PassepartoutCoreTests-macOS.xcscheme @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout-iOS/Passepartout.entitlements b/Passepartout/App/iOS/App.entitlements similarity index 100% rename from Passepartout-iOS/Passepartout.entitlements rename to Passepartout/App/iOS/App.entitlements diff --git a/Passepartout-iOS/AppDelegate.swift b/Passepartout/App/iOS/AppDelegate.swift similarity index 100% rename from Passepartout-iOS/AppDelegate.swift rename to Passepartout/App/iOS/AppDelegate.swift diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-120.png b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-120.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-120.png rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-120.png diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-152.png b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-152.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-152.png rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-152.png diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-167.png b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-167.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-167.png rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-167.png diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-180.png b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-180.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-180.png rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-180.png diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-76.png b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-76.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-76.png rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/AppIcon-76.png diff --git a/Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Passepartout-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Passepartout/App/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Passepartout-iOS/Assets.xcassets/Contents.json b/Passepartout/App/iOS/Assets.xcassets/Contents.json similarity index 100% rename from Passepartout-iOS/Assets.xcassets/Contents.json rename to Passepartout/App/iOS/Assets.xcassets/Contents.json diff --git a/Passepartout-iOS/Assets.xcassets/logo.imageset/Contents.json b/Passepartout/App/iOS/Assets.xcassets/logo.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Assets.xcassets/logo.imageset/Contents.json rename to Passepartout/App/iOS/Assets.xcassets/logo.imageset/Contents.json diff --git a/Passepartout-iOS/Assets.xcassets/logo.imageset/logo@2x.png b/Passepartout/App/iOS/Assets.xcassets/logo.imageset/logo@2x.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/logo.imageset/logo@2x.png rename to Passepartout/App/iOS/Assets.xcassets/logo.imageset/logo@2x.png diff --git a/Passepartout-iOS/Assets.xcassets/logo.imageset/logo@3x.png b/Passepartout/App/iOS/Assets.xcassets/logo.imageset/logo@3x.png similarity index 100% rename from Passepartout-iOS/Assets.xcassets/logo.imageset/logo@3x.png rename to Passepartout/App/iOS/Assets.xcassets/logo.imageset/logo@3x.png diff --git a/Passepartout-iOS/Base.lproj/About.storyboard b/Passepartout/App/iOS/Base.lproj/About.storyboard similarity index 100% rename from Passepartout-iOS/Base.lproj/About.storyboard rename to Passepartout/App/iOS/Base.lproj/About.storyboard diff --git a/Passepartout-iOS/Base.lproj/LaunchScreen.storyboard b/Passepartout/App/iOS/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Passepartout-iOS/Base.lproj/LaunchScreen.storyboard rename to Passepartout/App/iOS/Base.lproj/LaunchScreen.storyboard diff --git a/Passepartout-iOS/Base.lproj/Main.storyboard b/Passepartout/App/iOS/Base.lproj/Main.storyboard similarity index 100% rename from Passepartout-iOS/Base.lproj/Main.storyboard rename to Passepartout/App/iOS/Base.lproj/Main.storyboard diff --git a/Passepartout-iOS/Base.lproj/Organizer.storyboard b/Passepartout/App/iOS/Base.lproj/Organizer.storyboard similarity index 100% rename from Passepartout-iOS/Base.lproj/Organizer.storyboard rename to Passepartout/App/iOS/Base.lproj/Organizer.storyboard diff --git a/Passepartout-iOS/Base.lproj/Purchase.storyboard b/Passepartout/App/iOS/Base.lproj/Purchase.storyboard similarity index 100% rename from Passepartout-iOS/Base.lproj/Purchase.storyboard rename to Passepartout/App/iOS/Base.lproj/Purchase.storyboard diff --git a/Passepartout-iOS/Base.lproj/Shortcuts.storyboard b/Passepartout/App/iOS/Base.lproj/Shortcuts.storyboard similarity index 100% rename from Passepartout-iOS/Base.lproj/Shortcuts.storyboard rename to Passepartout/App/iOS/Base.lproj/Shortcuts.storyboard diff --git a/CHANGELOG.md b/Passepartout/App/iOS/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to Passepartout/App/iOS/CHANGELOG.md diff --git a/Passepartout-iOS/Cells/ActivityTableViewCell.swift b/Passepartout/App/iOS/Cells/ActivityTableViewCell.swift similarity index 100% rename from Passepartout-iOS/Cells/ActivityTableViewCell.swift rename to Passepartout/App/iOS/Cells/ActivityTableViewCell.swift diff --git a/Passepartout-iOS/Cells/Cells.swift b/Passepartout/App/iOS/Cells/Cells.swift similarity index 100% rename from Passepartout-iOS/Cells/Cells.swift rename to Passepartout/App/iOS/Cells/Cells.swift diff --git a/Passepartout-iOS/Cells/DestructiveTableViewCell.swift b/Passepartout/App/iOS/Cells/DestructiveTableViewCell.swift similarity index 100% rename from Passepartout-iOS/Cells/DestructiveTableViewCell.swift rename to Passepartout/App/iOS/Cells/DestructiveTableViewCell.swift diff --git a/Passepartout-iOS/Cells/FieldTableViewCell.swift b/Passepartout/App/iOS/Cells/FieldTableViewCell.swift similarity index 100% rename from Passepartout-iOS/Cells/FieldTableViewCell.swift rename to Passepartout/App/iOS/Cells/FieldTableViewCell.swift diff --git a/Passepartout-iOS/Cells/SettingTableViewCell.swift b/Passepartout/App/iOS/Cells/SettingTableViewCell.swift similarity index 100% rename from Passepartout-iOS/Cells/SettingTableViewCell.swift rename to Passepartout/App/iOS/Cells/SettingTableViewCell.swift diff --git a/Passepartout-iOS/Cells/ToggleTableViewCell.swift b/Passepartout/App/iOS/Cells/ToggleTableViewCell.swift similarity index 100% rename from Passepartout-iOS/Cells/ToggleTableViewCell.swift rename to Passepartout/App/iOS/Cells/ToggleTableViewCell.swift diff --git a/Passepartout-iOS/Flags.xcassets/Contents.json b/Passepartout/App/iOS/Flags.xcassets/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ad.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ad.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ad.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ad.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ad.imageset/ad@2x.png b/Passepartout/App/iOS/Flags.xcassets/ad.imageset/ad@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ad.imageset/ad@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ad.imageset/ad@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ad.imageset/ad@3x.png b/Passepartout/App/iOS/Flags.xcassets/ad.imageset/ad@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ad.imageset/ad@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ad.imageset/ad@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ae.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ae.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ae.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ae.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ae.imageset/ae@2x.png b/Passepartout/App/iOS/Flags.xcassets/ae.imageset/ae@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ae.imageset/ae@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ae.imageset/ae@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ae.imageset/ae@3x.png b/Passepartout/App/iOS/Flags.xcassets/ae.imageset/ae@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ae.imageset/ae@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ae.imageset/ae@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/af.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/af.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/af.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/af.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/af.imageset/af@2x.png b/Passepartout/App/iOS/Flags.xcassets/af.imageset/af@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/af.imageset/af@2x.png rename to Passepartout/App/iOS/Flags.xcassets/af.imageset/af@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/af.imageset/af@3x.png b/Passepartout/App/iOS/Flags.xcassets/af.imageset/af@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/af.imageset/af@3x.png rename to Passepartout/App/iOS/Flags.xcassets/af.imageset/af@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ag.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ag.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ag.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ag.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ag.imageset/ag@2x.png b/Passepartout/App/iOS/Flags.xcassets/ag.imageset/ag@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ag.imageset/ag@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ag.imageset/ag@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ag.imageset/ag@3x.png b/Passepartout/App/iOS/Flags.xcassets/ag.imageset/ag@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ag.imageset/ag@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ag.imageset/ag@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ai.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ai.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ai.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ai.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ai.imageset/ai@2x.png b/Passepartout/App/iOS/Flags.xcassets/ai.imageset/ai@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ai.imageset/ai@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ai.imageset/ai@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ai.imageset/ai@3x.png b/Passepartout/App/iOS/Flags.xcassets/ai.imageset/ai@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ai.imageset/ai@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ai.imageset/ai@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/al.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/al.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/al.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/al.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/al.imageset/al@2x.png b/Passepartout/App/iOS/Flags.xcassets/al.imageset/al@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/al.imageset/al@2x.png rename to Passepartout/App/iOS/Flags.xcassets/al.imageset/al@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/al.imageset/al@3x.png b/Passepartout/App/iOS/Flags.xcassets/al.imageset/al@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/al.imageset/al@3x.png rename to Passepartout/App/iOS/Flags.xcassets/al.imageset/al@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/am.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/am.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/am.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/am.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/am.imageset/am@2x.png b/Passepartout/App/iOS/Flags.xcassets/am.imageset/am@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/am.imageset/am@2x.png rename to Passepartout/App/iOS/Flags.xcassets/am.imageset/am@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/am.imageset/am@3x.png b/Passepartout/App/iOS/Flags.xcassets/am.imageset/am@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/am.imageset/am@3x.png rename to Passepartout/App/iOS/Flags.xcassets/am.imageset/am@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ao.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ao.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ao.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ao.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ao.imageset/ao@2x.png b/Passepartout/App/iOS/Flags.xcassets/ao.imageset/ao@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ao.imageset/ao@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ao.imageset/ao@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ao.imageset/ao@3x.png b/Passepartout/App/iOS/Flags.xcassets/ao.imageset/ao@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ao.imageset/ao@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ao.imageset/ao@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/aq.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/aq.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/aq.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/aq.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/aq.imageset/aq@2x.png b/Passepartout/App/iOS/Flags.xcassets/aq.imageset/aq@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/aq.imageset/aq@2x.png rename to Passepartout/App/iOS/Flags.xcassets/aq.imageset/aq@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/aq.imageset/aq@3x.png b/Passepartout/App/iOS/Flags.xcassets/aq.imageset/aq@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/aq.imageset/aq@3x.png rename to Passepartout/App/iOS/Flags.xcassets/aq.imageset/aq@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ar.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ar.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ar.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ar.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ar.imageset/ar@2x.png b/Passepartout/App/iOS/Flags.xcassets/ar.imageset/ar@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ar.imageset/ar@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ar.imageset/ar@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ar.imageset/ar@3x.png b/Passepartout/App/iOS/Flags.xcassets/ar.imageset/ar@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ar.imageset/ar@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ar.imageset/ar@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/as.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/as.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/as.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/as.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/as.imageset/as@2x.png b/Passepartout/App/iOS/Flags.xcassets/as.imageset/as@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/as.imageset/as@2x.png rename to Passepartout/App/iOS/Flags.xcassets/as.imageset/as@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/as.imageset/as@3x.png b/Passepartout/App/iOS/Flags.xcassets/as.imageset/as@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/as.imageset/as@3x.png rename to Passepartout/App/iOS/Flags.xcassets/as.imageset/as@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/at.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/at.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/at.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/at.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/at.imageset/at@2x.png b/Passepartout/App/iOS/Flags.xcassets/at.imageset/at@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/at.imageset/at@2x.png rename to Passepartout/App/iOS/Flags.xcassets/at.imageset/at@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/at.imageset/at@3x.png b/Passepartout/App/iOS/Flags.xcassets/at.imageset/at@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/at.imageset/at@3x.png rename to Passepartout/App/iOS/Flags.xcassets/at.imageset/at@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/au.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/au.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/au.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/au.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/au.imageset/au@2x.png b/Passepartout/App/iOS/Flags.xcassets/au.imageset/au@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/au.imageset/au@2x.png rename to Passepartout/App/iOS/Flags.xcassets/au.imageset/au@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/au.imageset/au@3x.png b/Passepartout/App/iOS/Flags.xcassets/au.imageset/au@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/au.imageset/au@3x.png rename to Passepartout/App/iOS/Flags.xcassets/au.imageset/au@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/aw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/aw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/aw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/aw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/aw.imageset/aw@2x.png b/Passepartout/App/iOS/Flags.xcassets/aw.imageset/aw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/aw.imageset/aw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/aw.imageset/aw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/aw.imageset/aw@3x.png b/Passepartout/App/iOS/Flags.xcassets/aw.imageset/aw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/aw.imageset/aw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/aw.imageset/aw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ax.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ax.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ax.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ax.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ax.imageset/ax@2x.png b/Passepartout/App/iOS/Flags.xcassets/ax.imageset/ax@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ax.imageset/ax@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ax.imageset/ax@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ax.imageset/ax@3x.png b/Passepartout/App/iOS/Flags.xcassets/ax.imageset/ax@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ax.imageset/ax@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ax.imageset/ax@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/az.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/az.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/az.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/az.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/az.imageset/az@2x.png b/Passepartout/App/iOS/Flags.xcassets/az.imageset/az@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/az.imageset/az@2x.png rename to Passepartout/App/iOS/Flags.xcassets/az.imageset/az@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/az.imageset/az@3x.png b/Passepartout/App/iOS/Flags.xcassets/az.imageset/az@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/az.imageset/az@3x.png rename to Passepartout/App/iOS/Flags.xcassets/az.imageset/az@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ba.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ba.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ba.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ba.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ba.imageset/ba@2x.png b/Passepartout/App/iOS/Flags.xcassets/ba.imageset/ba@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ba.imageset/ba@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ba.imageset/ba@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ba.imageset/ba@3x.png b/Passepartout/App/iOS/Flags.xcassets/ba.imageset/ba@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ba.imageset/ba@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ba.imageset/ba@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bb.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bb.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bb.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bb.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bb.imageset/bb@2x.png b/Passepartout/App/iOS/Flags.xcassets/bb.imageset/bb@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bb.imageset/bb@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bb.imageset/bb@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bb.imageset/bb@3x.png b/Passepartout/App/iOS/Flags.xcassets/bb.imageset/bb@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bb.imageset/bb@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bb.imageset/bb@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bd.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bd.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bd.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bd.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bd.imageset/bd@2x.png b/Passepartout/App/iOS/Flags.xcassets/bd.imageset/bd@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bd.imageset/bd@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bd.imageset/bd@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bd.imageset/bd@3x.png b/Passepartout/App/iOS/Flags.xcassets/bd.imageset/bd@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bd.imageset/bd@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bd.imageset/bd@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/be.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/be.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/be.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/be.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/be.imageset/be@2x.png b/Passepartout/App/iOS/Flags.xcassets/be.imageset/be@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/be.imageset/be@2x.png rename to Passepartout/App/iOS/Flags.xcassets/be.imageset/be@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/be.imageset/be@3x.png b/Passepartout/App/iOS/Flags.xcassets/be.imageset/be@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/be.imageset/be@3x.png rename to Passepartout/App/iOS/Flags.xcassets/be.imageset/be@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bf.imageset/bf@2x.png b/Passepartout/App/iOS/Flags.xcassets/bf.imageset/bf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bf.imageset/bf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bf.imageset/bf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bf.imageset/bf@3x.png b/Passepartout/App/iOS/Flags.xcassets/bf.imageset/bf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bf.imageset/bf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bf.imageset/bf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bg.imageset/bg@2x.png b/Passepartout/App/iOS/Flags.xcassets/bg.imageset/bg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bg.imageset/bg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bg.imageset/bg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bg.imageset/bg@3x.png b/Passepartout/App/iOS/Flags.xcassets/bg.imageset/bg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bg.imageset/bg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bg.imageset/bg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bh.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bh.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bh.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bh.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bh.imageset/bh@2x.png b/Passepartout/App/iOS/Flags.xcassets/bh.imageset/bh@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bh.imageset/bh@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bh.imageset/bh@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bh.imageset/bh@3x.png b/Passepartout/App/iOS/Flags.xcassets/bh.imageset/bh@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bh.imageset/bh@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bh.imageset/bh@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bi.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bi.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bi.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bi.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bi.imageset/bi@2x.png b/Passepartout/App/iOS/Flags.xcassets/bi.imageset/bi@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bi.imageset/bi@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bi.imageset/bi@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bi.imageset/bi@3x.png b/Passepartout/App/iOS/Flags.xcassets/bi.imageset/bi@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bi.imageset/bi@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bi.imageset/bi@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bj.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bj.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bj.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bj.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bj.imageset/bj@2x.png b/Passepartout/App/iOS/Flags.xcassets/bj.imageset/bj@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bj.imageset/bj@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bj.imageset/bj@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bj.imageset/bj@3x.png b/Passepartout/App/iOS/Flags.xcassets/bj.imageset/bj@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bj.imageset/bj@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bj.imageset/bj@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bl.imageset/bl@2x.png b/Passepartout/App/iOS/Flags.xcassets/bl.imageset/bl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bl.imageset/bl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bl.imageset/bl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bl.imageset/bl@3x.png b/Passepartout/App/iOS/Flags.xcassets/bl.imageset/bl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bl.imageset/bl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bl.imageset/bl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bm.imageset/bm@2x.png b/Passepartout/App/iOS/Flags.xcassets/bm.imageset/bm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bm.imageset/bm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bm.imageset/bm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bm.imageset/bm@3x.png b/Passepartout/App/iOS/Flags.xcassets/bm.imageset/bm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bm.imageset/bm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bm.imageset/bm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bn.imageset/bn@2x.png b/Passepartout/App/iOS/Flags.xcassets/bn.imageset/bn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bn.imageset/bn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bn.imageset/bn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bn.imageset/bn@3x.png b/Passepartout/App/iOS/Flags.xcassets/bn.imageset/bn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bn.imageset/bn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bn.imageset/bn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bo.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bo.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bo.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bo.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bo.imageset/bo@2x.png b/Passepartout/App/iOS/Flags.xcassets/bo.imageset/bo@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bo.imageset/bo@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bo.imageset/bo@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bo.imageset/bo@3x.png b/Passepartout/App/iOS/Flags.xcassets/bo.imageset/bo@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bo.imageset/bo@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bo.imageset/bo@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bq.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bq.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bq.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bq.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bq.imageset/bq@2x.png b/Passepartout/App/iOS/Flags.xcassets/bq.imageset/bq@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bq.imageset/bq@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bq.imageset/bq@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bq.imageset/bq@3x.png b/Passepartout/App/iOS/Flags.xcassets/bq.imageset/bq@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bq.imageset/bq@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bq.imageset/bq@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/br.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/br.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/br.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/br.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/br.imageset/br@2x.png b/Passepartout/App/iOS/Flags.xcassets/br.imageset/br@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/br.imageset/br@2x.png rename to Passepartout/App/iOS/Flags.xcassets/br.imageset/br@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/br.imageset/br@3x.png b/Passepartout/App/iOS/Flags.xcassets/br.imageset/br@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/br.imageset/br@3x.png rename to Passepartout/App/iOS/Flags.xcassets/br.imageset/br@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bs.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bs.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bs.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bs.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bs.imageset/bs@2x.png b/Passepartout/App/iOS/Flags.xcassets/bs.imageset/bs@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bs.imageset/bs@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bs.imageset/bs@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bs.imageset/bs@3x.png b/Passepartout/App/iOS/Flags.xcassets/bs.imageset/bs@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bs.imageset/bs@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bs.imageset/bs@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bt.imageset/bt@2x.png b/Passepartout/App/iOS/Flags.xcassets/bt.imageset/bt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bt.imageset/bt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bt.imageset/bt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bt.imageset/bt@3x.png b/Passepartout/App/iOS/Flags.xcassets/bt.imageset/bt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bt.imageset/bt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bt.imageset/bt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bv.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bv.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bv.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bv.imageset/bv@2x.png b/Passepartout/App/iOS/Flags.xcassets/bv.imageset/bv@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bv.imageset/bv@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bv.imageset/bv@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bv.imageset/bv@3x.png b/Passepartout/App/iOS/Flags.xcassets/bv.imageset/bv@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bv.imageset/bv@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bv.imageset/bv@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bw.imageset/bw@2x.png b/Passepartout/App/iOS/Flags.xcassets/bw.imageset/bw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bw.imageset/bw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bw.imageset/bw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bw.imageset/bw@3x.png b/Passepartout/App/iOS/Flags.xcassets/bw.imageset/bw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bw.imageset/bw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bw.imageset/bw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/by.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/by.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/by.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/by.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/by.imageset/by@2x.png b/Passepartout/App/iOS/Flags.xcassets/by.imageset/by@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/by.imageset/by@2x.png rename to Passepartout/App/iOS/Flags.xcassets/by.imageset/by@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/by.imageset/by@3x.png b/Passepartout/App/iOS/Flags.xcassets/by.imageset/by@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/by.imageset/by@3x.png rename to Passepartout/App/iOS/Flags.xcassets/by.imageset/by@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/bz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/bz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/bz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/bz.imageset/bz@2x.png b/Passepartout/App/iOS/Flags.xcassets/bz.imageset/bz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bz.imageset/bz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/bz.imageset/bz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/bz.imageset/bz@3x.png b/Passepartout/App/iOS/Flags.xcassets/bz.imageset/bz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/bz.imageset/bz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/bz.imageset/bz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ca.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ca.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ca.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ca.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ca.imageset/ca@2x.png b/Passepartout/App/iOS/Flags.xcassets/ca.imageset/ca@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ca.imageset/ca@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ca.imageset/ca@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ca.imageset/ca@3x.png b/Passepartout/App/iOS/Flags.xcassets/ca.imageset/ca@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ca.imageset/ca@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ca.imageset/ca@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cc.imageset/cc@2x.png b/Passepartout/App/iOS/Flags.xcassets/cc.imageset/cc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cc.imageset/cc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cc.imageset/cc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cc.imageset/cc@3x.png b/Passepartout/App/iOS/Flags.xcassets/cc.imageset/cc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cc.imageset/cc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cc.imageset/cc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cd.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cd.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cd.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cd.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cd.imageset/cd@2x.png b/Passepartout/App/iOS/Flags.xcassets/cd.imageset/cd@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cd.imageset/cd@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cd.imageset/cd@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cd.imageset/cd@3x.png b/Passepartout/App/iOS/Flags.xcassets/cd.imageset/cd@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cd.imageset/cd@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cd.imageset/cd@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cf.imageset/cf@2x.png b/Passepartout/App/iOS/Flags.xcassets/cf.imageset/cf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cf.imageset/cf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cf.imageset/cf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cf.imageset/cf@3x.png b/Passepartout/App/iOS/Flags.xcassets/cf.imageset/cf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cf.imageset/cf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cf.imageset/cf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cg.imageset/cg@2x.png b/Passepartout/App/iOS/Flags.xcassets/cg.imageset/cg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cg.imageset/cg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cg.imageset/cg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cg.imageset/cg@3x.png b/Passepartout/App/iOS/Flags.xcassets/cg.imageset/cg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cg.imageset/cg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cg.imageset/cg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ch.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ch.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ch.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ch.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ch.imageset/ch@2x.png b/Passepartout/App/iOS/Flags.xcassets/ch.imageset/ch@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ch.imageset/ch@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ch.imageset/ch@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ch.imageset/ch@3x.png b/Passepartout/App/iOS/Flags.xcassets/ch.imageset/ch@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ch.imageset/ch@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ch.imageset/ch@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ci.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ci.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ci.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ci.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ci.imageset/ci@2x.png b/Passepartout/App/iOS/Flags.xcassets/ci.imageset/ci@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ci.imageset/ci@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ci.imageset/ci@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ci.imageset/ci@3x.png b/Passepartout/App/iOS/Flags.xcassets/ci.imageset/ci@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ci.imageset/ci@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ci.imageset/ci@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ck.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ck.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ck.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ck.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ck.imageset/ck@2x.png b/Passepartout/App/iOS/Flags.xcassets/ck.imageset/ck@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ck.imageset/ck@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ck.imageset/ck@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ck.imageset/ck@3x.png b/Passepartout/App/iOS/Flags.xcassets/ck.imageset/ck@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ck.imageset/ck@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ck.imageset/ck@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cl.imageset/cl@2x.png b/Passepartout/App/iOS/Flags.xcassets/cl.imageset/cl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cl.imageset/cl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cl.imageset/cl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cl.imageset/cl@3x.png b/Passepartout/App/iOS/Flags.xcassets/cl.imageset/cl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cl.imageset/cl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cl.imageset/cl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cm.imageset/cm@2x.png b/Passepartout/App/iOS/Flags.xcassets/cm.imageset/cm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cm.imageset/cm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cm.imageset/cm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cm.imageset/cm@3x.png b/Passepartout/App/iOS/Flags.xcassets/cm.imageset/cm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cm.imageset/cm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cm.imageset/cm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cn.imageset/cn@2x.png b/Passepartout/App/iOS/Flags.xcassets/cn.imageset/cn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cn.imageset/cn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cn.imageset/cn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cn.imageset/cn@3x.png b/Passepartout/App/iOS/Flags.xcassets/cn.imageset/cn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cn.imageset/cn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cn.imageset/cn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/co.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/co.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/co.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/co.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/co.imageset/co@2x.png b/Passepartout/App/iOS/Flags.xcassets/co.imageset/co@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/co.imageset/co@2x.png rename to Passepartout/App/iOS/Flags.xcassets/co.imageset/co@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/co.imageset/co@3x.png b/Passepartout/App/iOS/Flags.xcassets/co.imageset/co@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/co.imageset/co@3x.png rename to Passepartout/App/iOS/Flags.xcassets/co.imageset/co@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cr.imageset/cr@2x.png b/Passepartout/App/iOS/Flags.xcassets/cr.imageset/cr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cr.imageset/cr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cr.imageset/cr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cr.imageset/cr@3x.png b/Passepartout/App/iOS/Flags.xcassets/cr.imageset/cr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cr.imageset/cr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cr.imageset/cr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cu.imageset/cu@2x.png b/Passepartout/App/iOS/Flags.xcassets/cu.imageset/cu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cu.imageset/cu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cu.imageset/cu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cu.imageset/cu@3x.png b/Passepartout/App/iOS/Flags.xcassets/cu.imageset/cu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cu.imageset/cu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cu.imageset/cu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cv.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cv.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cv.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cv.imageset/cv@2x.png b/Passepartout/App/iOS/Flags.xcassets/cv.imageset/cv@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cv.imageset/cv@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cv.imageset/cv@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cv.imageset/cv@3x.png b/Passepartout/App/iOS/Flags.xcassets/cv.imageset/cv@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cv.imageset/cv@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cv.imageset/cv@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cw.imageset/cw@2x.png b/Passepartout/App/iOS/Flags.xcassets/cw.imageset/cw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cw.imageset/cw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cw.imageset/cw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cw.imageset/cw@3x.png b/Passepartout/App/iOS/Flags.xcassets/cw.imageset/cw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cw.imageset/cw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cw.imageset/cw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cx.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cx.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cx.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cx.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cx.imageset/cx@2x.png b/Passepartout/App/iOS/Flags.xcassets/cx.imageset/cx@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cx.imageset/cx@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cx.imageset/cx@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cx.imageset/cx@3x.png b/Passepartout/App/iOS/Flags.xcassets/cx.imageset/cx@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cx.imageset/cx@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cx.imageset/cx@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cy.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cy.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cy.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cy.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cy.imageset/cy@2x.png b/Passepartout/App/iOS/Flags.xcassets/cy.imageset/cy@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cy.imageset/cy@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cy.imageset/cy@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cy.imageset/cy@3x.png b/Passepartout/App/iOS/Flags.xcassets/cy.imageset/cy@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cy.imageset/cy@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cy.imageset/cy@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/cz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/cz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/cz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/cz.imageset/cz@2x.png b/Passepartout/App/iOS/Flags.xcassets/cz.imageset/cz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cz.imageset/cz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/cz.imageset/cz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/cz.imageset/cz@3x.png b/Passepartout/App/iOS/Flags.xcassets/cz.imageset/cz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/cz.imageset/cz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/cz.imageset/cz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/de.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/de.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/de.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/de.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/de.imageset/de@2x.png b/Passepartout/App/iOS/Flags.xcassets/de.imageset/de@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/de.imageset/de@2x.png rename to Passepartout/App/iOS/Flags.xcassets/de.imageset/de@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/de.imageset/de@3x.png b/Passepartout/App/iOS/Flags.xcassets/de.imageset/de@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/de.imageset/de@3x.png rename to Passepartout/App/iOS/Flags.xcassets/de.imageset/de@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/dj.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/dj.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dj.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/dj.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/dj.imageset/dj@2x.png b/Passepartout/App/iOS/Flags.xcassets/dj.imageset/dj@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dj.imageset/dj@2x.png rename to Passepartout/App/iOS/Flags.xcassets/dj.imageset/dj@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/dj.imageset/dj@3x.png b/Passepartout/App/iOS/Flags.xcassets/dj.imageset/dj@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dj.imageset/dj@3x.png rename to Passepartout/App/iOS/Flags.xcassets/dj.imageset/dj@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/dk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/dk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/dk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/dk.imageset/dk@2x.png b/Passepartout/App/iOS/Flags.xcassets/dk.imageset/dk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dk.imageset/dk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/dk.imageset/dk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/dk.imageset/dk@3x.png b/Passepartout/App/iOS/Flags.xcassets/dk.imageset/dk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dk.imageset/dk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/dk.imageset/dk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/dm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/dm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/dm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/dm.imageset/dm@2x.png b/Passepartout/App/iOS/Flags.xcassets/dm.imageset/dm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dm.imageset/dm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/dm.imageset/dm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/dm.imageset/dm@3x.png b/Passepartout/App/iOS/Flags.xcassets/dm.imageset/dm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dm.imageset/dm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/dm.imageset/dm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/do.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/do.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/do.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/do.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/do.imageset/do@2x.png b/Passepartout/App/iOS/Flags.xcassets/do.imageset/do@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/do.imageset/do@2x.png rename to Passepartout/App/iOS/Flags.xcassets/do.imageset/do@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/do.imageset/do@3x.png b/Passepartout/App/iOS/Flags.xcassets/do.imageset/do@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/do.imageset/do@3x.png rename to Passepartout/App/iOS/Flags.xcassets/do.imageset/do@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/dz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/dz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/dz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/dz.imageset/dz@2x.png b/Passepartout/App/iOS/Flags.xcassets/dz.imageset/dz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dz.imageset/dz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/dz.imageset/dz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/dz.imageset/dz@3x.png b/Passepartout/App/iOS/Flags.xcassets/dz.imageset/dz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/dz.imageset/dz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/dz.imageset/dz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ec.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ec.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ec.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ec.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ec.imageset/ec@2x.png b/Passepartout/App/iOS/Flags.xcassets/ec.imageset/ec@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ec.imageset/ec@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ec.imageset/ec@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ec.imageset/ec@3x.png b/Passepartout/App/iOS/Flags.xcassets/ec.imageset/ec@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ec.imageset/ec@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ec.imageset/ec@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ee.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ee.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ee.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ee.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ee.imageset/ee@2x.png b/Passepartout/App/iOS/Flags.xcassets/ee.imageset/ee@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ee.imageset/ee@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ee.imageset/ee@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ee.imageset/ee@3x.png b/Passepartout/App/iOS/Flags.xcassets/ee.imageset/ee@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ee.imageset/ee@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ee.imageset/ee@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/eg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/eg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/eg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/eg.imageset/eg@2x.png b/Passepartout/App/iOS/Flags.xcassets/eg.imageset/eg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eg.imageset/eg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/eg.imageset/eg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/eg.imageset/eg@3x.png b/Passepartout/App/iOS/Flags.xcassets/eg.imageset/eg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eg.imageset/eg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/eg.imageset/eg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/eh.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/eh.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eh.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/eh.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/eh.imageset/eh@2x.png b/Passepartout/App/iOS/Flags.xcassets/eh.imageset/eh@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eh.imageset/eh@2x.png rename to Passepartout/App/iOS/Flags.xcassets/eh.imageset/eh@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/eh.imageset/eh@3x.png b/Passepartout/App/iOS/Flags.xcassets/eh.imageset/eh@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eh.imageset/eh@3x.png rename to Passepartout/App/iOS/Flags.xcassets/eh.imageset/eh@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/er.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/er.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/er.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/er.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/er.imageset/er@2x.png b/Passepartout/App/iOS/Flags.xcassets/er.imageset/er@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/er.imageset/er@2x.png rename to Passepartout/App/iOS/Flags.xcassets/er.imageset/er@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/er.imageset/er@3x.png b/Passepartout/App/iOS/Flags.xcassets/er.imageset/er@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/er.imageset/er@3x.png rename to Passepartout/App/iOS/Flags.xcassets/er.imageset/er@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/es-ct.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/es-ct.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/es-ct.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/es-ct.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png b/Passepartout/App/iOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png rename to Passepartout/App/iOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png b/Passepartout/App/iOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png rename to Passepartout/App/iOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/es.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/es.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/es.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/es.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/es.imageset/es@2x.png b/Passepartout/App/iOS/Flags.xcassets/es.imageset/es@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/es.imageset/es@2x.png rename to Passepartout/App/iOS/Flags.xcassets/es.imageset/es@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/es.imageset/es@3x.png b/Passepartout/App/iOS/Flags.xcassets/es.imageset/es@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/es.imageset/es@3x.png rename to Passepartout/App/iOS/Flags.xcassets/es.imageset/es@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/et.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/et.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/et.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/et.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/et.imageset/et@2x.png b/Passepartout/App/iOS/Flags.xcassets/et.imageset/et@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/et.imageset/et@2x.png rename to Passepartout/App/iOS/Flags.xcassets/et.imageset/et@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/et.imageset/et@3x.png b/Passepartout/App/iOS/Flags.xcassets/et.imageset/et@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/et.imageset/et@3x.png rename to Passepartout/App/iOS/Flags.xcassets/et.imageset/et@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/eu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/eu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/eu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/eu.imageset/eu@2x.png b/Passepartout/App/iOS/Flags.xcassets/eu.imageset/eu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eu.imageset/eu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/eu.imageset/eu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/eu.imageset/eu@3x.png b/Passepartout/App/iOS/Flags.xcassets/eu.imageset/eu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/eu.imageset/eu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/eu.imageset/eu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/fi.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/fi.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fi.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/fi.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/fi.imageset/fi@2x.png b/Passepartout/App/iOS/Flags.xcassets/fi.imageset/fi@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fi.imageset/fi@2x.png rename to Passepartout/App/iOS/Flags.xcassets/fi.imageset/fi@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/fi.imageset/fi@3x.png b/Passepartout/App/iOS/Flags.xcassets/fi.imageset/fi@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fi.imageset/fi@3x.png rename to Passepartout/App/iOS/Flags.xcassets/fi.imageset/fi@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/fj.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/fj.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fj.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/fj.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/fj.imageset/fj@2x.png b/Passepartout/App/iOS/Flags.xcassets/fj.imageset/fj@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fj.imageset/fj@2x.png rename to Passepartout/App/iOS/Flags.xcassets/fj.imageset/fj@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/fj.imageset/fj@3x.png b/Passepartout/App/iOS/Flags.xcassets/fj.imageset/fj@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fj.imageset/fj@3x.png rename to Passepartout/App/iOS/Flags.xcassets/fj.imageset/fj@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/fk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/fk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/fk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/fk.imageset/fk@2x.png b/Passepartout/App/iOS/Flags.xcassets/fk.imageset/fk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fk.imageset/fk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/fk.imageset/fk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/fk.imageset/fk@3x.png b/Passepartout/App/iOS/Flags.xcassets/fk.imageset/fk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fk.imageset/fk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/fk.imageset/fk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/fm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/fm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/fm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/fm.imageset/fm@2x.png b/Passepartout/App/iOS/Flags.xcassets/fm.imageset/fm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fm.imageset/fm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/fm.imageset/fm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/fm.imageset/fm@3x.png b/Passepartout/App/iOS/Flags.xcassets/fm.imageset/fm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fm.imageset/fm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/fm.imageset/fm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/fo.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/fo.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fo.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/fo.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/fo.imageset/fo@2x.png b/Passepartout/App/iOS/Flags.xcassets/fo.imageset/fo@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fo.imageset/fo@2x.png rename to Passepartout/App/iOS/Flags.xcassets/fo.imageset/fo@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/fo.imageset/fo@3x.png b/Passepartout/App/iOS/Flags.xcassets/fo.imageset/fo@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fo.imageset/fo@3x.png rename to Passepartout/App/iOS/Flags.xcassets/fo.imageset/fo@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/fr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/fr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/fr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/fr.imageset/fr@2x.png b/Passepartout/App/iOS/Flags.xcassets/fr.imageset/fr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fr.imageset/fr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/fr.imageset/fr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/fr.imageset/fr@3x.png b/Passepartout/App/iOS/Flags.xcassets/fr.imageset/fr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/fr.imageset/fr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/fr.imageset/fr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ga.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ga.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ga.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ga.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ga.imageset/ga@2x.png b/Passepartout/App/iOS/Flags.xcassets/ga.imageset/ga@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ga.imageset/ga@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ga.imageset/ga@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ga.imageset/ga@3x.png b/Passepartout/App/iOS/Flags.xcassets/ga.imageset/ga@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ga.imageset/ga@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ga.imageset/ga@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-eng.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gb-eng.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-eng.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gb-eng.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png b/Passepartout/App/iOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png b/Passepartout/App/iOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-nir.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gb-nir.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-nir.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gb-nir.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png b/Passepartout/App/iOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png b/Passepartout/App/iOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-sct.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gb-sct.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-sct.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gb-sct.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png b/Passepartout/App/iOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png b/Passepartout/App/iOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-wls.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gb-wls.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-wls.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gb-wls.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png b/Passepartout/App/iOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png b/Passepartout/App/iOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gb.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gb.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gb.imageset/gb@2x.png b/Passepartout/App/iOS/Flags.xcassets/gb.imageset/gb@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb.imageset/gb@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gb.imageset/gb@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gb.imageset/gb@3x.png b/Passepartout/App/iOS/Flags.xcassets/gb.imageset/gb@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gb.imageset/gb@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gb.imageset/gb@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gd.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gd.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gd.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gd.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gd.imageset/gd@2x.png b/Passepartout/App/iOS/Flags.xcassets/gd.imageset/gd@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gd.imageset/gd@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gd.imageset/gd@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gd.imageset/gd@3x.png b/Passepartout/App/iOS/Flags.xcassets/gd.imageset/gd@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gd.imageset/gd@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gd.imageset/gd@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ge.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ge.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ge.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ge.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ge.imageset/ge@2x.png b/Passepartout/App/iOS/Flags.xcassets/ge.imageset/ge@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ge.imageset/ge@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ge.imageset/ge@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ge.imageset/ge@3x.png b/Passepartout/App/iOS/Flags.xcassets/ge.imageset/ge@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ge.imageset/ge@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ge.imageset/ge@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gf.imageset/gf@2x.png b/Passepartout/App/iOS/Flags.xcassets/gf.imageset/gf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gf.imageset/gf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gf.imageset/gf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gf.imageset/gf@3x.png b/Passepartout/App/iOS/Flags.xcassets/gf.imageset/gf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gf.imageset/gf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gf.imageset/gf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gg.imageset/gg@2x.png b/Passepartout/App/iOS/Flags.xcassets/gg.imageset/gg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gg.imageset/gg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gg.imageset/gg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gg.imageset/gg@3x.png b/Passepartout/App/iOS/Flags.xcassets/gg.imageset/gg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gg.imageset/gg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gg.imageset/gg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gh.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gh.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gh.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gh.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gh.imageset/gh@2x.png b/Passepartout/App/iOS/Flags.xcassets/gh.imageset/gh@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gh.imageset/gh@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gh.imageset/gh@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gh.imageset/gh@3x.png b/Passepartout/App/iOS/Flags.xcassets/gh.imageset/gh@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gh.imageset/gh@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gh.imageset/gh@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gi.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gi.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gi.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gi.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gi.imageset/gi@2x.png b/Passepartout/App/iOS/Flags.xcassets/gi.imageset/gi@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gi.imageset/gi@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gi.imageset/gi@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gi.imageset/gi@3x.png b/Passepartout/App/iOS/Flags.xcassets/gi.imageset/gi@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gi.imageset/gi@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gi.imageset/gi@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gl.imageset/gl@2x.png b/Passepartout/App/iOS/Flags.xcassets/gl.imageset/gl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gl.imageset/gl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gl.imageset/gl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gl.imageset/gl@3x.png b/Passepartout/App/iOS/Flags.xcassets/gl.imageset/gl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gl.imageset/gl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gl.imageset/gl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gm.imageset/gm@2x.png b/Passepartout/App/iOS/Flags.xcassets/gm.imageset/gm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gm.imageset/gm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gm.imageset/gm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gm.imageset/gm@3x.png b/Passepartout/App/iOS/Flags.xcassets/gm.imageset/gm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gm.imageset/gm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gm.imageset/gm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gn.imageset/gn@2x.png b/Passepartout/App/iOS/Flags.xcassets/gn.imageset/gn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gn.imageset/gn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gn.imageset/gn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gn.imageset/gn@3x.png b/Passepartout/App/iOS/Flags.xcassets/gn.imageset/gn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gn.imageset/gn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gn.imageset/gn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gp.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gp.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gp.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gp.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gp.imageset/gp@2x.png b/Passepartout/App/iOS/Flags.xcassets/gp.imageset/gp@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gp.imageset/gp@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gp.imageset/gp@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gp.imageset/gp@3x.png b/Passepartout/App/iOS/Flags.xcassets/gp.imageset/gp@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gp.imageset/gp@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gp.imageset/gp@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gq.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gq.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gq.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gq.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gq.imageset/gq@2x.png b/Passepartout/App/iOS/Flags.xcassets/gq.imageset/gq@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gq.imageset/gq@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gq.imageset/gq@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gq.imageset/gq@3x.png b/Passepartout/App/iOS/Flags.xcassets/gq.imageset/gq@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gq.imageset/gq@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gq.imageset/gq@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gr.imageset/gr@2x.png b/Passepartout/App/iOS/Flags.xcassets/gr.imageset/gr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gr.imageset/gr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gr.imageset/gr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gr.imageset/gr@3x.png b/Passepartout/App/iOS/Flags.xcassets/gr.imageset/gr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gr.imageset/gr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gr.imageset/gr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gs.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gs.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gs.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gs.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gs.imageset/gs@2x.png b/Passepartout/App/iOS/Flags.xcassets/gs.imageset/gs@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gs.imageset/gs@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gs.imageset/gs@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gs.imageset/gs@3x.png b/Passepartout/App/iOS/Flags.xcassets/gs.imageset/gs@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gs.imageset/gs@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gs.imageset/gs@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gt.imageset/gt@2x.png b/Passepartout/App/iOS/Flags.xcassets/gt.imageset/gt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gt.imageset/gt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gt.imageset/gt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gt.imageset/gt@3x.png b/Passepartout/App/iOS/Flags.xcassets/gt.imageset/gt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gt.imageset/gt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gt.imageset/gt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gu.imageset/gu@2x.png b/Passepartout/App/iOS/Flags.xcassets/gu.imageset/gu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gu.imageset/gu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gu.imageset/gu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gu.imageset/gu@3x.png b/Passepartout/App/iOS/Flags.xcassets/gu.imageset/gu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gu.imageset/gu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gu.imageset/gu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gw.imageset/gw@2x.png b/Passepartout/App/iOS/Flags.xcassets/gw.imageset/gw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gw.imageset/gw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gw.imageset/gw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gw.imageset/gw@3x.png b/Passepartout/App/iOS/Flags.xcassets/gw.imageset/gw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gw.imageset/gw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gw.imageset/gw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/gy.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/gy.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gy.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/gy.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/gy.imageset/gy@2x.png b/Passepartout/App/iOS/Flags.xcassets/gy.imageset/gy@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gy.imageset/gy@2x.png rename to Passepartout/App/iOS/Flags.xcassets/gy.imageset/gy@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/gy.imageset/gy@3x.png b/Passepartout/App/iOS/Flags.xcassets/gy.imageset/gy@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/gy.imageset/gy@3x.png rename to Passepartout/App/iOS/Flags.xcassets/gy.imageset/gy@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/hk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/hk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/hk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/hk.imageset/hk@2x.png b/Passepartout/App/iOS/Flags.xcassets/hk.imageset/hk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hk.imageset/hk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/hk.imageset/hk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/hk.imageset/hk@3x.png b/Passepartout/App/iOS/Flags.xcassets/hk.imageset/hk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hk.imageset/hk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/hk.imageset/hk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/hm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/hm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/hm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/hm.imageset/hm@2x.png b/Passepartout/App/iOS/Flags.xcassets/hm.imageset/hm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hm.imageset/hm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/hm.imageset/hm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/hm.imageset/hm@3x.png b/Passepartout/App/iOS/Flags.xcassets/hm.imageset/hm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hm.imageset/hm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/hm.imageset/hm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/hn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/hn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/hn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/hn.imageset/hn@2x.png b/Passepartout/App/iOS/Flags.xcassets/hn.imageset/hn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hn.imageset/hn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/hn.imageset/hn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/hn.imageset/hn@3x.png b/Passepartout/App/iOS/Flags.xcassets/hn.imageset/hn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hn.imageset/hn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/hn.imageset/hn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/hr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/hr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/hr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/hr.imageset/hr@2x.png b/Passepartout/App/iOS/Flags.xcassets/hr.imageset/hr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hr.imageset/hr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/hr.imageset/hr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/hr.imageset/hr@3x.png b/Passepartout/App/iOS/Flags.xcassets/hr.imageset/hr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hr.imageset/hr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/hr.imageset/hr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ht.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ht.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ht.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ht.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ht.imageset/ht@2x.png b/Passepartout/App/iOS/Flags.xcassets/ht.imageset/ht@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ht.imageset/ht@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ht.imageset/ht@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ht.imageset/ht@3x.png b/Passepartout/App/iOS/Flags.xcassets/ht.imageset/ht@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ht.imageset/ht@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ht.imageset/ht@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/hu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/hu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/hu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/hu.imageset/hu@2x.png b/Passepartout/App/iOS/Flags.xcassets/hu.imageset/hu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hu.imageset/hu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/hu.imageset/hu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/hu.imageset/hu@3x.png b/Passepartout/App/iOS/Flags.xcassets/hu.imageset/hu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/hu.imageset/hu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/hu.imageset/hu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/id.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/id.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/id.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/id.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/id.imageset/id@2x.png b/Passepartout/App/iOS/Flags.xcassets/id.imageset/id@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/id.imageset/id@2x.png rename to Passepartout/App/iOS/Flags.xcassets/id.imageset/id@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/id.imageset/id@3x.png b/Passepartout/App/iOS/Flags.xcassets/id.imageset/id@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/id.imageset/id@3x.png rename to Passepartout/App/iOS/Flags.xcassets/id.imageset/id@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ie.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ie.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ie.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ie.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ie.imageset/ie@2x.png b/Passepartout/App/iOS/Flags.xcassets/ie.imageset/ie@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ie.imageset/ie@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ie.imageset/ie@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ie.imageset/ie@3x.png b/Passepartout/App/iOS/Flags.xcassets/ie.imageset/ie@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ie.imageset/ie@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ie.imageset/ie@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/il.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/il.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/il.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/il.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/il.imageset/il@2x.png b/Passepartout/App/iOS/Flags.xcassets/il.imageset/il@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/il.imageset/il@2x.png rename to Passepartout/App/iOS/Flags.xcassets/il.imageset/il@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/il.imageset/il@3x.png b/Passepartout/App/iOS/Flags.xcassets/il.imageset/il@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/il.imageset/il@3x.png rename to Passepartout/App/iOS/Flags.xcassets/il.imageset/il@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/im.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/im.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/im.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/im.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/im.imageset/im@2x.png b/Passepartout/App/iOS/Flags.xcassets/im.imageset/im@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/im.imageset/im@2x.png rename to Passepartout/App/iOS/Flags.xcassets/im.imageset/im@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/im.imageset/im@3x.png b/Passepartout/App/iOS/Flags.xcassets/im.imageset/im@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/im.imageset/im@3x.png rename to Passepartout/App/iOS/Flags.xcassets/im.imageset/im@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/in.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/in.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/in.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/in.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/in.imageset/in@2x.png b/Passepartout/App/iOS/Flags.xcassets/in.imageset/in@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/in.imageset/in@2x.png rename to Passepartout/App/iOS/Flags.xcassets/in.imageset/in@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/in.imageset/in@3x.png b/Passepartout/App/iOS/Flags.xcassets/in.imageset/in@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/in.imageset/in@3x.png rename to Passepartout/App/iOS/Flags.xcassets/in.imageset/in@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/io.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/io.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/io.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/io.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/io.imageset/io@2x.png b/Passepartout/App/iOS/Flags.xcassets/io.imageset/io@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/io.imageset/io@2x.png rename to Passepartout/App/iOS/Flags.xcassets/io.imageset/io@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/io.imageset/io@3x.png b/Passepartout/App/iOS/Flags.xcassets/io.imageset/io@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/io.imageset/io@3x.png rename to Passepartout/App/iOS/Flags.xcassets/io.imageset/io@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/iq.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/iq.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/iq.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/iq.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/iq.imageset/iq@2x.png b/Passepartout/App/iOS/Flags.xcassets/iq.imageset/iq@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/iq.imageset/iq@2x.png rename to Passepartout/App/iOS/Flags.xcassets/iq.imageset/iq@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/iq.imageset/iq@3x.png b/Passepartout/App/iOS/Flags.xcassets/iq.imageset/iq@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/iq.imageset/iq@3x.png rename to Passepartout/App/iOS/Flags.xcassets/iq.imageset/iq@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ir.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ir.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ir.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ir.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ir.imageset/ir@2x.png b/Passepartout/App/iOS/Flags.xcassets/ir.imageset/ir@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ir.imageset/ir@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ir.imageset/ir@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ir.imageset/ir@3x.png b/Passepartout/App/iOS/Flags.xcassets/ir.imageset/ir@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ir.imageset/ir@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ir.imageset/ir@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/is.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/is.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/is.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/is.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/is.imageset/is@2x.png b/Passepartout/App/iOS/Flags.xcassets/is.imageset/is@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/is.imageset/is@2x.png rename to Passepartout/App/iOS/Flags.xcassets/is.imageset/is@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/is.imageset/is@3x.png b/Passepartout/App/iOS/Flags.xcassets/is.imageset/is@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/is.imageset/is@3x.png rename to Passepartout/App/iOS/Flags.xcassets/is.imageset/is@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/it.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/it.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/it.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/it.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/it.imageset/it@2x.png b/Passepartout/App/iOS/Flags.xcassets/it.imageset/it@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/it.imageset/it@2x.png rename to Passepartout/App/iOS/Flags.xcassets/it.imageset/it@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/it.imageset/it@3x.png b/Passepartout/App/iOS/Flags.xcassets/it.imageset/it@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/it.imageset/it@3x.png rename to Passepartout/App/iOS/Flags.xcassets/it.imageset/it@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/je.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/je.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/je.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/je.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/je.imageset/je@2x.png b/Passepartout/App/iOS/Flags.xcassets/je.imageset/je@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/je.imageset/je@2x.png rename to Passepartout/App/iOS/Flags.xcassets/je.imageset/je@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/je.imageset/je@3x.png b/Passepartout/App/iOS/Flags.xcassets/je.imageset/je@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/je.imageset/je@3x.png rename to Passepartout/App/iOS/Flags.xcassets/je.imageset/je@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/jm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/jm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/jm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/jm.imageset/jm@2x.png b/Passepartout/App/iOS/Flags.xcassets/jm.imageset/jm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jm.imageset/jm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/jm.imageset/jm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/jm.imageset/jm@3x.png b/Passepartout/App/iOS/Flags.xcassets/jm.imageset/jm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jm.imageset/jm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/jm.imageset/jm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/jo.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/jo.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jo.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/jo.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/jo.imageset/jo@2x.png b/Passepartout/App/iOS/Flags.xcassets/jo.imageset/jo@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jo.imageset/jo@2x.png rename to Passepartout/App/iOS/Flags.xcassets/jo.imageset/jo@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/jo.imageset/jo@3x.png b/Passepartout/App/iOS/Flags.xcassets/jo.imageset/jo@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jo.imageset/jo@3x.png rename to Passepartout/App/iOS/Flags.xcassets/jo.imageset/jo@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/jp.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/jp.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jp.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/jp.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/jp.imageset/jp@2x.png b/Passepartout/App/iOS/Flags.xcassets/jp.imageset/jp@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jp.imageset/jp@2x.png rename to Passepartout/App/iOS/Flags.xcassets/jp.imageset/jp@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/jp.imageset/jp@3x.png b/Passepartout/App/iOS/Flags.xcassets/jp.imageset/jp@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/jp.imageset/jp@3x.png rename to Passepartout/App/iOS/Flags.xcassets/jp.imageset/jp@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ke.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ke.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ke.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ke.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ke.imageset/ke@2x.png b/Passepartout/App/iOS/Flags.xcassets/ke.imageset/ke@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ke.imageset/ke@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ke.imageset/ke@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ke.imageset/ke@3x.png b/Passepartout/App/iOS/Flags.xcassets/ke.imageset/ke@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ke.imageset/ke@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ke.imageset/ke@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kg.imageset/kg@2x.png b/Passepartout/App/iOS/Flags.xcassets/kg.imageset/kg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kg.imageset/kg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kg.imageset/kg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kg.imageset/kg@3x.png b/Passepartout/App/iOS/Flags.xcassets/kg.imageset/kg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kg.imageset/kg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kg.imageset/kg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kh.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kh.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kh.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kh.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kh.imageset/kh@2x.png b/Passepartout/App/iOS/Flags.xcassets/kh.imageset/kh@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kh.imageset/kh@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kh.imageset/kh@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kh.imageset/kh@3x.png b/Passepartout/App/iOS/Flags.xcassets/kh.imageset/kh@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kh.imageset/kh@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kh.imageset/kh@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ki.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ki.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ki.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ki.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ki.imageset/ki@2x.png b/Passepartout/App/iOS/Flags.xcassets/ki.imageset/ki@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ki.imageset/ki@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ki.imageset/ki@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ki.imageset/ki@3x.png b/Passepartout/App/iOS/Flags.xcassets/ki.imageset/ki@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ki.imageset/ki@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ki.imageset/ki@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/km.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/km.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/km.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/km.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/km.imageset/km@2x.png b/Passepartout/App/iOS/Flags.xcassets/km.imageset/km@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/km.imageset/km@2x.png rename to Passepartout/App/iOS/Flags.xcassets/km.imageset/km@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/km.imageset/km@3x.png b/Passepartout/App/iOS/Flags.xcassets/km.imageset/km@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/km.imageset/km@3x.png rename to Passepartout/App/iOS/Flags.xcassets/km.imageset/km@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kn.imageset/kn@2x.png b/Passepartout/App/iOS/Flags.xcassets/kn.imageset/kn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kn.imageset/kn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kn.imageset/kn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kn.imageset/kn@3x.png b/Passepartout/App/iOS/Flags.xcassets/kn.imageset/kn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kn.imageset/kn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kn.imageset/kn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kp.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kp.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kp.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kp.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kp.imageset/kp@2x.png b/Passepartout/App/iOS/Flags.xcassets/kp.imageset/kp@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kp.imageset/kp@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kp.imageset/kp@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kp.imageset/kp@3x.png b/Passepartout/App/iOS/Flags.xcassets/kp.imageset/kp@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kp.imageset/kp@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kp.imageset/kp@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kr.imageset/kr@2x.png b/Passepartout/App/iOS/Flags.xcassets/kr.imageset/kr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kr.imageset/kr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kr.imageset/kr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kr.imageset/kr@3x.png b/Passepartout/App/iOS/Flags.xcassets/kr.imageset/kr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kr.imageset/kr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kr.imageset/kr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kw.imageset/kw@2x.png b/Passepartout/App/iOS/Flags.xcassets/kw.imageset/kw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kw.imageset/kw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kw.imageset/kw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kw.imageset/kw@3x.png b/Passepartout/App/iOS/Flags.xcassets/kw.imageset/kw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kw.imageset/kw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kw.imageset/kw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ky.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ky.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ky.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ky.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ky.imageset/ky@2x.png b/Passepartout/App/iOS/Flags.xcassets/ky.imageset/ky@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ky.imageset/ky@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ky.imageset/ky@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ky.imageset/ky@3x.png b/Passepartout/App/iOS/Flags.xcassets/ky.imageset/ky@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ky.imageset/ky@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ky.imageset/ky@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/kz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/kz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/kz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/kz.imageset/kz@2x.png b/Passepartout/App/iOS/Flags.xcassets/kz.imageset/kz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kz.imageset/kz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/kz.imageset/kz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/kz.imageset/kz@3x.png b/Passepartout/App/iOS/Flags.xcassets/kz.imageset/kz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/kz.imageset/kz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/kz.imageset/kz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/la.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/la.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/la.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/la.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/la.imageset/la@2x.png b/Passepartout/App/iOS/Flags.xcassets/la.imageset/la@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/la.imageset/la@2x.png rename to Passepartout/App/iOS/Flags.xcassets/la.imageset/la@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/la.imageset/la@3x.png b/Passepartout/App/iOS/Flags.xcassets/la.imageset/la@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/la.imageset/la@3x.png rename to Passepartout/App/iOS/Flags.xcassets/la.imageset/la@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lb.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lb.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lb.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lb.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lb.imageset/lb@2x.png b/Passepartout/App/iOS/Flags.xcassets/lb.imageset/lb@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lb.imageset/lb@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lb.imageset/lb@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lb.imageset/lb@3x.png b/Passepartout/App/iOS/Flags.xcassets/lb.imageset/lb@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lb.imageset/lb@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lb.imageset/lb@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lc.imageset/lc@2x.png b/Passepartout/App/iOS/Flags.xcassets/lc.imageset/lc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lc.imageset/lc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lc.imageset/lc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lc.imageset/lc@3x.png b/Passepartout/App/iOS/Flags.xcassets/lc.imageset/lc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lc.imageset/lc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lc.imageset/lc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/li.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/li.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/li.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/li.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/li.imageset/li@2x.png b/Passepartout/App/iOS/Flags.xcassets/li.imageset/li@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/li.imageset/li@2x.png rename to Passepartout/App/iOS/Flags.xcassets/li.imageset/li@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/li.imageset/li@3x.png b/Passepartout/App/iOS/Flags.xcassets/li.imageset/li@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/li.imageset/li@3x.png rename to Passepartout/App/iOS/Flags.xcassets/li.imageset/li@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lk.imageset/lk@2x.png b/Passepartout/App/iOS/Flags.xcassets/lk.imageset/lk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lk.imageset/lk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lk.imageset/lk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lk.imageset/lk@3x.png b/Passepartout/App/iOS/Flags.xcassets/lk.imageset/lk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lk.imageset/lk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lk.imageset/lk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lr.imageset/lr@2x.png b/Passepartout/App/iOS/Flags.xcassets/lr.imageset/lr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lr.imageset/lr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lr.imageset/lr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lr.imageset/lr@3x.png b/Passepartout/App/iOS/Flags.xcassets/lr.imageset/lr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lr.imageset/lr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lr.imageset/lr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ls.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ls.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ls.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ls.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ls.imageset/ls@2x.png b/Passepartout/App/iOS/Flags.xcassets/ls.imageset/ls@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ls.imageset/ls@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ls.imageset/ls@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ls.imageset/ls@3x.png b/Passepartout/App/iOS/Flags.xcassets/ls.imageset/ls@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ls.imageset/ls@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ls.imageset/ls@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lt.imageset/lt@2x.png b/Passepartout/App/iOS/Flags.xcassets/lt.imageset/lt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lt.imageset/lt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lt.imageset/lt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lt.imageset/lt@3x.png b/Passepartout/App/iOS/Flags.xcassets/lt.imageset/lt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lt.imageset/lt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lt.imageset/lt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lu.imageset/lu@2x.png b/Passepartout/App/iOS/Flags.xcassets/lu.imageset/lu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lu.imageset/lu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lu.imageset/lu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lu.imageset/lu@3x.png b/Passepartout/App/iOS/Flags.xcassets/lu.imageset/lu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lu.imageset/lu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lu.imageset/lu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/lv.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/lv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lv.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/lv.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/lv.imageset/lv@2x.png b/Passepartout/App/iOS/Flags.xcassets/lv.imageset/lv@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lv.imageset/lv@2x.png rename to Passepartout/App/iOS/Flags.xcassets/lv.imageset/lv@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/lv.imageset/lv@3x.png b/Passepartout/App/iOS/Flags.xcassets/lv.imageset/lv@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/lv.imageset/lv@3x.png rename to Passepartout/App/iOS/Flags.xcassets/lv.imageset/lv@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ly.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ly.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ly.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ly.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ly.imageset/ly@2x.png b/Passepartout/App/iOS/Flags.xcassets/ly.imageset/ly@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ly.imageset/ly@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ly.imageset/ly@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ly.imageset/ly@3x.png b/Passepartout/App/iOS/Flags.xcassets/ly.imageset/ly@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ly.imageset/ly@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ly.imageset/ly@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ma.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ma.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ma.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ma.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ma.imageset/ma@2x.png b/Passepartout/App/iOS/Flags.xcassets/ma.imageset/ma@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ma.imageset/ma@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ma.imageset/ma@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ma.imageset/ma@3x.png b/Passepartout/App/iOS/Flags.xcassets/ma.imageset/ma@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ma.imageset/ma@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ma.imageset/ma@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mc.imageset/mc@2x.png b/Passepartout/App/iOS/Flags.xcassets/mc.imageset/mc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mc.imageset/mc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mc.imageset/mc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mc.imageset/mc@3x.png b/Passepartout/App/iOS/Flags.xcassets/mc.imageset/mc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mc.imageset/mc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mc.imageset/mc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/md.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/md.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/md.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/md.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/md.imageset/md@2x.png b/Passepartout/App/iOS/Flags.xcassets/md.imageset/md@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/md.imageset/md@2x.png rename to Passepartout/App/iOS/Flags.xcassets/md.imageset/md@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/md.imageset/md@3x.png b/Passepartout/App/iOS/Flags.xcassets/md.imageset/md@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/md.imageset/md@3x.png rename to Passepartout/App/iOS/Flags.xcassets/md.imageset/md@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/me.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/me.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/me.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/me.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/me.imageset/me@2x.png b/Passepartout/App/iOS/Flags.xcassets/me.imageset/me@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/me.imageset/me@2x.png rename to Passepartout/App/iOS/Flags.xcassets/me.imageset/me@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/me.imageset/me@3x.png b/Passepartout/App/iOS/Flags.xcassets/me.imageset/me@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/me.imageset/me@3x.png rename to Passepartout/App/iOS/Flags.xcassets/me.imageset/me@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mf.imageset/mf@2x.png b/Passepartout/App/iOS/Flags.xcassets/mf.imageset/mf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mf.imageset/mf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mf.imageset/mf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mf.imageset/mf@3x.png b/Passepartout/App/iOS/Flags.xcassets/mf.imageset/mf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mf.imageset/mf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mf.imageset/mf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mg.imageset/mg@2x.png b/Passepartout/App/iOS/Flags.xcassets/mg.imageset/mg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mg.imageset/mg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mg.imageset/mg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mg.imageset/mg@3x.png b/Passepartout/App/iOS/Flags.xcassets/mg.imageset/mg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mg.imageset/mg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mg.imageset/mg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mh.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mh.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mh.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mh.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mh.imageset/mh@2x.png b/Passepartout/App/iOS/Flags.xcassets/mh.imageset/mh@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mh.imageset/mh@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mh.imageset/mh@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mh.imageset/mh@3x.png b/Passepartout/App/iOS/Flags.xcassets/mh.imageset/mh@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mh.imageset/mh@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mh.imageset/mh@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mk.imageset/mk@2x.png b/Passepartout/App/iOS/Flags.xcassets/mk.imageset/mk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mk.imageset/mk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mk.imageset/mk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mk.imageset/mk@3x.png b/Passepartout/App/iOS/Flags.xcassets/mk.imageset/mk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mk.imageset/mk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mk.imageset/mk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ml.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ml.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ml.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ml.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ml.imageset/ml@2x.png b/Passepartout/App/iOS/Flags.xcassets/ml.imageset/ml@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ml.imageset/ml@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ml.imageset/ml@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ml.imageset/ml@3x.png b/Passepartout/App/iOS/Flags.xcassets/ml.imageset/ml@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ml.imageset/ml@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ml.imageset/ml@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mm.imageset/mm@2x.png b/Passepartout/App/iOS/Flags.xcassets/mm.imageset/mm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mm.imageset/mm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mm.imageset/mm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mm.imageset/mm@3x.png b/Passepartout/App/iOS/Flags.xcassets/mm.imageset/mm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mm.imageset/mm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mm.imageset/mm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mn.imageset/mn@2x.png b/Passepartout/App/iOS/Flags.xcassets/mn.imageset/mn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mn.imageset/mn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mn.imageset/mn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mn.imageset/mn@3x.png b/Passepartout/App/iOS/Flags.xcassets/mn.imageset/mn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mn.imageset/mn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mn.imageset/mn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mo.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mo.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mo.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mo.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mo.imageset/mo@2x.png b/Passepartout/App/iOS/Flags.xcassets/mo.imageset/mo@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mo.imageset/mo@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mo.imageset/mo@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mo.imageset/mo@3x.png b/Passepartout/App/iOS/Flags.xcassets/mo.imageset/mo@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mo.imageset/mo@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mo.imageset/mo@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mp.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mp.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mp.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mp.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mp.imageset/mp@2x.png b/Passepartout/App/iOS/Flags.xcassets/mp.imageset/mp@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mp.imageset/mp@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mp.imageset/mp@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mp.imageset/mp@3x.png b/Passepartout/App/iOS/Flags.xcassets/mp.imageset/mp@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mp.imageset/mp@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mp.imageset/mp@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mq.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mq.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mq.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mq.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mq.imageset/mq@2x.png b/Passepartout/App/iOS/Flags.xcassets/mq.imageset/mq@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mq.imageset/mq@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mq.imageset/mq@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mq.imageset/mq@3x.png b/Passepartout/App/iOS/Flags.xcassets/mq.imageset/mq@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mq.imageset/mq@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mq.imageset/mq@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mr.imageset/mr@2x.png b/Passepartout/App/iOS/Flags.xcassets/mr.imageset/mr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mr.imageset/mr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mr.imageset/mr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mr.imageset/mr@3x.png b/Passepartout/App/iOS/Flags.xcassets/mr.imageset/mr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mr.imageset/mr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mr.imageset/mr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ms.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ms.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ms.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ms.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ms.imageset/ms@2x.png b/Passepartout/App/iOS/Flags.xcassets/ms.imageset/ms@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ms.imageset/ms@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ms.imageset/ms@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ms.imageset/ms@3x.png b/Passepartout/App/iOS/Flags.xcassets/ms.imageset/ms@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ms.imageset/ms@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ms.imageset/ms@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mt.imageset/mt@2x.png b/Passepartout/App/iOS/Flags.xcassets/mt.imageset/mt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mt.imageset/mt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mt.imageset/mt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mt.imageset/mt@3x.png b/Passepartout/App/iOS/Flags.xcassets/mt.imageset/mt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mt.imageset/mt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mt.imageset/mt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mu.imageset/mu@2x.png b/Passepartout/App/iOS/Flags.xcassets/mu.imageset/mu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mu.imageset/mu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mu.imageset/mu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mu.imageset/mu@3x.png b/Passepartout/App/iOS/Flags.xcassets/mu.imageset/mu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mu.imageset/mu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mu.imageset/mu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mv.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mv.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mv.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mv.imageset/mv@2x.png b/Passepartout/App/iOS/Flags.xcassets/mv.imageset/mv@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mv.imageset/mv@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mv.imageset/mv@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mv.imageset/mv@3x.png b/Passepartout/App/iOS/Flags.xcassets/mv.imageset/mv@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mv.imageset/mv@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mv.imageset/mv@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mw.imageset/mw@2x.png b/Passepartout/App/iOS/Flags.xcassets/mw.imageset/mw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mw.imageset/mw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mw.imageset/mw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mw.imageset/mw@3x.png b/Passepartout/App/iOS/Flags.xcassets/mw.imageset/mw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mw.imageset/mw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mw.imageset/mw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mx.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mx.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mx.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mx.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mx.imageset/mx@2x.png b/Passepartout/App/iOS/Flags.xcassets/mx.imageset/mx@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mx.imageset/mx@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mx.imageset/mx@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mx.imageset/mx@3x.png b/Passepartout/App/iOS/Flags.xcassets/mx.imageset/mx@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mx.imageset/mx@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mx.imageset/mx@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/my.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/my.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/my.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/my.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/my.imageset/my@2x.png b/Passepartout/App/iOS/Flags.xcassets/my.imageset/my@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/my.imageset/my@2x.png rename to Passepartout/App/iOS/Flags.xcassets/my.imageset/my@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/my.imageset/my@3x.png b/Passepartout/App/iOS/Flags.xcassets/my.imageset/my@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/my.imageset/my@3x.png rename to Passepartout/App/iOS/Flags.xcassets/my.imageset/my@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/mz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/mz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/mz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/mz.imageset/mz@2x.png b/Passepartout/App/iOS/Flags.xcassets/mz.imageset/mz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mz.imageset/mz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/mz.imageset/mz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/mz.imageset/mz@3x.png b/Passepartout/App/iOS/Flags.xcassets/mz.imageset/mz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/mz.imageset/mz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/mz.imageset/mz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/na.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/na.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/na.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/na.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/na.imageset/na@2x.png b/Passepartout/App/iOS/Flags.xcassets/na.imageset/na@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/na.imageset/na@2x.png rename to Passepartout/App/iOS/Flags.xcassets/na.imageset/na@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/na.imageset/na@3x.png b/Passepartout/App/iOS/Flags.xcassets/na.imageset/na@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/na.imageset/na@3x.png rename to Passepartout/App/iOS/Flags.xcassets/na.imageset/na@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/nc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/nc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/nc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/nc.imageset/nc@2x.png b/Passepartout/App/iOS/Flags.xcassets/nc.imageset/nc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nc.imageset/nc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/nc.imageset/nc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/nc.imageset/nc@3x.png b/Passepartout/App/iOS/Flags.xcassets/nc.imageset/nc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nc.imageset/nc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/nc.imageset/nc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ne.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ne.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ne.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ne.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ne.imageset/ne@2x.png b/Passepartout/App/iOS/Flags.xcassets/ne.imageset/ne@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ne.imageset/ne@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ne.imageset/ne@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ne.imageset/ne@3x.png b/Passepartout/App/iOS/Flags.xcassets/ne.imageset/ne@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ne.imageset/ne@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ne.imageset/ne@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/nf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/nf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/nf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/nf.imageset/nf@2x.png b/Passepartout/App/iOS/Flags.xcassets/nf.imageset/nf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nf.imageset/nf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/nf.imageset/nf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/nf.imageset/nf@3x.png b/Passepartout/App/iOS/Flags.xcassets/nf.imageset/nf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nf.imageset/nf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/nf.imageset/nf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ng.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ng.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ng.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ng.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ng.imageset/ng@2x.png b/Passepartout/App/iOS/Flags.xcassets/ng.imageset/ng@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ng.imageset/ng@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ng.imageset/ng@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ng.imageset/ng@3x.png b/Passepartout/App/iOS/Flags.xcassets/ng.imageset/ng@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ng.imageset/ng@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ng.imageset/ng@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ni.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ni.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ni.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ni.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ni.imageset/ni@2x.png b/Passepartout/App/iOS/Flags.xcassets/ni.imageset/ni@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ni.imageset/ni@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ni.imageset/ni@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ni.imageset/ni@3x.png b/Passepartout/App/iOS/Flags.xcassets/ni.imageset/ni@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ni.imageset/ni@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ni.imageset/ni@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/nl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/nl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/nl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/nl.imageset/nl@2x.png b/Passepartout/App/iOS/Flags.xcassets/nl.imageset/nl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nl.imageset/nl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/nl.imageset/nl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/nl.imageset/nl@3x.png b/Passepartout/App/iOS/Flags.xcassets/nl.imageset/nl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nl.imageset/nl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/nl.imageset/nl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/no.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/no.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/no.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/no.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/no.imageset/no@2x.png b/Passepartout/App/iOS/Flags.xcassets/no.imageset/no@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/no.imageset/no@2x.png rename to Passepartout/App/iOS/Flags.xcassets/no.imageset/no@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/no.imageset/no@3x.png b/Passepartout/App/iOS/Flags.xcassets/no.imageset/no@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/no.imageset/no@3x.png rename to Passepartout/App/iOS/Flags.xcassets/no.imageset/no@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/np.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/np.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/np.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/np.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/np.imageset/np@2x.png b/Passepartout/App/iOS/Flags.xcassets/np.imageset/np@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/np.imageset/np@2x.png rename to Passepartout/App/iOS/Flags.xcassets/np.imageset/np@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/np.imageset/np@3x.png b/Passepartout/App/iOS/Flags.xcassets/np.imageset/np@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/np.imageset/np@3x.png rename to Passepartout/App/iOS/Flags.xcassets/np.imageset/np@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/nr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/nr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/nr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/nr.imageset/nr@2x.png b/Passepartout/App/iOS/Flags.xcassets/nr.imageset/nr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nr.imageset/nr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/nr.imageset/nr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/nr.imageset/nr@3x.png b/Passepartout/App/iOS/Flags.xcassets/nr.imageset/nr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nr.imageset/nr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/nr.imageset/nr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/nu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/nu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/nu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/nu.imageset/nu@2x.png b/Passepartout/App/iOS/Flags.xcassets/nu.imageset/nu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nu.imageset/nu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/nu.imageset/nu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/nu.imageset/nu@3x.png b/Passepartout/App/iOS/Flags.xcassets/nu.imageset/nu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nu.imageset/nu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/nu.imageset/nu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/nz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/nz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/nz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/nz.imageset/nz@2x.png b/Passepartout/App/iOS/Flags.xcassets/nz.imageset/nz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nz.imageset/nz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/nz.imageset/nz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/nz.imageset/nz@3x.png b/Passepartout/App/iOS/Flags.xcassets/nz.imageset/nz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/nz.imageset/nz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/nz.imageset/nz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/om.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/om.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/om.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/om.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/om.imageset/om@2x.png b/Passepartout/App/iOS/Flags.xcassets/om.imageset/om@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/om.imageset/om@2x.png rename to Passepartout/App/iOS/Flags.xcassets/om.imageset/om@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/om.imageset/om@3x.png b/Passepartout/App/iOS/Flags.xcassets/om.imageset/om@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/om.imageset/om@3x.png rename to Passepartout/App/iOS/Flags.xcassets/om.imageset/om@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pa.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pa.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pa.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pa.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pa.imageset/pa@2x.png b/Passepartout/App/iOS/Flags.xcassets/pa.imageset/pa@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pa.imageset/pa@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pa.imageset/pa@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pa.imageset/pa@3x.png b/Passepartout/App/iOS/Flags.xcassets/pa.imageset/pa@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pa.imageset/pa@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pa.imageset/pa@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pe.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pe.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pe.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pe.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pe.imageset/pe@2x.png b/Passepartout/App/iOS/Flags.xcassets/pe.imageset/pe@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pe.imageset/pe@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pe.imageset/pe@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pe.imageset/pe@3x.png b/Passepartout/App/iOS/Flags.xcassets/pe.imageset/pe@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pe.imageset/pe@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pe.imageset/pe@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pf.imageset/pf@2x.png b/Passepartout/App/iOS/Flags.xcassets/pf.imageset/pf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pf.imageset/pf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pf.imageset/pf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pf.imageset/pf@3x.png b/Passepartout/App/iOS/Flags.xcassets/pf.imageset/pf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pf.imageset/pf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pf.imageset/pf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pg.imageset/pg@2x.png b/Passepartout/App/iOS/Flags.xcassets/pg.imageset/pg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pg.imageset/pg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pg.imageset/pg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pg.imageset/pg@3x.png b/Passepartout/App/iOS/Flags.xcassets/pg.imageset/pg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pg.imageset/pg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pg.imageset/pg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ph.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ph.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ph.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ph.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ph.imageset/ph@2x.png b/Passepartout/App/iOS/Flags.xcassets/ph.imageset/ph@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ph.imageset/ph@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ph.imageset/ph@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ph.imageset/ph@3x.png b/Passepartout/App/iOS/Flags.xcassets/ph.imageset/ph@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ph.imageset/ph@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ph.imageset/ph@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pk.imageset/pk@2x.png b/Passepartout/App/iOS/Flags.xcassets/pk.imageset/pk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pk.imageset/pk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pk.imageset/pk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pk.imageset/pk@3x.png b/Passepartout/App/iOS/Flags.xcassets/pk.imageset/pk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pk.imageset/pk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pk.imageset/pk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pl.imageset/pl@2x.png b/Passepartout/App/iOS/Flags.xcassets/pl.imageset/pl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pl.imageset/pl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pl.imageset/pl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pl.imageset/pl@3x.png b/Passepartout/App/iOS/Flags.xcassets/pl.imageset/pl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pl.imageset/pl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pl.imageset/pl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pm.imageset/pm@2x.png b/Passepartout/App/iOS/Flags.xcassets/pm.imageset/pm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pm.imageset/pm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pm.imageset/pm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pm.imageset/pm@3x.png b/Passepartout/App/iOS/Flags.xcassets/pm.imageset/pm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pm.imageset/pm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pm.imageset/pm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pn.imageset/pn@2x.png b/Passepartout/App/iOS/Flags.xcassets/pn.imageset/pn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pn.imageset/pn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pn.imageset/pn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pn.imageset/pn@3x.png b/Passepartout/App/iOS/Flags.xcassets/pn.imageset/pn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pn.imageset/pn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pn.imageset/pn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pr.imageset/pr@2x.png b/Passepartout/App/iOS/Flags.xcassets/pr.imageset/pr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pr.imageset/pr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pr.imageset/pr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pr.imageset/pr@3x.png b/Passepartout/App/iOS/Flags.xcassets/pr.imageset/pr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pr.imageset/pr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pr.imageset/pr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ps.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ps.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ps.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ps.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ps.imageset/ps@2x.png b/Passepartout/App/iOS/Flags.xcassets/ps.imageset/ps@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ps.imageset/ps@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ps.imageset/ps@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ps.imageset/ps@3x.png b/Passepartout/App/iOS/Flags.xcassets/ps.imageset/ps@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ps.imageset/ps@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ps.imageset/ps@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pt.imageset/pt@2x.png b/Passepartout/App/iOS/Flags.xcassets/pt.imageset/pt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pt.imageset/pt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pt.imageset/pt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pt.imageset/pt@3x.png b/Passepartout/App/iOS/Flags.xcassets/pt.imageset/pt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pt.imageset/pt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pt.imageset/pt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/pw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/pw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/pw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/pw.imageset/pw@2x.png b/Passepartout/App/iOS/Flags.xcassets/pw.imageset/pw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pw.imageset/pw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/pw.imageset/pw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/pw.imageset/pw@3x.png b/Passepartout/App/iOS/Flags.xcassets/pw.imageset/pw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/pw.imageset/pw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/pw.imageset/pw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/py.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/py.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/py.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/py.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/py.imageset/py@2x.png b/Passepartout/App/iOS/Flags.xcassets/py.imageset/py@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/py.imageset/py@2x.png rename to Passepartout/App/iOS/Flags.xcassets/py.imageset/py@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/py.imageset/py@3x.png b/Passepartout/App/iOS/Flags.xcassets/py.imageset/py@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/py.imageset/py@3x.png rename to Passepartout/App/iOS/Flags.xcassets/py.imageset/py@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/qa.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/qa.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/qa.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/qa.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/qa.imageset/qa@2x.png b/Passepartout/App/iOS/Flags.xcassets/qa.imageset/qa@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/qa.imageset/qa@2x.png rename to Passepartout/App/iOS/Flags.xcassets/qa.imageset/qa@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/qa.imageset/qa@3x.png b/Passepartout/App/iOS/Flags.xcassets/qa.imageset/qa@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/qa.imageset/qa@3x.png rename to Passepartout/App/iOS/Flags.xcassets/qa.imageset/qa@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/re.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/re.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/re.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/re.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/re.imageset/re@2x.png b/Passepartout/App/iOS/Flags.xcassets/re.imageset/re@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/re.imageset/re@2x.png rename to Passepartout/App/iOS/Flags.xcassets/re.imageset/re@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/re.imageset/re@3x.png b/Passepartout/App/iOS/Flags.xcassets/re.imageset/re@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/re.imageset/re@3x.png rename to Passepartout/App/iOS/Flags.xcassets/re.imageset/re@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ro.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ro.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ro.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ro.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ro.imageset/ro@2x.png b/Passepartout/App/iOS/Flags.xcassets/ro.imageset/ro@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ro.imageset/ro@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ro.imageset/ro@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ro.imageset/ro@3x.png b/Passepartout/App/iOS/Flags.xcassets/ro.imageset/ro@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ro.imageset/ro@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ro.imageset/ro@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/rs.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/rs.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/rs.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/rs.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/rs.imageset/rs@2x.png b/Passepartout/App/iOS/Flags.xcassets/rs.imageset/rs@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/rs.imageset/rs@2x.png rename to Passepartout/App/iOS/Flags.xcassets/rs.imageset/rs@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/rs.imageset/rs@3x.png b/Passepartout/App/iOS/Flags.xcassets/rs.imageset/rs@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/rs.imageset/rs@3x.png rename to Passepartout/App/iOS/Flags.xcassets/rs.imageset/rs@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ru.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ru.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ru.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ru.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ru.imageset/ru@2x.png b/Passepartout/App/iOS/Flags.xcassets/ru.imageset/ru@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ru.imageset/ru@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ru.imageset/ru@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ru.imageset/ru@3x.png b/Passepartout/App/iOS/Flags.xcassets/ru.imageset/ru@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ru.imageset/ru@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ru.imageset/ru@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/rw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/rw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/rw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/rw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/rw.imageset/rw@2x.png b/Passepartout/App/iOS/Flags.xcassets/rw.imageset/rw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/rw.imageset/rw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/rw.imageset/rw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/rw.imageset/rw@3x.png b/Passepartout/App/iOS/Flags.xcassets/rw.imageset/rw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/rw.imageset/rw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/rw.imageset/rw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sa.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sa.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sa.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sa.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sa.imageset/sa@2x.png b/Passepartout/App/iOS/Flags.xcassets/sa.imageset/sa@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sa.imageset/sa@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sa.imageset/sa@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sa.imageset/sa@3x.png b/Passepartout/App/iOS/Flags.xcassets/sa.imageset/sa@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sa.imageset/sa@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sa.imageset/sa@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sb.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sb.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sb.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sb.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sb.imageset/sb@2x.png b/Passepartout/App/iOS/Flags.xcassets/sb.imageset/sb@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sb.imageset/sb@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sb.imageset/sb@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sb.imageset/sb@3x.png b/Passepartout/App/iOS/Flags.xcassets/sb.imageset/sb@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sb.imageset/sb@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sb.imageset/sb@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sc.imageset/sc@2x.png b/Passepartout/App/iOS/Flags.xcassets/sc.imageset/sc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sc.imageset/sc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sc.imageset/sc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sc.imageset/sc@3x.png b/Passepartout/App/iOS/Flags.xcassets/sc.imageset/sc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sc.imageset/sc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sc.imageset/sc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sd.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sd.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sd.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sd.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sd.imageset/sd@2x.png b/Passepartout/App/iOS/Flags.xcassets/sd.imageset/sd@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sd.imageset/sd@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sd.imageset/sd@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sd.imageset/sd@3x.png b/Passepartout/App/iOS/Flags.xcassets/sd.imageset/sd@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sd.imageset/sd@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sd.imageset/sd@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/se.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/se.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/se.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/se.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/se.imageset/se@2x.png b/Passepartout/App/iOS/Flags.xcassets/se.imageset/se@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/se.imageset/se@2x.png rename to Passepartout/App/iOS/Flags.xcassets/se.imageset/se@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/se.imageset/se@3x.png b/Passepartout/App/iOS/Flags.xcassets/se.imageset/se@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/se.imageset/se@3x.png rename to Passepartout/App/iOS/Flags.xcassets/se.imageset/se@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sg.imageset/sg@2x.png b/Passepartout/App/iOS/Flags.xcassets/sg.imageset/sg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sg.imageset/sg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sg.imageset/sg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sg.imageset/sg@3x.png b/Passepartout/App/iOS/Flags.xcassets/sg.imageset/sg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sg.imageset/sg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sg.imageset/sg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sh.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sh.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sh.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sh.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sh.imageset/sh@2x.png b/Passepartout/App/iOS/Flags.xcassets/sh.imageset/sh@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sh.imageset/sh@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sh.imageset/sh@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sh.imageset/sh@3x.png b/Passepartout/App/iOS/Flags.xcassets/sh.imageset/sh@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sh.imageset/sh@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sh.imageset/sh@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/si.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/si.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/si.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/si.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/si.imageset/si@2x.png b/Passepartout/App/iOS/Flags.xcassets/si.imageset/si@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/si.imageset/si@2x.png rename to Passepartout/App/iOS/Flags.xcassets/si.imageset/si@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/si.imageset/si@3x.png b/Passepartout/App/iOS/Flags.xcassets/si.imageset/si@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/si.imageset/si@3x.png rename to Passepartout/App/iOS/Flags.xcassets/si.imageset/si@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sj.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sj.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sj.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sj.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sj.imageset/sj@2x.png b/Passepartout/App/iOS/Flags.xcassets/sj.imageset/sj@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sj.imageset/sj@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sj.imageset/sj@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sj.imageset/sj@3x.png b/Passepartout/App/iOS/Flags.xcassets/sj.imageset/sj@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sj.imageset/sj@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sj.imageset/sj@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sk.imageset/sk@2x.png b/Passepartout/App/iOS/Flags.xcassets/sk.imageset/sk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sk.imageset/sk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sk.imageset/sk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sk.imageset/sk@3x.png b/Passepartout/App/iOS/Flags.xcassets/sk.imageset/sk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sk.imageset/sk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sk.imageset/sk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sl.imageset/sl@2x.png b/Passepartout/App/iOS/Flags.xcassets/sl.imageset/sl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sl.imageset/sl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sl.imageset/sl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sl.imageset/sl@3x.png b/Passepartout/App/iOS/Flags.xcassets/sl.imageset/sl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sl.imageset/sl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sl.imageset/sl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sm.imageset/sm@2x.png b/Passepartout/App/iOS/Flags.xcassets/sm.imageset/sm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sm.imageset/sm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sm.imageset/sm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sm.imageset/sm@3x.png b/Passepartout/App/iOS/Flags.xcassets/sm.imageset/sm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sm.imageset/sm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sm.imageset/sm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sn.imageset/sn@2x.png b/Passepartout/App/iOS/Flags.xcassets/sn.imageset/sn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sn.imageset/sn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sn.imageset/sn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sn.imageset/sn@3x.png b/Passepartout/App/iOS/Flags.xcassets/sn.imageset/sn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sn.imageset/sn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sn.imageset/sn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/so.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/so.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/so.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/so.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/so.imageset/so@2x.png b/Passepartout/App/iOS/Flags.xcassets/so.imageset/so@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/so.imageset/so@2x.png rename to Passepartout/App/iOS/Flags.xcassets/so.imageset/so@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/so.imageset/so@3x.png b/Passepartout/App/iOS/Flags.xcassets/so.imageset/so@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/so.imageset/so@3x.png rename to Passepartout/App/iOS/Flags.xcassets/so.imageset/so@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sr.imageset/sr@2x.png b/Passepartout/App/iOS/Flags.xcassets/sr.imageset/sr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sr.imageset/sr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sr.imageset/sr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sr.imageset/sr@3x.png b/Passepartout/App/iOS/Flags.xcassets/sr.imageset/sr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sr.imageset/sr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sr.imageset/sr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ss.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ss.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ss.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ss.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ss.imageset/ss@2x.png b/Passepartout/App/iOS/Flags.xcassets/ss.imageset/ss@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ss.imageset/ss@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ss.imageset/ss@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ss.imageset/ss@3x.png b/Passepartout/App/iOS/Flags.xcassets/ss.imageset/ss@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ss.imageset/ss@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ss.imageset/ss@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/st.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/st.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/st.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/st.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/st.imageset/st@2x.png b/Passepartout/App/iOS/Flags.xcassets/st.imageset/st@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/st.imageset/st@2x.png rename to Passepartout/App/iOS/Flags.xcassets/st.imageset/st@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/st.imageset/st@3x.png b/Passepartout/App/iOS/Flags.xcassets/st.imageset/st@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/st.imageset/st@3x.png rename to Passepartout/App/iOS/Flags.xcassets/st.imageset/st@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sv.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sv.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sv.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sv.imageset/sv@2x.png b/Passepartout/App/iOS/Flags.xcassets/sv.imageset/sv@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sv.imageset/sv@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sv.imageset/sv@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sv.imageset/sv@3x.png b/Passepartout/App/iOS/Flags.xcassets/sv.imageset/sv@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sv.imageset/sv@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sv.imageset/sv@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sx.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sx.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sx.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sx.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sx.imageset/sx@2x.png b/Passepartout/App/iOS/Flags.xcassets/sx.imageset/sx@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sx.imageset/sx@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sx.imageset/sx@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sx.imageset/sx@3x.png b/Passepartout/App/iOS/Flags.xcassets/sx.imageset/sx@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sx.imageset/sx@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sx.imageset/sx@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sy.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sy.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sy.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sy.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sy.imageset/sy@2x.png b/Passepartout/App/iOS/Flags.xcassets/sy.imageset/sy@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sy.imageset/sy@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sy.imageset/sy@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sy.imageset/sy@3x.png b/Passepartout/App/iOS/Flags.xcassets/sy.imageset/sy@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sy.imageset/sy@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sy.imageset/sy@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/sz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/sz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/sz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/sz.imageset/sz@2x.png b/Passepartout/App/iOS/Flags.xcassets/sz.imageset/sz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sz.imageset/sz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/sz.imageset/sz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/sz.imageset/sz@3x.png b/Passepartout/App/iOS/Flags.xcassets/sz.imageset/sz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/sz.imageset/sz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/sz.imageset/sz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tc.imageset/tc@2x.png b/Passepartout/App/iOS/Flags.xcassets/tc.imageset/tc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tc.imageset/tc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tc.imageset/tc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tc.imageset/tc@3x.png b/Passepartout/App/iOS/Flags.xcassets/tc.imageset/tc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tc.imageset/tc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tc.imageset/tc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/td.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/td.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/td.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/td.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/td.imageset/td@2x.png b/Passepartout/App/iOS/Flags.xcassets/td.imageset/td@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/td.imageset/td@2x.png rename to Passepartout/App/iOS/Flags.xcassets/td.imageset/td@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/td.imageset/td@3x.png b/Passepartout/App/iOS/Flags.xcassets/td.imageset/td@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/td.imageset/td@3x.png rename to Passepartout/App/iOS/Flags.xcassets/td.imageset/td@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tf.imageset/tf@2x.png b/Passepartout/App/iOS/Flags.xcassets/tf.imageset/tf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tf.imageset/tf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tf.imageset/tf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tf.imageset/tf@3x.png b/Passepartout/App/iOS/Flags.xcassets/tf.imageset/tf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tf.imageset/tf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tf.imageset/tf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tg.imageset/tg@2x.png b/Passepartout/App/iOS/Flags.xcassets/tg.imageset/tg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tg.imageset/tg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tg.imageset/tg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tg.imageset/tg@3x.png b/Passepartout/App/iOS/Flags.xcassets/tg.imageset/tg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tg.imageset/tg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tg.imageset/tg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/th.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/th.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/th.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/th.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/th.imageset/th@2x.png b/Passepartout/App/iOS/Flags.xcassets/th.imageset/th@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/th.imageset/th@2x.png rename to Passepartout/App/iOS/Flags.xcassets/th.imageset/th@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/th.imageset/th@3x.png b/Passepartout/App/iOS/Flags.xcassets/th.imageset/th@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/th.imageset/th@3x.png rename to Passepartout/App/iOS/Flags.xcassets/th.imageset/th@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tj.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tj.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tj.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tj.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tj.imageset/tj@2x.png b/Passepartout/App/iOS/Flags.xcassets/tj.imageset/tj@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tj.imageset/tj@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tj.imageset/tj@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tj.imageset/tj@3x.png b/Passepartout/App/iOS/Flags.xcassets/tj.imageset/tj@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tj.imageset/tj@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tj.imageset/tj@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tk.imageset/tk@2x.png b/Passepartout/App/iOS/Flags.xcassets/tk.imageset/tk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tk.imageset/tk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tk.imageset/tk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tk.imageset/tk@3x.png b/Passepartout/App/iOS/Flags.xcassets/tk.imageset/tk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tk.imageset/tk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tk.imageset/tk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tl.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tl.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tl.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tl.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tl.imageset/tl@2x.png b/Passepartout/App/iOS/Flags.xcassets/tl.imageset/tl@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tl.imageset/tl@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tl.imageset/tl@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tl.imageset/tl@3x.png b/Passepartout/App/iOS/Flags.xcassets/tl.imageset/tl@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tl.imageset/tl@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tl.imageset/tl@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tm.imageset/tm@2x.png b/Passepartout/App/iOS/Flags.xcassets/tm.imageset/tm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tm.imageset/tm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tm.imageset/tm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tm.imageset/tm@3x.png b/Passepartout/App/iOS/Flags.xcassets/tm.imageset/tm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tm.imageset/tm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tm.imageset/tm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tn.imageset/tn@2x.png b/Passepartout/App/iOS/Flags.xcassets/tn.imageset/tn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tn.imageset/tn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tn.imageset/tn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tn.imageset/tn@3x.png b/Passepartout/App/iOS/Flags.xcassets/tn.imageset/tn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tn.imageset/tn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tn.imageset/tn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/to.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/to.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/to.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/to.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/to.imageset/to@2x.png b/Passepartout/App/iOS/Flags.xcassets/to.imageset/to@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/to.imageset/to@2x.png rename to Passepartout/App/iOS/Flags.xcassets/to.imageset/to@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/to.imageset/to@3x.png b/Passepartout/App/iOS/Flags.xcassets/to.imageset/to@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/to.imageset/to@3x.png rename to Passepartout/App/iOS/Flags.xcassets/to.imageset/to@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tr.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tr.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tr.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tr.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tr.imageset/tr@2x.png b/Passepartout/App/iOS/Flags.xcassets/tr.imageset/tr@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tr.imageset/tr@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tr.imageset/tr@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tr.imageset/tr@3x.png b/Passepartout/App/iOS/Flags.xcassets/tr.imageset/tr@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tr.imageset/tr@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tr.imageset/tr@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tt.imageset/tt@2x.png b/Passepartout/App/iOS/Flags.xcassets/tt.imageset/tt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tt.imageset/tt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tt.imageset/tt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tt.imageset/tt@3x.png b/Passepartout/App/iOS/Flags.xcassets/tt.imageset/tt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tt.imageset/tt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tt.imageset/tt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tv.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tv.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tv.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tv.imageset/tv@2x.png b/Passepartout/App/iOS/Flags.xcassets/tv.imageset/tv@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tv.imageset/tv@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tv.imageset/tv@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tv.imageset/tv@3x.png b/Passepartout/App/iOS/Flags.xcassets/tv.imageset/tv@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tv.imageset/tv@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tv.imageset/tv@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tw.imageset/tw@2x.png b/Passepartout/App/iOS/Flags.xcassets/tw.imageset/tw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tw.imageset/tw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tw.imageset/tw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tw.imageset/tw@3x.png b/Passepartout/App/iOS/Flags.xcassets/tw.imageset/tw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tw.imageset/tw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tw.imageset/tw@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/tz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/tz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/tz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/tz.imageset/tz@2x.png b/Passepartout/App/iOS/Flags.xcassets/tz.imageset/tz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tz.imageset/tz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/tz.imageset/tz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/tz.imageset/tz@3x.png b/Passepartout/App/iOS/Flags.xcassets/tz.imageset/tz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/tz.imageset/tz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/tz.imageset/tz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ua.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ua.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ua.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ua.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ua.imageset/ua@2x.png b/Passepartout/App/iOS/Flags.xcassets/ua.imageset/ua@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ua.imageset/ua@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ua.imageset/ua@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ua.imageset/ua@3x.png b/Passepartout/App/iOS/Flags.xcassets/ua.imageset/ua@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ua.imageset/ua@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ua.imageset/ua@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ug.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ug.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ug.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ug.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ug.imageset/ug@2x.png b/Passepartout/App/iOS/Flags.xcassets/ug.imageset/ug@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ug.imageset/ug@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ug.imageset/ug@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ug.imageset/ug@3x.png b/Passepartout/App/iOS/Flags.xcassets/ug.imageset/ug@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ug.imageset/ug@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ug.imageset/ug@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/um.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/um.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/um.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/um.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/um.imageset/um@2x.png b/Passepartout/App/iOS/Flags.xcassets/um.imageset/um@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/um.imageset/um@2x.png rename to Passepartout/App/iOS/Flags.xcassets/um.imageset/um@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/um.imageset/um@3x.png b/Passepartout/App/iOS/Flags.xcassets/um.imageset/um@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/um.imageset/um@3x.png rename to Passepartout/App/iOS/Flags.xcassets/um.imageset/um@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/un.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/un.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/un.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/un.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/un.imageset/un@2x.png b/Passepartout/App/iOS/Flags.xcassets/un.imageset/un@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/un.imageset/un@2x.png rename to Passepartout/App/iOS/Flags.xcassets/un.imageset/un@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/un.imageset/un@3x.png b/Passepartout/App/iOS/Flags.xcassets/un.imageset/un@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/un.imageset/un@3x.png rename to Passepartout/App/iOS/Flags.xcassets/un.imageset/un@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/us.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/us.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/us.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/us.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/us.imageset/us@2x.png b/Passepartout/App/iOS/Flags.xcassets/us.imageset/us@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/us.imageset/us@2x.png rename to Passepartout/App/iOS/Flags.xcassets/us.imageset/us@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/us.imageset/us@3x.png b/Passepartout/App/iOS/Flags.xcassets/us.imageset/us@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/us.imageset/us@3x.png rename to Passepartout/App/iOS/Flags.xcassets/us.imageset/us@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/uy.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/uy.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/uy.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/uy.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/uy.imageset/uy@2x.png b/Passepartout/App/iOS/Flags.xcassets/uy.imageset/uy@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/uy.imageset/uy@2x.png rename to Passepartout/App/iOS/Flags.xcassets/uy.imageset/uy@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/uy.imageset/uy@3x.png b/Passepartout/App/iOS/Flags.xcassets/uy.imageset/uy@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/uy.imageset/uy@3x.png rename to Passepartout/App/iOS/Flags.xcassets/uy.imageset/uy@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/uz.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/uz.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/uz.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/uz.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/uz.imageset/uz@2x.png b/Passepartout/App/iOS/Flags.xcassets/uz.imageset/uz@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/uz.imageset/uz@2x.png rename to Passepartout/App/iOS/Flags.xcassets/uz.imageset/uz@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/uz.imageset/uz@3x.png b/Passepartout/App/iOS/Flags.xcassets/uz.imageset/uz@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/uz.imageset/uz@3x.png rename to Passepartout/App/iOS/Flags.xcassets/uz.imageset/uz@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/va.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/va.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/va.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/va.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/va.imageset/va@2x.png b/Passepartout/App/iOS/Flags.xcassets/va.imageset/va@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/va.imageset/va@2x.png rename to Passepartout/App/iOS/Flags.xcassets/va.imageset/va@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/va.imageset/va@3x.png b/Passepartout/App/iOS/Flags.xcassets/va.imageset/va@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/va.imageset/va@3x.png rename to Passepartout/App/iOS/Flags.xcassets/va.imageset/va@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/vc.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/vc.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vc.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/vc.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/vc.imageset/vc@2x.png b/Passepartout/App/iOS/Flags.xcassets/vc.imageset/vc@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vc.imageset/vc@2x.png rename to Passepartout/App/iOS/Flags.xcassets/vc.imageset/vc@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/vc.imageset/vc@3x.png b/Passepartout/App/iOS/Flags.xcassets/vc.imageset/vc@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vc.imageset/vc@3x.png rename to Passepartout/App/iOS/Flags.xcassets/vc.imageset/vc@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ve.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ve.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ve.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ve.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ve.imageset/ve@2x.png b/Passepartout/App/iOS/Flags.xcassets/ve.imageset/ve@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ve.imageset/ve@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ve.imageset/ve@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ve.imageset/ve@3x.png b/Passepartout/App/iOS/Flags.xcassets/ve.imageset/ve@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ve.imageset/ve@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ve.imageset/ve@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/vg.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/vg.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vg.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/vg.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/vg.imageset/vg@2x.png b/Passepartout/App/iOS/Flags.xcassets/vg.imageset/vg@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vg.imageset/vg@2x.png rename to Passepartout/App/iOS/Flags.xcassets/vg.imageset/vg@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/vg.imageset/vg@3x.png b/Passepartout/App/iOS/Flags.xcassets/vg.imageset/vg@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vg.imageset/vg@3x.png rename to Passepartout/App/iOS/Flags.xcassets/vg.imageset/vg@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/vi.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/vi.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vi.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/vi.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/vi.imageset/vi@2x.png b/Passepartout/App/iOS/Flags.xcassets/vi.imageset/vi@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vi.imageset/vi@2x.png rename to Passepartout/App/iOS/Flags.xcassets/vi.imageset/vi@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/vi.imageset/vi@3x.png b/Passepartout/App/iOS/Flags.xcassets/vi.imageset/vi@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vi.imageset/vi@3x.png rename to Passepartout/App/iOS/Flags.xcassets/vi.imageset/vi@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/vn.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/vn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vn.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/vn.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/vn.imageset/vn@2x.png b/Passepartout/App/iOS/Flags.xcassets/vn.imageset/vn@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vn.imageset/vn@2x.png rename to Passepartout/App/iOS/Flags.xcassets/vn.imageset/vn@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/vn.imageset/vn@3x.png b/Passepartout/App/iOS/Flags.xcassets/vn.imageset/vn@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vn.imageset/vn@3x.png rename to Passepartout/App/iOS/Flags.xcassets/vn.imageset/vn@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/vu.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/vu.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vu.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/vu.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/vu.imageset/vu@2x.png b/Passepartout/App/iOS/Flags.xcassets/vu.imageset/vu@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vu.imageset/vu@2x.png rename to Passepartout/App/iOS/Flags.xcassets/vu.imageset/vu@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/vu.imageset/vu@3x.png b/Passepartout/App/iOS/Flags.xcassets/vu.imageset/vu@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/vu.imageset/vu@3x.png rename to Passepartout/App/iOS/Flags.xcassets/vu.imageset/vu@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/wf.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/wf.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/wf.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/wf.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/wf.imageset/wf@2x.png b/Passepartout/App/iOS/Flags.xcassets/wf.imageset/wf@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/wf.imageset/wf@2x.png rename to Passepartout/App/iOS/Flags.xcassets/wf.imageset/wf@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/wf.imageset/wf@3x.png b/Passepartout/App/iOS/Flags.xcassets/wf.imageset/wf@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/wf.imageset/wf@3x.png rename to Passepartout/App/iOS/Flags.xcassets/wf.imageset/wf@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ws.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ws.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ws.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ws.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ws.imageset/ws@2x.png b/Passepartout/App/iOS/Flags.xcassets/ws.imageset/ws@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ws.imageset/ws@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ws.imageset/ws@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ws.imageset/ws@3x.png b/Passepartout/App/iOS/Flags.xcassets/ws.imageset/ws@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ws.imageset/ws@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ws.imageset/ws@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/xk.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/xk.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/xk.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/xk.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/xk.imageset/xk@2x.png b/Passepartout/App/iOS/Flags.xcassets/xk.imageset/xk@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/xk.imageset/xk@2x.png rename to Passepartout/App/iOS/Flags.xcassets/xk.imageset/xk@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/xk.imageset/xk@3x.png b/Passepartout/App/iOS/Flags.xcassets/xk.imageset/xk@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/xk.imageset/xk@3x.png rename to Passepartout/App/iOS/Flags.xcassets/xk.imageset/xk@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/ye.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/ye.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ye.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/ye.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/ye.imageset/ye@2x.png b/Passepartout/App/iOS/Flags.xcassets/ye.imageset/ye@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ye.imageset/ye@2x.png rename to Passepartout/App/iOS/Flags.xcassets/ye.imageset/ye@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/ye.imageset/ye@3x.png b/Passepartout/App/iOS/Flags.xcassets/ye.imageset/ye@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/ye.imageset/ye@3x.png rename to Passepartout/App/iOS/Flags.xcassets/ye.imageset/ye@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/yt.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/yt.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/yt.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/yt.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/yt.imageset/yt@2x.png b/Passepartout/App/iOS/Flags.xcassets/yt.imageset/yt@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/yt.imageset/yt@2x.png rename to Passepartout/App/iOS/Flags.xcassets/yt.imageset/yt@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/yt.imageset/yt@3x.png b/Passepartout/App/iOS/Flags.xcassets/yt.imageset/yt@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/yt.imageset/yt@3x.png rename to Passepartout/App/iOS/Flags.xcassets/yt.imageset/yt@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/za.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/za.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/za.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/za.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/za.imageset/za@2x.png b/Passepartout/App/iOS/Flags.xcassets/za.imageset/za@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/za.imageset/za@2x.png rename to Passepartout/App/iOS/Flags.xcassets/za.imageset/za@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/za.imageset/za@3x.png b/Passepartout/App/iOS/Flags.xcassets/za.imageset/za@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/za.imageset/za@3x.png rename to Passepartout/App/iOS/Flags.xcassets/za.imageset/za@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/zm.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/zm.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/zm.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/zm.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/zm.imageset/zm@2x.png b/Passepartout/App/iOS/Flags.xcassets/zm.imageset/zm@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/zm.imageset/zm@2x.png rename to Passepartout/App/iOS/Flags.xcassets/zm.imageset/zm@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/zm.imageset/zm@3x.png b/Passepartout/App/iOS/Flags.xcassets/zm.imageset/zm@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/zm.imageset/zm@3x.png rename to Passepartout/App/iOS/Flags.xcassets/zm.imageset/zm@3x.png diff --git a/Passepartout-iOS/Flags.xcassets/zw.imageset/Contents.json b/Passepartout/App/iOS/Flags.xcassets/zw.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Flags.xcassets/zw.imageset/Contents.json rename to Passepartout/App/iOS/Flags.xcassets/zw.imageset/Contents.json diff --git a/Passepartout-iOS/Flags.xcassets/zw.imageset/zw@2x.png b/Passepartout/App/iOS/Flags.xcassets/zw.imageset/zw@2x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/zw.imageset/zw@2x.png rename to Passepartout/App/iOS/Flags.xcassets/zw.imageset/zw@2x.png diff --git a/Passepartout-iOS/Flags.xcassets/zw.imageset/zw@3x.png b/Passepartout/App/iOS/Flags.xcassets/zw.imageset/zw@3x.png similarity index 100% rename from Passepartout-iOS/Flags.xcassets/zw.imageset/zw@3x.png rename to Passepartout/App/iOS/Flags.xcassets/zw.imageset/zw@3x.png diff --git a/Passepartout-iOS/Global/AppConstants+App.swift b/Passepartout/App/iOS/Global/AppConstants+App.swift similarity index 100% rename from Passepartout-iOS/Global/AppConstants+App.swift rename to Passepartout/App/iOS/Global/AppConstants+App.swift diff --git a/Passepartout-iOS/Global/HostImporter.swift b/Passepartout/App/iOS/Global/HostImporter.swift similarity index 100% rename from Passepartout-iOS/Global/HostImporter.swift rename to Passepartout/App/iOS/Global/HostImporter.swift diff --git a/Passepartout-iOS/Global/IssueReporter.swift b/Passepartout/App/iOS/Global/IssueReporter.swift similarity index 100% rename from Passepartout-iOS/Global/IssueReporter.swift rename to Passepartout/App/iOS/Global/IssueReporter.swift diff --git a/Passepartout-iOS/Global/Macros.swift b/Passepartout/App/iOS/Global/Macros.swift similarity index 100% rename from Passepartout-iOS/Global/Macros.swift rename to Passepartout/App/iOS/Global/Macros.swift diff --git a/Passepartout-iOS/Global/ProductManager+App.swift b/Passepartout/App/iOS/Global/ProductManager+App.swift similarity index 100% rename from Passepartout-iOS/Global/ProductManager+App.swift rename to Passepartout/App/iOS/Global/ProductManager+App.swift diff --git a/Passepartout-iOS/Global/SwiftGen+Assets.swift b/Passepartout/App/iOS/Global/SwiftGen+Assets.swift similarity index 100% rename from Passepartout-iOS/Global/SwiftGen+Assets.swift rename to Passepartout/App/iOS/Global/SwiftGen+Assets.swift diff --git a/Passepartout-iOS/Global/SwiftGen+Scenes.swift b/Passepartout/App/iOS/Global/SwiftGen+Scenes.swift similarity index 100% rename from Passepartout-iOS/Global/SwiftGen+Scenes.swift rename to Passepartout/App/iOS/Global/SwiftGen+Scenes.swift diff --git a/Passepartout-iOS/Global/SwiftGen+Segues.swift b/Passepartout/App/iOS/Global/SwiftGen+Segues.swift similarity index 100% rename from Passepartout-iOS/Global/SwiftGen+Segues.swift rename to Passepartout/App/iOS/Global/SwiftGen+Segues.swift diff --git a/Passepartout-iOS/Global/SwiftGen+Strings.swift b/Passepartout/App/iOS/Global/SwiftGen+Strings.swift similarity index 100% rename from Passepartout-iOS/Global/SwiftGen+Strings.swift rename to Passepartout/App/iOS/Global/SwiftGen+Strings.swift diff --git a/Passepartout-iOS/Global/Theme+Cells.swift b/Passepartout/App/iOS/Global/Theme+Cells.swift similarity index 100% rename from Passepartout-iOS/Global/Theme+Cells.swift rename to Passepartout/App/iOS/Global/Theme+Cells.swift diff --git a/Passepartout-iOS/Global/Theme+Titles.swift b/Passepartout/App/iOS/Global/Theme+Titles.swift similarity index 100% rename from Passepartout-iOS/Global/Theme+Titles.swift rename to Passepartout/App/iOS/Global/Theme+Titles.swift diff --git a/Passepartout-iOS/Global/Theme.swift b/Passepartout/App/iOS/Global/Theme.swift similarity index 100% rename from Passepartout-iOS/Global/Theme.swift rename to Passepartout/App/iOS/Global/Theme.swift diff --git a/Passepartout-iOS/Global/UITextView+Search.swift b/Passepartout/App/iOS/Global/UITextView+Search.swift similarity index 100% rename from Passepartout-iOS/Global/UITextView+Search.swift rename to Passepartout/App/iOS/Global/UITextView+Search.swift diff --git a/Passepartout-iOS/Info.plist b/Passepartout/App/iOS/Info.plist similarity index 93% rename from Passepartout-iOS/Info.plist rename to Passepartout/App/iOS/Info.plist index 2133a4b7..77331810 100644 --- a/Passepartout-iOS/Info.plist +++ b/Passepartout/App/iOS/Info.plist @@ -33,15 +33,17 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.13.1 + $(CFG_APP_VERSION) CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS LSSupportsOpeningDocumentsInPlace + NSHumanReadableCopyright + $(CFG_COPYRIGHT) NSLocationWhenInUseUsageDescription dummy NSUserActivityTypes @@ -90,7 +92,7 @@ com.algoritmico.Passepartout.config appstore_id - $(CFG_APPSTORE_ID) + $(CFG_APPSTORE_IOS_ID) group_id group.$(CFG_GROUP_ID) diff --git a/Passepartout-iOS/Providers.xcassets/Contents.json b/Passepartout/App/iOS/Providers.xcassets/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/csv.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/csv.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/csv.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/csv.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/csv.imageset/csv@2x.png b/Passepartout/App/iOS/Providers.xcassets/csv.imageset/csv@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/csv.imageset/csv@2x.png rename to Passepartout/App/iOS/Providers.xcassets/csv.imageset/csv@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/csv.imageset/csv@3x.png b/Passepartout/App/iOS/Providers.xcassets/csv.imageset/csv@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/csv.imageset/csv@3x.png rename to Passepartout/App/iOS/Providers.xcassets/csv.imageset/csv@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/hideme.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/hideme.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/hideme.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/hideme.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/hideme.imageset/hideme@2x.png b/Passepartout/App/iOS/Providers.xcassets/hideme.imageset/hideme@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/hideme.imageset/hideme@2x.png rename to Passepartout/App/iOS/Providers.xcassets/hideme.imageset/hideme@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/hideme.imageset/hideme@3x.png b/Passepartout/App/iOS/Providers.xcassets/hideme.imageset/hideme@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/hideme.imageset/hideme@3x.png rename to Passepartout/App/iOS/Providers.xcassets/hideme.imageset/hideme@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/mullvad.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/mullvad.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/mullvad.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/mullvad.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png b/Passepartout/App/iOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png rename to Passepartout/App/iOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png b/Passepartout/App/iOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png rename to Passepartout/App/iOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/nordvpn.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/nordvpn.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png b/Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png rename to Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png b/Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png rename to Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png b/Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png rename to Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png b/Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png rename to Passepartout/App/iOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/pia.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/pia.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/pia.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/pia.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/pia.imageset/pia@2x.png b/Passepartout/App/iOS/Providers.xcassets/pia.imageset/pia@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/pia.imageset/pia@2x.png rename to Passepartout/App/iOS/Providers.xcassets/pia.imageset/pia@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/pia.imageset/pia@3x.png b/Passepartout/App/iOS/Providers.xcassets/pia.imageset/pia@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/pia.imageset/pia@3x.png rename to Passepartout/App/iOS/Providers.xcassets/pia.imageset/pia@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/placeholder.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/placeholder.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/placeholder.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/placeholder.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png b/Passepartout/App/iOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png rename to Passepartout/App/iOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png b/Passepartout/App/iOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png rename to Passepartout/App/iOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/protonvpn.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/protonvpn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/protonvpn.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/protonvpn.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png b/Passepartout/App/iOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png rename to Passepartout/App/iOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png b/Passepartout/App/iOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png rename to Passepartout/App/iOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/torguard.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/torguard.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/torguard.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/torguard.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/torguard.imageset/torguard@2x.png b/Passepartout/App/iOS/Providers.xcassets/torguard.imageset/torguard@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/torguard.imageset/torguard@2x.png rename to Passepartout/App/iOS/Providers.xcassets/torguard.imageset/torguard@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/torguard.imageset/torguard@3x.png b/Passepartout/App/iOS/Providers.xcassets/torguard.imageset/torguard@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/torguard.imageset/torguard@3x.png rename to Passepartout/App/iOS/Providers.xcassets/torguard.imageset/torguard@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/tunnelbear.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/tunnelbear.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/tunnelbear.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/tunnelbear.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png b/Passepartout/App/iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png rename to Passepartout/App/iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png b/Passepartout/App/iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png rename to Passepartout/App/iOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/vyprvpn.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/vyprvpn.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/vyprvpn.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/vyprvpn.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png b/Passepartout/App/iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png rename to Passepartout/App/iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png b/Passepartout/App/iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png rename to Passepartout/App/iOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png diff --git a/Passepartout-iOS/Providers.xcassets/windscribe.imageset/Contents.json b/Passepartout/App/iOS/Providers.xcassets/windscribe.imageset/Contents.json similarity index 100% rename from Passepartout-iOS/Providers.xcassets/windscribe.imageset/Contents.json rename to Passepartout/App/iOS/Providers.xcassets/windscribe.imageset/Contents.json diff --git a/Passepartout-iOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png b/Passepartout/App/iOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png rename to Passepartout/App/iOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png diff --git a/Passepartout-iOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png b/Passepartout/App/iOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png similarity index 100% rename from Passepartout-iOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png rename to Passepartout/App/iOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png diff --git a/Passepartout-iOS/Scenes/About/AboutViewController.swift b/Passepartout/App/iOS/Scenes/About/AboutViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/About/AboutViewController.swift rename to Passepartout/App/iOS/Scenes/About/AboutViewController.swift diff --git a/Passepartout-iOS/Scenes/AccountViewController.swift b/Passepartout/App/iOS/Scenes/AccountViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/AccountViewController.swift rename to Passepartout/App/iOS/Scenes/AccountViewController.swift diff --git a/Passepartout-iOS/Scenes/ConfigurationModificationDelegate.swift b/Passepartout/App/iOS/Scenes/ConfigurationModificationDelegate.swift similarity index 100% rename from Passepartout-iOS/Scenes/ConfigurationModificationDelegate.swift rename to Passepartout/App/iOS/Scenes/ConfigurationModificationDelegate.swift diff --git a/Passepartout-iOS/Scenes/ConfigurationViewController.swift b/Passepartout/App/iOS/Scenes/ConfigurationViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/ConfigurationViewController.swift rename to Passepartout/App/iOS/Scenes/ConfigurationViewController.swift diff --git a/Passepartout-iOS/Scenes/DebugLogViewController.swift b/Passepartout/App/iOS/Scenes/DebugLogViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/DebugLogViewController.swift rename to Passepartout/App/iOS/Scenes/DebugLogViewController.swift diff --git a/Passepartout-iOS/Scenes/EndpointViewController.swift b/Passepartout/App/iOS/Scenes/EndpointViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/EndpointViewController.swift rename to Passepartout/App/iOS/Scenes/EndpointViewController.swift diff --git a/Passepartout-iOS/Scenes/NetworkSettingsViewController.swift b/Passepartout/App/iOS/Scenes/NetworkSettingsViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/NetworkSettingsViewController.swift rename to Passepartout/App/iOS/Scenes/NetworkSettingsViewController.swift diff --git a/Passepartout-iOS/Scenes/Organizer/DonationViewController.swift b/Passepartout/App/iOS/Scenes/Organizer/DonationViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Organizer/DonationViewController.swift rename to Passepartout/App/iOS/Scenes/Organizer/DonationViewController.swift diff --git a/Passepartout-iOS/Scenes/Organizer/ImportedHostsViewController.swift b/Passepartout/App/iOS/Scenes/Organizer/ImportedHostsViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Organizer/ImportedHostsViewController.swift rename to Passepartout/App/iOS/Scenes/Organizer/ImportedHostsViewController.swift diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout/App/iOS/Scenes/Organizer/OrganizerViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift rename to Passepartout/App/iOS/Scenes/Organizer/OrganizerViewController.swift diff --git a/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift b/Passepartout/App/iOS/Scenes/Organizer/WizardHostViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift rename to Passepartout/App/iOS/Scenes/Organizer/WizardHostViewController.swift diff --git a/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift b/Passepartout/App/iOS/Scenes/Organizer/WizardProviderViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift rename to Passepartout/App/iOS/Scenes/Organizer/WizardProviderViewController.swift diff --git a/Passepartout-iOS/Scenes/ProviderPoolViewController.swift b/Passepartout/App/iOS/Scenes/ProviderPoolViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/ProviderPoolViewController.swift rename to Passepartout/App/iOS/Scenes/ProviderPoolViewController.swift diff --git a/Passepartout-iOS/Scenes/ProviderPresetViewController.swift b/Passepartout/App/iOS/Scenes/ProviderPresetViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/ProviderPresetViewController.swift rename to Passepartout/App/iOS/Scenes/ProviderPresetViewController.swift diff --git a/Passepartout-iOS/Scenes/Purchase/PurchaseTableViewCell.swift b/Passepartout/App/iOS/Scenes/Purchase/PurchaseTableViewCell.swift similarity index 100% rename from Passepartout-iOS/Scenes/Purchase/PurchaseTableViewCell.swift rename to Passepartout/App/iOS/Scenes/Purchase/PurchaseTableViewCell.swift diff --git a/Passepartout-iOS/Scenes/Purchase/PurchaseViewController.swift b/Passepartout/App/iOS/Scenes/Purchase/PurchaseViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Purchase/PurchaseViewController.swift rename to Passepartout/App/iOS/Scenes/Purchase/PurchaseViewController.swift diff --git a/Passepartout-iOS/Scenes/ServerNetworkViewController.swift b/Passepartout/App/iOS/Scenes/ServerNetworkViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/ServerNetworkViewController.swift rename to Passepartout/App/iOS/Scenes/ServerNetworkViewController.swift diff --git a/Passepartout-iOS/Scenes/ServiceViewController.swift b/Passepartout/App/iOS/Scenes/ServiceViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/ServiceViewController.swift rename to Passepartout/App/iOS/Scenes/ServiceViewController.swift diff --git a/Passepartout-iOS/Scenes/Shortcuts/ShortcutsAddViewController.swift b/Passepartout/App/iOS/Scenes/Shortcuts/ShortcutsAddViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Shortcuts/ShortcutsAddViewController.swift rename to Passepartout/App/iOS/Scenes/Shortcuts/ShortcutsAddViewController.swift diff --git a/Passepartout-iOS/Scenes/Shortcuts/ShortcutsConnectToViewController.swift b/Passepartout/App/iOS/Scenes/Shortcuts/ShortcutsConnectToViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Shortcuts/ShortcutsConnectToViewController.swift rename to Passepartout/App/iOS/Scenes/Shortcuts/ShortcutsConnectToViewController.swift diff --git a/Passepartout-iOS/Scenes/Shortcuts/ShortcutsViewController.swift b/Passepartout/App/iOS/Scenes/Shortcuts/ShortcutsViewController.swift similarity index 100% rename from Passepartout-iOS/Scenes/Shortcuts/ShortcutsViewController.swift rename to Passepartout/App/iOS/Scenes/Shortcuts/ShortcutsViewController.swift diff --git a/Passepartout-iOS/Settings.bundle/Root.plist b/Passepartout/App/iOS/Settings.bundle/Root.plist similarity index 100% rename from Passepartout-iOS/Settings.bundle/Root.plist rename to Passepartout/App/iOS/Settings.bundle/Root.plist diff --git a/Passepartout-iOS/Settings.bundle/en.lproj/Root.strings b/Passepartout/App/iOS/Settings.bundle/en.lproj/Root.strings similarity index 100% rename from Passepartout-iOS/Settings.bundle/en.lproj/Root.strings rename to Passepartout/App/iOS/Settings.bundle/en.lproj/Root.strings diff --git a/Passepartout-iOS/Global/de.lproj/App.strings b/Passepartout/App/iOS/de.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/de.lproj/App.strings rename to Passepartout/App/iOS/de.lproj/App.strings diff --git a/Passepartout-iOS/de.lproj/InfoPlist.strings b/Passepartout/App/iOS/de.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/de.lproj/InfoPlist.strings rename to Passepartout/App/iOS/de.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/el.lproj/App.strings b/Passepartout/App/iOS/el.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/el.lproj/App.strings rename to Passepartout/App/iOS/el.lproj/App.strings diff --git a/Passepartout-iOS/el.lproj/InfoPlist.strings b/Passepartout/App/iOS/el.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/el.lproj/InfoPlist.strings rename to Passepartout/App/iOS/el.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/en.lproj/App.strings b/Passepartout/App/iOS/en.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/en.lproj/App.strings rename to Passepartout/App/iOS/en.lproj/App.strings diff --git a/Passepartout-iOS/en.lproj/InfoPlist.strings b/Passepartout/App/iOS/en.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/en.lproj/InfoPlist.strings rename to Passepartout/App/iOS/en.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/es.lproj/App.strings b/Passepartout/App/iOS/es.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/es.lproj/App.strings rename to Passepartout/App/iOS/es.lproj/App.strings diff --git a/Passepartout-iOS/es.lproj/InfoPlist.strings b/Passepartout/App/iOS/es.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/es.lproj/InfoPlist.strings rename to Passepartout/App/iOS/es.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/fr.lproj/App.strings b/Passepartout/App/iOS/fr.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/fr.lproj/App.strings rename to Passepartout/App/iOS/fr.lproj/App.strings diff --git a/Passepartout-iOS/fr.lproj/InfoPlist.strings b/Passepartout/App/iOS/fr.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/fr.lproj/InfoPlist.strings rename to Passepartout/App/iOS/fr.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/it.lproj/App.strings b/Passepartout/App/iOS/it.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/it.lproj/App.strings rename to Passepartout/App/iOS/it.lproj/App.strings diff --git a/Passepartout-iOS/it.lproj/InfoPlist.strings b/Passepartout/App/iOS/it.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/it.lproj/InfoPlist.strings rename to Passepartout/App/iOS/it.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/nl.lproj/App.strings b/Passepartout/App/iOS/nl.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/nl.lproj/App.strings rename to Passepartout/App/iOS/nl.lproj/App.strings diff --git a/Passepartout-iOS/nl.lproj/InfoPlist.strings b/Passepartout/App/iOS/nl.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/nl.lproj/InfoPlist.strings rename to Passepartout/App/iOS/nl.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/pl.lproj/App.strings b/Passepartout/App/iOS/pl.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/pl.lproj/App.strings rename to Passepartout/App/iOS/pl.lproj/App.strings diff --git a/Passepartout-iOS/pl.lproj/InfoPlist.strings b/Passepartout/App/iOS/pl.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/pl.lproj/InfoPlist.strings rename to Passepartout/App/iOS/pl.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/pt.lproj/App.strings b/Passepartout/App/iOS/pt.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/pt.lproj/App.strings rename to Passepartout/App/iOS/pt.lproj/App.strings diff --git a/Passepartout-iOS/pt.lproj/InfoPlist.strings b/Passepartout/App/iOS/pt.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/pt.lproj/InfoPlist.strings rename to Passepartout/App/iOS/pt.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/ru.lproj/App.strings b/Passepartout/App/iOS/ru.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/ru.lproj/App.strings rename to Passepartout/App/iOS/ru.lproj/App.strings diff --git a/Passepartout-iOS/ru.lproj/InfoPlist.strings b/Passepartout/App/iOS/ru.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/ru.lproj/InfoPlist.strings rename to Passepartout/App/iOS/ru.lproj/InfoPlist.strings diff --git a/Passepartout-iOS/Global/sv.lproj/App.strings b/Passepartout/App/iOS/sv.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/sv.lproj/App.strings rename to Passepartout/App/iOS/sv.lproj/App.strings diff --git a/Passepartout-iOS/sv.lproj/InfoPlist.strings b/Passepartout/App/iOS/sv.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/sv.lproj/InfoPlist.strings rename to Passepartout/App/iOS/sv.lproj/InfoPlist.strings diff --git a/Passepartout/App/iOS/swiftgen.yml b/Passepartout/App/iOS/swiftgen.yml new file mode 100644 index 00000000..bdbfc73f --- /dev/null +++ b/Passepartout/App/iOS/swiftgen.yml @@ -0,0 +1,29 @@ +strings: + inputs: + - ../../Core/Resources/en.lproj/Core.strings + - en.lproj/App.strings + outputs: + - templateName: structured-swift4 + output: Global/SwiftGen+Strings.swift + +ib: + inputs: + - Base.lproj/About.storyboard + - Base.lproj/Main.storyboard + - Base.lproj/Organizer.storyboard + - Base.lproj/Purchase.storyboard + - Base.lproj/Shortcuts.storyboard + outputs: + - templateName: scenes-swift4 + output: Global/SwiftGen+Scenes.swift + - templateName: segues-swift4 + output: Global/SwiftGen+Segues.swift + +xcassets: + inputs: + - Assets.xcassets + - Flags.xcassets + - Providers.xcassets + outputs: + - templateName: swift4 + output: Global/SwiftGen+Assets.swift diff --git a/Passepartout-iOS/Global/zh-Hans.lproj/App.strings b/Passepartout/App/iOS/zh-Hans.lproj/App.strings similarity index 100% rename from Passepartout-iOS/Global/zh-Hans.lproj/App.strings rename to Passepartout/App/iOS/zh-Hans.lproj/App.strings diff --git a/Passepartout-iOS/zh-Hans.lproj/InfoPlist.strings b/Passepartout/App/iOS/zh-Hans.lproj/InfoPlist.strings similarity index 100% rename from Passepartout-iOS/zh-Hans.lproj/InfoPlist.strings rename to Passepartout/App/iOS/zh-Hans.lproj/InfoPlist.strings diff --git a/Passepartout/App/macOS/App.entitlements b/Passepartout/App/macOS/App.entitlements new file mode 100644 index 00000000..61ce30e2 --- /dev/null +++ b/Passepartout/App/macOS/App.entitlements @@ -0,0 +1,20 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + $(TeamIdentifierPrefix)group.$(CFG_GROUP_ID) + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + + diff --git a/Passepartout/App/macOS/AppDelegate.swift b/Passepartout/App/macOS/AppDelegate.swift new file mode 100644 index 00000000..6106aec0 --- /dev/null +++ b/Passepartout/App/macOS/AppDelegate.swift @@ -0,0 +1,133 @@ +// +// AppDelegate.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/6/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import Convenience +import TunnelKit +import ServiceManagement + +// comment on release +//import AppCenter +//import AppCenterAnalytics +//import AppCenterCrashes + +extension Notification.Name { + static let killLauncher = Notification.Name("killLauncher") +} + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + private let appCenterSecret = GroupConstants.App.config?["appcenter_secret"] as? String + + private var importer: HostImporter? + + override init() { + AppConstants.Log.configure() + InfrastructureFactory.shared.preload() + VPN.shared = OpenVPNProvider(bundleIdentifier: AppConstants.App.tunnelBundleId) + super.init() + } + + func applicationDidFinishLaunching(_ aNotification: Notification) { + Reviewer.shared.eventCountBeforeRating = AppConstants.Rating.eventCount + ProductManager.shared.listProducts(completionHandler: nil) + + NSApp.mainMenu = loadMainMenu() + StatusMenu.shared.install() + +// if let appCenterSecret = appCenterSecret, !appCenterSecret.isEmpty { +// AppCenter.start(withAppSecret: appCenterSecret, services: [Analytics.self, Crashes.self]) +// } + + // launcher configuration + + let launcherAppId = AppConstants.App.appLauncherId + let runningApps = NSWorkspace.shared.runningApplications + let isRunning = !runningApps.filter { $0.bundleIdentifier == launcherAppId }.isEmpty + + if isRunning { + DistributedNotificationCenter.default().post(name: .killLauncher, object: Bundle.main.bundleIdentifier!) + } + + if !TransientStore.didHandleSubreddit { + let alert = Macros.warning(L10n.Core.Reddit.title, L10n.Core.Reddit.message) + alert.present(in: nil, withOK: L10n.Core.Reddit.Buttons.subscribe, cancel: L10n.Core.Reddit.Buttons.never, dummy: L10n.Core.Reddit.Buttons.remind, handler: { + TransientStore.didHandleSubreddit = true + self.subscribeSubreddit() + }, cancelHandler: { + TransientStore.didHandleSubreddit = true + }) + } + } + + func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { + let alert = Macros.warning( + L10n.App.Menu.Quit.title(GroupConstants.App.name), + L10n.App.Menu.Quit.Messages.confirm + ) + guard alert.presentModally(withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel) else { + return .terminateCancel + } + return .terminateNow + } + + func applicationWillTerminate(_ aNotification: Notification) { + TransientStore.shared.serialize(withProfiles: true) // exit + } + + func application(_ sender: NSApplication, openFile filename: String) -> Bool { + let url = URL(fileURLWithPath: filename) + importer = HostImporter(withConfigurationURL: url) + importer?.importHost(withPassphrase: nil) + return true + } + + // MARK: Helpers + + private func loadMainMenu() -> NSMenu? { + let nibName = "MainMenu" + guard let nib = NSNib(nibNamed: nibName, bundle: nil) else { + fatalError(nibName) + } + var objects: NSArray? + guard nib.instantiate(withOwner: nil, topLevelObjects: &objects) else { + fatalError(nibName) + } + guard let nonOptionalObjects = objects else { + fatalError(nibName) + } + for o in nonOptionalObjects { + if let menu = o as? NSMenu { + return menu + } + } + return nil + } + + private func subscribeSubreddit() { + NSWorkspace.shared.open(AppConstants.URLs.subreddit) + } +} diff --git a/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png new file mode 100644 index 00000000..71b80831 Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png new file mode 100644 index 00000000..686769c6 Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png new file mode 100644 index 00000000..58f60c3b Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png new file mode 100644 index 00000000..107599c4 Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png new file mode 100644 index 00000000..6ea91306 Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..3618dab4 --- /dev/null +++ b/Passepartout/App/macOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,63 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "AppIcon-32.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "AppIcon-64.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "AppIcon-256.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "AppIcon-512.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "AppIcon-1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Assets.xcassets/Contents.json b/Passepartout/App/macOS/Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/Passepartout/App/macOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/Contents.json b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/Contents.json new file mode 100644 index 00000000..6b337b65 --- /dev/null +++ b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/Contents.json @@ -0,0 +1,54 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "1x", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ] + }, + { + "idiom" : "universal", + "filename" : "StatusBarButtonImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarButtonImage-dark@2x.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarButtonImage@3x.png", + "scale" : "3x" + }, + { + "idiom" : "universal", + "filename" : "StatusBarButtonImage-dark@3x.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage-dark@2x.png b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage-dark@2x.png new file mode 100644 index 00000000..6832c10b Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage-dark@2x.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage-dark@3x.png b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage-dark@3x.png new file mode 100644 index 00000000..b80ff5b7 Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage-dark@3x.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage@2x.png b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage@2x.png new file mode 100644 index 00000000..2a0337ac Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage@2x.png differ diff --git a/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage@3x.png b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage@3x.png new file mode 100644 index 00000000..bd90cd93 Binary files /dev/null and b/Passepartout/App/macOS/Assets.xcassets/StatusBarButtonImage.imageset/StatusBarButtonImage@3x.png differ diff --git a/Passepartout/App/macOS/Base.lproj/Main.storyboard b/Passepartout/App/macOS/Base.lproj/Main.storyboard new file mode 100644 index 00000000..f1eddc16 --- /dev/null +++ b/Passepartout/App/macOS/Base.lproj/Main.storyboard @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Base.lproj/Preferences.storyboard b/Passepartout/App/macOS/Base.lproj/Preferences.storyboard new file mode 100644 index 00000000..06b58cb4 --- /dev/null +++ b/Passepartout/App/macOS/Base.lproj/Preferences.storyboard @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Base.lproj/Service.storyboard b/Passepartout/App/macOS/Base.lproj/Service.storyboard new file mode 100644 index 00000000..aeff6219 --- /dev/null +++ b/Passepartout/App/macOS/Base.lproj/Service.storyboard @@ -0,0 +1,1693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/CHANGELOG.md b/Passepartout/App/macOS/CHANGELOG.md new file mode 100644 index 00000000..37e7609f --- /dev/null +++ b/Passepartout/App/macOS/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 1.0.0 (2021-01-01) + +### Added + +- Launch on boot/login. +- Change active profile from menu. +- Edit credentials/profile from menu. +- Links in About dialog. + +### Changed + +- Mimic iOS app when activating a profile (Use then Enable). +- Do not autoconnect to selected location. + +### Fixed + +- Unsaved settings. +- Incorrect keychain management. +- Menu inconsistencies. + +## 1.0.0 beta 345 (2018-10-01) + +First private beta release. diff --git a/Passepartout/App/macOS/Flags.xcassets/Contents.json b/Passepartout/App/macOS/Flags.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ad.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ad.imageset/Contents.json new file mode 100644 index 00000000..a471458c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ad.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ad@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ad@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ad.imageset/ad@2x.png b/Passepartout/App/macOS/Flags.xcassets/ad.imageset/ad@2x.png new file mode 100644 index 00000000..8e579814 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ad.imageset/ad@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ad.imageset/ad@3x.png b/Passepartout/App/macOS/Flags.xcassets/ad.imageset/ad@3x.png new file mode 100644 index 00000000..47bdb6c0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ad.imageset/ad@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ae.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ae.imageset/Contents.json new file mode 100644 index 00000000..6f4b00ab --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ae.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ae@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ae@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ae.imageset/ae@2x.png b/Passepartout/App/macOS/Flags.xcassets/ae.imageset/ae@2x.png new file mode 100644 index 00000000..db2f5051 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ae.imageset/ae@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ae.imageset/ae@3x.png b/Passepartout/App/macOS/Flags.xcassets/ae.imageset/ae@3x.png new file mode 100644 index 00000000..ccff5f26 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ae.imageset/ae@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/af.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/af.imageset/Contents.json new file mode 100644 index 00000000..69e26fc4 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/af.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "af@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "af@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/af.imageset/af@2x.png b/Passepartout/App/macOS/Flags.xcassets/af.imageset/af@2x.png new file mode 100644 index 00000000..4c978a46 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/af.imageset/af@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/af.imageset/af@3x.png b/Passepartout/App/macOS/Flags.xcassets/af.imageset/af@3x.png new file mode 100644 index 00000000..7115e0f7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/af.imageset/af@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ag.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ag.imageset/Contents.json new file mode 100644 index 00000000..74d0de20 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ag.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ag@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ag@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ag.imageset/ag@2x.png b/Passepartout/App/macOS/Flags.xcassets/ag.imageset/ag@2x.png new file mode 100644 index 00000000..f9cdd01f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ag.imageset/ag@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ag.imageset/ag@3x.png b/Passepartout/App/macOS/Flags.xcassets/ag.imageset/ag@3x.png new file mode 100644 index 00000000..a810f5fb Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ag.imageset/ag@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ai.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ai.imageset/Contents.json new file mode 100644 index 00000000..c16ebd2b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ai.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ai@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ai@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ai.imageset/ai@2x.png b/Passepartout/App/macOS/Flags.xcassets/ai.imageset/ai@2x.png new file mode 100644 index 00000000..0730496f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ai.imageset/ai@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ai.imageset/ai@3x.png b/Passepartout/App/macOS/Flags.xcassets/ai.imageset/ai@3x.png new file mode 100644 index 00000000..bb2d25aa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ai.imageset/ai@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/al.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/al.imageset/Contents.json new file mode 100644 index 00000000..f895dcbd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/al.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "al@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "al@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/al.imageset/al@2x.png b/Passepartout/App/macOS/Flags.xcassets/al.imageset/al@2x.png new file mode 100644 index 00000000..27d216d8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/al.imageset/al@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/al.imageset/al@3x.png b/Passepartout/App/macOS/Flags.xcassets/al.imageset/al@3x.png new file mode 100644 index 00000000..c4c41808 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/al.imageset/al@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/am.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/am.imageset/Contents.json new file mode 100644 index 00000000..398dde0c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/am.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "am@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "am@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/am.imageset/am@2x.png b/Passepartout/App/macOS/Flags.xcassets/am.imageset/am@2x.png new file mode 100644 index 00000000..5704f242 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/am.imageset/am@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/am.imageset/am@3x.png b/Passepartout/App/macOS/Flags.xcassets/am.imageset/am@3x.png new file mode 100644 index 00000000..c33d1b5f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/am.imageset/am@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ao.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ao.imageset/Contents.json new file mode 100644 index 00000000..b1d09b75 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ao.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ao@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ao@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ao.imageset/ao@2x.png b/Passepartout/App/macOS/Flags.xcassets/ao.imageset/ao@2x.png new file mode 100644 index 00000000..51386a8d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ao.imageset/ao@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ao.imageset/ao@3x.png b/Passepartout/App/macOS/Flags.xcassets/ao.imageset/ao@3x.png new file mode 100644 index 00000000..b3370cb5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ao.imageset/ao@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/aq.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/aq.imageset/Contents.json new file mode 100644 index 00000000..f6979ace --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/aq.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "aq@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "aq@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/aq.imageset/aq@2x.png b/Passepartout/App/macOS/Flags.xcassets/aq.imageset/aq@2x.png new file mode 100644 index 00000000..f3ef9dba Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/aq.imageset/aq@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/aq.imageset/aq@3x.png b/Passepartout/App/macOS/Flags.xcassets/aq.imageset/aq@3x.png new file mode 100644 index 00000000..0b15fda0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/aq.imageset/aq@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ar.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ar.imageset/Contents.json new file mode 100644 index 00000000..540e2b7b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ar.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ar@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ar@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ar.imageset/ar@2x.png b/Passepartout/App/macOS/Flags.xcassets/ar.imageset/ar@2x.png new file mode 100644 index 00000000..c43d67f3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ar.imageset/ar@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ar.imageset/ar@3x.png b/Passepartout/App/macOS/Flags.xcassets/ar.imageset/ar@3x.png new file mode 100644 index 00000000..069e0da0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ar.imageset/ar@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/as.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/as.imageset/Contents.json new file mode 100644 index 00000000..ce2c26cc --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/as.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "as@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "as@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/as.imageset/as@2x.png b/Passepartout/App/macOS/Flags.xcassets/as.imageset/as@2x.png new file mode 100644 index 00000000..1691f39b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/as.imageset/as@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/as.imageset/as@3x.png b/Passepartout/App/macOS/Flags.xcassets/as.imageset/as@3x.png new file mode 100644 index 00000000..5cd68145 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/as.imageset/as@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/at.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/at.imageset/Contents.json new file mode 100644 index 00000000..05bdb0a5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/at.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "at@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "at@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/at.imageset/at@2x.png b/Passepartout/App/macOS/Flags.xcassets/at.imageset/at@2x.png new file mode 100644 index 00000000..4a37c7e4 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/at.imageset/at@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/at.imageset/at@3x.png b/Passepartout/App/macOS/Flags.xcassets/at.imageset/at@3x.png new file mode 100644 index 00000000..d5fe09ee Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/at.imageset/at@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/au.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/au.imageset/Contents.json new file mode 100644 index 00000000..069342c5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/au.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "au@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "au@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/au.imageset/au@2x.png b/Passepartout/App/macOS/Flags.xcassets/au.imageset/au@2x.png new file mode 100644 index 00000000..f5738884 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/au.imageset/au@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/au.imageset/au@3x.png b/Passepartout/App/macOS/Flags.xcassets/au.imageset/au@3x.png new file mode 100644 index 00000000..ad0a94e1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/au.imageset/au@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/aw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/aw.imageset/Contents.json new file mode 100644 index 00000000..08ec8e6b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/aw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "aw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "aw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/aw.imageset/aw@2x.png b/Passepartout/App/macOS/Flags.xcassets/aw.imageset/aw@2x.png new file mode 100644 index 00000000..15258516 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/aw.imageset/aw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/aw.imageset/aw@3x.png b/Passepartout/App/macOS/Flags.xcassets/aw.imageset/aw@3x.png new file mode 100644 index 00000000..7d6e1a6d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/aw.imageset/aw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ax.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ax.imageset/Contents.json new file mode 100644 index 00000000..b5ba2c77 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ax.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ax@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ax@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ax.imageset/ax@2x.png b/Passepartout/App/macOS/Flags.xcassets/ax.imageset/ax@2x.png new file mode 100644 index 00000000..f0284343 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ax.imageset/ax@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ax.imageset/ax@3x.png b/Passepartout/App/macOS/Flags.xcassets/ax.imageset/ax@3x.png new file mode 100644 index 00000000..af32efc2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ax.imageset/ax@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/az.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/az.imageset/Contents.json new file mode 100644 index 00000000..467ecc6d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/az.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "az@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "az@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/az.imageset/az@2x.png b/Passepartout/App/macOS/Flags.xcassets/az.imageset/az@2x.png new file mode 100644 index 00000000..95ef09b3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/az.imageset/az@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/az.imageset/az@3x.png b/Passepartout/App/macOS/Flags.xcassets/az.imageset/az@3x.png new file mode 100644 index 00000000..1f6a7f86 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/az.imageset/az@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ba.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ba.imageset/Contents.json new file mode 100644 index 00000000..20c2a32b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ba.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ba@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ba@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ba.imageset/ba@2x.png b/Passepartout/App/macOS/Flags.xcassets/ba.imageset/ba@2x.png new file mode 100644 index 00000000..3cff7d5a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ba.imageset/ba@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ba.imageset/ba@3x.png b/Passepartout/App/macOS/Flags.xcassets/ba.imageset/ba@3x.png new file mode 100644 index 00000000..97a8e729 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ba.imageset/ba@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bb.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bb.imageset/Contents.json new file mode 100644 index 00000000..674dc77e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bb.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bb@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bb@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bb.imageset/bb@2x.png b/Passepartout/App/macOS/Flags.xcassets/bb.imageset/bb@2x.png new file mode 100644 index 00000000..e4a4afc2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bb.imageset/bb@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bb.imageset/bb@3x.png b/Passepartout/App/macOS/Flags.xcassets/bb.imageset/bb@3x.png new file mode 100644 index 00000000..4dc72aff Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bb.imageset/bb@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bd.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bd.imageset/Contents.json new file mode 100644 index 00000000..d756d84f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bd.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bd@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bd@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bd.imageset/bd@2x.png b/Passepartout/App/macOS/Flags.xcassets/bd.imageset/bd@2x.png new file mode 100644 index 00000000..be8ec438 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bd.imageset/bd@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bd.imageset/bd@3x.png b/Passepartout/App/macOS/Flags.xcassets/bd.imageset/bd@3x.png new file mode 100644 index 00000000..fb094aef Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bd.imageset/bd@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/be.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/be.imageset/Contents.json new file mode 100644 index 00000000..1f7f4e05 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/be.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "be@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "be@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/be.imageset/be@2x.png b/Passepartout/App/macOS/Flags.xcassets/be.imageset/be@2x.png new file mode 100644 index 00000000..a427e6cc Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/be.imageset/be@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/be.imageset/be@3x.png b/Passepartout/App/macOS/Flags.xcassets/be.imageset/be@3x.png new file mode 100644 index 00000000..9e026097 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/be.imageset/be@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bf.imageset/Contents.json new file mode 100644 index 00000000..9faa797e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bf.imageset/bf@2x.png b/Passepartout/App/macOS/Flags.xcassets/bf.imageset/bf@2x.png new file mode 100644 index 00000000..cc51e485 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bf.imageset/bf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bf.imageset/bf@3x.png b/Passepartout/App/macOS/Flags.xcassets/bf.imageset/bf@3x.png new file mode 100644 index 00000000..48383357 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bf.imageset/bf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bg.imageset/Contents.json new file mode 100644 index 00000000..6ed3e15d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bg.imageset/bg@2x.png b/Passepartout/App/macOS/Flags.xcassets/bg.imageset/bg@2x.png new file mode 100644 index 00000000..3aaad404 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bg.imageset/bg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bg.imageset/bg@3x.png b/Passepartout/App/macOS/Flags.xcassets/bg.imageset/bg@3x.png new file mode 100644 index 00000000..5d511c11 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bg.imageset/bg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bh.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bh.imageset/Contents.json new file mode 100644 index 00000000..0e554092 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bh@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bh@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bh.imageset/bh@2x.png b/Passepartout/App/macOS/Flags.xcassets/bh.imageset/bh@2x.png new file mode 100644 index 00000000..8a9c1391 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bh.imageset/bh@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bh.imageset/bh@3x.png b/Passepartout/App/macOS/Flags.xcassets/bh.imageset/bh@3x.png new file mode 100644 index 00000000..8ee86495 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bh.imageset/bh@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bi.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bi.imageset/Contents.json new file mode 100644 index 00000000..5367f5f4 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bi.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bi@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bi@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bi.imageset/bi@2x.png b/Passepartout/App/macOS/Flags.xcassets/bi.imageset/bi@2x.png new file mode 100644 index 00000000..d13b54af Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bi.imageset/bi@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bi.imageset/bi@3x.png b/Passepartout/App/macOS/Flags.xcassets/bi.imageset/bi@3x.png new file mode 100644 index 00000000..5ba15862 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bi.imageset/bi@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bj.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bj.imageset/Contents.json new file mode 100644 index 00000000..d3d37453 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bj.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bj@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bj@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bj.imageset/bj@2x.png b/Passepartout/App/macOS/Flags.xcassets/bj.imageset/bj@2x.png new file mode 100644 index 00000000..854cc8e5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bj.imageset/bj@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bj.imageset/bj@3x.png b/Passepartout/App/macOS/Flags.xcassets/bj.imageset/bj@3x.png new file mode 100644 index 00000000..8330f3b7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bj.imageset/bj@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bl.imageset/Contents.json new file mode 100644 index 00000000..59cca760 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bl.imageset/bl@2x.png b/Passepartout/App/macOS/Flags.xcassets/bl.imageset/bl@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bl.imageset/bl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bl.imageset/bl@3x.png b/Passepartout/App/macOS/Flags.xcassets/bl.imageset/bl@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bl.imageset/bl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bm.imageset/Contents.json new file mode 100644 index 00000000..2435e7ed --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bm.imageset/bm@2x.png b/Passepartout/App/macOS/Flags.xcassets/bm.imageset/bm@2x.png new file mode 100644 index 00000000..7d99c3ce Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bm.imageset/bm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bm.imageset/bm@3x.png b/Passepartout/App/macOS/Flags.xcassets/bm.imageset/bm@3x.png new file mode 100644 index 00000000..32ced602 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bm.imageset/bm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bn.imageset/Contents.json new file mode 100644 index 00000000..c6dbd79a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bn.imageset/bn@2x.png b/Passepartout/App/macOS/Flags.xcassets/bn.imageset/bn@2x.png new file mode 100644 index 00000000..07e87ec5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bn.imageset/bn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bn.imageset/bn@3x.png b/Passepartout/App/macOS/Flags.xcassets/bn.imageset/bn@3x.png new file mode 100644 index 00000000..ad63e601 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bn.imageset/bn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bo.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bo.imageset/Contents.json new file mode 100644 index 00000000..2c4e6dfa --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bo.imageset/bo@2x.png b/Passepartout/App/macOS/Flags.xcassets/bo.imageset/bo@2x.png new file mode 100644 index 00000000..e2136c1d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bo.imageset/bo@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bo.imageset/bo@3x.png b/Passepartout/App/macOS/Flags.xcassets/bo.imageset/bo@3x.png new file mode 100644 index 00000000..22bb99dc Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bo.imageset/bo@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bq.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bq.imageset/Contents.json new file mode 100644 index 00000000..8c361eb7 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bq.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bq@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bq@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bq.imageset/bq@2x.png b/Passepartout/App/macOS/Flags.xcassets/bq.imageset/bq@2x.png new file mode 100644 index 00000000..f1b7efd5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bq.imageset/bq@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bq.imageset/bq@3x.png b/Passepartout/App/macOS/Flags.xcassets/bq.imageset/bq@3x.png new file mode 100644 index 00000000..333a1320 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bq.imageset/bq@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/br.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/br.imageset/Contents.json new file mode 100644 index 00000000..3eb3ddb8 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/br.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "br@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "br@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/br.imageset/br@2x.png b/Passepartout/App/macOS/Flags.xcassets/br.imageset/br@2x.png new file mode 100644 index 00000000..02e55517 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/br.imageset/br@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/br.imageset/br@3x.png b/Passepartout/App/macOS/Flags.xcassets/br.imageset/br@3x.png new file mode 100644 index 00000000..f2207dfc Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/br.imageset/br@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bs.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bs.imageset/Contents.json new file mode 100644 index 00000000..c28f5fec --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bs.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bs@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bs@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bs.imageset/bs@2x.png b/Passepartout/App/macOS/Flags.xcassets/bs.imageset/bs@2x.png new file mode 100644 index 00000000..5ce92477 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bs.imageset/bs@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bs.imageset/bs@3x.png b/Passepartout/App/macOS/Flags.xcassets/bs.imageset/bs@3x.png new file mode 100644 index 00000000..090f7264 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bs.imageset/bs@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bt.imageset/Contents.json new file mode 100644 index 00000000..59623c89 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bt.imageset/bt@2x.png b/Passepartout/App/macOS/Flags.xcassets/bt.imageset/bt@2x.png new file mode 100644 index 00000000..b24dd866 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bt.imageset/bt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bt.imageset/bt@3x.png b/Passepartout/App/macOS/Flags.xcassets/bt.imageset/bt@3x.png new file mode 100644 index 00000000..4d6f6b43 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bt.imageset/bt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bv.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bv.imageset/Contents.json new file mode 100644 index 00000000..69d8e0bd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bv.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bv@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bv@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bv.imageset/bv@2x.png b/Passepartout/App/macOS/Flags.xcassets/bv.imageset/bv@2x.png new file mode 100644 index 00000000..311bc00f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bv.imageset/bv@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bv.imageset/bv@3x.png b/Passepartout/App/macOS/Flags.xcassets/bv.imageset/bv@3x.png new file mode 100644 index 00000000..28b960a3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bv.imageset/bv@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bw.imageset/Contents.json new file mode 100644 index 00000000..aa3d06de --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bw.imageset/bw@2x.png b/Passepartout/App/macOS/Flags.xcassets/bw.imageset/bw@2x.png new file mode 100644 index 00000000..66114c67 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bw.imageset/bw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bw.imageset/bw@3x.png b/Passepartout/App/macOS/Flags.xcassets/bw.imageset/bw@3x.png new file mode 100644 index 00000000..032e483a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bw.imageset/bw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/by.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/by.imageset/Contents.json new file mode 100644 index 00000000..f7b13fc6 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/by.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "by@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "by@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/by.imageset/by@2x.png b/Passepartout/App/macOS/Flags.xcassets/by.imageset/by@2x.png new file mode 100644 index 00000000..3b09bc47 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/by.imageset/by@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/by.imageset/by@3x.png b/Passepartout/App/macOS/Flags.xcassets/by.imageset/by@3x.png new file mode 100644 index 00000000..ac56a118 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/by.imageset/by@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/bz.imageset/Contents.json new file mode 100644 index 00000000..35c628e4 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/bz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/bz.imageset/bz@2x.png b/Passepartout/App/macOS/Flags.xcassets/bz.imageset/bz@2x.png new file mode 100644 index 00000000..db05dfc9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bz.imageset/bz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/bz.imageset/bz@3x.png b/Passepartout/App/macOS/Flags.xcassets/bz.imageset/bz@3x.png new file mode 100644 index 00000000..81824caa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/bz.imageset/bz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ca.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ca.imageset/Contents.json new file mode 100644 index 00000000..9090fb87 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ca.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ca@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ca@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ca.imageset/ca@2x.png b/Passepartout/App/macOS/Flags.xcassets/ca.imageset/ca@2x.png new file mode 100644 index 00000000..5b3423c4 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ca.imageset/ca@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ca.imageset/ca@3x.png b/Passepartout/App/macOS/Flags.xcassets/ca.imageset/ca@3x.png new file mode 100644 index 00000000..938af2e0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ca.imageset/ca@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cc.imageset/Contents.json new file mode 100644 index 00000000..4f10c903 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cc.imageset/cc@2x.png b/Passepartout/App/macOS/Flags.xcassets/cc.imageset/cc@2x.png new file mode 100644 index 00000000..70e652a1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cc.imageset/cc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cc.imageset/cc@3x.png b/Passepartout/App/macOS/Flags.xcassets/cc.imageset/cc@3x.png new file mode 100644 index 00000000..738e29a8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cc.imageset/cc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cd.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cd.imageset/Contents.json new file mode 100644 index 00000000..3f149671 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cd.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cd@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cd@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cd.imageset/cd@2x.png b/Passepartout/App/macOS/Flags.xcassets/cd.imageset/cd@2x.png new file mode 100644 index 00000000..228e8eda Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cd.imageset/cd@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cd.imageset/cd@3x.png b/Passepartout/App/macOS/Flags.xcassets/cd.imageset/cd@3x.png new file mode 100644 index 00000000..7326d42e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cd.imageset/cd@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cf.imageset/Contents.json new file mode 100644 index 00000000..b7a75bdc --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cf.imageset/cf@2x.png b/Passepartout/App/macOS/Flags.xcassets/cf.imageset/cf@2x.png new file mode 100644 index 00000000..e741d126 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cf.imageset/cf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cf.imageset/cf@3x.png b/Passepartout/App/macOS/Flags.xcassets/cf.imageset/cf@3x.png new file mode 100644 index 00000000..0fd84a90 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cf.imageset/cf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cg.imageset/Contents.json new file mode 100644 index 00000000..3ad6e3e3 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cg.imageset/cg@2x.png b/Passepartout/App/macOS/Flags.xcassets/cg.imageset/cg@2x.png new file mode 100644 index 00000000..0e219d6d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cg.imageset/cg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cg.imageset/cg@3x.png b/Passepartout/App/macOS/Flags.xcassets/cg.imageset/cg@3x.png new file mode 100644 index 00000000..71e7524d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cg.imageset/cg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ch.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ch.imageset/Contents.json new file mode 100644 index 00000000..1d5681ce --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ch.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ch@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ch@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ch.imageset/ch@2x.png b/Passepartout/App/macOS/Flags.xcassets/ch.imageset/ch@2x.png new file mode 100644 index 00000000..811c7429 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ch.imageset/ch@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ch.imageset/ch@3x.png b/Passepartout/App/macOS/Flags.xcassets/ch.imageset/ch@3x.png new file mode 100644 index 00000000..01066f88 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ch.imageset/ch@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ci.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ci.imageset/Contents.json new file mode 100644 index 00000000..4ec1ef56 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ci.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ci@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ci@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ci.imageset/ci@2x.png b/Passepartout/App/macOS/Flags.xcassets/ci.imageset/ci@2x.png new file mode 100644 index 00000000..54025ba9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ci.imageset/ci@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ci.imageset/ci@3x.png b/Passepartout/App/macOS/Flags.xcassets/ci.imageset/ci@3x.png new file mode 100644 index 00000000..e3f19908 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ci.imageset/ci@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ck.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ck.imageset/Contents.json new file mode 100644 index 00000000..4e637127 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ck.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ck@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ck@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ck.imageset/ck@2x.png b/Passepartout/App/macOS/Flags.xcassets/ck.imageset/ck@2x.png new file mode 100644 index 00000000..1543a11d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ck.imageset/ck@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ck.imageset/ck@3x.png b/Passepartout/App/macOS/Flags.xcassets/ck.imageset/ck@3x.png new file mode 100644 index 00000000..17f9f171 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ck.imageset/ck@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cl.imageset/Contents.json new file mode 100644 index 00000000..f329c863 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cl.imageset/cl@2x.png b/Passepartout/App/macOS/Flags.xcassets/cl.imageset/cl@2x.png new file mode 100644 index 00000000..636adc7d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cl.imageset/cl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cl.imageset/cl@3x.png b/Passepartout/App/macOS/Flags.xcassets/cl.imageset/cl@3x.png new file mode 100644 index 00000000..e91a5bba Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cl.imageset/cl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cm.imageset/Contents.json new file mode 100644 index 00000000..40a18873 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cm.imageset/cm@2x.png b/Passepartout/App/macOS/Flags.xcassets/cm.imageset/cm@2x.png new file mode 100644 index 00000000..f4e50452 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cm.imageset/cm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cm.imageset/cm@3x.png b/Passepartout/App/macOS/Flags.xcassets/cm.imageset/cm@3x.png new file mode 100644 index 00000000..44c17d62 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cm.imageset/cm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cn.imageset/Contents.json new file mode 100644 index 00000000..ca204426 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cn.imageset/cn@2x.png b/Passepartout/App/macOS/Flags.xcassets/cn.imageset/cn@2x.png new file mode 100644 index 00000000..420508ba Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cn.imageset/cn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cn.imageset/cn@3x.png b/Passepartout/App/macOS/Flags.xcassets/cn.imageset/cn@3x.png new file mode 100644 index 00000000..9d402958 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cn.imageset/cn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/co.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/co.imageset/Contents.json new file mode 100644 index 00000000..e6ead9c7 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/co.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "co@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "co@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/co.imageset/co@2x.png b/Passepartout/App/macOS/Flags.xcassets/co.imageset/co@2x.png new file mode 100644 index 00000000..37e680f8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/co.imageset/co@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/co.imageset/co@3x.png b/Passepartout/App/macOS/Flags.xcassets/co.imageset/co@3x.png new file mode 100644 index 00000000..068e4ef2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/co.imageset/co@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cr.imageset/Contents.json new file mode 100644 index 00000000..b86ea704 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cr.imageset/cr@2x.png b/Passepartout/App/macOS/Flags.xcassets/cr.imageset/cr@2x.png new file mode 100644 index 00000000..ec31ed89 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cr.imageset/cr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cr.imageset/cr@3x.png b/Passepartout/App/macOS/Flags.xcassets/cr.imageset/cr@3x.png new file mode 100644 index 00000000..f2fefdbd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cr.imageset/cr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cu.imageset/Contents.json new file mode 100644 index 00000000..cd022b9a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cu.imageset/cu@2x.png b/Passepartout/App/macOS/Flags.xcassets/cu.imageset/cu@2x.png new file mode 100644 index 00000000..f259ed3f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cu.imageset/cu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cu.imageset/cu@3x.png b/Passepartout/App/macOS/Flags.xcassets/cu.imageset/cu@3x.png new file mode 100644 index 00000000..cb228b94 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cu.imageset/cu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cv.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cv.imageset/Contents.json new file mode 100644 index 00000000..b0c64157 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cv.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cv@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cv@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cv.imageset/cv@2x.png b/Passepartout/App/macOS/Flags.xcassets/cv.imageset/cv@2x.png new file mode 100644 index 00000000..b78cb6c2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cv.imageset/cv@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cv.imageset/cv@3x.png b/Passepartout/App/macOS/Flags.xcassets/cv.imageset/cv@3x.png new file mode 100644 index 00000000..8b1db429 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cv.imageset/cv@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cw.imageset/Contents.json new file mode 100644 index 00000000..4f8897e9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cw.imageset/cw@2x.png b/Passepartout/App/macOS/Flags.xcassets/cw.imageset/cw@2x.png new file mode 100644 index 00000000..975bd666 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cw.imageset/cw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cw.imageset/cw@3x.png b/Passepartout/App/macOS/Flags.xcassets/cw.imageset/cw@3x.png new file mode 100644 index 00000000..ec84960f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cw.imageset/cw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cx.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cx.imageset/Contents.json new file mode 100644 index 00000000..6074dd4c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cx.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cx@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cx@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cx.imageset/cx@2x.png b/Passepartout/App/macOS/Flags.xcassets/cx.imageset/cx@2x.png new file mode 100644 index 00000000..cd59e2b7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cx.imageset/cx@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cx.imageset/cx@3x.png b/Passepartout/App/macOS/Flags.xcassets/cx.imageset/cx@3x.png new file mode 100644 index 00000000..2cf589d2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cx.imageset/cx@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cy.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cy.imageset/Contents.json new file mode 100644 index 00000000..7ce08eca --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cy.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cy@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cy.imageset/cy@2x.png b/Passepartout/App/macOS/Flags.xcassets/cy.imageset/cy@2x.png new file mode 100644 index 00000000..95d07a79 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cy.imageset/cy@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cy.imageset/cy@3x.png b/Passepartout/App/macOS/Flags.xcassets/cy.imageset/cy@3x.png new file mode 100644 index 00000000..c12a80dd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cy.imageset/cy@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/cz.imageset/Contents.json new file mode 100644 index 00000000..c7326443 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/cz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "cz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "cz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/cz.imageset/cz@2x.png b/Passepartout/App/macOS/Flags.xcassets/cz.imageset/cz@2x.png new file mode 100644 index 00000000..2a0b1d30 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cz.imageset/cz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/cz.imageset/cz@3x.png b/Passepartout/App/macOS/Flags.xcassets/cz.imageset/cz@3x.png new file mode 100644 index 00000000..22f0d03e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/cz.imageset/cz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/de.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/de.imageset/Contents.json new file mode 100644 index 00000000..a6648ba1 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/de.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "de@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "de@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/de.imageset/de@2x.png b/Passepartout/App/macOS/Flags.xcassets/de.imageset/de@2x.png new file mode 100644 index 00000000..8a52fd2a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/de.imageset/de@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/de.imageset/de@3x.png b/Passepartout/App/macOS/Flags.xcassets/de.imageset/de@3x.png new file mode 100644 index 00000000..f8cfea27 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/de.imageset/de@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dj.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/dj.imageset/Contents.json new file mode 100644 index 00000000..64809945 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/dj.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "dj@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "dj@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/dj.imageset/dj@2x.png b/Passepartout/App/macOS/Flags.xcassets/dj.imageset/dj@2x.png new file mode 100644 index 00000000..ba77415d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dj.imageset/dj@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dj.imageset/dj@3x.png b/Passepartout/App/macOS/Flags.xcassets/dj.imageset/dj@3x.png new file mode 100644 index 00000000..14a2e040 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dj.imageset/dj@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/dk.imageset/Contents.json new file mode 100644 index 00000000..1465b615 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/dk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "dk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "dk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/dk.imageset/dk@2x.png b/Passepartout/App/macOS/Flags.xcassets/dk.imageset/dk@2x.png new file mode 100644 index 00000000..0b8f33d2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dk.imageset/dk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dk.imageset/dk@3x.png b/Passepartout/App/macOS/Flags.xcassets/dk.imageset/dk@3x.png new file mode 100644 index 00000000..e4add9d7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dk.imageset/dk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/dm.imageset/Contents.json new file mode 100644 index 00000000..c96c4669 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/dm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "dm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "dm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/dm.imageset/dm@2x.png b/Passepartout/App/macOS/Flags.xcassets/dm.imageset/dm@2x.png new file mode 100644 index 00000000..159144d1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dm.imageset/dm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dm.imageset/dm@3x.png b/Passepartout/App/macOS/Flags.xcassets/dm.imageset/dm@3x.png new file mode 100644 index 00000000..3fc36d7d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dm.imageset/dm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/do.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/do.imageset/Contents.json new file mode 100644 index 00000000..bd6c28e6 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/do.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "do@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "do@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/do.imageset/do@2x.png b/Passepartout/App/macOS/Flags.xcassets/do.imageset/do@2x.png new file mode 100644 index 00000000..02f536d7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/do.imageset/do@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/do.imageset/do@3x.png b/Passepartout/App/macOS/Flags.xcassets/do.imageset/do@3x.png new file mode 100644 index 00000000..36531e4f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/do.imageset/do@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/dz.imageset/Contents.json new file mode 100644 index 00000000..431e938c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/dz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "dz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "dz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/dz.imageset/dz@2x.png b/Passepartout/App/macOS/Flags.xcassets/dz.imageset/dz@2x.png new file mode 100644 index 00000000..7700ce96 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dz.imageset/dz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/dz.imageset/dz@3x.png b/Passepartout/App/macOS/Flags.xcassets/dz.imageset/dz@3x.png new file mode 100644 index 00000000..9e679fa9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/dz.imageset/dz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ec.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ec.imageset/Contents.json new file mode 100644 index 00000000..33c89f9f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ec.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ec@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ec@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ec.imageset/ec@2x.png b/Passepartout/App/macOS/Flags.xcassets/ec.imageset/ec@2x.png new file mode 100644 index 00000000..5659dada Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ec.imageset/ec@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ec.imageset/ec@3x.png b/Passepartout/App/macOS/Flags.xcassets/ec.imageset/ec@3x.png new file mode 100644 index 00000000..7bfe0528 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ec.imageset/ec@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ee.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ee.imageset/Contents.json new file mode 100644 index 00000000..e96a6b27 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ee.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ee@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ee@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ee.imageset/ee@2x.png b/Passepartout/App/macOS/Flags.xcassets/ee.imageset/ee@2x.png new file mode 100644 index 00000000..d5c8765b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ee.imageset/ee@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ee.imageset/ee@3x.png b/Passepartout/App/macOS/Flags.xcassets/ee.imageset/ee@3x.png new file mode 100644 index 00000000..5aff2cb2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ee.imageset/ee@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/eg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/eg.imageset/Contents.json new file mode 100644 index 00000000..a0639c9c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/eg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "eg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "eg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/eg.imageset/eg@2x.png b/Passepartout/App/macOS/Flags.xcassets/eg.imageset/eg@2x.png new file mode 100644 index 00000000..5768de7e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/eg.imageset/eg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/eg.imageset/eg@3x.png b/Passepartout/App/macOS/Flags.xcassets/eg.imageset/eg@3x.png new file mode 100644 index 00000000..084665d1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/eg.imageset/eg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/eh.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/eh.imageset/Contents.json new file mode 100644 index 00000000..6f4e2f95 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/eh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "eh@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "eh@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/eh.imageset/eh@2x.png b/Passepartout/App/macOS/Flags.xcassets/eh.imageset/eh@2x.png new file mode 100644 index 00000000..e7fffa44 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/eh.imageset/eh@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/eh.imageset/eh@3x.png b/Passepartout/App/macOS/Flags.xcassets/eh.imageset/eh@3x.png new file mode 100644 index 00000000..16c52ae6 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/eh.imageset/eh@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/er.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/er.imageset/Contents.json new file mode 100644 index 00000000..555b3cbd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/er.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "er@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "er@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/er.imageset/er@2x.png b/Passepartout/App/macOS/Flags.xcassets/er.imageset/er@2x.png new file mode 100644 index 00000000..7297a1c5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/er.imageset/er@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/er.imageset/er@3x.png b/Passepartout/App/macOS/Flags.xcassets/er.imageset/er@3x.png new file mode 100644 index 00000000..6b32648e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/er.imageset/er@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/Contents.json new file mode 100644 index 00000000..8db5b0ae --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "es-ct@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "es-ct@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png b/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png new file mode 100644 index 00000000..09abf984 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/es-ct@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png b/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png new file mode 100644 index 00000000..e18fffbe Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/es-ct.imageset/es-ct@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/es.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/es.imageset/Contents.json new file mode 100644 index 00000000..b70dcd3f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/es.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "es@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "es@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/es.imageset/es@2x.png b/Passepartout/App/macOS/Flags.xcassets/es.imageset/es@2x.png new file mode 100644 index 00000000..2fca4f35 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/es.imageset/es@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/es.imageset/es@3x.png b/Passepartout/App/macOS/Flags.xcassets/es.imageset/es@3x.png new file mode 100644 index 00000000..94af2908 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/es.imageset/es@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/et.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/et.imageset/Contents.json new file mode 100644 index 00000000..45f68159 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/et.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "et@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "et@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/et.imageset/et@2x.png b/Passepartout/App/macOS/Flags.xcassets/et.imageset/et@2x.png new file mode 100644 index 00000000..c064bb8f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/et.imageset/et@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/et.imageset/et@3x.png b/Passepartout/App/macOS/Flags.xcassets/et.imageset/et@3x.png new file mode 100644 index 00000000..28ae5536 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/et.imageset/et@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/eu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/eu.imageset/Contents.json new file mode 100644 index 00000000..70ec8ab9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/eu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "eu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "eu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/eu.imageset/eu@2x.png b/Passepartout/App/macOS/Flags.xcassets/eu.imageset/eu@2x.png new file mode 100644 index 00000000..e747620e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/eu.imageset/eu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/eu.imageset/eu@3x.png b/Passepartout/App/macOS/Flags.xcassets/eu.imageset/eu@3x.png new file mode 100644 index 00000000..1e13b0dd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/eu.imageset/eu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fi.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/fi.imageset/Contents.json new file mode 100644 index 00000000..a84ff1ca --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/fi.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "fi@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "fi@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/fi.imageset/fi@2x.png b/Passepartout/App/macOS/Flags.xcassets/fi.imageset/fi@2x.png new file mode 100644 index 00000000..99ba758f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fi.imageset/fi@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fi.imageset/fi@3x.png b/Passepartout/App/macOS/Flags.xcassets/fi.imageset/fi@3x.png new file mode 100644 index 00000000..ca9ab2a0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fi.imageset/fi@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fj.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/fj.imageset/Contents.json new file mode 100644 index 00000000..d36f15ab --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/fj.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "fj@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "fj@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/fj.imageset/fj@2x.png b/Passepartout/App/macOS/Flags.xcassets/fj.imageset/fj@2x.png new file mode 100644 index 00000000..d080bb48 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fj.imageset/fj@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fj.imageset/fj@3x.png b/Passepartout/App/macOS/Flags.xcassets/fj.imageset/fj@3x.png new file mode 100644 index 00000000..3584ad32 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fj.imageset/fj@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/fk.imageset/Contents.json new file mode 100644 index 00000000..5c0391b1 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/fk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "fk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "fk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/fk.imageset/fk@2x.png b/Passepartout/App/macOS/Flags.xcassets/fk.imageset/fk@2x.png new file mode 100644 index 00000000..fdea77ca Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fk.imageset/fk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fk.imageset/fk@3x.png b/Passepartout/App/macOS/Flags.xcassets/fk.imageset/fk@3x.png new file mode 100644 index 00000000..10316169 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fk.imageset/fk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/fm.imageset/Contents.json new file mode 100644 index 00000000..4f6defce --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/fm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "fm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "fm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/fm.imageset/fm@2x.png b/Passepartout/App/macOS/Flags.xcassets/fm.imageset/fm@2x.png new file mode 100644 index 00000000..2a4a7aad Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fm.imageset/fm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fm.imageset/fm@3x.png b/Passepartout/App/macOS/Flags.xcassets/fm.imageset/fm@3x.png new file mode 100644 index 00000000..a47c9917 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fm.imageset/fm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fo.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/fo.imageset/Contents.json new file mode 100644 index 00000000..fd4e7136 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/fo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "fo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "fo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/fo.imageset/fo@2x.png b/Passepartout/App/macOS/Flags.xcassets/fo.imageset/fo@2x.png new file mode 100644 index 00000000..bd58b6ba Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fo.imageset/fo@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fo.imageset/fo@3x.png b/Passepartout/App/macOS/Flags.xcassets/fo.imageset/fo@3x.png new file mode 100644 index 00000000..28b382af Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fo.imageset/fo@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/fr.imageset/Contents.json new file mode 100644 index 00000000..e8a2d126 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/fr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "fr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "fr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/fr.imageset/fr@2x.png b/Passepartout/App/macOS/Flags.xcassets/fr.imageset/fr@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fr.imageset/fr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/fr.imageset/fr@3x.png b/Passepartout/App/macOS/Flags.xcassets/fr.imageset/fr@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/fr.imageset/fr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ga.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ga.imageset/Contents.json new file mode 100644 index 00000000..f8b037ff --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ga.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ga@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ga@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ga.imageset/ga@2x.png b/Passepartout/App/macOS/Flags.xcassets/ga.imageset/ga@2x.png new file mode 100644 index 00000000..ede5241b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ga.imageset/ga@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ga.imageset/ga@3x.png b/Passepartout/App/macOS/Flags.xcassets/ga.imageset/ga@3x.png new file mode 100644 index 00000000..96ff3a3f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ga.imageset/ga@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/Contents.json new file mode 100644 index 00000000..ebac6de7 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gb-eng@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gb-eng@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png b/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png new file mode 100644 index 00000000..ae4091ef Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/gb-eng@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png b/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png new file mode 100644 index 00000000..f8537799 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-eng.imageset/gb-eng@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/Contents.json new file mode 100644 index 00000000..06765425 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gb-nir@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gb-nir@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png b/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png new file mode 100644 index 00000000..d4aa5abd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/gb-nir@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png b/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png new file mode 100644 index 00000000..31a7955e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-nir.imageset/gb-nir@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/Contents.json new file mode 100644 index 00000000..a2d9bac3 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gb-sct@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gb-sct@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png b/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png new file mode 100644 index 00000000..cd5ae41d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/gb-sct@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png b/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png new file mode 100644 index 00000000..634f245e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-sct.imageset/gb-sct@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/Contents.json new file mode 100644 index 00000000..432f48ff --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gb-wls@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gb-wls@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png b/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png new file mode 100644 index 00000000..bcd336f0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/gb-wls@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png b/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png new file mode 100644 index 00000000..04ac0760 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb-wls.imageset/gb-wls@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gb.imageset/Contents.json new file mode 100644 index 00000000..c4e27395 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gb.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gb@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gb@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gb.imageset/gb@2x.png b/Passepartout/App/macOS/Flags.xcassets/gb.imageset/gb@2x.png new file mode 100644 index 00000000..097220d6 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb.imageset/gb@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gb.imageset/gb@3x.png b/Passepartout/App/macOS/Flags.xcassets/gb.imageset/gb@3x.png new file mode 100644 index 00000000..0e23883b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gb.imageset/gb@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gd.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gd.imageset/Contents.json new file mode 100644 index 00000000..3fd68edf --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gd.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gd@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gd@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gd.imageset/gd@2x.png b/Passepartout/App/macOS/Flags.xcassets/gd.imageset/gd@2x.png new file mode 100644 index 00000000..1d66a587 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gd.imageset/gd@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gd.imageset/gd@3x.png b/Passepartout/App/macOS/Flags.xcassets/gd.imageset/gd@3x.png new file mode 100644 index 00000000..e0bfdd2e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gd.imageset/gd@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ge.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ge.imageset/Contents.json new file mode 100644 index 00000000..ca3dbb2f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ge.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ge@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ge@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ge.imageset/ge@2x.png b/Passepartout/App/macOS/Flags.xcassets/ge.imageset/ge@2x.png new file mode 100644 index 00000000..80960fc5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ge.imageset/ge@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ge.imageset/ge@3x.png b/Passepartout/App/macOS/Flags.xcassets/ge.imageset/ge@3x.png new file mode 100644 index 00000000..110e1561 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ge.imageset/ge@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gf.imageset/Contents.json new file mode 100644 index 00000000..70c3eb67 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gf.imageset/gf@2x.png b/Passepartout/App/macOS/Flags.xcassets/gf.imageset/gf@2x.png new file mode 100644 index 00000000..7b23bf42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gf.imageset/gf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gf.imageset/gf@3x.png b/Passepartout/App/macOS/Flags.xcassets/gf.imageset/gf@3x.png new file mode 100644 index 00000000..1cb6e71e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gf.imageset/gf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gg.imageset/Contents.json new file mode 100644 index 00000000..fe3ea1a1 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gg.imageset/gg@2x.png b/Passepartout/App/macOS/Flags.xcassets/gg.imageset/gg@2x.png new file mode 100644 index 00000000..146322fc Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gg.imageset/gg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gg.imageset/gg@3x.png b/Passepartout/App/macOS/Flags.xcassets/gg.imageset/gg@3x.png new file mode 100644 index 00000000..d87b6b52 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gg.imageset/gg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gh.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gh.imageset/Contents.json new file mode 100644 index 00000000..d15231e6 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gh@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gh@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gh.imageset/gh@2x.png b/Passepartout/App/macOS/Flags.xcassets/gh.imageset/gh@2x.png new file mode 100644 index 00000000..a6f7bc00 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gh.imageset/gh@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gh.imageset/gh@3x.png b/Passepartout/App/macOS/Flags.xcassets/gh.imageset/gh@3x.png new file mode 100644 index 00000000..a8462728 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gh.imageset/gh@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gi.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gi.imageset/Contents.json new file mode 100644 index 00000000..75faa11d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gi.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gi@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gi@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gi.imageset/gi@2x.png b/Passepartout/App/macOS/Flags.xcassets/gi.imageset/gi@2x.png new file mode 100644 index 00000000..949bd742 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gi.imageset/gi@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gi.imageset/gi@3x.png b/Passepartout/App/macOS/Flags.xcassets/gi.imageset/gi@3x.png new file mode 100644 index 00000000..9ed943f1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gi.imageset/gi@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gl.imageset/Contents.json new file mode 100644 index 00000000..399dacbc --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gl.imageset/gl@2x.png b/Passepartout/App/macOS/Flags.xcassets/gl.imageset/gl@2x.png new file mode 100644 index 00000000..1172ffd8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gl.imageset/gl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gl.imageset/gl@3x.png b/Passepartout/App/macOS/Flags.xcassets/gl.imageset/gl@3x.png new file mode 100644 index 00000000..f168e134 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gl.imageset/gl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gm.imageset/Contents.json new file mode 100644 index 00000000..eb99bd62 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gm.imageset/gm@2x.png b/Passepartout/App/macOS/Flags.xcassets/gm.imageset/gm@2x.png new file mode 100644 index 00000000..0b89cf17 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gm.imageset/gm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gm.imageset/gm@3x.png b/Passepartout/App/macOS/Flags.xcassets/gm.imageset/gm@3x.png new file mode 100644 index 00000000..9ab11e75 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gm.imageset/gm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gn.imageset/Contents.json new file mode 100644 index 00000000..09710fc5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gn.imageset/gn@2x.png b/Passepartout/App/macOS/Flags.xcassets/gn.imageset/gn@2x.png new file mode 100644 index 00000000..88f1362d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gn.imageset/gn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gn.imageset/gn@3x.png b/Passepartout/App/macOS/Flags.xcassets/gn.imageset/gn@3x.png new file mode 100644 index 00000000..797ab9c5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gn.imageset/gn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gp.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gp.imageset/Contents.json new file mode 100644 index 00000000..e31b6f54 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gp.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gp@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gp@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gp.imageset/gp@2x.png b/Passepartout/App/macOS/Flags.xcassets/gp.imageset/gp@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gp.imageset/gp@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gp.imageset/gp@3x.png b/Passepartout/App/macOS/Flags.xcassets/gp.imageset/gp@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gp.imageset/gp@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gq.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gq.imageset/Contents.json new file mode 100644 index 00000000..311477f7 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gq.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gq@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gq@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gq.imageset/gq@2x.png b/Passepartout/App/macOS/Flags.xcassets/gq.imageset/gq@2x.png new file mode 100644 index 00000000..49e1ff8a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gq.imageset/gq@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gq.imageset/gq@3x.png b/Passepartout/App/macOS/Flags.xcassets/gq.imageset/gq@3x.png new file mode 100644 index 00000000..9469ed72 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gq.imageset/gq@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gr.imageset/Contents.json new file mode 100644 index 00000000..346cdd61 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gr.imageset/gr@2x.png b/Passepartout/App/macOS/Flags.xcassets/gr.imageset/gr@2x.png new file mode 100644 index 00000000..0c5e7314 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gr.imageset/gr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gr.imageset/gr@3x.png b/Passepartout/App/macOS/Flags.xcassets/gr.imageset/gr@3x.png new file mode 100644 index 00000000..b879dd8d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gr.imageset/gr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gs.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gs.imageset/Contents.json new file mode 100644 index 00000000..5845c325 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gs.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gs@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gs@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gs.imageset/gs@2x.png b/Passepartout/App/macOS/Flags.xcassets/gs.imageset/gs@2x.png new file mode 100644 index 00000000..849c97ef Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gs.imageset/gs@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gs.imageset/gs@3x.png b/Passepartout/App/macOS/Flags.xcassets/gs.imageset/gs@3x.png new file mode 100644 index 00000000..1884af4f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gs.imageset/gs@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gt.imageset/Contents.json new file mode 100644 index 00000000..3984f3a1 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gt.imageset/gt@2x.png b/Passepartout/App/macOS/Flags.xcassets/gt.imageset/gt@2x.png new file mode 100644 index 00000000..787d9b3c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gt.imageset/gt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gt.imageset/gt@3x.png b/Passepartout/App/macOS/Flags.xcassets/gt.imageset/gt@3x.png new file mode 100644 index 00000000..d3d3a4f9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gt.imageset/gt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gu.imageset/Contents.json new file mode 100644 index 00000000..0f5f389a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gu.imageset/gu@2x.png b/Passepartout/App/macOS/Flags.xcassets/gu.imageset/gu@2x.png new file mode 100644 index 00000000..a63dfc15 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gu.imageset/gu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gu.imageset/gu@3x.png b/Passepartout/App/macOS/Flags.xcassets/gu.imageset/gu@3x.png new file mode 100644 index 00000000..f3232c3b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gu.imageset/gu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gw.imageset/Contents.json new file mode 100644 index 00000000..6fa4eaaa --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gw.imageset/gw@2x.png b/Passepartout/App/macOS/Flags.xcassets/gw.imageset/gw@2x.png new file mode 100644 index 00000000..0c03edae Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gw.imageset/gw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gw.imageset/gw@3x.png b/Passepartout/App/macOS/Flags.xcassets/gw.imageset/gw@3x.png new file mode 100644 index 00000000..6db26a97 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gw.imageset/gw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gy.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/gy.imageset/Contents.json new file mode 100644 index 00000000..3cd4b397 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/gy.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "gy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "gy@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/gy.imageset/gy@2x.png b/Passepartout/App/macOS/Flags.xcassets/gy.imageset/gy@2x.png new file mode 100644 index 00000000..0fce653a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gy.imageset/gy@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/gy.imageset/gy@3x.png b/Passepartout/App/macOS/Flags.xcassets/gy.imageset/gy@3x.png new file mode 100644 index 00000000..a8d4b86e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/gy.imageset/gy@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/hk.imageset/Contents.json new file mode 100644 index 00000000..60b14d75 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/hk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "hk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "hk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/hk.imageset/hk@2x.png b/Passepartout/App/macOS/Flags.xcassets/hk.imageset/hk@2x.png new file mode 100644 index 00000000..975e73b0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hk.imageset/hk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hk.imageset/hk@3x.png b/Passepartout/App/macOS/Flags.xcassets/hk.imageset/hk@3x.png new file mode 100644 index 00000000..228615a8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hk.imageset/hk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/hm.imageset/Contents.json new file mode 100644 index 00000000..cca51f0b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/hm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "hm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "hm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/hm.imageset/hm@2x.png b/Passepartout/App/macOS/Flags.xcassets/hm.imageset/hm@2x.png new file mode 100644 index 00000000..d2f46c4f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hm.imageset/hm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hm.imageset/hm@3x.png b/Passepartout/App/macOS/Flags.xcassets/hm.imageset/hm@3x.png new file mode 100644 index 00000000..ba39e666 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hm.imageset/hm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/hn.imageset/Contents.json new file mode 100644 index 00000000..c4c5c676 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/hn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "hn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "hn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/hn.imageset/hn@2x.png b/Passepartout/App/macOS/Flags.xcassets/hn.imageset/hn@2x.png new file mode 100644 index 00000000..72ce68cf Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hn.imageset/hn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hn.imageset/hn@3x.png b/Passepartout/App/macOS/Flags.xcassets/hn.imageset/hn@3x.png new file mode 100644 index 00000000..382c0cf1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hn.imageset/hn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/hr.imageset/Contents.json new file mode 100644 index 00000000..b170577c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/hr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "hr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "hr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/hr.imageset/hr@2x.png b/Passepartout/App/macOS/Flags.xcassets/hr.imageset/hr@2x.png new file mode 100644 index 00000000..ad56e104 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hr.imageset/hr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hr.imageset/hr@3x.png b/Passepartout/App/macOS/Flags.xcassets/hr.imageset/hr@3x.png new file mode 100644 index 00000000..41932264 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hr.imageset/hr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ht.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ht.imageset/Contents.json new file mode 100644 index 00000000..02362ebd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ht.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ht@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ht@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ht.imageset/ht@2x.png b/Passepartout/App/macOS/Flags.xcassets/ht.imageset/ht@2x.png new file mode 100644 index 00000000..cf8db38b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ht.imageset/ht@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ht.imageset/ht@3x.png b/Passepartout/App/macOS/Flags.xcassets/ht.imageset/ht@3x.png new file mode 100644 index 00000000..d02663d7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ht.imageset/ht@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/hu.imageset/Contents.json new file mode 100644 index 00000000..04c74089 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/hu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "hu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "hu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/hu.imageset/hu@2x.png b/Passepartout/App/macOS/Flags.xcassets/hu.imageset/hu@2x.png new file mode 100644 index 00000000..2d4f37cf Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hu.imageset/hu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/hu.imageset/hu@3x.png b/Passepartout/App/macOS/Flags.xcassets/hu.imageset/hu@3x.png new file mode 100644 index 00000000..06f50b6b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/hu.imageset/hu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/id.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/id.imageset/Contents.json new file mode 100644 index 00000000..72af7398 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/id.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "id@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "id@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/id.imageset/id@2x.png b/Passepartout/App/macOS/Flags.xcassets/id.imageset/id@2x.png new file mode 100644 index 00000000..9a25f4e9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/id.imageset/id@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/id.imageset/id@3x.png b/Passepartout/App/macOS/Flags.xcassets/id.imageset/id@3x.png new file mode 100644 index 00000000..53905d34 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/id.imageset/id@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ie.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ie.imageset/Contents.json new file mode 100644 index 00000000..fe85e16c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ie.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ie@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ie@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ie.imageset/ie@2x.png b/Passepartout/App/macOS/Flags.xcassets/ie.imageset/ie@2x.png new file mode 100644 index 00000000..cced55a6 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ie.imageset/ie@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ie.imageset/ie@3x.png b/Passepartout/App/macOS/Flags.xcassets/ie.imageset/ie@3x.png new file mode 100644 index 00000000..deaf1c57 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ie.imageset/ie@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/il.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/il.imageset/Contents.json new file mode 100644 index 00000000..7faf42a7 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/il.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "il@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "il@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/il.imageset/il@2x.png b/Passepartout/App/macOS/Flags.xcassets/il.imageset/il@2x.png new file mode 100644 index 00000000..0ebeaf6b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/il.imageset/il@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/il.imageset/il@3x.png b/Passepartout/App/macOS/Flags.xcassets/il.imageset/il@3x.png new file mode 100644 index 00000000..0f5ce63e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/il.imageset/il@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/im.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/im.imageset/Contents.json new file mode 100644 index 00000000..54098bd5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/im.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "im@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "im@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/im.imageset/im@2x.png b/Passepartout/App/macOS/Flags.xcassets/im.imageset/im@2x.png new file mode 100644 index 00000000..58773b5b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/im.imageset/im@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/im.imageset/im@3x.png b/Passepartout/App/macOS/Flags.xcassets/im.imageset/im@3x.png new file mode 100644 index 00000000..57bfb8e4 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/im.imageset/im@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/in.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/in.imageset/Contents.json new file mode 100644 index 00000000..02a5763e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/in.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "in@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "in@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/in.imageset/in@2x.png b/Passepartout/App/macOS/Flags.xcassets/in.imageset/in@2x.png new file mode 100644 index 00000000..d6922841 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/in.imageset/in@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/in.imageset/in@3x.png b/Passepartout/App/macOS/Flags.xcassets/in.imageset/in@3x.png new file mode 100644 index 00000000..924262e9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/in.imageset/in@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/io.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/io.imageset/Contents.json new file mode 100644 index 00000000..ab461d7c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/io.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "io@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "io@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/io.imageset/io@2x.png b/Passepartout/App/macOS/Flags.xcassets/io.imageset/io@2x.png new file mode 100644 index 00000000..31d2cd35 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/io.imageset/io@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/io.imageset/io@3x.png b/Passepartout/App/macOS/Flags.xcassets/io.imageset/io@3x.png new file mode 100644 index 00000000..dc6264b5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/io.imageset/io@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/iq.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/iq.imageset/Contents.json new file mode 100644 index 00000000..c7c87454 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/iq.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "iq@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "iq@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/iq.imageset/iq@2x.png b/Passepartout/App/macOS/Flags.xcassets/iq.imageset/iq@2x.png new file mode 100644 index 00000000..191c4772 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/iq.imageset/iq@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/iq.imageset/iq@3x.png b/Passepartout/App/macOS/Flags.xcassets/iq.imageset/iq@3x.png new file mode 100644 index 00000000..00c53dd7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/iq.imageset/iq@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ir.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ir.imageset/Contents.json new file mode 100644 index 00000000..9598ddc5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ir.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ir@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ir@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ir.imageset/ir@2x.png b/Passepartout/App/macOS/Flags.xcassets/ir.imageset/ir@2x.png new file mode 100644 index 00000000..287c11ac Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ir.imageset/ir@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ir.imageset/ir@3x.png b/Passepartout/App/macOS/Flags.xcassets/ir.imageset/ir@3x.png new file mode 100644 index 00000000..2cfc11c9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ir.imageset/ir@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/is.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/is.imageset/Contents.json new file mode 100644 index 00000000..3ccfe7ce --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/is.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "is@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "is@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/is.imageset/is@2x.png b/Passepartout/App/macOS/Flags.xcassets/is.imageset/is@2x.png new file mode 100644 index 00000000..2d24e403 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/is.imageset/is@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/is.imageset/is@3x.png b/Passepartout/App/macOS/Flags.xcassets/is.imageset/is@3x.png new file mode 100644 index 00000000..a7a5481c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/is.imageset/is@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/it.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/it.imageset/Contents.json new file mode 100644 index 00000000..c59fcb30 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/it.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "it@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "it@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/it.imageset/it@2x.png b/Passepartout/App/macOS/Flags.xcassets/it.imageset/it@2x.png new file mode 100644 index 00000000..4b090314 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/it.imageset/it@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/it.imageset/it@3x.png b/Passepartout/App/macOS/Flags.xcassets/it.imageset/it@3x.png new file mode 100644 index 00000000..df9a88af Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/it.imageset/it@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/je.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/je.imageset/Contents.json new file mode 100644 index 00000000..2ce97cf8 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/je.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "je@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "je@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/je.imageset/je@2x.png b/Passepartout/App/macOS/Flags.xcassets/je.imageset/je@2x.png new file mode 100644 index 00000000..90ff19c0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/je.imageset/je@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/je.imageset/je@3x.png b/Passepartout/App/macOS/Flags.xcassets/je.imageset/je@3x.png new file mode 100644 index 00000000..6de40bf1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/je.imageset/je@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/jm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/jm.imageset/Contents.json new file mode 100644 index 00000000..cc6fcf90 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/jm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "jm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "jm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/jm.imageset/jm@2x.png b/Passepartout/App/macOS/Flags.xcassets/jm.imageset/jm@2x.png new file mode 100644 index 00000000..276ecc6b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/jm.imageset/jm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/jm.imageset/jm@3x.png b/Passepartout/App/macOS/Flags.xcassets/jm.imageset/jm@3x.png new file mode 100644 index 00000000..e7f649b9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/jm.imageset/jm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/jo.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/jo.imageset/Contents.json new file mode 100644 index 00000000..198727e0 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/jo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "jo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "jo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/jo.imageset/jo@2x.png b/Passepartout/App/macOS/Flags.xcassets/jo.imageset/jo@2x.png new file mode 100644 index 00000000..5b01d9b5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/jo.imageset/jo@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/jo.imageset/jo@3x.png b/Passepartout/App/macOS/Flags.xcassets/jo.imageset/jo@3x.png new file mode 100644 index 00000000..33e4251e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/jo.imageset/jo@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/jp.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/jp.imageset/Contents.json new file mode 100644 index 00000000..7ed4886c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/jp.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "jp@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "jp@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/jp.imageset/jp@2x.png b/Passepartout/App/macOS/Flags.xcassets/jp.imageset/jp@2x.png new file mode 100644 index 00000000..a5c91734 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/jp.imageset/jp@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/jp.imageset/jp@3x.png b/Passepartout/App/macOS/Flags.xcassets/jp.imageset/jp@3x.png new file mode 100644 index 00000000..3e6153d6 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/jp.imageset/jp@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ke.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ke.imageset/Contents.json new file mode 100644 index 00000000..68a11284 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ke.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ke@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ke@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ke.imageset/ke@2x.png b/Passepartout/App/macOS/Flags.xcassets/ke.imageset/ke@2x.png new file mode 100644 index 00000000..c8014827 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ke.imageset/ke@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ke.imageset/ke@3x.png b/Passepartout/App/macOS/Flags.xcassets/ke.imageset/ke@3x.png new file mode 100644 index 00000000..ae26b27e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ke.imageset/ke@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kg.imageset/Contents.json new file mode 100644 index 00000000..10ed8881 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kg.imageset/kg@2x.png b/Passepartout/App/macOS/Flags.xcassets/kg.imageset/kg@2x.png new file mode 100644 index 00000000..32144c44 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kg.imageset/kg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kg.imageset/kg@3x.png b/Passepartout/App/macOS/Flags.xcassets/kg.imageset/kg@3x.png new file mode 100644 index 00000000..e1a0b5a9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kg.imageset/kg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kh.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kh.imageset/Contents.json new file mode 100644 index 00000000..423ac3ac --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kh@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kh@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kh.imageset/kh@2x.png b/Passepartout/App/macOS/Flags.xcassets/kh.imageset/kh@2x.png new file mode 100644 index 00000000..5ab5cc81 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kh.imageset/kh@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kh.imageset/kh@3x.png b/Passepartout/App/macOS/Flags.xcassets/kh.imageset/kh@3x.png new file mode 100644 index 00000000..f391da82 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kh.imageset/kh@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ki.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ki.imageset/Contents.json new file mode 100644 index 00000000..103a7f8e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ki.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ki@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ki@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ki.imageset/ki@2x.png b/Passepartout/App/macOS/Flags.xcassets/ki.imageset/ki@2x.png new file mode 100644 index 00000000..224aac6f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ki.imageset/ki@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ki.imageset/ki@3x.png b/Passepartout/App/macOS/Flags.xcassets/ki.imageset/ki@3x.png new file mode 100644 index 00000000..5eb820fa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ki.imageset/ki@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/km.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/km.imageset/Contents.json new file mode 100644 index 00000000..4b603c3c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/km.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "km@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "km@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/km.imageset/km@2x.png b/Passepartout/App/macOS/Flags.xcassets/km.imageset/km@2x.png new file mode 100644 index 00000000..74e6ad27 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/km.imageset/km@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/km.imageset/km@3x.png b/Passepartout/App/macOS/Flags.xcassets/km.imageset/km@3x.png new file mode 100644 index 00000000..08bc9535 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/km.imageset/km@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kn.imageset/Contents.json new file mode 100644 index 00000000..782f11b6 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kn.imageset/kn@2x.png b/Passepartout/App/macOS/Flags.xcassets/kn.imageset/kn@2x.png new file mode 100644 index 00000000..cdfc63e1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kn.imageset/kn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kn.imageset/kn@3x.png b/Passepartout/App/macOS/Flags.xcassets/kn.imageset/kn@3x.png new file mode 100644 index 00000000..11f6dc83 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kn.imageset/kn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kp.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kp.imageset/Contents.json new file mode 100644 index 00000000..dc604660 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kp.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kp@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kp@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kp.imageset/kp@2x.png b/Passepartout/App/macOS/Flags.xcassets/kp.imageset/kp@2x.png new file mode 100644 index 00000000..8150ce68 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kp.imageset/kp@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kp.imageset/kp@3x.png b/Passepartout/App/macOS/Flags.xcassets/kp.imageset/kp@3x.png new file mode 100644 index 00000000..3d45d787 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kp.imageset/kp@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kr.imageset/Contents.json new file mode 100644 index 00000000..e51c6f44 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kr.imageset/kr@2x.png b/Passepartout/App/macOS/Flags.xcassets/kr.imageset/kr@2x.png new file mode 100644 index 00000000..4f4b1c5d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kr.imageset/kr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kr.imageset/kr@3x.png b/Passepartout/App/macOS/Flags.xcassets/kr.imageset/kr@3x.png new file mode 100644 index 00000000..4e83a5d6 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kr.imageset/kr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kw.imageset/Contents.json new file mode 100644 index 00000000..7dd61ad6 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kw.imageset/kw@2x.png b/Passepartout/App/macOS/Flags.xcassets/kw.imageset/kw@2x.png new file mode 100644 index 00000000..ce74c634 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kw.imageset/kw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kw.imageset/kw@3x.png b/Passepartout/App/macOS/Flags.xcassets/kw.imageset/kw@3x.png new file mode 100644 index 00000000..bc18e3dd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kw.imageset/kw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ky.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ky.imageset/Contents.json new file mode 100644 index 00000000..4a4160cf --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ky.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ky@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ky@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ky.imageset/ky@2x.png b/Passepartout/App/macOS/Flags.xcassets/ky.imageset/ky@2x.png new file mode 100644 index 00000000..2fb44b3e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ky.imageset/ky@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ky.imageset/ky@3x.png b/Passepartout/App/macOS/Flags.xcassets/ky.imageset/ky@3x.png new file mode 100644 index 00000000..5480fd6d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ky.imageset/ky@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/kz.imageset/Contents.json new file mode 100644 index 00000000..75065861 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/kz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "kz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "kz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/kz.imageset/kz@2x.png b/Passepartout/App/macOS/Flags.xcassets/kz.imageset/kz@2x.png new file mode 100644 index 00000000..bdeef063 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kz.imageset/kz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/kz.imageset/kz@3x.png b/Passepartout/App/macOS/Flags.xcassets/kz.imageset/kz@3x.png new file mode 100644 index 00000000..29db6110 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/kz.imageset/kz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/la.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/la.imageset/Contents.json new file mode 100644 index 00000000..d0729f43 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/la.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "la@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "la@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/la.imageset/la@2x.png b/Passepartout/App/macOS/Flags.xcassets/la.imageset/la@2x.png new file mode 100644 index 00000000..99ca1435 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/la.imageset/la@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/la.imageset/la@3x.png b/Passepartout/App/macOS/Flags.xcassets/la.imageset/la@3x.png new file mode 100644 index 00000000..b8ad1121 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/la.imageset/la@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lb.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lb.imageset/Contents.json new file mode 100644 index 00000000..195bbb5c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lb.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lb@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lb@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lb.imageset/lb@2x.png b/Passepartout/App/macOS/Flags.xcassets/lb.imageset/lb@2x.png new file mode 100644 index 00000000..22413f2d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lb.imageset/lb@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lb.imageset/lb@3x.png b/Passepartout/App/macOS/Flags.xcassets/lb.imageset/lb@3x.png new file mode 100644 index 00000000..09e5996a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lb.imageset/lb@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lc.imageset/Contents.json new file mode 100644 index 00000000..7712a0f2 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lc.imageset/lc@2x.png b/Passepartout/App/macOS/Flags.xcassets/lc.imageset/lc@2x.png new file mode 100644 index 00000000..c164b270 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lc.imageset/lc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lc.imageset/lc@3x.png b/Passepartout/App/macOS/Flags.xcassets/lc.imageset/lc@3x.png new file mode 100644 index 00000000..56f96429 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lc.imageset/lc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/li.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/li.imageset/Contents.json new file mode 100644 index 00000000..d792d4df --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/li.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "li@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "li@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/li.imageset/li@2x.png b/Passepartout/App/macOS/Flags.xcassets/li.imageset/li@2x.png new file mode 100644 index 00000000..c595cc33 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/li.imageset/li@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/li.imageset/li@3x.png b/Passepartout/App/macOS/Flags.xcassets/li.imageset/li@3x.png new file mode 100644 index 00000000..4356ede6 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/li.imageset/li@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lk.imageset/Contents.json new file mode 100644 index 00000000..81f9ebf9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lk.imageset/lk@2x.png b/Passepartout/App/macOS/Flags.xcassets/lk.imageset/lk@2x.png new file mode 100644 index 00000000..eb1e736c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lk.imageset/lk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lk.imageset/lk@3x.png b/Passepartout/App/macOS/Flags.xcassets/lk.imageset/lk@3x.png new file mode 100644 index 00000000..f1e2b591 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lk.imageset/lk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lr.imageset/Contents.json new file mode 100644 index 00000000..38464552 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lr.imageset/lr@2x.png b/Passepartout/App/macOS/Flags.xcassets/lr.imageset/lr@2x.png new file mode 100644 index 00000000..75f6ad4c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lr.imageset/lr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lr.imageset/lr@3x.png b/Passepartout/App/macOS/Flags.xcassets/lr.imageset/lr@3x.png new file mode 100644 index 00000000..43e259dd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lr.imageset/lr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ls.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ls.imageset/Contents.json new file mode 100644 index 00000000..0a4350f0 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ls.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ls@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ls@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ls.imageset/ls@2x.png b/Passepartout/App/macOS/Flags.xcassets/ls.imageset/ls@2x.png new file mode 100644 index 00000000..0e9daddb Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ls.imageset/ls@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ls.imageset/ls@3x.png b/Passepartout/App/macOS/Flags.xcassets/ls.imageset/ls@3x.png new file mode 100644 index 00000000..0573c05f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ls.imageset/ls@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lt.imageset/Contents.json new file mode 100644 index 00000000..0a71075c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lt.imageset/lt@2x.png b/Passepartout/App/macOS/Flags.xcassets/lt.imageset/lt@2x.png new file mode 100644 index 00000000..33af49e2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lt.imageset/lt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lt.imageset/lt@3x.png b/Passepartout/App/macOS/Flags.xcassets/lt.imageset/lt@3x.png new file mode 100644 index 00000000..7f2c76a2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lt.imageset/lt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lu.imageset/Contents.json new file mode 100644 index 00000000..80e8f320 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lu.imageset/lu@2x.png b/Passepartout/App/macOS/Flags.xcassets/lu.imageset/lu@2x.png new file mode 100644 index 00000000..0175718a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lu.imageset/lu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lu.imageset/lu@3x.png b/Passepartout/App/macOS/Flags.xcassets/lu.imageset/lu@3x.png new file mode 100644 index 00000000..dee17ae1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lu.imageset/lu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lv.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/lv.imageset/Contents.json new file mode 100644 index 00000000..42677cf5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/lv.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "lv@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "lv@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/lv.imageset/lv@2x.png b/Passepartout/App/macOS/Flags.xcassets/lv.imageset/lv@2x.png new file mode 100644 index 00000000..5a4c14f4 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lv.imageset/lv@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/lv.imageset/lv@3x.png b/Passepartout/App/macOS/Flags.xcassets/lv.imageset/lv@3x.png new file mode 100644 index 00000000..c34d91b1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/lv.imageset/lv@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ly.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ly.imageset/Contents.json new file mode 100644 index 00000000..e91cb286 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ly.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ly@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ly@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ly.imageset/ly@2x.png b/Passepartout/App/macOS/Flags.xcassets/ly.imageset/ly@2x.png new file mode 100644 index 00000000..738e8ad3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ly.imageset/ly@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ly.imageset/ly@3x.png b/Passepartout/App/macOS/Flags.xcassets/ly.imageset/ly@3x.png new file mode 100644 index 00000000..e5f51a54 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ly.imageset/ly@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ma.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ma.imageset/Contents.json new file mode 100644 index 00000000..144333be --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ma.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ma@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ma@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ma.imageset/ma@2x.png b/Passepartout/App/macOS/Flags.xcassets/ma.imageset/ma@2x.png new file mode 100644 index 00000000..0f8f7aaa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ma.imageset/ma@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ma.imageset/ma@3x.png b/Passepartout/App/macOS/Flags.xcassets/ma.imageset/ma@3x.png new file mode 100644 index 00000000..4294dd34 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ma.imageset/ma@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mc.imageset/Contents.json new file mode 100644 index 00000000..47971ff9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mc.imageset/mc@2x.png b/Passepartout/App/macOS/Flags.xcassets/mc.imageset/mc@2x.png new file mode 100644 index 00000000..2cabbfa7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mc.imageset/mc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mc.imageset/mc@3x.png b/Passepartout/App/macOS/Flags.xcassets/mc.imageset/mc@3x.png new file mode 100644 index 00000000..b6319e7f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mc.imageset/mc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/md.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/md.imageset/Contents.json new file mode 100644 index 00000000..76682709 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/md.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "md@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "md@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/md.imageset/md@2x.png b/Passepartout/App/macOS/Flags.xcassets/md.imageset/md@2x.png new file mode 100644 index 00000000..b5213fb1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/md.imageset/md@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/md.imageset/md@3x.png b/Passepartout/App/macOS/Flags.xcassets/md.imageset/md@3x.png new file mode 100644 index 00000000..2accb74a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/md.imageset/md@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/me.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/me.imageset/Contents.json new file mode 100644 index 00000000..954d3c0d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/me.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "me@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "me@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/me.imageset/me@2x.png b/Passepartout/App/macOS/Flags.xcassets/me.imageset/me@2x.png new file mode 100644 index 00000000..a69b1967 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/me.imageset/me@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/me.imageset/me@3x.png b/Passepartout/App/macOS/Flags.xcassets/me.imageset/me@3x.png new file mode 100644 index 00000000..dd08c87e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/me.imageset/me@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mf.imageset/Contents.json new file mode 100644 index 00000000..84292268 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mf.imageset/mf@2x.png b/Passepartout/App/macOS/Flags.xcassets/mf.imageset/mf@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mf.imageset/mf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mf.imageset/mf@3x.png b/Passepartout/App/macOS/Flags.xcassets/mf.imageset/mf@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mf.imageset/mf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mg.imageset/Contents.json new file mode 100644 index 00000000..d8ed83d5 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mg.imageset/mg@2x.png b/Passepartout/App/macOS/Flags.xcassets/mg.imageset/mg@2x.png new file mode 100644 index 00000000..04f7101f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mg.imageset/mg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mg.imageset/mg@3x.png b/Passepartout/App/macOS/Flags.xcassets/mg.imageset/mg@3x.png new file mode 100644 index 00000000..a13cbb8d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mg.imageset/mg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mh.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mh.imageset/Contents.json new file mode 100644 index 00000000..7c5b3788 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mh@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mh@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mh.imageset/mh@2x.png b/Passepartout/App/macOS/Flags.xcassets/mh.imageset/mh@2x.png new file mode 100644 index 00000000..f0439102 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mh.imageset/mh@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mh.imageset/mh@3x.png b/Passepartout/App/macOS/Flags.xcassets/mh.imageset/mh@3x.png new file mode 100644 index 00000000..ba36b4a8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mh.imageset/mh@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mk.imageset/Contents.json new file mode 100644 index 00000000..b5a72fa3 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mk.imageset/mk@2x.png b/Passepartout/App/macOS/Flags.xcassets/mk.imageset/mk@2x.png new file mode 100644 index 00000000..1b4ed77d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mk.imageset/mk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mk.imageset/mk@3x.png b/Passepartout/App/macOS/Flags.xcassets/mk.imageset/mk@3x.png new file mode 100644 index 00000000..024a361a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mk.imageset/mk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ml.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ml.imageset/Contents.json new file mode 100644 index 00000000..7b2cd541 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ml.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ml@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ml@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ml.imageset/ml@2x.png b/Passepartout/App/macOS/Flags.xcassets/ml.imageset/ml@2x.png new file mode 100644 index 00000000..b8527fb9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ml.imageset/ml@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ml.imageset/ml@3x.png b/Passepartout/App/macOS/Flags.xcassets/ml.imageset/ml@3x.png new file mode 100644 index 00000000..bdff9bae Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ml.imageset/ml@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mm.imageset/Contents.json new file mode 100644 index 00000000..fac2fb73 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mm.imageset/mm@2x.png b/Passepartout/App/macOS/Flags.xcassets/mm.imageset/mm@2x.png new file mode 100644 index 00000000..8bd69d74 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mm.imageset/mm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mm.imageset/mm@3x.png b/Passepartout/App/macOS/Flags.xcassets/mm.imageset/mm@3x.png new file mode 100644 index 00000000..f4cb181d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mm.imageset/mm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mn.imageset/Contents.json new file mode 100644 index 00000000..58b5b662 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mn.imageset/mn@2x.png b/Passepartout/App/macOS/Flags.xcassets/mn.imageset/mn@2x.png new file mode 100644 index 00000000..684cecc9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mn.imageset/mn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mn.imageset/mn@3x.png b/Passepartout/App/macOS/Flags.xcassets/mn.imageset/mn@3x.png new file mode 100644 index 00000000..8a5734bf Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mn.imageset/mn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mo.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mo.imageset/Contents.json new file mode 100644 index 00000000..6be1f045 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mo@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mo@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mo.imageset/mo@2x.png b/Passepartout/App/macOS/Flags.xcassets/mo.imageset/mo@2x.png new file mode 100644 index 00000000..afeb2408 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mo.imageset/mo@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mo.imageset/mo@3x.png b/Passepartout/App/macOS/Flags.xcassets/mo.imageset/mo@3x.png new file mode 100644 index 00000000..8d38b3fb Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mo.imageset/mo@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mp.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mp.imageset/Contents.json new file mode 100644 index 00000000..5d0fc266 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mp.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mp@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mp@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mp.imageset/mp@2x.png b/Passepartout/App/macOS/Flags.xcassets/mp.imageset/mp@2x.png new file mode 100644 index 00000000..4855abee Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mp.imageset/mp@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mp.imageset/mp@3x.png b/Passepartout/App/macOS/Flags.xcassets/mp.imageset/mp@3x.png new file mode 100644 index 00000000..ec15329a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mp.imageset/mp@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mq.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mq.imageset/Contents.json new file mode 100644 index 00000000..2820787f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mq.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mq@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mq@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mq.imageset/mq@2x.png b/Passepartout/App/macOS/Flags.xcassets/mq.imageset/mq@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mq.imageset/mq@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mq.imageset/mq@3x.png b/Passepartout/App/macOS/Flags.xcassets/mq.imageset/mq@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mq.imageset/mq@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mr.imageset/Contents.json new file mode 100644 index 00000000..3a27dfde --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mr.imageset/mr@2x.png b/Passepartout/App/macOS/Flags.xcassets/mr.imageset/mr@2x.png new file mode 100644 index 00000000..f26b0462 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mr.imageset/mr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mr.imageset/mr@3x.png b/Passepartout/App/macOS/Flags.xcassets/mr.imageset/mr@3x.png new file mode 100644 index 00000000..2896bddd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mr.imageset/mr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ms.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ms.imageset/Contents.json new file mode 100644 index 00000000..9da4de8e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ms.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ms@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ms@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ms.imageset/ms@2x.png b/Passepartout/App/macOS/Flags.xcassets/ms.imageset/ms@2x.png new file mode 100644 index 00000000..7f357cf3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ms.imageset/ms@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ms.imageset/ms@3x.png b/Passepartout/App/macOS/Flags.xcassets/ms.imageset/ms@3x.png new file mode 100644 index 00000000..ab33c26b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ms.imageset/ms@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mt.imageset/Contents.json new file mode 100644 index 00000000..e2c30591 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mt.imageset/mt@2x.png b/Passepartout/App/macOS/Flags.xcassets/mt.imageset/mt@2x.png new file mode 100644 index 00000000..614eb1f8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mt.imageset/mt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mt.imageset/mt@3x.png b/Passepartout/App/macOS/Flags.xcassets/mt.imageset/mt@3x.png new file mode 100644 index 00000000..ea3c0406 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mt.imageset/mt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mu.imageset/Contents.json new file mode 100644 index 00000000..5e2c7994 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mu.imageset/mu@2x.png b/Passepartout/App/macOS/Flags.xcassets/mu.imageset/mu@2x.png new file mode 100644 index 00000000..11eea966 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mu.imageset/mu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mu.imageset/mu@3x.png b/Passepartout/App/macOS/Flags.xcassets/mu.imageset/mu@3x.png new file mode 100644 index 00000000..c4f9996b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mu.imageset/mu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mv.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mv.imageset/Contents.json new file mode 100644 index 00000000..53757b3a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mv.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mv@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mv@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mv.imageset/mv@2x.png b/Passepartout/App/macOS/Flags.xcassets/mv.imageset/mv@2x.png new file mode 100644 index 00000000..7aa9d896 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mv.imageset/mv@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mv.imageset/mv@3x.png b/Passepartout/App/macOS/Flags.xcassets/mv.imageset/mv@3x.png new file mode 100644 index 00000000..66b1e87a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mv.imageset/mv@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mw.imageset/Contents.json new file mode 100644 index 00000000..8d741139 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mw.imageset/mw@2x.png b/Passepartout/App/macOS/Flags.xcassets/mw.imageset/mw@2x.png new file mode 100644 index 00000000..19ceaeb5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mw.imageset/mw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mw.imageset/mw@3x.png b/Passepartout/App/macOS/Flags.xcassets/mw.imageset/mw@3x.png new file mode 100644 index 00000000..16214d0a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mw.imageset/mw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mx.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mx.imageset/Contents.json new file mode 100644 index 00000000..31970ec4 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mx.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mx@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mx@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mx.imageset/mx@2x.png b/Passepartout/App/macOS/Flags.xcassets/mx.imageset/mx@2x.png new file mode 100644 index 00000000..b803ff29 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mx.imageset/mx@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mx.imageset/mx@3x.png b/Passepartout/App/macOS/Flags.xcassets/mx.imageset/mx@3x.png new file mode 100644 index 00000000..45ecb039 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mx.imageset/mx@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/my.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/my.imageset/Contents.json new file mode 100644 index 00000000..6e53f21b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/my.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "my@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "my@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/my.imageset/my@2x.png b/Passepartout/App/macOS/Flags.xcassets/my.imageset/my@2x.png new file mode 100644 index 00000000..fd19357d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/my.imageset/my@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/my.imageset/my@3x.png b/Passepartout/App/macOS/Flags.xcassets/my.imageset/my@3x.png new file mode 100644 index 00000000..7fd792ea Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/my.imageset/my@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/mz.imageset/Contents.json new file mode 100644 index 00000000..3b4d02c9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/mz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/mz.imageset/mz@2x.png b/Passepartout/App/macOS/Flags.xcassets/mz.imageset/mz@2x.png new file mode 100644 index 00000000..7ff17b6c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mz.imageset/mz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/mz.imageset/mz@3x.png b/Passepartout/App/macOS/Flags.xcassets/mz.imageset/mz@3x.png new file mode 100644 index 00000000..341e6e42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/mz.imageset/mz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/na.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/na.imageset/Contents.json new file mode 100644 index 00000000..3b73c1eb --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/na.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "na@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "na@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/na.imageset/na@2x.png b/Passepartout/App/macOS/Flags.xcassets/na.imageset/na@2x.png new file mode 100644 index 00000000..5bb37a9a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/na.imageset/na@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/na.imageset/na@3x.png b/Passepartout/App/macOS/Flags.xcassets/na.imageset/na@3x.png new file mode 100644 index 00000000..1a19529a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/na.imageset/na@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/nc.imageset/Contents.json new file mode 100644 index 00000000..9287c8b3 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/nc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "nc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/nc.imageset/nc@2x.png b/Passepartout/App/macOS/Flags.xcassets/nc.imageset/nc@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nc.imageset/nc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nc.imageset/nc@3x.png b/Passepartout/App/macOS/Flags.xcassets/nc.imageset/nc@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nc.imageset/nc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ne.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ne.imageset/Contents.json new file mode 100644 index 00000000..764ee262 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ne.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ne@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ne@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ne.imageset/ne@2x.png b/Passepartout/App/macOS/Flags.xcassets/ne.imageset/ne@2x.png new file mode 100644 index 00000000..7ea65c48 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ne.imageset/ne@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ne.imageset/ne@3x.png b/Passepartout/App/macOS/Flags.xcassets/ne.imageset/ne@3x.png new file mode 100644 index 00000000..5d815698 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ne.imageset/ne@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/nf.imageset/Contents.json new file mode 100644 index 00000000..47a555ca --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/nf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "nf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/nf.imageset/nf@2x.png b/Passepartout/App/macOS/Flags.xcassets/nf.imageset/nf@2x.png new file mode 100644 index 00000000..45028b87 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nf.imageset/nf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nf.imageset/nf@3x.png b/Passepartout/App/macOS/Flags.xcassets/nf.imageset/nf@3x.png new file mode 100644 index 00000000..e3648293 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nf.imageset/nf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ng.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ng.imageset/Contents.json new file mode 100644 index 00000000..497947a0 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ng.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ng@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ng@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ng.imageset/ng@2x.png b/Passepartout/App/macOS/Flags.xcassets/ng.imageset/ng@2x.png new file mode 100644 index 00000000..31ca8c39 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ng.imageset/ng@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ng.imageset/ng@3x.png b/Passepartout/App/macOS/Flags.xcassets/ng.imageset/ng@3x.png new file mode 100644 index 00000000..447f1bf5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ng.imageset/ng@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ni.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ni.imageset/Contents.json new file mode 100644 index 00000000..70d1fe41 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ni.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ni@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ni@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ni.imageset/ni@2x.png b/Passepartout/App/macOS/Flags.xcassets/ni.imageset/ni@2x.png new file mode 100644 index 00000000..99f58ce5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ni.imageset/ni@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ni.imageset/ni@3x.png b/Passepartout/App/macOS/Flags.xcassets/ni.imageset/ni@3x.png new file mode 100644 index 00000000..517239fa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ni.imageset/ni@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/nl.imageset/Contents.json new file mode 100644 index 00000000..2f73923d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/nl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "nl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/nl.imageset/nl@2x.png b/Passepartout/App/macOS/Flags.xcassets/nl.imageset/nl@2x.png new file mode 100644 index 00000000..8f28328d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nl.imageset/nl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nl.imageset/nl@3x.png b/Passepartout/App/macOS/Flags.xcassets/nl.imageset/nl@3x.png new file mode 100644 index 00000000..15ce6d6a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nl.imageset/nl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/no.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/no.imageset/Contents.json new file mode 100644 index 00000000..04face2b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/no.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "no@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "no@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/no.imageset/no@2x.png b/Passepartout/App/macOS/Flags.xcassets/no.imageset/no@2x.png new file mode 100644 index 00000000..6a5ef869 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/no.imageset/no@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/no.imageset/no@3x.png b/Passepartout/App/macOS/Flags.xcassets/no.imageset/no@3x.png new file mode 100644 index 00000000..a14878a7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/no.imageset/no@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/np.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/np.imageset/Contents.json new file mode 100644 index 00000000..1757ac7d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/np.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "np@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "np@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/np.imageset/np@2x.png b/Passepartout/App/macOS/Flags.xcassets/np.imageset/np@2x.png new file mode 100644 index 00000000..9c0ee926 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/np.imageset/np@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/np.imageset/np@3x.png b/Passepartout/App/macOS/Flags.xcassets/np.imageset/np@3x.png new file mode 100644 index 00000000..3615dd8d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/np.imageset/np@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/nr.imageset/Contents.json new file mode 100644 index 00000000..0f55378b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/nr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "nr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/nr.imageset/nr@2x.png b/Passepartout/App/macOS/Flags.xcassets/nr.imageset/nr@2x.png new file mode 100644 index 00000000..b442ef2b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nr.imageset/nr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nr.imageset/nr@3x.png b/Passepartout/App/macOS/Flags.xcassets/nr.imageset/nr@3x.png new file mode 100644 index 00000000..ebe5c198 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nr.imageset/nr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/nu.imageset/Contents.json new file mode 100644 index 00000000..6ca17282 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/nu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "nu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/nu.imageset/nu@2x.png b/Passepartout/App/macOS/Flags.xcassets/nu.imageset/nu@2x.png new file mode 100644 index 00000000..3cd2b842 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nu.imageset/nu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nu.imageset/nu@3x.png b/Passepartout/App/macOS/Flags.xcassets/nu.imageset/nu@3x.png new file mode 100644 index 00000000..2504561d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nu.imageset/nu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/nz.imageset/Contents.json new file mode 100644 index 00000000..3b318786 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/nz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "nz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/nz.imageset/nz@2x.png b/Passepartout/App/macOS/Flags.xcassets/nz.imageset/nz@2x.png new file mode 100644 index 00000000..2fe78b9d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nz.imageset/nz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/nz.imageset/nz@3x.png b/Passepartout/App/macOS/Flags.xcassets/nz.imageset/nz@3x.png new file mode 100644 index 00000000..c915cde5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/nz.imageset/nz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/om.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/om.imageset/Contents.json new file mode 100644 index 00000000..10fafd75 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/om.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "om@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "om@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/om.imageset/om@2x.png b/Passepartout/App/macOS/Flags.xcassets/om.imageset/om@2x.png new file mode 100644 index 00000000..56854450 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/om.imageset/om@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/om.imageset/om@3x.png b/Passepartout/App/macOS/Flags.xcassets/om.imageset/om@3x.png new file mode 100644 index 00000000..a1da5c68 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/om.imageset/om@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pa.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pa.imageset/Contents.json new file mode 100644 index 00000000..37cc6cd3 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pa.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pa@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pa@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pa.imageset/pa@2x.png b/Passepartout/App/macOS/Flags.xcassets/pa.imageset/pa@2x.png new file mode 100644 index 00000000..709b52da Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pa.imageset/pa@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pa.imageset/pa@3x.png b/Passepartout/App/macOS/Flags.xcassets/pa.imageset/pa@3x.png new file mode 100644 index 00000000..f944e16a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pa.imageset/pa@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pe.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pe.imageset/Contents.json new file mode 100644 index 00000000..abba4a21 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pe.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pe@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pe@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pe.imageset/pe@2x.png b/Passepartout/App/macOS/Flags.xcassets/pe.imageset/pe@2x.png new file mode 100644 index 00000000..0ebaefb2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pe.imageset/pe@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pe.imageset/pe@3x.png b/Passepartout/App/macOS/Flags.xcassets/pe.imageset/pe@3x.png new file mode 100644 index 00000000..3e10ce30 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pe.imageset/pe@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pf.imageset/Contents.json new file mode 100644 index 00000000..f258944a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pf.imageset/pf@2x.png b/Passepartout/App/macOS/Flags.xcassets/pf.imageset/pf@2x.png new file mode 100644 index 00000000..399812c7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pf.imageset/pf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pf.imageset/pf@3x.png b/Passepartout/App/macOS/Flags.xcassets/pf.imageset/pf@3x.png new file mode 100644 index 00000000..597b28c0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pf.imageset/pf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pg.imageset/Contents.json new file mode 100644 index 00000000..c69d9730 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pg.imageset/pg@2x.png b/Passepartout/App/macOS/Flags.xcassets/pg.imageset/pg@2x.png new file mode 100644 index 00000000..c67d49af Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pg.imageset/pg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pg.imageset/pg@3x.png b/Passepartout/App/macOS/Flags.xcassets/pg.imageset/pg@3x.png new file mode 100644 index 00000000..131018be Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pg.imageset/pg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ph.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ph.imageset/Contents.json new file mode 100644 index 00000000..2ea988f2 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ph.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ph@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ph@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ph.imageset/ph@2x.png b/Passepartout/App/macOS/Flags.xcassets/ph.imageset/ph@2x.png new file mode 100644 index 00000000..c7cbee37 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ph.imageset/ph@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ph.imageset/ph@3x.png b/Passepartout/App/macOS/Flags.xcassets/ph.imageset/ph@3x.png new file mode 100644 index 00000000..5cbb9894 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ph.imageset/ph@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pk.imageset/Contents.json new file mode 100644 index 00000000..44615c4a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pk.imageset/pk@2x.png b/Passepartout/App/macOS/Flags.xcassets/pk.imageset/pk@2x.png new file mode 100644 index 00000000..ea2a0b38 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pk.imageset/pk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pk.imageset/pk@3x.png b/Passepartout/App/macOS/Flags.xcassets/pk.imageset/pk@3x.png new file mode 100644 index 00000000..12d58ff0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pk.imageset/pk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pl.imageset/Contents.json new file mode 100644 index 00000000..e50e8cc0 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pl.imageset/pl@2x.png b/Passepartout/App/macOS/Flags.xcassets/pl.imageset/pl@2x.png new file mode 100644 index 00000000..7e0873d5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pl.imageset/pl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pl.imageset/pl@3x.png b/Passepartout/App/macOS/Flags.xcassets/pl.imageset/pl@3x.png new file mode 100644 index 00000000..8b250c04 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pl.imageset/pl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pm.imageset/Contents.json new file mode 100644 index 00000000..be2e1130 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pm.imageset/pm@2x.png b/Passepartout/App/macOS/Flags.xcassets/pm.imageset/pm@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pm.imageset/pm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pm.imageset/pm@3x.png b/Passepartout/App/macOS/Flags.xcassets/pm.imageset/pm@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pm.imageset/pm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pn.imageset/Contents.json new file mode 100644 index 00000000..fe607877 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pn.imageset/pn@2x.png b/Passepartout/App/macOS/Flags.xcassets/pn.imageset/pn@2x.png new file mode 100644 index 00000000..f228eab5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pn.imageset/pn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pn.imageset/pn@3x.png b/Passepartout/App/macOS/Flags.xcassets/pn.imageset/pn@3x.png new file mode 100644 index 00000000..8aa36c47 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pn.imageset/pn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pr.imageset/Contents.json new file mode 100644 index 00000000..4073c21e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pr.imageset/pr@2x.png b/Passepartout/App/macOS/Flags.xcassets/pr.imageset/pr@2x.png new file mode 100644 index 00000000..a31a6a9f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pr.imageset/pr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pr.imageset/pr@3x.png b/Passepartout/App/macOS/Flags.xcassets/pr.imageset/pr@3x.png new file mode 100644 index 00000000..12dd0acc Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pr.imageset/pr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ps.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ps.imageset/Contents.json new file mode 100644 index 00000000..74da65e7 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ps.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ps@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ps@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ps.imageset/ps@2x.png b/Passepartout/App/macOS/Flags.xcassets/ps.imageset/ps@2x.png new file mode 100644 index 00000000..1f98ed62 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ps.imageset/ps@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ps.imageset/ps@3x.png b/Passepartout/App/macOS/Flags.xcassets/ps.imageset/ps@3x.png new file mode 100644 index 00000000..991c51a7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ps.imageset/ps@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pt.imageset/Contents.json new file mode 100644 index 00000000..fd5b9cad --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pt.imageset/pt@2x.png b/Passepartout/App/macOS/Flags.xcassets/pt.imageset/pt@2x.png new file mode 100644 index 00000000..7f7ce200 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pt.imageset/pt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pt.imageset/pt@3x.png b/Passepartout/App/macOS/Flags.xcassets/pt.imageset/pt@3x.png new file mode 100644 index 00000000..c20fe78d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pt.imageset/pt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/pw.imageset/Contents.json new file mode 100644 index 00000000..14f31b4b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/pw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/pw.imageset/pw@2x.png b/Passepartout/App/macOS/Flags.xcassets/pw.imageset/pw@2x.png new file mode 100644 index 00000000..26eee9fb Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pw.imageset/pw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/pw.imageset/pw@3x.png b/Passepartout/App/macOS/Flags.xcassets/pw.imageset/pw@3x.png new file mode 100644 index 00000000..714ebbe9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/pw.imageset/pw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/py.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/py.imageset/Contents.json new file mode 100644 index 00000000..e430edbf --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/py.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "py@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "py@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/py.imageset/py@2x.png b/Passepartout/App/macOS/Flags.xcassets/py.imageset/py@2x.png new file mode 100644 index 00000000..84496f98 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/py.imageset/py@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/py.imageset/py@3x.png b/Passepartout/App/macOS/Flags.xcassets/py.imageset/py@3x.png new file mode 100644 index 00000000..5e3497e1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/py.imageset/py@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/qa.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/qa.imageset/Contents.json new file mode 100644 index 00000000..3ca2d93f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/qa.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "qa@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "qa@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/qa.imageset/qa@2x.png b/Passepartout/App/macOS/Flags.xcassets/qa.imageset/qa@2x.png new file mode 100644 index 00000000..54120932 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/qa.imageset/qa@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/qa.imageset/qa@3x.png b/Passepartout/App/macOS/Flags.xcassets/qa.imageset/qa@3x.png new file mode 100644 index 00000000..b845f069 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/qa.imageset/qa@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/re.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/re.imageset/Contents.json new file mode 100644 index 00000000..83133245 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/re.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "re@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "re@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/re.imageset/re@2x.png b/Passepartout/App/macOS/Flags.xcassets/re.imageset/re@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/re.imageset/re@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/re.imageset/re@3x.png b/Passepartout/App/macOS/Flags.xcassets/re.imageset/re@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/re.imageset/re@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ro.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ro.imageset/Contents.json new file mode 100644 index 00000000..2853e8db --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ro.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ro@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ro@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ro.imageset/ro@2x.png b/Passepartout/App/macOS/Flags.xcassets/ro.imageset/ro@2x.png new file mode 100644 index 00000000..25ea7aaa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ro.imageset/ro@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ro.imageset/ro@3x.png b/Passepartout/App/macOS/Flags.xcassets/ro.imageset/ro@3x.png new file mode 100644 index 00000000..a8c3cb2d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ro.imageset/ro@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/rs.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/rs.imageset/Contents.json new file mode 100644 index 00000000..393bbfe4 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/rs.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "rs@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "rs@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/rs.imageset/rs@2x.png b/Passepartout/App/macOS/Flags.xcassets/rs.imageset/rs@2x.png new file mode 100644 index 00000000..5ff02e46 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/rs.imageset/rs@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/rs.imageset/rs@3x.png b/Passepartout/App/macOS/Flags.xcassets/rs.imageset/rs@3x.png new file mode 100644 index 00000000..f559d43e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/rs.imageset/rs@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ru.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ru.imageset/Contents.json new file mode 100644 index 00000000..ba5226c9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ru.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ru@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ru@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ru.imageset/ru@2x.png b/Passepartout/App/macOS/Flags.xcassets/ru.imageset/ru@2x.png new file mode 100644 index 00000000..a43e6c13 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ru.imageset/ru@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ru.imageset/ru@3x.png b/Passepartout/App/macOS/Flags.xcassets/ru.imageset/ru@3x.png new file mode 100644 index 00000000..9f5d4658 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ru.imageset/ru@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/rw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/rw.imageset/Contents.json new file mode 100644 index 00000000..2ee6c9dd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/rw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "rw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "rw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/rw.imageset/rw@2x.png b/Passepartout/App/macOS/Flags.xcassets/rw.imageset/rw@2x.png new file mode 100644 index 00000000..0b1dae12 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/rw.imageset/rw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/rw.imageset/rw@3x.png b/Passepartout/App/macOS/Flags.xcassets/rw.imageset/rw@3x.png new file mode 100644 index 00000000..de322a3f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/rw.imageset/rw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sa.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sa.imageset/Contents.json new file mode 100644 index 00000000..f6a16107 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sa.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sa@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sa@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sa.imageset/sa@2x.png b/Passepartout/App/macOS/Flags.xcassets/sa.imageset/sa@2x.png new file mode 100644 index 00000000..88171bda Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sa.imageset/sa@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sa.imageset/sa@3x.png b/Passepartout/App/macOS/Flags.xcassets/sa.imageset/sa@3x.png new file mode 100644 index 00000000..dc09c90e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sa.imageset/sa@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sb.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sb.imageset/Contents.json new file mode 100644 index 00000000..3dc5434c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sb.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sb@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sb@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sb.imageset/sb@2x.png b/Passepartout/App/macOS/Flags.xcassets/sb.imageset/sb@2x.png new file mode 100644 index 00000000..47310850 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sb.imageset/sb@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sb.imageset/sb@3x.png b/Passepartout/App/macOS/Flags.xcassets/sb.imageset/sb@3x.png new file mode 100644 index 00000000..930e3748 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sb.imageset/sb@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sc.imageset/Contents.json new file mode 100644 index 00000000..282bd27e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sc.imageset/sc@2x.png b/Passepartout/App/macOS/Flags.xcassets/sc.imageset/sc@2x.png new file mode 100644 index 00000000..02f57a8c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sc.imageset/sc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sc.imageset/sc@3x.png b/Passepartout/App/macOS/Flags.xcassets/sc.imageset/sc@3x.png new file mode 100644 index 00000000..b7b57640 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sc.imageset/sc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sd.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sd.imageset/Contents.json new file mode 100644 index 00000000..e790510e --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sd.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sd@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sd@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sd.imageset/sd@2x.png b/Passepartout/App/macOS/Flags.xcassets/sd.imageset/sd@2x.png new file mode 100644 index 00000000..55f0018d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sd.imageset/sd@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sd.imageset/sd@3x.png b/Passepartout/App/macOS/Flags.xcassets/sd.imageset/sd@3x.png new file mode 100644 index 00000000..2d8a4426 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sd.imageset/sd@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/se.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/se.imageset/Contents.json new file mode 100644 index 00000000..168d11cd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/se.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "se@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "se@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/se.imageset/se@2x.png b/Passepartout/App/macOS/Flags.xcassets/se.imageset/se@2x.png new file mode 100644 index 00000000..d2cc99a5 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/se.imageset/se@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/se.imageset/se@3x.png b/Passepartout/App/macOS/Flags.xcassets/se.imageset/se@3x.png new file mode 100644 index 00000000..5cae3183 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/se.imageset/se@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sg.imageset/Contents.json new file mode 100644 index 00000000..d251c0f2 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sg.imageset/sg@2x.png b/Passepartout/App/macOS/Flags.xcassets/sg.imageset/sg@2x.png new file mode 100644 index 00000000..baf21ab9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sg.imageset/sg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sg.imageset/sg@3x.png b/Passepartout/App/macOS/Flags.xcassets/sg.imageset/sg@3x.png new file mode 100644 index 00000000..bd654121 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sg.imageset/sg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sh.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sh.imageset/Contents.json new file mode 100644 index 00000000..811d8a03 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sh@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sh@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sh.imageset/sh@2x.png b/Passepartout/App/macOS/Flags.xcassets/sh.imageset/sh@2x.png new file mode 100644 index 00000000..02a74828 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sh.imageset/sh@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sh.imageset/sh@3x.png b/Passepartout/App/macOS/Flags.xcassets/sh.imageset/sh@3x.png new file mode 100644 index 00000000..edd7df44 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sh.imageset/sh@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/si.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/si.imageset/Contents.json new file mode 100644 index 00000000..2cffdcae --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/si.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "si@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "si@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/si.imageset/si@2x.png b/Passepartout/App/macOS/Flags.xcassets/si.imageset/si@2x.png new file mode 100644 index 00000000..cec61dc4 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/si.imageset/si@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/si.imageset/si@3x.png b/Passepartout/App/macOS/Flags.xcassets/si.imageset/si@3x.png new file mode 100644 index 00000000..4b9e49fa Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/si.imageset/si@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sj.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sj.imageset/Contents.json new file mode 100644 index 00000000..b77353e9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sj.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sj@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sj@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sj.imageset/sj@2x.png b/Passepartout/App/macOS/Flags.xcassets/sj.imageset/sj@2x.png new file mode 100644 index 00000000..c926520d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sj.imageset/sj@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sj.imageset/sj@3x.png b/Passepartout/App/macOS/Flags.xcassets/sj.imageset/sj@3x.png new file mode 100644 index 00000000..1fffa473 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sj.imageset/sj@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sk.imageset/Contents.json new file mode 100644 index 00000000..841f7305 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sk.imageset/sk@2x.png b/Passepartout/App/macOS/Flags.xcassets/sk.imageset/sk@2x.png new file mode 100644 index 00000000..5423c94b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sk.imageset/sk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sk.imageset/sk@3x.png b/Passepartout/App/macOS/Flags.xcassets/sk.imageset/sk@3x.png new file mode 100644 index 00000000..58505d19 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sk.imageset/sk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sl.imageset/Contents.json new file mode 100644 index 00000000..d10c6c5a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sl.imageset/sl@2x.png b/Passepartout/App/macOS/Flags.xcassets/sl.imageset/sl@2x.png new file mode 100644 index 00000000..d4351924 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sl.imageset/sl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sl.imageset/sl@3x.png b/Passepartout/App/macOS/Flags.xcassets/sl.imageset/sl@3x.png new file mode 100644 index 00000000..d3460689 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sl.imageset/sl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sm.imageset/Contents.json new file mode 100644 index 00000000..7b0e3341 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sm.imageset/sm@2x.png b/Passepartout/App/macOS/Flags.xcassets/sm.imageset/sm@2x.png new file mode 100644 index 00000000..a4c6ee62 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sm.imageset/sm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sm.imageset/sm@3x.png b/Passepartout/App/macOS/Flags.xcassets/sm.imageset/sm@3x.png new file mode 100644 index 00000000..02dc0cd2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sm.imageset/sm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sn.imageset/Contents.json new file mode 100644 index 00000000..f4b5a049 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sn.imageset/sn@2x.png b/Passepartout/App/macOS/Flags.xcassets/sn.imageset/sn@2x.png new file mode 100644 index 00000000..7d9c580d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sn.imageset/sn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sn.imageset/sn@3x.png b/Passepartout/App/macOS/Flags.xcassets/sn.imageset/sn@3x.png new file mode 100644 index 00000000..1ff8ce74 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sn.imageset/sn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/so.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/so.imageset/Contents.json new file mode 100644 index 00000000..2fbafee1 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/so.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "so@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "so@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/so.imageset/so@2x.png b/Passepartout/App/macOS/Flags.xcassets/so.imageset/so@2x.png new file mode 100644 index 00000000..c66ac725 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/so.imageset/so@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/so.imageset/so@3x.png b/Passepartout/App/macOS/Flags.xcassets/so.imageset/so@3x.png new file mode 100644 index 00000000..91f5c517 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/so.imageset/so@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sr.imageset/Contents.json new file mode 100644 index 00000000..40255474 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sr.imageset/sr@2x.png b/Passepartout/App/macOS/Flags.xcassets/sr.imageset/sr@2x.png new file mode 100644 index 00000000..6c863350 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sr.imageset/sr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sr.imageset/sr@3x.png b/Passepartout/App/macOS/Flags.xcassets/sr.imageset/sr@3x.png new file mode 100644 index 00000000..8ea5905c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sr.imageset/sr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ss.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ss.imageset/Contents.json new file mode 100644 index 00000000..b5a1e806 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ss.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ss@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ss@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ss.imageset/ss@2x.png b/Passepartout/App/macOS/Flags.xcassets/ss.imageset/ss@2x.png new file mode 100644 index 00000000..b6f9e0b8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ss.imageset/ss@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ss.imageset/ss@3x.png b/Passepartout/App/macOS/Flags.xcassets/ss.imageset/ss@3x.png new file mode 100644 index 00000000..d0222881 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ss.imageset/ss@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/st.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/st.imageset/Contents.json new file mode 100644 index 00000000..4c900098 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/st.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "st@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "st@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/st.imageset/st@2x.png b/Passepartout/App/macOS/Flags.xcassets/st.imageset/st@2x.png new file mode 100644 index 00000000..1b839638 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/st.imageset/st@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/st.imageset/st@3x.png b/Passepartout/App/macOS/Flags.xcassets/st.imageset/st@3x.png new file mode 100644 index 00000000..19cdff5d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/st.imageset/st@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sv.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sv.imageset/Contents.json new file mode 100644 index 00000000..bf1d63a6 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sv.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sv@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sv@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sv.imageset/sv@2x.png b/Passepartout/App/macOS/Flags.xcassets/sv.imageset/sv@2x.png new file mode 100644 index 00000000..a4848bd9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sv.imageset/sv@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sv.imageset/sv@3x.png b/Passepartout/App/macOS/Flags.xcassets/sv.imageset/sv@3x.png new file mode 100644 index 00000000..d3ccec70 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sv.imageset/sv@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sx.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sx.imageset/Contents.json new file mode 100644 index 00000000..a3a9ad97 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sx.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sx@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sx@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sx.imageset/sx@2x.png b/Passepartout/App/macOS/Flags.xcassets/sx.imageset/sx@2x.png new file mode 100644 index 00000000..be9c4a5b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sx.imageset/sx@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sx.imageset/sx@3x.png b/Passepartout/App/macOS/Flags.xcassets/sx.imageset/sx@3x.png new file mode 100644 index 00000000..34f2fe34 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sx.imageset/sx@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sy.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sy.imageset/Contents.json new file mode 100644 index 00000000..9e97adfc --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sy.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sy@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sy.imageset/sy@2x.png b/Passepartout/App/macOS/Flags.xcassets/sy.imageset/sy@2x.png new file mode 100644 index 00000000..3d2493d8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sy.imageset/sy@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sy.imageset/sy@3x.png b/Passepartout/App/macOS/Flags.xcassets/sy.imageset/sy@3x.png new file mode 100644 index 00000000..9de4c98a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sy.imageset/sy@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/sz.imageset/Contents.json new file mode 100644 index 00000000..1e8ba38a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/sz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "sz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "sz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/sz.imageset/sz@2x.png b/Passepartout/App/macOS/Flags.xcassets/sz.imageset/sz@2x.png new file mode 100644 index 00000000..c46582ac Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sz.imageset/sz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/sz.imageset/sz@3x.png b/Passepartout/App/macOS/Flags.xcassets/sz.imageset/sz@3x.png new file mode 100644 index 00000000..ccc29cb8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/sz.imageset/sz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tc.imageset/Contents.json new file mode 100644 index 00000000..f051f128 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tc.imageset/tc@2x.png b/Passepartout/App/macOS/Flags.xcassets/tc.imageset/tc@2x.png new file mode 100644 index 00000000..68df16ca Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tc.imageset/tc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tc.imageset/tc@3x.png b/Passepartout/App/macOS/Flags.xcassets/tc.imageset/tc@3x.png new file mode 100644 index 00000000..f9fdd73c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tc.imageset/tc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/td.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/td.imageset/Contents.json new file mode 100644 index 00000000..385ba7db --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/td.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "td@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "td@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/td.imageset/td@2x.png b/Passepartout/App/macOS/Flags.xcassets/td.imageset/td@2x.png new file mode 100644 index 00000000..45dee310 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/td.imageset/td@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/td.imageset/td@3x.png b/Passepartout/App/macOS/Flags.xcassets/td.imageset/td@3x.png new file mode 100644 index 00000000..72d25e65 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/td.imageset/td@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tf.imageset/Contents.json new file mode 100644 index 00000000..ac0be50d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tf.imageset/tf@2x.png b/Passepartout/App/macOS/Flags.xcassets/tf.imageset/tf@2x.png new file mode 100644 index 00000000..3b7dc74e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tf.imageset/tf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tf.imageset/tf@3x.png b/Passepartout/App/macOS/Flags.xcassets/tf.imageset/tf@3x.png new file mode 100644 index 00000000..88c2b3d3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tf.imageset/tf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tg.imageset/Contents.json new file mode 100644 index 00000000..d3b40886 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tg.imageset/tg@2x.png b/Passepartout/App/macOS/Flags.xcassets/tg.imageset/tg@2x.png new file mode 100644 index 00000000..09f45643 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tg.imageset/tg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tg.imageset/tg@3x.png b/Passepartout/App/macOS/Flags.xcassets/tg.imageset/tg@3x.png new file mode 100644 index 00000000..f047a3bf Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tg.imageset/tg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/th.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/th.imageset/Contents.json new file mode 100644 index 00000000..dfe7a6ea --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/th.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "th@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "th@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/th.imageset/th@2x.png b/Passepartout/App/macOS/Flags.xcassets/th.imageset/th@2x.png new file mode 100644 index 00000000..d739e0cd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/th.imageset/th@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/th.imageset/th@3x.png b/Passepartout/App/macOS/Flags.xcassets/th.imageset/th@3x.png new file mode 100644 index 00000000..d68886f3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/th.imageset/th@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tj.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tj.imageset/Contents.json new file mode 100644 index 00000000..d215bf85 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tj.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tj@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tj@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tj.imageset/tj@2x.png b/Passepartout/App/macOS/Flags.xcassets/tj.imageset/tj@2x.png new file mode 100644 index 00000000..91341dd2 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tj.imageset/tj@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tj.imageset/tj@3x.png b/Passepartout/App/macOS/Flags.xcassets/tj.imageset/tj@3x.png new file mode 100644 index 00000000..3e41137d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tj.imageset/tj@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tk.imageset/Contents.json new file mode 100644 index 00000000..71ffcd2f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tk.imageset/tk@2x.png b/Passepartout/App/macOS/Flags.xcassets/tk.imageset/tk@2x.png new file mode 100644 index 00000000..a2680894 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tk.imageset/tk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tk.imageset/tk@3x.png b/Passepartout/App/macOS/Flags.xcassets/tk.imageset/tk@3x.png new file mode 100644 index 00000000..635e76ab Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tk.imageset/tk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tl.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tl.imageset/Contents.json new file mode 100644 index 00000000..07c4d944 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tl.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tl@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tl@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tl.imageset/tl@2x.png b/Passepartout/App/macOS/Flags.xcassets/tl.imageset/tl@2x.png new file mode 100644 index 00000000..174403f9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tl.imageset/tl@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tl.imageset/tl@3x.png b/Passepartout/App/macOS/Flags.xcassets/tl.imageset/tl@3x.png new file mode 100644 index 00000000..b202cd59 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tl.imageset/tl@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tm.imageset/Contents.json new file mode 100644 index 00000000..23cb8c9b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tm.imageset/tm@2x.png b/Passepartout/App/macOS/Flags.xcassets/tm.imageset/tm@2x.png new file mode 100644 index 00000000..634da525 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tm.imageset/tm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tm.imageset/tm@3x.png b/Passepartout/App/macOS/Flags.xcassets/tm.imageset/tm@3x.png new file mode 100644 index 00000000..7fdb4007 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tm.imageset/tm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tn.imageset/Contents.json new file mode 100644 index 00000000..0488262b --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tn.imageset/tn@2x.png b/Passepartout/App/macOS/Flags.xcassets/tn.imageset/tn@2x.png new file mode 100644 index 00000000..8d5ca25a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tn.imageset/tn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tn.imageset/tn@3x.png b/Passepartout/App/macOS/Flags.xcassets/tn.imageset/tn@3x.png new file mode 100644 index 00000000..dc21ed63 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tn.imageset/tn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/to.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/to.imageset/Contents.json new file mode 100644 index 00000000..f63e7a15 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/to.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "to@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "to@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/to.imageset/to@2x.png b/Passepartout/App/macOS/Flags.xcassets/to.imageset/to@2x.png new file mode 100644 index 00000000..7a7bae06 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/to.imageset/to@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/to.imageset/to@3x.png b/Passepartout/App/macOS/Flags.xcassets/to.imageset/to@3x.png new file mode 100644 index 00000000..12e78406 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/to.imageset/to@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tr.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tr.imageset/Contents.json new file mode 100644 index 00000000..a18ec00f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tr.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tr@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tr@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tr.imageset/tr@2x.png b/Passepartout/App/macOS/Flags.xcassets/tr.imageset/tr@2x.png new file mode 100644 index 00000000..77e74c1c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tr.imageset/tr@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tr.imageset/tr@3x.png b/Passepartout/App/macOS/Flags.xcassets/tr.imageset/tr@3x.png new file mode 100644 index 00000000..9b15cb08 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tr.imageset/tr@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tt.imageset/Contents.json new file mode 100644 index 00000000..39c55a5a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tt.imageset/tt@2x.png b/Passepartout/App/macOS/Flags.xcassets/tt.imageset/tt@2x.png new file mode 100644 index 00000000..dccefb1d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tt.imageset/tt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tt.imageset/tt@3x.png b/Passepartout/App/macOS/Flags.xcassets/tt.imageset/tt@3x.png new file mode 100644 index 00000000..27159253 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tt.imageset/tt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tv.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tv.imageset/Contents.json new file mode 100644 index 00000000..a25b8ffe --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tv.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tv@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tv@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tv.imageset/tv@2x.png b/Passepartout/App/macOS/Flags.xcassets/tv.imageset/tv@2x.png new file mode 100644 index 00000000..20c6a43d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tv.imageset/tv@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tv.imageset/tv@3x.png b/Passepartout/App/macOS/Flags.xcassets/tv.imageset/tv@3x.png new file mode 100644 index 00000000..6eb443af Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tv.imageset/tv@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tw.imageset/Contents.json new file mode 100644 index 00000000..6cbb7236 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tw.imageset/tw@2x.png b/Passepartout/App/macOS/Flags.xcassets/tw.imageset/tw@2x.png new file mode 100644 index 00000000..e67b370a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tw.imageset/tw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tw.imageset/tw@3x.png b/Passepartout/App/macOS/Flags.xcassets/tw.imageset/tw@3x.png new file mode 100644 index 00000000..76ca8cef Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tw.imageset/tw@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/tz.imageset/Contents.json new file mode 100644 index 00000000..d903bbe9 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/tz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/tz.imageset/tz@2x.png b/Passepartout/App/macOS/Flags.xcassets/tz.imageset/tz@2x.png new file mode 100644 index 00000000..39a1615e Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tz.imageset/tz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/tz.imageset/tz@3x.png b/Passepartout/App/macOS/Flags.xcassets/tz.imageset/tz@3x.png new file mode 100644 index 00000000..a81ce85c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/tz.imageset/tz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ua.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ua.imageset/Contents.json new file mode 100644 index 00000000..4ae29332 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ua.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ua@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ua@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ua.imageset/ua@2x.png b/Passepartout/App/macOS/Flags.xcassets/ua.imageset/ua@2x.png new file mode 100644 index 00000000..776abba8 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ua.imageset/ua@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ua.imageset/ua@3x.png b/Passepartout/App/macOS/Flags.xcassets/ua.imageset/ua@3x.png new file mode 100644 index 00000000..af612183 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ua.imageset/ua@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ug.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ug.imageset/Contents.json new file mode 100644 index 00000000..37e3a88d --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ug.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ug@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ug@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ug.imageset/ug@2x.png b/Passepartout/App/macOS/Flags.xcassets/ug.imageset/ug@2x.png new file mode 100644 index 00000000..1643347d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ug.imageset/ug@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ug.imageset/ug@3x.png b/Passepartout/App/macOS/Flags.xcassets/ug.imageset/ug@3x.png new file mode 100644 index 00000000..bbed2413 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ug.imageset/ug@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/um.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/um.imageset/Contents.json new file mode 100644 index 00000000..8771cd57 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/um.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "um@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "um@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/um.imageset/um@2x.png b/Passepartout/App/macOS/Flags.xcassets/um.imageset/um@2x.png new file mode 100644 index 00000000..e286037a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/um.imageset/um@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/um.imageset/um@3x.png b/Passepartout/App/macOS/Flags.xcassets/um.imageset/um@3x.png new file mode 100644 index 00000000..e254dd2c Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/um.imageset/um@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/un.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/un.imageset/Contents.json new file mode 100644 index 00000000..39ed99a8 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/un.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "un@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "un@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/un.imageset/un@2x.png b/Passepartout/App/macOS/Flags.xcassets/un.imageset/un@2x.png new file mode 100644 index 00000000..c4697d14 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/un.imageset/un@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/un.imageset/un@3x.png b/Passepartout/App/macOS/Flags.xcassets/un.imageset/un@3x.png new file mode 100644 index 00000000..ce81e498 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/un.imageset/un@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/us.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/us.imageset/Contents.json new file mode 100644 index 00000000..94c9f941 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/us.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "us@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "us@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/us.imageset/us@2x.png b/Passepartout/App/macOS/Flags.xcassets/us.imageset/us@2x.png new file mode 100644 index 00000000..6f7141cd Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/us.imageset/us@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/us.imageset/us@3x.png b/Passepartout/App/macOS/Flags.xcassets/us.imageset/us@3x.png new file mode 100644 index 00000000..8e231c49 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/us.imageset/us@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/uy.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/uy.imageset/Contents.json new file mode 100644 index 00000000..126bbc73 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/uy.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "uy@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "uy@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/uy.imageset/uy@2x.png b/Passepartout/App/macOS/Flags.xcassets/uy.imageset/uy@2x.png new file mode 100644 index 00000000..ef2c2ead Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/uy.imageset/uy@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/uy.imageset/uy@3x.png b/Passepartout/App/macOS/Flags.xcassets/uy.imageset/uy@3x.png new file mode 100644 index 00000000..886bdb3a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/uy.imageset/uy@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/uz.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/uz.imageset/Contents.json new file mode 100644 index 00000000..1c68372c --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/uz.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "uz@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "uz@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/uz.imageset/uz@2x.png b/Passepartout/App/macOS/Flags.xcassets/uz.imageset/uz@2x.png new file mode 100644 index 00000000..bc35ebeb Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/uz.imageset/uz@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/uz.imageset/uz@3x.png b/Passepartout/App/macOS/Flags.xcassets/uz.imageset/uz@3x.png new file mode 100644 index 00000000..0c6f0fad Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/uz.imageset/uz@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/va.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/va.imageset/Contents.json new file mode 100644 index 00000000..017f6979 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/va.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "va@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "va@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/va.imageset/va@2x.png b/Passepartout/App/macOS/Flags.xcassets/va.imageset/va@2x.png new file mode 100644 index 00000000..8c677b45 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/va.imageset/va@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/va.imageset/va@3x.png b/Passepartout/App/macOS/Flags.xcassets/va.imageset/va@3x.png new file mode 100644 index 00000000..073caa14 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/va.imageset/va@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vc.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/vc.imageset/Contents.json new file mode 100644 index 00000000..1240cdde --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/vc.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "vc@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "vc@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/vc.imageset/vc@2x.png b/Passepartout/App/macOS/Flags.xcassets/vc.imageset/vc@2x.png new file mode 100644 index 00000000..c4ef8c8a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vc.imageset/vc@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vc.imageset/vc@3x.png b/Passepartout/App/macOS/Flags.xcassets/vc.imageset/vc@3x.png new file mode 100644 index 00000000..0317c7e9 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vc.imageset/vc@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ve.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ve.imageset/Contents.json new file mode 100644 index 00000000..1ccf5bc3 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ve.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ve@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ve@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ve.imageset/ve@2x.png b/Passepartout/App/macOS/Flags.xcassets/ve.imageset/ve@2x.png new file mode 100644 index 00000000..18053a4a Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ve.imageset/ve@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ve.imageset/ve@3x.png b/Passepartout/App/macOS/Flags.xcassets/ve.imageset/ve@3x.png new file mode 100644 index 00000000..aae4602f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ve.imageset/ve@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vg.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/vg.imageset/Contents.json new file mode 100644 index 00000000..257af5ff --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/vg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "vg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "vg@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/vg.imageset/vg@2x.png b/Passepartout/App/macOS/Flags.xcassets/vg.imageset/vg@2x.png new file mode 100644 index 00000000..0fc07117 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vg.imageset/vg@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vg.imageset/vg@3x.png b/Passepartout/App/macOS/Flags.xcassets/vg.imageset/vg@3x.png new file mode 100644 index 00000000..743f1d4f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vg.imageset/vg@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vi.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/vi.imageset/Contents.json new file mode 100644 index 00000000..8c5e4610 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/vi.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "vi@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "vi@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/vi.imageset/vi@2x.png b/Passepartout/App/macOS/Flags.xcassets/vi.imageset/vi@2x.png new file mode 100644 index 00000000..6f3bd1bc Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vi.imageset/vi@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vi.imageset/vi@3x.png b/Passepartout/App/macOS/Flags.xcassets/vi.imageset/vi@3x.png new file mode 100644 index 00000000..2a08c645 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vi.imageset/vi@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vn.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/vn.imageset/Contents.json new file mode 100644 index 00000000..20975668 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/vn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "vn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "vn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/vn.imageset/vn@2x.png b/Passepartout/App/macOS/Flags.xcassets/vn.imageset/vn@2x.png new file mode 100644 index 00000000..eea6e770 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vn.imageset/vn@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vn.imageset/vn@3x.png b/Passepartout/App/macOS/Flags.xcassets/vn.imageset/vn@3x.png new file mode 100644 index 00000000..d86b6896 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vn.imageset/vn@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vu.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/vu.imageset/Contents.json new file mode 100644 index 00000000..4effe554 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/vu.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "vu@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "vu@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/vu.imageset/vu@2x.png b/Passepartout/App/macOS/Flags.xcassets/vu.imageset/vu@2x.png new file mode 100644 index 00000000..5c1ec83f Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vu.imageset/vu@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/vu.imageset/vu@3x.png b/Passepartout/App/macOS/Flags.xcassets/vu.imageset/vu@3x.png new file mode 100644 index 00000000..de55b8b3 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/vu.imageset/vu@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/wf.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/wf.imageset/Contents.json new file mode 100644 index 00000000..11c0d01a --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/wf.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "wf@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "wf@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/wf.imageset/wf@2x.png b/Passepartout/App/macOS/Flags.xcassets/wf.imageset/wf@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/wf.imageset/wf@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/wf.imageset/wf@3x.png b/Passepartout/App/macOS/Flags.xcassets/wf.imageset/wf@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/wf.imageset/wf@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ws.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ws.imageset/Contents.json new file mode 100644 index 00000000..b27b0e25 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ws.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ws@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ws@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ws.imageset/ws@2x.png b/Passepartout/App/macOS/Flags.xcassets/ws.imageset/ws@2x.png new file mode 100644 index 00000000..07840dd7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ws.imageset/ws@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ws.imageset/ws@3x.png b/Passepartout/App/macOS/Flags.xcassets/ws.imageset/ws@3x.png new file mode 100644 index 00000000..69bdcd27 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ws.imageset/ws@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/xk.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/xk.imageset/Contents.json new file mode 100644 index 00000000..9cc7c031 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/xk.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "xk@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "xk@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/xk.imageset/xk@2x.png b/Passepartout/App/macOS/Flags.xcassets/xk.imageset/xk@2x.png new file mode 100644 index 00000000..a66e0ac1 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/xk.imageset/xk@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/xk.imageset/xk@3x.png b/Passepartout/App/macOS/Flags.xcassets/xk.imageset/xk@3x.png new file mode 100644 index 00000000..2499b6b7 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/xk.imageset/xk@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ye.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/ye.imageset/Contents.json new file mode 100644 index 00000000..682860a1 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/ye.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ye@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ye@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/ye.imageset/ye@2x.png b/Passepartout/App/macOS/Flags.xcassets/ye.imageset/ye@2x.png new file mode 100644 index 00000000..0978749b Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ye.imageset/ye@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/ye.imageset/ye@3x.png b/Passepartout/App/macOS/Flags.xcassets/ye.imageset/ye@3x.png new file mode 100644 index 00000000..8b10d449 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/ye.imageset/ye@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/yt.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/yt.imageset/Contents.json new file mode 100644 index 00000000..ce85b9dd --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/yt.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "yt@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "yt@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/yt.imageset/yt@2x.png b/Passepartout/App/macOS/Flags.xcassets/yt.imageset/yt@2x.png new file mode 100644 index 00000000..62d74b42 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/yt.imageset/yt@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/yt.imageset/yt@3x.png b/Passepartout/App/macOS/Flags.xcassets/yt.imageset/yt@3x.png new file mode 100644 index 00000000..5b94a226 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/yt.imageset/yt@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/za.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/za.imageset/Contents.json new file mode 100644 index 00000000..f00ea47f --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/za.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "za@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "za@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/za.imageset/za@2x.png b/Passepartout/App/macOS/Flags.xcassets/za.imageset/za@2x.png new file mode 100644 index 00000000..5d2bb1b4 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/za.imageset/za@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/za.imageset/za@3x.png b/Passepartout/App/macOS/Flags.xcassets/za.imageset/za@3x.png new file mode 100644 index 00000000..bcfce825 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/za.imageset/za@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/zm.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/zm.imageset/Contents.json new file mode 100644 index 00000000..5def39bf --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/zm.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "zm@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "zm@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/zm.imageset/zm@2x.png b/Passepartout/App/macOS/Flags.xcassets/zm.imageset/zm@2x.png new file mode 100644 index 00000000..8f314bb0 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/zm.imageset/zm@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/zm.imageset/zm@3x.png b/Passepartout/App/macOS/Flags.xcassets/zm.imageset/zm@3x.png new file mode 100644 index 00000000..1deb600d Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/zm.imageset/zm@3x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/zw.imageset/Contents.json b/Passepartout/App/macOS/Flags.xcassets/zw.imageset/Contents.json new file mode 100644 index 00000000..40b25c00 --- /dev/null +++ b/Passepartout/App/macOS/Flags.xcassets/zw.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "zw@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "zw@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Flags.xcassets/zw.imageset/zw@2x.png b/Passepartout/App/macOS/Flags.xcassets/zw.imageset/zw@2x.png new file mode 100644 index 00000000..1029f472 Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/zw.imageset/zw@2x.png differ diff --git a/Passepartout/App/macOS/Flags.xcassets/zw.imageset/zw@3x.png b/Passepartout/App/macOS/Flags.xcassets/zw.imageset/zw@3x.png new file mode 100644 index 00000000..97d93cee Binary files /dev/null and b/Passepartout/App/macOS/Flags.xcassets/zw.imageset/zw@3x.png differ diff --git a/Passepartout/App/macOS/Global/AppConstants+App.swift b/Passepartout/App/macOS/Global/AppConstants+App.swift new file mode 100644 index 00000000..c328ea99 --- /dev/null +++ b/Passepartout/App/macOS/Global/AppConstants+App.swift @@ -0,0 +1,46 @@ +// +// AppConstants+App.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 11/4/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import PassepartoutCore + +extension AppConstants { + struct Rating { + static let eventCount = 10 + } + + struct InApp { + static var isBetaFullVersion: Bool { + guard !ProcessInfo.processInfo.arguments.contains("FULL_VERSION") else { + return true + } + return false + } + + static let lastFullVersionBuild = 0 + + static let limitedNumberOfHosts = 2 + } +} diff --git a/Passepartout/App/macOS/Global/Credits.html b/Passepartout/App/macOS/Global/Credits.html new file mode 100644 index 00000000..233c1b05 --- /dev/null +++ b/Passepartout/App/macOS/Global/Credits.html @@ -0,0 +1,24 @@ + + + + + + README · + CHANGELOG · + FAQ +
+ Disclaimer · + Privacy policy + + diff --git a/Passepartout/App/macOS/Global/Donation.swift b/Passepartout/App/macOS/Global/Donation.swift new file mode 100644 index 00000000..aaa664f5 --- /dev/null +++ b/Passepartout/App/macOS/Global/Donation.swift @@ -0,0 +1,49 @@ +// +// InApp.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 8/16/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +enum Donation: String { + case tiny = "com.algoritmico.macos.Passepartout.donations.Tiny" + + case small = "com.algoritmico.macos.Passepartout.donations.Small" + + case medium = "com.algoritmico.macos.Passepartout.donations.Medium" + + case big = "com.algoritmico.macos.Passepartout.donations.Big" + + case huge = "com.algoritmico.macos.Passepartout.donations.Huge" + + case maxi = "com.algoritmico.macos.Passepartout.donations.Maxi" + + static let all: [Donation] = [ + .tiny, + .small, + .medium, + .big, + .huge, + .maxi + ] +} diff --git a/Passepartout/App/macOS/Global/HostImporter.swift b/Passepartout/App/macOS/Global/HostImporter.swift new file mode 100644 index 00000000..433dcca6 --- /dev/null +++ b/Passepartout/App/macOS/Global/HostImporter.swift @@ -0,0 +1,239 @@ +// +// HostImporter.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 8/18/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import PassepartoutCore +import TunnelKit +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +class HostImporter { + private let service = TransientStore.shared.service + + private let windowController: NSWindowController? + + private let viewController: NSViewController? + + private weak var accountDelegate: AccountViewControllerDelegate? + + private let configurationURL: URL + + private var createdTitle: String? + + private var replacedProfile: ConnectionProfile? + + init(withConfigurationURL configurationURL: URL) { + self.configurationURL = configurationURL + log.debug("Parsing configuration URL: \(configurationURL)") + + windowController = WindowManager.shared.showOrganizer() + viewController = windowController?.contentViewController + accountDelegate = viewController as? AccountViewControllerDelegate + } + + func importHost(withPassphrase passphrase: String?) { + let result: OpenVPN.ConfigurationParser.Result + do { + result = try OpenVPN.ConfigurationParser.parsed(fromURL: configurationURL, passphrase: passphrase) + } catch let e as ConfigurationError { + switch e { + case .encryptionPassphrase, .unableToDecrypt(_): + enterPassphraseForHost(at: configurationURL) + + default: + let message = HostImporter.localizedMessage(forError: e) + let alert = Macros.warning(configurationURL.normalizedFilename, message) + _ = alert.presentModally(withOK: L10n.Core.Global.ok, cancel: nil) + } + return + } catch let e { + let message = HostImporter.localizedMessage(forError: e) + let alert = Macros.warning(configurationURL.normalizedFilename, message) + _ = alert.presentModally(withOK: L10n.Core.Global.ok, cancel: nil) + return + } + + if let warning = result.warning { + let message = HostImporter.localizedDetailsMessage(forWarning: warning) + let alert = Macros.warning(configurationURL.normalizedFilename, L10n.Core.ParsedFile.Alerts.PotentiallyUnsupported.message(message)) + + if alert.presentModally(withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel) { + enterProfileName(forHostWithResult: result) + } + + return + } + + enterProfileName(forHostWithResult: result) + } + + private func enterPassphraseForHost(at url: URL) { + let vc = StoryboardScene.Main.textInputViewController.instantiate() + vc.caption = L10n.Core.ParsedFile.Alerts.EncryptionPassphrase.message + vc.isSecure = true + vc.object = url + vc.delegate = self + present(vc) + } + + private func enterProfileName(forHostWithResult result: OpenVPN.ConfigurationParser.Result) { + guard let title = result.url?.normalizedFilename, let hostname = result.configuration.hostname else { + return + } + + let vc = StoryboardScene.Main.textInputViewController.instantiate() + vc.caption = L10n.Core.Service.Alerts.Rename.title.asCaption + let profile = HostConnectionProfile(hostname: hostname) + let builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: result.configuration) + profile.parameters = builder.build() + vc.text = title + vc.placeholder = L10n.Core.Global.Host.TitleInput.placeholder + vc.object = profile + vc.delegate = self + present(vc) + } + + private func enterCredentials(forProfile profile: ConnectionProfile) { + let vc = StoryboardScene.Service.accountViewController.instantiate() + vc.profile = profile + vc.delegate = self + present(vc) + } + + // MARK: Helpers + + private func present(_ presentedViewController: NSViewController) { + viewController?.presentAsSheet(presentedViewController) + } + + private func dismiss(_ presentedViewController: NSViewController) { + viewController?.dismiss(presentedViewController) + } + + // XXX: copy/paste from iOS + private static func localizedMessage(forError error: Error) -> String { + if let appError = error as? ConfigurationError { + switch appError { + case .malformed(let option): + log.error("Could not parse configuration URL: malformed option, \(option)") + return L10n.Core.ParsedFile.Alerts.Malformed.message(option) + + case .missingConfiguration(let option): + log.error("Could not parse configuration URL: missing configuration, \(option)") + return L10n.Core.ParsedFile.Alerts.Missing.message(option) + + case .unsupportedConfiguration(let option): + log.error("Could not parse configuration URL: unsupported configuration, \(option)") + return L10n.Core.ParsedFile.Alerts.Unsupported.message(option) + + default: + break + } + } + log.error("Could not parse configuration URL: \(error)") + return L10n.Core.ParsedFile.Alerts.Parsing.message(error.localizedDescription) + } + + // XXX: copy/paste from iOS + private static func localizedDetailsMessage(forWarning warning: ConfigurationError) -> String { + switch warning { + case .malformed(let option): + return option + + case .missingConfiguration(let option): + return option + + case .unsupportedConfiguration(let option): + return option + + default: + return "" // XXX: should never get here + } + } +} + +extension HostImporter: TextInputViewControllerDelegate { + func textInputController(_ textInputController: TextInputViewController, shouldEnterText text: String) -> Bool { + + // rename profile + guard let _ = textInputController.object as? ConnectionProfile else { + return true + } + return true//text.rangeOfCharacter(from: CharacterSet.filename.inverted) == nil + } + + func textInputController(_ textInputController: TextInputViewController, didEnterText text: String) { + + // rename profile + if let profile = textInputController.object as? ConnectionProfile { + createdTitle = text + + // overwrite host with existing name? + replacedProfile = nil + if let existingHostId = service.existingHostId(withTitle: text) { + dismiss(textInputController) + + let alert = Macros.warning(text, L10n.Core.Wizards.Host.Alerts.Existing.message) + if alert.presentModally(withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel) { + guard let existingProfile = service.profile(withContext: profile.context, id: existingHostId) else { + fatalError("ConnectionService.existingHostId() returned a non-existing host profile?") + } + replacedProfile = existingProfile + enterCredentials(forProfile: profile) + } + return + } + enterCredentials(forProfile: profile) + } + // enter passphrase + else { + importHost(withPassphrase: text) + } + + dismiss(textInputController) + } +} + +// enrich delegate +extension HostImporter : AccountViewControllerDelegate { + func accountController(_ accountController: AccountViewController, shouldUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) -> Bool { + return accountDelegate?.accountController(accountController, shouldUpdateCredentials: credentials, forProfile: profile) ?? true + } + + func accountController(_ accountController: AccountViewController, didUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) { + if let replacedProfile = replacedProfile { + service.removeProfile(ProfileKey(replacedProfile)) + } + service.addOrReplaceProfile(profile, credentials: credentials, title: createdTitle) + _ = try? service.save(configurationURL: configurationURL, for: profile) + + accountDelegate?.accountController(accountController, didUpdateCredentials: credentials, forProfile: profile) + } + + func accountControllerDidCancel(_ accountController: AccountViewController) { + accountDelegate?.accountControllerDidCancel(accountController) + } +} diff --git a/Passepartout/App/macOS/Global/IssueReporter.swift b/Passepartout/App/macOS/Global/IssueReporter.swift new file mode 100644 index 00000000..fca18879 --- /dev/null +++ b/Passepartout/App/macOS/Global/IssueReporter.swift @@ -0,0 +1,122 @@ +// +// IssueReporter.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 9/5/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit +import PassepartoutCore + +class IssueReporter: NSObject { + static let shared = IssueReporter() + + override private init() { + super.init() + } + + func present(withIssue issue: Issue) { + if issue.debugLog { + let alert = Macros.warning(L10n.Core.IssueReporter.title, L10n.Core.IssueReporter.message) + alert.present(in: nil, withOK: L10n.Core.IssueReporter.Buttons.accept, cancel: L10n.Core.Global.cancel, handler: { + VPN.shared.requestDebugLog(fallback: AppConstants.Log.debugSnapshot) { + self.composeEmail(withDebugLog: $0, issue: issue) + } + }, cancelHandler: nil) + } else { + composeEmail(withDebugLog: nil, issue: issue) + } + } + + private func composeEmail(withDebugLog debugLog: String?, issue: Issue) { + guard let sharing = NSSharingService(named: .composeEmail) else { + // TODO: show error alert + return + } + sharing.recipients = [AppConstants.IssueReporter.Email.recipient] + sharing.subject = AppConstants.IssueReporter.Email.subject + + var items: [Any] = [] + + // delete temporary files on exit + // NO, they're needed until NSSharingService is dismissed (who knows when?) +// defer { +// for item in items { +// guard let url = item as? URL else { +// continue +// } +// try? FileManager.default.removeItem(at: url) +// } +// } + + let bodyContent = AppConstants.IssueReporter.Email.template + var bodyMetadata = "--\n\n" + bodyMetadata += DebugLog(raw: "").decoratedString() + if let metadata = issue.infrastructureMetadata { + bodyMetadata += "Provider: \(metadata.description)\n" + if let lastUpdated = InfrastructureFactory.shared.modificationDate(forName: metadata.name) { + bodyMetadata += "Last updated: \(lastUpdated)\n" + } + bodyMetadata += "\n" + } + bodyMetadata += "--" + let body = AppConstants.IssueReporter.Email.body(bodyContent, bodyMetadata) + items.append(body) + + if let raw = debugLog { + let attachment = DebugLog(raw: raw).decoratedData() + if let item = attachment.temporaryURL(withFileName: AppConstants.IssueReporter.Filenames.debugLog) { + items.append(item) + } + } + if let url = issue.configurationURL { + do { + let parsedFile = try OpenVPN.ConfigurationParser.parsed(fromURL: url, returnsStripped: true) + if let attachment = parsedFile.strippedLines?.joined(separator: "\n").data(using: .utf8), + let item = attachment.temporaryURL(withFileName: AppConstants.IssueReporter.Filenames.configuration) { + + items.append(item) + } + } catch { + } + } + + guard sharing.canPerform(withItems: items) else { + // TODO: show error alert + return + } + sharing.perform(withItems: items) + } +} + +private extension Data { + func temporaryURL(withFileName fileName: String) -> URL? { + let tempURL = URL(fileURLWithPath: NSTemporaryDirectory()) + let dest = tempURL.appendingPathComponent(fileName) + do { + try write(to: dest) + } catch { + return nil + } + return dest + } +} diff --git a/Passepartout/App/macOS/Global/Macros.swift b/Passepartout/App/macOS/Global/Macros.swift new file mode 100644 index 00000000..fc1a7a7d --- /dev/null +++ b/Passepartout/App/macOS/Global/Macros.swift @@ -0,0 +1,139 @@ +// +// Macros.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/30/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa + +class Macros { + static func warning(_ title: String, _ message: String) -> NSAlert { + return genericAlert(.warning, title, message) + } + + private static func genericAlert(_ style: NSAlert.Style, _ title: String, _ message: String) -> NSAlert { + let alert = NSAlert() + alert.alertStyle = style + alert.messageText = title + alert.informativeText = message + return alert + } +} + +extension NSAlert { + func present(in window: NSWindow?, withOK okTitle: String, handler: (() -> Void)?) { + present(in: window, withOK: okTitle, cancel: nil, handler: handler, cancelHandler: nil) + } + + func present(in window: NSWindow?, withOK okTitle: String, cancel cancelTitle: String?, dummy dummyTitle: String? = nil, handler: (() -> Void)?, cancelHandler: (() -> Void)?) { + guard let window = window else { + if presentModally(withOK: okTitle, cancel: cancelTitle, dummy: dummyTitle) { + handler?() + } else { + cancelHandler?() + } + return + } + + addButton(withTitle: okTitle) + if let cancelTitle = cancelTitle { + addButton(withTitle: cancelTitle) + } + if let dummyTitle = dummyTitle { + addButton(withTitle: dummyTitle) + } + + beginSheetModal(for: window) { + switch $0 { + case .alertFirstButtonReturn: + handler?() + + default: + cancelHandler?() + } + } + } + + func presentModally(withOK okTitle: String, cancel cancelTitle: String?, dummy dummyTitle: String? = nil) -> Bool { + addButton(withTitle: okTitle) + if let cancelTitle = cancelTitle { + addButton(withTitle: cancelTitle) + } + if let dummyTitle = dummyTitle { + addButton(withTitle: dummyTitle) + } + return runModal() == .alertFirstButtonReturn + } +} + +extension NSView { + static func get() -> T { + let name = String(describing: T.self) + guard let nib = NSNib(nibNamed: name, bundle: nil) else { + fatalError() + } + var objects: NSArray? + guard nib.instantiate(withOwner: nil, topLevelObjects: &objects) else { + fatalError() + } + guard let nonOptionalObjects = objects else { + fatalError() + } + for o in nonOptionalObjects { + if let view = o as? T { + return view + } + } + fatalError() + } +} + +extension NSView { + func endEditing() { + window?.makeFirstResponder(nil) + } +} + +extension NSImage { + func tinted(withColor color: NSColor) -> NSImage { + let image = copy() as! NSImage + image.lockFocus() + + color.set() + + let imageRect = NSRect(origin: NSZeroPoint, size: image.size) + imageRect.fill(using: .sourceAtop) + image.unlockFocus() + + return image + } +} + +extension String { + var asCaption: String { + return "\(self):" + } + + var asContinuation: String { + return "\(self)..." + } +} diff --git a/Passepartout/App/macOS/Global/NSTextView+Search.swift b/Passepartout/App/macOS/Global/NSTextView+Search.swift new file mode 100644 index 00000000..70f11a1e --- /dev/null +++ b/Passepartout/App/macOS/Global/NSTextView+Search.swift @@ -0,0 +1,32 @@ +// +// NSTextView+Search.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 8/1/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa + +extension NSTextView { + func scrollToEnd() { + scrollRangeToVisible(NSMakeRange(string.count - 1, 1)) + } +} diff --git a/Passepartout/App/macOS/Global/ProductManager+App.swift b/Passepartout/App/macOS/Global/ProductManager+App.swift new file mode 100644 index 00000000..8724481e --- /dev/null +++ b/Passepartout/App/macOS/Global/ProductManager+App.swift @@ -0,0 +1,36 @@ +// +// ProductManager+App.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 12/25/20. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import PassepartoutCore + +extension ProductManager { + static let shared = ProductManager( + Configuration( + isBetaFullVersion: AppConstants.InApp.isBetaFullVersion, + lastFullVersionBuild: AppConstants.InApp.lastFullVersionBuild + ) + ) +} diff --git a/Passepartout/App/macOS/Global/SwiftGen+Assets.swift b/Passepartout/App/macOS/Global/SwiftGen+Assets.swift new file mode 100644 index 00000000..b66117ed --- /dev/null +++ b/Passepartout/App/macOS/Global/SwiftGen+Assets.swift @@ -0,0 +1,348 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +#if os(macOS) + import AppKit +#elseif os(iOS) + import UIKit +#elseif os(tvOS) || os(watchOS) + import UIKit +#endif + +// 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 + +// swiftlint:disable identifier_name line_length nesting type_body_length type_name +internal enum Asset { + internal enum Assets { + internal static let statusBarButtonImage = ImageAsset(name: "StatusBarButtonImage") + } + internal enum Flags { + internal static let ad = ImageAsset(name: "ad") + internal static let ae = ImageAsset(name: "ae") + internal static let af = ImageAsset(name: "af") + internal static let ag = ImageAsset(name: "ag") + internal static let ai = ImageAsset(name: "ai") + internal static let al = ImageAsset(name: "al") + internal static let am = ImageAsset(name: "am") + internal static let ao = ImageAsset(name: "ao") + internal static let aq = ImageAsset(name: "aq") + internal static let ar = ImageAsset(name: "ar") + internal static let `as` = ImageAsset(name: "as") + internal static let at = ImageAsset(name: "at") + internal static let au = ImageAsset(name: "au") + internal static let aw = ImageAsset(name: "aw") + internal static let ax = ImageAsset(name: "ax") + internal static let az = ImageAsset(name: "az") + internal static let ba = ImageAsset(name: "ba") + internal static let bb = ImageAsset(name: "bb") + internal static let bd = ImageAsset(name: "bd") + internal static let be = ImageAsset(name: "be") + internal static let bf = ImageAsset(name: "bf") + internal static let bg = ImageAsset(name: "bg") + internal static let bh = ImageAsset(name: "bh") + internal static let bi = ImageAsset(name: "bi") + internal static let bj = ImageAsset(name: "bj") + internal static let bl = ImageAsset(name: "bl") + internal static let bm = ImageAsset(name: "bm") + internal static let bn = ImageAsset(name: "bn") + internal static let bo = ImageAsset(name: "bo") + internal static let bq = ImageAsset(name: "bq") + internal static let br = ImageAsset(name: "br") + internal static let bs = ImageAsset(name: "bs") + internal static let bt = ImageAsset(name: "bt") + internal static let bv = ImageAsset(name: "bv") + internal static let bw = ImageAsset(name: "bw") + internal static let by = ImageAsset(name: "by") + internal static let bz = ImageAsset(name: "bz") + internal static let ca = ImageAsset(name: "ca") + internal static let cc = ImageAsset(name: "cc") + internal static let cd = ImageAsset(name: "cd") + internal static let cf = ImageAsset(name: "cf") + internal static let cg = ImageAsset(name: "cg") + internal static let ch = ImageAsset(name: "ch") + internal static let ci = ImageAsset(name: "ci") + internal static let ck = ImageAsset(name: "ck") + internal static let cl = ImageAsset(name: "cl") + internal static let cm = ImageAsset(name: "cm") + internal static let cn = ImageAsset(name: "cn") + internal static let co = ImageAsset(name: "co") + internal static let cr = ImageAsset(name: "cr") + internal static let cu = ImageAsset(name: "cu") + internal static let cv = ImageAsset(name: "cv") + internal static let cw = ImageAsset(name: "cw") + internal static let cx = ImageAsset(name: "cx") + internal static let cy = ImageAsset(name: "cy") + internal static let cz = ImageAsset(name: "cz") + internal static let de = ImageAsset(name: "de") + internal static let dj = ImageAsset(name: "dj") + internal static let dk = ImageAsset(name: "dk") + internal static let dm = ImageAsset(name: "dm") + internal static let `do` = ImageAsset(name: "do") + internal static let dz = ImageAsset(name: "dz") + internal static let ec = ImageAsset(name: "ec") + internal static let ee = ImageAsset(name: "ee") + internal static let eg = ImageAsset(name: "eg") + internal static let eh = ImageAsset(name: "eh") + internal static let er = ImageAsset(name: "er") + internal static let esCt = ImageAsset(name: "es-ct") + internal static let es = ImageAsset(name: "es") + internal static let et = ImageAsset(name: "et") + internal static let eu = ImageAsset(name: "eu") + internal static let fi = ImageAsset(name: "fi") + internal static let fj = ImageAsset(name: "fj") + internal static let fk = ImageAsset(name: "fk") + internal static let fm = ImageAsset(name: "fm") + internal static let fo = ImageAsset(name: "fo") + internal static let fr = ImageAsset(name: "fr") + internal static let ga = ImageAsset(name: "ga") + internal static let gbEng = ImageAsset(name: "gb-eng") + internal static let gbNir = ImageAsset(name: "gb-nir") + internal static let gbSct = ImageAsset(name: "gb-sct") + internal static let gbWls = ImageAsset(name: "gb-wls") + internal static let gb = ImageAsset(name: "gb") + internal static let gd = ImageAsset(name: "gd") + internal static let ge = ImageAsset(name: "ge") + internal static let gf = ImageAsset(name: "gf") + internal static let gg = ImageAsset(name: "gg") + internal static let gh = ImageAsset(name: "gh") + internal static let gi = ImageAsset(name: "gi") + internal static let gl = ImageAsset(name: "gl") + internal static let gm = ImageAsset(name: "gm") + internal static let gn = ImageAsset(name: "gn") + internal static let gp = ImageAsset(name: "gp") + internal static let gq = ImageAsset(name: "gq") + internal static let gr = ImageAsset(name: "gr") + internal static let gs = ImageAsset(name: "gs") + internal static let gt = ImageAsset(name: "gt") + internal static let gu = ImageAsset(name: "gu") + internal static let gw = ImageAsset(name: "gw") + internal static let gy = ImageAsset(name: "gy") + internal static let hk = ImageAsset(name: "hk") + internal static let hm = ImageAsset(name: "hm") + internal static let hn = ImageAsset(name: "hn") + internal static let hr = ImageAsset(name: "hr") + internal static let ht = ImageAsset(name: "ht") + internal static let hu = ImageAsset(name: "hu") + internal static let id = ImageAsset(name: "id") + internal static let ie = ImageAsset(name: "ie") + internal static let il = ImageAsset(name: "il") + internal static let im = ImageAsset(name: "im") + internal static let `in` = ImageAsset(name: "in") + internal static let io = ImageAsset(name: "io") + internal static let iq = ImageAsset(name: "iq") + internal static let ir = ImageAsset(name: "ir") + internal static let `is` = ImageAsset(name: "is") + internal static let it = ImageAsset(name: "it") + internal static let je = ImageAsset(name: "je") + internal static let jm = ImageAsset(name: "jm") + internal static let jo = ImageAsset(name: "jo") + internal static let jp = ImageAsset(name: "jp") + internal static let ke = ImageAsset(name: "ke") + internal static let kg = ImageAsset(name: "kg") + internal static let kh = ImageAsset(name: "kh") + internal static let ki = ImageAsset(name: "ki") + internal static let km = ImageAsset(name: "km") + internal static let kn = ImageAsset(name: "kn") + internal static let kp = ImageAsset(name: "kp") + internal static let kr = ImageAsset(name: "kr") + internal static let kw = ImageAsset(name: "kw") + internal static let ky = ImageAsset(name: "ky") + internal static let kz = ImageAsset(name: "kz") + internal static let la = ImageAsset(name: "la") + internal static let lb = ImageAsset(name: "lb") + internal static let lc = ImageAsset(name: "lc") + internal static let li = ImageAsset(name: "li") + internal static let lk = ImageAsset(name: "lk") + internal static let lr = ImageAsset(name: "lr") + internal static let ls = ImageAsset(name: "ls") + internal static let lt = ImageAsset(name: "lt") + internal static let lu = ImageAsset(name: "lu") + internal static let lv = ImageAsset(name: "lv") + internal static let ly = ImageAsset(name: "ly") + internal static let ma = ImageAsset(name: "ma") + internal static let mc = ImageAsset(name: "mc") + internal static let md = ImageAsset(name: "md") + internal static let me = ImageAsset(name: "me") + internal static let mf = ImageAsset(name: "mf") + internal static let mg = ImageAsset(name: "mg") + internal static let mh = ImageAsset(name: "mh") + internal static let mk = ImageAsset(name: "mk") + internal static let ml = ImageAsset(name: "ml") + internal static let mm = ImageAsset(name: "mm") + internal static let mn = ImageAsset(name: "mn") + internal static let mo = ImageAsset(name: "mo") + internal static let mp = ImageAsset(name: "mp") + internal static let mq = ImageAsset(name: "mq") + internal static let mr = ImageAsset(name: "mr") + internal static let ms = ImageAsset(name: "ms") + internal static let mt = ImageAsset(name: "mt") + internal static let mu = ImageAsset(name: "mu") + internal static let mv = ImageAsset(name: "mv") + internal static let mw = ImageAsset(name: "mw") + internal static let mx = ImageAsset(name: "mx") + internal static let my = ImageAsset(name: "my") + internal static let mz = ImageAsset(name: "mz") + internal static let na = ImageAsset(name: "na") + internal static let nc = ImageAsset(name: "nc") + internal static let ne = ImageAsset(name: "ne") + internal static let nf = ImageAsset(name: "nf") + internal static let ng = ImageAsset(name: "ng") + internal static let ni = ImageAsset(name: "ni") + internal static let nl = ImageAsset(name: "nl") + internal static let no = ImageAsset(name: "no") + internal static let np = ImageAsset(name: "np") + internal static let nr = ImageAsset(name: "nr") + internal static let nu = ImageAsset(name: "nu") + internal static let nz = ImageAsset(name: "nz") + internal static let om = ImageAsset(name: "om") + internal static let pa = ImageAsset(name: "pa") + internal static let pe = ImageAsset(name: "pe") + internal static let pf = ImageAsset(name: "pf") + internal static let pg = ImageAsset(name: "pg") + internal static let ph = ImageAsset(name: "ph") + internal static let pk = ImageAsset(name: "pk") + internal static let pl = ImageAsset(name: "pl") + internal static let pm = ImageAsset(name: "pm") + internal static let pn = ImageAsset(name: "pn") + internal static let pr = ImageAsset(name: "pr") + internal static let ps = ImageAsset(name: "ps") + internal static let pt = ImageAsset(name: "pt") + internal static let pw = ImageAsset(name: "pw") + internal static let py = ImageAsset(name: "py") + internal static let qa = ImageAsset(name: "qa") + internal static let re = ImageAsset(name: "re") + internal static let ro = ImageAsset(name: "ro") + internal static let rs = ImageAsset(name: "rs") + internal static let ru = ImageAsset(name: "ru") + internal static let rw = ImageAsset(name: "rw") + internal static let sa = ImageAsset(name: "sa") + internal static let sb = ImageAsset(name: "sb") + internal static let sc = ImageAsset(name: "sc") + internal static let sd = ImageAsset(name: "sd") + internal static let se = ImageAsset(name: "se") + internal static let sg = ImageAsset(name: "sg") + internal static let sh = ImageAsset(name: "sh") + internal static let si = ImageAsset(name: "si") + internal static let sj = ImageAsset(name: "sj") + internal static let sk = ImageAsset(name: "sk") + internal static let sl = ImageAsset(name: "sl") + internal static let sm = ImageAsset(name: "sm") + internal static let sn = ImageAsset(name: "sn") + internal static let so = ImageAsset(name: "so") + internal static let sr = ImageAsset(name: "sr") + internal static let ss = ImageAsset(name: "ss") + internal static let st = ImageAsset(name: "st") + internal static let sv = ImageAsset(name: "sv") + internal static let sx = ImageAsset(name: "sx") + internal static let sy = ImageAsset(name: "sy") + internal static let sz = ImageAsset(name: "sz") + internal static let tc = ImageAsset(name: "tc") + internal static let td = ImageAsset(name: "td") + internal static let tf = ImageAsset(name: "tf") + internal static let tg = ImageAsset(name: "tg") + internal static let th = ImageAsset(name: "th") + internal static let tj = ImageAsset(name: "tj") + internal static let tk = ImageAsset(name: "tk") + internal static let tl = ImageAsset(name: "tl") + internal static let tm = ImageAsset(name: "tm") + internal static let tn = ImageAsset(name: "tn") + internal static let to = ImageAsset(name: "to") + internal static let tr = ImageAsset(name: "tr") + internal static let tt = ImageAsset(name: "tt") + internal static let tv = ImageAsset(name: "tv") + internal static let tw = ImageAsset(name: "tw") + internal static let tz = ImageAsset(name: "tz") + internal static let ua = ImageAsset(name: "ua") + internal static let ug = ImageAsset(name: "ug") + internal static let um = ImageAsset(name: "um") + internal static let un = ImageAsset(name: "un") + internal static let us = ImageAsset(name: "us") + internal static let uy = ImageAsset(name: "uy") + internal static let uz = ImageAsset(name: "uz") + internal static let va = ImageAsset(name: "va") + internal static let vc = ImageAsset(name: "vc") + internal static let ve = ImageAsset(name: "ve") + internal static let vg = ImageAsset(name: "vg") + internal static let vi = ImageAsset(name: "vi") + internal static let vn = ImageAsset(name: "vn") + internal static let vu = ImageAsset(name: "vu") + internal static let wf = ImageAsset(name: "wf") + internal static let ws = ImageAsset(name: "ws") + internal static let xk = ImageAsset(name: "xk") + internal static let ye = ImageAsset(name: "ye") + internal static let yt = ImageAsset(name: "yt") + internal static let za = ImageAsset(name: "za") + internal static let zm = ImageAsset(name: "zm") + 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") + internal static let pia = ImageAsset(name: "pia") + internal static let placeholder = ImageAsset(name: "placeholder") + internal static let protonvpn = ImageAsset(name: "protonvpn") + internal static let torguard = ImageAsset(name: "torguard") + internal static let tunnelbear = ImageAsset(name: "tunnelbear") + internal static let vyprvpn = ImageAsset(name: "vyprvpn") + internal static let windscribe = ImageAsset(name: "windscribe") + } +} +// swiftlint:enable identifier_name line_length nesting type_body_length type_name + +// MARK: - Implementation Details + +internal struct ImageAsset { + internal fileprivate(set) var name: String + + #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 = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + let image = bundle.image(forResource: NSImage.Name(name)) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load image named \(name).") + } + return result + } +} + +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 = BundleToken.bundle + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSImage.Name(asset.name)) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + Bundle(for: BundleToken.self) + }() +} +// swiftlint:enable convenience_type diff --git a/Passepartout/App/macOS/Global/SwiftGen+Scenes.swift b/Passepartout/App/macOS/Global/SwiftGen+Scenes.swift new file mode 100644 index 00000000..ba32d10b --- /dev/null +++ b/Passepartout/App/macOS/Global/SwiftGen+Scenes.swift @@ -0,0 +1,82 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import AppKit + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Storyboard Scenes + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +internal enum StoryboardScene { + internal enum Main: StoryboardType { + internal static let storyboardName = "Main" + + internal static let organizerWindowController = SceneType(storyboard: Main.self, identifier: "OrganizerWindowController") + + internal static let textInputViewController = SceneType(storyboard: Main.self, identifier: "TextInputViewController") + } + internal enum Preferences: StoryboardType { + internal static let storyboardName = "Preferences" + + internal static let initialScene = InitialSceneType(storyboard: Preferences.self) + } + internal enum Service: StoryboardType { + internal static let storyboardName = "Service" + + internal static let initialScene = InitialSceneType(storyboard: Service.self) + + internal static let accountViewController = SceneType(storyboard: Service.self, identifier: "AccountViewController") + + internal static let profileCustomizationContainerViewController = SceneType(storyboard: Service.self, identifier: "ProfileCustomizationContainerViewController") + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +// MARK: - Implementation Details + +internal protocol StoryboardType { + static var storyboardName: String { get } +} + +internal extension StoryboardType { + static var storyboard: NSStoryboard { + let name = NSStoryboard.Name(self.storyboardName) + return NSStoryboard(name: name, bundle: BundleToken.bundle) + } +} + +internal struct SceneType { + internal let storyboard: StoryboardType.Type + internal let identifier: String + + internal func instantiate() -> T { + let identifier = NSStoryboard.SceneIdentifier(self.identifier) + guard let controller = storyboard.storyboard.instantiateController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +internal struct InitialSceneType { + internal let storyboard: StoryboardType.Type + + internal func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller + } +} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + Bundle(for: BundleToken.self) + }() +} +// swiftlint:enable convenience_type diff --git a/Passepartout/App/macOS/Global/SwiftGen+Segues.swift b/Passepartout/App/macOS/Global/SwiftGen+Segues.swift new file mode 100644 index 00000000..49a2ca52 --- /dev/null +++ b/Passepartout/App/macOS/Global/SwiftGen+Segues.swift @@ -0,0 +1,54 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import AppKit + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Storyboard Segues + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +internal enum StoryboardSegue { + internal enum Main: String, SegueType { + case enterAccountSegueIdentifier = "EnterAccountSegueIdentifier" + case renameProfileSegueIdentifier = "RenameProfileSegueIdentifier" + } + internal enum Service: String, SegueType { + case accountSegueIdentifier = "AccountSegueIdentifier" + case customizeSegueIdentifier = "CustomizeSegueIdentifier" + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +// MARK: - Implementation Details + +internal protocol SegueType: RawRepresentable {} + +internal extension NSSeguePerforming { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + let identifier = NSStoryboardSegue.Identifier(segue.rawValue) + performSegue?(withIdentifier: identifier, sender: sender) + } +} + +internal extension SegueType where RawValue == String { + init?(_ segue: NSStoryboardSegue) { + #if swift(>=4.2) + guard let identifier = segue.identifier else { return nil } + #else + guard let identifier = segue.identifier?.rawValue else { return nil } + #endif + self.init(rawValue: identifier) + } +} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + Bundle(for: BundleToken.self) + }() +} +// swiftlint:enable convenience_type diff --git a/Passepartout/App/macOS/Global/SwiftGen+Strings.swift b/Passepartout/App/macOS/Global/SwiftGen+Strings.swift new file mode 100644 index 00000000..fea51209 --- /dev/null +++ b/Passepartout/App/macOS/Global/SwiftGen+Strings.swift @@ -0,0 +1,1114 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +import Foundation + +// swiftlint:disable superfluous_disable_command file_length implicit_return + +// MARK: - Strings + +// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length +// swiftlint:disable nesting type_body_length type_name +internal enum L10n { + internal enum App { + internal enum Configuration { + /// Configuration + internal static let title = L10n.tr("App", "configuration.title") + internal enum Alerts { + internal enum Commit { + /// New parameters will not be effective until you reconnect manually. Changes in trusted networks will apply immediately. + internal static let message = L10n.tr("App", "configuration.alerts.commit.message") + internal enum Buttons { + /// Reconnect now + internal static let reconnect = L10n.tr("App", "configuration.alerts.commit.buttons.reconnect") + /// Skip + internal static let skip = L10n.tr("App", "configuration.alerts.commit.buttons.skip") + } + } + } + } + internal enum Endpoint { + internal enum Cells { + /// Address + internal static let address = L10n.tr("App", "endpoint.cells.address") + /// Protocol + internal static let `protocol` = L10n.tr("App", "endpoint.cells.protocol") + } + } + internal enum Global { + internal enum Values { + /// Default + internal static let `default` = L10n.tr("App", "global.values.default") + } + } + internal enum Menu { + internal enum ActiveProfile { + internal enum Items { + internal enum Customize { + /// Customize... + internal static let title = L10n.tr("App", "menu.active_profile.items.customize.title") + } + } + internal enum Messages { + /// No account configured + internal static let missingCredentials = L10n.tr("App", "menu.active_profile.messages.missing_credentials") + } + internal enum Title { + /// No active profile + internal static let `none` = L10n.tr("App", "menu.active_profile.title.none") + } + } + internal enum Organizer { + /// Organizer + internal static let title = L10n.tr("App", "menu.organizer.title") + } + internal enum Preferences { + /// Preferences + internal static let title = L10n.tr("App", "menu.preferences.title") + } + internal enum Quit { + /// Quit %@ + internal static func title(_ p1: Any) -> String { + return L10n.tr("App", "menu.quit.title", String(describing: p1)) + } + internal enum Messages { + /// The VPN, if enabled, will still run in the background. Do you want to quit? + internal static let confirm = L10n.tr("App", "menu.quit.messages.confirm") + } + } + internal enum Support { + /// Support + internal static let title = L10n.tr("App", "menu.support.title") + } + internal enum SwitchProfile { + /// Active profile + internal static let title = L10n.tr("App", "menu.switch_profile.title") + } + } + internal enum NetworkSettings { + internal enum Dns { + internal enum Cells { + internal enum Addresses { + /// Servers + internal static let title = L10n.tr("App", "network_settings.dns.cells.addresses.title") + } + internal enum Domains { + /// Domains + internal static let title = L10n.tr("App", "network_settings.dns.cells.domains.title") + } + } + } + internal enum Proxy { + internal enum Cells { + internal enum BypassDomains { + /// Bypass domains + internal static let title = L10n.tr("App", "network_settings.proxy.cells.bypass_domains.title") + } + } + } + } + internal enum Organizer { + /// %@ + internal static func title(_ p1: Any) -> String { + return L10n.tr("App", "organizer.title", String(describing: p1)) + } + internal enum Alerts { + internal enum OpenHostFile { + /// Select an .ovpn file + internal static let title = L10n.tr("App", "organizer.alerts.open_host_file.title") + } + internal enum RemoveProfile { + /// Are you sure you want to delete profile %@? + internal static func message(_ p1: Any) -> String { + return L10n.tr("App", "organizer.alerts.remove_profile.message", String(describing: p1)) + } + /// Remove profile + internal static let title = L10n.tr("App", "organizer.alerts.remove_profile.title") + } + } + internal enum Menus { + /// Host + internal static let host = L10n.tr("App", "organizer.menus.host") + /// Provider + internal static let provider = L10n.tr("App", "organizer.menus.provider") + internal enum Provider { + /// No providers left + internal static let unavailable = L10n.tr("App", "organizer.menus.provider.unavailable") + } + } + } + internal enum Preferences { + /// %@ Preferences + internal static func title(_ p1: Any) -> String { + return L10n.tr("App", "preferences.title", String(describing: p1)) + } + internal enum Cells { + internal enum LaunchesOnLogin { + /// Launch on login + internal static let caption = L10n.tr("App", "preferences.cells.launches_on_login.caption") + /// Check to automatically launch the app on boot or login. + internal static let footer = L10n.tr("App", "preferences.cells.launches_on_login.footer") + } + } + internal enum Sections { + internal enum General { + /// General + internal static let header = L10n.tr("App", "preferences.sections.general.header") + } + } + } + internal enum Service { + internal enum Cells { + internal enum Addresses { + /// Addresses + internal static let caption = L10n.tr("App", "service.cells.addresses.caption") + } + internal enum Category { + /// Category + internal static let caption = L10n.tr("App", "service.cells.category.caption") + } + internal enum Vpn { + internal enum TurnOff { + /// Disable VPN + internal static let caption = L10n.tr("App", "service.cells.vpn.turn_off.caption") + } + internal enum TurnOn { + /// Enable VPN + internal static let caption = L10n.tr("App", "service.cells.vpn.turn_on.caption") + } + } + } + } + internal enum Trusted { + internal enum Columns { + internal enum Trust { + /// Trust + internal static let title = L10n.tr("App", "trusted.columns.trust.title") + } + } + internal enum Ethernet { + /// Check to trust any wired cable connection. + internal static let description = L10n.tr("App", "trusted.ethernet.description") + /// Trust wired connections + internal static let title = L10n.tr("App", "trusted.ethernet.title") + } + } + internal enum Vpn { + /// Off + internal static let unused = L10n.tr("App", "vpn.unused") + } + } + internal enum Core { + internal enum About { + /// About + internal static let title = L10n.tr("Core", "about.title") + internal enum Cells { + internal enum Credits { + /// Credits + internal static let caption = L10n.tr("Core", "about.cells.credits.caption") + } + internal enum Disclaimer { + /// Disclaimer + internal static let caption = L10n.tr("Core", "about.cells.disclaimer.caption") + } + internal enum Faq { + /// FAQ + internal static let caption = L10n.tr("Core", "about.cells.faq.caption") + } + internal enum PrivacyPolicy { + /// Privacy policy + internal static let caption = L10n.tr("Core", "about.cells.privacy_policy.caption") + } + internal enum ShareGeneric { + /// Invite a friend + internal static let caption = L10n.tr("Core", "about.cells.share_generic.caption") + } + internal enum ShareTwitter { + /// Tweet about it! + internal static let caption = L10n.tr("Core", "about.cells.share_twitter.caption") + } + internal enum Website { + /// Home page + internal static let caption = L10n.tr("Core", "about.cells.website.caption") + } + } + internal enum Sections { + internal enum Share { + /// Share + internal static let header = L10n.tr("Core", "about.sections.share.header") + } + internal enum Web { + /// Web + internal static let header = L10n.tr("Core", "about.sections.web.header") + } + } + } + internal enum Account { + /// Account + internal static let title = L10n.tr("Core", "account.title") + internal enum Cells { + internal enum OpenGuide { + /// See your credentials + internal static let caption = L10n.tr("Core", "account.cells.open_guide.caption") + } + internal enum Password { + /// Password + internal static let caption = L10n.tr("Core", "account.cells.password.caption") + /// secret + internal static let placeholder = L10n.tr("Core", "account.cells.password.placeholder") + } + internal enum Signup { + /// Register with %@ + internal static func caption(_ p1: Any) -> String { + return L10n.tr("Core", "account.cells.signup.caption", String(describing: p1)) + } + } + internal enum Username { + /// Username + internal static let caption = L10n.tr("Core", "account.cells.username.caption") + /// username + internal static let placeholder = L10n.tr("Core", "account.cells.username.placeholder") + } + } + internal enum Sections { + internal enum Guidance { + internal enum Footer { + internal enum Infrastructure { + /// Use your %@ website credentials. + 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: 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: 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: 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: 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: 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: 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: 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: 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: Any) -> String { + return L10n.tr("Core", "account.sections.registration.footer", String(describing: p1)) + } + } + } + } + internal enum Configuration { + internal enum Cells { + internal enum Cipher { + /// Cipher + internal static let caption = L10n.tr("Core", "configuration.cells.cipher.caption") + } + internal enum Client { + /// Client certificate + internal static let caption = L10n.tr("Core", "configuration.cells.client.caption") + internal enum Value { + /// Not verified + internal static let disabled = L10n.tr("Core", "configuration.cells.client.value.disabled") + /// Verified + internal static let enabled = L10n.tr("Core", "configuration.cells.client.value.enabled") + } + } + internal enum CompressionAlgorithm { + /// Algorithm + internal static let caption = L10n.tr("Core", "configuration.cells.compression_algorithm.caption") + internal enum Value { + /// LZO + internal static let lzo = L10n.tr("Core", "configuration.cells.compression_algorithm.value.lzo") + /// Unsupported + internal static let other = L10n.tr("Core", "configuration.cells.compression_algorithm.value.other") + } + } + internal enum CompressionFraming { + /// Framing + internal static let caption = L10n.tr("Core", "configuration.cells.compression_framing.caption") + internal enum Value { + /// --compress + internal static let compress = L10n.tr("Core", "configuration.cells.compression_framing.value.compress") + /// --comp-lzo + internal static let lzo = L10n.tr("Core", "configuration.cells.compression_framing.value.lzo") + } + } + internal enum Digest { + /// Authentication + internal static let caption = L10n.tr("Core", "configuration.cells.digest.caption") + internal enum Value { + /// Embedded + internal static let embedded = L10n.tr("Core", "configuration.cells.digest.value.embedded") + } + } + internal enum Eku { + /// Extended verification + internal static let caption = L10n.tr("Core", "configuration.cells.eku.caption") + } + internal enum KeepAlive { + /// Keep-alive + internal static let caption = L10n.tr("Core", "configuration.cells.keep_alive.caption") + internal enum Value { + /// %d seconds + internal static func seconds(_ p1: Int) -> String { + return L10n.tr("Core", "configuration.cells.keep_alive.value.seconds", p1) + } + } + } + internal enum RandomEndpoint { + /// Randomize endpoint + internal static let caption = L10n.tr("Core", "configuration.cells.random_endpoint.caption") + } + internal enum RenegotiationSeconds { + /// Renegotiation + internal static let caption = L10n.tr("Core", "configuration.cells.renegotiation_seconds.caption") + internal enum Value { + /// after %@ + internal static func after(_ p1: Any) -> String { + return L10n.tr("Core", "configuration.cells.renegotiation_seconds.value.after", String(describing: p1)) + } + } + } + internal enum ResetOriginal { + /// Reset configuration + internal static let caption = L10n.tr("Core", "configuration.cells.reset_original.caption") + } + internal enum TlsWrapping { + /// Wrapping + internal static let caption = L10n.tr("Core", "configuration.cells.tls_wrapping.caption") + internal enum Value { + /// Authentication + internal static let auth = L10n.tr("Core", "configuration.cells.tls_wrapping.value.auth") + /// Encryption + internal static let crypt = L10n.tr("Core", "configuration.cells.tls_wrapping.value.crypt") + } + } + } + internal enum Sections { + internal enum Communication { + /// Communication + internal static let header = L10n.tr("Core", "configuration.sections.communication.header") + } + internal enum Compression { + /// Compression + internal static let header = L10n.tr("Core", "configuration.sections.compression.header") + } + internal enum Network { + /// Network + internal static let header = L10n.tr("Core", "configuration.sections.network.header") + } + internal enum Other { + /// Other + internal static let header = L10n.tr("Core", "configuration.sections.other.header") + } + internal enum Reset { + /// If you ended up with broken connectivity after changing the communication parameters, tap to revert to the original configuration. + internal static let footer = L10n.tr("Core", "configuration.sections.reset.footer") + } + internal enum Tls { + /// TLS + internal static let header = L10n.tr("Core", "configuration.sections.tls.header") + } + } + } + internal enum Credits { + /// Credits + internal static let title = L10n.tr("Core", "credits.title") + internal enum Sections { + internal enum Licenses { + /// Licenses + internal static let header = L10n.tr("Core", "credits.sections.licenses.header") + } + internal enum Notices { + /// Notices + internal static let header = L10n.tr("Core", "credits.sections.notices.header") + } + internal enum Translations { + /// Translations + internal static let header = L10n.tr("Core", "credits.sections.translations.header") + } + } + } + internal enum DebugLog { + internal enum Alerts { + internal enum EmptyLog { + /// The debug log is empty. + internal static let message = L10n.tr("Core", "debug_log.alerts.empty_log.message") + } + } + internal enum Buttons { + /// Next + internal static let next = L10n.tr("Core", "debug_log.buttons.next") + /// Previous + internal static let previous = L10n.tr("Core", "debug_log.buttons.previous") + } + } + internal enum Donation { + /// Donate + internal static let title = L10n.tr("Core", "donation.title") + internal enum Alerts { + internal enum Purchase { + internal enum Failure { + /// Unable to perform the donation. %@ + internal static func message(_ p1: Any) -> String { + return L10n.tr("Core", "donation.alerts.purchase.failure.message", String(describing: p1)) + } + } + internal enum Success { + /// This means a lot to me and I really hope you keep using and promoting this app. + internal static let message = L10n.tr("Core", "donation.alerts.purchase.success.message") + /// Thank you + internal static let title = L10n.tr("Core", "donation.alerts.purchase.success.title") + } + } + } + internal enum Cells { + internal enum Loading { + /// Loading donations + internal static let caption = L10n.tr("Core", "donation.cells.loading.caption") + } + internal enum Purchasing { + /// Performing donation + internal static let caption = L10n.tr("Core", "donation.cells.purchasing.caption") + } + } + internal enum Sections { + internal enum OneTime { + /// If you want to display gratitude for my free work, here are a couple amounts you can donate instantly.\n\nYou will only be charged once per donation, and you can donate multiple times. + internal static let footer = L10n.tr("Core", "donation.sections.one_time.footer") + /// One time + internal static let header = L10n.tr("Core", "donation.sections.one_time.header") + } + } + } + internal enum Endpoint { + /// Endpoint + internal static let title = L10n.tr("Core", "endpoint.title") + internal enum Cells { + internal enum AnyAddress { + /// Automatic + internal static let caption = L10n.tr("Core", "endpoint.cells.any_address.caption") + } + internal enum AnyProtocol { + /// Automatic + internal static let caption = L10n.tr("Core", "endpoint.cells.any_protocol.caption") + } + } + } + internal enum Global { + /// Cancel + internal static let cancel = L10n.tr("Core", "global.cancel") + /// Close + internal static let close = L10n.tr("Core", "global.close") + /// No e-mail account is configured. + internal static let emailNotConfigured = L10n.tr("Core", "global.email_not_configured") + /// Next + internal static let next = L10n.tr("Core", "global.next") + /// OK + internal static let ok = L10n.tr("Core", "global.ok") + internal enum Captions { + /// Address + internal static let address = L10n.tr("Core", "global.captions.address") + /// Port + internal static let port = L10n.tr("Core", "global.captions.port") + } + internal enum Host { + internal enum TitleInput { + /// Acceptable characters are alphanumerics plus dash "-", underscore "_" and dot ".". + internal static let message = L10n.tr("Core", "global.host.title_input.message") + /// My profile + internal static let placeholder = L10n.tr("Core", "global.host.title_input.placeholder") + } + } + internal enum Values { + /// Automatic + internal static let automatic = L10n.tr("Core", "global.values.automatic") + /// Disabled + internal static let disabled = L10n.tr("Core", "global.values.disabled") + /// Enabled + internal static let enabled = L10n.tr("Core", "global.values.enabled") + /// Manual + internal static let manual = L10n.tr("Core", "global.values.manual") + /// None + internal static let `none` = L10n.tr("Core", "global.values.none") + } + } + internal enum IssueReporter { + /// The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous.\n\nThe .ovpn configuration file, if any, is attached stripped of any sensitive data.\n\nPlease double check the e-mail attachments if unsure. + internal static let message = L10n.tr("Core", "issue_reporter.message") + /// Report issue + internal static let title = L10n.tr("Core", "issue_reporter.title") + internal enum Buttons { + /// I understand + internal static let accept = L10n.tr("Core", "issue_reporter.buttons.accept") + } + } + internal enum Label { + internal enum License { + /// Unable to download full license content. + internal static let error = L10n.tr("Core", "label.license.error") + } + } + internal enum NetworkChoice { + /// Read .ovpn + internal static let client = L10n.tr("Core", "network_choice.client") + /// Pull from server + internal static let server = L10n.tr("Core", "network_choice.server") + } + internal enum NetworkSettings { + /// Network settings + internal static let title = L10n.tr("Core", "network_settings.title") + internal enum Dns { + /// DNS + internal static let title = L10n.tr("Core", "network_settings.dns.title") + internal enum Cells { + internal enum Domain { + /// Domain + internal static let caption = L10n.tr("Core", "network_settings.dns.cells.domain.caption") + } + } + } + internal enum Gateway { + /// Default gateway + internal static let title = L10n.tr("Core", "network_settings.gateway.title") + } + internal enum Mtu { + /// MTU + internal static let title = L10n.tr("Core", "network_settings.mtu.title") + internal enum Cells { + internal enum Bytes { + /// Bytes + internal static let caption = L10n.tr("Core", "network_settings.mtu.cells.bytes.caption") + } + } + } + internal enum Proxy { + /// Proxy + internal static let title = L10n.tr("Core", "network_settings.proxy.title") + } + } + internal enum Organizer { + internal enum Alerts { + internal enum AddHost { + /// Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile.\n\nYou can also import an .ovpn with iTunes File Sharing. + internal static let message = L10n.tr("Core", "organizer.alerts.add_host.message") + } + internal enum CannotDonate { + /// There is no payment method configured on this device. + internal static let message = L10n.tr("Core", "organizer.alerts.cannot_donate.message") + } + internal enum DeleteVpnProfile { + /// Do you really want to erase the VPN configuration from your device settings? This may fix some broken VPN states and will not affect your provider and host profiles. + internal static let message = L10n.tr("Core", "organizer.alerts.delete_vpn_profile.message") + } + internal enum ExhaustedProviders { + /// You have created profiles for any available provider. + internal static let message = L10n.tr("Core", "organizer.alerts.exhausted_providers.message") + } + } + internal enum Cells { + internal enum About { + /// About %@ + internal static func caption(_ p1: Any) -> String { + return L10n.tr("Core", "organizer.cells.about.caption", String(describing: p1)) + } + } + internal enum Donate { + /// Make a donation + internal static let caption = L10n.tr("Core", "organizer.cells.donate.caption") + } + internal enum FollowTwitch { + /// Watch Passepartout on Twitch + internal static let caption = L10n.tr("Core", "organizer.cells.follow_twitch.caption") + } + internal enum GithubSponsors { + /// Support me on GitHub + internal static let caption = L10n.tr("Core", "organizer.cells.github_sponsors.caption") + } + internal enum JoinCommunity { + /// Join community + internal static let caption = L10n.tr("Core", "organizer.cells.join_community.caption") + } + internal enum Profile { + internal enum Value { + /// In use + internal static let current = L10n.tr("Core", "organizer.cells.profile.value.current") + } + } + internal enum SiriShortcuts { + /// Manage shortcuts + internal static let caption = L10n.tr("Core", "organizer.cells.siri_shortcuts.caption") + } + internal enum Translate { + /// Offer to translate + internal static let caption = L10n.tr("Core", "organizer.cells.translate.caption") + } + internal enum Uninstall { + /// Remove VPN configuration + internal static let caption = L10n.tr("Core", "organizer.cells.uninstall.caption") + } + internal enum WriteReview { + /// Write a review + internal static let caption = L10n.tr("Core", "organizer.cells.write_review.caption") + } + } + internal enum Sections { + internal enum Feedback { + /// Feedback + internal static let header = L10n.tr("Core", "organizer.sections.feedback.header") + } + internal enum Hosts { + /// Import hosts from raw .ovpn configuration files. + internal static let footer = L10n.tr("Core", "organizer.sections.hosts.footer") + /// Hosts + internal static let header = L10n.tr("Core", "organizer.sections.hosts.header") + } + internal enum Providers { + /// Here you find a few providers with preset configuration profiles. + internal static let footer = L10n.tr("Core", "organizer.sections.providers.footer") + /// Providers + internal static let header = L10n.tr("Core", "organizer.sections.providers.header") + } + internal enum Siri { + /// Get help from Siri to speed up your most common interactions with the app. + internal static let footer = L10n.tr("Core", "organizer.sections.siri.footer") + /// Siri + internal static let header = L10n.tr("Core", "organizer.sections.siri.header") + } + internal enum Support { + /// Support + internal static let header = L10n.tr("Core", "organizer.sections.support.header") + } + internal enum Twitch { + /// Come watch me make Passepartout live on Twitch, join the chat to interact and contribute! + internal static let footer = L10n.tr("Core", "organizer.sections.twitch.footer") + /// Twitch + internal static let header = L10n.tr("Core", "organizer.sections.twitch.header") + } + } + } + internal enum ParsedFile { + internal enum Alerts { + internal enum Buttons { + /// Report an issue + internal static let report = L10n.tr("Core", "parsed_file.alerts.buttons.report") + } + internal enum Decryption { + /// The configuration contains an encrypted private key and it could not be decrypted. Double check your entered passphrase. + internal static let message = L10n.tr("Core", "parsed_file.alerts.decryption.message") + } + internal enum EncryptionPassphrase { + /// Please enter the encryption passphrase. + internal static let message = L10n.tr("Core", "parsed_file.alerts.encryption_passphrase.message") + } + internal enum Malformed { + /// The configuration file contains a malformed option (%@). + 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: 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: 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: 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: Any) -> String { + return L10n.tr("Core", "parsed_file.alerts.unsupported.message", String(describing: p1)) + } + } + } + } + internal enum Reddit { + /// Did you know that Passepartout has a subreddit? Subscribe for updates or to discuss issues, features, new platforms or whatever you like.\n\nIt's also a great way to show you care about this project. + internal static let message = L10n.tr("Core", "reddit.message") + /// Reddit + internal static let title = L10n.tr("Core", "reddit.title") + internal enum Buttons { + /// Don't ask again + internal static let never = L10n.tr("Core", "reddit.buttons.never") + /// Remind me later + internal static let remind = L10n.tr("Core", "reddit.buttons.remind") + /// Subscribe now! + internal static let subscribe = L10n.tr("Core", "reddit.buttons.subscribe") + } + } + internal enum ServerNetwork { + internal enum Cells { + internal enum Route { + /// Route + internal static let caption = L10n.tr("Core", "server_network.cells.route.caption") + } + } + } + internal enum Service { + internal enum Alerts { + internal enum Buttons { + /// Reconnect + internal static let reconnect = L10n.tr("Core", "service.alerts.buttons.reconnect") + } + internal enum Configuration { + /// Configuration unavailable, make sure you are connected to the VPN. + internal static let disconnected = L10n.tr("Core", "service.alerts.configuration.disconnected") + } + internal enum CredentialsNeeded { + /// You need to enter account credentials first. + internal static let message = L10n.tr("Core", "service.alerts.credentials_needed.message") + } + internal enum Download { + /// Failed to download configuration files. %@ + 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: 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") + internal enum Hud { + /// Extracting files, please be patient... + internal static let extracting = L10n.tr("Core", "service.alerts.download.hud.extracting") + } + } + internal enum MasksPrivateData { + internal enum Messages { + /// In order to safely reset the current debug log and apply the new masking preference, you must reconnect to the VPN now. + internal static let mustReconnect = L10n.tr("Core", "service.alerts.masks_private_data.messages.must_reconnect") + } + } + internal enum ReconnectVpn { + /// Do you want to reconnect to the VPN? + internal static let message = L10n.tr("Core", "service.alerts.reconnect_vpn.message") + } + internal enum Rename { + /// Rename profile + internal static let title = L10n.tr("Core", "service.alerts.rename.title") + } + internal enum TestConnectivity { + /// Connectivity + internal static let title = L10n.tr("Core", "service.alerts.test_connectivity.title") + internal enum Messages { + /// Your device has no Internet connectivity, please review your profile parameters. + internal static let failure = L10n.tr("Core", "service.alerts.test_connectivity.messages.failure") + /// Your device is connected to the Internet! + internal static let success = L10n.tr("Core", "service.alerts.test_connectivity.messages.success") + } + } + internal enum Trusted { + internal enum NoNetwork { + /// You are not connected to any Wi-Fi network. + internal static let message = L10n.tr("Core", "service.alerts.trusted.no_network.message") + } + internal enum WillDisconnectPolicy { + /// By changing the trust policy, the VPN may be disconnected. Continue? + internal static let message = L10n.tr("Core", "service.alerts.trusted.will_disconnect_policy.message") + } + internal enum WillDisconnectTrusted { + /// By trusting this network, the VPN may be disconnected. Continue? + internal static let message = L10n.tr("Core", "service.alerts.trusted.will_disconnect_trusted.message") + } + } + } + internal enum Cells { + internal enum ConnectionStatus { + /// Status + internal static let caption = L10n.tr("Core", "service.cells.connection_status.caption") + } + internal enum DataCount { + /// Exchanged data + internal static let caption = L10n.tr("Core", "service.cells.data_count.caption") + /// Unavailable + internal static let `none` = L10n.tr("Core", "service.cells.data_count.none") + } + internal enum DebugLog { + /// Debug log + internal static let caption = L10n.tr("Core", "service.cells.debug_log.caption") + } + internal enum MasksPrivateData { + /// Mask network data + internal static let caption = L10n.tr("Core", "service.cells.masks_private_data.caption") + } + internal enum Provider { + internal enum Pool { + /// Location + internal static let caption = L10n.tr("Core", "service.cells.provider.pool.caption") + } + internal enum Preset { + /// Preset + internal static let caption = L10n.tr("Core", "service.cells.provider.preset.caption") + } + } + internal enum Reconnect { + /// Reconnect + internal static let caption = L10n.tr("Core", "service.cells.reconnect.caption") + } + internal enum ReportIssue { + /// Report connectivity issue + internal static let caption = L10n.tr("Core", "service.cells.report_issue.caption") + } + internal enum ServerConfiguration { + /// Server configuration + internal static let caption = L10n.tr("Core", "service.cells.server_configuration.caption") + } + internal enum ServerNetwork { + /// Server network + internal static let caption = L10n.tr("Core", "service.cells.server_network.caption") + } + internal enum TestConnectivity { + /// Test connectivity + internal static let caption = L10n.tr("Core", "service.cells.test_connectivity.caption") + } + internal enum TrustedMobile { + /// Cellular network + internal static let caption = L10n.tr("Core", "service.cells.trusted_mobile.caption") + } + internal enum TrustedPolicy { + /// Trust disables VPN + internal static let caption = L10n.tr("Core", "service.cells.trusted_policy.caption") + } + internal enum UseProfile { + /// Use this profile + internal static let caption = L10n.tr("Core", "service.cells.use_profile.caption") + } + internal enum VpnResolvesHostname { + /// Resolve provider hostname + internal static let caption = L10n.tr("Core", "service.cells.vpn_resolves_hostname.caption") + } + internal enum VpnSurvivesSleep { + /// Keep alive on sleep + internal static let caption = L10n.tr("Core", "service.cells.vpn_survives_sleep.caption") + } + } + internal enum Sections { + internal enum Diagnostics { + /// Masking status will be effective after reconnecting. Network data are hostnames, IP addresses, routing, SSID. Credentials and private keys are not logged regardless. + internal static let footer = L10n.tr("Core", "service.sections.diagnostics.footer") + /// Diagnostics + internal static let header = L10n.tr("Core", "service.sections.diagnostics.header") + } + internal enum ProviderInfrastructure { + /// Last updated on %@. + internal static func footer(_ p1: Any) -> String { + return L10n.tr("Core", "service.sections.provider_infrastructure.footer", String(describing: p1)) + } + } + internal enum Trusted { + /// 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("Core", "service.sections.trusted.footer") + /// Trusted networks + internal static let header = L10n.tr("Core", "service.sections.trusted.header") + } + internal enum Vpn { + /// The connection will be established whenever necessary. + internal static let footer = L10n.tr("Core", "service.sections.vpn.footer") + } + internal enum VpnResolvesHostname { + /// Preferred in most networks and required in some IPv6 networks. Disable where DNS is blocked, or to speed up negotiation when DNS is slow to respond. + internal static let footer = L10n.tr("Core", "service.sections.vpn_resolves_hostname.footer") + } + internal enum VpnSurvivesSleep { + /// Disable to improve battery usage, at the expense of occasional slowdowns due to wake-up reconnections. + internal static let footer = L10n.tr("Core", "service.sections.vpn_survives_sleep.footer") + } + } + internal enum Welcome { + /// Welcome to Passepartout!\n\nUse the organizer to add a new profile. + internal static let message = L10n.tr("Core", "service.welcome.message") + } + } + internal enum Share { + /// Passepartout is an user-friendly, open source OpenVPN client for iOS and macOS + internal static let message = L10n.tr("Core", "share.message") + } + internal enum Shortcuts { + internal enum Add { + internal enum Alerts { + internal enum NoProfiles { + /// There is no profile to connect to. + internal static let message = L10n.tr("Core", "shortcuts.add.alerts.no_profiles.message") + } + } + internal enum Cells { + internal enum Connect { + /// Connect to + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.connect.caption") + } + internal enum DisableVpn { + /// Disable VPN + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.disable_vpn.caption") + } + internal enum EnableVpn { + /// Enable VPN + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.enable_vpn.caption") + } + internal enum TrustCellular { + /// Trust cellular network + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.trust_cellular.caption") + } + internal enum TrustCurrentWifi { + /// Trust current Wi-Fi + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.trust_current_wifi.caption") + } + internal enum UntrustCellular { + /// Untrust cellular network + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.untrust_cellular.caption") + } + internal enum UntrustCurrentWifi { + /// Untrust current Wi-Fi + internal static let caption = L10n.tr("Core", "shortcuts.add.cells.untrust_current_wifi.caption") + } + } + internal enum Sections { + internal enum Cellular { + /// Cellular + internal static let header = L10n.tr("Core", "shortcuts.add.sections.cellular.header") + } + internal enum Vpn { + /// VPN + internal static let header = L10n.tr("Core", "shortcuts.add.sections.vpn.header") + } + internal enum Wifi { + /// Wi-Fi + internal static let header = L10n.tr("Core", "shortcuts.add.sections.wifi.header") + } + } + } + internal enum Edit { + internal enum Sections { + internal enum All { + /// Existing shortcuts + internal static let header = L10n.tr("Core", "shortcuts.edit.sections.all.header") + } + } + } + } + internal enum Translations { + /// Translations + internal static let title = L10n.tr("Core", "translations.title") + } + internal enum Version { + /// Version + internal static let title = L10n.tr("Core", "version.title") + internal enum Labels { + /// Passepartout and TunnelKit are written and maintained by Davide De Rosa (keeshux).\n\nSource code for Passepartout and TunnelKit is publicly available on GitHub under the GPLv3, you can find links in the home page.\n\nPassepartout is a non-official client and is in no way affiliated with OpenVPN Inc. + internal static let intro = L10n.tr("Core", "version.labels.intro") + } + } + internal enum Vpn { + /// Active + internal static let active = L10n.tr("Core", "vpn.active") + /// Connecting + internal static let connecting = L10n.tr("Core", "vpn.connecting") + /// Disabled + internal static let disabled = L10n.tr("Core", "vpn.disabled") + /// Disconnecting + internal static let disconnecting = L10n.tr("Core", "vpn.disconnecting") + /// Inactive + internal static let inactive = L10n.tr("Core", "vpn.inactive") + internal enum Errors { + /// Auth failed + internal static let auth = L10n.tr("Core", "vpn.errors.auth") + /// Compression unsupported + internal static let compression = L10n.tr("Core", "vpn.errors.compression") + /// DNS failed + internal static let dns = L10n.tr("Core", "vpn.errors.dns") + /// Encryption failed + internal static let encryption = L10n.tr("Core", "vpn.errors.encryption") + /// No gateway + internal static let gateway = L10n.tr("Core", "vpn.errors.gateway") + /// Network changed + internal static let network = L10n.tr("Core", "vpn.errors.network") + /// Missing routing + internal static let routing = L10n.tr("Core", "vpn.errors.routing") + /// Server shutdown + internal static let shutdown = L10n.tr("Core", "vpn.errors.shutdown") + /// Timeout + internal static let timeout = L10n.tr("Core", "vpn.errors.timeout") + /// TLS failed + internal static let tls = L10n.tr("Core", "vpn.errors.tls") + } + } + internal enum Wizards { + internal enum Host { + internal enum Alerts { + internal enum Existing { + /// A host profile with the same title already exists. Replace it? + internal static let message = L10n.tr("Core", "wizards.host.alerts.existing.message") + } + } + } + internal enum Provider { + internal enum Alerts { + internal enum Unavailable { + /// Could not download provider infrastructure, please retry later. + internal static let message = L10n.tr("Core", "wizards.provider.alerts.unavailable.message") + } + } + internal enum Cells { + internal enum UpdateList { + /// Update list + internal static let caption = L10n.tr("Core", "wizards.provider.cells.update_list.caption") + } + } + } + } + } +} +// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length +// swiftlint:enable nesting type_body_length type_name + +// MARK: - Implementation Details + +extension L10n { + private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + let format = BundleToken.bundle.localizedString(forKey: key, value: nil, table: table) + return String(format: format, locale: Locale.current, arguments: args) + } +} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + Bundle(for: BundleToken.self) + }() +} +// swiftlint:enable convenience_type diff --git a/Passepartout/App/macOS/Global/TextInputViewController.swift b/Passepartout/App/macOS/Global/TextInputViewController.swift new file mode 100644 index 00000000..c91c29db --- /dev/null +++ b/Passepartout/App/macOS/Global/TextInputViewController.swift @@ -0,0 +1,92 @@ +// +// TextInputViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/3/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +protocol TextInputViewControllerDelegate: class { + func textInputController(_ textInputController: TextInputViewController, shouldEnterText text: String) -> Bool + + func textInputController(_ textInputController: TextInputViewController, didEnterText text: String) +} + +class TextInputViewController: NSViewController { + @IBOutlet private weak var labelTextCaption: NSTextField! + + @IBOutlet private weak var textPlain: NSTextField! + + @IBOutlet private weak var textSecure: NSSecureTextField! + + private var textField: NSTextField { + guard !isSecure else { + return textSecure + } + return textPlain + } + + @IBOutlet private weak var buttonOK: NSButton! + + @IBOutlet private weak var buttonCancel: NSButton! + + var caption = "" + + var text = "" + + var placeholder: String? + + var isSecure = false + + var object: Any? + + weak var delegate: TextInputViewControllerDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + labelTextCaption.stringValue = caption + textField.stringValue = text + textField.placeholderString = placeholder + buttonOK.title = L10n.Core.Global.ok + buttonCancel.title = L10n.Core.Global.cancel + + textPlain.isHidden = isSecure + textSecure.isHidden = !isSecure + } + + @IBAction private func confirm(_ sender: Any?) { + let text = textField.stringValue + if let delegate = delegate { + guard delegate.textInputController(self, shouldEnterText: text) else { + textField.becomeFirstResponder() + return + } + } + delegate?.textInputController(self, didEnterText: text) + } + + override func cancelOperation(_ sender: Any?) { + dismiss(sender) + } +} diff --git a/Passepartout/App/macOS/Global/Theme+Views.swift b/Passepartout/App/macOS/Global/Theme+Views.swift new file mode 100644 index 00000000..1338de37 --- /dev/null +++ b/Passepartout/App/macOS/Global/Theme+Views.swift @@ -0,0 +1,99 @@ +// +// Theme+Views.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/29/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +extension NSTextField { + func applyVPN(_ theme: Theme, isActive: Bool, with vpnStatus: VPNStatus?, error: OpenVPNTunnelProvider.ProviderError?) { + guard isActive else { + stringValue = L10n.App.Vpn.unused + textColor = theme.palette.colorSecondaryText + return + } + guard let vpnStatus = vpnStatus else { + stringValue = L10n.Core.Vpn.disabled + textColor = theme.palette.colorSecondaryText + return + } + + switch vpnStatus { + case .connecting: + stringValue = L10n.Core.Vpn.connecting + textColor = theme.palette.colorIndeterminate + + case .connected: + stringValue = L10n.Core.Vpn.active + textColor = theme.palette.colorOn + + case .disconnecting: + stringValue = disconnectionReason(for: error) ?? L10n.Core.Vpn.disconnecting + textColor = theme.palette.colorIndeterminate + + case .disconnected: + stringValue = disconnectionReason(for: error) ?? L10n.Core.Vpn.inactive + textColor = theme.palette.colorOff + } + } + + private func disconnectionReason(for error: OpenVPNTunnelProvider.ProviderError?) -> String? { + guard let error = error else { + return nil + } + let V = L10n.Core.Vpn.Errors.self + switch error { + case .socketActivity, .timeout: + return V.timeout + + case .dnsFailure: + return V.dns + + case .tlsInitialization, .tlsServerVerification, .tlsHandshake: + return V.tls + + case .authentication: + return V.auth + + case .encryptionInitialization, .encryptionData: + return V.encryption + + case .serverCompression, .lzo: + return V.compression + + case .networkChanged: + return V.network + + case .routing: + return V.routing + + case .gatewayUnattainable: + return V.gateway + + default: + return nil + } + } +} diff --git a/Passepartout/App/macOS/Global/Theme.swift b/Passepartout/App/macOS/Global/Theme.swift new file mode 100644 index 00000000..80cf5c1c --- /dev/null +++ b/Passepartout/App/macOS/Global/Theme.swift @@ -0,0 +1,99 @@ +// +// Theme.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/29/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +struct Theme { + struct Palette { + var colorPrimaryText: NSColor = .labelColor + + var colorSecondaryText: NSColor = .secondaryLabelColor + + var colorOff: NSColor = .red + + var colorOn = NSColor(red: 0.0, green: 0.8, blue: 0.0, alpha: 1.0) + + var colorIndeterminate: NSColor = .orange + + var colorInline = NSColor(red: 0, green: 0.478431, blue: 1, alpha: 1) + } + + static let current = Theme() + + var palette: Palette + + private init() { + palette = Palette() + } +} + +// FIXME: load from index JSON +extension Infrastructure.Metadata { + var logo: NSImage? { + guard let image = ImageAsset.Image(named: name) else { + return Asset.Providers.placeholder.image + } + return image + } +} + +extension ConnectionProfile { + var image: NSImage? { + if let profile = self as? ProviderConnectionProfile { + return profile.infrastructure.metadata?.logo + } else { +// return NSImage(named: NSImage.applicationIconName)//smartBadgeTemplateName) + return nil + } + } +} + +extension PoolGroup { + var logo: NSImage? { + return ImageAsset(name: country.lowercased()).image + } +} + +extension NetworkChoice: CustomStringConvertible { + public var description: String { + switch self { + case .client: + return L10n.Core.NetworkChoice.client + + case .server: + return L10n.Core.NetworkChoice.server + + case .manual: + return L10n.Core.Global.Values.manual + } + } +} + +extension String { + var image: NSImage? { + return ImageAsset(name: lowercased()).image + } +} diff --git a/Passepartout/App/macOS/Global/WindowManager.swift b/Passepartout/App/macOS/Global/WindowManager.swift new file mode 100644 index 00000000..bac36ad2 --- /dev/null +++ b/Passepartout/App/macOS/Global/WindowManager.swift @@ -0,0 +1,93 @@ +// +// WindowManager.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 8/12/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +class WindowManager: NSObject { + static let shared = WindowManager() + + private var organizer: NSWindowController? + +// private var preferences: NSWindowController? + + private override init() { + } + + @discardableResult func showOrganizer() -> NSWindowController? { + organizer = presentWindowController( + StoryboardScene.Main.organizerWindowController, + existing: organizer, + title: L10n.App.Organizer.title(GroupConstants.App.name) + ) + return organizer + } + +// @discardableResult func showPreferences() -> NSWindowController? { +// preferences = presentWindowController( +// StoryboardScene.Preferences.initialScene.instantiate(), +// existing: preferences, +// title: L10n.App.Preferences.title(GroupConstants.App.name) +// ) +// return preferences +// } + + func showAbout() { + NSApp.orderFrontStandardAboutPanel(nil) + NSApp.activate(ignoringOtherApps: true) + } + + // MARK: Helpers + + private func presentWindowController(_ wcScene: SceneType, existing: NSWindowController?, title: String) -> NSWindowController? { + var wc: NSWindowController? + if existing == nil { + wc = wcScene.instantiate() + wc?.window?.title = title + wc?.window?.delegate = self + wc?.window?.center() + wc?.showWindow(nil) + } else { + existing?.window?.makeKeyAndOrderFront(self) + } + NSApp.activate(ignoringOtherApps: true) + return existing ?? wc + } +} + +extension WindowManager: NSWindowDelegate { + func windowWillClose(_ notification: Notification) { + switch notification.object as? NSWindowController { + case organizer: + organizer = nil + +// case preferences: +// preferences = nil + + default: + break + } + } +} diff --git a/Passepartout/App/macOS/Info.plist b/Passepartout/App/macOS/Info.plist new file mode 100644 index 00000000..19b236f1 --- /dev/null +++ b/Passepartout/App/macOS/Info.plist @@ -0,0 +1,75 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + ovpn + + CFBundleTypeName + OpenVPN Configuration + CFBundleTypeRole + Viewer + LSHandlerRank + Alternate + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(CFG_APP_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + ITSAppUsesNonExemptEncryption + + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + LSUIElement + + NSHumanReadableCopyright + $(CFG_COPYRIGHT) + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + NSUserActivityTypes + + ConnectVPNIntent + DisableVPNIntent + EnableVPNIntent + MoveToLocationIntent + TrustCellularNetworkIntent + TrustCurrentNetworkIntent + UntrustCellularNetworkIntent + UntrustCurrentNetworkIntent + + com.algoritmico.Passepartout.config + + app_launcher_id + $(CFG_APP_LAUNCHER_ID) + appcenter_secret + $(CFG_APPCENTER_SECRET) + appstore_id + $(CFG_APPSTORE_MACOS_ID) + group_id + $(CFG_TEAM_ID).group.$(CFG_GROUP_ID) + + + diff --git a/Passepartout/App/macOS/Launcher/AppDelegate.swift b/Passepartout/App/macOS/Launcher/AppDelegate.swift new file mode 100644 index 00000000..7f514e7f --- /dev/null +++ b/Passepartout/App/macOS/Launcher/AppDelegate.swift @@ -0,0 +1,63 @@ +// +// AppDelegate.swift +// PassepartoutLauncher +// +// Created by Davide De Rosa on 12/16/20. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa + +extension Notification.Name { + static let killLauncher = Notification.Name("killLauncher") +} + +@NSApplicationMain +class AppDelegate: NSObject { + @objc func terminate() { + NSApp.terminate(nil) + } +} + +extension AppDelegate: NSApplicationDelegate { + func applicationDidFinishLaunching(_ aNotification: Notification) { + let mainAppIdentifier = "com.algoritmico.macos.Passepartout" // XXX: hardcoded + let runningApps = NSWorkspace.shared.runningApplications + let isRunning = !runningApps.filter { $0.bundleIdentifier == mainAppIdentifier }.isEmpty + + if !isRunning { + DistributedNotificationCenter.default().addObserver(self, selector: #selector(terminate), name: .killLauncher, object: mainAppIdentifier) + + let path = Bundle.main.bundlePath as NSString + var components = path.pathComponents + components.removeLast() + components.removeLast() + components.removeLast() + components.append("MacOS") + components.append("Passepartout") // XXX: hardcoded + + let newPath = NSString.path(withComponents: components) + + NSWorkspace.shared.launchApplication(newPath) + } else { + terminate() + } + } +} diff --git a/Passepartout/App/macOS/Launcher/Assets.xcassets/AccentColor.colorset/Contents.json b/Passepartout/App/macOS/Launcher/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Passepartout/App/macOS/Launcher/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Passepartout/App/macOS/Launcher/Assets.xcassets/AppIcon.appiconset/Contents.json b/Passepartout/App/macOS/Launcher/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..3f00db43 --- /dev/null +++ b/Passepartout/App/macOS/Launcher/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Passepartout/App/macOS/Launcher/Assets.xcassets/Contents.json b/Passepartout/App/macOS/Launcher/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Passepartout/App/macOS/Launcher/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Passepartout/App/macOS/Launcher/Base.lproj/Main.storyboard b/Passepartout/App/macOS/Launcher/Base.lproj/Main.storyboard new file mode 100644 index 00000000..bb76ffca --- /dev/null +++ b/Passepartout/App/macOS/Launcher/Base.lproj/Main.storyboard @@ -0,0 +1,684 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Launcher/Info.plist b/Passepartout/App/macOS/Launcher/Info.plist new file mode 100644 index 00000000..d75166c3 --- /dev/null +++ b/Passepartout/App/macOS/Launcher/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(CFG_APP_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSApplicationCategoryType + public.app-category.utilities + LSBackgroundOnly + + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(CFG_COPYRIGHT) + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/Passepartout/App/macOS/Launcher/Launcher.entitlements b/Passepartout/App/macOS/Launcher/Launcher.entitlements new file mode 100644 index 00000000..f2ef3ae0 --- /dev/null +++ b/Passepartout/App/macOS/Launcher/Launcher.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Passepartout/App/macOS/Menu/MainMenu.swift b/Passepartout/App/macOS/Menu/MainMenu.swift new file mode 100644 index 00000000..9baba858 --- /dev/null +++ b/Passepartout/App/macOS/Menu/MainMenu.swift @@ -0,0 +1,35 @@ +// +// MainMenu.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 8/13/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa + +class MainMenu: NSObject { + @IBAction private func showPreferences(_ sender: Any?) { + guard let vc = NSApp.mainWindow?.contentViewController else { + return + } + vc.presentAsModalWindow(StoryboardScene.Preferences.initialScene.instantiate()) + } +} diff --git a/Passepartout/App/macOS/Menu/MainMenu.xib b/Passepartout/App/macOS/Menu/MainMenu.xib new file mode 100644 index 00000000..ac8696b0 --- /dev/null +++ b/Passepartout/App/macOS/Menu/MainMenu.xib @@ -0,0 +1,678 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Menu/StatusMenu.swift b/Passepartout/App/macOS/Menu/StatusMenu.swift new file mode 100644 index 00000000..53014a2f --- /dev/null +++ b/Passepartout/App/macOS/Menu/StatusMenu.swift @@ -0,0 +1,586 @@ +// +// StatusMenu.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 8/14/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit +import Convenience + +class StatusMenu: NSObject { + static let didAddProfile = Notification.Name("didAddProfile") + + static let didRenameProfile = Notification.Name("didRenameProfile") + + static let didRemoveProfile = Notification.Name("didRemoveProfile") + + static let willDeactivateProfile = Notification.Name("willDeactivateProfile") + + static let didActivateProfile = Notification.Name("didActivateProfile") + + static let didUpdateProfile = Notification.Name("didUpdateProfile") + + static let shared = StatusMenu() + + private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + + private let service = TransientStore.shared.service + + private var vpn: GracefulVPN { + return GracefulVPN(service: service) + } + + // MARK: Button images + + private let imageStatus = Asset.Assets.statusBarButtonImage.image + + private lazy var imageStatusActive: NSImage = imageStatus.tinted(withColor: Theme.current.palette.colorOn) + + private lazy var imageStatusInactive: NSImage = imageStatus.tinted(withColor: Theme.current.palette.colorPrimaryText) + + private lazy var imageStatusInProgress: NSImage = imageStatus.tinted(withColor: Theme.current.palette.colorIndeterminate) + + // MARK: Menu references + + private let menu = NSMenu() + + private let menuAllProfiles = NSMenu() + + private var itemSwitchProfile: NSMenuItem? + + private var itemsAllProfiles: [NSMenuItem] = [] + + private var itemProfileName: NSMenuItem? + + private var itemsProfile: [NSMenuItem] = [] + + private var itemPool: NSMenuItem? + + private var itemToggleVPN: NSMenuItem? + + private var itemReconnectVPN: NSMenuItem? + + private override init() { + super.init() + + service.delegate = self + + let nc = NotificationCenter.default + nc.addObserver(self, selector: #selector(vpnDidUpdate), name: VPN.didChangeStatus, object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self) + } + + func install() { + guard let button = statusItem.button else { + return + } + button.image = imageStatus + + VPN.shared.prepare { + self.rebuild() + self.statusItem.menu = self.menu + } + } + + private func rebuild() { + menu.removeAllItems() + + // main windows + + let itemAbout = NSMenuItem(title: L10n.Core.Organizer.Cells.About.caption(GroupConstants.App.name), action: #selector(showAbout), keyEquivalent: "") + let itemOrganizer = NSMenuItem(title: L10n.App.Menu.Organizer.title.asContinuation, action: #selector(showOrganizer), keyEquivalent: "o") + let itemPreferences = NSMenuItem(title: L10n.App.Menu.Preferences.title.asContinuation, action: #selector(showPreferences), keyEquivalent: ",") + itemAbout.target = self + itemOrganizer.target = self + itemPreferences.target = self + menu.addItem(itemAbout) + menu.addItem(itemOrganizer) + menu.addItem(itemPreferences) + menu.addItem(.separator()) + + // profiles + + itemSwitchProfile = NSMenuItem(title: L10n.App.Menu.SwitchProfile.title, action: nil, keyEquivalent: "") + menu.addItem(itemSwitchProfile!) + reloadProfiles() + menu.addItem(.separator()) + + // active profile + + itemProfileName = NSMenuItem(title: "", action: nil, keyEquivalent: "") + menu.addItem(itemProfileName!) + setActiveProfile(service.activeProfile) + menu.addItem(.separator()) + + // support + + let menuSupport = NSMenu() + let itemCommunity = NSMenuItem(title: L10n.Core.Organizer.Cells.JoinCommunity.caption.asContinuation, action: #selector(joinCommunity), keyEquivalent: "") + let itemReview = NSMenuItem(title: L10n.Core.Organizer.Cells.WriteReview.caption.asContinuation, action: #selector(writeReview), keyEquivalent: "") +// let itemDonate = NSMenuItem(title: L10n.Core.Organizer.Cells.Donate.caption.asContinuation, action: #selector(showDonations), keyEquivalent: "") +// let itemGitHubSponsors = NSMenuItem(title: L10n.Core.Organizer.Cells.GithubSponsors.caption.asContinuation, action: #selector(seeGitHubSponsors), keyEquivalent: "") +// let itemTranslate = NSMenuItem(title: L10n.Core.Organizer.Cells.Translate.caption.asContinuation, action: #selector(offerToTranslate), keyEquivalent: "") + let itemFAQ = NSMenuItem(title: L10n.Core.About.Cells.Faq.caption.asContinuation, action: #selector(visitFAQ), keyEquivalent: "") + let itemReport = NSMenuItem(title: L10n.Core.Service.Cells.ReportIssue.caption.asContinuation, action: #selector(reportConnectivityIssue), keyEquivalent: "") + itemCommunity.target = self + itemReview.target = self +// itemDonate.target = self +// itemGitHubSponsors.target = self +// itemTranslate.target = self + itemFAQ.target = self + itemReport.target = self +// menuSupport.addItem(itemDonate) + menuSupport.addItem(itemCommunity) +// menuSupport.addItem(.separator()) +// menuSupport.addItem(itemGitHubSponsors) +// menuSupport.addItem(itemTranslate) + menuSupport.addItem(itemReview) + menuSupport.addItem(.separator()) + menuSupport.addItem(itemFAQ) + menuSupport.addItem(itemReport) + let itemSupport = NSMenuItem(title: L10n.App.Menu.Support.title, action: nil, keyEquivalent: "") + menu.setSubmenu(menuSupport, for: itemSupport) + menu.addItem(itemSupport) + menu.addItem(.separator()) + + // quit + + let itemQuit = NSMenuItem(title: L10n.App.Menu.Quit.title(GroupConstants.App.name), action: #selector(quit), keyEquivalent: "q") + itemQuit.target = self + menu.addItem(itemQuit) + } + + private func reloadProfiles() { + for item in itemsAllProfiles { + menuAllProfiles.removeItem(item) + } + itemsAllProfiles.removeAll() + + let sortedProfileKeys = service.allProfileKeys().sorted { + service.screenTitle($0).lowercased() < service.screenTitle($1).lowercased() + } + + for profileKey in sortedProfileKeys { + let title = service.screenTitle(profileKey) + let item = NSMenuItem(title: title, action: #selector(switchActiveProfile(_:)), keyEquivalent: "") + item.representedObject = profileKey + item.target = self + item.state = service.isActiveProfile(profileKey) ? .on : .off + menuAllProfiles.addItem(item) + itemsAllProfiles.append(item) + } + menu.setSubmenu(menuAllProfiles, for: itemSwitchProfile!) + } + + func refreshWithCurrentProfile() { + setActiveProfile(service.activeProfile) + } + + func setActiveProfile(_ profile: ConnectionProfile?) { + let startIndex = menu.index(of: itemProfileName!) + var i = startIndex + 1 + + for item in itemsProfile { + menu.removeItem(item) + } + itemsProfile.removeAll() + + guard let profile = profile else { + itemProfileName?.title = L10n.App.Menu.ActiveProfile.Title.none +// itemProfileName?.image = nil + itemToggleVPN = nil + itemReconnectVPN = nil + statusItem.button?.image = imageStatusInactive + return + } + + itemProfileName?.title = service.screenTitle(ProfileKey(profile)) +// itemProfileName?.image = profile.image + + let needsCredentials = service.needsCredentials(for: profile) + if !needsCredentials { + itemToggleVPN = NSMenuItem(title: L10n.App.Service.Cells.Vpn.TurnOn.caption, action: nil, keyEquivalent: "") + itemReconnectVPN = NSMenuItem(title: L10n.Core.Service.Cells.Reconnect.caption, action: #selector(reconnectVPN), keyEquivalent: "") + itemToggleVPN?.indentationLevel = 1 + itemReconnectVPN?.indentationLevel = 1 + itemToggleVPN?.target = self + itemReconnectVPN?.target = self + menu.insertItem(itemToggleVPN!, at: i) + i += 1 + menu.insertItem(itemReconnectVPN!, at: i) + i += 1 + + itemsProfile.append(itemToggleVPN!) + itemsProfile.append(itemReconnectVPN!) + } else { + let itemMissingCredentials = NSMenuItem(title: L10n.App.Menu.ActiveProfile.Messages.missingCredentials, action: nil, keyEquivalent: "") + itemMissingCredentials.indentationLevel = 1 + menu.insertItem(itemMissingCredentials, at: i) + i += 1 + itemsProfile.append(itemMissingCredentials) + } + + updateUIWithVPNStatus() + + if !needsCredentials, let providerProfile = profile as? ProviderConnectionProfile { + + // endpoint (port only) + let itemEndpoint = NSMenuItem(title: L10n.Core.Endpoint.title, action: nil, keyEquivalent: "") + itemEndpoint.indentationLevel = 1 + let menuEndpoint = NSMenu() + + // automatic + let itemEndpointAutomatic = NSMenuItem(title: L10n.Core.Endpoint.Cells.AnyProtocol.caption, action: #selector(connectToEndpoint(_:)), keyEquivalent: "") + itemEndpointAutomatic.target = self + if providerProfile.customProtocol == nil { + itemEndpointAutomatic.state = .on + } + menuEndpoint.addItem(itemEndpointAutomatic) + + for proto in profile.protocols { + let item = NSMenuItem(title: proto.description, action: #selector(connectToEndpoint(_:)), keyEquivalent: "") + item.representedObject = proto + item.target = self + if providerProfile.customProtocol == proto { + item.state = .on + } + menuEndpoint.addItem(item) + } + menu.setSubmenu(menuEndpoint, for: itemEndpoint) + menu.insertItem(itemEndpoint, at: i) + i += 1 + itemsProfile.append(itemEndpoint) + + // account + let itemAccount = NSMenuItem(title: L10n.Core.Account.title.asContinuation, action: #selector(editAccountCredentials(_:)), keyEquivalent: "") + menu.insertItem(itemAccount, at: i) + i += 1 + itemAccount.target = self + itemAccount.indentationLevel = 1 + itemsProfile.append(itemAccount) + + // customize + let itemCustomize = NSMenuItem(title: L10n.App.Menu.ActiveProfile.Items.Customize.title, action: #selector(customizeProfile(_:)), keyEquivalent: "") + menu.insertItem(itemCustomize, at: i) + i += 1 + itemCustomize.target = self + itemCustomize.indentationLevel = 1 + itemsProfile.append(itemCustomize) + + let itemSep1: NSMenuItem = .separator() + menu.insertItem(itemSep1, at: i) + i += 1 + itemsProfile.append(itemSep1) + +// guard poolDescription = providerProfile.pool?.localizedId else { +// fatalError("No pool selected?") +// } + itemPool = NSMenuItem(title: providerProfile.pool?.localizedId ?? "", action: nil, keyEquivalent: "") + menu.insertItem(itemPool!, at: i) + i += 1 + itemsProfile.append(itemPool!) + + let infrastructure = providerProfile.infrastructure + for category in infrastructure.categories { + let title = category.name.isEmpty ? L10n.App.Global.Values.default : category.name.capitalized + let submenu = NSMenu() + let item = NSMenuItem(title: title, action: nil, keyEquivalent: "") + item.indentationLevel = 1 + + for group in category.groups.sorted() { + var title = group.localizedCountry + if let area = group.area?.uppercased() { + title = "\(title) - \(area)" + } + + let itemGroup = NSMenuItem(title: title, action: #selector(connectToPool(_:)), keyEquivalent: "") + itemGroup.target = self + itemGroup.representedObject = group + + for pool in group.pools { + if pool.id == providerProfile.poolId { + itemGroup.state = .on + break + } + } + submenu.addItem(itemGroup) + } + menu.setSubmenu(submenu, for: item) + menu.insertItem(item, at: i) + i += 1 + itemsProfile.append(item) + } + } else { + + // account + let itemAccount = NSMenuItem(title: L10n.Core.Account.title.asContinuation, action: #selector(editAccountCredentials(_:)), keyEquivalent: "") + menu.insertItem(itemAccount, at: i) + i += 1 + itemAccount.target = self + itemAccount.indentationLevel = 1 + itemsProfile.append(itemAccount) + + // customize + let itemCustomize = NSMenuItem(title: L10n.App.Menu.ActiveProfile.Items.Customize.title, action: #selector(customizeProfile(_:)), keyEquivalent: "") + menu.insertItem(itemCustomize, at: i) + i += 1 + itemCustomize.target = self + itemCustomize.indentationLevel = 1 + itemsProfile.append(itemCustomize) + + let itemSep1: NSMenuItem = .separator() + menu.insertItem(itemSep1, at: i) + i += 1 + itemsProfile.append(itemSep1) + } + } + + // MARK: Actions + + @objc private func showAbout() { + WindowManager.shared.showAbout() + } + + @objc private func showOrganizer() { + WindowManager.shared.showOrganizer() + } + + @objc private func showPreferences() { + let organizer = WindowManager.shared.showOrganizer() + let preferences = StoryboardScene.Preferences.initialScene.instantiate() + organizer?.contentViewController?.presentAsModalWindow(preferences) + } + + @objc private func switchActiveProfile(_ sender: Any?) { + guard let item = sender as? NSMenuItem else { + return + } + guard let profileKey = item.representedObject as? ProfileKey, let profile = service.profile(withKey: profileKey) else { + return + } + + let wasConnected = (vpn.status == .connected) || (vpn.status == .connecting) + + // XXX: copy/paste from ServiceViewController.activateProfile() + service.activateProfile(profile) + vpn.disconnect(completionHandler: nil) + if wasConnected { + DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { [weak self] in + self?.vpn.reconnect(completionHandler: nil) + } + } + } + + @objc private func enableVPN() { + vpn.reconnect(completionHandler: nil) + } + + @objc private func disableVPN() { + vpn.disconnect(completionHandler: nil) + } + + @objc private func reconnectVPN() { + vpn.reconnect(completionHandler: nil) + } + + @objc private func connectToPool(_ sender: Any?) { + guard let item = sender as? NSMenuItem else { + return + } + guard let group = item.representedObject as? PoolGroup else { + return + } + guard let profile = service.activeProfile as? ProviderConnectionProfile else { + return + } + assert(!group.pools.isEmpty) + service.setPoolId(group.pools.randomElement()!.id, forProviderProfile: profile) + vpn.reconnect(completionHandler: nil) + + // update menu + setActiveProfile(profile) + } + + @objc private func connectToEndpoint(_ sender: Any?) { + guard let item = sender as? NSMenuItem else { + return + } + guard let profile = service.activeProfile as? ProviderConnectionProfile else { + return + } + profile.customProtocol = item.representedObject as? EndpointProtocol + vpn.reconnect(completionHandler: nil) + + // update menu + setActiveProfile(profile) + } + + @objc private func editAccountCredentials(_ sender: Any?) { + let organizer = WindowManager.shared.showOrganizer() + let accountController = StoryboardScene.Service.accountViewController.instantiate() + accountController.profile = service.activeProfile + organizer?.contentViewController?.presentAsSheet(accountController) + } + + @objc private func customizeProfile(_ sender: Any?) { + let organizer = WindowManager.shared.showOrganizer() + let profileCustomization = StoryboardScene.Service.profileCustomizationContainerViewController.instantiate() + profileCustomization.profile = service.activeProfile + organizer?.contentViewController?.presentAsSheet(profileCustomization) + } + + @objc private func joinCommunity() { + NSWorkspace.shared.open(AppConstants.URLs.subreddit) + } + + @objc private func writeReview() { + let url = Reviewer.urlForReview(withAppId: AppConstants.App.appStoreId) + NSWorkspace.shared.open(url) + } + + @objc private func showDonations() { + NSWorkspace.shared.open(AppConstants.URLs.donate) + } + + @objc private func seeGitHubSponsors() { + NSWorkspace.shared.open(AppConstants.URLs.githubSponsors) + } + + @objc private func offerToTranslate() { + let V = AppConstants.Translations.Email.self + let recipient = V.recipient + let subject = V.subject + let body = V.body(V.template) + + guard let url = URL.mailto(to: recipient, subject: subject, body: body) else { + return + } + NSWorkspace.shared.open(url) + } + + @objc private func visitFAQ() { + NSWorkspace.shared.open(AppConstants.URLs.faq) + } + + @objc private func reportConnectivityIssue() { + let issue = Issue(debugLog: true, profile: TransientStore.shared.service.activeProfile) + IssueReporter.shared.present(withIssue: issue) + } + + @objc private func quit() { + NSApp.terminate(self) + } + + // MARK: Notifications + + @objc private func vpnDidUpdate() { + reloadVpnStatus() + } + + // MARK: Helpers + + private func reloadVpnStatus() { + guard service.hasActiveProfile() else { + return + } + updateUIWithVPNStatus() + } + + private func updateUIWithVPNStatus() { + if vpn.isEnabled { + itemToggleVPN?.title = L10n.App.Service.Cells.Vpn.TurnOff.caption + itemToggleVPN?.action = #selector(disableVPN) + } else { + itemToggleVPN?.title = L10n.App.Service.Cells.Vpn.TurnOn.caption + itemToggleVPN?.action = #selector(enableVPN) + } + + switch vpn.status ?? .disconnected { + case .connected: + statusItem.button?.image = imageStatusActive + + Reviewer.shared.reportEvent() + + case .connecting: + statusItem.button?.image = imageStatusInProgress + + case .disconnected: + statusItem.button?.image = imageStatusInactive + + case .disconnecting: + statusItem.button?.image = imageStatusInProgress + } + } +} + +extension StatusMenu: ConnectionServiceDelegate { + func connectionService(didAdd profile: ConnectionProfile) { + TransientStore.shared.serialize(withProfiles: false) // add + reloadProfiles() + + NotificationCenter.default.post(name: StatusMenu.didAddProfile, object: profile) + } + + func connectionService(didRename profile: ConnectionProfile, to newTitle: String) { + TransientStore.shared.serialize(withProfiles: false) // rename + reloadProfiles() + + NotificationCenter.default.post(name: StatusMenu.didRenameProfile, object: profile) + } + + func connectionService(didRemoveProfileWithKey key: ProfileKey) { + TransientStore.shared.serialize(withProfiles: false) // delete + reloadProfiles() + + NotificationCenter.default.post(name: StatusMenu.didRemoveProfile, object: key) + } + + func connectionService(willDeactivate profile: ConnectionProfile) { + TransientStore.shared.serialize(withProfiles: false) // deactivate + reloadProfiles() + setActiveProfile(nil) + + NotificationCenter.default.post(name: StatusMenu.willDeactivateProfile, object: profile) + } + + func connectionService(didActivate profile: ConnectionProfile) { + TransientStore.shared.serialize(withProfiles: false) // activate + reloadProfiles() + setActiveProfile(profile) + + NotificationCenter.default.post(name: StatusMenu.didActivateProfile, object: profile) + } + + func connectionService(didUpdate profile: ConnectionProfile) { + guard let providerProfile = profile as? ProviderConnectionProfile else { + return + } + itemPool?.title = providerProfile.pool?.localizedId ?? "" + + NotificationCenter.default.post(name: StatusMenu.didUpdateProfile, object: profile) + } +} diff --git a/Passepartout/App/macOS/Providers.xcassets/Contents.json b/Passepartout/App/macOS/Providers.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/csv.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/csv.imageset/Contents.json new file mode 100644 index 00000000..68bb32b9 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/csv.imageset/Contents.json @@ -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 + } +} diff --git a/Passepartout/App/macOS/Providers.xcassets/csv.imageset/csv@2x.png b/Passepartout/App/macOS/Providers.xcassets/csv.imageset/csv@2x.png new file mode 100644 index 00000000..1c79287b Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/csv.imageset/csv@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/csv.imageset/csv@3x.png b/Passepartout/App/macOS/Providers.xcassets/csv.imageset/csv@3x.png new file mode 100644 index 00000000..d92972fa Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/csv.imageset/csv@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/Contents.json new file mode 100644 index 00000000..1fd99117 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hideme@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hideme@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/hideme@2x.png b/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/hideme@2x.png new file mode 100644 index 00000000..923e1849 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/hideme@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/hideme@3x.png b/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/hideme@3x.png new file mode 100644 index 00000000..57d1ff1a Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/hideme.imageset/hideme@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/Contents.json new file mode 100644 index 00000000..89ebd272 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mullvad@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "mullvad@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png b/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png new file mode 100644 index 00000000..2ede91d9 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/mullvad@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png b/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png new file mode 100644 index 00000000..4fc64944 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/mullvad.imageset/mullvad@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/Contents.json new file mode 100644 index 00000000..c088a073 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/Contents.json @@ -0,0 +1,54 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "1x", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ] + }, + { + "idiom" : "universal", + "filename" : "nordvpn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nordvpn-dark@2x.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "nordvpn@3x.png", + "scale" : "3x" + }, + { + "idiom" : "universal", + "filename" : "nordvpn-dark@3x.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png new file mode 100644 index 00000000..2703a4dd Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png new file mode 100644 index 00000000..7f0af2ef Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn-dark@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png new file mode 100644 index 00000000..a8db1e30 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png new file mode 100644 index 00000000..971a5361 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/nordvpn.imageset/nordvpn@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/pia.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/pia.imageset/Contents.json new file mode 100644 index 00000000..8a2923a3 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/pia.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pia@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pia@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/pia.imageset/pia@2x.png b/Passepartout/App/macOS/Providers.xcassets/pia.imageset/pia@2x.png new file mode 100644 index 00000000..92ce04c6 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/pia.imageset/pia@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/pia.imageset/pia@3x.png b/Passepartout/App/macOS/Providers.xcassets/pia.imageset/pia@3x.png new file mode 100644 index 00000000..97c08e84 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/pia.imageset/pia@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/Contents.json new file mode 100644 index 00000000..13f500e4 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "placeholder@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "placeholder@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png b/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png new file mode 100644 index 00000000..3117a662 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/placeholder@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png b/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png new file mode 100644 index 00000000..1dc8aed7 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/placeholder.imageset/placeholder@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/Contents.json new file mode 100644 index 00000000..148aaa0a --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "protonvpn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "protonvpn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png b/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png new file mode 100644 index 00000000..f5b03522 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/protonvpn@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png b/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png new file mode 100644 index 00000000..c25f8ded Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/protonvpn.imageset/protonvpn@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/Contents.json new file mode 100644 index 00000000..69d95d66 --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "torguard@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "torguard@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/torguard@2x.png b/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/torguard@2x.png new file mode 100644 index 00000000..32710a2d Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/torguard@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/torguard@3x.png b/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/torguard@3x.png new file mode 100644 index 00000000..de3a90da Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/torguard.imageset/torguard@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/Contents.json new file mode 100644 index 00000000..d3910b1a --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tunnelbear@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tunnelbear@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png b/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png new file mode 100644 index 00000000..b7d3bb4c Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png b/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png new file mode 100644 index 00000000..973baf5c Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/tunnelbear.imageset/tunnelbear@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/Contents.json new file mode 100644 index 00000000..34292c4b --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "vyprvpn@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "vyprvpn@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png b/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png new file mode 100644 index 00000000..07db8402 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png b/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png new file mode 100644 index 00000000..1ee302b2 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/vyprvpn.imageset/vyprvpn@3x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/Contents.json b/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/Contents.json new file mode 100644 index 00000000..63da3f6c --- /dev/null +++ b/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "windscribe@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "windscribe@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png b/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png new file mode 100644 index 00000000..b6cc4e90 Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/windscribe@2x.png differ diff --git a/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png b/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png new file mode 100644 index 00000000..9987b8ad Binary files /dev/null and b/Passepartout/App/macOS/Providers.xcassets/windscribe.imageset/windscribe@3x.png differ diff --git a/Passepartout/App/macOS/Scenes/OrganizerProfileTableView.swift b/Passepartout/App/macOS/Scenes/OrganizerProfileTableView.swift new file mode 100644 index 00000000..1f222fbf --- /dev/null +++ b/Passepartout/App/macOS/Scenes/OrganizerProfileTableView.swift @@ -0,0 +1,179 @@ +// +// OrganizerProfileTableView.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/23/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +protocol OrganizerProfileTableViewDelegate: class { + func profileTableViewDidRequestAdd(_ profileTableView: OrganizerProfileTableView, sender: NSView) + + func profileTableView(_ profileTableView: OrganizerProfileTableView, didRequestRemove profile: ConnectionProfile) + + func profileTableView(_ profileTableView: OrganizerProfileTableView, didRequestRename profile: HostConnectionProfile) +} + +class OrganizerProfileTableView: NSView { + @IBOutlet private weak var tableView: NSTableView! + + @IBOutlet private weak var buttonAdd: NSButton! + + @IBOutlet private weak var buttonRemove: NSButton! + + @IBOutlet private weak var buttonRename: NSButton! + + private let service = TransientStore.shared.service + + var rows: [ConnectionProfile] = [] + + var selectedRow: Int? + + var selectionBlock: ((ConnectionProfile) -> Void)? + + var deselectionBlock: (() -> Void)? + + private var isAddEnabled: Bool { + get { + return buttonAdd.isEnabled + } + set { + buttonAdd.isEnabled = newValue + } + } + + private var isRemoveEnabled: Bool { + get { + return buttonRemove.isEnabled + } + set { + buttonRemove.isEnabled = newValue + } + } + + private var isRenameEnabled: Bool { + get { + return buttonRename.isEnabled + } + set { + buttonRename.isEnabled = newValue + } + } + + weak var delegate: OrganizerProfileTableViewDelegate? + + override func viewWillMove(toSuperview newSuperview: NSView?) { + super.viewWillMove(toSuperview: newSuperview) + + buttonAdd.image = NSImage(named: NSImage.addTemplateName) + buttonRemove.image = NSImage(named: NSImage.removeTemplateName) + buttonRename.image = NSImage(named: NSImage.actionTemplateName) + } + + func reloadData() { + tableView.reloadData() + if let i = selectedRow { + tableView.selectRowIndexes(IndexSet(integer: i), byExtendingSelection: false) + } + updateButtonsStatus() + } + + // MARK: Actions + + @IBAction private func addProfile(_ sender: Any?) { + delegate?.profileTableViewDidRequestAdd(self, sender: sender as! NSButton) + } + + @IBAction private func removeProfile(_ sender: Any?) { + let index = tableView.selectedRow + guard index != -1 else { + return + } + delegate?.profileTableView(self, didRequestRemove: rows[index]) + } + + @IBAction private func renameProfile(_ sender: Any?) { + let index = tableView.selectedRow + guard index != -1 else { + return + } + guard let hostProfile = rows[index] as? HostConnectionProfile else { + return + } + delegate?.profileTableView(self, didRequestRename: hostProfile) + } + + // MARK: Helpers + + private func updateButtonsStatus() { + let index = tableView.selectedRow + guard index != -1 else { + isRemoveEnabled = false + isRenameEnabled = false + deselectionBlock?() + return + } + isRemoveEnabled = true + isRenameEnabled = (rows[index] as? HostConnectionProfile != nil) + } +} + +class OrganizerProfileTableViewCell: NSTableCellView { + @IBOutlet private weak var imageActive: NSImageView? + + override var objectValue: Any? { + didSet { + guard let objectValue = objectValue else { + return + } + guard let pair = objectValue as? (ConnectionService, ConnectionProfile) else { + fatalError("objectValue is not a (ConnectionService, ConnectionProfile)") + } + imageView?.image = pair.1.image + textField?.stringValue = pair.0.screenTitle(ProfileKey(pair.1)) + + // FIXME: active profile icon + imageActive?.image = NSImage(named: NSImage.menuOnStateTemplateName) + imageActive?.isHidden = !TransientStore.shared.service.isActiveProfile(pair.1) + } + } +} + +extension OrganizerProfileTableView: NSTableViewDataSource, NSTableViewDelegate { + func numberOfRows(in tableView: NSTableView) -> Int { + return rows.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + return (service, rows[row]) + } + + func tableViewSelectionDidChange(_ notification: Notification) { + updateButtonsStatus() + + let index = tableView.selectedRow + if index != -1 { + selectionBlock?(rows[index]) + } + } +} diff --git a/Passepartout/App/macOS/Scenes/OrganizerProfileTableView.xib b/Passepartout/App/macOS/Scenes/OrganizerProfileTableView.xib new file mode 100644 index 00000000..a6ada462 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/OrganizerProfileTableView.xib @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Scenes/OrganizerViewController.swift b/Passepartout/App/macOS/Scenes/OrganizerViewController.swift new file mode 100644 index 00000000..83e13e64 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/OrganizerViewController.swift @@ -0,0 +1,358 @@ +// +// OrganizerViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/6/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +class OrganizerViewController: NSViewController { + @IBOutlet private weak var viewProfiles: NSView! + + private lazy var tableProfiles: OrganizerProfileTableView = .get() + + @IBOutlet private weak var buttonRemoveConfiguration: NSButton! + + @IBOutlet private weak var serviceController: ServiceViewController? + + private let service = TransientStore.shared.service + + private var profiles: [ConnectionProfile] = [] + + private var importer: HostImporter? + + private var profilePendingRemoval: ConnectionProfile? + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override func viewDidLoad() { + super.viewDidLoad() + + viewProfiles.addSubview(tableProfiles) + tableProfiles.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + tableProfiles.topAnchor.constraint(equalTo: viewProfiles.topAnchor), + tableProfiles.bottomAnchor.constraint(equalTo: viewProfiles.bottomAnchor), + tableProfiles.leftAnchor.constraint(equalTo: viewProfiles.leftAnchor), + tableProfiles.rightAnchor.constraint(equalTo: viewProfiles.rightAnchor), + ]) + + buttonRemoveConfiguration.title = L10n.Core.Organizer.Cells.Uninstall.caption + + tableProfiles.selectionBlock = { [weak self] in + self?.serviceController?.setProfile($0) + } + tableProfiles.deselectionBlock = { [weak self] in + self?.serviceController?.setProfile(nil) + } + tableProfiles.delegate = self + reloadProfiles() + tableProfiles.reloadData() + + let nc = NotificationCenter.default + nc.addObserver(self, selector: #selector(menuDidAddProfile(_:)), name: StatusMenu.didAddProfile, object: nil) + nc.addObserver(self, selector: #selector(menuDidRenameProfile(_:)), name: StatusMenu.didRenameProfile, object: nil) + nc.addObserver(self, selector: #selector(menuDidRemoveProfile(_:)), name: StatusMenu.didRemoveProfile, object: nil) + nc.addObserver(self, selector: #selector(menuDidActivateProfile(_:)), name: StatusMenu.didActivateProfile, object: nil) + } + + // MARK: Actions + + @objc private func addProvider(_ sender: Any?) { + guard let item = sender as? NSMenuItem, let metadata = item.representedObject as? Infrastructure.Metadata else { + return + } + perform(segue: StoryboardSegue.Main.enterAccountSegueIdentifier, sender: metadata.name) + } + + @objc private func addHost() { + let panel = NSOpenPanel() + + panel.title = L10n.App.Organizer.Alerts.OpenHostFile.title + panel.allowsMultipleSelection = false + panel.canChooseDirectories = false + panel.canChooseFiles = true + panel.canCreateDirectories = false + panel.allowedFileTypes = ["ovpn"] + + guard panel.runModal() == .OK, let url = panel.url else { + return + } + + importer = HostImporter(withConfigurationURL: url) + importer?.importHost(withPassphrase: nil) + } + + @objc private func updateProvidersList() { + InfrastructureFactory.shared.updateIndex { + if let error = $0 { + log.error("Unable to update providers list: \(error)") + return + } + +// ProductManager.shared.listProducts { (products, error) in +// if let error = error { +// log.error("Unable to list products: \(error)") +// return +// } +// } + } + } + + private func confirmRenameProfile(_ profile: ConnectionProfile, to newTitle: String) { + + // rename to existing title -> confirm overwrite existing + if let existingProfile = service.hostProfile(withTitle: newTitle) { + let alert = Macros.warning( + L10n.Core.Service.Alerts.Rename.title, + L10n.Core.Wizards.Host.Alerts.Existing.message + ) + alert.present(in: view.window, withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel, handler: { + self.doReplaceProfile(profile, to: newTitle, existingProfile: existingProfile) + }, cancelHandler: nil) + return + } + + // do nothing if same title + if newTitle != service.screenTitle(forHostId: profile.id) { + service.renameProfile(profile, to: newTitle) + } + } + + private func doReplaceProfile(_ profile: ConnectionProfile, to newTitle: String, existingProfile: ConnectionProfile) { + let wasActive = service.isActiveProfile(existingProfile) + service.removeProfile(ProfileKey(existingProfile)) + service.renameProfile(profile, to: newTitle) + if wasActive { + service.activateProfile(profile) + } + serviceController?.setProfile(profile) + } + + @IBAction private func confirmVpnProfileDeletion(_ sender: Any?) { + let alert = Macros.warning( + L10n.Core.Organizer.Cells.Uninstall.caption, + L10n.Core.Organizer.Alerts.DeleteVpnProfile.message + ) + alert.present(in: view.window, withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel, handler: { + VPN.shared.uninstall(completionHandler: nil) + }, cancelHandler: nil) + } + + override func prepare(for segue: NSStoryboardSegue, sender: Any?) { + if let vc = segue.destinationController as? ServiceViewController { + serviceController = vc + } else if let vc = segue.destinationController as? AccountViewController { + + // add provider -> account + if let name = sender as? Infrastructure.Name { + vc.profile = ProviderConnectionProfile(name: name) + } + // add host -> rename -> account + else { + vc.profile = sender as? ConnectionProfile + } + vc.delegate = self + } else if let vc = segue.destinationController as? TextInputViewController { + guard let profile = sender as? ConnectionProfile else { + return + } + + // rename host + vc.caption = L10n.Core.Service.Alerts.Rename.title.asCaption + vc.text = service.screenTitle(forHostId: profile.id) + vc.placeholder = L10n.Core.Global.Host.TitleInput.placeholder + vc.object = profile + vc.delegate = self + } + } + + // MARK: Notifications + + @objc private func menuDidAddProfile(_ notification: Notification) { + reloadProfiles() + tableProfiles.reloadData() + } + + @objc private func menuDidRenameProfile(_ notification: Notification) { + reloadProfiles() + tableProfiles.reloadData() + } + + @objc private func menuDidRemoveProfile(_ notification: Notification) { + reloadProfiles() + tableProfiles.selectedRow = nil + tableProfiles.reloadData() + } + + @objc private func menuDidActivateProfile(_ notification: Notification) { + guard let profile = notification.object as? ConnectionProfile else { + return + } + for (i, p) in profiles.enumerated() { + if p.id == profile.id { + tableProfiles.selectedRow = i + break + } + } + tableProfiles.reloadData() + } + + // MARK: Helpers + + private func removePendingProfile() { + guard let profile = profilePendingRemoval else { + return + } + + service.removeProfile(ProfileKey(profile)) + profilePendingRemoval = nil + + if profiles.isEmpty || !service.hasActiveProfile() { + serviceController?.setProfile(nil) + VPN.shared.uninstall(completionHandler: nil) + } + } + + private func reloadProfiles() { + let providerIds = service.ids(forContext: .provider) + let hostIds = service.ids(forContext: .host) + profiles.removeAll() + for id in providerIds { + guard let profile = service.profile(withContext: .provider, id: id) else { + continue + } + profiles.append(profile) + } + for id in hostIds { + guard let profile = service.profile(withContext: .host, id: id) else { + continue + } + profiles.append(profile) + } + profiles.sort { + service.screenTitle(ProfileKey($0)).lowercased() < service.screenTitle(ProfileKey($1)).lowercased() + } + + tableProfiles.rows = profiles + for (i, p) in profiles.enumerated() { + if service.isActiveProfile(p) { + tableProfiles.selectedRow = i + break + } + } + } +} + +extension OrganizerViewController: OrganizerProfileTableViewDelegate { + func profileTableViewDidRequestAdd(_ profileTableView: OrganizerProfileTableView, sender: NSView) { + guard let event = NSApp.currentEvent else { + return + } + + let menu = NSMenu() + + let itemProvider = NSMenuItem(title: L10n.App.Organizer.Menus.provider, action: nil, keyEquivalent: "") + let menuProvider = NSMenu() + let availableMetadata = service.availableProviders() + if !availableMetadata.isEmpty { + for metadata in availableMetadata { + let item = NSMenuItem(title: metadata.description, action: #selector(addProvider(_:)), keyEquivalent: "") +// item.image = metadata.logo + item.representedObject = metadata + menuProvider.addItem(item) + } + } else { + let item = NSMenuItem(title: L10n.App.Organizer.Menus.Provider.unavailable, action: nil, keyEquivalent: "") + item.isEnabled = false + menuProvider.addItem(item) + } + menuProvider.addItem(.separator()) + let itemProviderUpdateList = NSMenuItem(title: L10n.Core.Wizards.Provider.Cells.UpdateList.caption, action: #selector(updateProvidersList), keyEquivalent: "") + menuProvider.addItem(itemProviderUpdateList) + menu.setSubmenu(menuProvider, for: itemProvider) + menu.addItem(itemProvider) + + let menuHost = NSMenuItem(title: L10n.App.Organizer.Menus.host.asContinuation, action: #selector(addHost), keyEquivalent: "") + menu.addItem(menuHost) + + NSMenu.popUpContextMenu(menu, with: event, for: sender) + } + + func profileTableView(_ profileTableView: OrganizerProfileTableView, didRequestRemove profile: ConnectionProfile) { + profilePendingRemoval = profile + + let alert = Macros.warning( + L10n.App.Organizer.Alerts.RemoveProfile.title, + L10n.App.Organizer.Alerts.RemoveProfile.message(service.screenTitle(ProfileKey(profile))) + ) + alert.present(in: view.window, withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel, handler: { + self.removePendingProfile() + }, cancelHandler: nil) + } + + func profileTableView(_ profileTableView: OrganizerProfileTableView, didRequestRename profile: HostConnectionProfile) { + perform(segue: StoryboardSegue.Main.renameProfileSegueIdentifier, sender: profile) + } +} + +extension OrganizerViewController: AccountViewControllerDelegate { + func accountController(_ accountController: AccountViewController, shouldUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) -> Bool { + guard profile.requiresCredentials else { + return true + } + return credentials.isValid + } + + func accountController(_ accountController: AccountViewController, didUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) { + + // finish adding provider (host adding is done by HostImporter) + if profile.context == .provider { + service.addOrReplaceProfile(profile, credentials: credentials) + } + } + + func accountControllerDidCancel(_ accountController: AccountViewController) { + } +} + +// rename existing host profile +extension OrganizerViewController: TextInputViewControllerDelegate { + func textInputController(_ textInputController: TextInputViewController, shouldEnterText text: String) -> Bool { + return true//text.rangeOfCharacter(from: CharacterSet.filename.inverted) == nil + } + + func textInputController(_ textInputController: TextInputViewController, didEnterText text: String) { + guard let profile = textInputController.object as? ConnectionProfile else { + return + } + confirmRenameProfile(profile, to: text) + dismiss(textInputController) + } +} diff --git a/Passepartout/App/macOS/Scenes/Preferences/DebugLogViewController.swift b/Passepartout/App/macOS/Scenes/Preferences/DebugLogViewController.swift new file mode 100644 index 00000000..08248f2e --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Preferences/DebugLogViewController.swift @@ -0,0 +1,226 @@ +// +// DebugLogViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/31/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +class DebugLogViewController: NSViewController { + @IBOutlet private weak var labelExchangedCaption: NSTextField! + + @IBOutlet private weak var labelExchanged: NSTextField! + + @IBOutlet private weak var checkMasking: NSButton! + + @IBOutlet private weak var labelLog: NSTextField! + + @IBOutlet private weak var scrollTextLog: NSScrollView! + + @IBOutlet private var textLog: NSTextView! + + @IBOutlet private weak var textFinderLog: NSTextFinder! + + @IBOutlet private weak var buttonPrevious: NSButton! + + @IBOutlet private weak var buttonNext: NSButton! + + @IBOutlet private weak var buttonShare: NSButton! + + private let service = TransientStore.shared.service + + private let vpn = VPN.shared + + private var tmpDebugURL: URL? + + private var shouldDeleteLogOnDisconnection = false + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override func viewDidLoad() { + super.viewDidLoad() + + title = L10n.Core.Service.Cells.DebugLog.caption + + checkMasking.title = L10n.Core.Service.Cells.MasksPrivateData.caption + checkMasking.state = (TransientStore.masksPrivateData ? .on : .off) + + labelExchangedCaption.stringValue = L10n.Core.Service.Cells.DataCount.caption.asCaption + labelLog.stringValue = L10n.Core.Service.Cells.DebugLog.caption.asCaption +// scrollTextLog.scrollerStyle = .overlay +// scrollTextLog.autohidesScrollers = false + textLog.font = NSFont(name: "Courier New", size: NSFont.systemFontSize(for: .regular)) + if #available(macOS 10.12.2, *) { + buttonPrevious.image = NSImage(named: NSImage.touchBarRewindTemplateName) + buttonNext.image = NSImage(named: NSImage.touchBarFastForwardTemplateName) + } else { + buttonPrevious.title = L10n.Core.DebugLog.Buttons.previous + buttonNext.title = L10n.Core.DebugLog.Buttons.next + } + buttonShare.image = NSImage(named: NSImage.shareTemplateName) + + let nc = NotificationCenter.default + nc.addObserver(self, selector: #selector(vpnDidPrepare), name: VPN.didPrepare, object: nil) + nc.addObserver(self, selector: #selector(vpnDidUpdate), name: VPN.didChangeStatus, object: nil) + nc.addObserver(self, selector: #selector(serviceDidUpdateDataCount), name: ConnectionService.didUpdateDataCount, object: nil) + + if vpn.isPrepared { + startRefreshingLog() + } + refreshDataCount() + } + + @IBAction private func toggleMasking(_ sender: Any?) { + let isOn = (self.checkMasking.state == .on) + let handler = { + TransientStore.masksPrivateData = isOn + self.service.baseConfiguration = TransientStore.baseVPNConfiguration.build() + } + + guard vpn.status == .disconnected else { + let alert = Macros.warning( + L10n.Core.Service.Cells.MasksPrivateData.caption, + L10n.Core.Service.Alerts.MasksPrivateData.Messages.mustReconnect + ) + alert.present(in: view.window, withOK: L10n.Core.Service.Alerts.Buttons.reconnect, cancel: L10n.Core.Global.cancel, handler: { + handler() + self.shouldDeleteLogOnDisconnection = true + + do { + self.vpn.reconnect(configuration: try self.service.vpnConfiguration(), completionHandler: nil) + } catch { + } + }, cancelHandler: { + self.checkMasking.state = (isOn ? .off : .on) + }) + return + } + + handler() + service.eraseVpnLog() + shouldDeleteLogOnDisconnection = false + } + + @IBAction private func share(_ sender: Any?) { + let text = textLog.string + guard !text.isEmpty else { + let alert = Macros.warning( + L10n.Core.Service.Cells.DebugLog.caption, + L10n.Core.DebugLog.Alerts.EmptyLog.message + ) + alert.present(in: view.window, withOK: L10n.Core.Global.ok, handler: nil) + return + } + let log = DebugLog(raw: text) + let logString = log.decoratedString() + let picker = NSSharingServicePicker(items: [logString]) + picker.show(relativeTo: buttonShare.bounds, of: buttonShare, preferredEdge: .minY) + } + + @IBAction private func previousSession(_ sender: Any?) { + textFinderLog.performAction(.previousMatch) +// textLog.findPrevious(string: GroupConstants.Log.sessionMarker) + } + + @IBAction private func nextSession(_ sender: Any?) { + textFinderLog.performAction(.previousMatch) +// textLog.findNext(string: GroupConstants.Log.sessionMarker) + } + + private func startRefreshingLog() { + let fallback: () -> String = { self.service.vpnLog } + + vpn.requestDebugLog(fallback: fallback) { + self.textLog.string = $0 + + DispatchQueue.main.async { + self.textLog.scrollToEnd() + self.refreshLogInBackground() + } + } + } + + private func refreshLogInBackground() { + let fallback: () -> String = { self.service.vpnLog } + let updateBlock = { + DispatchQueue.main.asyncAfter(deadline: .now() + AppConstants.Log.viewerRefreshInterval) { [weak self] in + self?.refreshLogInBackground() + } + } + + // only update if screen is visible + guard let _ = view.window else { + updateBlock() + return + } + + vpn.requestDebugLog(fallback: fallback) { + let wasEmpty = self.textLog.string.isEmpty + self.textLog.string = $0 + updateBlock() + if wasEmpty { + self.textLog.scrollToEnd() + } + } + } + + // MARK: Notifications + + @objc private func vpnDidPrepare() { + startRefreshingLog() + } + + @objc private func vpnDidUpdate() { + switch vpn.status { + case .disconnected: + if shouldDeleteLogOnDisconnection { + service.eraseVpnLog() + shouldDeleteLogOnDisconnection = false + } + + default: + break + } + + refreshDataCount() + } + + @objc private func serviceDidUpdateDataCount() { + refreshDataCount() + } + + // MARK: Helpers + + private func refreshDataCount() { + if let count = service.vpnDataCount, vpn.status == .connected { + let down = count.0.dataUnitDescription + let up = count.1.dataUnitDescription + labelExchanged.stringValue = "↓\(down) / ↑\(up)" + } else { + labelExchanged.stringValue = L10n.Core.Service.Cells.DataCount.none + } + } +} diff --git a/Passepartout/App/macOS/Scenes/Preferences/PreferencesGeneralViewController.swift b/Passepartout/App/macOS/Scenes/Preferences/PreferencesGeneralViewController.swift new file mode 100644 index 00000000..3452a95a --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Preferences/PreferencesGeneralViewController.swift @@ -0,0 +1,80 @@ +// +// PreferencesGeneralViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 5/31/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import ServiceManagement + +class PreferencesGeneralViewController: NSViewController { + @IBOutlet private weak var checkLaunchOnLogin: NSButton! + + @IBOutlet private weak var labelLaunchOnLogin: NSTextField! + + @IBOutlet private weak var checkResolveHostname: NSButton! + + @IBOutlet private weak var labelResolveHostname: NSTextField! + + private let service = TransientStore.shared.service + + override func viewDidLoad() { + super.viewDidLoad() + + checkLaunchOnLogin.title = L10n.App.Preferences.Cells.LaunchesOnLogin.caption + labelLaunchOnLogin.stringValue = L10n.App.Preferences.Cells.LaunchesOnLogin.footer + checkResolveHostname.title = L10n.Core.Service.Cells.VpnResolvesHostname.caption + labelResolveHostname.stringValue = L10n.Core.Service.Sections.VpnResolvesHostname.footer + + checkLaunchOnLogin.state = (service.preferences.launchesOnLogin ?? true) ? .on : .off + checkResolveHostname.state = service.preferences.resolvesHostname ? .on : .off + } + + override func viewWillDisappear() { + super.viewWillDisappear() + + TransientStore.shared.serialize(withProfiles: false) // close preferences + } + + @IBAction private func toggleLaunchesOnLogin(_ sender: Any?) { + service.preferences.launchesOnLogin = (checkLaunchOnLogin.state == .on) + SMLoginItemSetEnabled(AppConstants.App.appLauncherId as CFString, service.preferences.launchesOnLogin ?? true) + } + + @IBAction private func toggleResolvesHostname(_ sender: Any?) { + service.preferences.resolvesHostname = (checkResolveHostname.state == .on) + cycleVPNIfNeeded() + } + + private func cycleVPNIfNeeded() { + let vpn = GracefulVPN(service: service) + guard vpn.isEnabled else { + return + } +// guard vpn.status == .disconnected else { +// confirmVpnReconnection() +// return +// } + vpn.reinstall(completionHandler: nil) + } +} diff --git a/Passepartout/App/macOS/Scenes/Preferences/PreferencesViewController.swift b/Passepartout/App/macOS/Scenes/Preferences/PreferencesViewController.swift new file mode 100644 index 00000000..69413539 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Preferences/PreferencesViewController.swift @@ -0,0 +1,44 @@ +// +// PreferencesViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 5/31/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +class PreferencesViewController: NSViewController { + @IBOutlet private weak var tabView: NSTabView! + + override func viewDidLoad() { + super.viewDidLoad() + + title = L10n.App.Preferences.title(GroupConstants.App.name) + let labels = [ + L10n.App.Preferences.Sections.General.header, + L10n.Core.Service.Sections.Diagnostics.header + ] + tabView.tabViewItems.enumerated().forEach { + $1.label = labels[$0] + } + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/AccountViewController.swift b/Passepartout/App/macOS/Scenes/Service/AccountViewController.swift new file mode 100644 index 00000000..6df312c1 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/AccountViewController.swift @@ -0,0 +1,106 @@ +// +// AccountViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/29/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import TunnelKit +import PassepartoutCore + +protocol AccountViewControllerDelegate: class { + func accountController(_ accountController: AccountViewController, shouldUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) -> Bool + + func accountController(_ accountController: AccountViewController, didUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) + + func accountControllerDidCancel(_ accountController: AccountViewController) +} + +class AccountViewController: NSViewController { + @IBOutlet private weak var labelUsernameCaption: NSTextField! + + @IBOutlet private weak var textUsername: NSTextField! + + @IBOutlet private weak var labelPasswordCaption: NSTextField! + + @IBOutlet private weak var textPassword: NSSecureTextField! + + @IBOutlet private weak var buttonOK: NSButton! + + @IBOutlet private weak var buttonCancel: NSButton! + + private let service = TransientStore.shared.service + + var profile: ConnectionProfile! + + weak var delegate: AccountViewControllerDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + assert(profile != nil, "Profile not set") + + labelUsernameCaption.stringValue = L10n.Core.Account.Cells.Username.caption.asCaption + if let providerProfile = profile as? ProviderConnectionProfile { + textUsername.placeholderString = providerProfile.infrastructure.defaults.username + } else { + textUsername.placeholderString = L10n.Core.Account.Cells.Username.placeholder + } + labelPasswordCaption.stringValue = L10n.Core.Account.Cells.Password.caption.asCaption + textPassword.placeholderString = L10n.Core.Account.Cells.Password.placeholder + buttonOK.title = L10n.Core.Global.ok + buttonCancel.title = L10n.Core.Global.cancel + + let credentials = service.credentials(for: profile) + textUsername.stringValue = credentials?.username ?? "" + textPassword.stringValue = credentials?.password ?? "" + } + + @IBAction private func confirm(_ sender: Any?) { + let username = textUsername.stringValue + let password = textPassword.stringValue + let credentials = Credentials(username, password) + if let delegate = delegate { + guard delegate.accountController(self, shouldUpdateCredentials: credentials, forProfile: profile) else { + return + } + } + + do { + try service.setCredentials(credentials, for: profile) + } catch { + return + } + + delegate?.accountController(self, didUpdateCredentials: credentials, forProfile: profile) + dismiss(self) + } + + @IBAction private func delegateAndDismiss(_ sender: Any?) { + delegate?.accountControllerDidCancel(self) + dismiss(self) + } + + override func cancelOperation(_ sender: Any?) { + delegateAndDismiss(sender) + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/ConfigurationViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/ConfigurationViewController.swift new file mode 100644 index 00000000..c130e303 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/ConfigurationViewController.swift @@ -0,0 +1,300 @@ +// +// ConfigurationViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 5/31/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +class ConfigurationViewController: NSViewController, ProfileCustomization { + @IBOutlet private weak var labelPresetCaption: NSTextField! + + @IBOutlet private weak var popupPreset: NSPopUpButton! + + @IBOutlet private weak var boxCommunication: NSBox! + + @IBOutlet private weak var labelCipherCaption: NSTextField! + + @IBOutlet private weak var popupCipher: NSPopUpButton! + + @IBOutlet private weak var labelDigestCaption: NSTextField! + + @IBOutlet private weak var popupDigest: NSPopUpButton! + + @IBOutlet private weak var boxCompression: NSBox! + + @IBOutlet private weak var labelCompressionFramingCaption: NSTextField! + + @IBOutlet private weak var popupCompressionFraming: NSPopUpButton! + + @IBOutlet private weak var labelCompressionAlgorithmCaption: NSTextField! + + @IBOutlet private weak var popupCompressionAlgorithm: NSPopUpButton! + + @IBOutlet private weak var boxTLS: NSBox! + + @IBOutlet private weak var labelClientCertificateCaption: NSTextField! + + @IBOutlet private weak var labelClientCertificate: NSTextField! + + @IBOutlet private weak var labelWrappingCaption: NSTextField! + + @IBOutlet private weak var labelWrapping: NSTextField! + + @IBOutlet private weak var labelExtendedVerificationCaption: NSTextField! + + @IBOutlet private weak var labelExtendedVerification: NSTextField! + + @IBOutlet private weak var boxOther: NSBox! + + @IBOutlet private weak var labelKeepAliveCaption: NSTextField! + + @IBOutlet private weak var labelKeepAlive: NSTextField! + + @IBOutlet private weak var labelRenegotiationCaption: NSTextField! + + @IBOutlet private weak var labelRenegotiation: NSTextField! + + @IBOutlet private weak var labelRandomizeEndpointCaption: NSTextField! + + @IBOutlet private weak var labelRandomizeEndpoint: NSTextField! + + private lazy var allPresets: [InfrastructurePreset] = { + guard let providerProfile = profile as? ProviderConnectionProfile else { + return [] + } + let infra = providerProfile.infrastructure + return providerProfile.pool?.supportedPresetIds(in: infra).map { + return infra.preset(for: $0)! + } ?? [] + }() + + private var preset: InfrastructurePreset? { + didSet { + guard let preset = preset else { + return + } + configuration = preset.configuration.sessionConfiguration.builder() + } + } + + private var configuration = OpenVPN.ConfigurationBuilder() + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? { + didSet { + if let providerProfile = profile as? ProviderConnectionProfile { + preset = providerProfile.preset + } else if let hostProfile = profile as? HostConnectionProfile { + configuration = hostProfile.parameters.sessionConfiguration.builder() + } + } + } + + weak var delegate: ProfileCustomizationDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + let V = L10n.Core.Configuration.Cells.self + + labelPresetCaption.stringValue = L10n.Core.Service.Cells.Provider.Preset.caption.asCaption + popupPreset.removeAllItems() + if !allPresets.isEmpty { + for preset in allPresets { + popupPreset.addItem(withTitle: preset.name) + } + popupCipher.isEnabled = false + popupDigest.isEnabled = false + popupCompressionFraming.isEnabled = false + popupCompressionAlgorithm.isEnabled = false + } else { + popupPreset.addItem(withTitle: L10n.App.Global.Values.default) + popupPreset.isEnabled = false + } + + boxCommunication.title = L10n.Core.Configuration.Sections.Communication.header + boxCompression.title = L10n.Core.Configuration.Sections.Compression.header + boxTLS.title = L10n.Core.Configuration.Sections.Tls.header + boxOther.title = L10n.Core.Configuration.Sections.Other.header + + labelCipherCaption.stringValue = V.Cipher.caption.asCaption + labelDigestCaption.stringValue = V.Digest.caption.asCaption + labelCompressionFramingCaption.stringValue = V.CompressionFraming.caption.asCaption + labelCompressionAlgorithmCaption.stringValue = V.CompressionAlgorithm.caption.asCaption + labelClientCertificateCaption.stringValue = V.Client.caption.asCaption + labelWrappingCaption.stringValue = V.TlsWrapping.caption.asCaption + labelExtendedVerificationCaption.stringValue = V.Eku.caption.asCaption + labelKeepAliveCaption.stringValue = V.KeepAlive.caption.asCaption + labelRenegotiationCaption.stringValue = V.RenegotiationSeconds.caption.asCaption + labelRandomizeEndpointCaption.stringValue = V.RandomEndpoint.caption.asCaption + + popupCipher.removeAllItems() + popupDigest.removeAllItems() + popupCompressionFraming.removeAllItems() + popupCompressionAlgorithm.removeAllItems() + for cipher in OpenVPN.Cipher.available { + popupCipher.addItem(withTitle: cipher.rawValue) + } + for digest in OpenVPN.Digest.available { + popupDigest.addItem(withTitle: digest.rawValue) + } + for framing in OpenVPN.CompressionFraming.available { + popupCompressionFraming.addItem(withTitle: framing.itemDescription) + } + for algorithm in OpenVPN.CompressionAlgorithm.available { + popupCompressionAlgorithm.addItem(withTitle: algorithm.itemDescription) + } + + reloadModel() + } + + private func reloadModel() { + let V = L10n.Core.Configuration.Cells.self + + if let index = allPresets.firstIndex(where: { $0.id == preset?.id }) { + popupPreset.selectItem(at: index) + } + if let index = OpenVPN.Cipher.available.firstIndex(of: configuration.fallbackCipher) { + popupCipher.selectItem(at: index) + } + if let index = OpenVPN.Digest.available.firstIndex(of: configuration.fallbackDigest) { + popupDigest.selectItem(at: index) + } + if let index = OpenVPN.CompressionFraming.available.firstIndex(of: configuration.compressionFraming ?? .disabled) { + popupCompressionFraming.selectItem(at: index) + } + if let index = OpenVPN.CompressionAlgorithm.available.firstIndex(of: configuration.compressionAlgorithm ?? .disabled) { + popupCompressionAlgorithm.selectItem(at: index) + } + + // enforce item constraints + selectCompressionFraming(nil) + selectCompressionAlgorithm(nil) + + labelClientCertificate.stringValue = (configuration.clientCertificate != nil) ? V.Client.Value.enabled : V.Client.Value.disabled + if let strategy = configuration.tlsWrap?.strategy { + switch strategy { + case .auth: + labelWrapping.stringValue = V.TlsWrapping.Value.auth + + case .crypt: + labelWrapping.stringValue = V.TlsWrapping.Value.crypt + } + } else { + labelWrapping.stringValue = L10n.Core.Global.Values.disabled + } + labelExtendedVerification.stringValue = (configuration.checksEKU ?? false) ? L10n.Core.Global.Values.enabled : L10n.Core.Global.Values.disabled + + if let keepAlive = configuration.keepAliveInterval, keepAlive > 0 { + labelKeepAlive.stringValue = V.KeepAlive.Value.seconds(Int(keepAlive)) + } else { + labelKeepAlive.stringValue = L10n.Core.Global.Values.disabled + } + if let reneg = configuration.renegotiatesAfter, reneg > 0 { + labelRenegotiation.stringValue = V.RenegotiationSeconds.Value.after(TimeInterval(reneg).localized) + } else { + labelRenegotiation.stringValue = L10n.Core.Global.Values.disabled + } + labelRandomizeEndpoint.stringValue = (configuration.randomizeEndpoint ?? false) ? L10n.Core.Global.Values.enabled : L10n.Core.Global.Values.disabled + } + + // MARK: Actions + + @IBAction private func selectPreset(_ sender: Any?) { + let preset = allPresets[popupPreset.indexOfSelectedItem] + self.preset = preset + reloadModel() + delegate?.profileCustomization(self, didUpdatePreset: preset) + } + + @IBAction private func selectCipher(_ sender: Any?) { + configuration.cipher = OpenVPN.Cipher.available[popupCipher.indexOfSelectedItem] + delegate?.profileCustomization(self, didUpdateConfiguration: configuration) + } + + @IBAction private func selectDigest(_ sender: Any?) { + configuration.digest = OpenVPN.Digest.available[popupDigest.indexOfSelectedItem] + delegate?.profileCustomization(self, didUpdateConfiguration: configuration) + } + + @IBAction private func selectCompressionFraming(_ sender: Any?) { + + // if framing is disabled, disable algorithm + if popupCompressionFraming.indexOfSelectedItem == 0 { + popupCompressionAlgorithm.selectItem(at: 0) + } + + configuration.compressionFraming = OpenVPN.CompressionFraming.available[popupCompressionFraming.indexOfSelectedItem] + configuration.compressionAlgorithm = OpenVPN.CompressionAlgorithm.available[popupCompressionAlgorithm.indexOfSelectedItem] + delegate?.profileCustomization(self, didUpdateConfiguration: configuration) + } + + @IBAction private func selectCompressionAlgorithm(_ sender: Any?) { + + // if framing is disabled and algorithm is not disabled, enable --comp-lzo framing + if popupCompressionFraming.indexOfSelectedItem == 0 && popupCompressionAlgorithm.indexOfSelectedItem != 0 { + popupCompressionFraming.selectItem(at: 1) + } + + configuration.compressionFraming = OpenVPN.CompressionFraming.available[popupCompressionFraming.indexOfSelectedItem] + configuration.compressionAlgorithm = OpenVPN.CompressionAlgorithm.available[popupCompressionAlgorithm.indexOfSelectedItem] + delegate?.profileCustomization(self, didUpdateConfiguration: configuration) + } +} + +// MARK: - + +private extension OpenVPN.CompressionFraming { + var itemDescription: String { + let V = L10n.Core.Configuration.Cells.self + switch self { + case .disabled: + return L10n.Core.Global.Values.disabled + + case .compLZO: + return V.CompressionFraming.Value.lzo + + case .compress: + return V.CompressionFraming.Value.compress + } + } +} + +private extension OpenVPN.CompressionAlgorithm { + var itemDescription: String { + let V = L10n.Core.Configuration.Cells.self + switch self { + case .disabled: + return L10n.Core.Global.Values.disabled + + case .LZO: + return V.CompressionAlgorithm.Value.lzo + + case .other: + return V.CompressionAlgorithm.Value.other + } + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/DNSViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/DNSViewController.swift new file mode 100644 index 00000000..cb1e38b1 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/DNSViewController.swift @@ -0,0 +1,157 @@ +// +// DNSViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/21/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +class DNSViewController: NSViewController, ProfileCustomization { + private struct Templates { + static let domain = "" + + static let server = "0.0.0.0" + } + + @IBOutlet private weak var popupChoice: NSPopUpButton! + + @IBOutlet private weak var viewSettings: NSView! + + @IBOutlet private weak var viewDNSDomains: NSView! + + @IBOutlet private weak var viewDNSAddresses: NSView! + + @IBOutlet private var constraintChoiceBottom: NSLayoutConstraint! + + @IBOutlet private var constraintSettingsTop: NSLayoutConstraint! + + private lazy var tableDNSDomains: TextTableView = .get() + + private lazy var tableDNSAddresses: TextTableView = .get() + + private lazy var choices = NetworkChoice.choices(for: profile) + + private lazy var currentChoice = profile?.networkChoices?.dns ?? ProfileNetworkChoices.with(profile: profile).dns + + private lazy var clientNetworkSettings = profile?.clientNetworkSettings + + private let networkSettings = ProfileNetworkSettings() + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? + + weak var delegate: ProfileCustomizationDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + tableDNSDomains.title = L10n.App.NetworkSettings.Dns.Cells.Domains.title.asCaption + viewDNSDomains.addSubview(tableDNSDomains) + tableDNSDomains.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + tableDNSDomains.topAnchor.constraint(equalTo: viewDNSDomains.topAnchor), + tableDNSDomains.bottomAnchor.constraint(equalTo: viewDNSDomains.bottomAnchor), + tableDNSDomains.leftAnchor.constraint(equalTo: viewDNSDomains.leftAnchor), + tableDNSDomains.rightAnchor.constraint(equalTo: viewDNSDomains.rightAnchor), + ]) + + tableDNSAddresses.title = L10n.App.NetworkSettings.Dns.Cells.Addresses.title.asCaption + viewDNSAddresses.addSubview(tableDNSAddresses) + tableDNSAddresses.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + tableDNSAddresses.topAnchor.constraint(equalTo: viewDNSAddresses.topAnchor), + tableDNSAddresses.bottomAnchor.constraint(equalTo: viewDNSAddresses.bottomAnchor), + tableDNSAddresses.leftAnchor.constraint(equalTo: viewDNSAddresses.leftAnchor), + tableDNSAddresses.rightAnchor.constraint(equalTo: viewDNSAddresses.rightAnchor), + ]) + + popupChoice.removeAllItems() + for choice in choices { + popupChoice.addItem(withTitle: choice.description) + if choice == currentChoice { + popupChoice.selectItem(at: popupChoice.numberOfItems - 1) + } + } + tableDNSDomains.rowTemplate = Templates.domain + tableDNSAddresses.rowTemplate = Templates.server + loadSettings(from: currentChoice) + } + + // MARK: Actions + + @IBAction private func pickChoice(_ sender: Any?) { + let choice = choices[popupChoice.indexOfSelectedItem] + loadSettings(from: choice) + + delegate?.profileCustomization(self, didUpdateDNS: choice, withManualSettings: networkSettings) + } + + func commitManualSettings() { + guard currentChoice == .manual else { + return + } + view.endEditing() + networkSettings.dnsSearchDomains = tableDNSDomains.rows + networkSettings.dnsServers = tableDNSAddresses.rows + + delegate?.profileCustomization(self, didUpdateDNS: .manual, withManualSettings: networkSettings) + } + + // MARK: Helpers + + private func loadSettings(from choice: NetworkChoice) { + currentChoice = choice + switch currentChoice { + case .client: + if let settings = clientNetworkSettings { + networkSettings.copyDNS(from: settings) + } + + case .server: + break + + case .manual: + if let settings = profile?.manualNetworkSettings { + networkSettings.copyDNS(from: settings) + } + } + + tableDNSDomains.isEnabled = (currentChoice == .manual) + tableDNSDomains.rows = networkSettings.dnsSearchDomains ?? [] + tableDNSDomains.isRemoveEnabled = false + tableDNSDomains.selectedRow = nil + tableDNSDomains.reloadData() + + tableDNSAddresses.isAddEnabled = (currentChoice == .manual) + tableDNSAddresses.rows = networkSettings.dnsServers ?? [] + tableDNSAddresses.isRemoveEnabled = false + tableDNSAddresses.selectedRow = nil + tableDNSAddresses.reloadData() + + let isServer = (currentChoice == .server) + constraintChoiceBottom.priority = isServer ? .defaultHigh : .defaultLow + constraintSettingsTop.priority = isServer ? .defaultLow : .defaultHigh + viewSettings.isHidden = isServer + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/DefaultGatewayViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/DefaultGatewayViewController.swift new file mode 100644 index 00000000..b279335c --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/DefaultGatewayViewController.swift @@ -0,0 +1,137 @@ +// +// DefaultGatewayViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/21/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +class DefaultGatewayViewController: NSViewController, ProfileCustomization { + @IBOutlet private weak var popupChoice: NSPopUpButton! + + @IBOutlet private weak var viewSettings: NSView! + + @IBOutlet private weak var checkIPv4: NSButton! + + @IBOutlet private weak var checkIPv6: NSButton! + + @IBOutlet private var constraintChoiceBottom: NSLayoutConstraint! + + @IBOutlet private var constraintSettingsTop: NSLayoutConstraint! + + private lazy var choices = NetworkChoice.choices(for: profile) + + private lazy var currentChoice = profile?.networkChoices?.gateway ?? ProfileNetworkChoices.with(profile: profile).gateway + + private lazy var clientNetworkSettings = profile?.clientNetworkSettings + + private let networkSettings = ProfileNetworkSettings() + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? + + weak var delegate: ProfileCustomizationDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + checkIPv4.title = "IPv4" + checkIPv6.title = "IPv6" + + popupChoice.removeAllItems() + for choice in choices { + popupChoice.addItem(withTitle: choice.description) + if choice == currentChoice { + popupChoice.selectItem(at: popupChoice.numberOfItems - 1) + } + } + loadSettings(from: currentChoice) + } + + // MARK: Actions + + @IBAction private func pickChoice(_ sender: Any?) { + let choice = choices[popupChoice.indexOfSelectedItem] + loadSettings(from: choice) + + delegate?.profileCustomization(self, didUpdateGateway: choice, withManualSettings: networkSettings) + } + + @IBAction private func checkPolicy(_ sender: Any?) { + guard let button = sender as? NSButton else { + return + } + var policies = Set(networkSettings.gatewayPolicies ?? []) + let policy: OpenVPN.RoutingPolicy + switch button { + case checkIPv4: + policy = .IPv4 + + case checkIPv6: + policy = .IPv6 + + default: + return + } + if button.state == .on { + policies.insert(policy) + } else { + policies.remove(policy) + } + networkSettings.gatewayPolicies = Array(policies) + + delegate?.profileCustomization(self, didUpdateGateway: .manual, withManualSettings: networkSettings) + } + + private func loadSettings(from choice: NetworkChoice) { + currentChoice = choice + switch currentChoice { + case .client: + if let settings = clientNetworkSettings { + networkSettings.copyGateway(from: settings) + } + + case .server: + break + + case .manual: + if let settings = profile?.manualNetworkSettings { + networkSettings.copyGateway(from: settings) + } + } + + let policies = networkSettings.gatewayPolicies ?? [] + + checkIPv4.isEnabled = (currentChoice == .manual) + checkIPv4.state = policies.contains(.IPv4) ? .on : .off + checkIPv6.isEnabled = (currentChoice == .manual) + checkIPv6.state = policies.contains(.IPv6) ? .on : .off + + let isServer = (currentChoice == .server) + constraintChoiceBottom.priority = isServer ? .defaultHigh : .defaultLow + constraintSettingsTop.priority = isServer ? .defaultLow : .defaultHigh + viewSettings.isHidden = isServer + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/EndpointViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/EndpointViewController.swift new file mode 100644 index 00000000..67935a33 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/EndpointViewController.swift @@ -0,0 +1,120 @@ +// +// EndpointViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/19/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +class EndpointViewController: NSViewController, ProfileCustomization { + @IBOutlet private weak var labelAddressCaption: NSTextField! + + @IBOutlet private weak var popupAddress: NSPopUpButton! + + @IBOutlet private weak var labelProtocolCaption: NSTextField! + + @IBOutlet private weak var popupProtocol: NSPopUpButton! + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? + + weak var delegate: ProfileCustomizationDelegate? + + private lazy var dataSource: EndpointDataSource = { + guard let profile = profile else { + fatalError("No profile set") + } + return profile as EndpointDataSource + }() + + override func viewDidLoad() { + super.viewDidLoad() + + labelAddressCaption.stringValue = L10n.App.Endpoint.Cells.address.asCaption + labelProtocolCaption.stringValue = L10n.App.Endpoint.Cells.protocol.asCaption + + popupAddress.removeAllItems() + for address in dataSource.addresses { + popupAddress.addItem(withTitle: address) + if address == dataSource.customAddress { + popupAddress.selectItem(at: popupAddress.numberOfItems - 1) + } + } + popupProtocol.removeAllItems() + for proto in dataSource.protocols { + popupProtocol.addItem(withTitle: proto.rawValue) + if proto == dataSource.customProtocol { + popupProtocol.selectItem(at: popupProtocol.numberOfItems - 1) + } + } + + if dataSource.canCustomizeEndpoint { + popupAddress.insertItem(withTitle: L10n.Core.Endpoint.Cells.AnyAddress.caption, at: 0) + popupProtocol.insertItem(withTitle: L10n.Core.Endpoint.Cells.AnyProtocol.caption, at: 0) + + if dataSource.customAddress == nil { + popupAddress.selectItem(at: 0) + } + if dataSource.customProtocol == nil { + popupProtocol.selectItem(at: 0) + } +// } else { +// popupAddress.isEnabled = false +// popupProtocol.isEnabled = false + } + } + + // MARK: Actions + + @IBAction private func selectAddress(_ sender: Any?) { + guard dataSource.canCustomizeEndpoint else { + return + } + let customAddress: String? + if popupAddress.indexOfSelectedItem == 0 { + customAddress = nil + } else { + customAddress = popupAddress.selectedItem?.title + } + delegate?.profileCustomization(self, didUpdateEndpointWithAddress: customAddress) + } + + @IBAction private func selectProtocol(_ sender: Any?) { + guard dataSource.canCustomizeEndpoint else { + return + } + let customProtocol: EndpointProtocol? + if popupProtocol.indexOfSelectedItem == 0 { + customProtocol = nil + } else { + if let title = popupProtocol.selectedItem?.title { + customProtocol = EndpointProtocol(rawValue: title) + } else { + customProtocol = nil + } + } + delegate?.profileCustomization(self, didUpdateEndpointWithProtocol: customProtocol) + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/MTUViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/MTUViewController.swift new file mode 100644 index 00000000..adde80de --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/MTUViewController.swift @@ -0,0 +1,139 @@ +// +// MTUViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 12/28/20. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +class MTUViewController: NSViewController, ProfileCustomization { + @IBOutlet private weak var popupChoice: NSPopUpButton! + + @IBOutlet private weak var viewSettings: NSView! + + @IBOutlet private weak var labelMTUCaption: NSTextField! + + @IBOutlet private weak var popupMTU: NSPopUpButton! + + @IBOutlet private var constraintChoiceBottom: NSLayoutConstraint! + + @IBOutlet private var constraintSettingsTop: NSLayoutConstraint! + + private lazy var choices = NetworkChoice.choices(for: profile) + + private lazy var currentChoice = profile?.networkChoices?.mtu ?? ProfileNetworkChoices.with(profile: profile).mtu + + private lazy var clientNetworkSettings = profile?.clientNetworkSettings + + private let networkSettings = ProfileNetworkSettings() + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? + + weak var delegate: ProfileCustomizationDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + popupChoice.removeAllItems() + for choice in choices { + popupChoice.addItem(withTitle: choice.description) + if choice == currentChoice { + popupChoice.selectItem(at: popupChoice.numberOfItems - 1) + } + } + labelMTUCaption.stringValue = L10n.Core.NetworkSettings.Mtu.Cells.Bytes.caption.asCaption + popupMTU.removeAllItems() + for opt in ProfileNetworkSettings.mtuOptions { + popupMTU.addItem(withTitle: (opt != 0) ? opt.description : "Default") + } + loadSettings(from: currentChoice ?? ProfileNetworkChoices.defaultChoice) + } + + // MARK: Actions + + @IBAction private func pickChoice(_ sender: Any?) { + let choice = choices[popupChoice.indexOfSelectedItem] + loadSettings(from: choice) + + delegate?.profileCustomization(self, didUpdateMTU: choice, withManualSettings: networkSettings) + } + + @IBAction private func pickBytes(_ sender: Any?) { + guard let popup = sender as? NSPopUpButton, let title = popup.titleOfSelectedItem else { + return + } + guard let bytes = Int(title) else { + networkSettings.mtuBytes = nil + return + } + networkSettings.mtuBytes = bytes + + delegate?.profileCustomization(self, didUpdateMTU: .manual, withManualSettings: networkSettings) + } + + private func loadSettings(from choice: NetworkChoice) { + currentChoice = choice + switch choice { + case .client: + if let settings = clientNetworkSettings { + networkSettings.copyMTU(from: settings) + } + + case .server: + break + + case .manual: + if let settings = profile?.manualNetworkSettings { + networkSettings.copyMTU(from: settings) + } + } + + let bytes = networkSettings.mtuBytes + + popupMTU.isEnabled = (currentChoice == .manual) + for (i, opt) in popupMTU.itemTitles.enumerated() { + if opt == "Default" { + if bytes == nil { + popupMTU.selectItem(at: i) + break + } + continue + } + guard let optValue = Int(opt) else { + continue + } + if optValue == bytes { + popupMTU.selectItem(at: i) + break + } + } + + let isServer = (currentChoice == .server) + constraintChoiceBottom.priority = isServer ? .defaultHigh : .defaultLow + constraintSettingsTop.priority = isServer ? .defaultLow : .defaultHigh + viewSettings.isHidden = isServer + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/ProfileCustomizationViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/ProfileCustomizationViewController.swift new file mode 100644 index 00000000..d935c248 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/ProfileCustomizationViewController.swift @@ -0,0 +1,258 @@ +// +// ProfileCustomizationViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/19/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit + +protocol ProfileCustomization: class { + var profile: ConnectionProfile? { get set } + + var delegate: ProfileCustomizationDelegate? { get set } +} + +protocol ProfileCustomizationDelegate: class { + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateEndpointWithAddress newAddress: String?) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateEndpointWithProtocol newEndpointProtocol: EndpointProtocol?) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdatePreset newPreset: InfrastructurePreset) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateConfiguration newConfiguration: OpenVPN.ConfigurationBuilder) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateTrustedNetworks newTrustedNetworks: TrustedNetworks) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateGateway choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateDNS choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateProxy choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateMTU choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) +} + +class ProfileCustomizationContainerViewController: NSViewController { + @IBOutlet private weak var buttonOK: NSButton! + + @IBOutlet private weak var buttonCancel: NSButton! + + fileprivate weak var dnsController: DNSViewController? + + fileprivate weak var proxyController: ProxyViewController? + + var profile: ConnectionProfile? + + // MARK: Pending (provider) + + private var pendingAddress: String? + + private var pendingProtocol: EndpointProtocol? + + private var pendingPreset: InfrastructurePreset? + + // MARK: Pending (host) + + private var pendingParameters: OpenVPN.ConfigurationBuilder? + + // MARK: Pending + + private var pendingTrustedNetworks: TrustedNetworks? + + private var pendingChoices: ProfileNetworkChoices? + + private let pendingManualNetworkSettings = ProfileNetworkSettings() + + override func viewDidLoad() { + super.viewDidLoad() + + buttonOK.title = L10n.Core.Global.ok + buttonCancel.title = L10n.Core.Global.cancel + + pendingAddress = (profile as? ProviderConnectionProfile)?.customAddress + pendingProtocol = (profile as? ProviderConnectionProfile)?.customProtocol + pendingPreset = (profile as? ProviderConnectionProfile)?.preset + pendingTrustedNetworks = profile?.trustedNetworks + pendingParameters = (profile as? HostConnectionProfile)?.parameters.sessionConfiguration.builder() + pendingChoices = ProfileNetworkChoices.with(profile: profile) + } + + override func prepare(for segue: NSStoryboardSegue, sender: Any?) { + guard let customVC = segue.destinationController as? ProfileCustomizationViewController else { + return + } + customVC.containerController = self + customVC.profile = profile + } + + // MARK: Actions + + @IBAction private func commitChanges(_ sender: Any?) { + dnsController?.commitManualSettings() + proxyController?.commitManualSettings() + + if let providerProfile = profile as? ProviderConnectionProfile { + if let pending = pendingPreset { + providerProfile.presetId = pending.id + } + } else if let hostProfile = profile as? HostConnectionProfile, let pendingParameters = pendingParameters { + var builder = hostProfile.parameters.builder() + builder.sessionConfiguration = pendingParameters.build() + hostProfile.parameters = builder.build() + } + profile?.customAddress = pendingAddress + profile?.customProtocol = pendingProtocol + profile?.trustedNetworks = pendingTrustedNetworks + + if let choices = pendingChoices { + let settings = profile?.manualNetworkSettings ?? ProfileNetworkSettings() + if choices.gateway == .manual { + settings.copyGateway(from: pendingManualNetworkSettings) + } + if choices.dns == .manual { + settings.copyDNS(from: pendingManualNetworkSettings) + } + if choices.proxy == .manual { + settings.copyProxy(from: pendingManualNetworkSettings) + } + if choices.mtu == .manual { + settings.copyMTU(from: pendingManualNetworkSettings) + } + profile?.networkChoices = choices + profile?.manualNetworkSettings = settings + } + + TransientStore.shared.serialize(withProfiles: true) // customize + + if let profile = profile, TransientStore.shared.service.isActiveProfile(ProfileKey(profile)) { + let vpn = GracefulVPN(service: TransientStore.shared.service) + if vpn.isEnabled { + switch vpn.status { + case .connected, .connecting: + let alert = Macros.warning( + L10n.App.Configuration.title, + L10n.App.Configuration.Alerts.Commit.message + ) + if alert.presentModally( + withOK: L10n.App.Configuration.Alerts.Commit.Buttons.reconnect, + cancel: L10n.App.Configuration.Alerts.Commit.Buttons.skip) { + + vpn.reconnect(completionHandler: nil) + } else { + vpn.reinstall(completionHandler: nil) + } + + default: + vpn.reinstall(completionHandler: nil) + } + } + } + + dismiss(self) + } +} + +extension ProfileCustomizationContainerViewController: ProfileCustomizationDelegate { + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateEndpointWithAddress newAddress: String?) { + pendingAddress = newAddress + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateEndpointWithProtocol newEndpointProtocol: EndpointProtocol?) { + pendingProtocol = newEndpointProtocol + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdatePreset newPreset: InfrastructurePreset) { + pendingPreset = newPreset + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateConfiguration newConfiguration: OpenVPN.ConfigurationBuilder) { + pendingParameters = newConfiguration + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateTrustedNetworks newTrustedNetworks: TrustedNetworks) { + pendingTrustedNetworks = newTrustedNetworks + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateGateway choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) { + pendingChoices?.gateway = choice + pendingManualNetworkSettings.gatewayPolicies = newSettings.gatewayPolicies + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateDNS choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) { + pendingChoices?.dns = choice + pendingManualNetworkSettings.dnsSearchDomains = newSettings.dnsSearchDomains + pendingManualNetworkSettings.dnsServers = newSettings.dnsServers + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateProxy choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) { + pendingChoices?.proxy = choice + pendingManualNetworkSettings.proxyAddress = newSettings.proxyAddress + pendingManualNetworkSettings.proxyPort = newSettings.proxyPort + pendingManualNetworkSettings.proxyBypassDomains = newSettings.proxyBypassDomains + } + + func profileCustomization(_ profileCustomization: ProfileCustomization, didUpdateMTU choice: NetworkChoice, withManualSettings newSettings: ProfileNetworkSettings) { + pendingChoices?.mtu = choice + pendingManualNetworkSettings.mtuBytes = newSettings.mtuBytes + } +} + +// + +class ProfileCustomizationViewController: NSTabViewController { + fileprivate weak var containerController: ProfileCustomizationContainerViewController? + + fileprivate var profile: ConnectionProfile? { + didSet { + for item in tabViewItems { + guard let custom = item.viewController as? ProfileCustomization else { + continue + } + custom.profile = profile + custom.delegate = containerController + + if let vc = custom as? DNSViewController { + containerController?.dnsController = vc + } else if let vc = custom as? ProxyViewController { + containerController?.proxyController = vc + } + } + } + } + + override func viewDidLoad() { + super.viewDidLoad() + + let expectedTabs = 7 + assert(tabViewItems.count == expectedTabs, "Customization tabs misconfigured (expected \(expectedTabs))") + + tabViewItems[0].label = L10n.Core.Endpoint.title + tabViewItems[1].label = L10n.App.Configuration.title + tabViewItems[2].label = L10n.Core.Service.Sections.Trusted.header + tabViewItems[3].label = L10n.Core.NetworkSettings.Gateway.title + tabViewItems[4].label = L10n.Core.NetworkSettings.Dns.title + tabViewItems[5].label = L10n.Core.NetworkSettings.Proxy.title + tabViewItems[6].label = L10n.Core.NetworkSettings.Mtu.title + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/ProxyViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/ProxyViewController.swift new file mode 100644 index 00000000..58f7ac23 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/ProxyViewController.swift @@ -0,0 +1,149 @@ +// +// ProxyViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/21/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +class ProxyViewController: NSViewController, ProfileCustomization { + private struct Templates { + static let bypass = "domain.com" + } + + @IBOutlet private weak var popupChoice: NSPopUpButton! + + @IBOutlet private weak var viewSettings: NSView! + + @IBOutlet private weak var labelProxyCaption: NSTextField! + + @IBOutlet private weak var textProxyAddress: NSTextField! + + @IBOutlet private weak var textProxyPort: NSTextField! + + @IBOutlet private weak var viewProxyBypass: NSView! + + @IBOutlet private var constraintChoiceBottom: NSLayoutConstraint! + + @IBOutlet private var constraintSettingsTop: NSLayoutConstraint! + + private lazy var tableProxyBypass: TextTableView = .get() + + private lazy var choices = NetworkChoice.choices(for: profile) + + private lazy var currentChoice = profile?.networkChoices?.proxy ?? ProfileNetworkChoices.with(profile: profile).proxy + + private lazy var clientNetworkSettings = profile?.clientNetworkSettings + + private let networkSettings = ProfileNetworkSettings() + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? + + weak var delegate: ProfileCustomizationDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + labelProxyCaption.stringValue = L10n.Core.Global.Captions.address.asCaption + textProxyAddress.placeholderString = L10n.Core.Global.Values.none + textProxyPort.placeholderString = L10n.Core.Global.Values.none + + tableProxyBypass.title = L10n.App.NetworkSettings.Proxy.Cells.BypassDomains.title.asCaption + viewProxyBypass.addSubview(tableProxyBypass) + tableProxyBypass.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + tableProxyBypass.topAnchor.constraint(equalTo: viewProxyBypass.topAnchor), + tableProxyBypass.bottomAnchor.constraint(equalTo: viewProxyBypass.bottomAnchor), + tableProxyBypass.leftAnchor.constraint(equalTo: viewProxyBypass.leftAnchor), + tableProxyBypass.rightAnchor.constraint(equalTo: viewProxyBypass.rightAnchor), + ]) + + popupChoice.removeAllItems() + for choice in choices { + popupChoice.addItem(withTitle: choice.description) + if choice == currentChoice { + popupChoice.selectItem(at: popupChoice.numberOfItems - 1) + } + } + tableProxyBypass.rowTemplate = Templates.bypass + loadSettings(from: currentChoice) + } + + // MARK: Actions + + @IBAction private func pickChoice(_ sender: Any?) { + let choice = choices[popupChoice.indexOfSelectedItem] + loadSettings(from: choice) + + delegate?.profileCustomization(self, didUpdateProxy: choice, withManualSettings: networkSettings) + } + + func commitManualSettings() { + guard currentChoice == .manual else { + return + } + view.endEditing() + networkSettings.proxyAddress = textProxyAddress.stringValue + networkSettings.proxyPort = UInt16(textProxyPort.stringValue) + networkSettings.proxyBypassDomains = tableProxyBypass.rows + + delegate?.profileCustomization(self, didUpdateProxy: .manual, withManualSettings: networkSettings) + } + + // MARK: Helpers + + private func loadSettings(from choice: NetworkChoice) { + currentChoice = choice + switch currentChoice { + case .client: + if let settings = clientNetworkSettings { + networkSettings.copyProxy(from: settings) + } + + case .server: + break + + case .manual: + if let settings = profile?.manualNetworkSettings { + networkSettings.copyProxy(from: settings) + } + } + + textProxyAddress.isEnabled = (currentChoice == .manual) + textProxyAddress.stringValue = networkSettings.proxyAddress ?? "" + textProxyPort.isEnabled = (currentChoice == .manual) + textProxyPort.stringValue = networkSettings.proxyPort?.description ?? "" + tableProxyBypass.rows = networkSettings.proxyBypassDomains ?? [] + tableProxyBypass.isAddEnabled = (currentChoice == .manual) + tableProxyBypass.isRemoveEnabled = false + tableProxyBypass.selectedRow = nil + tableProxyBypass.reloadData() + + let isServer = (currentChoice == .server) + constraintChoiceBottom.priority = isServer ? .defaultHigh : .defaultLow + constraintSettingsTop.priority = isServer ? .defaultLow : .defaultHigh + viewSettings.isHidden = isServer + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/TrustedNetworksAddViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/TrustedNetworksAddViewController.swift new file mode 100644 index 00000000..6351482f --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/TrustedNetworksAddViewController.swift @@ -0,0 +1,59 @@ +// +// TrustedNetworksAddViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/30/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +protocol TrustedNetworksAddViewControllerDelegate: class { + func trustedController(_ trustedController: TrustedNetworksAddViewController, didEnterSSID ssid: String) +} + +class TrustedNetworksAddViewController: NSViewController { + @IBOutlet private weak var textSSID: NSTextField! + + @IBOutlet private weak var buttonOK: NSButton! + + @IBOutlet private weak var buttonCancel: NSButton! + + weak var delegate: TrustedNetworksAddViewControllerDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + buttonOK.title = L10n.Core.Global.ok + buttonCancel.title = L10n.Core.Global.cancel + + textSSID.stringValue = Utils.currentWifiNetworkName() ?? "" + } + + @IBAction private func confirm(_ sender: Any?) { + let ssid = textSSID.stringValue.trimmingCharacters(in: .whitespaces) + guard !ssid.isEmpty else { + return + } + delegate?.trustedController(self, didEnterSSID: ssid) + dismiss(self) + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/Customization/TrustedNetworksViewController.swift b/Passepartout/App/macOS/Scenes/Service/Customization/TrustedNetworksViewController.swift new file mode 100644 index 00000000..951deac6 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/Customization/TrustedNetworksViewController.swift @@ -0,0 +1,235 @@ +// +// TrustedNetworksViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/29/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +class TrustedNetworksViewController: NSViewController, ProfileCustomization { + private struct Columns { + static let ssid = NSUserInterfaceItemIdentifier("SSID") + + static let trust = NSUserInterfaceItemIdentifier("Trust") + } + + @IBOutlet private weak var labelTitle: NSTextField! + + @IBOutlet private weak var tableView: NSTableView! + + @IBOutlet private weak var buttonAdd: NSButton! + + @IBOutlet private weak var buttonRemove: NSButton! + + @IBOutlet private weak var checkTrustEthernet: NSButton! + + @IBOutlet private weak var labelTrustEthernetDescription: NSTextField! + + @IBOutlet private weak var checkDisableConnection: NSButton! + + @IBOutlet private weak var labelDisableConnectionDescription: NSTextField! + + private let service = TransientStore.shared.service + + private let model = TrustedNetworksUI() + + // MARK: ProfileCustomization + + var profile: ConnectionProfile? + + private lazy var trustedNetworks = profile?.trustedNetworks ?? TrustedNetworks() + + weak var delegate: ProfileCustomizationDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + labelTitle.stringValue = L10n.Core.Service.Sections.Trusted.header.asCaption + buttonAdd.image = NSImage(named: NSImage.addTemplateName) + buttonRemove.image = NSImage(named: NSImage.removeTemplateName) + checkTrustEthernet.title = L10n.App.Trusted.Ethernet.title + labelTrustEthernetDescription.stringValue = L10n.App.Trusted.Ethernet.description + checkDisableConnection.title = L10n.Core.Service.Cells.TrustedPolicy.caption + labelDisableConnectionDescription.stringValue = L10n.Core.Service.Sections.Trusted.footer + + checkTrustEthernet.state = trustedNetworks.includesEthernet ? .on : .off + checkDisableConnection.state = (trustedNetworks.policy == .disconnect) ? .on : .off + model.delegate = self + model.load(from: trustedNetworks) + updateButtons() + + tableView.reloadData() + for column in tableView.tableColumns { + switch column.identifier { + case Columns.ssid: + column.title = "SSID" + + case Columns.trust: + column.title = L10n.App.Trusted.Columns.Trust.title + + default: + break + } + } + if tableView.numberOfRows > 0 { + tableView.selectRowIndexes(IndexSet(integer: 0), byExtendingSelection: false) + } + } + + // MARK: Actions + + @IBAction private func remove(_ sender: Any?) { + let index = tableView.selectedRow + guard index != -1 else { + return + } + model.removeWifi(at: index) + } + + @IBAction private func toggleTrustEthernet(_ sender: Any?) { + trustedNetworks.includesEthernet = (checkTrustEthernet.state == .on) + + delegate?.profileCustomization(self, didUpdateTrustedNetworks: trustedNetworks) + } + + @IBAction private func toggleRetainConnection(_ sender: Any?) { + let isOn = (checkDisableConnection.state == .on) + let completionHandler: () -> Void = { + self.trustedNetworks.policy = isOn ? .disconnect : .ignore + } + completionHandler() + + delegate?.profileCustomization(self, didUpdateTrustedNetworks: trustedNetworks) + } + + override func prepare(for segue: NSStoryboardSegue, sender: Any?) { + if let addVC = segue.destinationController as? TrustedNetworksAddViewController { + addVC.delegate = self + } + } + + // MARK: Helpers + + private func updateButtons() { + buttonRemove.isEnabled = !model.sortedWifis.isEmpty && (tableView.selectedRow != -1) + } +} + +extension TrustedNetworksViewController: NSTableViewDataSource, NSTableViewDelegate { + func numberOfRows(in tableView: NSTableView) -> Int { + return model.sortedWifis.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + guard row < model.sortedWifis.count else { // XXX + return nil + } + + let wifi = model.sortedWifis[row] + switch tableColumn?.identifier { + case Columns.ssid: + return wifi + + case Columns.trust: + return model.isTrusted(wifi: wifi) + + default: + return nil + } + } + + func tableView(_ tableView: NSTableView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, row: Int) { + guard row < model.sortedWifis.count else { // XXX + return + } + + switch tableColumn?.identifier { + case Columns.trust: + guard let checkTrust = object as? Bool else { + fatalError("Expected a Bool for trust checkbox state") + } + if checkTrust { + model.enableWifi(at: row) + } else { + model.disableWifi(at: row) + } + + default: + break + } + } + + func tableViewSelectionDidChange(_ notification: Notification) { + updateButtons() + } +} + +extension TrustedNetworksViewController: TrustedNetworksUIDelegate { + func trustedNetworksCouldDisconnect(_: TrustedNetworksUI) -> Bool { + + // VPN untouched + return false + } + + func trustedNetworksShouldConfirmDisconnection(_: TrustedNetworksUI, triggeredAt rowIndex: Int, completionHandler: @escaping () -> Void) { + let alert = Macros.warning( + L10n.Core.Service.Sections.Trusted.header, + L10n.Core.Service.Alerts.Trusted.WillDisconnectTrusted.message + ) + alert.present(in: view.window, withOK: L10n.Core.Global.ok, cancel: L10n.Core.Global.cancel, handler: completionHandler, cancelHandler: nil) + } + + func trustedNetworks(_: TrustedNetworksUI, shouldInsertWifiAt rowIndex: Int) { +// tableView.beginUpdates() +// tableView.insertRows(at: IndexSet(integer: rowIndex), withAnimation: .slideDown) +// tableView.endUpdates() + tableView.reloadData() + + updateButtons() + } + + func trustedNetworks(_: TrustedNetworksUI, shouldReloadWifiAt rowIndex: Int, isTrusted: Bool) { + // + } + + func trustedNetworks(_: TrustedNetworksUI, shouldDeleteWifiAt rowIndex: Int) { +// tableView.beginUpdates() +// tableView.removeRows(at: IndexSet(integer: rowIndex), withAnimation: .slideUp) +// tableView.endUpdates() + tableView.reloadData() + + updateButtons() + } + + func trustedNetworksShouldReinstall(_: TrustedNetworksUI) { + trustedNetworks.includedWiFis = model.trustedWifis + + delegate?.profileCustomization(self, didUpdateTrustedNetworks: trustedNetworks) + } +} + +extension TrustedNetworksViewController: TrustedNetworksAddViewControllerDelegate { + func trustedController(_ trustedController: TrustedNetworksAddViewController, didEnterSSID ssid: String) { + model.addWifi(ssid) + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/HostServiceView.swift b/Passepartout/App/macOS/Scenes/Service/HostServiceView.swift new file mode 100644 index 00000000..f67caeb0 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/HostServiceView.swift @@ -0,0 +1,77 @@ +// +// HostServiceView.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/13/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +protocol HostServiceViewDelegate: class { +} + +class HostServiceView: NSView { + @IBOutlet private weak var labelAddressesCaption: NSTextField! + + @IBOutlet private weak var tableAddresses: NSTableView! + + var isEnabled: Bool = true { + didSet { + } + } + + var profile: HostConnectionProfile? { + didSet { + tableAddresses.reloadData() + } + } + + weak var delegate: HostServiceViewDelegate? + + override func viewWillMove(toSuperview newSuperview: NSView?) { + super.viewWillMove(toSuperview: newSuperview) + + labelAddressesCaption.stringValue = L10n.App.Service.Cells.Addresses.caption.asCaption + } + + func reloadData() { + } +} + +extension HostServiceView: NSTableViewDataSource, NSTableViewDelegate { + func numberOfRows(in tableView: NSTableView) -> Int { + guard let profile = profile else { + return 0 + } + return profile.addresses.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + guard let profile = profile else { + return nil + } + return profile.addresses[row] + } + + func tableView(_ tableView: NSTableView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, row: Int) { + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/HostServiceView.xib b/Passepartout/App/macOS/Scenes/Service/HostServiceView.xib new file mode 100644 index 00000000..44a6a5c6 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/HostServiceView.xib @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Scenes/Service/ProviderServiceView.swift b/Passepartout/App/macOS/Scenes/Service/ProviderServiceView.swift new file mode 100644 index 00000000..a8d43820 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/ProviderServiceView.swift @@ -0,0 +1,249 @@ +// +// ProviderServiceView.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/13/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore + +protocol ProviderServiceViewDelegate: class { + func providerView(_ providerView: ProviderServiceView, didSelectPool pool: Pool) + + func providerViewDidRequestInfrastructureRefresh(_ providerView: ProviderServiceView) +} + +class ProviderServiceView: NSView { + @IBOutlet private weak var labelCategoryCaption: NSTextField! + + @IBOutlet private weak var popupCategory: NSPopUpButton! + + @IBOutlet private weak var labelLocationCaption: NSTextField! + + @IBOutlet private weak var popupLocation: NSPopUpButton! + + @IBOutlet private weak var popupArea: NSPopUpButton! + + @IBOutlet private weak var labelLastInfrastructureUpdate: NSTextField! + + @IBOutlet private weak var buttonRefreshInfrastructure: NSButton! + + var isEnabled: Bool = true { + didSet { + popupCategory.isEnabled = isEnabled + popupLocation.isEnabled = isEnabled + popupArea.isEnabled = isEnabled + } + } + + private var categories: [PoolCategory] = [] + + private var sortedGroupsByCategory: [String: [PoolGroup]] = [:] + + private var currentCategoryIndex = -1 + + private var currentLocationIndex = -1 + + private var currentSortedPools: [Pool] = [] + + var profile: ProviderConnectionProfile? { + didSet { + guard let profile = profile else { + categories = [] + sortedGroupsByCategory = [:] + currentSortedPools = [] + popupCategory.removeAllItems() + popupLocation.removeAllItems() + popupArea.removeAllItems() + return + } + reloadData(withProfile: profile) + } + } + + var isRefreshingInfrastructure: Bool = false { + didSet { + buttonRefreshInfrastructure.isEnabled = !isRefreshingInfrastructure + } + } + + weak var delegate: ProviderServiceViewDelegate? + + override func viewWillMove(toSuperview newSuperview: NSView?) { + super.viewWillMove(toSuperview: newSuperview) + + labelCategoryCaption.stringValue = L10n.App.Service.Cells.Category.caption.asCaption + labelLocationCaption.stringValue = L10n.Core.Service.Cells.Provider.Pool.caption.asCaption + buttonRefreshInfrastructure.image = NSImage(named: NSImage.refreshTemplateName) + } + + // MARK: Actions + + @IBAction private func selectCategory(_ sender: Any?) { + let index = popupCategory.indexOfSelectedItem + guard index != currentCategoryIndex else { + return + } + currentCategoryIndex = index + + loadLocations(withCategory: index) + loadAreas(withLocation: 0) + if let pool = currentSortedPools.first { + delegate?.providerView(self, didSelectPool: pool) + } + } + + @IBAction private func selectLocation(_ sender: Any?) { + let index = popupLocation.indexOfSelectedItem + guard index != currentLocationIndex else { + return + } + currentLocationIndex = index + + loadAreas(withLocation: index) + if let pool = currentSortedPools.first { + delegate?.providerView(self, didSelectPool: pool) + } + } + + @IBAction private func selectArea(_ sender: Any?) { + let pool = currentSortedPools[popupArea.indexOfSelectedItem] + delegate?.providerView(self, didSelectPool: pool) + } + + @IBAction private func refreshInfrastructure(_ sender: Any?) { + delegate?.providerViewDidRequestInfrastructureRefresh(self) + } + + // MARK: Helpers + + func reloadData() { + guard let profile = profile else { + return + } + reloadData(withProfile: profile) + } + + private func reloadData(withProfile profile: ProviderConnectionProfile) { + categories = profile.infrastructure.categories.sorted { $0.name.lowercased() < $1.name.lowercased() } + for c in categories { + sortedGroupsByCategory[c.name] = c.groups.sorted() + } + + popupCategory.removeAllItems() + categories.forEach { + let categoryTitle: String + if $0.name.isEmpty { + categoryTitle = L10n.App.Global.Values.default + } else { + categoryTitle = $0.name.capitalized + } + popupCategory.addItem(withTitle: categoryTitle) + } + + if let (a, b, c) = selectPopupsFromCurrentProfile() { + popupCategory.selectItem(at: a) + loadLocations(withCategory: a) + popupLocation.selectItem(at: b) + loadAreas(withLocation: b) + popupArea.selectItem(at: c) + + currentCategoryIndex = a + currentLocationIndex = b + } + if let lastInfrastructureUpdate = InfrastructureFactory.shared.modificationDate(forName: profile.name) { + labelLastInfrastructureUpdate.stringValue = L10n.Core.Service.Sections.ProviderInfrastructure.footer(lastInfrastructureUpdate.timestamp) + } + } + + private func selectPopupsFromCurrentProfile() -> (Int, Int, Int)? { + for (a, category) in categories.enumerated() { + guard let groups = sortedGroupsByCategory[category.name] else { + continue + } + for (b, group) in groups.enumerated() { + + // FIXME: inefficient, cache sorted pools + for (c, pool) in group.pools.sortedPools().enumerated() { + if pool.id == profile?.poolId { + return (a, b, c) + } + } + } + } + return nil + } + + private func loadLocations(withCategory index: Int) { + let category = categories[index] + let menu = NSMenu() + + popupLocation.removeAllItems() + sortedGroupsByCategory[category.name]?.forEach { + guard let pool = $0.pools.first else { + return + } + + var title = $0.localizedCountry + let subtitle: String? + if $0.pools.count > 1 { + subtitle = pool.area?.uppercased() + } else { + subtitle = pool.secondaryId + } + if !(subtitle?.isEmpty ?? true) { + title.append(" - \(subtitle!)") + } + + let item = NSMenuItem(title: title, action: nil, keyEquivalent: "") + item.image = $0.logo + menu.addItem(item) + } + popupLocation.menu = menu + } + + private func loadAreas(withLocation index: Int) { + let categoryIndex = popupCategory.indexOfSelectedItem + let category = categories[categoryIndex] + guard let sortedGroups = sortedGroupsByCategory[category.name] else { + fatalError("No groups in category \(category.name)") + } + let group = sortedGroups[index] + let menu = NSMenu() + + popupArea.removeAllItems() + // FIXME: inefficient, cache sorted pools + currentSortedPools = group.pools.sortedPools() + currentSortedPools.forEach { + guard !$0.secondaryId.isEmpty else { + return + } + let item = NSMenuItem(title: $0.secondaryId, action: nil, keyEquivalent: "") + if let extraCountry = $0.extraCountries?.first { + item.image = extraCountry.image + } + menu.addItem(item) + } + popupArea.menu = menu + popupArea.isHidden = menu.items.isEmpty + } +} diff --git a/Passepartout/App/macOS/Scenes/Service/ProviderServiceView.xib b/Passepartout/App/macOS/Scenes/Service/ProviderServiceView.xib new file mode 100644 index 00000000..1fc62476 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/ProviderServiceView.xib @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/Scenes/Service/ServiceViewController.swift b/Passepartout/App/macOS/Scenes/Service/ServiceViewController.swift new file mode 100644 index 00000000..159d05c6 --- /dev/null +++ b/Passepartout/App/macOS/Scenes/Service/ServiceViewController.swift @@ -0,0 +1,386 @@ +// +// ServiceViewController.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 7/29/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa +import PassepartoutCore +import TunnelKit +import SwiftyBeaver +import Convenience + +private let log = SwiftyBeaver.self + +class ServiceViewController: NSViewController { + @IBOutlet private weak var labelWelcome: NSTextField! + + @IBOutlet private weak var viewVPN: NSView! + + @IBOutlet private weak var viewProfile: NSView! + + @IBOutlet private weak var viewFooter: NSView! + + @IBOutlet private weak var labelStatusCaption: NSTextField! + + @IBOutlet private weak var labelStatus: NSTextField! + + @IBOutlet private weak var activityVPN: NSProgressIndicator! + + @IBOutlet private weak var labelServiceDescription: NSTextField! + + @IBOutlet private weak var viewInactive: NSView! + + @IBOutlet private weak var buttonUse: NSButton! + + @IBOutlet private weak var viewActive: NSView! + + @IBOutlet private weak var buttonToggle: NSButton! + + @IBOutlet private weak var buttonReconnect: NSButton! + + @IBOutlet private weak var labelConnectedLocation: NSTextField! + + @IBOutlet private weak var buttonCustomize: NSButton! + + @IBOutlet private weak var buttonAccount: NSButton! + + @IBOutlet private weak var viewProfileContainer: NSView! + + private lazy var viewProvider: ProviderServiceView = .get() + + private lazy var viewHost: HostServiceView = .get() + + private var profile: ConnectionProfile? + + private let service = TransientStore.shared.service + + private lazy var vpn = GracefulVPN(service: service) + + private var isPendingConnection = false + + deinit { + NotificationCenter.default.removeObserver(self) + } + + func setProfile(_ profile: ConnectionProfile?) { + defer { + let hasProfile = (self.profile != nil) + labelWelcome.isHidden = hasProfile + viewProfile.isHidden = !hasProfile + viewProfileContainer.isHidden = !hasProfile + viewFooter.isHidden = !hasProfile + reloadVpnStatus() + + if let profile = self.profile, service.isActiveProfile(profile) { + viewInactive.isHidden = true + viewActive.isHidden = false + buttonToggle.isEnabled = true + } else { + viewActive.isHidden = true + viewInactive.isHidden = false + buttonUse.isEnabled = true + } + } + + if let profile = profile, let currentProfile = self.profile { + guard (profile.context != currentProfile.context) || (profile.id != currentProfile.id) else { + return + } + } + + self.profile = profile + guard let _ = profile else { + return + } + + let view: NSView + if let providerProfile = profile as? ProviderConnectionProfile { + viewProvider.profile = providerProfile + viewProvider.delegate = self + view = viewProvider + } else if let hostProfile = profile as? HostConnectionProfile { + viewHost.profile = hostProfile + viewHost.delegate = self + view = viewHost + } else { + fatalError("Unexpected profile type") + } + + view.translatesAutoresizingMaskIntoConstraints = false + viewProfileContainer.subviews.forEach { + $0.removeFromSuperview() + } + viewProfileContainer.addSubview(view) + NSLayoutConstraint.activate([ + view.topAnchor.constraint(equalTo: viewProfileContainer.topAnchor), +// view.bottomAnchor.constraint(equalTo: viewProfileContainer.bottomAnchor), +// view.centerYAnchor.constraint(equalTo: viewProfileContainer.centerYAnchor), + view.rightAnchor.constraint(equalTo: viewProfileContainer.rightAnchor), + view.leftAnchor.constraint(equalTo: viewProfileContainer.leftAnchor), + ]) + } + + override func viewDidLoad() { + super.viewDidLoad() + + if profile == nil { + setProfile(service.activeProfile) + } + + // enforce on macOS + service.preferences.disconnectsOnSleep = true + + labelWelcome.stringValue = L10n.Core.Service.Welcome.message + labelStatusCaption.stringValue = L10n.Core.Service.Cells.ConnectionStatus.caption.asCaption + labelServiceDescription.stringValue = L10n.Core.Service.Sections.Vpn.footer + buttonUse.title = L10n.Core.Service.Cells.UseProfile.caption + buttonToggle.title = L10n.App.Service.Cells.Vpn.TurnOn.caption + buttonReconnect.title = L10n.Core.Service.Cells.Reconnect.caption + buttonCustomize.image = NSImage(named: NSImage.actionTemplateName) + buttonAccount.title = L10n.Core.Account.title.asContinuation + + let nc = NotificationCenter.default + nc.addObserver(self, selector: #selector(vpnDidUpdate), name: VPN.didChangeStatus, object: nil) + nc.addObserver(self, selector: #selector(vpnDidReinstall), name: VPN.didReinstall, object: nil) + + vpn.prepare { + self.reloadVpnStatus() + } + } + + // MARK: Actions + + @IBAction private func activateProfile(_ sender: Any?) { + service.activateProfile(uncheckedProfile) + vpn.disconnect(completionHandler: nil) + } + + @IBAction private func toggleVpnService(_ sender: Any?) { + guard let profile = profile else { + return + } + + let status: VPNStatus + if service.isActiveProfile(profile) { + status = vpn.status ?? .disconnected + } else { + + // force reconnection when activating a different profile + status = .disconnected + } + service.activateProfile(profile) + reloadVpnStatus() + + switch status { + case .disconnected: + guard !service.needsCredentials(for: uncheckedProfile) else { + isPendingConnection = true + perform(segue: StoryboardSegue.Service.accountSegueIdentifier) + return + } + vpn.reconnect(completionHandler: nil) + + default: + vpn.disconnect(completionHandler: nil) + } + } + + @IBAction private func reconnectVPN(_ sender: Any?) { + GracefulVPN(service: service).reconnect(completionHandler: nil) + } + +// @IBAction private func cycleConnection(_ sender: Any?) { +// guard vpn.isEnabled else { +// return +// } +//// guard vpn.status == .disconnected else { +//// let alert = Macros.alert( +//// L10n.Core.Service.Cells.ConnectionStatus.caption, +//// L10n.Core.Service.Alerts.ReconnectVpn.message +//// ) +//// alert.addDefaultAction(L10n.Core.Global.ok) { +//// self.vpn.reconnect(configuration: self.currentVpnConfiguration(), completionHandler: nil) +//// } +//// alert.addCancelAction(L10n.Core.Global.cancel) +//// present(alert, animated: true, completion: nil) +//// return +//// } +// vpn.reconnect(completionHandler: nil) +// } + + @IBAction private func customizeProfile(_ sender: Any?) { + perform(segue: StoryboardSegue.Service.customizeSegueIdentifier) + } + + override func prepare(for segue: NSStoryboardSegue, sender: Any?) { + if let accountVC = segue.destinationController as? AccountViewController { + accountVC.profile = profile + accountVC.delegate = self + } else if let customVC = segue.destinationController as? ProfileCustomizationContainerViewController { + customVC.profile = profile + } + } + + // MARK: Notifications + + @objc private func vpnDidUpdate() { + reloadVpnStatus() + + guard let status = vpn.status else { + return + } + log.debug("VPN.status: \(status)") + switch status { + case .connected: + Reviewer.shared.reportEvent() + + default: + break + } + } + + @objc private func vpnDidReinstall() { + viewProvider.reloadData() + viewHost.reloadData() + } + + // MARK: Helpers + + private func reloadVpnStatus() { + labelConnectedLocation.stringValue = "" + guard let profile = profile else { + return + } + let isActive = service.isActiveProfile(profile) + guard isActive && vpn.isEnabled else { + labelStatus.applyVPN(Theme.current, isActive: isActive, with: nil, error: nil) + activityVPN.stopAnimation(nil) + buttonToggle.title = L10n.App.Service.Cells.Vpn.TurnOn.caption + buttonToggle.isEnabled = true + buttonReconnect.isEnabled = false + return + } + + labelStatus.applyVPN(Theme.current, isActive: isActive, with: vpn.status, error: service.vpnLastError) + buttonToggle.title = vpn.isEnabled ? L10n.App.Service.Cells.Vpn.TurnOff.caption : L10n.App.Service.Cells.Vpn.TurnOn.caption + buttonReconnect.isEnabled = true + + // append connected location for providers + if vpn.status == .connected, let providerProfile = profile as? ProviderConnectionProfile { + labelConnectedLocation.stringValue = "(\(providerProfile.pool?.localizedCountry ?? ""))" + } + + switch vpn.status ?? .disconnected { + case .connected: + activityVPN.stopAnimation(nil) + + case .disconnected: + activityVPN.stopAnimation(nil) + + case .connecting: + activityVPN.startAnimation(nil) + + case .disconnecting: + activityVPN.startAnimation(nil) + } + } +} + +extension ServiceViewController: AccountViewControllerDelegate { + func accountController(_ accountController: AccountViewController, shouldUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) -> Bool { + guard profile.requiresCredentials else { + return true + } + return credentials.isValid + } + + func accountController(_ accountController: AccountViewController, didUpdateCredentials credentials: Credentials, forProfile profile: ConnectionProfile) { + if isPendingConnection { + isPendingConnection = false + vpn.reconnect(completionHandler: nil) + } + StatusMenu.shared.refreshWithCurrentProfile() + } + + func accountControllerDidCancel(_ accountController: AccountViewController) { + isPendingConnection = false + } +} + +extension ServiceViewController: ProviderServiceViewDelegate { + func providerView(_ providerView: ProviderServiceView, didSelectPool pool: Pool) { + + // fall back to a supported preset + let supportedPresets = pool.supportedPresetIds(in: uncheckedProviderProfile.infrastructure) + if let presetId = uncheckedProviderProfile.preset?.id, !supportedPresets.contains(presetId), + let fallback = supportedPresets.first { + + uncheckedProviderProfile.presetId = fallback + } + + service.setPoolId(pool.id, forProviderProfile: uncheckedProviderProfile) +// vpn.reinstallIfEnabled() + } + + func providerViewDidRequestInfrastructureRefresh(_ providerView: ProviderServiceView) { + let name = uncheckedProviderProfile.name + + viewProvider.isRefreshingInfrastructure = true + let isUpdating = InfrastructureFactory.shared.update(name, notBeforeInterval: AppConstants.Services.minimumUpdateInterval) { (response, error) in + self.viewProvider.isRefreshingInfrastructure = false + guard let _ = response else { + return + } + self.viewProvider.reloadData() + } + if !isUpdating { + viewProvider.isRefreshingInfrastructure = false + } + } +} + +extension ServiceViewController: HostServiceViewDelegate { +} + +private extension ServiceViewController { + private var uncheckedProfile: ConnectionProfile { + guard let profile = profile else { + fatalError("Expected non-nil profile here") + } + return profile + } + + private var uncheckedProviderProfile: ProviderConnectionProfile { + guard let profile = profile as? ProviderConnectionProfile else { + fatalError("Expected ProviderConnectionProfile (found: \(type(of: self.profile)))") + } + return profile + } + + private var uncheckedHostProfile: HostConnectionProfile { + guard let profile = profile as? HostConnectionProfile else { + fatalError("Expected HostConnectionProfile (found: \(type(of: self.profile)))") + } + return profile + } +} diff --git a/Passepartout/App/macOS/Tables/TextTableView.swift b/Passepartout/App/macOS/Tables/TextTableView.swift new file mode 100644 index 00000000..98eab5f8 --- /dev/null +++ b/Passepartout/App/macOS/Tables/TextTableView.swift @@ -0,0 +1,150 @@ +// +// TextTableView.swift +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/20/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Cocoa + +class TextTableView: NSView { + @IBOutlet private weak var labelTitle: NSTextField! + + @IBOutlet private weak var tableView: NSTableView! + + @IBOutlet private weak var buttonAdd: NSButton! + + @IBOutlet private weak var buttonRemove: NSButton! + + var title = "" + + var rows: [String] = [] + + var selectedRow: Int? { + didSet { + guard let _ = selectedRow else { + tableView.deselectColumn(0) + return + } + } + } + + var selectionBlock: ((String) -> Void)? + + var deselectionBlock: (() -> Void)? + + var updateBlock: (() -> Void)? + + var rowTemplate = "" + + var isEnabled: Bool = true { + didSet { + isAddEnabled = isEnabled + isRemoveEnabled = isEnabled + } + } + + var isAddEnabled: Bool { + get { + return buttonAdd.isEnabled + } + set { + buttonAdd.isEnabled = newValue + } + } + + var isRemoveEnabled: Bool { + get { + return buttonRemove.isEnabled + } + set { + buttonRemove.isEnabled = newValue + } + } + + override func viewWillMove(toSuperview newSuperview: NSView?) { + super.viewWillMove(toSuperview: newSuperview) + + labelTitle.stringValue = title + buttonAdd.image = NSImage(named: NSImage.addTemplateName) + buttonRemove.image = NSImage(named: NSImage.removeTemplateName) + + if let i = selectedRow { + tableView.reloadData() + tableView.selectRowIndexes(IndexSet(integer: i), byExtendingSelection: true) + } + } + + // MARK: Actions + + func reloadData() { + tableView.reloadData() + } + + @IBAction private func addElement(_ sender: Any?) { + rows.append(rowTemplate) + tableView.reloadData() + tableView.editColumn(0, row: rows.count - 1, with: nil, select: true) + updateBlock?() + } + + @IBAction private func removeElement(_ sender: Any?) { + let index = tableView.selectedRow + guard index != -1 else { + return + } + rows.remove(at: index) + tableView.reloadData() + updateBlock?() + } +} + +extension TextTableView: NSTableViewDataSource, NSTableViewDelegate { + func numberOfRows(in tableView: NSTableView) -> Int { + return rows.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + return rows[row] + } + + func tableView(_ tableView: NSTableView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, row: Int) { + defer { + tableView.reloadData() + } + guard let string = object as? String, !string.isEmpty else { + rows.remove(at: row) + return + } + rows[row] = string + } + + func tableViewSelectionDidChange(_ notification: Notification) { + let index = tableView.selectedRow + guard index != -1 else { + isRemoveEnabled = false + deselectionBlock?() + return + } + isRemoveEnabled = true + selectionBlock?(rows[index]) + } +} diff --git a/Passepartout/App/macOS/Tables/TextTableView.xib b/Passepartout/App/macOS/Tables/TextTableView.xib new file mode 100644 index 00000000..4545e3aa --- /dev/null +++ b/Passepartout/App/macOS/Tables/TextTableView.xib @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Passepartout/App/macOS/en.lproj/App.strings b/Passepartout/App/macOS/en.lproj/App.strings new file mode 100644 index 00000000..1de504d2 --- /dev/null +++ b/Passepartout/App/macOS/en.lproj/App.strings @@ -0,0 +1,72 @@ +// +// App.strings +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/21/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.values.default" = "Default"; + +"vpn.unused" = "Off"; + +"organizer.title" = "%@"; +"organizer.menus.provider" = "Provider"; +"organizer.menus.provider.unavailable" = "No providers left"; +"organizer.menus.host" = "Host"; +"organizer.alerts.remove_profile.title" = "Remove profile"; +"organizer.alerts.remove_profile.message" = "Are you sure you want to delete profile %@?"; +"organizer.alerts.open_host_file.title" = "Select an .ovpn file"; + +"service.cells.vpn.turn_on.caption" = "Enable VPN"; +"service.cells.vpn.turn_off.caption" = "Disable VPN"; +"service.cells.category.caption" = "Category"; +"service.cells.addresses.caption" = "Addresses"; + +"endpoint.cells.address" = "Address"; +"endpoint.cells.protocol" = "Protocol"; + +"configuration.title" = "Configuration"; +"configuration.alerts.commit.message" = "New parameters will not be effective until you reconnect manually. Changes in trusted networks will apply immediately."; +"configuration.alerts.commit.buttons.reconnect" = "Reconnect now"; +"configuration.alerts.commit.buttons.skip" = "Skip"; + +"network_settings.dns.cells.domains.title" = "Domains"; +"network_settings.dns.cells.addresses.title" = "Servers"; +"network_settings.proxy.cells.bypass_domains.title" = "Bypass domains"; + +"preferences.title" = "%@ Preferences"; +"preferences.sections.general.header" = "General"; +"preferences.cells.launches_on_login.caption" = "Launch on login"; +"preferences.cells.launches_on_login.footer" = "Check to automatically launch the app on boot or login."; + +"trusted.columns.trust.title" = "Trust"; +"trusted.ethernet.title" = "Trust wired connections"; +"trusted.ethernet.description" = "Check to trust any wired cable connection."; + +"menu.switch_profile.title" = "Active profile"; +"menu.active_profile.title.none" = "No active profile"; +"menu.active_profile.items.customize.title" = "Customize..."; +"menu.active_profile.messages.missing_credentials" = "No account configured"; +"menu.organizer.title" = "Organizer"; +"menu.preferences.title" = "Preferences"; +"menu.support.title" = "Support"; +"menu.quit.title" = "Quit %@"; +"menu.quit.messages.confirm" = "The VPN, if enabled, will still run in the background. Do you want to quit?"; diff --git a/Passepartout/App/macOS/it.lproj/App.strings b/Passepartout/App/macOS/it.lproj/App.strings new file mode 100644 index 00000000..4a087c22 --- /dev/null +++ b/Passepartout/App/macOS/it.lproj/App.strings @@ -0,0 +1,53 @@ +// +// App.strings +// Passepartout-macOS +// +// Created by Davide De Rosa on 6/21/19. +// Copyright (c) 2019 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.values.default" = "Default"; + +"vpn.unused" = "Spento"; + +"organizer.menus.provider" = "Provider"; +"organizer.menus.provider.unavailable" = "Nessun altro provider disponibile"; +"organizer.menus.host" = "Host"; +"organizer.alerts.remove_profile.title" = "Cancella profilo"; +"organizer.alerts.remove_profile.message" = "Sei sicuro di voler cancellare il profilo %@?"; +"organizer.alerts.open_host_file.title" = "Seleziona un file .ovpn"; + +"service.cells.vpn.turn_on.caption" = "Abilita VPN"; +"service.cells.vpn.turn_off.caption" = "Disabilita VPN"; +"service.cells.category.caption" = "Categoria"; +"service.cells.addresses.caption" = "Indirizzi"; + +"endpoint.cells.address" = "Indirizzo"; +"endpoint.cells.protocol" = "Protocollo"; + +"configuration.title" = "Configurazione"; + +"network_settings.dns.cells.addresses.title" = "Server"; +"network_settings.proxy.cells.bypass_domains.title" = "Dominii ignorati"; + +"preferences.title" = "Preferenze"; +"preferences.sections.general.header" = "Generale"; + +"trusted.columns.trust.title" = "Sicura"; diff --git a/Passepartout/App/macOS/swiftgen.yml b/Passepartout/App/macOS/swiftgen.yml new file mode 100644 index 00000000..a3d8a603 --- /dev/null +++ b/Passepartout/App/macOS/swiftgen.yml @@ -0,0 +1,29 @@ +strings: + inputs: + - ../../Core/Resources/en.lproj/Core.strings + - en.lproj/App.strings + outputs: + - templateName: structured-swift4 + output: Global/SwiftGen+Strings.swift + +ib: + inputs: + #- Base.lproj/About.storyboard + - Base.lproj/Main.storyboard + - Base.lproj/Preferences.storyboard + - Base.lproj/Service.storyboard + #- Base.lproj/Shortcuts.storyboard + outputs: + - templateName: scenes-swift4 + output: Global/SwiftGen+Scenes.swift + - templateName: segues-swift4 + output: Global/SwiftGen+Segues.swift + +xcassets: + inputs: + - Assets.xcassets + - Flags.xcassets + - Providers.xcassets + outputs: + - templateName: swift4 + output: Global/SwiftGen+Assets.swift diff --git a/Passepartout/Core/Info.plist b/Passepartout/Core/Info.plist new file mode 100644 index 00000000..5dabe51b --- /dev/null +++ b/Passepartout/Core/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + $(CFG_APP_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + $(CFG_COPYRIGHT) + + diff --git a/PassepartoutCore-iOS/PassepartoutCore.h b/Passepartout/Core/PassepartoutCore.h similarity index 100% rename from PassepartoutCore-iOS/PassepartoutCore.h rename to Passepartout/Core/PassepartoutCore.h diff --git a/Passepartout/Core/README.md b/Passepartout/Core/README.md new file mode 100644 index 00000000..49be4156 --- /dev/null +++ b/Passepartout/Core/README.md @@ -0,0 +1,56 @@ +

+ +# [Passepartout][about-website] + +[![TunnelKit 3.1](https://img.shields.io/badge/tunnelkit-3.1-d69c68.svg)][dep-tunnelkit] +[![License GPLv3](https://img.shields.io/badge/license-GPLv3-lightgray.svg)](LICENSE) +[![Travis-CI](https://api.travis-ci.org/passepartoutvpn/passepartout-core-apple.svg?branch=master)](https://travis-ci.org/passepartoutvpn/passepartout-core-apple) + +Passepartout is a non-official, user-friendly [OpenVPN®][openvpn] client. + +## Core + +The repository merely hosts code, resources and translations shared across Passepartout for [iOS][git-ios] and [macOS][git-macos]. + +## License + +This project is licensed under the [GPLv3][license-content]. + +### Contributing + +By contributing to this project you are agreeing to the terms stated in the [Contributor License Agreement (CLA)][contrib-cla]. For more details please see [CONTRIBUTING][contrib-readme]. + +## Credits + +The logo is taken from the awesome Circle Icons set by Nick Roach. + +- lzo - © 1996-2017 Markus F.X.J. Oberhumer +- PIATunnel - © 2018-Present Private Internet Access +- SSZipArchive - © 2010-2012 Sam Soffes +- SwiftGen - © 2018 SwiftGen +- SwiftyBeaver - © 2015 Sebastian Kreutzberger + +This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. ([https://www.openssl.org/][dep-openssl]) + +© 2002-2018 OpenVPN Inc. - OpenVPN is a registered trademark of OpenVPN Inc. + +## Contacts + +Twitter: [@keeshux][about-twitter] + +Website: [passepartoutvpn.app][about-website] + +[openvpn]: https://openvpn.net/index.php/open-source/overview.html + +[git-ios]: https://github.com/passepartoutvpn/passepartout-ios +[git-macos]: https://github.com/passepartoutvpn/passepartout-macos + +[dep-tunnelkit]: https://github.com/passepartoutvpn/tunnelkit +[dep-openssl]: https://www.openssl.org/ + +[license-content]: LICENSE +[contrib-cla]: CLA.rst +[contrib-readme]: CONTRIBUTING.md + +[about-twitter]: https://twitter.com/keeshux +[about-website]: https://passepartoutvpn.app diff --git a/Passepartout/Core/Resources/Base.lproj/Intents.intentdefinition b/Passepartout/Core/Resources/Base.lproj/Intents.intentdefinition new file mode 100644 index 00000000..58ceccf9 --- /dev/null +++ b/Passepartout/Core/Resources/Base.lproj/Intents.intentdefinition @@ -0,0 +1,513 @@ + + + + + INEnums + + INIntentDefinitionModelVersion + 1.1 + INIntentDefinitionNamespace + CM6KGi + INIntentDefinitionSystemVersion + 19D76 + INIntentDefinitionToolsBuildVersion + 11C504 + INIntentDefinitionToolsVersion + 11.3.1 + INIntents + + + INIntentCategory + generic + INIntentDescription + Connects to a host profile + INIntentDescriptionID + eXXb2z + INIntentLastParameterTag + 6 + INIntentName + ConnectVPN + INIntentParameterCombinations + + profileId,profileTitle,context + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Connect to ${profileTitle} + INIntentParameterCombinationTitleID + U6o81V + + + INIntentParameters + + + INIntentParameterDisplayPriority + 1 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + + INIntentParameterName + context + INIntentParameterTag + 5 + INIntentParameterType + String + + + INIntentParameterDisplayPriority + 2 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + + INIntentParameterName + profileId + INIntentParameterTag + 4 + INIntentParameterType + String + + + INIntentParameterDisplayPriority + 3 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + + INIntentParameterName + profileTitle + INIntentParameterTag + 6 + INIntentParameterType + String + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Connect to VPN + INIntentTitleID + LA99yM + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentDescription + Adds current Wi-Fi to trusted networks + INIntentDescriptionID + BKxs8X + INIntentName + TrustCurrentNetwork + INIntentParameterCombinations + + + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Trust current Wi-Fi + INIntentParameterCombinationTitleID + POyDPM + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Trust current Wi-Fi + INIntentTitleID + m2E7SI + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentDescription + Disables the VPN service + INIntentDescriptionID + eQ1yzr + INIntentName + DisableVPN + INIntentParameterCombinations + + + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Disable VPN + INIntentParameterCombinationTitleID + IeGsEq + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Disable VPN + INIntentTitleID + 1ZRTCZ + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentDescription + Removes current Wi-Fi from trusted networks + INIntentDescriptionID + 7eoAss + INIntentName + UntrustCurrentNetwork + INIntentParameterCombinations + + + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Untrust current Wi-Fi + INIntentParameterCombinationTitleID + 0Wu9nb + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Untrust current Wi-Fi + INIntentTitleID + rd1T8p + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentDescription + Adds cellular to trusted networks + INIntentDescriptionID + 9GpJt5 + INIntentName + TrustCellularNetwork + INIntentParameterCombinations + + + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Trust cellular network + INIntentParameterCombinationTitleID + NWWgCl + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Trust cellular network + INIntentTitleID + H4taev + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentDescription + Removes cellular from trusted networks + INIntentDescriptionID + 0jRWn5 + INIntentName + UntrustCellularNetwork + INIntentParameterCombinations + + + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Untrust cellular network + INIntentParameterCombinationTitleID + ggzKA2 + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Untrust cellular network + INIntentTitleID + wB1iYX + INIntentType + Custom + INIntentVerb + Do + + + INIntentCategory + generic + INIntentDescription + Connects to a specific location of a provider profile + INIntentDescriptionID + KjkCfU + INIntentLastParameterTag + 3 + INIntentName + MoveToLocation + INIntentParameterCombinations + + providerId,poolName,poolId + + INIntentParameterCombinationSubtitle + With ${providerId} provider + INIntentParameterCombinationSubtitleID + 66bZBE + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Connect to ${poolName} + INIntentParameterCombinationTitleID + WnTPFg + + + INIntentParameters + + + INIntentParameterDisplayPriority + 1 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + + INIntentParameterName + providerId + INIntentParameterTag + 2 + INIntentParameterType + String + + + INIntentParameterDisplayPriority + 2 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + + INIntentParameterName + poolId + INIntentParameterTag + 3 + INIntentParameterType + String + + + INIntentParameterDisplayPriority + 3 + INIntentParameterMetadata + + INIntentParameterMetadataCapitalization + Sentences + + INIntentParameterName + poolName + INIntentParameterTag + 1 + INIntentParameterType + String + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Connect to provider location + INIntentTitleID + qo3Szz + INIntentType + Custom + INIntentVerb + Go + + + INIntentCategory + generic + INIntentDescription + Enables the VPN service with the profile currently in use + INIntentDescriptionID + xY97Vu + INIntentName + EnableVPN + INIntentParameterCombinations + + + + INIntentParameterCombinationIsPrimary + + INIntentParameterCombinationSubtitle + With profile in use + INIntentParameterCombinationSubtitleID + NCoK9B + INIntentParameterCombinationSupportsBackgroundExecution + + INIntentParameterCombinationTitle + Enable VPN + INIntentParameterCombinationTitleID + yesvFP + + + INIntentResponse + + INIntentResponseCodes + + + INIntentResponseCodeName + success + INIntentResponseCodeSuccess + + + + INIntentResponseCodeName + failure + + + + INIntentTitle + Enable VPN + INIntentTitleID + lQ6ziK + INIntentType + Custom + INIntentVerb + Do + + + INTypes + + + diff --git a/Passepartout/Core/Resources/de.lproj/Core.strings b/Passepartout/Core/Resources/de.lproj/Core.strings new file mode 100644 index 00000000..f5d11a3b --- /dev/null +++ b/Passepartout/Core/Resources/de.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 4/23/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Abbrechen"; +"global.next" = "Weiter"; +"global.close" = "Schließen"; +"global.host.title_input.message" = "Gültige Zeichen beinhalten Buchstaben und Zahlen sowie Bindestrich \"-\", Unterstrich \"_\" und Punkt \".\"."; +"global.host.title_input.placeholder" = "Mein Profil"; +"global.email_not_configured" = "Es wurde kein Email-Account konfiguriert."; +"global.values.enabled" = "Aktiviert"; +"global.values.disabled" = "Deaktiviert"; +"global.values.none" = "Keine"; +"global.values.automatic" = "Automatisch"; +"global.values.manual" = "Manuell"; +"reddit.title" = "Reddit"; +"reddit.message" = "Wusstest du, daß Passepartout einen Subreddit hat? Abonniere ihn für Updates oder um Features, Probleme, neue Plattformen zu diskutieren - oder was auch immer du möchtest.\n\nDies ist auch ein guter Weg zu zeigen dass dir dieses Projekt etwas bedeutet."; +"reddit.buttons.subscribe" = "Jetzt abbonnieren!"; +"reddit.buttons.remind" = "Später erinnern"; +"reddit.buttons.never" = "Nicht erneut fragen"; +"organizer.sections.providers.header" = "Anbieter"; +"organizer.sections.providers.footer" = "Hier findest du einige Anbieter mit voreingestellten Konfigurationsprofilen."; +"organizer.sections.hosts.header" = "Hosts"; +"organizer.sections.hosts.footer" = "Importiere Hosts aus .ovpn Konfigurationsdateien."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Erhalte Hilfe von Siri um deine üblichen Interaktionen mit der App zu beschleunigen."; +"organizer.sections.support.header" = "Support"; +"organizer.sections.feedback.header" = "Feedback"; +"organizer.cells.siri_shortcuts.caption" = "Kurzbefehle verwalten"; +"organizer.cells.join_community.caption" = "Community beitreten"; +"organizer.cells.write_review.caption" = "Rezension schreiben"; +"organizer.cells.donate.caption" = "Spenden"; +"organizer.cells.github_sponsors.caption" = "Unterstütze mich bei GitHub"; +"organizer.cells.translate.caption" = "Übersetzung anbieten"; +"organizer.cells.about.caption" = "Über %@"; +"organizer.cells.uninstall.caption" = "VPN-Konfiguration entfernen"; +"organizer.alerts.exhausted_providers.message" = "Du hast Profile für alle verfügbaren Anbieter erstellt."; +"organizer.alerts.add_host.message" = "Öffne eine URL zu einer .ovpn-Konfigurationsdatei aus Safari, Mail oder anderen App um ein Host-Profil einzurichten.\n\nDu kannst auch eine .ovpn-Datei mit iTunes Dateifreigabe importieren."; +"organizer.alerts.cannot_donate.message" = "Auf diesem Gerät ist keine Bezahlmethode konfiguriert."; +"organizer.alerts.delete_vpn_profile.message" = "Möchtest du wirklich die VPN-Konfiguration aus deinen Geräte-Einstellungen löschen? Dies behebt möglicherweise manche kaputten VPN-Zustände und beeinflusst nicht deine Anbieter und Hosts-Profile."; +"wizards.host.alerts.existing.message" = "Ein Host-Profil mit identischem Titel existiert bereits. Ersetzen?"; +"parsed_file.alerts.malformed.message" = "Die Konfigurations-Datei enthält eine ungültige Option (%@)."; +"parsed_file.alerts.missing.message" = "Die Konfigurations-Datei enthält eine benötigte Option nicht (%@)."; +"parsed_file.alerts.unsupported.message" = "Die Konfigurations-Datei enthält eine nicht unterstützte Option (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Die Konfigurations-Datei ist korrekt, enthält aber möglicherweise eine nicht unterstützte Option (%@).\n\nDie Verbindung kann, abhängig von den Server-Einstellungen, unterbrochen werden."; +"parsed_file.alerts.encryption_passphrase.message" = "Bitte die Verschlüsselungs-Passphrase eingeben."; +"parsed_file.alerts.decryption.message" = "Die Konfiguration enthält einen verschlüsselten Private Key und konnte nicht entschlüsselt werden. Bitte überprüfe ob du die Passphrase eingegeben hast."; +"parsed_file.alerts.parsing.message" = "Fehler beim Verarbeiten der Konfigurationsdatei (%@)."; +"parsed_file.alerts.buttons.report" = "Ein Problem melden"; +"service.sections.vpn.footer" = "Die Verbindung wird immer aufgebaut wenn notwendig."; +"service.sections.provider_infrastructure.footer" = "Zuletzt aktualisiert am %@."; +"service.sections.vpn_survives_sleep.footer" = "Deaktivieren um die Batterielaufzeit zu verbessern, allerdings verzögert sich der Verbindungsaufbau beim Aufwachen."; +"service.sections.vpn_resolves_hostname.footer" = "Bevorzugt in den meisten Netzwerken und benötigt in manchen IPv6 Netzwerken. Deaktivieren wo DNS geblockt ist oder um die Aushandlung zu beschleunigen bei langsam antwortenden DNS."; +"service.sections.trusted.header" = "Vertrauenswürdige Netzwerke"; +"service.sections.trusted.footer" = "Wenn ein vertrauenswürdiges Netzwerk verbunden wird, wird normalerweise die VPN-Verbindung beendet und bleibt deaktiviert. Deaktiviere diese Option um dieses Verhalten zu unterbinden."; +"service.sections.diagnostics.header" = "Diagnose"; +"service.sections.diagnostics.footer" = "Zensier-Status wird aktiv nach erneutem Verbinden. Netzwerk-Daten sind Hostnamen, IP-Adressen, Routingtabellen, SSID. Zugangsdaten und Private Keys werden nie gelogged."; +"service.cells.connection_status.caption" = "Status"; +"account.title" = "Account"; +"endpoint.title" = "Endpoint"; +"service.cells.provider.pool.caption" = "Ort"; +"service.cells.provider.preset.caption" = "Voreinstellung"; +"network_settings.title" = "Netzwerk-Einstellungen"; +"service.cells.vpn_survives_sleep.caption" = "Verbindung aktiv halten trotz Schlafmodus"; +"service.cells.vpn_resolves_hostname.caption" = "Server Hostname auflösen"; +"service.cells.trusted_mobile.caption" = "Mobilfunknetz"; +"service.cells.trusted_policy.caption" = "Vertrauen deaktiviert VPN"; +"service.cells.test_connectivity.caption" = "Verbindung testen"; +"service.cells.data_count.caption" = "Ausgetauschte Datenmenge"; +"service.cells.data_count.none" = "Nicht verfügbar"; +"service.cells.debug_log.caption" = "Debug log"; +"service.cells.masks_private_data.caption" = "Netzwerkdaten zensieren"; +"service.cells.reconnect.caption" = "Erneut verbinden"; +"service.cells.report_issue.caption" = "Verbindungsproblem melden"; +"service.alerts.rename.title" = "Profil umbenennen"; +"service.alerts.credentials_needed.message" = "Du musst zuerst die Account-Zugangsdaten eingeben."; +"service.alerts.reconnect_vpn.message" = "Möchtest du erneut zum VPN verbinden?"; +"service.alerts.trusted.no_network.message" = "Du bist mit keinem WLAN verbunden."; +"service.alerts.trusted.will_disconnect_trusted.message" = "In dem du diesem Netzwerk vertraust, wird das VPN getrennt. Weiter?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Durch das Ändern der Vertrauens-Policy könnte das VPN deaktiviert werden. Weiter?"; +"service.alerts.test_connectivity.title" = "Konnektivität"; +"service.alerts.test_connectivity.messages.success" = "Dein Gerät ist mit dem Internet verbunden!"; +"service.alerts.test_connectivity.messages.failure" = "Dein Gerät hat keine Verbindung mit dem Internet, bitte prüfe deine Profil-Parameter."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Um das aktuelle Debug-Log sicher zurückzusetzen und die neuen Zensier-Paramenter anzuwenden, musst du das VPN jetzt erneut verbinden."; +"service.alerts.buttons.reconnect" = "Erneut verbinden"; +"service.alerts.download.title" = "Download benötigt"; +"service.alerts.download.message" = "%@ benötigt den Download von zusätzlichen Konfigurationsdateien.\n\nBestätige um mit dem Download zu beginnen."; +"service.alerts.download.failed" = "Herunterladen der Konfigurationsdateien fehlgeschlagen. %@"; +"service.alerts.download.hud.extracting" = "Extrahiere Dateien, bitte warten..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Benutze deine %@ Web-Zugangsdaten."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Benutze deine %@ Web-Zugangsdaten. Dein Benutzername ist üblicherweise numerischt (ohne Zwischenraum)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Benutze deine %@ Web-Zugangsdaten. Dein Benutzername ist üblicherweise deine Email."; +"account.sections.guidance.footer.infrastructure.pia" = "Benutze deine %@ Web-Zugangsdaten. Dein Benutzername ist üblicherweise numerischt mit einem \"p\" Präfix."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Deine Zugangsdaten für %@ findest du unter \"Account > OpenVPN / IKEv2 Username\" auf der Webseite."; +"account.sections.guidance.footer.infrastructure.torguard" = "Verwenden Sie Ihre %@ service-Anmeldeinformationen, die von den Website-Anmeldeinformationen abweichen können."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Benutze deine %@ Web-Zugangsdaten. Dein Benutzername ist üblicherweise deine Email."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Benutze deine %@ Web-Zugangsdaten. Dein Benutzername ist üblicherweise deine Email."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Deine Zugangsdaten für %@ findest du im OpenVPN Config Generator auf der Webseite."; +"account.sections.registration.footer" = "Beantrage einen Account auf der %@ Webseite."; +"account.cells.username.caption" = "Benutzername"; +"account.cells.username.placeholder" = "Benutzername"; +"account.cells.password.caption" = "Passwort"; +"account.cells.password.placeholder" = "Geheim"; +"account.cells.open_guide.caption" = "Siehe deine Zugangsdaten"; +"account.cells.signup.caption" = "Registrieren bei %@"; +"endpoint.cells.any_address.caption" = "Automatisch"; +"endpoint.cells.any_protocol.caption" = "Automatisch"; +"configuration.sections.communication.header" = "Kommunikation"; +"configuration.sections.reset.footer" = "Wenn du nach einer Änderung der Kommunikations-Parameter dich nicht mehr verbinden kannst, hier tippen um zur originalen Konfiguration zurückzukehren."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Komprimierung"; +"configuration.sections.network.header" = "Netzwerk"; +"configuration.sections.other.header" = "Andere"; +"configuration.cells.cipher.caption" = "Chiffre"; +"configuration.cells.digest.caption" = "Authentifizierung"; +"configuration.cells.digest.value.embedded" = "Eingebettet"; +"configuration.cells.reset_original.caption" = "Konfiguration zurücksetzen"; +"configuration.cells.client.caption" = "Client Zertifikat"; +"configuration.cells.client.value.enabled" = "Geprüft"; +"configuration.cells.client.value.disabled" = "Nicht geprüft"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Authentifizierung"; +"configuration.cells.tls_wrapping.value.crypt" = "Verschlüsselung"; +"configuration.cells.eku.caption" = "Erweiterte Verifizierung"; +"network_settings.gateway.title" = "Standard-Gateway"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domäne"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algorithmus"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Nicht unterstützt"; +"configuration.cells.keep_alive.caption" = "Keep-alive"; +"configuration.cells.keep_alive.value.seconds" = "%d Sekunden"; +"configuration.cells.renegotiation_seconds.caption" = "erneute Aushandlung"; +"configuration.cells.renegotiation_seconds.value.after" = "nach %@"; +"configuration.cells.random_endpoint.caption" = "Endpunkt zufällig wählen"; +"network_choice.client" = ".ovpn-Datei einlesen"; +"network_choice.server" = "Vom Server holen"; +"global.captions.address" = "Adresse"; +"global.captions.port" = "Port"; +"debug_log.buttons.previous" = "Zurück"; +"debug_log.buttons.next" = "Weiter"; +"debug_log.alerts.empty_log.message" = "Das Debug-Log ist leer."; +"vpn.connecting" = "Verbinde"; +"vpn.active" = "Aktiv"; +"vpn.disconnecting" = "Trenne"; +"vpn.inactive" = "Inaktiv"; +"vpn.disabled" = "Deaktiviert"; +"vpn.errors.timeout" = "Timeout"; +"vpn.errors.dns" = "DNS fehlgeschlagen"; +"vpn.errors.auth" = "Authentifizierung fehlgeschlagen"; +"vpn.errors.tls" = "TLS fehlgeschlagen"; +"vpn.errors.encryption" = "Verschlüsselung fehlgeschlagen"; +"vpn.errors.compression" = "Komprimierung nicht unterstützt"; +"vpn.errors.network" = "Netzwerk geändert"; +"vpn.errors.routing" = "Kein Routing"; +"vpn.errors.gateway" = "Kein Gateway"; +"vpn.errors.shutdown" = "Server heruntergefahren"; +"issue_reporter.title" = "Problem melden"; +"issue_reporter.message" = "Das Debug-Log deiner letzten Verbindung ist notwendig um dein Verbindungs-Problem zu untersuchen und ist vollständig anonymisiert.\n\nDie .ovpn-Konfigurations-Datei, sofern vorhanden, wird anonymisiert von jeglichen sensiblen Daten, angehangen.\n\nBitte prüfe im Zweifelsfall die Email-Anhänge."; +"issue_reporter.buttons.accept" = "Ich verstehe"; +"translations.title" = "Übersetzungen"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "WLAN"; +"shortcuts.add.sections.cellular.header" = "Mobilfunknetz"; +"shortcuts.add.cells.connect.caption" = "Verbinde mit"; +"shortcuts.add.cells.enable_vpn.caption" = "Aktiviere VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Deaktiviere VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Vertraue aktivem WLAN"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Misstraue aktivem WLAN"; +"shortcuts.add.cells.trust_cellular.caption" = "Vertraue Mobilfunknetz"; +"shortcuts.add.cells.untrust_cellular.caption" = "Misstraue Mobilfunknetz"; +"shortcuts.add.alerts.no_profiles.message" = "Es gibt kein Profil mit dem eine Verbindung hergestellt werden kann."; +"shortcuts.edit.sections.all.header" = "Existierende Kurzbefehle"; +"about.title" = "Über"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Teilen"; +"about.cells.credits.caption" = "Credits"; +"about.cells.website.caption" = "Homepage"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Haftungsausschluss"; +"about.cells.privacy_policy.caption" = "Datenschutzrichtlinie"; +"about.cells.share_twitter.caption" = "Darüber Twittern!"; +"about.cells.share_generic.caption" = "Freund einladen"; +"donation.title" = "Spenden"; +"donation.sections.one_time.header" = "Einmalig"; +"donation.sections.one_time.footer" = "Wenn du dich erkenntlich zeigen möchtest für meine Arbeit, gibt es hier ein paar Beträge die du direkt spenden kannst.\n\nDu bezahlst pro Spende nur einmal und kannst mehrmals spenden wenn du möchtest."; +"donation.cells.loading.caption" = "Lade Spenden"; +"donation.cells.purchasing.caption" = "Führe Spende durch"; +"donation.alerts.purchase.success.title" = "Danke"; +"donation.alerts.purchase.success.message" = "Das bedeutet mir viel und ich hoffe wirklich dass du die App weiterhin benutzt und unterstützt."; +"donation.alerts.purchase.failure.message" = "Konnte Spende nicht durchführen. %@"; +"share.message" = "Passepartout ist ein Benutzerfreundlicher, Open Source OpenVPN client für iOS und macOS"; +"version.title" = "Version"; +"version.labels.intro" = "Passepartout und TunnelKit sind geschrieben und gewartet von by Davide De Rosa (keeshux).\n\nQuellcode für Passepartout und TunnelKit ist öffentlich auf GitHub unter GPLv3 verfügbar, du findest die Links auf der Homepage.\n\nPassepartout ist ein inoffizieller client und auf keine Art und Weise mit OpenVPN Inc. verbunden."; +"credits.title" = "Credits"; +"credits.sections.licenses.header" = "Lizenzen"; +"credits.sections.notices.header" = "Notizen"; +"credits.sections.translations.header" = "Übersetzungen"; +"label.license.error" = "Konnte vollständigen Lizenz-Inhalt nicht herunterladen."; +"organizer.cells.profile.value.current" = "In Benutzung"; +"service.welcome.message" = "Willkommen bei Passepartout!\n\nBenutze den Organizer um ein neues Profil hinzuzufügen."; +"service.cells.server_configuration.caption" = "Serverkonfiguration"; +"service.cells.server_network.caption" = "Servernetzwerk"; +"service.alerts.configuration.disconnected" = "Konfiguration nicht verfügbar, stellen Sie sicher, dass Sie mit dem VPN verbunden sind."; +"server_network.cells.route.caption" = "Route"; +"wizards.provider.cells.update_list.caption" = "Aktualisiere Liste"; +"wizards.provider.alerts.unavailable.message" = "Die Provider-Infrastruktur konnte nicht heruntergeladen werden. Bitte versuchen Sie es später erneut."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Come watch me make Passepartout live on Twitch, join the chat to interact and contribute!"; +"organizer.cells.follow_twitch.caption" = "Passepartout auf Twitch ansehen"; +"service.cells.use_profile.caption" = "Dieses Profil verwenden"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/de.lproj/Intents.strings b/Passepartout/Core/Resources/de.lproj/Intents.strings new file mode 100644 index 00000000..3e07dfa8 --- /dev/null +++ b/Passepartout/Core/Resources/de.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Entfernt Mobilfunknetz von vertrauten Netzwerken"; + +"IeGsEq" = "VPN deaktivieren"; +"1ZRTCZ" = "VPN deaktivieren"; + +"66bZBE" = "Mit Anbieter ${providerId}"; + +"7eoAss" = "Entferne aktuelles WLAN von vertrauten Netzwerken"; + +"9GpJt5" = "Fügt Mobilnetz zu vertrauten Netzwerken hinzu"; + +"BKxs8X" = "Fügt aktuelles WLAN zu vertrauten Netzwerken hinzu"; + +"NWWgCl" = "Mobilfunknetz vertrauen"; +"H4taev" = "Mobilfunknetz vertrauen"; + +"KjkCfU" = "Connects to a specific location of a provider profile"; + +"LA99yM" = "Verbinde mit VPN"; + +"U6o81V" = "Verbinde mit ${profileTitle}"; + +"WnTPFg" = "Verbinde mit ${poolName}"; + +"eQ1yzr" = "Deaktiviert den VPN-Dienst"; + +"eXXb2z" = "Verbindet mit einem Hostprofil"; + +"yesvFP" = "Aktiviere VPN"; +"lQ6ziK" = "Aktiviere VPN"; + +"POyDPM" = "Vertraue aktuellem WLAN"; +"m2E7SI" = "Vertraue aktuellem WLAN"; + +"qo3Szz" = "Verbinde mit Anbieter-Ort"; + +"0Wu9nb" = "Aktuellem WLAN nicht vertrauen"; +"rd1T8p" = "Aktuellem WLAN nicht vertrauen"; + +"ggzKA2" = "Mobilfunknetz nicht vertrauen"; +"wB1iYX" = "Mobilfunknetz nicht vertrauen"; + +"xY97Vu" = "Aktiviert den VPN-Dienst mit dem derzeitig benutzten Profil"; + +"NCoK9B" = "Mit dem benutzten Profil"; diff --git a/Passepartout/Core/Resources/el.lproj/Core.strings b/Passepartout/Core/Resources/el.lproj/Core.strings new file mode 100644 index 00000000..637c20fb --- /dev/null +++ b/Passepartout/Core/Resources/el.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Ακύρωση"; +"global.next" = "Επόμενο"; +"global.close" = "Κλείσιμο"; +"global.host.title_input.message" = "Αποδεκτοί χαρακτήρες είναι οι αλφαριθμητικοί συν τη παύλα \"-\", κάτω παύλα \"_\" και τελεία \".\"."; +"global.host.title_input.placeholder" = "Το προφίλ μου"; +"global.email_not_configured" = "Δεν έχει ρυθμιστεί λογαριασμός ηλεκτρονικού ταχυδρομείου."; +"global.values.enabled" = "Ενεργοποιήθηκε"; +"global.values.disabled" = "Απενεργοποιήθηκε"; +"global.values.none" = "Κανένα"; +"global.values.automatic" = "Αυτόματο"; +"global.values.manual" = "Χειροκίνητο"; +"reddit.title" = "Reddit"; +"reddit.message" = "Γνωρίζατε ότι το Passepartout έχει subreddit? Εγγραφείτε για ενημερώσεις ή για να συζητήσετε προβλήματα της εφαρμογές, νέες δυνατότητες και άλλα.\n\nΕίναι επίσης ένας ωραίος τρόπος να δείξετε ότι ενδιαφέρεστε για τη προσπάθεια αυτή."; +"reddit.buttons.subscribe" = "Εγγραφή τώρα!"; +"reddit.buttons.remind" = "Υπενθύμιση Αργότερα"; +"reddit.buttons.never" = "Μη με ρωτήσεις ξανά"; +"organizer.sections.providers.header" = "Πάροχοι"; +"organizer.sections.providers.footer" = "Εδώ θα βρείτε ορισμένους παρόχους με προκαθορισμένες ρυθμίσεις προφίλ."; +"organizer.sections.hosts.header" = "Φιλοξενητές"; +"organizer.sections.hosts.footer" = "Εισάγετε φιλοξενητές από ένα raw .ovpn αρχείο."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Get help from Siri to speed up your most common interactions with the app."; +"organizer.sections.support.header" = "Υποστήριξη"; +"organizer.sections.feedback.header" = "Ανατροφοδότηση"; +"organizer.cells.siri_shortcuts.caption" = "Διαχείριση Συντομεύσεων"; +"organizer.cells.join_community.caption" = "Συμμετοχή στην κοινότητα"; +"organizer.cells.write_review.caption" = "Γράψτε μια κριτική"; +"organizer.cells.donate.caption" = "Κάντε μια δωρεά"; +"organizer.cells.github_sponsors.caption" = "Υποστηρίξτε με στο GitHub"; +"organizer.cells.translate.caption" = "Βοηθήστε στη μετάφραση"; +"organizer.cells.about.caption" = "Σχετικά με %@"; +"organizer.cells.uninstall.caption" = "Αφαίρεση ρύθμισης VPN"; +"organizer.alerts.exhausted_providers.message" = "Έχετε δημιουργήσει προφίλ για οποιονδήποτε διαθέσιμο πάροχο."; +"organizer.alerts.add_host.message" = "Εισάγετε μια διεύθυνση από ένα αρχείο .ovpn στο Safari, το Mail ή άλλη εφαρμογή για να ρυθμίσετε ένα προφίλ διακομιστή.\n\nΜπορείτε επίσης να εισάγετε ένα .ovpn αρχείο από το iTunes File Sharing."; +"organizer.alerts.cannot_donate.message" = "Δεν έχει ρυθμιστεί καμία μέθοδος πληρωμής σε αυτήν τη συσκευή."; +"organizer.alerts.delete_vpn_profile.message" = "Θέλετε πραγματικά να διαγράψετε τη διαμόρφωση VPN από τις ρυθμίσεις της συσκευής σας; Αυτό μπορεί να διορθώσει κάποιες καταστραμμένες καταστάσεις VPN και δεν θα επηρεάσει τα προφίλ του παροχέα και του διακομιστή σας."; +"wizards.host.alerts.existing.message" = "Ένα προφίλ διακομιστή με τον ίδιο τίτλο υπάρχει ήδη. Αντικατέστησέ το;"; +"parsed_file.alerts.malformed.message" = "Το αρχείο ρυθμίσεων περιέχει μια ακατάλληλη επιλογή (%@)."; +"parsed_file.alerts.missing.message" = "Το αρχείο διαμόρφωσης δεν διαθέτει την απαιτούμενη επιλογή (%@)."; +"parsed_file.alerts.unsupported.message" = "Το αρχείο διαμόρφωσης περιέχει μια επιλογή που δεν υποστηρίζεται (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Το αρχείο ρυθμίσεων είναι σωστό, αλλά περιέχει μια δυνητικά μη υποστηριζόμενη επιλογή (%@).\n\nΗ δυνατότητα σύνδεσης μπορεί να διακοπεί ανάλογα με τις ρυθμίσεις του διακομιστή."; +"parsed_file.alerts.encryption_passphrase.message" = "Εισαγάγετε το κωδικό κρυπτογράφησης."; +"parsed_file.alerts.decryption.message" = "Η διαμόρφωση περιέχει κρυπτογραφημένο ιδιωτικό κλειδί και δεν ήταν δυνατό να αποκρυπτογραφηθεί. Δείτε πάλι το κωδικό που καταχωρίσατε."; +"parsed_file.alerts.parsing.message" = "Δεν είναι δυνατή η ανάλυση του παρεχόμενου αρχείου ρύθμισης παραμέτρων (%@)."; +"parsed_file.alerts.buttons.report" = "Αναφέρετε ένα πρόβλημα"; +"service.sections.vpn.footer" = "Η σύνδεση θα πραγματοποιηθεί όποτε είναι απαραίτητο."; +"service.sections.provider_infrastructure.footer" = "Τελευταία ενημέρωση στις %@."; +"service.sections.vpn_survives_sleep.footer" = "Απενεργοποιήστε για να βελτιώσετε τη χρήση της μπαταρίας, εις βάρος των περιστασιακών επιβραδύνσεων που οφείλονται σε επανασύνδεση αφύπνισης."; +"service.sections.vpn_resolves_hostname.footer" = "Προτιμάται στα περισσότερα δίκτυα και απαιτείται σε ορισμένα δίκτυα IPv6. Απενεργοποιήστε το εκεί που μπλοκάρεται το DNS ή για να επιταχύνετε τη επικοινωνία όταν το DNS είναι αργό για να ανταποκριθεί."; +"service.sections.trusted.header" = "Αξιόπιστα δίκτυα"; +"service.sections.trusted.footer" = "Κατά την είσοδο σε ένα αξιόπιστο δίκτυο, το VPN απενεργοποιείται κανονικά και διατηρείται αποσυνδεδεμένο. Απενεργοποιήστε αυτήν την επιλογή για να μην έχετε μια τέτοια συμπεριφορά."; +"service.sections.diagnostics.header" = "Διαγνωστικά"; +"service.sections.diagnostics.footer" = "Η κατάσταση κάλυψης θα είναι αποτελεσματική μετά την επανασύνδεση. Τα δεδομένα δικτύου είναι του διακομιστή, διευθύνσεις IP, δρομολόγηση και SSID. Τα διαπιστευτήρια και τα ιδιωτικά κλειδιά δεν καταγράφονται ανεξάρτητα."; +"service.cells.connection_status.caption" = "Κατάσταση"; +"account.title" = "Λογαριασμός"; +"endpoint.title" = "Τελικό σημείο"; +"service.cells.provider.pool.caption" = "Τοποθεσία"; +"service.cells.provider.preset.caption" = "Προεπιλογή"; +"network_settings.title" = "Ρυθμίσεις Δικτύου"; +"service.cells.vpn_survives_sleep.caption" = "Κρατήστε ζωντανό στον ύπνο"; +"service.cells.vpn_resolves_hostname.caption" = "Επίλυση του ονόματος σέρβερ διακομιστή"; +"service.cells.trusted_mobile.caption" = "Δίκτυο Κινητής"; +"service.cells.trusted_policy.caption" = "Τα αξιόπιστα δίκτυα απενεργοποιούν το VPN"; +"service.cells.test_connectivity.caption" = "Δοκιμή συνδεσιμότητας"; +"service.cells.data_count.caption" = "Ανταλλαγή δεδομένων"; +"service.cells.data_count.none" = "Μη διαθέσιμο"; +"service.cells.debug_log.caption" = "Μητρώο εντοπισμού σφαλμάτων"; +"service.cells.masks_private_data.caption" = "Μάσκα δεδομένα δικτύου"; +"service.cells.reconnect.caption" = "Επανασύνδεση"; +"service.cells.report_issue.caption" = "Αναφορά ζητήματος συνδεσιμότητας"; +"service.alerts.rename.title" = "Μετονομασία προφίλ"; +"service.alerts.credentials_needed.message" = "Πρέπει πρώτα να εισαγάγετε διαπιστευτήρια λογαριασμού."; +"service.alerts.reconnect_vpn.message" = "Θέλετε να συνδεθείτε ξανά με το VPN;"; +"service.alerts.trusted.no_network.message" = "Δεν είστε συνδεδεμένοι σε κανένα δίκτυο Wi-Fi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Με εμπιστοσύνη σε αυτό το δίκτυο, το VPN μπορεί να αποσυνδεθεί. Να συνεχίσω;"; +"service.alerts.trusted.will_disconnect_policy.message" = "Αλλάζοντας την πολιτική εμπιστοσύνης, το VPN μπορεί να αποσυνδεθεί. Να συνεχίσω;"; +"service.alerts.test_connectivity.title" = "Συνδεσιμότητα"; +"service.alerts.test_connectivity.messages.success" = "Η συσκευή σας είναι συνδεδεμένη στο Διαδίκτυο!"; +"service.alerts.test_connectivity.messages.failure" = "Η συσκευή σας δεν διαθέτει σύνδεση στο Internet, παρακαλούμε να ελέγξετε τις παραμέτρους του προφίλ σας."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Για να επαναφέρετε με ασφάλεια την τρέχουσα καταγραφή εντοπισμού σφαλμάτων και να εφαρμόσετε τη νέα προτίμηση κάλυψης, πρέπει να συνδεθείτε ξανά με το VPN."; +"service.alerts.buttons.reconnect" = "Επανασύνδεση"; +"service.alerts.download.title" = "Απαιτείται λήψη"; +"service.alerts.download.message" = "%@ απαιτεί τη λήψη πρόσθετων αρχείων ρυθμίσεων.\n\nΕπιβεβαιώστε για να ξεκινήσετε τη λήψη."; +"service.alerts.download.failed" = "Αποτυχία λήψης αρχείων ρυθμίσεων. %@"; +"service.alerts.download.hud.extracting" = "Εξάγοντας τα αρχεία, παρακαλώ να είστε υπομονετικοί..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Χρησιμοποιήστε τα διαπιστευτήρια ιστοτόπου %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Χρησιμοποιήστε τα διαπιστευτήρια ιστοτόπου %@. Το όνομα χρήστη είναι συνήθως αριθμητικό (χωρίς διαστήματα)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Χρησιμοποιήστε τα διαπιστευτήρια ιστοτόπου %@. Το όνομα χρήστη είναι συνήθως το ηλεκτρονικό σας ταχυδρομείο."; +"account.sections.guidance.footer.infrastructure.pia" = "Χρησιμοποιήστε τα διαπιστευτήρια ιστοτόπου %@. Το όνομα χρήστη είναι συνήθως αριθμητικό με πρόθεμα \"p\"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Βρείτε τα διαπιστευτήριά σας %@ στην ενότητα \"Λογαριασμός> OpenVPN / IKEv2 Username \" της ιστοσελίδας."; +"account.sections.guidance.footer.infrastructure.torguard" = "Χρησιμοποιήστε τα διαπιστευτήρια της υπηρεσίας %@, τα οποία ενδέχεται να διαφέρουν από τα διαπιστευτήρια του ιστότοπου."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Χρησιμοποιήστε τα διαπιστευτήρια ιστοτόπου %@. Το όνομα χρήστη είναι συνήθως το ηλεκτρονικό σας ταχυδρομείο."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Χρησιμοποιήστε τα διαπιστευτήρια ιστοτόπου %@. Το όνομα χρήστη είναι συνήθως το ηλεκτρονικό σας ταχυδρομείο."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Βρείτε τα διαπιστευτήριά σας %@ στο OpenVPN Config Generator στον ιστότοπο."; +"account.sections.registration.footer" = "Πηγαίνετε να αποκτήσετε λογαριασμό στον ιστότοπο %@."; +"account.cells.username.caption" = "Όνομα χρήστη"; +"account.cells.username.placeholder" = "χρήστης"; +"account.cells.password.caption" = "Κωδικός"; +"account.cells.password.placeholder" = "κωδικός"; +"account.cells.open_guide.caption" = "Δείτε τα διαπιστευτήρια σας"; +"account.cells.signup.caption" = "Εγγραφείτε με %@"; +"endpoint.cells.any_address.caption" = "Αυτόματο"; +"endpoint.cells.any_protocol.caption" = "Αυτόματο"; +"configuration.sections.communication.header" = "Επικοινωνία"; +"configuration.sections.reset.footer" = "Αν καταλήξατε σε κατεστραμένη συνδεσιμότητα μετά την αλλαγή των παραμέτρων επικοινωνίας, πατήστε για να επανέλθετε στην αρχική διαμόρφωση."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Συμπίεση"; +"configuration.sections.network.header" = "Δίκτυο"; +"configuration.sections.other.header" = "Άλλο"; +"configuration.cells.cipher.caption" = "Cipher"; +"configuration.cells.digest.caption" = "Αυθεντικοποίηση"; +"configuration.cells.digest.value.embedded" = "Ενσωματωμένο"; +"configuration.cells.reset_original.caption" = "Επαναφορά ρυθμίσεων"; +"configuration.cells.client.caption" = "Πιστοποιητικό πελάτη"; +"configuration.cells.client.value.enabled" = "Επαληθεύτηκε"; +"configuration.cells.client.value.disabled" = "Δεν επαληθεύτηκε"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Αυθεντικοποίηση"; +"configuration.cells.tls_wrapping.value.crypt" = "Κρυπτογράφηση"; +"configuration.cells.eku.caption" = "Εκτεταμένη επαλήθευση"; +"network_settings.gateway.title" = "Προεπιλεγμένη πύλη"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domain"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--συμπίεση"; +"configuration.cells.compression_algorithm.caption" = "Αλγόρυθμος"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Δεν υποστηρίζεται"; +"configuration.cells.keep_alive.caption" = "Διατηρήστε ζωντανή"; +"configuration.cells.keep_alive.value.seconds" = "%d δευτερόλεπτα"; +"configuration.cells.renegotiation_seconds.caption" = "Επαναδιαπραγμάτευση"; +"configuration.cells.renegotiation_seconds.value.after" = "μετά από %@"; +"configuration.cells.random_endpoint.caption" = "Τυχαίο τελικό σημείο"; +"network_choice.client" = "Ανάγνωση .ovpn"; +"network_choice.server" = "Λήψη από το διακομιστή"; +"global.captions.address" = "Διεύθυνση"; +"global.captions.port" = "Θύρα"; +"debug_log.buttons.previous" = "Προηγούμενο"; +"debug_log.buttons.next" = "Επόμενο"; +"debug_log.alerts.empty_log.message" = "Το αρχείο εντοπισμού σφαλμάτων είναι κενό."; +"vpn.connecting" = "Προσπάθεια Σύνδεσης"; +"vpn.active" = "Ενεργό"; +"vpn.disconnecting" = "Αποσυνδέετε"; +"vpn.inactive" = "Μη ενεργό"; +"vpn.disabled" = "Απενεργοποιημένο"; +"vpn.errors.timeout" = "Τέλος χρονικού Ορίου"; +"vpn.errors.dns" = "Το DNS απέτυχε"; +"vpn.errors.auth" = "Το Auth απέτυχε"; +"vpn.errors.tls" = "Το TLS απέτυχε"; +"vpn.errors.encryption" = "Η Κρυπτογράφηση απέτυχε"; +"vpn.errors.compression" = "Η συμπίεση δεν υποστηρίζεται"; +"vpn.errors.network" = "Το δίκτυο άλλαξε"; +"vpn.errors.routing" = "Λείπει η δρομολόγηση"; +"vpn.errors.gateway" = "Δεν υπάρχει πύλη"; +"vpn.errors.shutdown" = "Ο διακομιστής έκλεισε"; +"issue_reporter.title" = "Αναφορά Προβλήματος"; +"issue_reporter.message" = "The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous.\n\nThe .ovpn configuration file, if any, is attached stripped of any sensitive data.\n\nPlease double check the e-mail attachments if unsure."; +"issue_reporter.buttons.accept" = "Καταλαβαίνω"; +"translations.title" = "Μεταφράσεις"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Δίκτυο Κινητής"; +"shortcuts.add.cells.connect.caption" = "Σύνδεση σε"; +"shortcuts.add.cells.enable_vpn.caption" = "Ενεργοποίηση VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Απενεργοποίηση VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Εμπιστέψου το τρέχον Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Μην εμπιστευθείτε το τρέχον Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "Εμπιστοσύνη δικτύου κινητής τηλεφωνίας"; +"shortcuts.add.cells.untrust_cellular.caption" = "Μην εμπιστευθείτε το δίκτυο κινητής τηλεφωνίας"; +"shortcuts.add.alerts.no_profiles.message" = "Δεν υπάρχει προφίλ για σύνδεση."; +"shortcuts.edit.sections.all.header" = "Υπάρχουσες συντομεύσεις"; +"about.title" = "Περι"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Διαμοιράστε"; +"about.cells.credits.caption" = "Συντελεστές"; +"about.cells.website.caption" = "Αρχική Σελίδα"; +"about.cells.faq.caption" = "Συχνές Ερωτήσεις"; +"about.cells.disclaimer.caption" = "Άρνηση Ευθύνης"; +"about.cells.privacy_policy.caption" = "Πολιτική Απορρήτου"; +"about.cells.share_twitter.caption" = "Tweet γι 'αυτό!"; +"about.cells.share_generic.caption" = "Πρόσκληση Φίλου"; +"donation.title" = "Δωρεά"; +"donation.sections.one_time.header" = "Μια Φορά"; +"donation.sections.one_time.footer" = "Αν είστε χαρούμενη με τη δουλειά μου, εδώ είναι λίγα ποσά που μπορείτε να δώσετε αμέσως.\n\nΘα χρεωθείτε μόνο μία φορά και μπορείτε να δώσετε πολλές φορές."; +"donation.cells.loading.caption" = "Φόρτωση δωρεών"; +"donation.cells.purchasing.caption" = "Εκτέλεση δωρεάς"; +"donation.alerts.purchase.success.title" = "Ευχαριστώ"; +"donation.alerts.purchase.success.message" = "Αυτό σημαίνει πολλά για μένα και πραγματικά ελπίζω να συνεχίσετε να χρησιμοποιείτε και να προωθείτε αυτήν την εφαρμογή."; +"donation.alerts.purchase.failure.message" = "Δεν είναι δυνατή η εκτέλεση της δωρεάς. %@"; +"share.message" = "Το Passepartout είναι φιλικό προς το χρήστη, ανοιχτού κώδικα OpenVPN πρόγραμμα για iOS και macOS"; +"version.title" = "Έκδοση"; +"version.labels.intro" = "Το Passepartout και το TunnelKit γράφονται και συντηρούνται από τον Davide De Rosa (keeshux).\n\nΟ πηγαίος κώδικας για το Passepartout και το TunnelKit είναι δημόσια διαθέσιμε στο GitHub υπό το GPLv3, μπορείτε να βρείτε συνδέσμους στην αρχική σελίδα.\n\nΤο Passepartout είναι ένας μη επίσημος πελάτης και δεν είναι συνδεδεμένος με το OpenVPN Inc."; +"credits.title" = "Συντελεστές"; +"credits.sections.licenses.header" = "Άδειες"; +"credits.sections.notices.header" = "Σημειώσεις"; +"credits.sections.translations.header" = "Μεταφράσεις"; +"label.license.error" = "Δεν είναι δυνατή η λήψη πλήρους περιεχομένου άδειας χρήσης."; +"organizer.cells.profile.value.current" = "Σε χρήση"; +"service.welcome.message" = "Καλώς Ήλθατε στο Passepartout!\n\nΧρησιμοποιήστε τον διοργανωτή για να προσθέσετε ένα νέο προφίλ."; +"service.cells.server_configuration.caption" = "Ρυθμίσεις Διακομιστή"; +"service.cells.server_network.caption" = "Δίκτυο Διακομιστή"; +"service.alerts.configuration.disconnected" = "Μη διαθέσιμη Ρύθμιση, επιβεβαιώστε ότι είστε συνδεδεμένοι στο VPN."; +"server_network.cells.route.caption" = "Διαδρομή"; +"wizards.provider.cells.update_list.caption" = "Αναβάθμιση Λίστας"; +"wizards.provider.alerts.unavailable.message" = "Δεν ήταν δυνατή η λήψη της υποδομής του παρόχου, δοκιμάστε ξανά αργότερα."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Ελάτε να με παρακολουθήσετε ζωντανά το Passepartout στο Twitch, εγγραφείτε στη συνομιλία για να αλληλεπιδράσετε και να συνεισφέρετε!"; +"organizer.cells.follow_twitch.caption" = "Παρακολουθήστε το Passepartout στο Twitch"; +"service.cells.use_profile.caption" = "Χρησιμοποιήστε αυτό το προφίλ"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/el.lproj/Intents.strings b/Passepartout/Core/Resources/el.lproj/Intents.strings new file mode 100644 index 00000000..2e57fa92 --- /dev/null +++ b/Passepartout/Core/Resources/el.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Αφαιρεί το κινητό δίκτυο από τα αξιόπιστα δίκτυα"; + +"IeGsEq" = "Απενεργοποίηση VPN"; +"1ZRTCZ" = "Απενεργοποίηση VPN"; + +"66bZBE" = "Με ${providerId} πάροχο"; + +"7eoAss" = "Αφαίρεση συνδεδεμένου Wi-Fi από τα έμπιστα δίκτυα"; + +"9GpJt5" = "Προσθέτει το κινητό δίκτυο στα αξιόπιστα δίκτυα"; + +"BKxs8X" = "Προσθήκη τρέχων Wi-Fi στα έμπιστα δίκτυα"; + +"NWWgCl" = "Αξιόπιστο Δίκτυο κινητής τηλεφωνίας"; +"H4taev" = "Αξιόπιστο Δίκτυο κινητής τηλεφωνίας"; + +"KjkCfU" = "Συνδέετε σε μια συγκεκριμένη τοποθεσία ενός προφίλ παρόχου"; + +"LA99yM" = "Σύνδεση VPN"; + +"U6o81V" = "Σύνδεση στο ${profileTitle}"; + +"WnTPFg" = "Σύνδεση σε ${poolName}"; + +"eQ1yzr" = "Απενεργοποίηση υπηρεσίας VPN"; + +"eXXb2z" = "Συνδέεται σε ένα προφίλ διακομιστή"; + +"yesvFP" = "Ενεργοποίηση VPN"; +"lQ6ziK" = "Ενεργοποίηση VPN"; + +"POyDPM" = "Εμπιστευθείτε το τρέχον Wi-Fi"; +"m2E7SI" = "Εμπιστευθείτε το τρέχον Wi-Fi"; + +"qo3Szz" = "Συνδεθείτε με τη θέση του παρόχου"; + +"0Wu9nb" = "Μην εμπιστευθείτε το τρέχον Wi-Fi"; +"rd1T8p" = "Μην εμπιστευθείτε το τρέχον Wi-Fi"; + +"ggzKA2" = "Μη αξιόπιστο κινητό δίκτυο"; +"wB1iYX" = "Μη αξιόπιστο κινητό δίκτυο"; + +"xY97Vu" = "Ενεργοποιεί την υπηρεσία VPN με το προφίλ που χρησιμοποιείται αυτήν τη στιγμή"; + +"NCoK9B" = "Με προφίλ σε χρήση"; diff --git a/Passepartout/Core/Resources/en.lproj/Core.strings b/Passepartout/Core/Resources/en.lproj/Core.strings new file mode 100644 index 00000000..42b0bcca --- /dev/null +++ b/Passepartout/Core/Resources/en.lproj/Core.strings @@ -0,0 +1,269 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Cancel"; +"global.next" = "Next"; +"global.close" = "Close"; +"global.host.title_input.message" = "Acceptable characters are alphanumerics plus dash \"-\", underscore \"_\" and dot \".\"."; +"global.host.title_input.placeholder" = "My profile"; +"global.email_not_configured" = "No e-mail account is configured."; + +"global.captions.address" = "Address"; +"global.captions.port" = "Port"; + +"global.values.enabled" = "Enabled"; +"global.values.disabled" = "Disabled"; +"global.values.none" = "None"; +"global.values.automatic" = "Automatic"; +"global.values.manual" = "Manual"; + +"reddit.title" = "Reddit"; +"reddit.message" = "Did you know that Passepartout has a subreddit? Subscribe for updates or to discuss issues, features, new platforms or whatever you like.\n\nIt's also a great way to show you care about this project."; +"reddit.buttons.subscribe" = "Subscribe now!"; +"reddit.buttons.remind" = "Remind me later"; +"reddit.buttons.never" = "Don't ask again"; + +"vpn.connecting" = "Connecting"; +"vpn.active" = "Active"; +"vpn.disconnecting" = "Disconnecting"; +"vpn.inactive" = "Inactive"; +"vpn.disabled" = "Disabled"; + +"vpn.errors.timeout" = "Timeout"; +"vpn.errors.dns" = "DNS failed"; +"vpn.errors.auth" = "Auth failed"; +"vpn.errors.tls" = "TLS failed"; +"vpn.errors.encryption" = "Encryption failed"; +"vpn.errors.compression" = "Compression unsupported"; +"vpn.errors.network" = "Network changed"; +"vpn.errors.routing" = "Missing routing"; +"vpn.errors.gateway" = "No gateway"; +"vpn.errors.shutdown" = "Server shutdown"; + +"parsed_file.alerts.malformed.message" = "The configuration file contains a malformed option (%@)."; +"parsed_file.alerts.missing.message" = "The configuration file lacks a required option (%@)."; +"parsed_file.alerts.unsupported.message" = "The configuration file contains an unsupported option (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings."; +"parsed_file.alerts.encryption_passphrase.message" = "Please enter the encryption passphrase."; +"parsed_file.alerts.decryption.message" = "The configuration contains an encrypted private key and it could not be decrypted. Double check your entered passphrase."; +"parsed_file.alerts.parsing.message" = "Unable to parse the provided configuration file (%@)."; +"parsed_file.alerts.buttons.report" = "Report an issue"; + +"network_choice.client" = "Read .ovpn"; +"network_choice.server" = "Pull from server"; + +"issue_reporter.title" = "Report issue"; +"issue_reporter.message" = "The debug log of your latest connections is crucial to resolve your connectivity issues and is completely anonymous.\n\nThe .ovpn configuration file, if any, is attached stripped of any sensitive data.\n\nPlease double check the e-mail attachments if unsure."; +"issue_reporter.buttons.accept" = "I understand"; + +"translations.title" = "Translations"; + +"share.message" = "Passepartout is an user-friendly, open source OpenVPN client for iOS and macOS"; + +////////////////////// + +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Come watch me make Passepartout live on Twitch, join the chat to interact and contribute!"; +"organizer.sections.providers.header" = "Providers"; +"organizer.sections.providers.footer" = "Here you find a few providers with preset configuration profiles."; +"organizer.sections.hosts.header" = "Hosts"; +"organizer.sections.hosts.footer" = "Import hosts from raw .ovpn configuration files."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Get help from Siri to speed up your most common interactions with the app."; +"organizer.sections.support.header" = "Support"; +"organizer.sections.feedback.header" = "Feedback"; +"organizer.cells.follow_twitch.caption" = "Watch Passepartout on Twitch"; +"organizer.cells.profile.value.current" = "In use"; +"organizer.cells.siri_shortcuts.caption" = "Manage shortcuts"; +"organizer.cells.join_community.caption" = "Join community"; +"organizer.cells.write_review.caption" = "Write a review"; +"organizer.cells.donate.caption" = "Make a donation"; +"organizer.cells.github_sponsors.caption" = "Support me on GitHub"; +"organizer.cells.translate.caption" = "Offer to translate"; +"organizer.cells.about.caption" = "About %@"; +"organizer.cells.uninstall.caption" = "Remove VPN configuration"; +"organizer.alerts.exhausted_providers.message" = "You have created profiles for any available provider."; +"organizer.alerts.add_host.message" = "Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile.\n\nYou can also import an .ovpn with iTunes File Sharing."; +"organizer.alerts.cannot_donate.message" = "There is no payment method configured on this device."; +"organizer.alerts.delete_vpn_profile.message" = "Do you really want to erase the VPN configuration from your device settings? This may fix some broken VPN states and will not affect your provider and host profiles."; + +"wizards.provider.cells.update_list.caption" = "Update list"; +"wizards.provider.alerts.unavailable.message" = "Could not download provider infrastructure, please retry later."; +"wizards.host.alerts.existing.message" = "A host profile with the same title already exists. Replace it?"; + +"service.welcome.message" = "Welcome to Passepartout!\n\nUse the organizer to add a new profile."; +"service.sections.vpn.footer" = "The connection will be established whenever necessary."; +"service.sections.provider_infrastructure.footer" = "Last updated on %@."; +"service.sections.vpn_survives_sleep.footer" = "Disable to improve battery usage, at the expense of occasional slowdowns due to wake-up reconnections."; +"service.sections.vpn_resolves_hostname.footer" = "Preferred in most networks and required in some IPv6 networks. Disable where DNS is blocked, or to speed up negotiation when DNS is slow to respond."; +"service.sections.trusted.header" = "Trusted networks"; +"service.sections.trusted.footer" = "When entering a trusted network, the VPN is normally shut down and kept disconnected. Disable this option to not enforce such behavior."; +"service.sections.diagnostics.header" = "Diagnostics"; +"service.sections.diagnostics.footer" = "Masking status will be effective after reconnecting. Network data are hostnames, IP addresses, routing, SSID. Credentials and private keys are not logged regardless."; +"service.cells.use_profile.caption" = "Use this profile"; +"service.cells.connection_status.caption" = "Status"; +"service.cells.provider.pool.caption" = "Location"; +"service.cells.provider.preset.caption" = "Preset"; +"service.cells.vpn_survives_sleep.caption" = "Keep alive on sleep"; +"service.cells.vpn_resolves_hostname.caption" = "Resolve provider hostname"; +"service.cells.trusted_mobile.caption" = "Cellular network"; +"service.cells.trusted_policy.caption" = "Trust disables VPN"; +"service.cells.test_connectivity.caption" = "Test connectivity"; +"service.cells.data_count.caption" = "Exchanged data"; +"service.cells.data_count.none" = "Unavailable"; +"service.cells.server_configuration.caption" = "Server configuration"; +"service.cells.server_network.caption" = "Server network"; +"service.cells.debug_log.caption" = "Debug log"; +"service.cells.masks_private_data.caption" = "Mask network data"; +"service.cells.reconnect.caption" = "Reconnect"; +"service.cells.report_issue.caption" = "Report connectivity issue"; + +"service.alerts.rename.title" = "Rename profile"; +"service.alerts.credentials_needed.message" = "You need to enter account credentials first."; +"service.alerts.reconnect_vpn.message" = "Do you want to reconnect to the VPN?"; +"service.alerts.trusted.no_network.message" = "You are not connected to any Wi-Fi network."; +"service.alerts.trusted.will_disconnect_trusted.message" = "By trusting this network, the VPN may be disconnected. Continue?"; +"service.alerts.trusted.will_disconnect_policy.message" = "By changing the trust policy, the VPN may be disconnected. Continue?"; +"service.alerts.test_connectivity.title" = "Connectivity"; +"service.alerts.test_connectivity.messages.success" = "Your device is connected to the Internet!"; +"service.alerts.test_connectivity.messages.failure" = "Your device has no Internet connectivity, please review your profile parameters."; +"service.alerts.configuration.disconnected" = "Configuration unavailable, make sure you are connected to the VPN."; +"service.alerts.masks_private_data.messages.must_reconnect" = "In order to safely reset the current debug log and apply the new masking preference, you must reconnect to the VPN now."; +"service.alerts.buttons.reconnect" = "Reconnect"; +"service.alerts.download.title" = "Download required"; +"service.alerts.download.message" = "%@ requires the download of additional configuration files.\n\nConfirm to start the download."; +"service.alerts.download.failed" = "Failed to download configuration files. %@"; +"service.alerts.download.hud.extracting" = "Extracting files, please be patient..."; + +"account.title" = "Account"; +"account.sections.guidance.footer.infrastructure.hideme" = "Use your %@ website credentials."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Use your %@ website credentials. Your username is usually numeric (without spaces)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Use your %@ website credentials. Your username is usually your e-mail."; +"account.sections.guidance.footer.infrastructure.pia" = "Use your %@ website credentials. Your username is usually numeric with a \"p\" prefix."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Find your %@ credentials in the \"Account > OpenVPN / IKEv2 Username\" section of the website."; +"account.sections.guidance.footer.infrastructure.torguard" = "Use your %@ service credentials, which may differ from website credentials."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Use your %@ website credentials. Your username is usually your e-mail."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Use your %@ website credentials. Your username is usually your e-mail."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Find your %@ credentials in the OpenVPN Config Generator on the website."; +"account.sections.registration.footer" = "Go get an account on the %@ website."; +"account.cells.username.caption" = "Username"; +"account.cells.username.placeholder" = "username"; +"account.cells.password.caption" = "Password"; +"account.cells.password.placeholder" = "secret"; +"account.cells.open_guide.caption" = "See your credentials"; +"account.cells.signup.caption" = "Register with %@"; + +"endpoint.title" = "Endpoint"; +"endpoint.cells.any_address.caption" = "Automatic"; +"endpoint.cells.any_protocol.caption" = "Automatic"; + +"network_settings.title" = "Network settings"; + +"configuration.sections.communication.header" = "Communication"; +"configuration.sections.reset.footer" = "If you ended up with broken connectivity after changing the communication parameters, tap to revert to the original configuration."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Compression"; +"configuration.sections.network.header" = "Network"; +"configuration.sections.other.header" = "Other"; +"configuration.cells.cipher.caption" = "Cipher"; +"configuration.cells.digest.caption" = "Authentication"; +"configuration.cells.digest.value.embedded" = "Embedded"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algorithm"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Unsupported"; +"configuration.cells.reset_original.caption" = "Reset configuration"; +"configuration.cells.client.caption" = "Client certificate"; +"configuration.cells.client.value.enabled" = "Verified"; +"configuration.cells.client.value.disabled" = "Not verified"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Authentication"; +"configuration.cells.tls_wrapping.value.crypt" = "Encryption"; +"configuration.cells.eku.caption" = "Extended verification"; +"configuration.cells.keep_alive.caption" = "Keep-alive"; +"configuration.cells.keep_alive.value.seconds" = "%d seconds"; +"configuration.cells.renegotiation_seconds.caption" = "Renegotiation"; +"configuration.cells.renegotiation_seconds.value.after" = "after %@"; +"configuration.cells.random_endpoint.caption" = "Randomize endpoint"; + +"network_settings.gateway.title" = "Default gateway"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domain"; +"network_settings.proxy.title" = "Proxy"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; + +"server_network.cells.route.caption" = "Route"; + +"debug_log.buttons.previous" = "Previous"; +"debug_log.buttons.next" = "Next"; +"debug_log.alerts.empty_log.message" = "The debug log is empty."; + +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Cellular"; +"shortcuts.add.cells.connect.caption" = "Connect to"; +"shortcuts.add.cells.enable_vpn.caption" = "Enable VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Disable VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Trust current Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Untrust current Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "Trust cellular network"; +"shortcuts.add.cells.untrust_cellular.caption" = "Untrust cellular network"; +"shortcuts.add.alerts.no_profiles.message" = "There is no profile to connect to."; + +"shortcuts.edit.sections.all.header" = "Existing shortcuts"; + +"donation.title" = "Donate"; +"donation.sections.one_time.header" = "One time"; +"donation.sections.one_time.footer" = "If you want to display gratitude for my free work, here are a couple amounts you can donate instantly.\n\nYou will only be charged once per donation, and you can donate multiple times."; +"donation.cells.loading.caption" = "Loading donations"; +"donation.cells.purchasing.caption" = "Performing donation"; +"donation.alerts.purchase.success.title" = "Thank you"; +"donation.alerts.purchase.success.message" = "This means a lot to me and I really hope you keep using and promoting this app."; +"donation.alerts.purchase.failure.message" = "Unable to perform the donation. %@"; + +"about.title" = "About"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Share"; +"about.cells.credits.caption" = "Credits"; +"about.cells.website.caption" = "Home page"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Disclaimer"; +"about.cells.privacy_policy.caption" = "Privacy policy"; +"about.cells.share_twitter.caption" = "Tweet about it!"; +"about.cells.share_generic.caption" = "Invite a friend"; + +"version.title" = "Version"; +"version.labels.intro" = "Passepartout and TunnelKit are written and maintained by Davide De Rosa (keeshux).\n\nSource code for Passepartout and TunnelKit is publicly available on GitHub under the GPLv3, you can find links in the home page.\n\nPassepartout is a non-official client and is in no way affiliated with OpenVPN Inc."; + +"credits.title" = "Credits"; +"credits.sections.licenses.header" = "Licenses"; +"credits.sections.notices.header" = "Notices"; +"credits.sections.translations.header" = "Translations"; + +"label.license.error" = "Unable to download full license content."; diff --git a/Passepartout/Core/Resources/en.lproj/Intents.strings b/Passepartout/Core/Resources/en.lproj/Intents.strings new file mode 100644 index 00000000..8afbd82a --- /dev/null +++ b/Passepartout/Core/Resources/en.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Removes cellular from trusted networks"; + +"IeGsEq" = "Disable VPN"; +"1ZRTCZ" = "Disable VPN"; + +"66bZBE" = "With ${providerId} provider"; + +"7eoAss" = "Removes current Wi-Fi from trusted networks"; + +"9GpJt5" = "Adds cellular to trusted networks"; + +"BKxs8X" = "Adds current Wi-Fi to trusted networks"; + +"NWWgCl" = "Trust cellular network"; +"H4taev" = "Trust cellular network"; + +"KjkCfU" = "Connects to a specific location of a provider profile"; + +"LA99yM" = "Connect to VPN"; + +"U6o81V" = "Connect to ${profileTitle}"; + +"WnTPFg" = "Connect to ${poolName}"; + +"eQ1yzr" = "Disables the VPN service"; + +"eXXb2z" = "Connects to a host profile"; + +"yesvFP" = "Enable VPN"; +"lQ6ziK" = "Enable VPN"; + +"POyDPM" = "Trust current Wi-Fi"; +"m2E7SI" = "Trust current Wi-Fi"; + +"qo3Szz" = "Connect to provider location"; + +"0Wu9nb" = "Untrust current Wi-Fi"; +"rd1T8p" = "Untrust current Wi-Fi"; + +"ggzKA2" = "Untrust cellular network"; +"wB1iYX" = "Untrust cellular network"; + +"xY97Vu" = "Enables the VPN service with the profile currently in use"; + +"NCoK9B" = "With profile in use"; diff --git a/Passepartout/Core/Resources/es.lproj/Core.strings b/Passepartout/Core/Resources/es.lproj/Core.strings new file mode 100644 index 00000000..16fb42c7 --- /dev/null +++ b/Passepartout/Core/Resources/es.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Cancelar"; +"global.next" = "Siguiente"; +"global.close" = "Salir"; +"global.host.title_input.message" = "Caracteres aceptados son los alfanuméricos más el guión alto \"-\", el guión bajo \"_\" y el punto \".\"."; +"global.host.title_input.placeholder" = "Mi perfil"; +"global.email_not_configured" = "Ningún e-mail configurado."; +"global.values.enabled" = "Habilitado"; +"global.values.disabled" = "Deshabilitado"; +"global.values.none" = "Ninguno"; +"global.values.automatic" = "Automático"; +"global.values.manual" = "Manual"; +"reddit.title" = "Reddit"; +"reddit.message" = "Sabías que Passepartout tiene un subreddit? Suscríbete para actualizaciones o comentar problemas, funciones, nuevas plataformas o todo lo que se te ocurra.\n\nTambién es la manera ideal de mostrar interés en este proyecto."; +"reddit.buttons.subscribe" = "Suscribir ahora!"; +"reddit.buttons.remind" = "Recordar más tarde"; +"reddit.buttons.never" = "No preguntar más"; +"organizer.sections.providers.header" = "Proveedores"; +"organizer.sections.providers.footer" = "Aquí encuentras algunos proveedores con ajustes preconfigurados."; +"organizer.sections.hosts.header" = "Hosts"; +"organizer.sections.hosts.footer" = "Importa un host con ficheros de configuración .ovpn."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Déjate ayudar por Siri para acelerar tus interacciones más frecuentes con la aplicación."; +"organizer.sections.support.header" = "Soporte"; +"organizer.sections.feedback.header" = "Feedback"; +"organizer.cells.siri_shortcuts.caption" = "Gestionar atajos"; +"organizer.cells.join_community.caption" = "Apuntarse a la comunidad"; +"organizer.cells.write_review.caption" = "Escribir una reseña"; +"organizer.cells.donate.caption" = "Hacer una donación"; +"organizer.cells.github_sponsors.caption" = "Apoyar en GitHub"; +"organizer.cells.translate.caption" = "Ofrecer una traducción"; +"organizer.cells.about.caption" = "Sobre %@"; +"organizer.cells.uninstall.caption" = "Borrar configuración VPN"; +"organizer.alerts.exhausted_providers.message" = "Has creado perfiles para todos los proveedores disponibles."; +"organizer.alerts.add_host.message" = "Abre el URL de un fichero de configuración .ovpn a través de Safari, Mail u otra aplicación para configurar un host.\n\nTambién puedes importar un .ovpn con iTunes File Sharing."; +"organizer.alerts.cannot_donate.message" = "No hay métodos de pago configurados en este dispositivo."; +"organizer.alerts.delete_vpn_profile.message" = "Realmente quieres eliminar la configuración VPN de tu dispositivo? Ésto puede corregir algunos estados incorrectos del VPN y no afectará tus perfiles."; +"wizards.host.alerts.existing.message" = "Ya existe un host con el mismo título. Reemplazar?"; +"parsed_file.alerts.malformed.message" = "El fichero de configuración contiene una opción mal formada (%@)."; +"parsed_file.alerts.missing.message" = "El fichero de configuración falta de una opción necesaria (%@)."; +"parsed_file.alerts.unsupported.message" = "El fichero de configuración contiene una opción no soportada (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "El fichero de configuración es correcto pero contiene una opción potencialmente no soportada (%@).\n\nLa conectividad podría fallar según los parámetros del servidor."; +"parsed_file.alerts.encryption_passphrase.message" = "Por favor introducir la contraseña de cifrado."; +"parsed_file.alerts.decryption.message" = "La configuración contiene una clave privada cifrada que no ha podido ser descifrada. Por favor revisa la contraseña introducida."; +"parsed_file.alerts.parsing.message" = "Imposible importar el fichero de configuración proporcionado (%@)."; +"parsed_file.alerts.buttons.report" = "Reportar una incidencia"; +"service.sections.vpn.footer" = "La conexión se establecerá siempre y cuando sea necesario."; +"service.sections.provider_infrastructure.footer" = "Última actualización: %@."; +"service.sections.vpn_survives_sleep.footer" = "Deshabilitar para mejorar el uso de la batería, a costa de ralentizaciones ocasionales por las reconexiones al despertar el dispositivo."; +"service.sections.vpn_resolves_hostname.footer" = "Preferido en la mayoría de las redes y necesario en algunas redes IPv6. Deshabilitar donde el DNS esté bloqueado, o para acelerar la negociación cuando el DNS sea lento en responder."; +"service.sections.trusted.header" = "Redes de confianza"; +"service.sections.trusted.footer" = "Entrando en una red de confianza, normalmente el VPN es cerrado y mantenido desconectado. Deshabilitar esta opción para no forzar este modo."; +"service.sections.diagnostics.header" = "Diagnósticos"; +"service.sections.diagnostics.footer" = "El estado de ocultación será efectivo tras reconectar. Los datos de red son hostnames, direcciones IP, routing, SSID. Las credenciales y las claves privadas no son registrados a pesar."; +"service.cells.connection_status.caption" = "Estado"; +"account.title" = "Cuenta"; +"endpoint.title" = "Destino"; +"service.cells.provider.pool.caption" = "Ubicación"; +"service.cells.provider.preset.caption" = "Ajuste"; +"network_settings.title" = "Ajustes de red"; +"service.cells.vpn_survives_sleep.caption" = "Mantener en modo inactivo"; +"service.cells.vpn_resolves_hostname.caption" = "Resolver hostname del servidor"; +"service.cells.trusted_mobile.caption" = "Red móvil"; +"service.cells.trusted_policy.caption" = "Red de confianza deshabilita el VPN"; +"service.cells.test_connectivity.caption" = "Testear conectividad"; +"service.cells.data_count.caption" = "Datos intercambiados"; +"service.cells.data_count.none" = "No disponible"; +"service.cells.debug_log.caption" = "Registro de debug"; +"service.cells.masks_private_data.caption" = "Ocultar datos de red"; +"service.cells.reconnect.caption" = "Reconectar"; +"service.cells.report_issue.caption" = "Reportar problema de conectividad"; +"service.alerts.rename.title" = "Renombrar perfil"; +"service.alerts.credentials_needed.message" = "Primero debes introducir las credenciales de tu cuenta."; +"service.alerts.reconnect_vpn.message" = "Quieres reconectarte al VPN?"; +"service.alerts.trusted.no_network.message" = "No estás conectad@ a ninguna red Wi-Fi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Confiando en esta red, el VPN será desconectado. Continuar?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Cambiando la política de confianza, el VPN podría ser desconectado. Continuar?"; +"service.alerts.test_connectivity.title" = "Conectividad"; +"service.alerts.test_connectivity.messages.success" = "Tu dispositivo está conectado en Internet!"; +"service.alerts.test_connectivity.messages.failure" = "Tu dispositivo no tiene conectividad Internet, por favor revisa los parámetros de tu perfil."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Para resetear el registro de debug y aplicar la nueva preferencia de ocultación, debes reconectarte al VPN."; +"service.alerts.buttons.reconnect" = "Reconectar"; +"service.alerts.download.title" = "Descarga necesaria"; +"service.alerts.download.message" = "%@ requiere la descarga de fichero de configuración adicionales.\n\nConfirmar para empezar la descarga."; +"service.alerts.download.failed" = "Imposible descargar los ficheros de configuración. %@"; +"service.alerts.download.hud.extracting" = "Extrayendo ficheros, por favor ten paciencia..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Usa tus credenciales de la web %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Usa tus credenciales de la web %@. Normalmente tu usuario es numérico (sin espacios)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Usa tus credenciales de la web %@. Normalmente tu usuario es tu e-mail."; +"account.sections.guidance.footer.infrastructure.pia" = "Usa tus credenciales de la web %@. Normalmente tu usuario es numérico con un prefijo \"p\"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Encuentra tus credenciales %@ en la sección \"Account > OpenVPN / IKEv2 Username\" de la web."; +"account.sections.guidance.footer.infrastructure.torguard" = "Usa tus credenciales de servicio %@, que pueden diferir de las credenciales de la web."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Usa tus credenciales de la web %@. Normalmente tu usuario es tu e-mail."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Usa tus credenciales de la web %@. Normalmente tu usuario es tu e-mail."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Encuentra tus credenciales %@ en el \"OpenVPN Config Generator\" en la web."; +"account.sections.registration.footer" = "Obten una cuenta en la web de %@."; +"account.cells.username.caption" = "Usuario"; +"account.cells.username.placeholder" = "usuario"; +"account.cells.password.caption" = "Contraseña"; +"account.cells.password.placeholder" = "secreto"; +"account.cells.open_guide.caption" = "Mira tus credenciales"; +"account.cells.signup.caption" = "Registrarse con %@"; +"endpoint.cells.any_address.caption" = "Automática"; +"endpoint.cells.any_protocol.caption" = "Automático"; +"configuration.sections.communication.header" = "Comunicación"; +"configuration.sections.reset.footer" = "Si acabaste estropeando tu conectividad tras cambiar los parámetros de comunicación, pulsa para volver a la configuración inicial."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Compresión"; +"configuration.sections.network.header" = "Red"; +"configuration.sections.other.header" = "Otro"; +"configuration.cells.cipher.caption" = "Cifrado"; +"configuration.cells.digest.caption" = "Autentificación"; +"configuration.cells.digest.value.embedded" = "Incluida"; +"configuration.cells.reset_original.caption" = "Resetear configuración"; +"configuration.cells.client.caption" = "Certificado cliente"; +"configuration.cells.client.value.enabled" = "Verificado"; +"configuration.cells.client.value.disabled" = "No verificado"; +"configuration.cells.tls_wrapping.caption" = "Envoltorio"; +"configuration.cells.tls_wrapping.value.auth" = "Autentificado"; +"configuration.cells.tls_wrapping.value.crypt" = "Cifrado"; +"configuration.cells.eku.caption" = "Verificación extendida"; +"network_settings.gateway.title" = "Puerta de enlace"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Dominio"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Marco"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algoritmo"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "No soportado"; +"configuration.cells.keep_alive.caption" = "Keep-alive"; +"configuration.cells.keep_alive.value.seconds" = "%d segundos"; +"configuration.cells.renegotiation_seconds.caption" = "Renegociación"; +"configuration.cells.renegotiation_seconds.value.after" = "después de %@"; +"configuration.cells.random_endpoint.caption" = "Aleatorizar destino"; +"network_choice.client" = "Leer .ovpn"; +"network_choice.server" = "Obtener del servidor"; +"global.captions.address" = "Dirección"; +"global.captions.port" = "Puerta"; +"debug_log.buttons.previous" = "Anterior"; +"debug_log.buttons.next" = "Siguiente"; +"debug_log.alerts.empty_log.message" = "El registro de debug está vacío."; +"vpn.connecting" = "Conectando"; +"vpn.active" = "Activo"; +"vpn.disconnecting" = "Desconectando"; +"vpn.inactive" = "Inactivo"; +"vpn.disabled" = "Deshabilitado"; +"vpn.errors.timeout" = "Timeout"; +"vpn.errors.dns" = "DNS fallido"; +"vpn.errors.auth" = "Autentificación fallida"; +"vpn.errors.tls" = "TLS fallido"; +"vpn.errors.encryption" = "Cifrado fallido"; +"vpn.errors.compression" = "Compresión no soportada"; +"vpn.errors.network" = "Cambio de red"; +"vpn.errors.routing" = "Sin rutas"; +"vpn.errors.gateway" = "Sin puerta de enlace"; +"vpn.errors.shutdown" = "Servidor apagado"; +"issue_reporter.title" = "Reportar incidencia"; +"issue_reporter.message" = "El registro de debug de tus últimas conexiones es primordial para resolver tus problemas de conectividad y es completamente anónimo.\n\nSi hay un fichero de configuración .ovpn, se adjuntará sin ningún dato sensible.\n\nSi no estás segur@, por favor revisa los adjuntos del e-mail."; +"issue_reporter.buttons.accept" = "Entendido"; +"translations.title" = "Traducciones"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Móvil"; +"shortcuts.add.cells.connect.caption" = "Conectar a"; +"shortcuts.add.cells.enable_vpn.caption" = "Habilitar VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Deshabilitar VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Añadir Wi-Fi de confianza"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Borrar Wi-Fi de confianza"; +"shortcuts.add.cells.trust_cellular.caption" = "Añadir red móvil de confianza"; +"shortcuts.add.cells.untrust_cellular.caption" = "Borrar red móvil de confianza"; +"shortcuts.add.alerts.no_profiles.message" = "No hay ningún perfil al que conectarse."; +"shortcuts.edit.sections.all.header" = "Atajos existentes"; +"about.title" = "Información"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Compartir"; +"about.cells.credits.caption" = "Créditos"; +"about.cells.website.caption" = "Página de inicio"; +"about.cells.faq.caption" = "Preguntas frecuentes"; +"about.cells.disclaimer.caption" = "Aviso legal"; +"about.cells.privacy_policy.caption" = "Política de privacidad"; +"about.cells.share_twitter.caption" = "Enviar un Tweet!"; +"about.cells.share_generic.caption" = "Invitar a un amig@"; +"donation.title" = "Donar"; +"donation.sections.one_time.header" = "Única"; +"donation.sections.one_time.footer" = "Si te gusta mi trabajo, aquí puedes colaborar con una donación.\n\nSólo se te cobrará una vez por donación, y puedes donar las veces que quieras."; +"donation.cells.loading.caption" = "Cargando donaciones"; +"donation.cells.purchasing.caption" = "Efectuando donación"; +"donation.alerts.purchase.success.title" = "Muchas gracias"; +"donation.alerts.purchase.success.message" = "Ésto significa mucho para mí y espero sinceramente que sigas usando y promoviendo esta aplicación."; +"donation.alerts.purchase.failure.message" = "Imposible completar la donación, por favor vuelve a intentarlo. %@"; +"share.message" = "Passepartout es un cliente OpenVPN intuitivo, de código abierto para iOS y macOS"; +"version.title" = "Versión"; +"version.labels.intro" = "Passepartout y TunnelKit están escritos y son mantenidos por Davide De Rosa (keeshux).\n\nEl código de Passepartout y TunnelKit es público y está disponible en GitHub bajo la GPLv3, encontrarás enlaces en la página de inicio.\n\nPassepartout es un cliente no oficial y no es afiliado de OpenVPN Inc."; +"credits.title" = "Créditos"; +"credits.sections.licenses.header" = "Licencias"; +"credits.sections.notices.header" = "Avisos"; +"credits.sections.translations.header" = "Traducciones"; +"label.license.error" = "Imposible descargar el contenido completo de la licencia."; +"organizer.cells.profile.value.current" = "En uso"; +"service.welcome.message" = "Bienvenid@ a Passepartout!\n\nUsa el organizador para añadir un nuevo perfil."; +"service.cells.server_configuration.caption" = "Configuración del servidor"; +"service.cells.server_network.caption" = "Red del servidor"; +"service.alerts.configuration.disconnected" = "Configuración no disponible, asegúrate de estar conectad@ a la VPN."; +"server_network.cells.route.caption" = "Ruta"; +"wizards.provider.cells.update_list.caption" = "Actualizar lista"; +"wizards.provider.alerts.unavailable.message" = "No fue posible bajar la infraestructura del proveedor, por favor reinténtalo más tarde."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "¡Ven a ver cómo hago Passepartout en vivo en Twitch, únete al chat para interactuar y contribuir!"; +"organizer.cells.follow_twitch.caption" = "Ve Passepartout en Twitch"; +"service.cells.use_profile.caption" = "Usar este perfil"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/es.lproj/Intents.strings b/Passepartout/Core/Resources/es.lproj/Intents.strings new file mode 100644 index 00000000..95b880e8 --- /dev/null +++ b/Passepartout/Core/Resources/es.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Borra la red móvil de las redes de confianza"; + +"IeGsEq" = "Deshabilitar VPN"; +"1ZRTCZ" = "Deshabilitar VPN"; + +"66bZBE" = "Con el proveedor ${providerId}"; + +"7eoAss" = "Borra el Wi-Fi en uso de las redes de confianza"; + +"9GpJt5" = "Añade la red móvil a las redes de confianza"; + +"BKxs8X" = "Añade el Wi-Fi en uso a las redes de confianza"; + +"NWWgCl" = "Añadir red móvil de confianza"; +"H4taev" = "Añadir red móvil de confianza"; + +"KjkCfU" = "Conecta con una región específica de un proveedor"; + +"LA99yM" = "Conectar con el VPN"; + +"U6o81V" = "Conectar con ${profileTitle}"; + +"WnTPFg" = "Conectar con ${poolName}"; + +"eQ1yzr" = "Deshabilita el servicio VPN"; + +"eXXb2z" = "Conecta con un host"; + +"yesvFP" = "Habilitar VPN"; +"lQ6ziK" = "Habilitar VPN"; + +"POyDPM" = "Añadir Wi-Fi de confianza"; +"m2E7SI" = "Añadir Wi-Fi de confianza"; + +"qo3Szz" = "Conectar con una región del proveedor"; + +"0Wu9nb" = "Borrar Wi-Fi de confianza"; +"rd1T8p" = "Borrar Wi-Fi de confianza"; + +"ggzKA2" = "Borrar red móvil de confianza"; +"wB1iYX" = "Borrar red móvil de confianza"; + +"xY97Vu" = "Habilita el servicio VPN con el perfil en uso"; + +"NCoK9B" = "Con el perfil en uso"; diff --git a/Passepartout/Core/Resources/fr.lproj/Core.strings b/Passepartout/Core/Resources/fr.lproj/Core.strings new file mode 100644 index 00000000..178064e2 --- /dev/null +++ b/Passepartout/Core/Resources/fr.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Annuler"; +"global.next" = "Suivant"; +"global.close" = "Fermer"; +"global.host.title_input.message" = "Caractères acceptables sont alphanumériques et tiret \"-\", barre de soulignement \"_\" et point \".\"."; +"global.host.title_input.placeholder" = "Mon profile"; +"global.email_not_configured" = "Aucun compte courriel n'est configuré."; +"global.values.enabled" = "Activer"; +"global.values.disabled" = "Désactiver"; +"global.values.none" = "Aucun"; +"global.values.automatic" = "Automatique"; +"global.values.manual" = "Manuel"; +"reddit.title" = "Reddit"; +"reddit.message" = "Saviez-vous que Passepartout a un subreddit? Souscrivez pour les mises à jour ou discuter des problèmes, caractéristiques, nouvelles plateformes ou quoi que ce soit.\n\nC'est aussi une très bonne façon de démontrer votre enthousiasme envers le projet."; +"reddit.buttons.subscribe" = "Souscrivez maintenant!"; +"reddit.buttons.remind" = "Me rappeler plus tard"; +"reddit.buttons.never" = "Ne pas me redemander"; +"organizer.sections.providers.header" = "Fournisseurs"; +"organizer.sections.providers.footer" = "Ici vous pouvez trousers certains fournisseurs avec des profiles déjà configurés."; +"organizer.sections.hosts.header" = "Hôtes"; +"organizer.sections.hosts.footer" = "Importer des hôtes d'un fichier de configuration .ovpn."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Obtenez de l'aide de Siri pour accélérer vos intéractions les plus courantes avec l'app."; +"organizer.sections.support.header" = "Support"; +"organizer.sections.feedback.header" = "Commentaires"; +"organizer.cells.siri_shortcuts.caption" = "Gérer les raccourcis"; +"organizer.cells.join_community.caption" = "Rejoindre la communauté"; +"organizer.cells.write_review.caption" = "Écrire un avis"; +"organizer.cells.donate.caption" = "Faire un don"; +"organizer.cells.github_sponsors.caption" = "Me parrainer chez GitHub"; +"organizer.cells.translate.caption" = "Offre de traduction"; +"organizer.cells.about.caption" = "À propos %@"; +"organizer.cells.uninstall.caption" = "Supprimer la configuration VPN"; +"organizer.alerts.exhausted_providers.message" = "Vous avez créé un profile pour un fournisseur existant."; +"organizer.alerts.add_host.message" = "Ouvrir un URL vers un fichier de configuration .ovpn depuis Safari, Courriels ou un autre app pour installer un profile hôte.\n\nVous pouvez importer une configuration .ovpn avec le transfert de fichiers iTunes."; +"organizer.alerts.cannot_donate.message" = "Il n'y a aucune méthode de paiement configuré sur cet appareil."; +"organizer.alerts.delete_vpn_profile.message" = "Voulez-vous vraiment effacer la configuration VPN de vos paramètres? Ceci peux fixer certains VPN en arrêt et n'affectera pas vos profiles de fournisseurs et hôtes."; +"wizards.host.alerts.existing.message" = "Un profile hôte avec ce même nom existe déjà. Le remplacer?"; +"parsed_file.alerts.malformed.message" = "Le fichier de configuration contient une mauvaise option.(%@)."; +"parsed_file.alerts.missing.message" = "Le fichier de configuration ne contient pas une option requise. (%@)."; +"parsed_file.alerts.unsupported.message" = "Le fichier de configuration contient une option non supportée (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Le fichier de configuration est adéquat, mais contient une option potentiellement non supportée. (%@).\n\nLa connection peut être perdue selon les paramètres du serveur."; +"parsed_file.alerts.encryption_passphrase.message" = "Veuillez entrer le mot de passe d'encryption."; +"parsed_file.alerts.decryption.message" = "Le fichier de configuration contient une clé privée encryptée et n'a pas été décryptée. Veuillez revérifier votre mot de passe."; +"parsed_file.alerts.parsing.message" = "Incapable d'analyser le fichier de configuration fournis. (%@)."; +"parsed_file.alerts.buttons.report" = "Rapporter un problème"; +"service.sections.vpn.footer" = "La connection sera établie lorsque nécessaire."; +"service.sections.provider_infrastructure.footer" = "Mis à jour : %@."; +"service.sections.vpn_survives_sleep.footer" = "Désactiver pour augmenter l'autonomie de la batterie, au dépends de la rapidité au réveil pour la reconnection."; +"service.sections.vpn_resolves_hostname.footer" = "Préféré dans la plus part des réseaux et requis dans certains réseaux IPv6. Désactiver lorsque le DNS est bloqué ou pour augmenter la rapidité des négociations lorsque le DNS est lent à répondre."; +"service.sections.trusted.header" = "Réseaux de confiance"; +"service.sections.trusted.footer" = "Lors d'une connection à un réseau de confiance, le VPN est normalement fermé. Désactivez cette option pour ne pas autoriser ce comportement."; +"service.sections.diagnostics.header" = "Diagnostiques"; +"service.sections.diagnostics.footer" = "Camouflage du status sera effectif après la reconnection. Les données réseaux sont les noms d'hôtes, adresses IP, routage, SSID. Les identifiants et clés privés ne sont pas enregistrés."; +"service.cells.connection_status.caption" = "Statut"; +"account.title" = "Compte"; +"endpoint.title" = "Extrémité"; +"service.cells.provider.pool.caption" = "Locallisation"; +"service.cells.provider.preset.caption" = "Préréglage"; +"network_settings.title" = "Paramètres réseaux"; +"service.cells.vpn_survives_sleep.caption" = "Garder actif lors de la veille"; +"service.cells.vpn_resolves_hostname.caption" = "Résoudre le nom d'hôte du serveur"; +"service.cells.trusted_mobile.caption" = "Réseau cellulaire"; +"service.cells.trusted_policy.caption" = "La confiance désactive le VPN"; +"service.cells.test_connectivity.caption" = "Tester la connection"; +"service.cells.data_count.caption" = "Échanger les données"; +"service.cells.data_count.none" = "Indisponible"; +"service.cells.debug_log.caption" = "Journal de débogage"; +"service.cells.masks_private_data.caption" = "Masquer les données de réseau"; +"service.cells.reconnect.caption" = "Reconnecter"; +"service.cells.report_issue.caption" = "Rapporter un problème de connection"; +"service.alerts.rename.title" = "Renommer le profile"; +"service.alerts.credentials_needed.message" = "Vous devez entrer les identifiants de compte premièrement."; +"service.alerts.reconnect_vpn.message" = "Voulez-vous reconnecter le VPN?"; +"service.alerts.trusted.no_network.message" = "Vous n'êtes pas connectés à aucun réseau Wi-Fi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "En faisant confiance à ce réseau, le VPN pourrait être déconnecté. Continuer?"; +"service.alerts.trusted.will_disconnect_policy.message" = "En changeant la stratégie de confiance, le VPN pourrait être déconnecté. Continuer?"; +"service.alerts.test_connectivity.title" = "Connections"; +"service.alerts.test_connectivity.messages.success" = "Votre appareil est connecté à Internet!"; +"service.alerts.test_connectivity.messages.failure" = "Votre appareil n'a aucune connection Invernet, veuillez vérifier vos paramètres de profile."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Pour bien réinitialiser le registre de diagnostique et appliquer les préférences de camouflage, vous devez vous reconnecter au VPN maintenant."; +"service.alerts.buttons.reconnect" = "Reconnecter"; +"service.alerts.download.title" = "Téléchargement requis"; +"service.alerts.download.message" = "%@ requiert le téléchargement de fichiers de configuration supplémentaires.\n\nConfirmer le début du téléchargement."; +"service.alerts.download.failed" = "Échec de téléchargement des fichiers de configuration. %@"; +"service.alerts.download.hud.extracting" = "Extraction des fichiers, veuillez patienter..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Utilisez votre identifiants web de %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Utilisez votre identifiants web de %@. Votre nom d'utilisateur est normalement numérique (sans espaces)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Utilisez votre identifiants web de %@. Votre nom d'utilisateur est normalement votre courriel."; +"account.sections.guidance.footer.infrastructure.pia" = "Utilisez votre identifiants web de %@. Votre nom d'utilisateur est normalement numérique avec le préfixe \"p\" "; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Trouvez votre identifiant web %@ dans la section du site web \"Account > OpenVPN / IKEv2 nom d'utilisateur\" "; +"account.sections.guidance.footer.infrastructure.torguard" = "Utilisez vos informations d'identification de service %@, qui peuvent différer des informations d'identification du web."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Utilisez votre identifiants web de %@. Votre nom d'utilisateur est normalement votre courriel."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Utilisez votre identifiants web de %@. Votre nom d'utilisateur est normalement votre courriel."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Trouver votre identifiant %@ dans la section web Générateur de configuration OpenVPN."; +"account.sections.registration.footer" = "Allez créer un compte sur le site %@."; +"account.cells.username.caption" = "Nom d'utilisateur"; +"account.cells.username.placeholder" = "nom d'utilisateur"; +"account.cells.password.caption" = "Mot de passe"; +"account.cells.password.placeholder" = "secret"; +"account.cells.open_guide.caption" = "Voir vos identifiants"; +"account.cells.signup.caption" = "S'inscrire avec %@"; +"endpoint.cells.any_address.caption" = "Automatique"; +"endpoint.cells.any_protocol.caption" = "Automatique"; +"configuration.sections.communication.header" = "Communications"; +"configuration.sections.reset.footer" = "Si vous obtenez une connection erronnée après le changement des parameters de communication, tapotez pour revenir à la configuration initiale."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Compression"; +"configuration.sections.network.header" = "Réseau"; +"configuration.sections.other.header" = "Autre"; +"configuration.cells.cipher.caption" = "Cryptogramme"; +"configuration.cells.digest.caption" = "Authentification"; +"configuration.cells.digest.value.embedded" = "Intégré"; +"configuration.cells.reset_original.caption" = "Réinitialiser la configuration"; +"configuration.cells.client.caption" = "Certificat du client"; +"configuration.cells.client.value.enabled" = "Verifié"; +"configuration.cells.client.value.disabled" = "Non vérifié"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Authentification"; +"configuration.cells.tls_wrapping.value.crypt" = "Cryptage"; +"configuration.cells.eku.caption" = "Vérification étendue"; +"network_settings.gateway.title" = "Gateway"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domaine"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algorithme"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Non supporté"; +"configuration.cells.keep_alive.caption" = "Garder actif"; +"configuration.cells.keep_alive.value.seconds" = "%d secondes"; +"configuration.cells.renegotiation_seconds.caption" = "Renégociation"; +"configuration.cells.renegotiation_seconds.value.after" = "aprè %@"; +"configuration.cells.random_endpoint.caption" = "Extrémité aléatoire"; +"network_choice.client" = "Lire .ovpn"; +"network_choice.server" = "Récupérer depuis le serveur"; +"global.captions.address" = "Adresse"; +"global.captions.port" = "Port"; +"debug_log.buttons.previous" = "Précédent"; +"debug_log.buttons.next" = "Suivant"; +"debug_log.alerts.empty_log.message" = "Le journal de débogage est vide. "; +"vpn.connecting" = "Connection..."; +"vpn.active" = "Actif"; +"vpn.disconnecting" = "Déconnection..."; +"vpn.inactive" = "Inactif"; +"vpn.disabled" = "Désactivé"; +"vpn.errors.timeout" = "Délais dépassé"; +"vpn.errors.dns" = "Échec DNS"; +"vpn.errors.auth" = "Échec Auth"; +"vpn.errors.tls" = "Échec TLS"; +"vpn.errors.encryption" = "Échec du cryptage"; +"vpn.errors.compression" = "Compression non supportée"; +"vpn.errors.network" = "Réseau modifié"; +"vpn.errors.routing" = "Routage manquant"; +"vpn.errors.gateway" = "Aucune passerelle"; +"vpn.errors.shutdown" = "Arrêt du serveur"; +"issue_reporter.title" = "Rapporter un problème"; +"issue_reporter.message" = "Le journal débogage de votre dernière connection est crucial pour résoudre vos problèmes de connection et est entièrement anonyme.\n\nLe fichier de configuration .ovpn, si disponible, est attaché et supprimé de toute information confidentielle.\n\nVeuillez contre-vérifier les fichiers attachés au courriel si incertain."; +"issue_reporter.buttons.accept" = "Je comprends"; +"translations.title" = "Traductions"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Cellulaire"; +"shortcuts.add.cells.connect.caption" = "Connecter à"; +"shortcuts.add.cells.enable_vpn.caption" = "Activer VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Désactiver VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Faire confiance au présent réseau Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Retirer le présent réseau Wi-Fi des réseaux de confiance."; +"shortcuts.add.cells.trust_cellular.caption" = "Faire confiance au présent réseau cellulaire"; +"shortcuts.add.cells.untrust_cellular.caption" = "Retirer le présent réseau cellulaire des réseaux de confiance."; +"shortcuts.add.alerts.no_profiles.message" = "Il n'y a aucun profile pour se connecter."; +"shortcuts.edit.sections.all.header" = "Raccourcis existants"; +"about.title" = "À propos"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Partager"; +"about.cells.credits.caption" = "Crédits"; +"about.cells.website.caption" = "Page d'accueil"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Avis de non-responsabilité"; +"about.cells.privacy_policy.caption" = "Politique de la vie privée"; +"about.cells.share_twitter.caption" = "Tweetez!"; +"about.cells.share_generic.caption" = "Inviter un amis"; +"donation.title" = "Faire un don"; +"donation.sections.one_time.header" = "Une seule fois"; +"donation.sections.one_time.footer" = "Si vous voulez manifester votre gratitude envers mon travail bénévole, voici certains montants pour faire un don instantanément.\n\n Vous n'allez être chargé qu'une seule fois par don et vous pouvez faire un don plus d'une fois."; +"donation.cells.loading.caption" = "Chargement des dons"; +"donation.cells.purchasing.caption" = "Don en cours"; +"donation.alerts.purchase.success.title" = "Merci"; +"donation.alerts.purchase.success.message" = "Ceci signifie beaucoup pour moi et j'espère sincèrement que vous continuerez d'utiliser et de promouvoir cette app."; +"donation.alerts.purchase.failure.message" = "Impossible de faire le don. %@"; +"share.message" = "Passepartout est un client OpenVPN simple d'utilisation et open source pour iOS et macOS"; +"version.title" = "Version"; +"version.labels.intro" = "Passepartout et TunnelKit sont codés et maintenu par Davide De Rosa (keeshux).\n\nLe code source de Passepartout et TunnelKit est publiquement disponible sur GitHub sous license GPLv3, vous pouvez trouver les liens sur la page d'accueil.\n\nPassepartout est un client non-officiel et n'est aucunement affilié avec OpenVPN Inc."; +"credits.title" = "Crédits"; +"credits.sections.licenses.header" = "Licenses"; +"credits.sections.notices.header" = "Préavis"; +"credits.sections.translations.header" = "Traductions"; +"label.license.error" = "Impossible de télécharger le contenu complet de la license."; +"organizer.cells.profile.value.current" = "En utilisation"; +"service.welcome.message" = "Bienvenue à Passepartout!\n\nUtilisez l'organiseur pour ajouter un nouveau profile."; +"service.cells.server_configuration.caption" = "Configuration serveur"; +"service.cells.server_network.caption" = "Serveur réseau"; +"service.alerts.configuration.disconnected" = "Configuration non disponible, vous devez être connecté au VPN."; +"server_network.cells.route.caption" = "Routage"; +"wizards.provider.cells.update_list.caption" = "Actualiser la liste"; +"wizards.provider.alerts.unavailable.message" = "Impossible de télécharger l'infrastructure du fournisseur, veuillez réessayer plus tard."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Venez me regarder faire passer Passepartout en direct sur Twitch, rejoignez le chat pour interagir et contribuer!"; +"organizer.cells.follow_twitch.caption" = "Regardez Passepartout sur Twitch"; +"service.cells.use_profile.caption" = "Utiliser ce profile"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/fr.lproj/Intents.strings b/Passepartout/Core/Resources/fr.lproj/Intents.strings new file mode 100755 index 00000000..db08e72e --- /dev/null +++ b/Passepartout/Core/Resources/fr.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Supprime le réseau cellulaire des réseaux de confiance"; + +"IeGsEq" = "Désactive VPN"; +"1ZRTCZ" = "Désactive VPN"; + +"66bZBE" = "Avec ${providerId} fournisseur"; + +"7eoAss" = "Supprime le présent réseaux Wi-Fi des réseaux de confiance "; + +"9GpJt5" = "Ajoutes le réseau cellulaire aux réseaux de confiance"; + +"BKxs8X" = "Ajoutes le présent réseau Wi-Fi aux réseaux de confiance"; + +"NWWgCl" = "Faire confiance au réseau cellulaire"; +"H4taev" = "Faire confiance au réseau cellulaire"; + +"KjkCfU" = "Connecter à une localization spécifique d'un profile de fournisseur"; + +"LA99yM" = "Se connecter au VPN"; + +"U6o81V" = "Se connecter à ${profileTitle}"; + +"WnTPFg" = "Se connecter à ${poolName}"; + +"eQ1yzr" = "Désactives le service VPN"; + +"eXXb2z" = "Connectes à un profile hôte"; + +"yesvFP" = "Activer VPN"; +"lQ6ziK" = "Activer VPN"; + +"POyDPM" = "Faire confiance au présent réseau Wi-Fi"; +"m2E7SI" = "Faire confiance au présent réseau Wi-Fi"; + +"qo3Szz" = "Se connecter à la localisation du fournisseur"; + +"0Wu9nb" = "Ne plus faire confiance au présent réseau Wi-Fi"; +"rd1T8p" = "Ne plus faire confiance au présent réseau Wi-Fi"; + +"ggzKA2" = "Faire confiance au présent réseau cellulaire"; +"wB1iYX" = "Faire confiance au présent réseau cellulaire"; + +"xY97Vu" = "Activer le service VPN avec le profile présentement utilisé"; + +"NCoK9B" = "Avec le profile utilisé"; diff --git a/Passepartout/Core/Resources/it.lproj/Core.strings b/Passepartout/Core/Resources/it.lproj/Core.strings new file mode 100644 index 00000000..9dab62bc --- /dev/null +++ b/Passepartout/Core/Resources/it.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Annulla"; +"global.next" = "Avanti"; +"global.close" = "Chiudi"; +"global.host.title_input.message" = "I caratteri ammessi sono gli alfanumerici e il trattino breve \"-\", il trattino basso \"_\" ed il punto \".\"."; +"global.host.title_input.placeholder" = "Il mio profilo"; +"global.email_not_configured" = "Nessun account e-mail configurato."; +"global.values.enabled" = "Abilitato"; +"global.values.disabled" = "Disabilitato"; +"global.values.none" = "Nessuno"; +"global.values.automatic" = "Automatico"; +"global.values.manual" = "Manuale"; +"reddit.title" = "Reddit"; +"reddit.message" = "Sapevi che Passepartout ha un subreddit? Iscriviti per aggiornamenti o per discutere problemi, aggiunte, nuove piattaforme o qualunque cosa tu voglia.\n\nÈ anche un ottimo modo per dimostrare che hai a cuore questo progetto."; +"reddit.buttons.subscribe" = "Iscriviti ora!"; +"reddit.buttons.remind" = "Ricordami più tardi"; +"reddit.buttons.never" = "Non chiedere più"; +"organizer.sections.providers.header" = "Provider"; +"organizer.sections.providers.footer" = "Qui trovi alcuni provider con configurazioni precompilate."; +"organizer.sections.hosts.header" = "Host"; +"organizer.sections.hosts.footer" = "Importa un host da un file di configurazione .ovpn."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Chiedi aiuto a Siri per velocizzare le tue interazioni più frequenti con l'app."; +"organizer.sections.support.header" = "Supporto"; +"organizer.sections.feedback.header" = "Feedback"; +"organizer.cells.siri_shortcuts.caption" = "Gestisci comandi rapidi"; +"organizer.cells.join_community.caption" = "Entra nella community"; +"organizer.cells.write_review.caption" = "Scrivi una recensione"; +"organizer.cells.donate.caption" = "Fai una donazione"; +"organizer.cells.github_sponsors.caption" = "Supportami su GitHub"; +"organizer.cells.translate.caption" = "Offri una traduzione"; +"organizer.cells.about.caption" = "Informazioni su %@"; +"organizer.cells.uninstall.caption" = "Rimuovi configurazione VPN"; +"organizer.alerts.exhausted_providers.message" = "Hai creato profili per tutti i provider disponibili."; +"organizer.alerts.add_host.message" = "Apri l'URL di un file di configurazione .ovpn da Safari, Mail o da un'altra app per configurare un host.\n\nPuoi anche importare un file .ovpn con iTunes File Sharing."; +"organizer.alerts.cannot_donate.message" = "Nessun metodo di pagamento configurato su questo dispositivo."; +"organizer.alerts.delete_vpn_profile.message" = "Vuoi veramente cancellare la configurazione VPN dalle impostazioni del tuo dispositivo? Quest'azione potrebbe risolvere alcuni stati erronei della VPN e non altererà i tuoi provider e i tuoi host."; +"wizards.host.alerts.existing.message" = "Esiste già un host con lo stesso titolo. Sostituire?"; +"parsed_file.alerts.malformed.message" = "La configurazione contiene un'opzione malformata (%@)."; +"parsed_file.alerts.missing.message" = "La configurazione non contiene un'opzione obbligatoria (%@)."; +"parsed_file.alerts.unsupported.message" = "La configurazione contiene un'opzione non supportata (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "La configurazione è corretto ma contiene un'opzione potenzialmente non supportata (%@).\n\nLa connettività potrebbe fallire a seconda delle impostazioni del server."; +"parsed_file.alerts.encryption_passphrase.message" = "Per favore inserisci la passphrase di criptazione."; +"parsed_file.alerts.decryption.message" = "La configurazione contiene una chiave privata criptata e non è stato possibile decriptarla. Controlla la tua passphrase."; +"parsed_file.alerts.parsing.message" = "Impossibile processare il file di configurazione specificato (%@)."; +"parsed_file.alerts.buttons.report" = "Segnala un problema"; +"service.sections.vpn.footer" = "La connessione sarà stabilita ogni volta che è necessario."; +"service.sections.provider_infrastructure.footer" = "Ultimo aggiornamento: %@."; +"service.sections.vpn_survives_sleep.footer" = "Disabilita per migliorare il consumo della batteria, a discapito di rallentamenti occasionali causati dalle riconnessioni."; +"service.sections.vpn_resolves_hostname.footer" = "Preferibile nella maggior parte delle reti e necessario in alcune reti IPv6. Disabilita dove il DNS è bloccato, o per velocizzare la negoziazione quando il DNS tarda a rispondere."; +"service.sections.trusted.header" = "Reti sicure"; +"service.sections.trusted.footer" = "Entrando in una rete sicura, normalmente la VPN viene spenta e mantenuta disconnessa. Disabilita quest'opzione per non imporre questo comportamento."; +"service.sections.diagnostics.header" = "Diagnostica"; +"service.sections.diagnostics.footer" = "Il mascheramento sarà effettivo dopo una riconnessione. I dati di rete sono hostname, indirizzi IP, routing, SSID. Credenziali e chiavi private non sono registrati in ogni caso."; +"service.cells.connection_status.caption" = "Stato"; +"account.title" = "Account"; +"endpoint.title" = "Endpoint"; +"service.cells.provider.pool.caption" = "Regione"; +"service.cells.provider.preset.caption" = "Preset"; +"network_settings.title" = "Impostazioni di rete"; +"service.cells.vpn_survives_sleep.caption" = "Mantieni attivo in sleep"; +"service.cells.vpn_resolves_hostname.caption" = "Risolvi hostname del server"; +"service.cells.trusted_mobile.caption" = "Rete cellulare"; +"service.cells.trusted_policy.caption" = "Spegni VPN in rete sicura"; +"service.cells.test_connectivity.caption" = "Verifica connettività"; +"service.cells.data_count.caption" = "Dati scambiati"; +"service.cells.data_count.none" = "Non disponibile"; +"service.cells.debug_log.caption" = "Debug log"; +"service.cells.masks_private_data.caption" = "Maschera dati rete"; +"service.cells.reconnect.caption" = "Riconnetti"; +"service.cells.report_issue.caption" = "Segnala problema connettività"; +"service.alerts.rename.title" = "Rinomina profilo"; +"service.alerts.credentials_needed.message" = "Devi prima inserire le tue credenziali."; +"service.alerts.reconnect_vpn.message" = "Vuoi riconnetterti alla VPN?"; +"service.alerts.trusted.no_network.message" = "Non sei connesso/a a nessuna rete Wi-Fi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Rendendo questa rete sicura, la VPN potrebbe essere disconnessa. Continuare?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Cambiando la politica delle reti sicure, la VPN potrebbe essere disconnessa. Continuare?"; +"service.alerts.test_connectivity.title" = "Connettività"; +"service.alerts.test_connectivity.messages.success" = "Il tuo dispositivo è connesso a Internet!"; +"service.alerts.test_connectivity.messages.failure" = "Il tuo dispositivo non è connesso a Internet, per favore controlla i parametri del tuo profilo."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Per azzerare il debug log ed applicare la nuova preferenza di mascheramento, devi riconnetterti alla VPN."; +"service.alerts.buttons.reconnect" = "Riconnetti"; +"service.alerts.download.title" = "Download necessario"; +"service.alerts.download.message" = "%@ richiede lo scaricamento di file di configurazione aggiuntivi.\n\nConferma per avviare lo scaricamento."; +"service.alerts.download.failed" = "Impossibile scaricare i file di configurazione. %@"; +"service.alerts.download.hud.extracting" = "Estraendo i file, un attimo di pazienza..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Usa le credenziali del sito di %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Usa le credenziali del sito di %@. Il tuo username è generalmente numerico (senza spazi)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Usa le credenziali del sito di %@. Il tuo username è generalmente la tua e-mail."; +"account.sections.guidance.footer.infrastructure.pia" = "Usa le credenziali del sito di %@. Il tuo username è generalmente numerico con un prefisso \"p\"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Trova le tue credenziali nella sezione \"Account > OpenVPN / IKEv2 Username\" del sito di %@."; +"account.sections.guidance.footer.infrastructure.torguard" = "Usa le tue credenziali del servizio %@, che potrebbero differire dalle credenziali del sito web."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Usa le credenziali del sito di %@. Il tuo username è generalmente la tua e-mail."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Usa le credenziali del sito di %@. Il tuo username è generalmente la tua e-mail."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Trova le tue credenziali nell'OpenVPN Config Generator sul sito di %@."; +"account.sections.registration.footer" = "Registra un account sul sito di %@."; +"account.cells.username.caption" = "Username"; +"account.cells.username.placeholder" = "username"; +"account.cells.password.caption" = "Password"; +"account.cells.password.placeholder" = "segreto"; +"account.cells.open_guide.caption" = "Vedi le tue credenziali"; +"account.cells.signup.caption" = "Registrati con %@"; +"endpoint.cells.any_address.caption" = "Automatico"; +"endpoint.cells.any_protocol.caption" = "Automatico"; +"configuration.sections.communication.header" = "Comunicazione"; +"configuration.sections.reset.footer" = "Se ti trovi con una connettività compromessa dopo aver cambiato i parametri di comunicazione, tocca per tornare alla configurazione originale."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Compressione"; +"configuration.sections.network.header" = "Rete"; +"configuration.sections.other.header" = "Altro"; +"configuration.cells.cipher.caption" = "Cifratura"; +"configuration.cells.digest.caption" = "Autenticazione"; +"configuration.cells.digest.value.embedded" = "Incorporata"; +"configuration.cells.reset_original.caption" = "Ripristina configurazione"; +"configuration.cells.client.caption" = "Certificato client"; +"configuration.cells.client.value.enabled" = "Verificato"; +"configuration.cells.client.value.disabled" = "Non verificato"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Autenticazione"; +"configuration.cells.tls_wrapping.value.crypt" = "Criptazione"; +"configuration.cells.eku.caption" = "Verifica estesa"; +"network_settings.gateway.title" = "Gateway predefinito"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Dominio"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algoritmo"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Non supportato"; +"configuration.cells.keep_alive.caption" = "Keep-alive"; +"configuration.cells.keep_alive.value.seconds" = "%d secondi"; +"configuration.cells.renegotiation_seconds.caption" = "Rinegoziazione"; +"configuration.cells.renegotiation_seconds.value.after" = "dopo %@"; +"configuration.cells.random_endpoint.caption" = "Endpoint casuale"; +"network_choice.client" = "Leggi .ovpn"; +"network_choice.server" = "Ottieni dal server"; +"global.captions.address" = "Indirizzo"; +"global.captions.port" = "Porta"; +"debug_log.buttons.previous" = "Precedente"; +"debug_log.buttons.next" = "Successivo"; +"debug_log.alerts.empty_log.message" = "Il debug log è vuoto."; +"vpn.connecting" = "Connettendo"; +"vpn.active" = "Attiva"; +"vpn.disconnecting" = "Disconnettendo"; +"vpn.inactive" = "Inattiva"; +"vpn.disabled" = "Disabilitata"; +"vpn.errors.timeout" = "Timeout"; +"vpn.errors.dns" = "DNS fallito"; +"vpn.errors.auth" = "Autenticazione fallita"; +"vpn.errors.tls" = "TLS fallito"; +"vpn.errors.encryption" = "Crittografia fallita"; +"vpn.errors.compression" = "Compressione non supportata"; +"vpn.errors.network" = "Rete cambiata"; +"vpn.errors.routing" = "Routing mancante"; +"vpn.errors.gateway" = "Nessun gateway"; +"vpn.errors.shutdown" = "Server arrestato"; +"issue_reporter.title" = "Segnala problema"; +"issue_reporter.message" = "Il debug log delle tue ultime connessioni è cruciale per risolvere i tuoi problemi di connettività ed è completamente anonimo.\n\nIl file di configurazione .ovpn, se presente, è allegato privato di ogni dato sensibile.\n\nPer favore controlla gli allegati dell'e-mail se non sei sicuro/a."; +"issue_reporter.buttons.accept" = "Ho capito"; +"translations.title" = "Traduzioni"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Cellulare"; +"shortcuts.add.cells.connect.caption" = "Connetti a"; +"shortcuts.add.cells.enable_vpn.caption" = "Abilita VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Disabilita VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Aggiungi Wi-Fi sicura"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Rimuovi Wi-Fi sicura"; +"shortcuts.add.cells.trust_cellular.caption" = "Aggiungi rete mobile sicura"; +"shortcuts.add.cells.untrust_cellular.caption" = "Rimuovi rete mobile sicura"; +"shortcuts.add.alerts.no_profiles.message" = "Non c'è nessun profilo a cui connettersi."; +"shortcuts.edit.sections.all.header" = "Comandi esistenti"; +"about.title" = "Informazioni su"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Condividi"; +"about.cells.credits.caption" = "Credits"; +"about.cells.website.caption" = "Home page"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Disclaimer"; +"about.cells.privacy_policy.caption" = "Privacy policy"; +"about.cells.share_twitter.caption" = "Manda un Tweet!"; +"about.cells.share_generic.caption" = "Invita un amico"; +"donation.title" = "Donazione"; +"donation.sections.one_time.header" = "Unica"; +"donation.sections.one_time.footer" = "Se vuoi mostrare gratitudine per il mio lavoro a titolo gratuito, qui trovi varie somme da donare all'istante.\n\nLa donazione ti sarà addebitata solo una volta, e puoi effettuare più donazioni."; +"donation.cells.loading.caption" = "Caricando donazioni"; +"donation.cells.purchasing.caption" = "Effettuando donazione"; +"donation.alerts.purchase.success.title" = "Grazie"; +"donation.alerts.purchase.success.message" = "Questo significa molto per me e spero vivamente che tu continui ad usare e promuovere quest'applicazione."; +"donation.alerts.purchase.failure.message" = "Impossibile effettuare la donazione. %@"; +"share.message" = "Passepartout è un client OpenVPN user-friendly ed open source per iOS e macOS"; +"version.title" = "Versione"; +"version.labels.intro" = "Passepartout e TunnelKit sono scritti e mantenuti da Davide De Rosa (keeshux).\n\nIl codice sorgente di Passepartout e TunnelKit è pubblicamente disponibile su GitHub in accordo con la GPLv3, puoi trovare i link nella home page.\n\nPassepartout è un client non ufficiale e non è affiliato ad OpenVPN Inc. in alcuna maniera."; +"credits.title" = "Credits"; +"credits.sections.licenses.header" = "Licenze"; +"credits.sections.notices.header" = "Notice"; +"credits.sections.translations.header" = "Traduzioni"; +"label.license.error" = "Impossibile scaricare il contenuto completo della licenza."; +"organizer.cells.profile.value.current" = "In uso"; +"service.welcome.message" = "Benvenuto in Passepartout!\n\nUsa il menu per aggiungere un nuovo profilo."; +"service.cells.server_configuration.caption" = "Configurazione del server"; +"service.cells.server_network.caption" = "Rete del server"; +"service.alerts.configuration.disconnected" = "Configurazione non disponibile, assicurati di essere connesso/a alla VPN."; +"server_network.cells.route.caption" = "Rotta"; +"wizards.provider.cells.update_list.caption" = "Aggiorna lista"; +"wizards.provider.alerts.unavailable.message" = "Non è stato possibile scaricare l'infrastruttura del provider, per favore riprova più tardi."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Vieni a vedermi creare Passepartout in diretta su Twitch, unisciti alla chat per interagire e contribuire!"; +"organizer.cells.follow_twitch.caption" = "Guarda Passepartout su Twitch"; +"service.cells.use_profile.caption" = "Usa questo profilo"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/it.lproj/Intents.strings b/Passepartout/Core/Resources/it.lproj/Intents.strings new file mode 100644 index 00000000..2aeadfdb --- /dev/null +++ b/Passepartout/Core/Resources/it.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Rimuove la rete mobile dalle reti sicure"; + +"IeGsEq" = "Disabilita VPN"; +"1ZRTCZ" = "Disabilita VPN"; + +"66bZBE" = "Con il provider ${providerId}"; + +"7eoAss" = "Rimuove la Wi-Fi corrente dalle reti sicure"; + +"9GpJt5" = "Aggiunge la rete mobile alle reti sicure"; + +"BKxs8X" = "Aggiunge la Wi-Fi corrente alle reti sicure"; + +"NWWgCl" = "Aggiungi rete mobile sicura"; +"H4taev" = "Aggiungi rete mobile sicura"; + +"KjkCfU" = "Avvia una connessione ad una regione specifica di un provider"; + +"LA99yM" = "Connetti alla VPN"; + +"U6o81V" = "Connettiti a ${profileTitle}"; + +"WnTPFg" = "Connettiti in ${poolName}"; + +"eQ1yzr" = "Disabilita il servizio VPN"; + +"eXXb2z" = "Avvia la connessione ad un host"; + +"yesvFP" = "Abilita VPN"; +"lQ6ziK" = "Abilita VPN"; + +"POyDPM" = "Aggiungi Wi-Fi sicura"; +"m2E7SI" = "Aggiungi Wi-Fi sicura"; + +"qo3Szz" = "Connettiti a una regione del provider"; + +"0Wu9nb" = "Rimuovi Wi-Fi sicura"; +"rd1T8p" = "Rimuovi Wi-Fi sicura"; + +"ggzKA2" = "Rimuovi rete mobile sicura"; +"wB1iYX" = "Rimuovi rete mobile sicura"; + +"xY97Vu" = "Abilita il servizio VPN con il profilo attualmente in uso"; + +"NCoK9B" = "Con il profilo in uso"; diff --git a/Passepartout/Core/Resources/nl.lproj/Core.strings b/Passepartout/Core/Resources/nl.lproj/Core.strings new file mode 100644 index 00000000..0591abad --- /dev/null +++ b/Passepartout/Core/Resources/nl.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Afbreken"; +"global.next" = "Volgende"; +"global.close" = "Afsluiten"; +"global.host.title_input.message" = "Toegestane karakters zijn: alfanumerieke en streepjes \"-\", onderliggend streepje \"_\" en punten \".\"."; +"global.host.title_input.placeholder" = "Mijn Profiel"; +"global.email_not_configured" = "Er is geen email adres geconfigureerd."; +"global.values.enabled" = "Ingeschakeld"; +"global.values.disabled" = "Uitgeschakeld"; +"global.values.none" = "Geen"; +"global.values.automatic" = "Automatisch"; +"global.values.manual" = "Handmatig"; +"reddit.title" = "Reddit"; +"reddit.message" = "Wist je dat Passepartout een eigen subreddit heeft? Schrijf je in voor updates, of discussiëren over problemen, (nieuwe) mogelijkheden, nieuwe platformen of wat je maar wil.\n\nHet is ook een goede manier om te laten zien dat je om dit project geeft."; +"reddit.buttons.subscribe" = "Schfijf je nu in!"; +"reddit.buttons.remind" = "Herinner me later"; +"reddit.buttons.never" = "Vraag dit niet meer"; +"organizer.sections.providers.header" = "Aanbieders"; +"organizer.sections.providers.footer" = "Hier vind je aan aantal aanbieders met configuratie profielen."; +"organizer.sections.hosts.header" = "Hosts"; +"organizer.sections.hosts.footer" = "Importeer hosts met raw .ovpn configuratie bestanden."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Krijg hulp van Siri en versnel de meest gebruikte interacties binnen de app."; +"organizer.sections.support.header" = "Ondersteuning"; +"organizer.sections.feedback.header" = "Terugkoppeling"; +"organizer.cells.siri_shortcuts.caption" = "Beheer snelkoppelingen"; +"organizer.cells.join_community.caption" = "Word lid van de gemeenschap"; +"organizer.cells.write_review.caption" = "Schrijf een beoordeling"; +"organizer.cells.donate.caption" = "Doneer een gift"; +"organizer.cells.github_sponsors.caption" = "Steun me op GitHub"; +"organizer.cells.translate.caption" = "Help met vertalen"; +"organizer.cells.about.caption" = "Over %@"; +"organizer.cells.uninstall.caption" = "Verwijder VPN configuratie"; +"organizer.alerts.exhausted_providers.message" = "Er zijn profielen gemaakt voor elke beschikbare aanbieder."; +"organizer.alerts.add_host.message" = "Open een URL naar een .ovpn configuratie bestand met Safari, Mail of een andere app om een host profile te configureren.\n\nJe kan ook een .ovpn importeren met behulp van iTunes bestandsdeling."; +"organizer.alerts.cannot_donate.message" = "Er is geen betaalmethode geconfigureerd op dit apparaat."; +"organizer.alerts.delete_vpn_profile.message" = "Wilt u de VPN-configuratie van uw apparaatinstellingen verwijderen? Dit kan enkele problemen met VPN oplossen en heeft geen invloed op uw provider- en hostprofielen."; +"wizards.host.alerts.existing.message" = "Er bestaat al een host profiel met deze titel, wil je hem vervangen?"; +"parsed_file.alerts.malformed.message" = "Het configuratie betand bevat ongeldige optie(s) (%@)."; +"parsed_file.alerts.missing.message" = "Het configuratiebestand mist een vereiste optie (%@)."; +"parsed_file.alerts.unsupported.message" = "Het configuratiebestand bevat een niet-ondersteunde optie (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Het configuratiebestand is correct maar bevat mogelijk een niet-ondersteunde optie (%@).\n\nConnectiviteit kan hier door niet werken, afhankelijk van de serverinstellingen."; +"parsed_file.alerts.encryption_passphrase.message" = "Voer een coderingswachtwoord in"; +"parsed_file.alerts.decryption.message" = "De configuratie bevat een gecodeerde privésleutel en deze kan niet worden gedecodeerd. Controleer de ingevoerde wachtwoordzin nogmaals."; +"parsed_file.alerts.parsing.message" = "Kan het opgegeven configuratiebestand niet verwerken (%@)."; +"parsed_file.alerts.buttons.report" = "Een probleem melden"; +"service.sections.vpn.footer" = "De verbinding zal worden gestart wanneer nodig."; +"service.sections.provider_infrastructure.footer" = "Laatste update was op %@."; +"service.sections.vpn_survives_sleep.footer" = "Uitschakelen om het batterijverbruik te verbeteren, ten koste van incidentele vertragingen als gevolg van het opnieuw opstarten na wake-up."; +"service.sections.vpn_resolves_hostname.footer" = "Voorkeur om dit aan te zetten voor de meeste netwerken en vereist in sommige IPv6-netwerken. Uitschakelen waar DNS wordt geblokkeerd, of om de onderhandelingen te versnellen wanneer DNS traag reageert."; +"service.sections.trusted.header" = "Vertrouwde netwerken"; +"service.sections.trusted.footer" = "Bij het invoeren van een vertrouwd netwerk wordt de VPN uitgeschakeld en niet verbonden gehouden. Schakel deze optie uit om dergelijk gedrag niet af te dwingen."; +"service.sections.diagnostics.header" = "Diagnose"; +"service.sections.diagnostics.footer" = "De maskeerstatus is effectief na opnieuw verbinden. Netwerkgegevens zijn hostnamen, IP-adressen, routing, SSID's. Inloggegevens en privésleutels worden niet geregistreerd."; +"service.cells.connection_status.caption" = "Status"; +"account.title" = "Account"; +"endpoint.title" = "Endpoint"; +"service.cells.provider.pool.caption" = "Locatie"; +"service.cells.provider.preset.caption" = "Voorkeur"; +"network_settings.title" = "Netwerk instellingen"; +"service.cells.vpn_survives_sleep.caption" = "Actief tijdens slaapstand"; +"service.cells.vpn_resolves_hostname.caption" = "Haal de naam van de host op"; +"service.cells.trusted_mobile.caption" = "Mobiel netwerk"; +"service.cells.trusted_policy.caption" = "Trust disables VPN"; +"service.cells.test_connectivity.caption" = "Test connectiviteit"; +"service.cells.data_count.caption" = "Gegegevens uitgewisseld"; +"service.cells.data_count.none" = "Niet beschikbaar"; +"service.cells.debug_log.caption" = "Foutopsporingslogboek"; +"service.cells.masks_private_data.caption" = "Netwerkgegevens maskeren"; +"service.cells.reconnect.caption" = "Opnieuw verbinden"; +"service.cells.report_issue.caption" = "Probleem met connectiviteit melden"; +"service.alerts.rename.title" = "Profiel hernoemen"; +"service.alerts.credentials_needed.message" = "Voer eerst de accountgegevens in."; +"service.alerts.reconnect_vpn.message" = "Opnieuw verbinding maken met de VPN?"; +"service.alerts.trusted.no_network.message" = "U bent niet verbonden met een Wi-Fi-netwerk."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Door dit netwerk te vertrouwen, kan de verbinding met de VPN mogelijk worden verbroken. Doorgaan?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Door het vertrouwensbeleid te wijzigen, kan de verbinding met de VPN mogelijk worden verbroken. Doorgaan?"; +"service.alerts.test_connectivity.title" = "Connectiviteit"; +"service.alerts.test_connectivity.messages.success" = "Apparaat is verbonden met internet!"; +"service.alerts.test_connectivity.messages.failure" = "Uw apparaat heeft geen internetverbinding. Controleer uw profielparameters."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Om het huidige foutopsporingslogboek veilig opnieuw in te stellen en de nieuwe maskeervoorkeur toe te passen, moet u nu opnieuw verbinding maken met VPN."; +"service.alerts.buttons.reconnect" = "Opnieuw verbinden"; +"service.alerts.download.title" = "Download vereist"; +"service.alerts.download.message" = "%@ vereist het downloaden van extra configuratiebestanden.\n\nBevestig om het downloaden te starten."; +"service.alerts.download.failed" = "Downloaden van configuratiebestanden is mislukt. %@"; +"service.alerts.download.hud.extracting" = "Bestanden uitpakken, even geduld..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Gebruik de inloggegevens van %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Gebruik de inloggegevens van %@. Uw gebruikersnaam is meestal numeriek (zonder ruimte)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Gebruik de inloggegevens van %@. Uw gebruikersnaam is meestal uw e-mailadres."; +"account.sections.guidance.footer.infrastructure.pia" = "Gebruik de inloggegevens van %@. Uw gebruikersnaam is meestal numeriek met \"p\" als voorvoegsel."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Vind de inloggegevens van %@ in \"Account > OpenVPN / IKEv2 Username\" onderdeel van de website."; +"account.sections.guidance.footer.infrastructure.torguard" = "Gebruik uw %@ service-gegevens, die kunnen verschillen van de gegevens van de website."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Gebruik de inloggegevens van %@. Uw gebruikersnaam is meestal uw e-mailadres."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Gebruik de inloggegevens van %@ Uw gebruikersnaam is meestal uw e-mailadres."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Vind de inloggegevens van %@ in de OpenVPN Config Generator op de website."; +"account.sections.registration.footer" = "Registreer voor een %@ account op de website."; +"account.cells.username.caption" = "Gebruikersnaam"; +"account.cells.username.placeholder" = "gebruikersnaam"; +"account.cells.password.caption" = "Wachtwoord"; +"account.cells.password.placeholder" = "geheim"; +"account.cells.open_guide.caption" = "Bekijk de inloggegevens"; +"account.cells.signup.caption" = "Registreer bij %@"; +"endpoint.cells.any_address.caption" = "Automatisch"; +"endpoint.cells.any_protocol.caption" = "Automatisch"; +"configuration.sections.communication.header" = "Communicatie"; +"configuration.sections.reset.footer" = "Tik hier als de connectiviteit niet meer werkt na het aanpassen van instellingen, om terug te gaan naar de originele configuratie."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Compressie"; +"configuration.sections.network.header" = "Netwerk"; +"configuration.sections.other.header" = "Ander"; +"configuration.cells.cipher.caption" = "Cipher"; +"configuration.cells.digest.caption" = "Authenticatie"; +"configuration.cells.digest.value.embedded" = "Embedded"; +"configuration.cells.reset_original.caption" = "Reset configuratie"; +"configuration.cells.client.caption" = "Client certificaat"; +"configuration.cells.client.value.enabled" = "Geverifieerd"; +"configuration.cells.client.value.disabled" = "Niet geverifieerd"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Authenticatie"; +"configuration.cells.tls_wrapping.value.crypt" = "Versleuteling"; +"configuration.cells.eku.caption" = "Uitgebreide verificatie"; +"network_settings.gateway.title" = "Standaard gateway"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domein"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algoritme"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Niet ondersteund"; +"configuration.cells.keep_alive.caption" = "Keep-alive"; +"configuration.cells.keep_alive.value.seconds" = "%d seconden"; +"configuration.cells.renegotiation_seconds.caption" = "Renegotiation"; +"configuration.cells.renegotiation_seconds.value.after" = "na %@"; +"configuration.cells.random_endpoint.caption" = "Willekeurig eindpunt"; +"network_choice.client" = "Gebruik .ovpn"; +"network_choice.server" = "Haal op van server"; +"global.captions.address" = "Adress"; +"global.captions.port" = "Port"; +"debug_log.buttons.previous" = "Vorige"; +"debug_log.buttons.next" = "Volgende"; +"debug_log.alerts.empty_log.message" = "Het logboek voor foutopsporing is leeg."; +"vpn.connecting" = "Verbinden"; +"vpn.active" = "Actief"; +"vpn.disconnecting" = "Verbinding verbreken"; +"vpn.inactive" = "Inactief"; +"vpn.disabled" = "Uitgeschakeld"; +"vpn.errors.timeout" = "Time-out"; +"vpn.errors.dns" = "DNS niet gelukt"; +"vpn.errors.auth" = "Auth niet gelukt"; +"vpn.errors.tls" = "TLS niet gelukt"; +"vpn.errors.encryption" = "Versleuteling mislukt"; +"vpn.errors.compression" = "Compressie wordt niet ondersteund"; +"vpn.errors.network" = "Netwerk veranderd"; +"vpn.errors.routing" = "Ontbrekende routering"; +"vpn.errors.gateway" = "Geen gateway"; +"vpn.errors.shutdown" = "Server is afgesloten"; +"issue_reporter.title" = "Meld een probleem"; +"issue_reporter.message" = "Het foutopsporingslogboek van uw laatste verbindingen is cruciaal om uw verbindingsproblemen op te lossen en is volledig geanonimiseerd.\n\nHet .ovpn configuratiebestand, indien aanwezig, is ontdaan van alle gevoelige gegevens.\n\nControleer de e-mailbijlagen als je niet zeker bent dat alles verwijderd is."; +"issue_reporter.buttons.accept" = "Ik ga akkoord"; +"translations.title" = "Vertalingen"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Mobiel"; +"shortcuts.add.cells.connect.caption" = "Verbind met"; +"shortcuts.add.cells.enable_vpn.caption" = "Activeer VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Deactiveer VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Vertrouw huidig Wi-Fi netwerk"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Untrust current Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "Vertouw mobiel netwerk"; +"shortcuts.add.cells.untrust_cellular.caption" = "Untrust mobiel netwerk"; +"shortcuts.add.alerts.no_profiles.message" = "Er is geen profiel om verbinding mee te maken."; +"shortcuts.edit.sections.all.header" = "Bestaande snelkoppelingen"; +"about.title" = "Over"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Delen"; +"about.cells.credits.caption" = "Credits"; +"about.cells.website.caption" = "Home page"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Vrijwaring"; +"about.cells.privacy_policy.caption" = "Privacybeleid"; +"about.cells.share_twitter.caption" = "Tweet about it!"; +"about.cells.share_generic.caption" = "Nodig een vriend uit"; +"donation.title" = "Donatie"; +"donation.sections.one_time.header" = "Eenmalig"; +"donation.sections.one_time.footer" = "Als je dankbaarheid wilt tonen voor mijn gratis werk, zijn hier een paar bedragen die je direct kunt doneren.\n\nHet bedrag wordt slechts één keer per donatie in rekening gebracht en u kunt meerdere keren doneren."; +"donation.cells.loading.caption" = "Ophalen donaties"; +"donation.cells.purchasing.caption" = "Doneren"; +"donation.alerts.purchase.success.title" = "Hartelijk dank"; +"donation.alerts.purchase.success.message" = "Dit betekent veel voor mij en ik hoop echt dat je deze app blijft gebruiken en promoten."; +"donation.alerts.purchase.failure.message" = "Donatie mislukt. %@"; +"share.message" = "Passepartout is een gebruiksvriendelijke open source OpenVPN-client voor iOS en macOS"; +"version.title" = "Versie"; +"version.labels.intro" = "Passepartout en TunnelKit zijn geschreven en worden onderhouden door Davide De Rosa (keeshux).\n\nDe broncode voor Passepartout en TunnelKit is openbaar beschikbaar op GitHub onder de GPLv3, je kunt links op de startpagina vinden.\n\nPassepartout is een niet-officiële client en is op geen enkele manier verbonden aan OpenVPN Inc."; +"credits.title" = "Credits"; +"credits.sections.licenses.header" = "Licenties"; +"credits.sections.notices.header" = "Mededelingen"; +"credits.sections.translations.header" = "Vertalingen"; +"label.license.error" = "Kan volledige licentie-inhoud niet downloaden."; +"organizer.cells.profile.value.current" = "In gebruik"; +"service.welcome.message" = "Welkom bij Passepartout!\n\nGebruik de organizer om een nieuw profiel toe te voegen."; +"service.cells.server_configuration.caption" = "Server configuratie"; +"service.cells.server_network.caption" = "Server netwerk"; +"service.alerts.configuration.disconnected" = "Configuratie niet beschikbaar, zorg ervoor dat u verbonden bent met de VPN."; +"server_network.cells.route.caption" = "Route"; +"wizards.provider.cells.update_list.caption" = "Lijst bijwerken"; +"wizards.provider.alerts.unavailable.message" = "Kon de provider-infrastructuur niet downloaden, probeer het later opnieuw."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Kom kijken hoe ik Passepartout live maak op Twitch, doe mee aan de chat om te communiceren en bij te dragen!"; +"organizer.cells.follow_twitch.caption" = "Bekijk Passepartout op Twitch"; +"service.cells.use_profile.caption" = "Gebruik dit profiel"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/nl.lproj/Intents.strings b/Passepartout/Core/Resources/nl.lproj/Intents.strings new file mode 100644 index 00000000..f055e0f9 --- /dev/null +++ b/Passepartout/Core/Resources/nl.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Verwijder Mobielnetwerk van vertrouwde netwerken"; + +"IeGsEq" = "Disable VPN"; +"1ZRTCZ" = "Disable VPN"; + +"66bZBE" = "Met ${providerId} aanbieder"; + +"7eoAss" = "Verwijder huidige Wi-Fi van vertrouwde netwerken"; + +"9GpJt5" = "Voeg Mobielnetwerk to aan vertrouwde netwerken"; + +"BKxs8X" = "Voeg huidig Wi-Fi toe aan vertrouwde netwerken"; + +"NWWgCl" = "Vertrouw mobiel netwerk"; +"H4taev" = "Vertrouw mobiel netwerk"; + +"KjkCfU" = "Maak verbinding met een specifieke lokatie van een aanbieder profiel"; + +"LA99yM" = "Verbind VPN"; + +"U6o81V" = "Verbind met ${profileTitle}"; + +"WnTPFg" = "Verbind met ${poolName}"; + +"eQ1yzr" = "Schakel VPN service uit"; + +"eXXb2z" = "Verbind met een host profiel"; + +"yesvFP" = "Schakel VPN in"; +"lQ6ziK" = "Schakel VPN in"; + +"POyDPM" = "Vertrouw huidig Wi-Fi netwerk"; +"m2E7SI" = "Vertrouw huidig Wi-Fi netwerk"; + +"qo3Szz" = "Maak verbinding met de locatie van de aanbieder"; + +"0Wu9nb" = "Wantrouw huidig Wi-Fi netwerk"; +"rd1T8p" = "Wantrouw huidig Wi-Fi netwerk"; + +"ggzKA2" = "Wantrouw modbiel netwerk"; +"wB1iYX" = "Wantrouw modbiel netwerk"; + +"xY97Vu" = "Schakel de VPN-service in met het profiel dat momenteel in gebruik is"; + +"NCoK9B" = "Met het profiel dat momenteel in gebruik is"; diff --git a/Passepartout/Core/Resources/pl.lproj/Core.strings b/Passepartout/Core/Resources/pl.lproj/Core.strings new file mode 100644 index 00000000..b7e4df0f --- /dev/null +++ b/Passepartout/Core/Resources/pl.lproj/Core.strings @@ -0,0 +1,269 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Anuluj"; +"global.next" = "Następny"; +"global.close" = "Zamknij"; +"global.host.title_input.message" = "Akceptowane są znaki alfanumeryczne i pauza \"-\", podkreślenie \"_\" oraz kropka \".\"."; +"global.host.title_input.placeholder" = "Mój profil"; +"global.email_not_configured" = "Adres e-mail nie jest skonfigurowany."; + +"global.captions.address" = "Adres"; +"global.captions.port" = "Port"; + +"global.values.enabled" = "Włączony"; +"global.values.disabled" = "Wyłączony"; +"global.values.none" = "Brak"; +"global.values.automatic" = "Automatycznie"; +"global.values.manual" = "Ręcznie"; + +"reddit.title" = "Reddit"; +"reddit.message" = "Wiedziałeś/łaś, że Passepartout ma swój subreddit? Subskrybuj dla aktualizacji, dyskusji o funkcjonalności, nowych platformach lub o czymkolwiek zechcesz.\n\nTo również świetny sposób na okazanie zainteresowania projektem."; +"reddit.buttons.subscribe" = "Subskrybuj!"; +"reddit.buttons.remind" = "Przypomnij mi później"; +"reddit.buttons.never" = "Nie przypominaj"; + +"vpn.connecting" = "Łączenie"; +"vpn.active" = "Aktywne"; +"vpn.disconnecting" = "Rozłączanie"; +"vpn.inactive" = "Nieaktywne"; +"vpn.disabled" = "Wyłączone"; + +"vpn.errors.timeout" = "Upłynąl limit czasu połączenia"; +"vpn.errors.dns" = "Błąd DNS"; +"vpn.errors.auth" = "Błąd autoryzacji"; +"vpn.errors.tls" = "Błąd TLS"; +"vpn.errors.encryption" = "Błąd szyfrowania"; +"vpn.errors.compression" = "Niewspierana kompresja"; +"vpn.errors.network" = "Sieć zmieniona"; +"vpn.errors.routing" = "Brak routingu"; +"vpn.errors.gateway" = "Brak bramy domyślnej"; +"vpn.errors.shutdown" = "Serwer został zamknięty"; + +"parsed_file.alerts.malformed.message" = "Plik konfiguracyjny zawiera źle zformułowaną opcję (%@)."; +"parsed_file.alerts.missing.message" = "Plik konfiguracyjny nie nawiera potrzebnej opcji (%@)."; +"parsed_file.alerts.unsupported.message" = "Plik konfiguracyjny posiada niewspieraną opcję (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Plik konfiguracyjny jest poprawny, ale zawiera potencjalnie niewspieraną opcję (%@).\n\nPołączenie może zostać przerwane przez ustawienia serwera."; +"parsed_file.alerts.encryption_passphrase.message" = "Proszę wpisać frazę szyfrującą."; +"parsed_file.alerts.decryption.message" = "Konfiguracja zawiera zaszyfrowany klucz prywatny który nie może zostać odszyfrowany. Sprawdź frazę szyfrującą."; +"parsed_file.alerts.parsing.message" = "Błąd w przetwarzaniu pliku konfiguracyjnego (%@)."; +"parsed_file.alerts.buttons.report" = "Zgłoś błąd"; + +"network_choice.client" = "Otwórz plik .ovpn"; +"network_choice.server" = "Pobierz z serwera"; + +"issue_reporter.title" = "Zgłoś błąd"; +"issue_reporter.message" = "Rejestr debugowania jest potrzebny w rozwiązywaniu problemów z połaczeniem i jest w pełni anonimowy.\n\nPlik konfiguracyjny .ovpn, jeśli używany, jest dołączany bez wrażliwych danych.\n\nSPrawdź załącznik e-maila jeśli masz wątpliwości."; +"issue_reporter.buttons.accept" = "Rozumiem"; + +"translations.title" = "Tłumaczenia"; + +"share.message" = "Passepartout to klient OpenVPN, przyjazny użytkownikowi, open-source, stworzony dla iOS i macOS"; + +////////////////////// + +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Przyjdź i zobacz, jak tworzę Passepartout na żywo na Twitchu, dołącz do czatu, aby współdziałać i udzielać się!"; +"organizer.sections.providers.header" = "Usługodawcy"; +"organizer.sections.providers.footer" = "Tutaj znajdziesz kilku usługodawców z profilami konfiguracyjnymi."; +"organizer.sections.hosts.header" = "Hosty"; +"organizer.sections.hosts.footer" = "Importuj hosty z plików konfiguracyjnych .ovpn."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Użyj Siri żeby przyspieszyć najczęstsze akcje w aplikacji."; +"organizer.sections.support.header" = "Wsparcie"; +"organizer.sections.feedback.header" = "Wyraź opinię"; +"organizer.cells.follow_twitch.caption" = "Oglądaj Passepartout na Twitchu"; +"organizer.cells.profile.value.current" = "W użyciu"; +"organizer.cells.siri_shortcuts.caption" = "Zarządzaj skrótami"; +"organizer.cells.join_community.caption" = "Dołącz do społeczności"; +"organizer.cells.write_review.caption" = "Napisz recenzję"; +"organizer.cells.donate.caption" = "Wyślij dotację"; +"organizer.cells.github_sponsors.caption" = "Wesprzyj mnie na GitHub"; +"organizer.cells.translate.caption" = "Zaproponuj tłumaczenie"; +"organizer.cells.about.caption" = "O %@"; +"organizer.cells.uninstall.caption" = "Usuń konfiguracje VPN"; +"organizer.alerts.exhausted_providers.message" = "Stworzyłeś/aś już profile dla każdego usługodawcy."; +"organizer.alerts.add_host.message" = "Otwórz link z plikiem .ovpn w Safari, Poczcie lub innej aplikacji aby utworzyć profil hosta.\n\nMożesz też zaimportować plik .ovpn używając 'File Sharing' w iTunes."; +"organizer.alerts.cannot_donate.message" = "Żadna metoda płatności nie jest skonfigurowana na tym urządzeniu."; +"organizer.alerts.delete_vpn_profile.message" = "Na pewno chcesz usunąć konfigurację VPN z urządzenia? Może to naprawić błędy z statusem VPN i nie będzie miało wpływu na konfigurację usługodawców/hostów."; + +"wizards.provider.cells.update_list.caption" = "Zaktualizuj listę"; +"wizards.provider.alerts.unavailable.message" = "Nie można pobrać infrastruktury dostawcy, spróbuj ponownie później."; +"wizards.host.alerts.existing.message" = "Profil hosta z taką nazwą już istnieje. Nadpisać profil?"; + +"service.welcome.message" = "Witaj w Passepartout!\n\nUżyj organizera by utworzyć nowy profil."; +"service.sections.vpn.footer" = "Połączenie zostanie nawiązane zgodnie z ustawieniami."; +"service.sections.provider_infrastructure.footer" = "Ostatnio aktualizowane %@."; +"service.sections.vpn_survives_sleep.footer" = "Wyłącz dla mniejszego zużycia baterii kosztem wolniejszego działania spowodowanego ponownym połączeniem przy wybudzeniu urządzenia."; +"service.sections.vpn_resolves_hostname.footer" = "Preferowane w większości sieci i potrzebne w niektórych sieciach IPv6. Wyłącz kiedy DNS jest zablokowane, lub żeby przyspieszyć ustanawianie połączenia gdy DNS jest zbyt wolne."; +"service.sections.trusted.header" = "Zaufane sieci"; +"service.sections.trusted.footer" = "Kiedy urządzenie łączy się z zaufaną siecią, VPN jest wyłączane. Wyłącz tę opcję żeby nie wymuszać takiego zachowania."; +"service.sections.diagnostics.header" = "Diagnostyka"; +"service.sections.diagnostics.footer" = "Status maskowania będzie widoczny po ponownym połączeniu. Dane połączenia to nazwy hostów, adresy IP, routing, SSID. Loginy i klucze prywatne nie są zapisywane."; +"service.cells.connection_status.caption" = "Status"; +"service.cells.provider.pool.caption" = "Lokalizacja"; +"service.cells.provider.preset.caption" = "Preset"; +"service.cells.vpn_survives_sleep.caption" = "Utrzymuj połączenie przy zablokowanym ekranie"; +"service.cells.vpn_resolves_hostname.caption" = "Rozwiązuj nazwy hostów usługodawcy"; +"service.cells.trusted_mobile.caption" = "Sieć komórkowa"; +"service.cells.trusted_policy.caption" = "Wyłącz VPN dla zaufanych sieci"; +"service.cells.test_connectivity.caption" = "Testuj połączenie"; +"service.cells.data_count.caption" = "Pobrane/wysłane dane"; +"service.cells.data_count.none" = "Niedostępne"; +"service.cells.server_configuration.caption" = "Konfiguracja serwera"; +"service.cells.server_network.caption" = "Sieć serwera"; +"service.cells.debug_log.caption" = "Debugowanie"; +"service.cells.masks_private_data.caption" = "Maskuj dane sieci"; +"service.cells.reconnect.caption" = "Połącz ponownie"; +"service.cells.report_issue.caption" = "Zgłoś problemy z połączeniem"; + +"service.alerts.rename.title" = "Zmień nazwę profilu"; +"service.alerts.credentials_needed.message" = "Musisz najpierw wpisać login/hasło."; +"service.alerts.reconnect_vpn.message" = "Czy chcesz połączyć się ponownie z VPN?"; +"service.alerts.trusted.no_network.message" = "Nie jesteś połączony z siecią WiFi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Ufając tej sieci, połączenie VPN zostanie przerwane, kontynuować?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Aby zmienić ustawienia zaufania, połączenie VPN może zostać przerwane, kontynuować?"; +"service.alerts.test_connectivity.title" = "Połączenie"; +"service.alerts.test_connectivity.messages.success" = "Twoje urządzenie jest połączone z internetem!"; +"service.alerts.test_connectivity.messages.failure" = "Twoje urządzenie nie jest połączone z internetem, sprawdź ustawienia profilu."; +"service.alerts.configuration.disconnected" = "Konfiguracja niedostępna, upewnij się, że jesteś połączony/a z VPN."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Aby bezpiecznie zresetować rejestr debugowania i zastosować nowe ustawienia maskowania, musisz połączyć się z VPN ponownie."; +"service.alerts.buttons.reconnect" = "Połącz ponownie"; +"service.alerts.download.title" = "Potrzebne pobranie"; +"service.alerts.download.message" = "%@ potrzebuje pobrania dodatkowych plików konfiguracyjnych.\n\nPotwierdź aby zacząć pobieranie."; +"service.alerts.download.failed" = "Nie udało się pobrać plików konfiguracyjnych. %@"; +"service.alerts.download.hud.extracting" = "Wypakowywanie plików, proszę czekać ..."; + +"account.title" = "Konto"; +"account.sections.guidance.footer.infrastructure.hideme" = "Użyj loginu do %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Użyj loginu do %@. Twoja nazwa użytkownika jest najczęściej ciągiem liczb (bez przestrzeni)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Użyj loginu do %@. Twoja nazwa użytkownika to najczęściej e-mail."; +"account.sections.guidance.footer.infrastructure.pia" = "Użyj loginu do %@. Twoja nazwa użytkownika jesy najczęściej ciągiem liczb poprzedonym prefiksem \"p\"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Użyj loginu do %@. Zajdziesz go w sekcji \"Account > OpenVPN / IKEv2 Username\"."; +"account.sections.guidance.footer.infrastructure.torguard" = "Użyj poświadczeń usługi %@, które mogą różnić się od poświadczeń witryny."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Użyj loginu do %@. Twoja nazwa użytkownika to najczęściej e-mail."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Użyj loginu do %@. Twoja nazwa użytkownika to najczęściej e-mail."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Użyj loginu do %@ z generatora konfiguracji OpenVPN dostępnego na stronie."; +"account.sections.registration.footer" = "Utwórz konto na stronie: %@"; +"account.cells.username.caption" = "Nazwa użytkownika"; +"account.cells.username.placeholder" = "Nazwa użytkownika"; +"account.cells.password.caption" = "Hasło"; +"account.cells.password.placeholder" = "Ukryte"; +"account.cells.open_guide.caption" = "Zobacz swoje login/hasło"; +"account.cells.signup.caption" = "Zarejstruj się w %@"; + +"endpoint.title" = "Host końcowy"; +"endpoint.cells.any_address.caption" = "Automatyczny"; +"endpoint.cells.any_protocol.caption" = "Automatyczny"; + +"network_settings.title" = "Ustawienia sieci"; + +"configuration.sections.communication.header" = "Komunikacja"; +"configuration.sections.reset.footer" = "Jeśli masz problemy z połączeniem po zmianie konfiguracji komunikacji, kliknij żeby przywrócić domyślną konfigurację."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Kompresja"; +"configuration.sections.network.header" = "Sieć"; +"configuration.sections.other.header" = "Inne"; +"configuration.cells.cipher.caption" = "Szyfr"; +"configuration.cells.digest.caption" = "Uwierzytelnienie"; +"configuration.cells.digest.value.embedded" = "Osadzony"; +"configuration.cells.compression_framing.caption" = "Struktura"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algorytm"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Nieobsługiwane"; +"configuration.cells.reset_original.caption" = "Zresetuj konfigurację"; +"configuration.cells.client.caption" = "Certyfikat klienta"; +"configuration.cells.client.value.enabled" = "Zweryfikowany"; +"configuration.cells.client.value.disabled" = "Niezweryfikowany"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Uwierzytelnienie"; +"configuration.cells.tls_wrapping.value.crypt" = "Szyfrowanie"; +"configuration.cells.eku.caption" = "Rozszerzona weryfikacja"; +"configuration.cells.keep_alive.caption" = "Utrzymuj połączenie"; +"configuration.cells.keep_alive.value.seconds" = "%d sekund"; +"configuration.cells.renegotiation_seconds.caption" = "Ponowna negocjacja"; +"configuration.cells.renegotiation_seconds.value.after" = "po %@"; +"configuration.cells.random_endpoint.caption" = "Losowy host końcowy"; + +"network_settings.gateway.title" = "Domyślna brama sieciowa"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domena"; +"network_settings.proxy.title" = "Proxy"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; + +"server_network.cells.route.caption" = "Trasowanie"; + +"debug_log.buttons.previous" = "Poprzedni"; +"debug_log.buttons.next" = "Następny"; +"debug_log.alerts.empty_log.message" = "Rejestr debugowania jest pusty."; + +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Dane komórkowe"; +"shortcuts.add.cells.connect.caption" = "Połącz z"; +"shortcuts.add.cells.enable_vpn.caption" = "Włącz VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Wyłącz VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Zaufaj obecnie połączonej sieci Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Przestań ufać obecnie połączonej sieci Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "Ufaj danym komórkowym"; +"shortcuts.add.cells.untrust_cellular.caption" = "Przestań ufać danym komórkowym"; +"shortcuts.add.alerts.no_profiles.message" = "Brak wybranego profilu połączenia."; + +"shortcuts.edit.sections.all.header" = "Istniejące skróty"; + +"donation.title" = "Dotacja"; +"donation.sections.one_time.header" = "Jeden raz"; +"donation.sections.one_time.footer" = "Jeśli chcesz docenić moją pracę, poniżej znajdziesz kilka kwot do wyboru dotacji.\n\nTwoje konto zostanie obciążone tylko raz na jedną dotację, możesz wysłać dotację kilka razy."; +"donation.cells.loading.caption" = "Ładowanie dotacji"; +"donation.cells.purchasing.caption" = "Wykonywanie dotacji"; +"donation.alerts.purchase.success.title" = "Dziękuję"; +"donation.alerts.purchase.success.message" = "To dla mnie dużo znaczy, mam nadzięję że będziesz używać aplikacji i przyczynisz się do jej rozpowrzechnienia."; +"donation.alerts.purchase.failure.message" = "Nie można dokonać dotacji. %@"; + +"about.title" = "O programie"; +"about.sections.web.header" = "Strona WWW"; +"about.sections.share.header" = "Udostępnij"; +"about.cells.credits.caption" = "Twórcy"; +"about.cells.website.caption" = "Strona domowa"; +"about.cells.faq.caption" = "Pytania i odpowiedzi"; +"about.cells.disclaimer.caption" = "Disclaimer"; +"about.cells.privacy_policy.caption" = "Polityka prywatności"; +"about.cells.share_twitter.caption" = "Wyślij tweeta!"; +"about.cells.share_generic.caption" = "Zaproś znajomego"; + +"version.title" = "Wersja"; +"version.labels.intro" = "Passepartout i TunnelKit są stworzone i utrzymywane przez Davide De Rosa (keeshux).\n\nKod źródłowy Passepartout i TunnelKit jest publicznie dostępny na licencji GPLv3, linki możesz znaleźć na stronie domowej.\n\nPassepartout nie jest oficjanlnym klientem i nie jest powiązany z OpenVPN Inc."; + +"credits.title" = "Twórcy"; +"credits.sections.licenses.header" = "Licencje"; +"credits.sections.notices.header" = "Dodatki"; +"credits.sections.translations.header" = "Tłumaczenia"; + +"label.license.error" = "Nie udało się pobrać danych licencyjnych."; +"service.cells.use_profile.caption" = "Używaj tego profilu"; diff --git a/Passepartout/Core/Resources/pl.lproj/Intents.strings b/Passepartout/Core/Resources/pl.lproj/Intents.strings new file mode 100644 index 00000000..a364221a --- /dev/null +++ b/Passepartout/Core/Resources/pl.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Usuwa dane komórkowe z zaufanych sieci"; + +"IeGsEq" = "Wyłącz VPN"; +"1ZRTCZ" = "Wyłącz VPN"; + +"66bZBE" = "Z usługodawcą ${providerId}"; + +"7eoAss" = "Usuwa obecnie połączoną sieć Wi-Fi z zaufanych sieci"; + +"9GpJt5" = "Dodaje dane komórkowe do zaufanych sieci"; + +"BKxs8X" = "Dodaje obecnie połączoną sieć Wi-Fi do zaufanych sieci"; + +"NWWgCl" = "Ufaj danym komórkowym"; +"H4taev" = "Ufaj danym komórkowym"; + +"KjkCfU" = "Łączy z wybraną lokalizacją profilu usługodawcy"; + +"LA99yM" = "Połącz z VPN"; + +"U6o81V" = "Połącz z ${profileTitle}"; + +"WnTPFg" = "Połącz z ${poolName}"; + +"eQ1yzr" = "Wyłącza VPN"; + +"eXXb2z" = "Łączy z profilem hosta"; + +"yesvFP" = "Włącz VPN"; +"lQ6ziK" = "Włącz VPN"; + +"POyDPM" = "Zaufaj obecnie połączonej sieci Wi-Fi"; +"m2E7SI" = "Zaufaj obecnie połączonej sieci Wi-Fi"; + +"qo3Szz" = "Połącz z lokalizacją usługodawcy"; + +"0Wu9nb" = "Nie ufaj obecnie połączonej sieci Wi-Fi"; +"rd1T8p" = "Nie ufaj obecnie połączonej sieci Wi-Fi"; + +"ggzKA2" = "Nie ufaj danym komórkowym"; +"wB1iYX" = "Nie ufaj danym komórkowym"; + +"xY97Vu" = "Włącza VPN używając wybranego obecnie profilu"; + +"NCoK9B" = "Z profilem w użyciu"; diff --git a/Passepartout/Core/Resources/pt.lproj/Core.strings b/Passepartout/Core/Resources/pt.lproj/Core.strings new file mode 100644 index 00000000..9ede871f --- /dev/null +++ b/Passepartout/Core/Resources/pt.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Cancelar"; +"global.next" = "Próximo"; +"global.close" = "Fechar"; +"global.host.title_input.message" = "Caracteres aceitos são alfanuméricos, mais traço \"-\", underline \"_\" e ponto \".\"."; +"global.host.title_input.placeholder" = "Meu perfil"; +"global.email_not_configured" = "Nenhuma conta de email configurada."; +"global.values.enabled" = "Ativado"; +"global.values.disabled" = "Desativado"; +"global.values.none" = "Nenhum"; +"global.values.automatic" = "Automático"; +"global.values.manual" = "Manual"; +"reddit.title" = "Reddit"; +"reddit.message" = "Você sabia que Passepartout tem um subreddit? Siga-nos para atualizações ou para discutir problemas, novas funcionalidades, ou qualquer outro tópico.\n\nÉ uma boa maneira de mostrar seu interesse pelo projeto."; +"reddit.buttons.subscribe" = "Seguir!"; +"reddit.buttons.remind" = "Lembrar-me depois"; +"reddit.buttons.never" = "Não perguntar novamente"; +"organizer.sections.providers.header" = "Provedores"; +"organizer.sections.providers.footer" = "Aqui você encontra um provedor com o perfil pré-configurado."; +"organizer.sections.hosts.header" = "Hosts"; +"organizer.sections.hosts.footer" = "Importar hosts de um arquivo de configuração .ovpn."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Peça ajuda para Siri para agilar tarefas comum do aplicativo."; +"organizer.sections.support.header" = "Suporte"; +"organizer.sections.feedback.header" = "Feedback"; +"organizer.cells.siri_shortcuts.caption" = "Gerenciar atalhos"; +"organizer.cells.join_community.caption" = "Participar da comunidade"; +"organizer.cells.write_review.caption" = "Escrever avaliação"; +"organizer.cells.donate.caption" = "Fazer doação"; +"organizer.cells.github_sponsors.caption" = "Contribuir no GitHub"; +"organizer.cells.translate.caption" = "Ajudar-nos na tradução"; +"organizer.cells.about.caption" = "Sobre %@"; +"organizer.cells.uninstall.caption" = "Remover configuração VPN"; +"organizer.alerts.exhausted_providers.message" = "Você criou um perfil para qualquer provedor disponível."; +"organizer.alerts.add_host.message" = "Abre uma URL para um arquivo de configuração .ovpn no Safari, Mail ou outro aplicativo.\n\nVocê pode também importar um .ovpn com o compartilhamento de arquivos do iTunes."; +"organizer.alerts.cannot_donate.message" = "Nenhum meio de pagamento configurado nesse dispositivo."; +"organizer.alerts.delete_vpn_profile.message" = "Tem certeza que deseja remover as configurações de VPN do seu dispositivo? Isso poderá corrigir problemas com o estado atual, sem afetar seu provedor e perfis do host."; +"wizards.host.alerts.existing.message" = "Já existe um perfil com esse nome, deseja substituí-lo?"; +"parsed_file.alerts.malformed.message" = "O arquivo de configuração possui uma opção não formatada corretamente (%@)."; +"parsed_file.alerts.missing.message" = "O arquivo não possui todas configurações requeridas (%@)."; +"parsed_file.alerts.unsupported.message" = "O arquivo de configuração possui uma opção não suportada (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "O arquivo de configuração está correto, mas provavelmente possui uma opção não suportada (%@).\n\nSua conexão poderá ser instável dependendo as configurações do servidor."; +"parsed_file.alerts.encryption_passphrase.message" = "Por favor, digite sua senha de criptografia."; +"parsed_file.alerts.decryption.message" = "Sua configiração possui uma chave privada criptografada que talvez não possa ser descriptografada. Verifique novamente sua senha de criptografia."; +"parsed_file.alerts.parsing.message" = "Não foi possível processar as configurações do arquivo (%@)."; +"parsed_file.alerts.buttons.report" = "Reportar problema"; +"service.sections.vpn.footer" = "A conexão será estabelecida assim que necessária."; +"service.sections.provider_infrastructure.footer" = "Última atualização em %@."; +"service.sections.vpn_survives_sleep.footer" = "Desative para melhorar o consumo de bateria, o que poderá ocasionar queda de performance quando o restabelecimento de conexão for realizado."; +"service.sections.vpn_resolves_hostname.footer" = "Recomendado para maioria das redes e requirido em algumas redes IPv6. Desative se o DNS estiver bloqueado, ou para acelerar o DNS quando o mesmo está devagar."; +"service.sections.trusted.header" = "Redes seguras"; +"service.sections.trusted.footer" = "Ao entrar em uma rede segura, a VPN é normalmente é desconectada e mantido inativa. Desative essa opção para não forçar esse comportamento."; +"service.sections.diagnostics.header" = "Diagnóstico"; +"service.sections.diagnostics.footer" = "O status será escondido após reconectado. Os dados da rede são hostnames, endereços de IP, rotas, SSID. Credenciais e chaves privadas não será logadas em nenhum dos casos."; +"service.cells.connection_status.caption" = "Status"; +"account.title" = "Conta"; +"endpoint.title" = "Endereço"; +"service.cells.provider.pool.caption" = "Localização"; +"service.cells.provider.preset.caption" = "Pré-definição"; +"network_settings.title" = "Configurações de rede"; +"service.cells.vpn_survives_sleep.caption" = "Manter ativo em modo descanço"; +"service.cells.vpn_resolves_hostname.caption" = "Resolver hostname do servidor"; +"service.cells.trusted_mobile.caption" = "Rede celular"; +"service.cells.trusted_policy.caption" = "Trust disables VPN"; +"service.cells.test_connectivity.caption" = "Testar conexão"; +"service.cells.data_count.caption" = "Dados transferidos"; +"service.cells.data_count.none" = "Indisponível"; +"service.cells.debug_log.caption" = "Log de Debug"; +"service.cells.masks_private_data.caption" = "Esconder dados da rede"; +"service.cells.reconnect.caption" = "Reconectar"; +"service.cells.report_issue.caption" = "Reportar problemas de conexão"; +"service.alerts.rename.title" = "Renomear perfil"; +"service.alerts.credentials_needed.message" = "Primeiramente você precisa preencher suas credenciais."; +"service.alerts.reconnect_vpn.message" = "Deseja reconectar à VPN?"; +"service.alerts.trusted.no_network.message" = "Você não está conectado em nenhuma rede Wi-Fi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Ao confiar nessa rede, sua VPN provavelmente será desconectada. Deseja continuar?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Ao alterar a política de segurança, sua VPN provavelmente será desconectada. Deseja continuar?"; +"service.alerts.test_connectivity.title" = "Conectividade"; +"service.alerts.test_connectivity.messages.success" = "Seu dispositivo está conectado à Internet!"; +"service.alerts.test_connectivity.messages.failure" = "Seu dispositivo não está conectado à Internet, por favor, verifique sua configurações."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Para garantir uma restauração segura do seu log de debug, você precisa reconectar à VPN."; +"service.alerts.buttons.reconnect" = "Reconectar"; +"service.alerts.download.title" = "Download requirido"; +"service.alerts.download.message" = "%@ requer o download de arquivos de configuração adicionais.\n\nConfirme para iniciar."; +"service.alerts.download.failed" = "Erro no download do arquivo de configuração. %@"; +"service.alerts.download.hud.extracting" = "Extraindo arquivos, seja paciente..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Utilize %@ credenciais do site."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Utilize %@ credenciais do site. Seu usuário é normalmente numérico (sem espaços)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Utilize %@ credenciais do site. Seu usuário é normalmente o seu email."; +"account.sections.guidance.footer.infrastructure.pia" = "Utilize %@ credenciais do site. Seu usuário é normalmente numérico com prefixo \"p\"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Encontre %@ credenciais na sessão \"Account > OpenVPN / IKEv2 Username\" do site."; +"account.sections.guidance.footer.infrastructure.torguard" = "Utilize suas credenciais de serviço %@, que podem diferir das credenciais do site."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Utilize %@ credenciais do site. Seu usuário é normalmente o seu email."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Utilize %@ credenciais do site. Seu usuário é normalmente o seu email."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Encontre %@ credenciais no gerador de configuração OpenVPN do site."; +"account.sections.registration.footer" = "Registrar em %@ website."; +"account.cells.username.caption" = "Usuário"; +"account.cells.username.placeholder" = "usuário"; +"account.cells.password.caption" = "Senha"; +"account.cells.password.placeholder" = "senha secreta"; +"account.cells.open_guide.caption" = "Ver sua credenciais"; +"account.cells.signup.caption" = "Registrar com %@"; +"endpoint.cells.any_address.caption" = "Automático"; +"endpoint.cells.any_protocol.caption" = "Automático"; +"configuration.sections.communication.header" = "Comunicação"; +"configuration.sections.reset.footer" = "Se você foi desconectado após mudar parâmetros de comunicação, toque para restaurar a configuração original."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Compressão"; +"configuration.sections.network.header" = "Rede"; +"configuration.sections.other.header" = "Outro"; +"configuration.cells.cipher.caption" = "Criptografada"; +"configuration.cells.digest.caption" = "Autenticação"; +"configuration.cells.digest.value.embedded" = "Agregado"; +"configuration.cells.reset_original.caption" = "Restaurar configuração"; +"configuration.cells.client.caption" = "Certificado do cliente"; +"configuration.cells.client.value.enabled" = "Verificado"; +"configuration.cells.client.value.disabled" = "Não verificado"; +"configuration.cells.tls_wrapping.caption" = "Wrapping"; +"configuration.cells.tls_wrapping.value.auth" = "Autenticação"; +"configuration.cells.tls_wrapping.value.crypt" = "Criptografia"; +"configuration.cells.eku.caption" = "Verificação extendida"; +"network_settings.gateway.title" = "Gateway padrão"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domínio"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Framing"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algorítimo"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Não suportado"; +"configuration.cells.keep_alive.caption" = "Manter ativo"; +"configuration.cells.keep_alive.value.seconds" = "%d segundos"; +"configuration.cells.renegotiation_seconds.caption" = "Renegociando"; +"configuration.cells.renegotiation_seconds.value.after" = "depois de %@"; +"configuration.cells.random_endpoint.caption" = "Destino randômico"; +"network_choice.client" = "Ler .ovpn"; +"network_choice.server" = "Puxar do servidor"; +"global.captions.address" = "Endereço"; +"global.captions.port" = "Porta"; +"debug_log.buttons.previous" = "Anterior"; +"debug_log.buttons.next" = "Próximo"; +"debug_log.alerts.empty_log.message" = "O log está vazio."; +"vpn.connecting" = "Conectando"; +"vpn.active" = "Ativa"; +"vpn.disconnecting" = "Desconectando"; +"vpn.inactive" = "Inativo"; +"vpn.disabled" = "Desativado"; +"vpn.errors.timeout" = "Timeout"; +"vpn.errors.dns" = "Falha no DNS"; +"vpn.errors.auth" = "Falha na autenticação"; +"vpn.errors.tls" = "Falha no TLS"; +"vpn.errors.encryption" = "Falha na criptografia"; +"vpn.errors.compression" = "Compressão não suportada"; +"vpn.errors.network" = "Rede alterada"; +"vpn.errors.routing" = "Rota necessária"; +"vpn.errors.gateway" = "Sem gateway"; +"vpn.errors.shutdown" = "Servidor desligado"; +"issue_reporter.title" = "Reportar problema"; +"issue_reporter.message" = "O log de suas últimas conexões é crucial para resolver problemas de conectividade e é completamemnte anônimo.\n\nO arquivo de conexão .ovpn, se existente, é anexado sem nenhum dado sensitivo.\n\nPor favor, verique o anexos de email se necessário."; +"issue_reporter.buttons.accept" = "Eu concordo"; +"translations.title" = "Traduções"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Celular"; +"shortcuts.add.cells.connect.caption" = "Conectar à"; +"shortcuts.add.cells.enable_vpn.caption" = "Ativar VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Desativar VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Confiar na Wi-Fi atual"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Não confiar na Wi-Fi atual"; +"shortcuts.add.cells.trust_cellular.caption" = "Confiar em rede celular"; +"shortcuts.add.cells.untrust_cellular.caption" = "Não confiar em rede celular"; +"shortcuts.add.alerts.no_profiles.message" = "Ainda não existe nenhum perfil para se conectar."; +"shortcuts.edit.sections.all.header" = "Atalhos existentes"; +"about.title" = "Sobre"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Compartilhar"; +"about.cells.credits.caption" = "Créditos"; +"about.cells.website.caption" = "Home page"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Disclaimer"; +"about.cells.privacy_policy.caption" = "Política de privacidade"; +"about.cells.share_twitter.caption" = "Tweet sobre isso!"; +"about.cells.share_generic.caption" = "Convide um amigo"; +"donation.title" = "Doar"; +"donation.sections.one_time.header" = "Uma vez"; +"donation.sections.one_time.footer" = "Se você deseja mostrar gratidão pelo meu trabalho, aqui estão alguns valores do qual você pode contribuir.\n\nVocé só será cobrado uma única vez, ou doar mais vezes caso desejar."; +"donation.cells.loading.caption" = "Carregando doações"; +"donation.cells.purchasing.caption" = "Efetuando doação"; +"donation.alerts.purchase.success.title" = "Obrigado"; +"donation.alerts.purchase.success.message" = "Isso significa muito para mim! Espero que você continue usando e promovendo esse aplicativo."; +"donation.alerts.purchase.failure.message" = "Não foi possível realizar doação. %@"; +"share.message" = "Passepartout é um cliente OpenVPN fácil e open-source para iOS e macOS"; +"version.title" = "Versão"; +"version.labels.intro" = "Passepartout e TunnelKit são desenvolvidos e mantidos por Davide De Rosa (keeshux).\n\nO código de fonte está disponível no GitHub sobre a licença GPLv3, você pode encontrar links na home page.\n\nPassepartout não é um cliente oficial e não possui nenhuma ligação com a OpenVPN Inc."; +"credits.title" = "Créditos"; +"credits.sections.licenses.header" = "Licenças"; +"credits.sections.notices.header" = "Notices"; +"credits.sections.translations.header" = "Traduções"; +"label.license.error" = "Não foi possível realizar o download da licença."; +"organizer.cells.profile.value.current" = "Ativo"; +"service.welcome.message" = "Bem-vindo ao Passepartout!\n\nUse o organizador para adicionar um novo perfil."; +"service.cells.server_configuration.caption" = "Configuração do servidor"; +"service.cells.server_network.caption" = "Rede do servidor"; +"service.alerts.configuration.disconnected" = "Configuração indisponível, verifique se você está conectado em uma VPN."; +"server_network.cells.route.caption" = "Rota"; +"wizards.provider.cells.update_list.caption" = "Atualizar lista"; +"wizards.provider.alerts.unavailable.message" = "Não foi possível baixar a infraestrutura do provedor, tente novamente mais tarde."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Venha me ver fazer o Passepartout ao vivo no Twitch, entre no chat para interagir e contribuir!"; +"organizer.cells.follow_twitch.caption" = "Assistir Passepartout no Twitch"; +"service.cells.use_profile.caption" = "Usar esse perfil"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/pt.lproj/Intents.strings b/Passepartout/Core/Resources/pt.lproj/Intents.strings new file mode 100644 index 00000000..c8375784 --- /dev/null +++ b/Passepartout/Core/Resources/pt.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Remover celular de conexões seguras"; + +"IeGsEq" = "Desativar VPN"; +"1ZRTCZ" = "Desativar VPN"; + +"66bZBE" = "Com o provedor ${providerId}"; + +"7eoAss" = "Remover Wi-Fi atual de conexões seguras"; + +"9GpJt5" = "Adicionar celular em conexões seguras"; + +"BKxs8X" = "Adicionar Wi-Fi atual em conexões seguras"; + +"NWWgCl" = "Confiar em rede celular"; +"H4taev" = "Confiar em rede celular"; + +"KjkCfU" = "Conectar em uma localização específica de um provedor"; + +"LA99yM" = "Conectar VPN"; + +"U6o81V" = "Conectar ${profileTitle}"; + +"WnTPFg" = "Conectar ${poolName}"; + +"eQ1yzr" = "Desabilitar serviço de VPN"; + +"eXXb2z" = "Conectar em um host"; + +"yesvFP" = "Ativar VPN"; +"lQ6ziK" = "Ativar VPN"; + +"POyDPM" = "Confiar na Wi-Fi atual"; +"m2E7SI" = "Confiar na Wi-Fi atual"; + +"qo3Szz" = "Conectar em uma região do provedor"; + +"0Wu9nb" = "Não confiar na Wi-Fi atual"; +"rd1T8p" = "Não confiar na Wi-Fi atual"; + +"ggzKA2" = "Não confiar na conexão celular"; +"wB1iYX" = "Não confiar na conexão celular"; + +"xY97Vu" = "Ativar o serviço VPN no perfil em uso"; + +"NCoK9B" = "Com o perfil em uso"; diff --git a/Passepartout/Core/Resources/ru.lproj/Core.strings b/Passepartout/Core/Resources/ru.lproj/Core.strings new file mode 100644 index 00000000..091c378e --- /dev/null +++ b/Passepartout/Core/Resources/ru.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 4/23/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "Ок"; +"global.cancel" = "Отменить"; +"global.next" = "Далее"; +"global.close" = "Закрыть"; +"global.host.title_input.message" = "Разрешены буквы латиницы, дэш \"-\", нижнее подчеркивание \"_\" и точка \".\"."; +"global.host.title_input.placeholder" = "Мой профиль"; +"global.email_not_configured" = "E-mail аккаунт не создан."; +"global.values.enabled" = "Включен"; +"global.values.disabled" = "Выключен"; +"global.values.none" = "Нет"; +"global.values.automatic" = "Автоматически"; +"global.values.manual" = "Вручную"; +"reddit.title" = "Reddit"; +"reddit.message" = "А Вы знали, что Passepartout имеет свой сабреддит? Подписывайтесь для получения обновлений, обсуждения проблем, функций, новых платформ или чего угодно.\n\nЭто также отличный способ показать поддержку проекта."; +"reddit.buttons.subscribe" = "Подписаться сейчас!"; +"reddit.buttons.remind" = "Напомнить позже"; +"reddit.buttons.never" = "Больше не спрашивать"; +"organizer.sections.providers.header" = "Провайдеры"; +"organizer.sections.providers.footer" = "Здесь Вы найдёте несколько провайдеров с уже созданными профилями."; +"organizer.sections.hosts.header" = "Хосты|Hosts"; +"organizer.sections.hosts.footer" = "Импорт хостов из .ovpn файлов"; +"organizer.sections.siri.header" = "Сири"; +"organizer.sections.siri.footer" = "Получить помощь Сири, чтобы ускорить частые действия с приложением."; +"organizer.sections.support.header" = "Поддержка"; +"organizer.sections.feedback.header" = "Отзыв"; +"organizer.cells.siri_shortcuts.caption" = "Управлять коммандами"; +"organizer.cells.join_community.caption" = "Вступить в сообщество"; +"organizer.cells.write_review.caption" = "Написать отзыв"; +"organizer.cells.donate.caption" = "Сделать пожертвование"; +"organizer.cells.github_sponsors.caption" = "Поддержите меня на GitHub"; +"organizer.cells.translate.caption" = "Помощь с переводом"; +"organizer.cells.about.caption" = "Об %@"; +"organizer.cells.uninstall.caption" = "Удалить VPN конфигурацию"; +"organizer.alerts.exhausted_providers.message" = "Вы создали профили для всех доступных провайдеров."; +"organizer.alerts.add_host.message" = "Откройте ссылку на .ovpn файл конфигурации через Safari, Почту или другое приложение для добавление хост профиля.\n\nВы также можете импортировать .ovpn файл через общие файлы iTunes."; +"organizer.alerts.cannot_donate.message" = "На этом усторйстве не выбран способ платежа."; +"organizer.alerts.delete_vpn_profile.message" = "Вы действительно хотите убрать VPN конфигурацию из настроек устройства? Это может исправить несколько VPN ошибок, но не изменит установки приложения."; +"wizards.host.alerts.existing.message" = "Хост профиль с этим названием уже существует. Заменить?"; +"parsed_file.alerts.malformed.message" = "Файл конфигурации содержит неверную опцию (%@)."; +"parsed_file.alerts.missing.message" = "Файл конфигурации не содержит необходимую опцию (%@)."; +"parsed_file.alerts.unsupported.message" = "Файл конфигурации содержит неподдерживаемую опцию (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Файл конфигурации верный, но возможно содержит неподдерживаемую опцию (%@).\n\nСоединение может прерваться - зависит от настроек сервера."; +"parsed_file.alerts.encryption_passphrase.message" = "Пожалуйста, введите кодовую фразу шифрования"; +"parsed_file.alerts.decryption.message" = "Конфигурация содержит зашифрованный приватный ключ, он не может быть расшифрован. Перепроверьте кодовую фразу."; +"parsed_file.alerts.parsing.message" = "Не получается разобрать предоставленный файл конфигурации (%@)."; +"parsed_file.alerts.buttons.report" = "Сообщить о проблеме"; +"service.sections.vpn.footer" = "Соединение будет установлено при необходимости."; +"service.sections.provider_infrastructure.footer" = "Последнее обновление %@."; +"service.sections.vpn_survives_sleep.footer" = "Отключите для уменьшения расхода заряда аккумулятора, может привести к временным замедлениям в связи с повторным подключением после \"пробуждения\"."; +"service.sections.vpn_resolves_hostname.footer" = "Предпочтительно в большинстве сетей и необходимо в некоторых IPv6 сетях. Отключите если  DNS заблокирован, или для увеличения скорости в случае медленных ответов DNS."; +"service.sections.trusted.header" = "Доверенные сети"; +"service.sections.trusted.footer" = "При подключении к доверенным сетям VPN обычно выключается, и остаётся отключенным. Отключите эту опцию чтобы оставлять VPN подключенным."; +"service.sections.diagnostics.header" = "Диагностика"; +"service.sections.diagnostics.footer" = "Маскировка включится после повторного подключения. Информация о сети - это названия хост профилей, IP адрес, маршрутизация и SSID. Данные для входа и приватные ключи не собираются."; +"service.cells.connection_status.caption" = "Статус"; +"account.title" = "Аккаунт"; +"endpoint.title" = "Конечная точка"; +"service.cells.provider.pool.caption" = "Местоположение"; +"service.cells.provider.preset.caption" = "Пресет"; +"network_settings.title" = "Сетевые настройки"; +"service.cells.vpn_survives_sleep.caption" = "Оставлять включенным во время сна"; +"service.cells.vpn_resolves_hostname.caption" = "Разрешить имя хоста сервера"; +"service.cells.trusted_mobile.caption" = "Мобильная сеть"; +"service.cells.trusted_policy.caption" = "Дов. сеть отключает VPN"; +"service.cells.test_connectivity.caption" = "Проверить подключение"; +"service.cells.data_count.caption" = "Переданная информация"; +"service.cells.data_count.none" = "Недоступно"; +"service.cells.debug_log.caption" = "Журнал отладки"; +"service.cells.masks_private_data.caption" = "Маскировать информацию сети"; +"service.cells.reconnect.caption" = "Переподключиться"; +"service.cells.report_issue.caption" = "Сообщить о проблеме подкл."; +"service.alerts.rename.title" = "Переименовать профиль"; +"service.alerts.credentials_needed.message" = "Сначала нужно ввести данные аккаунта."; +"service.alerts.reconnect_vpn.message" = "Хотите заново подключиться к VPN?"; +"service.alerts.trusted.no_network.message" = "Вы не подключены к Wi-Fi."; +"service.alerts.trusted.will_disconnect_trusted.message" = "При доверии этой сети VPN может быть отключен. Продолжить?"; +"service.alerts.trusted.will_disconnect_policy.message" = "При изменении установок доверия VPN может быть отключен. Продолжить?"; +"service.alerts.test_connectivity.title" = "Связь"; +"service.alerts.test_connectivity.messages.success" = "Ваше устройство подключено к интернету!"; +"service.alerts.test_connectivity.messages.failure" = "Ваше устройство не подключено к интернету, пожалйста проверьте установки Вашего профиля."; +"service.alerts.masks_private_data.messages.must_reconnect" = "Для безопасного сброса журнала отладки и изменения маскировки информации сети Вы должны заново подключиться к VPN."; +"service.alerts.buttons.reconnect" = "Переподключить"; +"service.alerts.download.title" = "Необходимо скачивание"; +"service.alerts.download.message" = "%@ необходимы дополнительные файлы конфигурации.\n\nПодтвердите для скачивания."; +"service.alerts.download.failed" = "Не удалось скачать файлы конфигурации.%@"; +"service.alerts.download.hud.extracting" = "Извлечение файлов, пожалуста подождите..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Используйте Ваши данные для входа с веб-сайта %@."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Используйте Ваши данные для входа с веб-сайта %@. Ваш логин обычно числовой с (без пробелов)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Используйте данные для входа на %@ веб-сайт. Ваш логин обычно Ваш e-mail."; +"account.sections.guidance.footer.infrastructure.pia" = "Используйте Ваши данные для входа с веб-сайта %@. Ваш логин обычно числовой с приставкой \"p\"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Найдите Ваши данные для входа %@ \"Account > OpenVPN / IKEv2 Username\" секции веб-сайта."; +"account.sections.guidance.footer.infrastructure.torguard" = "Используйте свои учетные данные %@ service, которые могут отличаться от учетных данных веб-сайта."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Используйте данные для входа на %@ веб-сайт. Ваш логин обычно Ваш e-mail."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Используйте данные для входа на %@ веб-сайт. Ваш логин обычно Ваш e-mail."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Найдите Ваши данные для входа %@ в OpenVPN Config Generator на веб-сайте."; +"account.sections.registration.footer" = "Создайте аккаунт на %@ веб-сайте."; +"account.cells.username.caption" = "Логин"; +"account.cells.username.placeholder" = "логин"; +"account.cells.password.caption" = "Пароль"; +"account.cells.password.placeholder" = "пароль"; +"account.cells.open_guide.caption" = "Проверьте Ваши данные"; +"account.cells.signup.caption" = "Зарегистрируйтесь с %@"; +"endpoint.cells.any_address.caption" = "Автоматически"; +"endpoint.cells.any_protocol.caption" = "Автоматически"; +"configuration.sections.communication.header" = "Связь"; +"configuration.sections.reset.footer" = "Если после изменения параметров связи у Вас разорвалось соединение, нажмите, чтобы вернуться к исходной конфигурации."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Компресия"; +"configuration.sections.network.header" = "Сеть"; +"configuration.sections.other.header" = "Другое"; +"configuration.cells.cipher.caption" = "Шифруем"; +"configuration.cells.digest.caption" = "Аутентификация"; +"configuration.cells.digest.value.embedded" = "Внедрена"; +"configuration.cells.reset_original.caption" = "Сброс конфигурации"; +"configuration.cells.client.caption" = "Сертификат клиента"; +"configuration.cells.client.value.enabled" = "Проверено"; +"configuration.cells.client.value.disabled" = "Не проверено"; +"configuration.cells.tls_wrapping.caption" = "Упаковываем"; +"configuration.cells.tls_wrapping.value.auth" = "Аутентификация"; +"configuration.cells.tls_wrapping.value.crypt" = "Шифрование"; +"configuration.cells.eku.caption" = "Расширенная проверка"; +"network_settings.gateway.title" = "Шлюз по умолчанию"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Домен"; +"network_settings.proxy.title" = "Прокси"; +"configuration.cells.proxy_https.caption" = "Прокси (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Фрейминг"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Алгоритм"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Неподдерживаемое"; +"configuration.cells.keep_alive.caption" = "Поддерживаем"; +"configuration.cells.keep_alive.value.seconds" = "%d секунд"; +"configuration.cells.renegotiation_seconds.caption" = "Перезаключение"; +"configuration.cells.renegotiation_seconds.value.after" = "после %@"; +"configuration.cells.random_endpoint.caption" = "Рандомная конечная точка"; +"network_choice.client" = "Читать .ovpn"; +"network_choice.server" = "Вытащить с сервера"; +"global.captions.address" = "Адрес"; +"global.captions.port" = "порт"; +"debug_log.buttons.previous" = "Предыдущий"; +"debug_log.buttons.next" = "Следующий"; +"debug_log.alerts.empty_log.message" = "Журнал отладки пуст."; +"vpn.connecting" = "Подключается"; +"vpn.active" = "Активен"; +"vpn.disconnecting" = "Отключается"; +"vpn.inactive" = "Не активен"; +"vpn.disabled" = "Отключен"; +"vpn.errors.timeout" = "Тайм-аут"; +"vpn.errors.dns" = "Ошибка DNS"; +"vpn.errors.auth" = "Ошибка аутентификации"; +"vpn.errors.tls" = "Ошибка TSL"; +"vpn.errors.encryption" = "Ошибка расшифровки"; +"vpn.errors.compression" = "Сжатие не поддерживается"; +"vpn.errors.network" = "Изменение сети"; +"vpn.errors.routing" = "Отсутствует маршрутизация"; +"vpn.errors.gateway" = "Нет шлюза"; +"vpn.errors.shutdown" = "Сервер выключен"; +"issue_reporter.title" = "Сообщить о проблеме"; +"issue_reporter.message" = "Журнал отладки Вашего последнего соединения необходим для разрешения проблем подключения, и является полностью анонимным.\n\n .ovpn файл, если есть, прикреплён без каких-либо конфиденциальных данных .\n\nПожалуйста, перепроверьте прикреплённые файлы, если не уверены."; +"issue_reporter.buttons.accept" = "Я понимаю"; +"translations.title" = "Переводы"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Мобильная сеть"; +"shortcuts.add.cells.connect.caption" = "Подключиться к"; +"shortcuts.add.cells.enable_vpn.caption" = "Включи VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Выключи VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Доверять текущему Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Не доверять текущему Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "Доверять мобильной сети"; +"shortcuts.add.cells.untrust_cellular.caption" = "Не доверять мобильной сети"; +"shortcuts.add.alerts.no_profiles.message" = "Нет профиля для подключения."; +"shortcuts.edit.sections.all.header" = "Существующие команды"; +"about.title" = "О нас"; +"about.sections.web.header" = "Веб"; +"about.sections.share.header" = "Поделиться"; +"about.cells.credits.caption" = "Благодарности"; +"about.cells.website.caption" = "Домашняя страница"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Предупреждение"; +"about.cells.privacy_policy.caption" = "Политика конфиденциальности"; +"about.cells.share_twitter.caption" = "Твитнуть о нас!"; +"about.cells.share_generic.caption" = "Пригласить друга"; +"donation.title" = "Пожертвовать"; +"donation.sections.one_time.header" = "Один раз"; +"donation.sections.one_time.footer" = "Если Вы хотите поблагодарить мою бесплатную работу, здесь есть несколько сумм, которые Вы можете пожертвовать прямо сейчас.\n\nСумма будет списана только один раз, а Вы можете пожертвовать несколько раз."; +"donation.cells.loading.caption" = "Загружаем пожертвования"; +"donation.cells.purchasing.caption" = "Исполняется"; +"donation.alerts.purchase.success.title" = "Спасибо"; +"donation.alerts.purchase.success.message" = "Это значит многое для меня, и, я надеюсь, Вы продолжить использовать и рассказывать об этом приложении."; +"donation.alerts.purchase.failure.message" = "Не получается совершить пожертвование. %@"; +"share.message" = "Passepartout - это простой в использовании OpenVPN клиент для iOS и macOS, с открытым исходным кодом"; +"version.title" = "Версия"; +"version.labels.intro" = "Passepartout и TunnelKit написаны и установлены Davide De Rosa (keeshux).\n\nИсходные коды для Passepartout и TunnelKit публично доступны на GitHub под GPLv3, вы можете найти ссылки на домашней странице.\n\nPassepartout является неофициальным клиентом, и никаким образом не связан с OpenVPN Inc."; +"credits.title" = "Благодарность"; +"credits.sections.licenses.header" = "Лицензии"; +"credits.sections.notices.header" = "Упоминания"; +"credits.sections.translations.header" = "Переводы"; +"label.license.error" = "Не получается загрузить полную лицензию."; +"organizer.cells.profile.value.current" = "Используется"; +"service.welcome.message" = "Добро пожаловать в Passepartout!\n\nИспользуйте организатор для добавления нового профиля."; +"service.cells.server_configuration.caption" = "Конфигурация сервера"; +"service.cells.server_network.caption" = "Сеть сервера"; +"service.alerts.configuration.disconnected" = "Конфигурация недоступна, проверьте подключение к VPN."; +"server_network.cells.route.caption" = "Маршрут"; +"wizards.provider.cells.update_list.caption" = "Обновить список"; +"wizards.provider.alerts.unavailable.message" = "Не удалось загрузить инфраструктуру провайдера, повторите попытку позже."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Приходите посмотреть, как я делаю Passepartout в прямом эфире на Twitch, присоединяйтесь к чату, чтобы общаться и вносить свой вклад!"; +"organizer.cells.follow_twitch.caption" = "Смотрите Паспарту на Twitch"; +"service.cells.use_profile.caption" = "Использовать это профиль."; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "байты"; diff --git a/Passepartout/Core/Resources/ru.lproj/Intents.strings b/Passepartout/Core/Resources/ru.lproj/Intents.strings new file mode 100644 index 00000000..9b860a2c --- /dev/null +++ b/Passepartout/Core/Resources/ru.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Удаляет мобильную сеть из доверенных подключений"; + +"IeGsEq" = "Отключить VPN"; +"1ZRTCZ" = "Отключить VPN"; + +"66bZBE" = "С ${providerId} провайдером"; + +"7eoAss" = "Удаляет текущий Wi-Fi из доверенных подключений"; + +"9GpJt5" = "Добавляет мобильную сеть в доверенные подключения"; + +"BKxs8X" = "Добавляет текущий  Wi-Fi в доверенные подключения"; + +"NWWgCl" = "Доверять мобильной сети"; +"H4taev" = "Доверять мобильной сети"; + +"KjkCfU" = "Подключиться к конкретному местоположению провайдера"; + +"LA99yM" = "Подключиться к VPN"; + +"U6o81V" = "Подключиться к ${profileTitle}"; + +"WnTPFg" = "Подключиться к ${poolName}"; + +"eQ1yzr" = "Отключить этот VPN сервис"; + +"eXXb2z" = "Подключается к хост профилю"; + +"yesvFP" = "Включить VPN"; +"lQ6ziK" = "Включить VPN"; + +"POyDPM" = "Доверять текущему Wi-Fi"; +"m2E7SI" = "Доверять текущему Wi-Fi"; + +"qo3Szz" = "Подключиться к местоположению провайдера"; + +"0Wu9nb" = "Не доверять текущему Wi-Fi"; +"rd1T8p" = "Не доверять текущему Wi-Fi"; + +"ggzKA2" = "Не доверять мобильной сети"; +"wB1iYX" = "Не доверять мобильной сети"; + +"xY97Vu" = "Включает VPN с используемым профилем"; + +"NCoK9B" = "С используемым профилем"; diff --git a/Passepartout/Core/Resources/sv.lproj/Core.strings b/Passepartout/Core/Resources/sv.lproj/Core.strings new file mode 100644 index 00000000..fe64246c --- /dev/null +++ b/Passepartout/Core/Resources/sv.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "OK"; +"global.cancel" = "Avbryt"; +"global.next" = "Nästa"; +"global.close" = "Stäng"; +"global.host.title_input.message" = "Godtagbara tecken är alfanumeriska plus bindestreck \" - \", understrykning \" _ \"och punkt \". \"."; +"global.host.title_input.placeholder" = "Min profil"; +"global.email_not_configured" = "Inget e-postkonto är konfigurerat."; +"global.values.enabled" = "Aktiverad"; +"global.values.disabled" = "Inaktiverad"; +"global.values.none" = "Ingen"; +"global.values.automatic" = "Automatiskt"; +"global.values.manual" = "Manuellt"; +"reddit.title" = "Reddit"; +"reddit.message" = "Visste du att Passepartout har en subreddit? Prenumerera på uppdateringar eller diskutera problem, funktioner, nya plattformar eller vad du vill. \n\nDet är också ett bra sätt att visa dig bryr dig om detta projekt."; +"reddit.buttons.subscribe" = "Prenumerera nu!"; +"reddit.buttons.remind" = "Påminn mig senare"; +"reddit.buttons.never" = "Fråga inte igen"; +"organizer.sections.providers.header" = "Leverantörer"; +"organizer.sections.providers.footer" = "Här hittar du några leverantörer med förinställda konfigurationsprofiler."; +"organizer.sections.hosts.header" = "Värdar"; +"organizer.sections.hosts.footer" = "Importera värdar från .ovpn konfigurationsfiler."; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "Få hjälp från Siri för att påskynda dina vanligaste interaktioner med appen."; +"organizer.sections.support.header" = "Support"; +"organizer.sections.feedback.header" = "Feedback"; +"organizer.cells.siri_shortcuts.caption" = "Hantera genvägar"; +"organizer.cells.join_community.caption" = "Gå med i communityn"; +"organizer.cells.write_review.caption" = "Skriv en recension"; +"organizer.cells.donate.caption" = "Gör en donation"; +"organizer.cells.github_sponsors.caption" = "Stötta mig på GitHub"; +"organizer.cells.translate.caption" = "Erbjuda att översätta"; +"organizer.cells.about.caption" = "Om %@"; +"organizer.cells.uninstall.caption" = "Ta bort VPN-konfiguration"; +"organizer.alerts.exhausted_providers.message" = "Du har skapat profiler för alla tillgängliga leverantörer."; +"organizer.alerts.add_host.message" = "Öppna en URL till en .ovpn konfigurationsfil från Safari, Mail eller en annan app för att skapa en värdprofil. \n\nDu kan också importera en .ovpn med iTunes Fildelning." ; +"organizer.alerts.cannot_donate.message" = "Det finns ingen betalningsmetod konfigurerad på den här enheten."; +"organizer.alerts.delete_vpn_profile.message" = "Vill du verkligen radera VPN-konfigurationen från enhetens inställningar? Detta kan fixa några trasiga VPN tillstånd och påverkar inte dina leverantörs- och värdprofiler."; +"wizards.host.alerts.existing.message" = "En värdprofil med samma namn finns redan. Byt ut det?"; +"parsed_file.alerts.malformed.message" = "Konfigurationsfilen innehåller ett felaktigt val (%@)."; +"parsed_file.alerts.missing.message" = "Konfigurationsfilen saknar ett obligatoriskt val (%@)."; +"parsed_file.alerts.unsupported.message" = "Konfigurationsfilen innehåller ett stöd som inte stöds (%@)."; +"parsed_file.alerts.potentially_unsupported.message" = "Konfigurationsfilen är korrekt men innehåller ett eventuellt stöd som inte stöds (%@). \n\nConnectivity kan bryta beroende på serverinställningar."; +"parsed_file.alerts.encryption_passphrase.message" = "Var god ange krypteringslösenfrasen."; +"parsed_file.alerts.decryption.message" = "Konfigurationen innehåller en krypterad privat nyckel och den kan inte dekrypteras. Kontrollera din inmatade lösenfras."; +"parsed_file.alerts.parsing.message" = "Det gick inte att analysera den angivna konfigurationsfilen (%@)."; +"parsed_file.alerts.buttons.report" = "Rapportera ett problem"; +"service.sections.vpn.footer" = "Anslutningen kommer att upprättas vid behov."; +"service.sections.provider_infrastructure.footer" = "Senast uppdaterad på %@."; +"service.sections.vpn_survives_sleep.footer" = "Inaktivera för att förbättra batterianvändningen, på bekostnad av tillfälliga avmattningar på grund av återuppkoppling."; +"service.sections.vpn_resolves_hostname.footer" = "Föredragna i de flesta nätverk och krävs i vissa IPv6-nätverk. Inaktivera var DNS blockeras eller för att påskynda förhandlingar när DNS är långsamt att svara."; +"service.sections.trusted.header" = "Tillförlitliga nätverk"; +"service.sections.trusted.footer" = "När du advänder ett betrott nätverk, VPN:et stängs normalt och hålls bortkopplat. Avaktivera detta alternativet för att inte genomdriva sådant beteende."; +"service.sections.diagnostics.header" = "Diagnostics"; +"service.sections.diagnostics.footer" = "Masking status kommer att fungera efter återanslutning. Nätverksdata är värdnamn, IP-adresser, routing, SSID. Referenser och privata nycklar loggas inte oavsett."; +"service.cells.connection_status.caption" = "Status"; +"account.title" = "Konto"; +"endpoint.title" = "Slutpunkt"; +"service.cells.provider.pool.caption" = "Plats"; +"service.cells.provider.preset.caption" = "Förinställt"; +"network_settings.title" = "Nätverksinställningar"; +"service.cells.vpn_survives_sleep.caption" = "Håll dig levande i sömnen"; +"service.cells.vpn_resolves_hostname.caption" = "Lösa server värdnamn"; +"service.cells.trusted_mobile.caption" = "Mobilt nätverk"; +"service.cells.trusted_policy.caption" = "Förtroende inaktiverar VPN"; +"service.cells.test_connectivity.caption" = "Testanslutning"; +"service.cells.data_count.caption" = "Utbyttad data"; +"service.cells.data_count.none" = "Otillgänglig"; +"service.cells.debug_log.caption" = "Debug log"; +"service.cells.masks_private_data.caption" = "Mask nätverksdata"; +"service.cells.reconnect.caption" = "Återanslut"; +"service.cells.report_issue.caption" = "Rapportera anslutningsproblem"; +"service.alerts.rename.title" = "Byt namn på profil"; +"service.alerts.credentials_needed.message" = "Du måste ange kontouppgifterna först."; +"service.alerts.reconnect_vpn.message" = "Vill du återansluta till VPN?"; +"service.alerts.trusted.no_network.message" = "Du är inte ansluten till något Wi-Fi-nätverk."; +"service.alerts.trusted.will_disconnect_trusted.message" = "Genom att lita på detta nätverk kan VPN kopplas bort. Fortsätt?"; +"service.alerts.trusted.will_disconnect_policy.message" = "Genom att byta tillitspolicy kan VPN kopplas bort. Fortsätt?"; +"service.alerts.test_connectivity.title" = "Anslutningar"; +"service.alerts.test_connectivity.messages.success" = "Din enhet är ansluten till Internet!"; +"service.alerts.test_connectivity.messages.failure" = "Din enhet har ingen Internetanslutning, var god granska dina profilparametrar."; +"service.alerts.masks_private_data.messages.must_reconnect" = "För att säkert återställa den aktuella felsökningsloggen och tillämpa den nya maskeringspreferensen måste du återansluta till VPN nu."; +"service.alerts.buttons.reconnect" = "Reconnect"; +"service.alerts.download.title" = "Ladda ner krävs"; +"service.alerts.download.message" = "%@ kräver nedladdning av ytterligare konfigurationsfiler. \n\nKontrollera för att starta nedladdningen."; +"service.alerts.download.failed" = "Misslyckades med att ladda ner konfigurationsfiler. %@"; +"service.alerts.download.hud.extracting" = "Extraherar filer, var så tålmodig ..."; +"account.sections.guidance.footer.infrastructure.hideme" = "Använd dina %@ webbplatsuppgifter."; +"account.sections.guidance.footer.infrastructure.mullvad" = "Använd dina %@ webbplatsuppgifter. Ditt användarnamn är vanligtvis numeriskt (utan utrymmen)."; +"account.sections.guidance.footer.infrastructure.nordvpn" = "Använd dina %@ webbplatsuppgifter. Ditt användarnamn är vanligtvis ditt e-postmeddelande."; +"account.sections.guidance.footer.infrastructure.pia" = "Använd dina %@ webbplatsuppgifter. Ditt användarnamn är vanligtvis numeriskt med ett prefix för \" p \"."; +"account.sections.guidance.footer.infrastructure.protonvpn" = "Hitta dina %@ credentials i avsnittet \" Konto> OpenVPN / IKEv2 Användarnamn \"på webbplatsen."; +"account.sections.guidance.footer.infrastructure.torguard" = "Använd dina %@ service-referenser, som kan skilja sig från webbplatsens referenser."; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "Använd dina %@ webbplatsuppgifter. Ditt användarnamn är vanligtvis ditt e-postmeddelande."; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "Använd dina %@ webbplatsuppgifter. Ditt användarnamn är vanligtvis ditt e-postmeddelande."; +"account.sections.guidance.footer.infrastructure.windscribe" = "Hitta din %@ credentials i OpenVPN Config Generator på webbplatsen."; +"account.sections.registration.footer" = "Hämta ett konto på %@ webbplatsen."; +"account.cells.username.caption" = "Användarnamn"; +"account.cells.username.placeholder" = "användarnamn"; +"account.cells.password.caption" = "Lösenord"; +"account.cells.password.placeholder" = "hemlighet"; +"account.cells.open_guide.caption" = "Visa dina uppgifter"; +"account.cells.signup.caption" = "Registrera med %@"; +"endpoint.cells.any_address.caption" = "Automatiskt"; +"endpoint.cells.any_protocol.caption" = "Automatiskt"; +"configuration.sections.communication.header" = "Communication"; +"configuration.sections.reset.footer" = "Om du slutade med bruten anslutning efter att ha ändrat kommunikationsparametrarna trycker du på för att återgå till den ursprungliga konfigurationen."; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "Kompression"; +"configuration.sections.network.header" = "Nätverk"; +"configuration.sections.other.header" = "Other"; +"configuration.cells.cipher.caption" = "Cipher"; +"configuration.cells.digest.caption" = "Autentisering"; +"configuration.cells.digest.value.embedded" = "Inbäddad"; +"configuration.cells.reset_original.caption" = "Återställ konfiguration"; +"configuration.cells.client.caption" = "Klientcertifikat"; +"configuration.cells.client.value.enabled" = "Verified"; +"configuration.cells.client.value.disabled" = "Ej verifierad"; +"configuration.cells.tls_wrapping.caption" = "Omslagning"; +"configuration.cells.tls_wrapping.value.auth" = "Autentisering"; +"configuration.cells.tls_wrapping.value.crypt" = "Kryptering"; +"configuration.cells.eku.caption" = "Förlängd verifering"; +"network_settings.gateway.title" = "Normal gateway"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "Domain"; +"network_settings.proxy.title" = "Proxy"; +"configuration.cells.proxy_https.caption" = "Proxy (HTTPS)"; +"configuration.cells.compression_framing.caption" = "Inramning"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "Algoritm"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "Utan stöd"; +"configuration.cells.keep_alive.caption" = "hål-vid-liv"; +"configuration.cells.keep_alive.value.seconds" = "%d seconds"; +"configuration.cells.renegotiation_seconds.caption" = "Omförhandling"; +"configuration.cells.renegotiation_seconds.value.after" = "efter %@"; +"configuration.cells.random_endpoint.caption" = "Omställ slutpunkt på slumpmässigt sätt"; +"network_choice.client" = "Läs .ovpn"; +"network_choice.server" = "Dra från server"; +"global.captions.address" = "Adress"; +"global.captions.port" = "Port"; +"debug_log.buttons.previous" = "Previous"; +"debug_log.buttons.next" = "Next"; +"debug_log.alerts.empty_log.message" = "Felsökningsloggen är tom."; +"vpn.connecting" = "Anslutning"; +"vpn.active" = "Aktiv"; +"vpn.disconnecting" = "Koppla från"; +"vpn.inactive" = "Inaktiv"; +"vpn.disabled" = "Inaktiverad"; +"vpn.errors.timeout" = "Timeout"; +"vpn.errors.dns" = "DNS misslyckades"; +"vpn.errors.auth" = "Auth failed"; +"vpn.errors.tls" = "TLS misslyckades"; +"vpn.errors.encryption" = "Kryptering misslyckades"; +"vpn.errors.compression" = "Komprimering utan stöd"; +"vpn.errors.network" = "Nätverk ändrat"; +"vpn.errors.routing" = "Saknad routing"; +"vpn.errors.gateway" = "Ingen gateway"; +"vpn.errors.shutdown" = "Servern stängs av"; +"issue_reporter.title" = "Rapportera problem"; +"issue_reporter.message" = "Felsökningsloggen för dina senaste anslutningar är avgörande för att lösa dina anslutningsproblem och är helt anonym. \n\nHanteringsfilen .ovpn är eventuellt bifogad av någon känslig data. \n\nPresentera dubbelkolla e-postbilagorna om du är osäker. "; +"issue_reporter.buttons.accept" = "Jag förstår"; +"translations.title" = "Översättningar"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "Cellular"; +"shortcuts.add.cells.connect.caption" = "Anslut till"; +"shortcuts.add.cells.enable_vpn.caption" = "Aktivera VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "Inaktivera VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "Lita på nuvarande Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "Avaktivera nuvarande Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "Lita på mobilnätverk"; +"shortcuts.add.cells.untrust_cellular.caption" = "Untrust cellular network"; +"shortcuts.add.alerts.no_profiles.message" = "Det finns ingen profil att ansluta till."; +"shortcuts.edit.sections.all.header" = "Befintliga genvägar"; +"about.title" = "About"; +"about.sections.web.header" = "Web"; +"about.sections.share.header" = "Dela"; +"about.cells.credits.caption" = "Credits"; +"about.cells.website.caption" = "Hemsida"; +"about.cells.faq.caption" = "FAQ"; +"about.cells.disclaimer.caption" = "Disclaimer"; +"about.cells.privacy_policy.caption" = "Sekretesspolicy"; +"about.cells.share_twitter.caption" = "Tweet om det!"; +"about.cells.share_generic.caption" = "Bjud in en vän"; +"donation.title" = "Donera"; +"donation.sections.one_time.header" = "En gång"; +"donation.sections.one_time.footer" = "Om du vill visa tacksamhet för mitt fria arbete, här är några belopp du kan donera direkt. \n\nDu betalas endast en gång per donation, och du kan donera flera gånger. "; +"donation.cells.loading.caption" = "Laddar donationer"; +"donation.cells.purchasing.caption" = "Performing donation"; +"donation.alerts.purchase.success.title" = "Tack"; +"donation.alerts.purchase.success.message" = "Detta betyder mycket för mig och jag hoppas verkligen att du fortsätter att använda och marknadsföra denna app."; +"donation.alerts.purchase.failure.message" = "Kan inte göra donationen. %@"; +"share.message" = "Passepartout är en användarvänlig öppen källkod OpenVPN-klient för iOS och macOS"; +"version.title" = "Version"; +"version.labels.intro" = "Passepartout och TunnelKit skrivs och underhålls av Davide De Rosa (keeshux). \n\nKällkod för Passepartout och TunnelKit är offentligt tillgänglig på GitHub under GPLv3, du kan hitta länkar på hemsidan. \n\nPassepartout är en icke-officiell klient och är inte på något sätt ansluten till OpenVPN Inc. "; +"credits.title" = "Credits"; +"credits.sections.licenses.header" = "Licenses"; +"credits.sections.notices.header" = "Meddelanden"; +"credits.sections.translations.header" = "Translations"; +"label.license.error" = "Kan inte ladda ner fullständigt licensinnehåll."; +"organizer.cells.profile.value.current" = "Under användning"; +"service.welcome.message" = "Välkommen till Passepartout! \n\nAnvänd arrangören för att lägga till en ny profil."; +"service.cells.server_configuration.caption" = "Server konfiguration"; +"service.cells.server_network.caption" = "Server nätverk"; +"service.alerts.configuration.disconnected" = "Konfiguration otillgänglig. Se till att du är kopplad till VPN:et."; +"server_network.cells.route.caption" = "Rutt"; +"wizards.provider.cells.update_list.caption" = "Uppdatera listan"; +"wizards.provider.alerts.unavailable.message" = "Det gick inte att ladda ner leverantörens infrastruktur, försök igen senare."; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "Kom och se mig göra Passepartout live på Twitch, gå med i chatten för att interagera och bidra!"; +"organizer.cells.follow_twitch.caption" = "Se Passepartout on Twitch"; +"service.cells.use_profile.caption" = "Använd den här profilen"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/sv.lproj/Intents.strings b/Passepartout/Core/Resources/sv.lproj/Intents.strings new file mode 100644 index 00000000..36da334b --- /dev/null +++ b/Passepartout/Core/Resources/sv.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "Tar bort cellular från betrodda nätverk"; + +"IeGsEq" = "Avstäng VPN"; +"1ZRTCZ" = "Avstäng VPN"; + +"66bZBE" = "Med ${providerId} leverantör"; + +"7eoAss" = "Tar bort nuvarande Wi-Fi från betrodda nätverk"; + +"9GpJt5" = "Tillsätter cellular till lita betrodda nätverk"; + +"BKxs8X" = "Tillsätter nuvarande Wi-Fi till betrodda nätverk"; + +"NWWgCl" = "Lita på cellular nätverk"; +"H4taev" = "Lita på cellular nätverk"; + +"KjkCfU" = "Koppla till en specifik plats från en leverantör profil"; + +"LA99yM" = "Koppla till VPN"; + +"U6o81V" = "Koppla till ${profileTitle}"; + +"WnTPFg" = "Koppla till ${poolName}"; + +"eQ1yzr" = "Avstäng VPN service"; + +"eXXb2z" = "Koppla till en host profil"; + +"yesvFP" = "Avstäng VPN"; +"lQ6ziK" = "Avstäng VPN"; + +"POyDPM" = "lita på närvarande Wi-Fi"; +"m2E7SI" = "lita på närvarande Wi-Fi"; + +"qo3Szz" = "Koppla till provider plats"; + +"0Wu9nb" = "Untrust närvarande Wi-Fi"; +"rd1T8p" = "Untrust närvarande Wi-Fi"; + +"ggzKA2" = "Untrust cellular nätverk"; +"wB1iYX" = "Untrust cellular nätverk"; + +"xY97Vu" = "På-sätter VPN service med närvarande profil"; + +"NCoK9B" = "Med profil i andvänding"; diff --git a/Passepartout/Core/Resources/zh-Hans.lproj/Core.strings b/Passepartout/Core/Resources/zh-Hans.lproj/Core.strings new file mode 100644 index 00000000..9ccaf7af --- /dev/null +++ b/Passepartout/Core/Resources/zh-Hans.lproj/Core.strings @@ -0,0 +1,240 @@ +// +// Core.strings +// Passepartout +// +// Created by Davide De Rosa on 6/13/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +"global.ok" = "好的"; +"global.cancel" = "取消"; +"global.next" = "下一步"; +"global.close" = "关闭"; +"global.host.title_input.message" = "可输入的字符为字母、数字以及破折号\"-\",下划线\"_\"和点\".\"。"; +"global.host.title_input.placeholder" = "我的配置"; +"global.email_not_configured" = "未配置e-mail账户。"; +"global.captions.address" = "地址"; +"global.captions.port" = "端口"; +"global.values.enabled" = "已启用"; +"global.values.disabled" = "未启用"; +"global.values.none" = "无"; +"global.values.automatic" = "自动设置"; +"global.values.manual" = "手动设置"; +"reddit.title" = "Reddit"; +"reddit.message" = "你知道Passepartout有一个subreddit吗?可以在上面讨论更新、问题、功能、新的平台等n任何你想要的。\n\n这同样是表达你对此项目关注的地方。"; +"reddit.buttons.subscribe" = "立即订阅!"; +"reddit.buttons.remind" = "稍后提醒我"; +"reddit.buttons.never" = "不要再问"; +"vpn.connecting" = "连接中"; +"vpn.active" = "活动的"; +"vpn.disconnecting" = "断开中"; +"vpn.inactive" = "不活动"; +"vpn.disabled" = "未启用"; +"vpn.errors.timeout" = "超时"; +"vpn.errors.dns" = "DNS解析失败"; +"vpn.errors.auth" = "身份验证失败"; +"vpn.errors.tls" = "TLS连接失败"; +"vpn.errors.encryption" = "加密失败"; +"vpn.errors.compression" = "压缩方式不支持"; +"vpn.errors.network" = "网络更改"; +"vpn.errors.routing" = "缺少路由"; +"vpn.errors.gateway" = "无网关"; +"vpn.errors.shutdown" = "服务器关闭"; +"parsed_file.alerts.malformed.message" = "此配置文件包含格式错误的选项(%@)。"; +"parsed_file.alerts.missing.message" = "此配置文件缺少必须的选项(%@)。"; +"parsed_file.alerts.unsupported.message" = "此配置文件包含不支持的选项(%@)。"; +"parsed_file.alerts.potentially_unsupported.message" = "配置文件正确但包含不支持的选项(%@)。\n\n根据服务端的设置连接可能会断开。"; +"parsed_file.alerts.encryption_passphrase.message" = "请输入加密密码"; +"parsed_file.alerts.decryption.message" = "该配置包含加密私钥且不能被解密。请再次检查输入的密钥。"; +"parsed_file.alerts.parsing.message" = "无法解析提供的配置文件(%@)。"; +"parsed_file.alerts.buttons.report" = "报告问题"; +"network_choice.client" = "读取.ovpn文件"; +"network_choice.server" = "从服务端拉取"; +"issue_reporter.title" = "提交问题"; +"issue_reporter.message" = "最后一次连接的debug日志对于解决连接问题是很重要的,并且它是匿名的。\n\n如果有.ovpn文件,那么已经去除了敏感信息后才会y添加。\n\n如果不确定的话,请检查e-mail附件。"; +"issue_reporter.buttons.accept" = "我已知悉"; +"translations.title" = "翻译"; +"share.message" = "Passepartout是iOS和macOS平台下的用户友的、开源的OpenVPN客户端"; +"organizer.sections.providers.header" = "提供商"; +"organizer.sections.providers.footer" = "在这里你可以找到预设的新的提供商配置。"; +"organizer.sections.hosts.header" = "主机"; +"organizer.sections.hosts.footer" = "从原始的.ovpn配置文件导入。"; +"organizer.sections.siri.header" = "Siri"; +"organizer.sections.siri.footer" = "通过Siri来帮助你加快常用的操作。"; +"organizer.sections.support.header" = "支持"; +"organizer.sections.feedback.header" = "反馈"; +"organizer.cells.profile.value.current" = "使用中"; +"organizer.cells.siri_shortcuts.caption" = "管理捷径"; +"organizer.cells.join_community.caption" = "加入社区"; +"organizer.cells.write_review.caption" = "写下想法"; +"organizer.cells.donate.caption" = "提供捐助"; +"organizer.cells.github_sponsors.caption" = "在GitHub上支持我"; +"organizer.cells.translate.caption" = "提供翻译"; +"organizer.cells.about.caption" = "关于 %@"; +"organizer.cells.uninstall.caption" = "移除VPN配置"; +"organizer.alerts.exhausted_providers.message" = "你已针对每个可用的提供商创建了配置。"; +"organizer.alerts.add_host.message" = "从Safari、邮件或其他App中打开.ovpn文件的URL来设置主机配置。\n\n你同样可以通过iTunes文件分享来导入.ovpnf文件。"; +"organizer.alerts.cannot_donate.message" = "此设备未设置付款方式。"; +"organizer.alerts.delete_vpn_profile.message" = "你确定要从此设备移除VPN配置吗?这可能会固定一些断开的VPN状态,不会影响已经存在的配置。"; +"wizards.host.alerts.existing.message" = "已经存在同名的配置。要替换它吗?"; +"service.welcome.message" = "欢迎使用Passepartout!\n\n使用分类页面来添加一个新的配置。"; +"service.sections.vpn.footer" = "必要时连接将会建立。"; +"service.sections.provider_infrastructure.footer" = "最后在%@时更新"; +"service.sections.vpn_survives_sleep.footer" = "禁用以减少电池消耗,由于存在可能的唤醒时重连消耗。"; +"service.sections.vpn_resolves_hostname.footer" = "推荐在大部分的网络中打开,并要求在IPv6环境下。当DNS被阻断或相应缓慢时禁用。"; +"service.sections.trusted.header" = "可信网络"; +"service.sections.trusted.footer" = "当进入可信网络后,VPN将会断开并保持断开状态。禁用此选项可关闭此功能。"; +"service.sections.diagnostics.header" = "分析数据"; +"service.sections.diagnostics.footer" = "在重连后状态隐藏才有效。网络数据包括主机名、IP地址、路由、SSID、认证方式,但私钥不会出现在日志中。"; +"service.cells.connection_status.caption" = "状态"; +"service.cells.provider.pool.caption" = "位置"; +"service.cells.provider.preset.caption" = "预设"; +"service.cells.vpn_survives_sleep.caption" = "休眠时保持连接"; +"service.cells.vpn_resolves_hostname.caption" = "解析服务器主机名"; +"service.cells.trusted_mobile.caption" = "蜂窝网络"; +"service.cells.trusted_policy.caption" = "信任网络中禁用VPN"; +"service.cells.test_connectivity.caption" = "测试连接性"; +"service.cells.data_count.caption" = "已交换数据量"; +"service.cells.data_count.none" = "不可用"; +"service.cells.debug_log.caption" = "调试日志"; +"service.cells.masks_private_data.caption" = "隐藏网络数据"; +"service.cells.reconnect.caption" = "重连"; +"service.cells.report_issue.caption" = "报告连接问题"; +"service.alerts.rename.title" = "重命名配置"; +"service.alerts.credentials_needed.message" = "你需要先输入账户的认证信息。"; +"service.alerts.reconnect_vpn.message" = "要重连VPN吗?"; +"service.alerts.trusted.no_network.message" = "你没有连接到Wi-Fi网络。"; +"service.alerts.trusted.will_disconnect_trusted.message" = "信任此网络后,VPN会断开。要继续吗?"; +"service.alerts.trusted.will_disconnect_policy.message" = "改变信任策略后,VPN可能会断开,要继续吗?"; +"service.alerts.test_connectivity.title" = "连接性"; +"service.alerts.test_connectivity.messages.success" = "你的设备连接到了网络!"; +"service.alerts.test_connectivity.messages.failure" = "你的设备没有连接到网络,请检查你的配置参数。"; +"service.alerts.masks_private_data.messages.must_reconnect" = "为了安全地重置当前调试日志并应用新的掩码设置,你现在必须重连VPN。"; +"service.alerts.buttons.reconnect" = "重连"; +"service.alerts.download.title" = "下载必须的内容"; +"service.alerts.download.message" = "%@要求下载额外的配置文件。\n\n确认以开始下载。"; +"service.alerts.download.failed" = "下载配置文件失败。 %@"; +"service.alerts.download.hud.extracting" = "提取文件中,请等待..."; +"account.title" = "账户"; +"account.sections.guidance.footer.infrastructure.hideme" = "使用你的%@网站认证信息。"; +"account.sections.guidance.footer.infrastructure.mullvad" = "使用你的%@网站认证信息。你的用户名一般是数字 (没有空格)。"; +"account.sections.guidance.footer.infrastructure.nordvpn" = "使用你的%@网站认证信息。你的用户名一般是你的e-mail。"; +"account.sections.guidance.footer.infrastructure.pia" = "使用你的%@网站认证信息。你的用户名一般是数字且带有前缀\"p\"。"; +"account.sections.guidance.footer.infrastructure.protonvpn" = "在网站的\"Account > OpenVPN / IKEv2 Username\"部分找到你的%@的认证信息。"; +"account.sections.guidance.footer.infrastructure.torguard" = "使用您的%@服务凭据,该凭据可能与网站凭据不同。"; +"account.sections.guidance.footer.infrastructure.tunnelbear" = "使用你的%@网站认证信息。你的用户名一般是你的e-mail。"; +"account.sections.guidance.footer.infrastructure.vyprvpn" = "使用你的%@网站认证信息。你的用户名一般是你的e-mail。"; +"account.sections.guidance.footer.infrastructure.windscribe" = "在网站上的OpenVPN配置生成器中找到你的%@认证信息。 "; +"account.sections.registration.footer" = "在%@网站上获取一个账户"; +"account.cells.username.caption" = "用户名"; +"account.cells.username.placeholder" = "username"; +"account.cells.password.caption" = "密码"; +"account.cells.password.placeholder" = "secret"; +"account.cells.open_guide.caption" = "查看你的认证信息"; +"account.cells.signup.caption" = "以%@注册"; +"endpoint.title" = "服务端"; +"endpoint.cells.any_address.caption" = "自动"; +"endpoint.cells.any_protocol.caption" = "自动"; +"network_settings.title" = "网络设置"; +"configuration.sections.communication.header" = "通信"; +"configuration.sections.reset.footer" = "如果你在更改连接参数后变成断开状态,点按已恢复到原始的配置。"; +"configuration.sections.tls.header" = "TLS"; +"configuration.sections.compression.header" = "压缩"; +"configuration.sections.network.header" = "网络"; +"configuration.sections.other.header" = "其他"; +"configuration.cells.cipher.caption" = "加密"; +"configuration.cells.digest.caption" = "身份验证"; +"configuration.cells.digest.value.embedded" = "已包含"; +"configuration.cells.proxy_https.caption" = "代理(HTTPS)"; +"configuration.cells.compression_framing.caption" = "分帧"; +"configuration.cells.compression_framing.value.lzo" = "--comp-lzo"; +"configuration.cells.compression_framing.value.compress" = "--compress"; +"configuration.cells.compression_algorithm.caption" = "算法"; +"configuration.cells.compression_algorithm.value.lzo" = "LZO"; +"configuration.cells.compression_algorithm.value.other" = "未支持"; +"configuration.cells.reset_original.caption" = "重置配置"; +"configuration.cells.client.caption" = "客户端证书"; +"configuration.cells.client.value.enabled" = "已验证"; +"configuration.cells.client.value.disabled" = "未验证"; +"configuration.cells.tls_wrapping.caption" = "组包"; +"configuration.cells.tls_wrapping.value.auth" = "身份验证"; +"configuration.cells.tls_wrapping.value.crypt" = "加密"; +"configuration.cells.eku.caption" = "扩展身份验证"; +"configuration.cells.keep_alive.caption" = "保持活跃状态"; +"configuration.cells.keep_alive.value.seconds" = "%d秒"; +"configuration.cells.renegotiation_seconds.caption" = "重协商"; +"configuration.cells.renegotiation_seconds.value.after" = "在%@之后"; +"configuration.cells.random_endpoint.caption" = "随机的服务端"; +"network_settings.gateway.title" = "默认网关"; +"network_settings.dns.title" = "DNS"; +"network_settings.dns.cells.domain.caption" = "域名"; +"network_settings.proxy.title" = "代理"; +"debug_log.buttons.previous" = "上一步"; +"debug_log.buttons.next" = "下一步"; +"debug_log.alerts.empty_log.message" = "日志为空"; +"shortcuts.add.sections.vpn.header" = "VPN"; +"shortcuts.add.sections.wifi.header" = "Wi-Fi"; +"shortcuts.add.sections.cellular.header" = "蜂窝网络"; +"shortcuts.add.cells.connect.caption" = "连接到"; +"shortcuts.add.cells.enable_vpn.caption" = "开启VPN"; +"shortcuts.add.cells.disable_vpn.caption" = "关闭VPN"; +"shortcuts.add.cells.trust_current_wifi.caption" = "信任当前Wi-Fi"; +"shortcuts.add.cells.untrust_current_wifi.caption" = "不信任当前Wi-Fi"; +"shortcuts.add.cells.trust_cellular.caption" = "信任蜂窝网络"; +"shortcuts.add.cells.untrust_cellular.caption" = "不信任蜂窝网络"; +"shortcuts.add.alerts.no_profiles.message" = "没有可以连接的配置。"; +"shortcuts.edit.sections.all.header" = "已经存在的捷径"; +"donation.title" = "捐助"; +"donation.sections.one_time.header" = "一次性"; +"donation.sections.one_time.footer" = "如果你想对我免费的工作表示感谢,这里是一些你可以捐助的数额。\n\n每次捐助只需要付款一次,你可以捐助多次。"; +"donation.cells.loading.caption" = "加载捐助中"; +"donation.cells.purchasing.caption" = "展示捐助页面中"; +"donation.alerts.purchase.success.title" = "感谢"; +"donation.alerts.purchase.success.message" = "这对于我意味着很多,希望你保持使用并使它更好。"; +"donation.alerts.purchase.failure.message" = "无法展现捐助内容。%@"; +"about.title" = "关于"; +"about.sections.web.header" = "网络"; +"about.sections.share.header" = "分享"; +"about.cells.credits.caption" = "评分"; +"about.cells.website.caption" = "主页"; +"about.cells.faq.caption" = "常见问题"; +"about.cells.disclaimer.caption" = "免责声明"; +"about.cells.privacy_policy.caption" = "隐私政策"; +"about.cells.share_twitter.caption" = "发送关于它的推特!"; +"about.cells.share_generic.caption" = "邀请朋友"; +"version.title" = "版本"; +"version.labels.intro" = "Passepartout和TunnelKit由Davide De Rosa (keeshux)编写并维护。\n\nPassepartout和TunnelKit的源代码在GitHub上以GPLv3许可证面向大众开放,你可以在主页上找到链接。\n\nPassepartout不是官方的客户端,同OpenVPN Inc也没有关系。"; +"credits.title" = "评分"; +"credits.sections.licenses.header" = "许可证"; +"credits.sections.notices.header" = "注意"; +"credits.sections.translations.header" = "翻译"; +"label.license.error" = "不能下载到完整的许可证内容。"; +"service.cells.server_configuration.caption" = "服务端配置"; +"service.cells.server_network.caption" = "服务端网络"; +"service.alerts.configuration.disconnected" = "配置不可用,请确认你已连接到VPN。"; +"server_network.cells.route.caption" = "路由"; +"wizards.provider.cells.update_list.caption" = "更新列表"; +"wizards.provider.alerts.unavailable.message" = "无法下载提供商基础架构,请稍后重试。"; +"organizer.sections.twitch.header" = "Twitch"; +"organizer.sections.twitch.footer" = "快来看我让Passepartout在Twitch上直播,加入聊天互动并做出贡献!"; +"organizer.cells.follow_twitch.caption" = "在Twitch上观看路路通"; +"service.cells.use_profile.caption" = "使用此配置"; +"network_settings.mtu.title" = "MTU"; +"network_settings.mtu.cells.bytes.caption" = "Bytes"; diff --git a/Passepartout/Core/Resources/zh-Hans.lproj/Intents.strings b/Passepartout/Core/Resources/zh-Hans.lproj/Intents.strings new file mode 100644 index 00000000..49285ef3 --- /dev/null +++ b/Passepartout/Core/Resources/zh-Hans.lproj/Intents.strings @@ -0,0 +1,45 @@ +"0jRWn5" = "从可信网络中移除蜂窝网络"; + +"IeGsEq" = "禁用VPN"; +"1ZRTCZ" = "禁用VPN"; + +"66bZBE" = "使用 ${providerId} 提供商配置"; + +"7eoAss" = "从可信网络中移除当前Wi-Fi"; + +"9GpJt5" = "添加蜂窝网络到可信网络中"; + +"BKxs8X" = "添加当前Wi-Fi到可信网络中"; + +"NWWgCl" = "信任蜂窝网络"; +"H4taev" = "信任蜂窝网络"; + +"KjkCfU" = "连接到指定地区的提供商配置"; + +"LA99yM" = "连接到VPN"; + +"U6o81V" = "连接到${profileId}"; + +"WnTPFg" = "连接到${poolName}"; + +"eQ1yzr" = "禁用VPN服务"; + +"eXXb2z" = "连接到主机配置"; + +"yesvFP" = "启用VPN"; +"lQ6ziK" = "启用VPN"; + +"POyDPM" = "信任当前Wi-Fi"; +"m2E7SI" = "信任当前Wi-Fi"; + +"qo3Szz" = "连接到提供商的地区"; + +"0Wu9nb" = "不信任当前Wi-Fi"; +"rd1T8p" = "不信任当前Wi-Fi"; + +"ggzKA2" = "不信任当前蜂窝网络"; +"wB1iYX" = "不信任当前蜂窝网络"; + +"xY97Vu" = "使用当前配置启用VPN服务"; + +"NCoK9B" = "该配置在被使用"; diff --git a/Passepartout/Core/Sources/AppConstants.swift b/Passepartout/Core/Sources/AppConstants.swift new file mode 100644 index 00000000..c3332dfb --- /dev/null +++ b/Passepartout/Core/Sources/AppConstants.swift @@ -0,0 +1,333 @@ +// +// AppConstants.swift +// Passepartout +// +// Created by Davide De Rosa on 9/15/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit +import Convenience +import SwiftyBeaver + +public class AppConstants { + public class App { + public static let appLauncherId = GroupConstants.App.config?["app_launcher_id"] as? String ?? "DUMMY_app_launcher_id" + + public static let appStoreId = GroupConstants.App.config?["appstore_id"] as? String ?? "DUMMY_appstore_id" + + public static let tunnelBundleId: String = { + guard let identifier = Bundle.main.infoDictionary?[kCFBundleIdentifierKey as String] as? String else { + fatalError("Missing kCFBundleIdentifierKey from Info.plist") + } + return "\(identifier).Tunnel" + }() + } + + public class Domain { + public static let name = "passepartoutvpn.app" + } + + public class Store { + public static let serviceFilename = "ConnectionService.json" + + public static let apiDirectory = "API/\(WebServices.version)" + + public static let providersDirectory = "Providers" + + public static let hostsDirectory = "Hosts" + } + + public class Services { + public static func apiURL(version: String, path: String) -> URL { + return Repos.api.appendingPathComponent(version).appendingPathComponent(path) + } + + public static let timeout: TimeInterval = 3.0 + + public static let minimumUpdateInterval: TimeInterval = 600.0 // 10 minutes + + private static let connectivityStrings: [String] = [ + "https://www.amazon.com", + "https://www.google.com", + "https://www.twitter.com", + "https://www.facebook.com", + "https://www.instagram.com" + ] + + public static let connectivityURL = URL(string: connectivityStrings.randomElement()!)! + + public static let connectivityTimeout: TimeInterval = 10.0 + } + + public class Log { + public static let level: SwiftyBeaver.Level = .debug + + public static let debugFormat = "$DHH:mm:ss$d - $M" + + public static var debugSnapshot: () -> String = { TransientStore.shared.service.vpnLog } + + public static let viewerRefreshInterval: TimeInterval = 3.0 + + private static let fileName = "Debug.log" + + public static var fileURL: URL { + return GroupConstants.App.cachesURL.appendingPathComponent(fileName) + } + + private static let console: ConsoleDestination = { + let dest = ConsoleDestination() + dest.minLevel = level + dest.useNSLog = true + return dest + }() + + private static let file: FileDestination = { + let dest = FileDestination() + dest.minLevel = level + dest.logFileURL = fileURL + _ = dest.deleteLogFile() + return dest + }() + + public static func configure() { + SwiftyBeaver.addDestination(console) + SwiftyBeaver.addDestination(file) + } + } + + public class IssueReporter { + public class Email { + public static let recipient = "issues@\(Domain.name)" + + public static let subject = "\(GroupConstants.App.name) - Report issue" + + public static func body(_ description: String, _ metadata: String) -> String { + return "Hi,\n\n\(description)\n\n\(metadata)\n\nRegards" + } + + public static let template = "description of the issue: " + } + + public class Filenames { + public static var debugLog: String { + let fmt = DateFormatter() + fmt.dateFormat = "yyyyMMdd-HHmmss" + let iso = fmt.string(from: Date()) + return "debug-\(iso).txt" + } + + public static let configuration = "profile.ovpn" +// public static let configuration = "profile.ovpn.txt" + } + + public class MIME { + public static let debugLog = "text/plain" + +// public static let configuration = "application/x-openvpn-profile" + public static let configuration = "text/plain" + } + } + + public class Translations { + public class Email { + public static let recipient = "translate@\(Domain.name)" + + public static let subject = "\(GroupConstants.App.name) - Translations" + + public static func body(_ description: String) -> String { + return "Hi,\n\n\(description)\n\nRegards" + } + + public static let template = "I offer to translate to: " + } + + public static let translators: [String: String] = [ + "de": "Christian Lederer, Theodor Tietze", + "el": "Konstantinos Koukoulakis", + "en-US": "Davide De Rosa", + "es": "Davide De Rosa, Elena Vivó", + "fr-FR": "Julien Laniel", + "it": "Davide De Rosa", + "nl": "Norbert de Vreede", + "pl": "Piotr Książek", + "pt-BR": "Helder Santana", + "ru": "Alexander Korobynikov", + "sv": "Henry Gross-Hellsen", + "zh-Hans": "OnlyThen" + ] + } + + public class URLs { + public class iOS { + public static let readme = Repos.ios.appendingPathComponent("blob/master/README.md") + + public static let changelog = Repos.ios.appendingPathComponent("blob/master/CHANGELOG.md") + } + + public class macOS { + public static let readme = Repos.macos.appendingPathComponent("blob/master/README.md") + + public static let changelog = Repos.macos.appendingPathComponent("blob/master/CHANGELOG.md") + } + + public static let filetypes = ["public.content", "public.data"] + + public static let website = URL(string: "https://\(Domain.name)")! + + public static let faq = website.appendingPathComponent("faq") + + public static let disclaimer = website.appendingPathComponent("disclaimer") + + public static let privacyPolicy = website.appendingPathComponent("privacy") + + public static let donate = website.appendingPathComponent("donate") + + public static let subreddit = URL(string: "https://www.reddit.com/r/passepartout")! + + public static let twitch = URL(string: "twitch://stream/keeshux")! + + public static let twitchFallback = URL(string: "https://twitch.tv/keeshux")! + + public static let githubSponsors = URL(string: "https://www.github.com/sponsors/passepartoutvpn")! + + public static let alternativeTo = URL(string: "https://alternativeto.net/software/passepartout-vpn/")! + + public static let productHunt = URL(string: "https://www.producthunt.com/posts/passepartout-vpn/")! + + private static let twitterHashtags = ["OpenVPN", "iOS", "macOS"] + + public static func twitterIntent(withMessage message: String) -> URL { + var text = message + for ht in twitterHashtags { + text = text.replacingOccurrences(of: ht, with: "#\(ht)") + } + var comps = URLComponents(string: "https://twitter.com/intent/tweet")! + comps.queryItems = [ + URLQueryItem(name: "url", value: website.absoluteString), + URLQueryItem(name: "via", value: "keeshux"), + URLQueryItem(name: "text", value: text) + ] + return comps.url! + } + + public static let guidances: [Infrastructure.Name: String] = [ + .protonvpn: "https://account.protonvpn.com/settings", + .torguard: "https://torguard.net/clientarea.php?action=changepw", + .windscribe: "https://windscribe.com/getconfig/openvpn" + ] + + public static let referrals: [Infrastructure.Name: String] = [ + .hideme: "https://member.hide.me/en/checkout?plan=new_default_prices&coupon=6CB-BDB-802&duration=24", + .mullvad: "https://mullvad.net/en/account/create/", + .nordvpn: "https://go.nordvpn.net/SH21Z", + .pia: "https://www.privateinternetaccess.com/pages/buy-vpn/", + .protonvpn: "https://proton.go2cloud.org/SHZ", + .torguard: "https://torguard.net/", + .tunnelbear: "https://www.tunnelbear.com/", + .vyprvpn: "https://www.vyprvpn.com/", + .windscribe: "https://secure.link/kCsD0prd" + ] + + public static let externalResources: [Infrastructure.Name: String] = [ + .nordvpn: "https://downloads.nordcdn.com/configs/archives/certificates/servers.zip" // 9MB + ] + } + + public class Repos { + private static let githubRoot = URL(string: "https://github.com/passepartoutvpn/")! + + private static let githubRawRoot = URL(string: "https://\(Domain.name)/")! + + private static func github(repo: String) -> URL { + return githubRoot.appendingPathComponent(repo) + } + + private static func githubRaw(repo: String) -> URL { + return githubRawRoot.appendingPathComponent(repo) + } + + public static let ios = github(repo: "passepartout-ios") + + public static let macos = github(repo: "passepartout-macos") + + public static let api = githubRaw(repo: "api") + } + + public struct Credits { + public static let author = "Davide De Rosa" + + public static let software: [Software] = [ + Software( + "Kvitto", + license: "BSD", + url: "https://raw.githubusercontent.com/Cocoanetics/Kvitto/develop/LICENSE" + ), + Software( + "lzo", + license: "GPLv2", + url: "https://www.gnu.org/licenses/gpl-2.0.txt" + ), + Software( + "MBProgressHUD", + license: "MIT", + url: "https://raw.githubusercontent.com/jdg/MBProgressHUD/master/LICENSE" + ), + Software( + "OpenSSL", + license: "OpenSSL", + url: "https://www.openssl.org/source/license.txt" + ), + Software( + "PIATunnel", + license: "MIT", + url: "https://raw.githubusercontent.com/pia-foss/tunnel-apple/master/LICENSE" + ), + Software( + "SSZipArchive", + license: "MIT", + url: "https://raw.githubusercontent.com/samsoffes/ssziparchive/master/LICENSE" + ), + Software( + "SwiftGen", + license: "MIT", + url: "https://raw.githubusercontent.com/SwiftGen/SwiftGen/master/LICENCE" + ), + Software( + "SwiftyBeaver", + license: "MIT", + url: "https://raw.githubusercontent.com/SwiftyBeaver/SwiftyBeaver/master/LICENSE" + ), + Software( + "Circle Icons", + notice: "The logo is taken from the awesome Circle Icons set by Nick Roach." + ), + Software( + "Country flags", + notice: "The country flags are taken from: https://github.com/lipis/flag-icon-css/" + ), + Software( + "OpenVPN", + notice: "© 2002-2018 OpenVPN Inc. - OpenVPN is a registered trademark of OpenVPN Inc." + ) + ] + } +} diff --git a/Passepartout/Core/Sources/ApplicationError.swift b/Passepartout/Core/Sources/ApplicationError.swift new file mode 100644 index 00000000..4f7f6e79 --- /dev/null +++ b/Passepartout/Core/Sources/ApplicationError.swift @@ -0,0 +1,38 @@ +// +// ApplicationError.swift +// Passepartout +// +// Created by Davide De Rosa on 6/12/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public enum ApplicationError: String, Error { + case missingProfile + + case missingCredentials + + case migration + + case inactiveProfile + + case externalResources +} diff --git a/Passepartout/Core/Sources/GroupConstants.swift b/Passepartout/Core/Sources/GroupConstants.swift new file mode 100644 index 00000000..2b161c2c --- /dev/null +++ b/Passepartout/Core/Sources/GroupConstants.swift @@ -0,0 +1,78 @@ +// +// GroupConstants.swift +// Passepartout +// +// Created by Davide De Rosa on 6/7/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import Convenience + +public class GroupConstants { + public class App { + public static let config = Bundle.main.infoDictionary?["com.algoritmico.Passepartout.config"] as? [String: Any] + + public static let name = "Passepartout" + + public static let tunnelKitName = "TunnelKit" + + public static let title = name +// public static let title = "\u{1F511}" + + public static let versionNumber = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String + + public static let buildNumber = Int(Bundle.main.infoDictionary![kCFBundleVersionKey as String] as! String)! + + public static let versionString = "\(versionNumber) (\(buildNumber))" + + public static let groupId = config?["group_id"] as? String ?? "DUMMY_group_id" + + private static var containerURL: URL { + guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupId) else { + print("Unable to access App Group container") + return FileManager.default.userURL(for: .documentDirectory, appending: nil) + } + return url + } + + public static let documentsURL: URL = { + let url = containerURL.appendingPathComponent("Documents", isDirectory: true) + try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) + return url + }() + + public static let cachesURL: URL = { + let url = containerURL.appendingPathComponent("Library/Caches", isDirectory: true) + try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) + return url + }() + + public static let externalURL = cachesURL.appendingPathComponent("External") + } + + public class VPN { + public static let dnsTimeout = 5000 + + public static let sessionMarker = "--- EOF ---" + + public static let dataCountInterval = 5000 + } +} diff --git a/Passepartout/Core/Sources/Intents/IntentDispatcher.swift b/Passepartout/Core/Sources/Intents/IntentDispatcher.swift new file mode 100644 index 00000000..423a2313 --- /dev/null +++ b/Passepartout/Core/Sources/Intents/IntentDispatcher.swift @@ -0,0 +1,320 @@ +// +// IntentDispatcher.swift +// Passepartout +// +// Created by Davide De Rosa on 3/8/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import Intents +import SwiftyBeaver +import TunnelKit + +private let log = SwiftyBeaver.self + +@available(iOS 12, *) +public class IntentDispatcher { + private class Groups { + static let vpn = "VPN" + + static let trust = "Trust" + } + + public static let didUpdateService = Notification.Name("IntentDispatcherDidUpdateService") + + // MARK: Intents + + public static func intentConnect(profile: ConnectionProfile, title: String?) -> ConnectVPNIntent { + let intent = ConnectVPNIntent() + intent.context = profile.context.rawValue + intent.profileId = profile.id + intent.profileTitle = title ?? profile.id + return intent + } + + public static func intentMoveTo(profile: ProviderConnectionProfile, pool: Pool) -> MoveToLocationIntent { + let intent = MoveToLocationIntent() + intent.providerId = profile.id + intent.poolId = pool.id + intent.poolName = pool.localizedId + return intent + } + + public static func intentEnable() -> EnableVPNIntent { + return EnableVPNIntent() + } + + public static func intentDisable() -> DisableVPNIntent { + return DisableVPNIntent() + } + + public static func intentTrustWiFi() -> TrustCurrentNetworkIntent { + return TrustCurrentNetworkIntent() + } + + public static func intentUntrustWiFi() -> UntrustCurrentNetworkIntent { + return UntrustCurrentNetworkIntent() + } + + public static func intentTrustCellular() -> TrustCellularNetworkIntent { + return TrustCellularNetworkIntent() + } + + public static func intentUntrustCellular() -> UntrustCellularNetworkIntent { + return UntrustCellularNetworkIntent() + } + + // MARK: Donations + + public static func donateConnection(with profile: ConnectionProfile, title: String?) { + let genericIntent: INIntent + if let provider = profile as? ProviderConnectionProfile, let pool = provider.pool { + genericIntent = intentMoveTo(profile: provider, pool: pool) + } else { + genericIntent = intentConnect(profile: profile, title: title) + } + + let interaction = INInteraction(intent: genericIntent, response: nil) + interaction.groupIdentifier = ProfileKey(profile).rawValue + interaction.donateAndLog() + } + + public static func donateEnableVPN() { + let interaction = INInteraction(intent: intentEnable(), response: nil) + interaction.groupIdentifier = Groups.vpn + interaction.donateAndLog() + } + + public static func donateDisableVPN() { + let interaction = INInteraction(intent: intentDisable(), response: nil) + interaction.groupIdentifier = Groups.vpn + interaction.donateAndLog() + } + + public static func donateTrustCurrentNetwork() { + let interaction = INInteraction(intent: intentTrustWiFi(), response: nil) + interaction.groupIdentifier = Groups.trust + interaction.donateAndLog() + } + + public static func donateUntrustCurrentNetwork() { + let interaction = INInteraction(intent: intentUntrustWiFi(), response: nil) + interaction.groupIdentifier = Groups.trust + interaction.donateAndLog() + } + + public static func donateTrustCellularNetwork() { + let interaction = INInteraction(intent: intentTrustCellular(), response: nil) + interaction.groupIdentifier = Groups.trust + interaction.donateAndLog() + } + + public static func donateUntrustCellularNetwork() { + let interaction = INInteraction(intent: intentUntrustCellular(), response: nil) + interaction.groupIdentifier = Groups.trust + interaction.donateAndLog() + } + + // + + public static func handleInteraction(_ interaction: INInteraction, completionHandler: ((Error?) -> Void)?) { + handleIntent(interaction.intent, interaction: interaction, completionHandler: completionHandler) + } + + public static func handleIntent(_ intent: INIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + if let custom = intent as? ConnectVPNIntent { + handleConnectVPN(custom, interaction: interaction, completionHandler: completionHandler) + } else if let custom = intent as? EnableVPNIntent { + handleEnableVPN(custom, interaction: interaction, completionHandler: completionHandler) + } else if let custom = intent as? DisableVPNIntent { + handleDisableVPN(custom, interaction: interaction, completionHandler: completionHandler) + } else if let custom = intent as? MoveToLocationIntent { + handleMoveToLocation(custom, interaction: interaction, completionHandler: completionHandler) + } else if let _ = intent as? TrustCurrentNetworkIntent { + handleCurrentNetwork(trust: true, interaction: interaction, completionHandler: completionHandler) + } else if let _ = intent as? UntrustCurrentNetworkIntent { + handleCurrentNetwork(trust: false, interaction: interaction, completionHandler: completionHandler) + } else if let _ = intent as? TrustCellularNetworkIntent { + handleCellularNetwork(trust: true, interaction: interaction, completionHandler: completionHandler) + } else if let _ = intent as? UntrustCellularNetworkIntent { + handleCellularNetwork(trust: false, interaction: interaction, completionHandler: completionHandler) + } + } + + public static func handleConnectVPN(_ intent: ConnectVPNIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + guard let contextValue = intent.context, let context = Context(rawValue: contextValue), let id = intent.profileId else { + if let interactionIdentifier = interaction?.identifier { + INInteraction.delete(with: [interactionIdentifier], completion: nil) + } + // FIXME: error = missing data, programming error + completionHandler?(nil) + return + } + let profileKey = ProfileKey(context, id) + log.info("Connect to profile: \(profileKey)") + + let service = TransientStore.shared.service + let vpn = VPN.shared + guard !(service.isActiveProfile(profileKey) && (vpn.status == .connected)) else { + log.info("Profile is already active and connected") + completionHandler?(nil) + return + } + + guard let profile = service.profile(withContext: context, id: id) else { + // FIXME: error = no profile + completionHandler?(nil) + return + } + service.activateProfile(profile) + refreshVPN(service: service, doReconnect: true, completionHandler: completionHandler) + } + + public static func handleMoveToLocation(_ intent: MoveToLocationIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + guard let providerId = intent.providerId, let poolId = intent.poolId else { + // FIXME: error = no provider/pool + completionHandler?(nil) + return + } + let service = TransientStore.shared.service + guard let providerProfile = service.profile(withContext: .provider, id: providerId) as? ProviderConnectionProfile else { + // FIXME: error = no provider + completionHandler?(nil) + return + } + log.info("Connect to provider location: \(providerId) @ [\(poolId)]") + + let vpn = VPN.shared + guard !(service.isActiveProfile(providerProfile) && (providerProfile.poolId == poolId) && (vpn.status == .connected)) else { + log.info("Profile is already active and connected to \(poolId)") + completionHandler?(nil) + return + } + + providerProfile.poolId = poolId + service.activateProfile(providerProfile) + refreshVPN(service: service, doReconnect: true, completionHandler: completionHandler) + } + + public static func handleEnableVPN(_ intent: EnableVPNIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + let service = TransientStore.shared.service + log.info("Enabling VPN...") + refreshVPN(service: service, doReconnect: true, completionHandler: completionHandler) + } + + public static func handleDisableVPN(_ intent: DisableVPNIntent, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + log.info("Disabling VPN...") + + let vpn = VPN.shared + vpn.prepare { + vpn.disconnect { (error) in + notifyServiceUpdate() + completionHandler?(error) + } + } + } + + public static func handleCurrentNetwork(trust: Bool, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + guard let currentWifi = Utils.currentWifiNetworkName() else { + // FIXME: error = not connected to wifi + completionHandler?(nil) + return + } + let service = TransientStore.shared.service + service.activeProfile?.trustedNetworks.includedWiFis[currentWifi] = trust + TransientStore.shared.serialize(withProfiles: false) + + log.info("\(trust ? "Trusted" : "Untrusted") Wi-Fi: \(currentWifi)") + refreshVPN(service: service, doReconnect: false, completionHandler: completionHandler) + } + + public static func handleCellularNetwork(trust: Bool, interaction: INInteraction?, completionHandler: ((Error?) -> Void)?) { + #if os(iOS) + guard Utils.hasCellularData() else { + // FIXME: error = has no mobile data + completionHandler?(nil) + return + } + let service = TransientStore.shared.service + service.activeProfile?.trustedNetworks.includesMobile = trust + TransientStore.shared.serialize(withProfiles: false) + + log.info("\(trust ? "Trusted" : "Untrusted") cellular network") + refreshVPN(service: service, doReconnect: false, completionHandler: completionHandler) + #endif + } + + private static func refreshVPN(service: ConnectionService, doReconnect: Bool, completionHandler: ((Error?) -> Void)?) { + let configuration: VPNConfiguration + do { + configuration = try service.vpnConfiguration() + } catch let e { + log.error("Unable to build VPN configuration: \(e)") + notifyServiceUpdate() + completionHandler?(e) + return + } + + let vpn = VPN.shared + if doReconnect { + log.info("Reconnecting VPN: \(configuration)") + vpn.reconnect(configuration: configuration) { (error) in + notifyServiceUpdate() + completionHandler?(error) + } + } else { + log.info("Reinstalling VPN: \(configuration)") + vpn.install(configuration: configuration) { (error) in + notifyServiceUpdate() + completionHandler?(error) + } + } + } + + // + + public static func forgetProfile(withKey profileKey: ProfileKey) { + INInteraction.delete(with: profileKey.rawValue) { (error) in + if let error = error { + log.error("Unable to forget interactions: \(error)") + return + } + log.debug("Removed profile \(profileKey) interactions") + } + } + + // + + private static func notifyServiceUpdate() { + NotificationCenter.default.post(name: IntentDispatcher.didUpdateService, object: nil) + } +} + +private extension INInteraction { + func donateAndLog() { + donate { (error) in + if let error = error { + log.error("Unable to donate interaction: \(error)") + } + log.debug("Donated \(self.intent)") + } + } +} diff --git a/Passepartout/Core/Sources/Issue.swift b/Passepartout/Core/Sources/Issue.swift new file mode 100644 index 00000000..54ff717a --- /dev/null +++ b/Passepartout/Core/Sources/Issue.swift @@ -0,0 +1,58 @@ +// +// Issue.swift +// Passepartout +// +// Created by Davide De Rosa on 9/5/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit +#if os(iOS) +import MessageUI +#endif + +public struct Issue { + public let debugLog: Bool + + public let configurationURL: URL? + + public let infrastructureMetadata: Infrastructure.Metadata? + + public init(debugLog: Bool, configurationURL: URL?, infrastructureMetadata: Infrastructure.Metadata? = nil) { + self.debugLog = debugLog + self.configurationURL = configurationURL + self.infrastructureMetadata = infrastructureMetadata + } + + public init(debugLog: Bool, profile: ConnectionProfile?) { + let url: URL? + if let profile = profile { + url = TransientStore.shared.service.configurationURL(for: profile) + } else { + url = nil + } + var infrastructureMetadata: Infrastructure.Metadata? + if let name = (profile as? ProviderConnectionProfile)?.name { + infrastructureMetadata = InfrastructureFactory.shared.metadata(forName: name) + } + self.init(debugLog: debugLog, configurationURL: url, infrastructureMetadata: infrastructureMetadata) + } +} diff --git a/Passepartout/Core/Sources/Model/ConnectionProfile.swift b/Passepartout/Core/Sources/Model/ConnectionProfile.swift new file mode 100644 index 00000000..2d4edefc --- /dev/null +++ b/Passepartout/Core/Sources/Model/ConnectionProfile.swift @@ -0,0 +1,89 @@ +// +// ConnectionProfile.swift +// Passepartout +// +// Created by Davide De Rosa on 9/2/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit +import NetworkExtension + +public enum Context: String, Codable { + case provider + + case host +} + +public protocol ConnectionProfile: class, EndpointDataSource, CustomStringConvertible { + var context: Context { get } + + var id: String { get } + + var username: String? { get set } + + var requiresCredentials: Bool { get } + + var trustedNetworks: TrustedNetworks! { get set } + + var networkChoices: ProfileNetworkChoices? { get set } + + var manualNetworkSettings: ProfileNetworkSettings? { get set } + + func generate(from configuration: OpenVPNTunnelProvider.Configuration, preferences: Preferences) throws -> OpenVPNTunnelProvider.Configuration +} + +public extension ConnectionProfile { + var passwordContext: String { + return "\(Bundle.main.bundleIdentifier!).\(context.rawValue).\(id)" + } + + func password(in keychain: Keychain) -> String? { + guard let username = username else { + return nil + } + return try? keychain.password(for: username, context: passwordContext) + } + + func setPassword(_ password: String?, in keychain: Keychain) throws { + guard let username = username else { + return + } + guard let password = password else { + keychain.removePassword(for: username, context: passwordContext) + return + } + try keychain.set(password: password, for: username, context: passwordContext) + } + + func removePassword(in keychain: Keychain) { + guard let username = username else { + return + } + keychain.removePassword(for: username, context: passwordContext) + } +} + +public extension ConnectionProfile { + var description: String { + return "(\(context):\(id))" + } +} diff --git a/Passepartout/Core/Sources/Model/ConnectionService+Configurations.swift b/Passepartout/Core/Sources/Model/ConnectionService+Configurations.swift new file mode 100644 index 00000000..880004ec --- /dev/null +++ b/Passepartout/Core/Sources/Model/ConnectionService+Configurations.swift @@ -0,0 +1,69 @@ +// +// ConnectionService+Configurations.swift +// Passepartout +// +// Created by Davide De Rosa on 10/22/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +public extension ConnectionService { + func save(configurationURL: URL, for key: ProfileKey) throws -> URL { + let destinationURL = targetConfigurationURL(for: key) + let fm = FileManager.default + try? fm.removeItem(at: destinationURL) + try fm.copyItem(at: configurationURL, to: destinationURL) + return destinationURL + } + + func save(configurationURL: URL, for profile: ConnectionProfile) throws -> URL { + return try save(configurationURL: configurationURL, for: ProfileKey(profile)) + } + + func configurationURL(for key: ProfileKey) -> URL? { + let url = targetConfigurationURL(for: key) + guard FileManager.default.fileExists(atPath: url.path) else { + return nil + } + return url + } + + func configurationURL(for profile: ConnectionProfile) -> URL? { + return configurationURL(for: ProfileKey(profile)) + } + + func targetConfigurationURL(for key: ProfileKey) -> URL { + return contextURL(key).appendingPathComponent(key.id).appendingPathExtension("ovpn") + } + + func pendingConfigurationURLs() -> [URL] { + do { + let list = try FileManager.default.contentsOfDirectory(at: rootURL, includingPropertiesForKeys: nil, options: []) + return list.filter { $0.pathExtension == "ovpn" } + } catch let e { + log.error("Could not list imported configurations: \(e)") + return [] + } + } +} diff --git a/Passepartout/Core/Sources/Model/ConnectionService+Migration.swift b/Passepartout/Core/Sources/Model/ConnectionService+Migration.swift new file mode 100644 index 00000000..ed9851da --- /dev/null +++ b/Passepartout/Core/Sources/Model/ConnectionService+Migration.swift @@ -0,0 +1,185 @@ +// +// ConnectionService+Migration.swift +// Passepartout +// +// Created by Davide De Rosa on 10/25/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SwiftyBeaver +import TunnelKit + +private let log = SwiftyBeaver.self + +public extension ConnectionService { + static func migrateJSON(from: URL, to: URL) { + do { + let newData = try migrateJSON(at: from) +// log.verbose(String(data: newData, encoding: .utf8)!) + try newData.write(to: to) + } catch let e { + log.error("Could not migrate service: \(e)") + } + } + + static func migrateJSON(at url: URL) throws -> Data { + let data = try Data(contentsOf: url) + guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { + throw ApplicationError.migration + } + + // put migration logic here + let _ = json["build"] as? Int ?? 0 + + return try JSONSerialization.data(withJSONObject: json, options: []) + } + + func migrateProvidersToLowercase() { + + // migrate providers to lowercase names + guard let files = try? FileManager.default.contentsOfDirectory(at: providersURL, includingPropertiesForKeys: nil, options: []) else { + log.debug("No providers to migrate") + return + } + for entry in files { + let filename = entry.lastPathComponent + + // old names contain at least an uppercase letter + guard let _ = filename.rangeOfCharacter(from: .uppercaseLetters) else { + continue + } + + log.debug("Migrating provider in \(filename) to new name") + do { + let data = try Data(contentsOf: entry) + guard var obj = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let name = obj["name"] as? String else { + log.warning("Skipping provider \(filename), not a JSON or no 'name' key found") + continue + } + + // replace name and overwrite + obj["name"] = name.lowercased() + let migratedData = try JSONSerialization.data(withJSONObject: obj, options: []) + try? migratedData.write(to: entry) + + // rename file if it makes sense + let newEntry = entry.deletingLastPathComponent().appendingPathComponent(filename.lowercased()) + try? FileManager.default.moveItem(at: entry, to: newEntry) + + log.debug("Migrated provider: \(name)") + } catch let e { + log.warning("Unable to migrate provider \(filename): \(e)") + } + } + } + + func migrateHostsToUUID() { + guard let files = try? FileManager.default.contentsOfDirectory(at: hostsURL, includingPropertiesForKeys: nil, options: []) else { + log.debug("No hosts to migrate") + return + } + + // initialize titles mapping + hostTitles = [:] + + for entry in files { + let filename = entry.lastPathComponent + guard filename.hasSuffix(".json") else { + continue + } + + log.debug("Migrating host \(filename) to UUID-based") + do { + let data = try Data(contentsOf: entry) + guard var obj = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let title = obj["title"] as? String else { + log.warning("Skipping host \(filename), not a JSON or no 'title' key found") + continue + } + + // pick unique id + let uuid = UUID().uuidString + + // remove title from JSON (will move to index) + obj["id"] = uuid +// obj.removeValue(forKey: "title") + + // save mapping for later + hostTitles[uuid] = title + + // migrate active profile if necessary (= it's a host) + if let key = activeProfileKey, key.context == .host && key.id == title { + activeProfileKey = ProfileKey(.host, uuid) + } + + // replace name and overwrite + let migratedData = try JSONSerialization.data(withJSONObject: obj, options: []) + try? migratedData.write(to: entry) + + let parent = entry.deletingLastPathComponent() + + // rename file to UUID + let newFilename = "\(uuid).json" + let newEntry = parent.appendingPathComponent(newFilename) + try? FileManager.default.moveItem(at: entry, to: newEntry) + + // rename associated .ovpn (if any) + let ovpnFilename = "\(title).ovpn" + let ovpnNewFilename = "\(uuid).ovpn" + try? FileManager.default.moveItem( + at: parent.appendingPathComponent(ovpnFilename), + to: parent.appendingPathComponent(ovpnNewFilename) + ) + + log.debug("Migrated host: \(filename) -> \(newFilename)") + } catch let e { + log.warning("Unable to migrate host \(filename): \(e)") + } + } + } + + func migrateKeychainContext() { + for key in allProfileKeys() { + guard let profile = profile(withKey: key), let username = profile.username else { + continue + } + let keychain = Keychain(group: GroupConstants.App.groupId) + let prefix = "com.algoritmico.ios.Passepartout" + + // profiles + do { + let oldUsername = "\(prefix).\(key.context).\(key.id).\(username)" + let password = try keychain.password(for: oldUsername) + try profile.setPassword(password, in: keychain) + keychain.removePassword(for: oldUsername) + + // tunnel + if isActiveProfile(key) { + let oldTunnelUsername = prefix + let tunnelContext = "\(prefix).Tunnel" + try keychain.set(password: password, for: username, context: tunnelContext) + keychain.removePassword(for: oldTunnelUsername) + } + } catch { + // + } + } + } +} diff --git a/Passepartout/Core/Sources/Model/ConnectionService.swift b/Passepartout/Core/Sources/Model/ConnectionService.swift new file mode 100644 index 00000000..61375996 --- /dev/null +++ b/Passepartout/Core/Sources/Model/ConnectionService.swift @@ -0,0 +1,713 @@ +// +// ConnectionService.swift +// Passepartout +// +// Created by Davide De Rosa on 9/3/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit +import NetworkExtension +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +public protocol ConnectionServiceDelegate: class { + func connectionService(didAdd profile: ConnectionProfile) + + func connectionService(didRename profile: ConnectionProfile, to newTitle: String) + + func connectionService(didRemoveProfileWithKey key: ProfileKey) + + func connectionService(willDeactivate profile: ConnectionProfile) + + func connectionService(didActivate profile: ConnectionProfile) + + func connectionService(didUpdate profile: ConnectionProfile) +} + +public class ConnectionService: Codable { + public enum CodingKeys: String, CodingKey { + case build + + case appGroup + + case baseConfiguration + + case activeProfileKey + + case preferences + + case hostTitles + } + + public struct NotificationKeys { + public static let dataCount = "DataCount" + } + + public static let didUpdateDataCount = Notification.Name("ConnectionServiceDidUpdateDataCount") + + public var directory: String? = nil + + public var rootURL: URL { + var url = GroupConstants.App.documentsURL + if let directory = directory { + url.appendPathComponent(directory) + } + return url + } + + var providersURL: URL { + return rootURL.appendingPathComponent(AppConstants.Store.providersDirectory) + } + + var hostsURL: URL { + return rootURL.appendingPathComponent(AppConstants.Store.hostsDirectory) + } + + private var build: Int + + private let appGroup: String + + private let defaults: UserDefaults + + private let keychain: Keychain + + public var baseConfiguration: OpenVPNTunnelProvider.Configuration + + private var cache: [ProfileKey: ConnectionProfile] + + // XXX: access needed by +Migration + var hostTitles: [String: String] + + public internal(set) var activeProfileKey: ProfileKey? { + willSet { + if let oldProfile = activeProfile { + delegate?.connectionService(willDeactivate: oldProfile) + } + } + didSet { + if let newProfile = activeProfile { + delegate?.connectionService(didActivate: newProfile) + } + } + } + + public var activeProfile: ConnectionProfile? { + guard let id = activeProfileKey else { + return nil + } + var hit = cache[id] + if let placeholder = hit as? PlaceholderConnectionProfile { + hit = profile(withContext: placeholder.context, id: placeholder.id) + cache[id] = hit + } + return hit + } + + public let preferences: EditablePreferences + + public weak var delegate: ConnectionServiceDelegate? + + public init(withAppGroup appGroup: String, baseConfiguration: OpenVPNTunnelProvider.Configuration) { + guard let defaults = UserDefaults(suiteName: appGroup) else { + fatalError("No entitlements for group '\(appGroup)'") + } + build = GroupConstants.App.buildNumber + self.appGroup = appGroup + self.defaults = defaults + keychain = Keychain(group: appGroup) + + self.baseConfiguration = baseConfiguration + activeProfileKey = nil + preferences = EditablePreferences() + + cache = [:] + hostTitles = [:] + + ensureDirectoriesExistence() + } + + // MARK: Codable + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let appGroup = try container.decode(String.self, forKey: .appGroup) + guard let defaults = UserDefaults(suiteName: appGroup) else { + fatalError("No entitlements for group '\(appGroup)'") + } + build = try container.decode(Int.self, forKey: .build) + self.appGroup = appGroup + self.defaults = defaults + keychain = Keychain(group: appGroup) + + baseConfiguration = try container.decode(OpenVPNTunnelProvider.Configuration.self, forKey: .baseConfiguration) + activeProfileKey = try container.decodeIfPresent(ProfileKey.self, forKey: .activeProfileKey) + preferences = try container.decode(EditablePreferences.self, forKey: .preferences) + + cache = [:] + hostTitles = try container.decode([String: String].self, forKey: .hostTitles) + + ensureDirectoriesExistence() + } + + public func encode(to encoder: Encoder) throws { + build = GroupConstants.App.buildNumber + + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(build, forKey: .build) + try container.encode(appGroup, forKey: .appGroup) + try container.encode(baseConfiguration, forKey: .baseConfiguration) + try container.encodeIfPresent(activeProfileKey, forKey: .activeProfileKey) + try container.encode(preferences, forKey: .preferences) + try container.encode(hostTitles, forKey: .hostTitles) + } + + // MARK: Serialization + + public func loadProfiles() { + let fm = FileManager.default + do { + let files = try fm.contentsOfDirectory(at: providersURL, includingPropertiesForKeys: nil, options: []) +// log.debug("Found \(files.count) provider files: \(files)") + for entry in files { + guard let id = ConnectionService.profileId(fromURL: entry) else { + continue + } + let key = ProfileKey(.provider, id) + cache[key] = PlaceholderConnectionProfile(key) + } + } catch let e { + log.warning("Could not list provider contents: \(e) (\(providersURL))") + } + do { + let files = try fm.contentsOfDirectory(at: hostsURL, includingPropertiesForKeys: nil, options: []) +// log.debug("Found \(files.count) host files: \(files)") + for entry in files { + guard let id = ConnectionService.profileId(fromURL: entry) else { + continue + } + let key = ProfileKey(.host, id) + cache[key] = PlaceholderConnectionProfile(key) + } + } catch let e { + log.warning("Could not list host contents: \(e) (\(hostsURL))") + } + + // clean up hostTitles if necessary + let staleHostIds = hostTitles.keys.filter { cache[ProfileKey(.host, $0)] == nil } + staleHostIds.forEach { + hostTitles.removeValue(forKey: $0) + } + } + + public func saveProfiles() { + let encoder = JSONEncoder() + for profile in cache.values { + saveProfile(profile, withEncoder: encoder) + } + } + + private func ensureDirectoriesExistence() { + let fm = FileManager.default + do { + try fm.createDirectory(at: providersURL, withIntermediateDirectories: false, attributes: nil) + } catch let e { + log.warning("Could not create providers folder: \(e) (\(providersURL))") + } + do { + try fm.createDirectory(at: hostsURL, withIntermediateDirectories: false, attributes: nil) + } catch let e { + log.warning("Could not create hosts folder: \(e) (\(hostsURL))") + } + + } + + private func saveProfile(_ profile: ConnectionProfile, withEncoder encoder: JSONEncoder) { + do { + let url = profileURL(ProfileKey(profile)) + var optData: Data? + if let providerProfile = profile as? ProviderConnectionProfile { + optData = try encoder.encode(providerProfile) + } else if let hostProfile = profile as? HostConnectionProfile { + optData = try encoder.encode(hostProfile) + } else if let placeholder = profile as? PlaceholderConnectionProfile { + log.debug("Skipped placeholder \(placeholder)") + } else { + fatalError("Attempting to add an unhandled profile type: \(type(of: profile))") + } + guard let data = optData else { + return + } + try data.write(to: url) + log.debug("Serialized profile \(profile)") + } catch let e { + log.warning("Could not serialize profile \(profile): \(e)") + } + } + + public func profile(withContext context: Context, id: String) -> ConnectionProfile? { + return profile(withKey: ProfileKey(context, id)) + } + + public func profile(withKey key: ProfileKey) -> ConnectionProfile? { + var profile = cache[key] + if let _ = profile as? PlaceholderConnectionProfile { + let decoder = JSONDecoder() + do { + let data = try profileData(key) + switch key.context { + case .provider: + let providerProfile = try decoder.decode(ProviderConnectionProfile.self, from: data) + + // XXX: fix renamed presets, fall back to default + if providerProfile.preset == nil { + providerProfile.presetId = providerProfile.infrastructure.defaults.preset + } + + // XXX: fix renamed pool, fall back to default + if providerProfile.pool == nil, let fallbackPool = providerProfile.infrastructure.defaultPool() { + providerProfile.poolId = fallbackPool.id + } + + // XXX: fix unsupported preset + providerProfile.setSupportedPreset() + + // XXX: patch empty favorites + if providerProfile.favoriteGroupIds == nil { + providerProfile.favoriteGroupIds = [] + } + + profile = providerProfile + + case .host: + let hostProfile = try decoder.decode(HostConnectionProfile.self, from: data) + + profile = hostProfile + } + cache[key] = profile + } catch let e { + log.error("Could not decode profile JSON: \(e)") + + // drop corrupt cache entry + cache.removeValue(forKey: key) + try? FileManager.default.removeItem(at: profileURL(key)) + + return nil + } + } + + // XXX: preload trusted networks in a backwards compatible manner (deserialization) + if profile?.trustedNetworks == nil { + profile?.trustedNetworks = TrustedNetworks() + } + + return profile + } + + public func allProfileKeys() -> [ProfileKey] { + return Array(cache.keys) + } + + public func ids(forContext context: Context) -> [String] { + return cache.keys.filter { $0.context == context }.map { $0.id } + } + + public func contextURL(_ key: ProfileKey) -> URL { + switch key.context { + case .provider: + return providersURL + + case .host: + return hostsURL + } + } + + public func profileURL(_ key: ProfileKey) -> URL { + return contextURL(key).appendingPathComponent(key.id).appendingPathExtension("json") + } + + public func profileData(_ key: ProfileKey) throws -> Data { + return try Data(contentsOf: profileURL(key)) + } + + private static func profileId(fromURL url: URL) -> String? { + guard url.pathExtension == "json" else { + return nil + } + return url.deletingPathExtension().lastPathComponent + } + + func reloadHostProfilesFromConfigurationFiles() -> Bool { + var anyReloaded = false + for entry in cache { + guard entry.value.context == .host else { + continue + } + guard let host = profile(withKey: entry.key) as? HostConnectionProfile else { + log.warning("Host context but not a HostConnectionProfile?") + continue + } + guard let url = configurationURL(for: entry.key) else { + continue + } + + // can fail due to passphrase (migration is non-interactive) + if let result = try? OpenVPN.ConfigurationParser.parsed(fromURL: url) { + host.parameters = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: result.configuration).build() + } else { + + // fall back to the safer option + var builder = host.parameters.builder() + var sessionBuilder = builder.sessionConfiguration.builder() + sessionBuilder.routingPolicies = [.IPv4] + builder.sessionConfiguration = sessionBuilder.build() + host.parameters = builder.build() + } + cache[entry.key] = host + + anyReloaded = true + } + return anyReloaded + } + + // MARK: Profiles + + public func hasProfiles() -> Bool { + return !cache.isEmpty + } + + public func addProfile(_ profile: ConnectionProfile, credentials: Credentials?) -> Bool { + guard cache.index(forKey: ProfileKey(profile)) == nil else { + return false + } + addOrReplaceProfile(profile, credentials: credentials) + return true + } + + public func addOrReplaceProfile(_ profile: ConnectionProfile, credentials: Credentials?, title: String? = nil) { + let key = ProfileKey(profile) + cache[key] = profile + if key.context == .host { + hostTitles[key.id] = title + } + try? setCredentials(credentials, for: profile) + + if cache.count == 1 { + activeProfileKey = key + } + delegate?.connectionService(didAdd: profile) + + // serialization (can fail) + saveProfile(profile, withEncoder: JSONEncoder()) + } + + public func renameProfile(_ key: ProfileKey, to newTitle: String) { + precondition(key.context == .host, "Can only rename a HostConnectionProfile") + guard let profile = cache[key] else { + return + } + + hostTitles[key.id] = newTitle + delegate?.connectionService(didRename: profile, to: newTitle) + } + + public func renameProfile(_ profile: ConnectionProfile, to newTitle: String) { + renameProfile(ProfileKey(profile), to: newTitle) + } + + public func removeProfile(_ key: ProfileKey) { + guard let profile = cache[key] else { + return + } + + if key == activeProfileKey { + activeProfileKey = nil + } + cache.removeValue(forKey: key) + if key.context == .host { + hostTitles.removeValue(forKey: key.id) + } + removeCredentials(for: profile) + + delegate?.connectionService(didRemoveProfileWithKey: key) + + // serialization (can fail) + do { + let fm = FileManager.default + if let cfg = configurationURL(for: key) { + try? fm.removeItem(at: cfg) + } + let url = profileURL(key) + try fm.removeItem(at: url) + log.debug("Deleted removed profile '\(profile.id)'") + } catch let e { + log.warning("Could not delete profile '\(profile.id)': \(e)") + } + } + + public func containsProfile(_ key: ProfileKey) -> Bool { + return cache.index(forKey: key) != nil + } + + public func containsProfile(_ profile: ConnectionProfile) -> Bool { + return containsProfile(ProfileKey(profile)) + } + + public func hasActiveProfile() -> Bool { + return activeProfileKey != nil + } + + public func isActiveProfile(_ key: ProfileKey) -> Bool { + return key == activeProfileKey + } + + public func isActiveProfile(_ profile: ConnectionProfile) -> Bool { + return isActiveProfile(ProfileKey(profile)) + } + + public func activateProfile(_ profile: ConnectionProfile) { + activeProfileKey = ProfileKey(profile) + } + + public func existingHostId(withTitle title: String) -> String? { + for id in hostTitles.keys { + guard let _ = cache[ProfileKey(.host, id)] else { + continue + } + if hostTitles[id] == title { + return id + } + } + return nil + } + + public func hostProfile(withTitle title: String) -> HostConnectionProfile? { + guard let id = existingHostId(withTitle: title) else { + return nil + } + return profile(withContext: .host, id: id) as? HostConnectionProfile + } + + // MARK: Credentials + + public func needsCredentials(for profile: ConnectionProfile) -> Bool { + guard profile.requiresCredentials else { + return false + } + guard let creds = credentials(for: profile) else { + return true + } + return !creds.isValid + } + + public func credentials(for profile: ConnectionProfile) -> Credentials? { + guard let username = profile.username else { + return nil + } + let password = (try? keychain.password(for: username, context: profile.passwordContext)) ?? "" // make password optional + return Credentials(username, password) + } + + public func setCredentials(_ credentials: Credentials?, for profile: ConnectionProfile) throws { + profile.username = credentials?.username + try profile.setPassword(credentials?.password, in: keychain) + } + + public func removeCredentials(for profile: ConnectionProfile) { + profile.removePassword(in: keychain) + } + + // MARK: VPN + + public func vpnConfiguration() throws -> NetworkExtensionVPNConfiguration { + guard let profile = activeProfile else { + throw ApplicationError.missingProfile + } + let creds = credentials(for: profile) + if profile.requiresCredentials { + guard creds != nil else { + throw ApplicationError.missingCredentials + } + } + + var cfg = try profile.generate(from: baseConfiguration, preferences: preferences) + + // override network settings + if let choices = profile.networkChoices, let settings = profile.manualNetworkSettings { + var builder = cfg.builder() + var sessionBuilder = builder.sessionConfiguration.builder() + + // enforce default gateway for providers unless "Manual" + if type(of: profile) == ProviderConnectionProfile.self { + if choices.gateway == .manual { + sessionBuilder.applyGateway(from: choices, settings: settings) + } + } else { + sessionBuilder.applyGateway(from: choices, settings: settings) + } + + sessionBuilder.applyDNS(from: choices, settings: settings) + sessionBuilder.applyProxy(from: choices, settings: settings) + sessionBuilder.applyMTU(from: choices, settings: settings) + builder.sessionConfiguration = sessionBuilder.build() + cfg = builder.build() + } + + let protocolConfiguration = try cfg.generatedTunnelProtocol( + withBundleIdentifier: AppConstants.App.tunnelBundleId, + appGroup: appGroup, + credentials: creds + ) + protocolConfiguration.disconnectOnSleep = preferences.disconnectsOnSleep + + log.verbose("Configuration:") + log.verbose(protocolConfiguration) + + var rules: [NEOnDemandRule] = [] + #if os(iOS) + if profile.trustedNetworks.includesMobile { + let rule = policyRule(for: profile) + rule.interfaceTypeMatch = .cellular + rules.append(rule) + } + #else + if profile.trustedNetworks.includesEthernet { + let rule = policyRule(for: profile) + rule.interfaceTypeMatch = .ethernet + rules.append(rule) + } + #endif + let reallyTrustedWifis = Array(profile.trustedNetworks.includedWiFis.filter { $1 }.keys) + if !reallyTrustedWifis.isEmpty { + let rule = policyRule(for: profile) + rule.interfaceTypeMatch = .wiFi + rule.ssidMatch = reallyTrustedWifis + rules.append(rule) + } + let connection = NEOnDemandRuleConnect() + connection.interfaceTypeMatch = .any + rules.append(connection) + + return NetworkExtensionVPNConfiguration( + title: screenTitle(ProfileKey(profile)), + protocolConfiguration: protocolConfiguration, + onDemandRules: rules + ) + } + + private func policyRule(for profile: ConnectionProfile) -> NEOnDemandRule { + switch profile.trustedNetworks.policy { + case .ignore: + return NEOnDemandRuleIgnore() + + case .disconnect: + return NEOnDemandRuleDisconnect() + } + } + + public var vpnLog: String { + return baseConfiguration.existingLog(in: appGroup) ?? "" + } + + public func eraseVpnLog() { + log.info("Erasing VPN log...") + guard let url = baseConfiguration.urlForLog(in: appGroup) else { + return + } + try? FileManager.default.removeItem(at: url) + } + + public var vpnLastError: OpenVPNTunnelProvider.ProviderError? { + return baseConfiguration.lastError(in: appGroup) + } + + public func clearVpnLastError() { + baseConfiguration.clearLastError(in: appGroup) + } + + public func observeVPNDataCount(milliseconds: Int) { + reportDataCountAndRepeat(after: milliseconds) + } + + private func reportDataCountAndRepeat(after milliseconds: Int) { + reportDataCount() + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(milliseconds)) { [weak self] in + self?.reportDataCountAndRepeat(after: milliseconds) + } + } + + private func reportDataCount() { + guard let dataCount = vpnDataCount else { + return + } + NotificationCenter.default.post(name: ConnectionService.didUpdateDataCount, object: nil, userInfo: [NotificationKeys.dataCount: dataCount]) + } + + public var vpnDataCount: (Int, Int)? { + return baseConfiguration.dataCount(in: appGroup) + } +} + +public extension ConnectionService { + func providerNames() -> [Infrastructure.Name] { + return ids(forContext: .provider) + } + + func hostIds() -> [String] { + return ids(forContext: .host) + } + + func sortedProviderNames() -> [Infrastructure.Name] { + return providerNames().sorted() + } + + func sortedHostIds() -> [String] { + return hostIds().sorted { + let title1 = screenTitle(ProfileKey(.host, $0)) + let title2 = screenTitle(ProfileKey(.host, $1)) + return title1.lowercased() < title2.lowercased() + } + } + + func screenTitle(forHostId id: String) -> String { + return screenTitle(ProfileKey(.host, id)) + } + + func screenTitle(forProviderName name: Infrastructure.Name) -> String { + return screenTitle(ProfileKey(.provider, name)) + } + + func screenTitle(_ key: ProfileKey) -> String { + switch key.context { + case .provider: + if let metadata = InfrastructureFactory.shared.metadata(forName: key.id) { + return metadata.description + } + + case .host: + if let title = hostTitles[key.id] { + return title + } + } + return key.id + } +} diff --git a/Passepartout/Core/Sources/Model/Credentials.swift b/Passepartout/Core/Sources/Model/Credentials.swift new file mode 100644 index 00000000..9f54b244 --- /dev/null +++ b/Passepartout/Core/Sources/Model/Credentials.swift @@ -0,0 +1,45 @@ +// +// Credentials.swift +// Passepartout +// +// Created by Davide De Rosa on 6/7/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public typealias Credentials = OpenVPN.Credentials + +public extension Credentials { +// var isEmpty: Bool { +// return username.isEmpty || password.isEmpty +// } + + var isValid: Bool { + return !username.isEmpty + } + + func trimmed() -> Credentials { + let trimmedUsername = username.trimmingCharacters(in: .whitespacesAndNewlines) + let trimmedPassword = password.trimmingCharacters(in: .whitespacesAndNewlines) + return Credentials(trimmedUsername, trimmedPassword) + } +} diff --git a/Passepartout/Core/Sources/Model/DataUnit.swift b/Passepartout/Core/Sources/Model/DataUnit.swift new file mode 100644 index 00000000..66d66b51 --- /dev/null +++ b/Passepartout/Core/Sources/Model/DataUnit.swift @@ -0,0 +1,93 @@ +// +// DataUnit.swift +// Passepartout +// +// Created by Davide De Rosa on 3/30/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public enum DataUnit: Int, CustomStringConvertible { + case byte = 1 + + case kilobyte = 1024 + + case megabyte = 1048576 + + case gigabyte = 1073741824 + + fileprivate var showsDecimals: Bool { + switch self { + case .byte, .kilobyte: + return false + + case .megabyte, .gigabyte: + return true + } + } + + fileprivate var boundary: Int { + return Int(0.1 * Double(rawValue)) + } + + // MARK: CustomStringConvertible + + public var description: String { + switch self { + case .byte: + return "B" + + case .kilobyte: + return "kB" + + case .megabyte: + return "MB" + + case .gigabyte: + return "GB" + } + } +} + +public extension Int { + private static let allUnits: [DataUnit] = [ + .gigabyte, + .megabyte, + .kilobyte, + .byte + ] + + var dataUnitDescription: String { + if self == 0 { + return "0B" + } + for u in Int.allUnits { + if self >= u.boundary { + if !u.showsDecimals { + return "\(self / u.rawValue)\(u)" + } + let count = Double(self) / Double(u.rawValue) + return String(format: "%.2f%@", count, u.description) + } + } + fatalError("Number is negative") + } +} diff --git a/Passepartout/Core/Sources/Model/DebugLog.swift b/Passepartout/Core/Sources/Model/DebugLog.swift new file mode 100644 index 00000000..1af20b0e --- /dev/null +++ b/Passepartout/Core/Sources/Model/DebugLog.swift @@ -0,0 +1,84 @@ +// +// DebugLog.swift +// Passepartout +// +// Created by Davide De Rosa on 6/26/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +#if os(iOS) +import UIKit +#else +import Cocoa +#endif + +public struct DebugLog { + private let raw: String + + public init(raw: String) { + self.raw = raw + } + + public func string() -> String { + return raw + } + + public func data() -> Data? { + return raw.data(using: .utf8) + } + + public func decoratedString() -> String { + let appName = GroupConstants.App.name + let appVersion = GroupConstants.App.versionString + + var metadata: [String] = [] + let osVersion: String + let deviceType: String? + + #if os(iOS) + let device = UIDevice.current + osVersion = "\(device.systemName) \(device.systemVersion)" + deviceType = device.model + #else + let os = ProcessInfo().operatingSystemVersion + osVersion = "macOS \(os.majorVersion).\(os.minorVersion).\(os.patchVersion)" + deviceType = nil + #endif + + metadata.append("App: \(appName) \(appVersion)") + metadata.append("OS: \(osVersion)") + if let deviceType = deviceType { + metadata.append("Device: \(deviceType)") + } + + var fullText = metadata.joined(separator: "\n") + fullText += "\n\n" + fullText += raw + return fullText + } + + public func decoratedData() -> Data { + guard let data = decoratedString().data(using: .utf8) else { + fatalError("Could not encode log metadata to UTF8?") + } + return data + } +} diff --git a/Passepartout/Core/Sources/Model/EndpointDataSource.swift b/Passepartout/Core/Sources/Model/EndpointDataSource.swift new file mode 100644 index 00000000..8e8a12ae --- /dev/null +++ b/Passepartout/Core/Sources/Model/EndpointDataSource.swift @@ -0,0 +1,47 @@ +// +// EndpointDataSource.swift +// Passepartout +// +// Created by Davide De Rosa on 9/5/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public protocol EndpointDataSource { + var mainAddress: String? { get } + + var addresses: [String] { get } + + var protocols: [EndpointProtocol] { get } + + var canCustomizeEndpoint: Bool { get } + + var customAddress: String? { get set } + + var customProtocol: EndpointProtocol? { get set } +} + +public extension EndpointDataSource { + var usesCustomEndpoint: Bool { + return (customAddress != nil) || (customProtocol != nil) + } +} diff --git a/Passepartout/Core/Sources/Model/GracefulVPN.swift b/Passepartout/Core/Sources/Model/GracefulVPN.swift new file mode 100644 index 00000000..15366c61 --- /dev/null +++ b/Passepartout/Core/Sources/Model/GracefulVPN.swift @@ -0,0 +1,140 @@ +// +// GracefulVPN.swift +// Passepartout +// +// Created by Davide De Rosa on 9/18/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SwiftyBeaver +import TunnelKit + +private let log = SwiftyBeaver.self + +public class GracefulVPN { + private let service: ConnectionService + + private var vpn: VPNProvider? { + return VPN.shared + } + + public var isEnabled: Bool { + return vpn?.isEnabled ?? false + } + + public var status: VPNStatus? { + return vpn?.status + } + + public init(service: ConnectionService) { + self.service = service + } + + public func prepare(completionHandler: (() -> Void)?) { + service.clearVpnLastError() + guard let vpn = vpn else { + completionHandler?() + return + } + log.info("Preparing...") + vpn.prepare(completionHandler: completionHandler) + } + + public func reconnect(completionHandler: ((Error?) -> Void)?) { + service.clearVpnLastError() + guard let vpn = vpn else { + completionHandler?(ApplicationError.inactiveProfile) + return + } + do { + log.info("Reconnecting...") + try vpn.reconnect(configuration: service.vpnConfiguration(), completionHandler: completionHandler) + } catch let e { + guard e as? ApplicationError != .externalResources else { + completionHandler?(e) + return + } + log.error("Could not reconnect: \(e)") + } + } + + public func reinstall(completionHandler: ((Error?) -> Void)?) { + service.clearVpnLastError() + guard let vpn = vpn else { + completionHandler?(ApplicationError.inactiveProfile) + return + } + do { + log.info("Reinstalling...") + try vpn.install(configuration: service.vpnConfiguration(), completionHandler: completionHandler) + } catch let e { + guard e as? ApplicationError != .externalResources else { + completionHandler?(e) + return + } + log.error("Could not reinstall: \(e)") + } + } + + public func reinstallIfEnabled() { + guard isEnabled else { + log.warning("Not reinstalling (VPN is disabled)") + return + } + if status != .disconnected { + reconnect(completionHandler: nil) + } else { + reinstall(completionHandler: nil) + } + } + + public func disconnect(completionHandler: ((Error?) -> Void)?) { + guard let vpn = vpn else { + completionHandler?(ApplicationError.inactiveProfile) + return + } + vpn.disconnect(completionHandler: completionHandler) + } + + public func uninstall(completionHandler: (() -> Void)?) { + guard let vpn = vpn else { + completionHandler?() + return + } + vpn.uninstall(completionHandler: completionHandler) + } + + public func requestBytesCount(completionHandler: @escaping ((UInt, UInt)?) -> Void) { + guard let vpn = vpn else { + completionHandler(nil) + return + } + vpn.requestBytesCount(completionHandler: completionHandler) + } + + public func requestServerConfiguration(completionHandler: @escaping (Any?) -> Void) { + guard let vpn = vpn, vpn.status == .connected else { + completionHandler(nil) + return + } + vpn.requestServerConfiguration(completionHandler: completionHandler) + } +} diff --git a/Passepartout/Core/Sources/Model/OpenVPNOptions.swift b/Passepartout/Core/Sources/Model/OpenVPNOptions.swift new file mode 100644 index 00000000..2f537939 --- /dev/null +++ b/Passepartout/Core/Sources/Model/OpenVPNOptions.swift @@ -0,0 +1,63 @@ +// +// OpenVPNOptions.swift +// Passepartout +// +// Created by Davide De Rosa on 6/22/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +extension OpenVPN.Cipher { + public static let available: [OpenVPN.Cipher] = [ + .aes128cbc, + .aes192cbc, + .aes256cbc, + .aes128gcm, + .aes192gcm, + .aes256gcm + ] +} + +extension OpenVPN.Digest { + public static let available: [OpenVPN.Digest] = [ + .sha1, + .sha224, + .sha256, + .sha384, + .sha512 + ] +} + +extension OpenVPN.CompressionFraming { + public static let available: [OpenVPN.CompressionFraming] = [ + .disabled, + .compLZO, + .compress + ] +} + +extension OpenVPN.CompressionAlgorithm { + public static let available: [OpenVPN.CompressionAlgorithm] = [ + .disabled, + .LZO + ] +} diff --git a/Passepartout/Core/Sources/Model/Preferences.swift b/Passepartout/Core/Sources/Model/Preferences.swift new file mode 100644 index 00000000..69246516 --- /dev/null +++ b/Passepartout/Core/Sources/Model/Preferences.swift @@ -0,0 +1,42 @@ +// +// Preferences.swift +// Passepartout +// +// Created by Davide De Rosa on 9/4/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public protocol Preferences { + var launchesOnLogin: Bool? { get } + + var resolvesHostname: Bool { get } + + var disconnectsOnSleep: Bool { get } +} + +public class EditablePreferences: Preferences, Codable { + public var launchesOnLogin: Bool? = false + + public var resolvesHostname: Bool = true + + public var disconnectsOnSleep: Bool = false +} diff --git a/Passepartout/Core/Sources/Model/Product.swift b/Passepartout/Core/Sources/Model/Product.swift new file mode 100644 index 00000000..0eff5313 --- /dev/null +++ b/Passepartout/Core/Sources/Model/Product.swift @@ -0,0 +1,161 @@ +// +// Product.swift +// Passepartout +// +// Created by Davide De Rosa on 10/11/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import StoreKit + +public struct Product: RawRepresentable, Equatable, Hashable { + #if os(iOS) + private static let bundleSubdomain = "ios" + #else + private static let bundleSubdomain = "macos" + #endif + + private static let bundle = "com.algoritmico.\(bundleSubdomain).Passepartout" + + private static let donationsBundle = "\(bundle).donations" + + private static let featuresBundle = "\(bundle).features" + + private static let providersBundle = "\(bundle).providers" + + // MARK: Donations + + public static let tinyDonation = Product(donationDescription: "Tiny") + + public static let smallDonation = Product(donationDescription: "Small") + + public static let mediumDonation = Product(donationDescription: "Medium") + + public static let bigDonation = Product(donationDescription: "Big") + + public static let hugeDonation = Product(donationDescription: "Huge") + + public static let maxiDonation = Product(donationDescription: "Maxi") + + public static let allDonations: [Product] = [ + .tinyDonation, + .smallDonation, + .mediumDonation, + .bigDonation, + .hugeDonation, + .maxiDonation + ] + + private init(donationDescription: String) { + self.init(rawValue: "\(Product.donationsBundle).\(donationDescription)")! + } + + // MARK: Features + + #if os(iOS) + public static let unlimitedHosts = Product(featureId: "unlimited_hosts") + + public static let trustedNetworks = Product(featureId: "trusted_networks") + + public static let siriShortcuts = Product(featureId: "siri") + #endif + + public static let fullVersion = Product(featureId: "full_version") + + #if os(iOS) + public static let allFeatures: [Product] = [ + .unlimitedHosts, + .trustedNetworks, + .siriShortcuts, + .fullVersion + ] + #else + public static let allFeatures: [Product] = [ + .fullVersion + ] + #endif + + private init(featureId: String) { + self.init(rawValue: "\(Product.featuresBundle).\(featureId)")! + } + + // MARK: Providers + + public static var allProviders: [Product] { + return InfrastructureFactory.shared.allMetadata.map { + return Product(providerMetadata: $0) + } + } + + fileprivate init(providerMetadata: Infrastructure.Metadata) { + self.init(rawValue: "\(Product.providersBundle).\(providerMetadata.inApp ?? providerMetadata.name)")! + } + + // MARK: All + + public static var all: [Product] { + return allDonations + allFeatures + allProviders + } + + public var isDonation: Bool { + return rawValue.hasPrefix(Product.donationsBundle) + } + + public var isFeature: Bool { + return rawValue.hasPrefix(Product.featuresBundle) + } + + public var isProvider: Bool { + return rawValue.hasPrefix(Product.providersBundle) + } + + // MARK: RawRepresentable + + public let rawValue: String + + public init?(rawValue: String) { + self.rawValue = rawValue + } + + // MARK: Equatable + + public static func ==(lhs: Product, rhs: Product) -> Bool { + return lhs.rawValue == rhs.rawValue + } + + // MARK: Hashable + + public func hash(into hasher: inout Hasher) { + rawValue.hash(into: &hasher) + } +} + +public extension Infrastructure.Metadata { + var product: Product { + return Product(providerMetadata: self) + } +} + +public extension Product { + func matchesStoreKitProduct(_ skProduct: SKProduct) -> Bool { + return skProduct.productIdentifier == rawValue + } +} diff --git a/Passepartout/Core/Sources/Model/ProductManager.swift b/Passepartout/Core/Sources/Model/ProductManager.swift new file mode 100644 index 00000000..de0f9187 --- /dev/null +++ b/Passepartout/Core/Sources/Model/ProductManager.swift @@ -0,0 +1,250 @@ +// +// ProductManager.swift +// Passepartout +// +// Created by Davide De Rosa on 4/6/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import StoreKit +import Convenience +import SwiftyBeaver +import Kvitto +import TunnelKit + +private let log = SwiftyBeaver.self + +public class ProductManager: NSObject { + public struct Configuration { + public let isBetaFullVersion: Bool + + public let lastFullVersionBuild: Int + + public init( + isBetaFullVersion: Bool, + lastFullVersionBuild: Int + ) { + self.isBetaFullVersion = isBetaFullVersion + self.lastFullVersionBuild = lastFullVersionBuild + } + } + + public static let didReloadReceipt = Notification.Name("ProductManagerDidReloadReceipt") + + public static let didReviewPurchases = Notification.Name("ProductManagerDidReviewPurchases") + + public let cfg: Configuration + + private let inApp: InApp + + private var purchasedAppBuild: Int? + + private var purchasedFeatures: Set + + private var purchaseDates: [Product: Date] + + private var refreshRequest: SKReceiptRefreshRequest? + + private var restoreCompletionHandler: ((Error?) -> Void)? + + public init(_ cfg: Configuration) { + self.cfg = cfg + inApp = InApp() + purchasedAppBuild = nil + purchasedFeatures = [] + purchaseDates = [:] + + super.init() + + reloadReceipt() + SKPaymentQueue.default().add(self) + } + + deinit { + SKPaymentQueue.default().remove(self) + } + + public var isBeta: Bool { + #if targetEnvironment(simulator) + return true + #else + return Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt" + #endif + } + + public func listProducts(completionHandler: (([SKProduct]?, Error?) -> Void)?) { + let products = Product.all + guard !products.isEmpty else { + completionHandler?(nil, nil) + return + } + inApp.requestProducts(withIdentifiers: products, completionHandler: { _ in + log.debug("In-app products: \(self.inApp.products.map { $0.productIdentifier })") + + completionHandler?(self.inApp.products, nil) + }, failureHandler: { + completionHandler?(nil, $0) + }) + } + + public func product(withIdentifier identifier: Product) -> SKProduct? { + return inApp.product(withIdentifier: identifier) + } + + public func featureProducts(includingFullVersion: Bool) -> [SKProduct] { + return inApp.products.filter { + guard let p = Product(rawValue: $0.productIdentifier) else { + return false + } + guard includingFullVersion || p != .fullVersion else { + return false + } + guard p.isFeature else { + return false + } + return true + } + } + + public func purchase(_ product: SKProduct, completionHandler: @escaping (InAppPurchaseResult, Error?) -> Void) { + inApp.purchase(product: product) { + if $0 == .success { + self.reloadReceipt() + } + completionHandler($0, $1) + } + } + + public func restorePurchases(completionHandler: @escaping (Error?) -> Void) { + restoreCompletionHandler = completionHandler + refreshRequest = SKReceiptRefreshRequest() + refreshRequest?.delegate = self + refreshRequest?.start() + } + + // MARK: In-app eligibility + + public func isFullVersion() -> Bool { + #if os(iOS) + if isBeta && cfg.isBetaFullVersion { + return true + } + #else + if cfg.isBetaFullVersion { + return true + } + #endif + return purchasedFeatures.contains(.fullVersion) + } + + public func isEligible(forFeature feature: Product) -> Bool { + return isFullVersion() || purchasedFeatures.contains(feature) + } + + public func isEligible(forProvider metadata: Infrastructure.Metadata) -> Bool { + return isFullVersion() || purchasedFeatures.contains(metadata.product) + } + + public func isEligibleForFeedback() -> Bool { + #if os(iOS) + return isBeta || !purchasedFeatures.isEmpty + #else + return isFullVersion() + #endif + } + + public func purchaseDate(forProduct product: Product) -> Date? { + return purchaseDates[product] + } + + public func reloadReceipt(andNotify: Bool = true) { + guard let url = Bundle.main.appStoreReceiptURL else { + log.warning("No App Store receipt found!") + return + } + guard let receipt = Receipt(contentsOfURL: url) else { + log.error("Could not parse App Store receipt!") + return + } + + if let originalAppVersion = receipt.originalAppVersion, let buildNumber = Int(originalAppVersion) { + purchasedAppBuild = buildNumber + } + purchasedFeatures.removeAll() + + if let buildNumber = purchasedAppBuild { + log.debug("Original purchased build: \(buildNumber)") + + // treat former purchases as full versions + if buildNumber <= cfg.lastFullVersionBuild { + purchasedFeatures.insert(.fullVersion) + } + } + if let iapReceipts = receipt.inAppPurchaseReceipts { + purchaseDates.removeAll() + + log.debug("In-app receipts:") + iapReceipts.forEach { + guard let pid = $0.productIdentifier, let product = Product(rawValue: pid) else { + return + } + if let cancellationDate = $0.cancellationDate { + log.debug("\t\(pid) [cancelled on: \(cancellationDate)]") + return + } + if let purchaseDate = $0.originalPurchaseDate { + log.debug("\t\(pid) [purchased on: \(purchaseDate)]") + purchaseDates[product] = purchaseDate + } + purchasedFeatures.insert(product) + } + } + log.info("Purchased features: \(purchasedFeatures)") + + if andNotify { + NotificationCenter.default.post(name: ProductManager.didReloadReceipt, object: nil) + } + } +} + +extension ProductManager: SKPaymentTransactionObserver { + public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { + reloadReceipt() + } +} + +extension ProductManager: SKRequestDelegate { + public func requestDidFinish(_ request: SKRequest) { + reloadReceipt() + inApp.restorePurchases { [weak self] (finished, _, error) in + guard finished else { + return + } + self?.restoreCompletionHandler?(error) + self?.restoreCompletionHandler = nil + } + } + + public func request(_ request: SKRequest, didFailWithError error: Error) { + restoreCompletionHandler?(error) + restoreCompletionHandler = nil + } +} diff --git a/Passepartout/Core/Sources/Model/ProfileNetworkSettings.swift b/Passepartout/Core/Sources/Model/ProfileNetworkSettings.swift new file mode 100644 index 00000000..4c69725e --- /dev/null +++ b/Passepartout/Core/Sources/Model/ProfileNetworkSettings.swift @@ -0,0 +1,232 @@ +// +// ProfileNetworkSettings.swift +// Passepartout +// +// Created by Davide De Rosa on 04/28/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public enum NetworkChoice: String, Codable { + case client + + case server // erase client settings + + case manual + + public static func choices(for profile: ConnectionProfile?) -> [NetworkChoice] { + if let _ = profile as? HostConnectionProfile { + return [.client, .server, .manual] + } + return [.server, .manual] + } +} + +public struct ProfileNetworkChoices: Codable { + public static let defaultChoice: NetworkChoice = .client + + public var gateway: NetworkChoice + + public var dns: NetworkChoice + + public var proxy: NetworkChoice + + public var mtu: NetworkChoice? + + public init(choice: NetworkChoice) { + gateway = choice + dns = choice + proxy = choice + mtu = choice + } + + public static func with(profile: ConnectionProfile?) -> ProfileNetworkChoices { + if let choices = profile?.networkChoices { + return choices + } + if let _ = profile as? ProviderConnectionProfile { + return ProfileNetworkChoices(choice: .server) + } + return ProfileNetworkChoices(choice: .client) + } +} + +public class ProfileNetworkSettings: Codable, CustomStringConvertible { + public static let mtuOptions: [Int] = [0, 1500, 1400, 1300, 1200] + + public var gatewayPolicies: [OpenVPN.RoutingPolicy]? + + public var dnsServers: [String]? + + public var dnsSearchDomains: [String]? + + public var proxyAddress: String? + + public var proxyPort: UInt16? + + public var proxyServer: Proxy? { + guard let address = proxyAddress, let port = proxyPort, !address.isEmpty, port > 0 else { + return nil + } + return Proxy(address, port) + } + + public var proxyAutoConfigurationURL: URL? + + public var proxyBypassDomains: [String]? + + public var mtuBytes: Int? + + public init() { + gatewayPolicies = [.IPv4, .IPv6] + } + + public init(from configuration: OpenVPN.Configuration) { + gatewayPolicies = configuration.routingPolicies + dnsSearchDomains = configuration.searchDomains + dnsServers = configuration.dnsServers + proxyAddress = configuration.httpProxy?.address + proxyPort = configuration.httpProxy?.port + proxyAutoConfigurationURL = configuration.proxyAutoConfigurationURL + proxyBypassDomains = configuration.proxyBypassDomains + mtuBytes = configuration.mtu + } + + public func copy(from settings: ProfileNetworkSettings) { + copyGateway(from: settings) + copyDNS(from: settings) + copyProxy(from: settings) + copyMTU(from: settings) + } + + public func copyGateway(from settings: ProfileNetworkSettings) { + gatewayPolicies = settings.gatewayPolicies + } + + public func copyDNS(from settings: ProfileNetworkSettings) { + dnsSearchDomains = settings.dnsSearchDomains + dnsServers = settings.dnsServers?.filter { !$0.isEmpty } + } + + public func copyProxy(from settings: ProfileNetworkSettings) { + proxyAddress = settings.proxyAddress + proxyPort = settings.proxyPort + proxyAutoConfigurationURL = settings.proxyAutoConfigurationURL + proxyBypassDomains = settings.proxyBypassDomains?.filter { !$0.isEmpty } + } + + public func copyMTU(from settings: ProfileNetworkSettings) { + mtuBytes = settings.mtuBytes + } + + // MARK: CustomStringConvertible + + public var description: String { + let comps: [String] = [ + "gw: \(gatewayPolicies?.description ?? "")", + "dns: {domains: \(dnsSearchDomains?.description ?? "[]"), servers: \(dnsServers?.description ?? "[]")}", + "proxy: {address: \(proxyAddress ?? ""), port: \(proxyPort?.description ?? ""), PAC: \(proxyAutoConfigurationURL?.absoluteString ?? ""), bypass: \(proxyBypassDomains?.description ?? "[]")}", + "mtu: {bytes: \(mtuBytes?.description ?? "default")}" + ] + return "{\(comps.joined(separator: ", "))}" + } +} + +extension OpenVPN.ConfigurationBuilder { + public mutating func applyGateway(from choices: ProfileNetworkChoices, settings: ProfileNetworkSettings) { + switch choices.gateway { + case .client: + break + + case .server: + routingPolicies = nil + + case .manual: + routingPolicies = settings.gatewayPolicies + } + } + + public mutating func applyDNS(from choices: ProfileNetworkChoices, settings: ProfileNetworkSettings) { + switch choices.dns { + case .client: + break + + case .server: + dnsServers = nil + searchDomains = nil + + case .manual: + dnsServers = settings.dnsServers?.filter { !$0.isEmpty } + searchDomains = settings.dnsSearchDomains + } + } + + public mutating func applyProxy(from choices: ProfileNetworkChoices, settings: ProfileNetworkSettings) { + switch choices.proxy { + case .client: + break + + case .server: + httpProxy = nil + httpsProxy = nil + proxyAutoConfigurationURL = nil + proxyBypassDomains = nil + + case .manual: + if let proxyServer = settings.proxyServer { + httpProxy = proxyServer + httpsProxy = proxyServer + proxyBypassDomains = settings.proxyBypassDomains?.filter { !$0.isEmpty } + } else if let pac = settings.proxyAutoConfigurationURL { + proxyAutoConfigurationURL = pac + proxyBypassDomains = settings.proxyBypassDomains?.filter { !$0.isEmpty } + } else { + httpProxy = nil + httpsProxy = nil + proxyAutoConfigurationURL = nil + proxyBypassDomains = nil + } + } + } + + public mutating func applyMTU(from choices: ProfileNetworkChoices, settings: ProfileNetworkSettings) { + switch choices.mtu ?? ProfileNetworkChoices.defaultChoice { + case .client: + break + + case .server: + mtu = nil + + case .manual: + mtu = settings.mtuBytes + } + } +} + +extension ConnectionProfile { + public var clientNetworkSettings: ProfileNetworkSettings? { + guard let hostProfile = self as? HostConnectionProfile else { + return nil + } + return ProfileNetworkSettings(from: hostProfile.parameters.sessionConfiguration) + } +} diff --git a/Passepartout/Core/Sources/Model/Profiles/HostConnectionProfile.swift b/Passepartout/Core/Sources/Model/Profiles/HostConnectionProfile.swift new file mode 100644 index 00000000..afd9fbf7 --- /dev/null +++ b/Passepartout/Core/Sources/Model/Profiles/HostConnectionProfile.swift @@ -0,0 +1,132 @@ +// +// HostConnectionProfile.m +// Passepartout +// +// Created by Davide De Rosa on 9/2/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public class HostConnectionProfile: ConnectionProfile, Codable, Equatable { + public let hostname: String + + public var parameters: OpenVPNTunnelProvider.Configuration + + public var customAddress: String? + + public var customProtocol: EndpointProtocol? + + public init(hostname: String) { + id = UUID().uuidString + self.hostname = hostname + let sessionConfiguration = OpenVPN.ConfigurationBuilder().build() + parameters = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: sessionConfiguration).build() + + trustedNetworks = TrustedNetworks() + } + + // MARK: ConnectionProfile + + public var context: Context { + return .host + } + + public let id: String + + public var username: String? + + public var requiresCredentials: Bool { + return false + } + + public var trustedNetworks: TrustedNetworks! + + public var networkChoices: ProfileNetworkChoices? + + public var manualNetworkSettings: ProfileNetworkSettings? + + public func generate(from configuration: OpenVPNTunnelProvider.Configuration, preferences: Preferences) throws -> OpenVPNTunnelProvider.Configuration { + guard let endpointProtocols = parameters.sessionConfiguration.endpointProtocols, !endpointProtocols.isEmpty else { + preconditionFailure("No endpointProtocols") + } + + // XXX: copy paste, error prone + var builder = parameters.builder() + builder.shouldDebug = configuration.shouldDebug + builder.debugLogFormat = configuration.debugLogFormat + builder.masksPrivateData = configuration.masksPrivateData + + if let address = customAddress { + builder.prefersResolvedAddresses = true + builder.resolvedAddresses = [address] + } + + // forcibly override hostname with profile hostname (never nil) + var sessionBuilder = builder.sessionConfiguration.builder() + sessionBuilder.hostname = hostname + sessionBuilder.tlsSecurityLevel = 0 // lowest, tolerate widest range of certificates + if sessionBuilder.mtu == nil { + sessionBuilder.mtu = configuration.sessionConfiguration.mtu + } + + if let proto = customProtocol { + sessionBuilder.endpointProtocols = [proto] + } else { + + // restrict "Any" protocol to UDP, unless there are no UDP endpoints + let allEndpoints = builder.sessionConfiguration.endpointProtocols + var endpoints = allEndpoints?.filter { $0.socketType == .udp } + if endpoints?.isEmpty ?? true { + endpoints = allEndpoints + } + sessionBuilder.endpointProtocols = endpoints + } + + builder.sessionConfiguration = sessionBuilder.build() + + return builder.build() + } +} + +public extension HostConnectionProfile { + static func ==(lhs: HostConnectionProfile, rhs: HostConnectionProfile) -> Bool { + return lhs.id == rhs.id + } +} + +public extension HostConnectionProfile { + var mainAddress: String? { + return hostname + } + + var addresses: [String] { + return [hostname] + } + + var protocols: [EndpointProtocol] { + return parameters.sessionConfiguration.endpointProtocols ?? [] + } + + var canCustomizeEndpoint: Bool { + return true + } +} diff --git a/Passepartout/Core/Sources/Model/Profiles/PlaceholderConnectionProfile.swift b/Passepartout/Core/Sources/Model/Profiles/PlaceholderConnectionProfile.swift new file mode 100644 index 00000000..601f9d45 --- /dev/null +++ b/Passepartout/Core/Sources/Model/Profiles/PlaceholderConnectionProfile.swift @@ -0,0 +1,76 @@ +// +// PlaceholderConnectionProfile.swift +// Passepartout +// +// Created by Davide De Rosa on 11/6/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public class PlaceholderConnectionProfile: ConnectionProfile { + public let context: Context + + public let id: String + + public var username: String? = nil + + public var requiresCredentials: Bool = false + + public var trustedNetworks: TrustedNetworks! { + get { + fatalError("Getting trustedNetworks of a PlaceholderConnectionProfile") + } + set { + fatalError("Setting trustedNetworks of a PlaceholderConnectionProfile") + } + } + + public var networkChoices: ProfileNetworkChoices? + + public var manualNetworkSettings: ProfileNetworkSettings? + + public func generate(from configuration: OpenVPNTunnelProvider.Configuration, preferences: Preferences) throws -> OpenVPNTunnelProvider.Configuration { + fatalError("Generating configuration from a PlaceholderConnectionProfile") + } + + public var mainAddress: String? = nil + + public var addresses: [String] = [] + + public var protocols: [EndpointProtocol] = [] + + public var canCustomizeEndpoint: Bool = false + + public var customAddress: String? + + public var customProtocol: EndpointProtocol? + + public init(_ context: Context, _ id: String) { + self.context = context + self.id = id + } + + public init(_ key: ProfileKey) { + context = key.context + id = key.id + } +} diff --git a/Passepartout/Core/Sources/Model/Profiles/PoolCategory.swift b/Passepartout/Core/Sources/Model/Profiles/PoolCategory.swift new file mode 100644 index 00000000..28d47010 --- /dev/null +++ b/Passepartout/Core/Sources/Model/Profiles/PoolCategory.swift @@ -0,0 +1,40 @@ +// +// PoolCategory.swift +// Passepartout +// +// Created by Davide De Rosa on 4/11/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public struct PoolCategory: Codable { + public let name: String + + public let groups: [PoolGroup] + + public let presets: [String]? + + public init(name: String, groups: [PoolGroup], presets: [String]?) { + self.name = name + self.groups = groups + self.presets = presets + } +} diff --git a/Passepartout/Core/Sources/Model/Profiles/ProfileKey.swift b/Passepartout/Core/Sources/Model/Profiles/ProfileKey.swift new file mode 100644 index 00000000..dabfd56f --- /dev/null +++ b/Passepartout/Core/Sources/Model/Profiles/ProfileKey.swift @@ -0,0 +1,77 @@ +// +// ProfileKey.swift +// Passepartout +// +// Created by Davide De Rosa on 11/6/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public struct ProfileKey: RawRepresentable, Hashable, Codable, CustomStringConvertible { + private static let separator: Character = "." + + public let context: Context + + public let id: String + + public init(_ context: Context, _ id: String) { + self.context = context + self.id = id + } + + public init(_ profile: ConnectionProfile) { + context = profile.context + id = profile.id + } + + public init(_ name: Infrastructure.Name) { + context = .provider + id = name + } + + // MARK: RawRepresentable + + public var rawValue: String { + return "\(context)\(ProfileKey.separator)\(id)" + } + + public init?(rawValue: String) { + guard let separatorIndex = rawValue.firstIndex(of: ProfileKey.separator) else { + return nil + } + + let contextValue = rawValue[rawValue.startIndex... +// + +import Foundation +import TunnelKit + +public class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable { + public let name: Infrastructure.Name + + public var infrastructure: Infrastructure { + guard let infra = InfrastructureFactory.shared.infrastructure(forName: name) else { + fatalError("No infrastructure found for '\(name)'") + } + return infra + } + + public var poolId: String { + didSet { + validateEndpoint() + } + } + + public var pool: Pool? { + return infrastructure.pool(for: poolId) + } + + public var presetId: String { + didSet { + validateEndpoint() + } + } + + public var preset: InfrastructurePreset? { + return infrastructure.preset(for: presetId) + } + + public var customAddress: String? + + public var customProtocol: EndpointProtocol? + + public var favoriteGroupIds: [String]? + + public init(name: Infrastructure.Name) { + self.name = name + poolId = "" + presetId = "" + + username = nil + + poolId = infrastructure.defaultPool()?.id ?? infrastructure.defaults.pool + presetId = infrastructure.defaults.preset + + trustedNetworks = TrustedNetworks() + favoriteGroupIds = [] + } + + public func setSupportedPreset() { + guard let pool = pool else { + return + } + let supported = pool.supportedPresetIds(in: infrastructure) + if let current = preset?.id, !supported.contains(current), let fallback = supported.first { + presetId = fallback + } + } + + private func validateEndpoint() { + guard let pool = pool, let preset = preset else { + customAddress = nil + customProtocol = nil + return + } + if let address = customAddress, !pool.hasAddress(address) { + customAddress = nil + } + if let proto = customProtocol, !preset.hasProtocol(proto) { + customProtocol = nil + } + } + + // MARK: ConnectionProfile + + public var context: Context { + return .provider + } + + public var id: String { + return name + } + + public var username: String? + + public var requiresCredentials: Bool { + return true + } + + public var trustedNetworks: TrustedNetworks! + + public var networkChoices: ProfileNetworkChoices? + + public var manualNetworkSettings: ProfileNetworkSettings? + + public func generate(from configuration: OpenVPNTunnelProvider.Configuration, preferences: Preferences) throws -> OpenVPNTunnelProvider.Configuration { + guard let pool = pool else { + preconditionFailure("Nil pool?") + } + guard let preset = preset else { + preconditionFailure("Nil preset?") + } + +// assert(!pool.numericAddresses.isEmpty) + + // XXX: copy paste, error prone + var builder = preset.configuration.builder() + builder.shouldDebug = configuration.shouldDebug + builder.debugLogFormat = configuration.debugLogFormat + builder.masksPrivateData = configuration.masksPrivateData + + do { + try preset.injectExternalConfiguration(&builder, with: name, pool: pool) + } catch { + throw ApplicationError.externalResources + } + + if let address = customAddress { + builder.prefersResolvedAddresses = true + builder.resolvedAddresses = [address] + } else if builder.sessionConfiguration.hostname == nil || (pool.isResolved ?? false) { + builder.prefersResolvedAddresses = true + builder.resolvedAddresses = pool.addresses() + } else { + builder.prefersResolvedAddresses = !preferences.resolvesHostname + builder.resolvedAddresses = pool.addresses() + } + + var sessionBuilder = builder.sessionConfiguration.builder() + if let proto = customProtocol { + sessionBuilder.endpointProtocols = [proto] + } else { + + // restrict "Any" protocol to UDP, unless there are no UDP endpoints + let allEndpoints = builder.sessionConfiguration.endpointProtocols + var endpoints = allEndpoints?.filter { $0.socketType == .udp } + if endpoints?.isEmpty ?? true { + endpoints = allEndpoints + } + + sessionBuilder.endpointProtocols = endpoints +// sessionBuilder.endpointProtocols = [ +// EndpointProtocol(.udp, 8080), +// EndpointProtocol(.tcp, 443) +// ] + } + sessionBuilder.routingPolicies = [.IPv4, .IPv6] + if sessionBuilder.mtu == nil { + sessionBuilder.mtu = configuration.sessionConfiguration.mtu + } + builder.sessionConfiguration = sessionBuilder.build() + + return builder.build() + } +} + +public extension ProviderConnectionProfile { + static func ==(lhs: ProviderConnectionProfile, rhs: ProviderConnectionProfile) -> Bool { + return lhs.id == rhs.id + } +} + +public extension ProviderConnectionProfile { + var mainAddress: String? { + guard let pool = pool else { + assertionFailure("Getting provider main address but no pool set") + return nil + } + return pool.hostname + } + + var addresses: [String] { + var addrs = pool?.addresses() ?? [] + if let pool = pool, pool.hostname == nil, !(pool.isResolved ?? false), let externalHostname = try? preset?.externalConfiguration(forKey: .hostname, infrastructureName: infrastructure.name, pool: pool) as? String { + addrs.insert(externalHostname, at: 0) + } + return addrs + } + + var protocols: [EndpointProtocol] { + return preset?.configuration.sessionConfiguration.endpointProtocols ?? [] + } + + var canCustomizeEndpoint: Bool { + return true + } +} + +public extension ConnectionService { + func setPoolId(_ poolId: String, forProviderProfile profile: ProviderConnectionProfile) { + profile.poolId = poolId + delegate?.connectionService(didUpdate: profile) + } +} diff --git a/Passepartout/Core/Sources/Model/SessionProxy+Communication.swift b/Passepartout/Core/Sources/Model/SessionProxy+Communication.swift new file mode 100644 index 00000000..df75575d --- /dev/null +++ b/Passepartout/Core/Sources/Model/SessionProxy+Communication.swift @@ -0,0 +1,42 @@ +// +// SessionProxy+Communication.swift +// Passepartout +// +// Created by Davide De Rosa on 9/4/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public extension OpenVPN.ConfigurationBuilder { +// mutating func copyCommunication(from other: OpenVPN.ConfigurationBuilder) { +// cipher = other.cipher +// digest = other.digest +// compressionFraming = other.compressionFraming +// } + + func canCommunicate(with other: OpenVPN.Configuration) -> Bool { + return + (cipher == other.cipher) && + ((digest == other.digest) || fallbackCipher.embedsDigest) && + (compressionFraming == other.compressionFraming) + } +} diff --git a/Passepartout/Core/Sources/Model/TransientStore.swift b/Passepartout/Core/Sources/Model/TransientStore.swift new file mode 100644 index 00000000..de041ace --- /dev/null +++ b/Passepartout/Core/Sources/Model/TransientStore.swift @@ -0,0 +1,255 @@ +// +// TransientStore.swift +// Passepartout +// +// Created by Davide De Rosa on 7/16/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +public class TransientStore { + private struct Keys { + static let didHandleSubreddit = "DidHandleSubreddit" + + static let masksPrivateData = "MasksPrivateData" + + // migrations + + static let didMigrateHostsRoutingPolicies = "DidMigrateHostsRoutingPolicies" + + static let didMigrateDynamicProviders = "DidMigrateDynamicProviders" + + static let didMigrateHostsToUUID = "DidMigrateHostsToUUID" + + static let didMigrateKeychainContext = "didMigrateKeychainContext" + } + + public static let shared = TransientStore() + + private static var serviceURL: URL { + return GroupConstants.App.documentsURL.appendingPathComponent(AppConstants.Store.serviceFilename) + } + + public let service: ConnectionService + + public static var didHandleSubreddit: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.didHandleSubreddit) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.didHandleSubreddit) + } + } + + public static var masksPrivateData: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.masksPrivateData) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.masksPrivateData) + } + } + + public static var didMigrateHostsRoutingPolicies: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.didMigrateHostsRoutingPolicies) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.didMigrateHostsRoutingPolicies) + } + } + + public static var didMigrateDynamicProviders: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.didMigrateDynamicProviders) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.didMigrateDynamicProviders) + } + } + + public static var didMigrateHostsToUUID: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.didMigrateHostsToUUID) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.didMigrateHostsToUUID) + } + } + + public static var didMigrateKeychainContext: Bool { + get { + return UserDefaults.standard.bool(forKey: Keys.didMigrateKeychainContext) + } + set { + UserDefaults.standard.set(newValue, forKey: Keys.didMigrateKeychainContext) + } + } + + public static var baseVPNConfiguration: OpenVPNTunnelProvider.ConfigurationBuilder { + let sessionBuilder = OpenVPN.ConfigurationBuilder() + var builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) + builder.shouldDebug = true +// builder.debugLogFormat = "$Dyyyy-MM-dd HH:mm:ss.SSS$d $L $N.$F:$l - $M" +// builder.debugLogFormat = "$DHH:mm:ss$d $N.$F:$l - $M" + builder.debugLogFormat = AppConstants.Log.debugFormat + builder.masksPrivateData = masksPrivateData + return builder + } + + private init() { + UserDefaults.standard.register(defaults: [ + Keys.didHandleSubreddit: false, + Keys.masksPrivateData: true + ]) + + TransientStore.migrateDocumentsToAppGroup() + + // this must be graceful + ConnectionService.migrateJSON(from: TransientStore.serviceURL, to: TransientStore.serviceURL) + + let cfg = TransientStore.baseVPNConfiguration.build() + do { + var data = try Data(contentsOf: TransientStore.serviceURL) + if let content = String(data: data, encoding: .utf8) { + log.verbose("Service JSON:") + log.verbose(content) + } + + // pre-parsing migrations + if let migratedData = TransientStore.migratedDataIfNecessary(fromData: data) { + data = migratedData + } + + service = try JSONDecoder().decode(ConnectionService.self, from: data) + service.baseConfiguration = cfg + + // pre-load migrations + if !TransientStore.didMigrateDynamicProviders { + service.migrateProvidersToLowercase() + TransientStore.didMigrateDynamicProviders = true + } + if !TransientStore.didMigrateHostsToUUID { + service.migrateHostsToUUID() + TransientStore.didMigrateHostsToUUID = true + } + + service.loadProfiles() + + if !TransientStore.didMigrateKeychainContext { + service.migrateKeychainContext() + TransientStore.didMigrateKeychainContext = true + } + + // post-load migrations + if !TransientStore.didMigrateHostsRoutingPolicies { + if service.reloadHostProfilesFromConfigurationFiles() { + service.saveProfiles() + } + TransientStore.didMigrateHostsRoutingPolicies = true + } + } catch let e { + log.error("Could not decode service: \(e)") + service = ConnectionService( + withAppGroup: GroupConstants.App.groupId, + baseConfiguration: cfg + ) + + // fresh install, skip all migrations + TransientStore.didMigrateHostsRoutingPolicies = true + TransientStore.didMigrateDynamicProviders = true + TransientStore.didMigrateHostsToUUID = true + TransientStore.didMigrateKeychainContext = true + +// // hardcoded loading +// _ = service.addProfile(ProviderConnectionProfile(name: .pia), credentials: nil) +// _ = service.addProfile(HostConnectionProfile(title: "vps"), credentials: Credentials(username: "foo", password: "bar")) +// service.activateProfile(service.profiles.first!) + } + service.observeVPNDataCount(milliseconds: GroupConstants.VPN.dataCountInterval) + } + + public func serialize(withProfiles: Bool) { + try? JSONEncoder().encode(service).write(to: TransientStore.serviceURL) + if withProfiles { + service.saveProfiles() + } + } + + // + + private static func migrateDocumentsToAppGroup() { + var hasMigrated = false + let oldDocumentsURL = FileManager.default.userURL(for: .documentDirectory, appending: nil) + let newDocumentsURL = GroupConstants.App.documentsURL + log.debug("App documentsURL: \(oldDocumentsURL)") + log.debug("Group documentsURL: \(newDocumentsURL)") + let fm = FileManager.default + do { + for c in try fm.contentsOfDirectory(atPath: oldDocumentsURL.path) { + guard c != "Inbox" else { + continue + } + let old = oldDocumentsURL.appendingPathComponent(c) + let new = newDocumentsURL.appendingPathComponent(c) + log.verbose("Move:") + log.verbose("\tFROM: \(old)") + log.verbose("\tTO: \(new)") + try fm.moveItem(at: old, to: new) + hasMigrated = true + } + } catch let e { + hasMigrated = false + log.error("Could not migrate documents to App Group: \(e)") + } + if hasMigrated { + log.debug("Documents migrated to App Group") + } + } + + private static func migratedDataIfNecessary(fromData data: Data) -> Data? { + guard !TransientStore.didMigrateHostsToUUID else { + return data + } + + guard var json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { + return nil + } + + // do JSON migrations here + migrateHostTitles(&json) + + guard let migratedData = try? JSONSerialization.data(withJSONObject: json, options: []) else { + return nil + } + return migratedData + } + + private static func migrateHostTitles(_ json: inout [String: Any]) { + if json["hostTitles"] == nil { + json["hostTitles"] = [:] + } + } +} diff --git a/Passepartout/Core/Sources/Model/TrustPolicy.swift b/Passepartout/Core/Sources/Model/TrustPolicy.swift new file mode 100644 index 00000000..b50109be --- /dev/null +++ b/Passepartout/Core/Sources/Model/TrustPolicy.swift @@ -0,0 +1,32 @@ +// +// TrustPolicy.swift +// Passepartout +// +// Created by Davide De Rosa on 9/2/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public enum TrustPolicy: String, Codable { + case ignore + + case disconnect +} diff --git a/Passepartout/Core/Sources/Model/TrustedNetworks.swift b/Passepartout/Core/Sources/Model/TrustedNetworks.swift new file mode 100644 index 00000000..4e5d34ee --- /dev/null +++ b/Passepartout/Core/Sources/Model/TrustedNetworks.swift @@ -0,0 +1,41 @@ +// +// TrustPolicy.swift +// Passepartout +// +// Created by Davide De Rosa on 11/21/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public struct TrustedNetworks: Codable { + #if os(iOS) + public var includesMobile = false + #else + public var includesEthernet = false + #endif + + public var includedWiFis: [String: Bool] = [:] + + public var policy: TrustPolicy = .disconnect + + public init() { + } +} diff --git a/Passepartout/Core/Sources/Services/Infrastructure+Metadata.swift b/Passepartout/Core/Sources/Services/Infrastructure+Metadata.swift new file mode 100644 index 00000000..b527d68d --- /dev/null +++ b/Passepartout/Core/Sources/Services/Infrastructure+Metadata.swift @@ -0,0 +1,57 @@ +// +// Infrastructure+Metadata.swift +// Passepartout +// +// Created by Davide De Rosa on 11/24/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +extension Infrastructure { + public struct Metadata: Codable, Hashable, Comparable, CustomStringConvertible { + public let name: Name + + public let inApp: String? + + // MARK: CustomStringConvertible + + public let description: String + + // MARK: Hashable + + public func hash(into hasher: inout Hasher) { + name.hash(into: &hasher) + } + + public static func ==(lhs: Infrastructure.Metadata, rhs: Infrastructure.Metadata) -> Bool { + return lhs.name == rhs.name + } + + // MARK: Comparable + + public static func <(lhs: Infrastructure.Metadata, rhs: Infrastructure.Metadata) -> Bool { + return lhs.name < rhs.name + } + } +} diff --git a/Passepartout/Core/Sources/Services/Infrastructure+Name.swift b/Passepartout/Core/Sources/Services/Infrastructure+Name.swift new file mode 100644 index 00000000..fcf469fc --- /dev/null +++ b/Passepartout/Core/Sources/Services/Infrastructure+Name.swift @@ -0,0 +1,53 @@ +// +// Infrastructure+Name.swift +// Passepartout +// +// Created by Davide De Rosa on 11/24/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +extension Infrastructure { + public typealias Name = String +} + +extension Infrastructure.Name { + public static let hideme = "hideme" + + public static let mullvad = "mullvad" + + public static let nordvpn = "nordvpn" + + public static let pia = "pia" + + public static let protonvpn = "protonvpn" + + public static let torguard = "torguard" + + public static let tunnelbear = "tunnelbear" + + public static let vyprvpn = "vyprvpn" + + public static let windscribe = "windscribe" +} diff --git a/Passepartout/Core/Sources/Services/Infrastructure.swift b/Passepartout/Core/Sources/Services/Infrastructure.swift new file mode 100644 index 00000000..dd3d394f --- /dev/null +++ b/Passepartout/Core/Sources/Services/Infrastructure.swift @@ -0,0 +1,124 @@ +// +// Infrastructure.swift +// Passepartout +// +// Created by Davide De Rosa on 6/11/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SSZipArchive + +public class Infrastructure: Codable { + public struct Defaults: Codable { + public let username: String? + + public let pool: String + + public let preset: String + } + + public let build: [String: Int] + + public var buildNumber: Int { + var num: Int? + #if os(iOS) + num = build["ios"] + #else + num = build["macos"] + #endif + return num ?? 0 + } + + public let name: Name + + public let categories: [PoolCategory] + + public let presets: [InfrastructurePreset] + + public let defaults: Defaults + + public static func from(url: URL) throws -> Infrastructure { + let json = try Data(contentsOf: url) + return try JSONDecoder().decode(Infrastructure.self, from: json) + } + + public func defaultPool() -> Pool? { + return pool(withPrefix: defaults.pool) + } + + public func pool(for identifier: String) -> Pool? { + for cat in categories { + for group in cat.groups { + guard let found = group.pools.first(where: { $0.id == identifier }) else { + continue + } + return found + } + } + return nil + } + + public func pool(withPrefix prefix: String) -> Pool? { + for cat in categories { + for group in cat.groups { + guard let found = group.pools.first(where: { $0.id.hasPrefix(prefix) }) else { + continue + } + return found + } + } + return nil + } + + public func preset(for identifier: String) -> InfrastructurePreset? { + return presets.first { $0.id == identifier } + } +} + +extension Infrastructure.Name { + public var externalURL: URL { + return GroupConstants.App.externalURL.appendingPathComponent(self) + } + + public func importExternalResources(from url: URL, completionHandler: @escaping () -> Void) { + var task: () -> Void + switch self { + case .nordvpn: + task = { + SSZipArchive.unzipFile(atPath: url.path, toDestination: self.externalURL.path) + } + + default: + task = {} + } + execute(task: task, completionHandler: completionHandler) + } + + private func execute(task: @escaping () -> Void, completionHandler: @escaping () -> Void) { + let queue: DispatchQueue = .global(qos: .background) + queue.async { + task() + DispatchQueue.main.async { + completionHandler() + } + } + } +} diff --git a/Passepartout/Core/Sources/Services/InfrastructureFactory.swift b/Passepartout/Core/Sources/Services/InfrastructureFactory.swift new file mode 100644 index 00000000..15a1b1a5 --- /dev/null +++ b/Passepartout/Core/Sources/Services/InfrastructureFactory.swift @@ -0,0 +1,362 @@ +// +// InfrastructureFactory.swift +// Passepartout +// +// Created by Davide De Rosa on 9/2/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +// TODO: retain max N infrastructures at a time (LRU) + +public class InfrastructureFactory { + public static let shared = InfrastructureFactory() + + private let cachePath: URL + + fileprivate var cachedMetadata: [Infrastructure.Metadata] + + private var cachedInfrastructures: [Infrastructure.Name: Infrastructure] + + private var lastUpdate: [Infrastructure.Name: Date] + + private init() { + cachePath = GroupConstants.App.cachesURL + cachedMetadata = [] + cachedInfrastructures = [:] + lastUpdate = [:] + } + + // MARK: Storage + + public func preload() { + loadMetadata() + loadInfrastructures() + } + + public func loadMetadata() { + let decoder = JSONDecoder() + + // pick cache if newer + if Utils.isFile(at: cacheMetadataURL, newerThanFileAt: bundledMetadataURL) { + do { + let indexData = try Data(contentsOf: cacheMetadataURL) + cachedMetadata = try decoder.decode([Infrastructure.Metadata].self, from: indexData) + log.debug("Loaded metadata from cache: \(cachedMetadata)") + return + } catch let e { + log.warning("No index in cache: \(e)") + } + } else { + log.warning("Bundle is newer than cache, superseding cache for index") + } + + // fall back to bundled index + guard let bundleURL = bundledMetadataURL else { + fatalError("Unable to build index bundleURL") + } + do { + let indexData = try Data(contentsOf: bundleURL) + cachedMetadata = try decoder.decode([Infrastructure.Metadata].self, from: indexData) + log.debug("Loaded index from bundle: \(cachedMetadata)") + } catch let e { + log.error("Unable to load index from bundle: \(e)") + } + } + + public func loadInfrastructures() { + let apiPath = cachePath.appendingPathComponent(AppConstants.Store.apiDirectory) + let providersPath = apiPath.appendingPathComponent(WebServices.Group.providers.rawValue) + + log.debug("Loading cache from: \(providersPath)") + let cacheProvidersEntries: [URL] + do { + cacheProvidersEntries = try FileManager.default.contentsOfDirectory(at: providersPath, includingPropertiesForKeys: nil) + } catch let e { + log.warning("Error loading cache or nothing cached: \(e)") + + cachedMetadata.forEach { + guard let infra = bundledInfrastructure(withName: $0.name) else { + log.warning("Missing infrastructure \($0.name) from bundle") + return + } + cachedInfrastructures[$0.name] = infra + log.debug("Loaded infrastructure \($0.name) from bundle") + } + return + } + + let decoder = JSONDecoder() + for entry in cacheProvidersEntries { + let name = entry.lastPathComponent + + // skip *.json (index.json presumably) + guard !name.hasSuffix(".json") else { + continue + } + + // pick cache if newer + if Utils.isFile(at: entry, newerThanFileAt: name.bundleURL) { + let infraPath = WebServices.Endpoint.providerNetwork(name).apiURL(relativeTo: cachePath) + do { + let infraData = try Data(contentsOf: infraPath) + let infra = try decoder.decode(Infrastructure.self, from: infraData) + cachedInfrastructures[name] = infra + log.debug("Loaded infrastructure \(name) from cache") + continue + } catch let e { + log.warning("Unable to load infrastructure \(entry.lastPathComponent): \(e)") +// if let json = String(data: data, encoding: .utf8) { +// log.warning(json) +// } + } + } else { + log.warning("Bundle is newer than cache, superseding cache for \(name)") + } + + // fall back to bundle + guard let infra = bundledInfrastructure(withName: name) else { + log.warning("Missing infrastructure \(name) from bundle") + continue + } + cachedInfrastructures[name] = infra + log.debug("Loaded infrastructure \(name) from bundle") + } + + // fill up with bundled + cachedMetadata.forEach { + if cachedInfrastructures[$0.name] == nil { + guard let infra = bundledInfrastructure(withName: $0.name) else { + log.warning("Missing infrastructure \($0.name) from bundle") + return + } + cachedInfrastructures[$0.name] = infra + log.debug("Loaded infrastructure \($0.name) from bundle") + } + } + } + + public var allMetadata: [Infrastructure.Metadata] { + return cachedMetadata + } + + public func metadata(forName name: Infrastructure.Name) -> Infrastructure.Metadata? { + return cachedMetadata.first(where: { $0.name == name}) + } + + public func infrastructure(forName name: Infrastructure.Name) -> Infrastructure? { + return cachedInfrastructures[name] + } + + private func bundledInfrastructure(withName name: Infrastructure.Name) -> Infrastructure? { + guard let url = name.bundleURL else { + return nil + } + do { + return try Infrastructure.from(url: url) + } catch let e { + fatalError("Cannot parse JSON for infrastructure '\(name)': \(e)") + } + } + + // MARK: Web services + + public func updateIndex(completionHandler: @escaping (Error?) -> Void) { + WebServices.shared.providersIndex { + if let response = $0 { + self.saveIndex(with: response) + } + completionHandler($1) + } + } + + public func update(_ name: Infrastructure.Name, notBeforeInterval minInterval: TimeInterval?, completionHandler: @escaping ((Infrastructure, Date)?, Error?) -> Void) -> Bool { + let ifModifiedSince = modificationDate(forName: name) + + if let lastInfrastructureUpdate = lastUpdate[name] { + log.debug("Last update for \(name): \(lastUpdate)") + + if let minInterval = minInterval { + let elapsed = -lastInfrastructureUpdate.timeIntervalSinceNow + guard elapsed >= minInterval else { + log.warning("Skipping update, only \(elapsed) seconds elapsed (< \(minInterval))") + return false + } + } + } + + WebServices.shared.providerNetwork(with: name, ifModifiedSince: ifModifiedSince) { (response, error) in + if error == nil { + self.lastUpdate[name] = Date() + } + + guard let response = response else { + log.error("No response from web service") + DispatchQueue.main.async { + completionHandler(nil, error) + } + return + } + if response.isCached { + log.debug("Cache is up to date") + DispatchQueue.main.async { + completionHandler(nil, error) + } + return + } + guard let infra = response.value, let lastModified = response.lastModified else { + log.error("No response from web service or missing Last-Modified") + DispatchQueue.main.async { + completionHandler(nil, error) + } + return + } + let appBuild = GroupConstants.App.buildNumber + guard appBuild >= infra.buildNumber else { + log.error("Response requires app build >= \(infra.build) (found \(appBuild))") + DispatchQueue.main.async { + completionHandler(nil, error) + } + return + } + + var isNewer = true + if let bundleDate = self.bundleModificationDate(forName: name) { + log.verbose("Bundle date: \(bundleDate)") + log.verbose("Web date: \(lastModified)") + + isNewer = lastModified > bundleDate + } + guard isNewer else { + log.warning("Web service infrastructure is older than bundle, discarding") + DispatchQueue.main.async { + completionHandler(nil, error) + } + return + } + + self.save(name, with: infra, lastModified: lastModified) + + DispatchQueue.main.async { + completionHandler((infra, lastModified), nil) + } + } + return true + } + + private func saveIndex(with metadata: [Infrastructure.Metadata]) { + cachedMetadata = metadata + + let fm = FileManager.default + let url = cacheMetadataURL + do { + let parent = url.deletingLastPathComponent() + try fm.createDirectory(at: parent, withIntermediateDirectories: true, attributes: nil) + let data = try JSONEncoder().encode(metadata) + try data.write(to: url) + } catch let e { + log.error("Error saving index to cache: \(e)") + } + } + + private func save(_ name: Infrastructure.Name, with infrastructure: Infrastructure, lastModified: Date) { + cachedInfrastructures[name] = infrastructure + + let fm = FileManager.default + let url = cacheURL(forName: name) + do { + let parent = url.deletingLastPathComponent() + try fm.createDirectory(at: parent, withIntermediateDirectories: true, attributes: nil) + let data = try JSONEncoder().encode(infrastructure) + try data.write(to: url) + try fm.setAttributes([.modificationDate: lastModified], ofItemAtPath: url.path) + } catch let e { + log.error("Error saving infrastructure \(name) to cache: \(e)") + } + } + + // MARK: URLs + + private var cacheMetadataURL: URL { + return WebServices.Endpoint.providersIndex.apiURL(relativeTo: cachePath) + } + + private func cacheURL(forName name: Infrastructure.Name) -> URL { + return WebServices.Endpoint.providerNetwork(name).apiURL(relativeTo: cachePath) + } + + private var bundledMetadataURL: URL? { + return WebServices.Endpoint.providersIndex.bundleURL(in: Bundle(for: InfrastructureFactory.self)) + } + + // MARK: Modification dates + + public func modificationDate(forName name: Infrastructure.Name) -> Date? { + let optBundleDate = bundleModificationDate(forName: name) + guard let cacheDate = cacheModificationDate(forName: name) else { + return optBundleDate + } + guard let bundleDate = optBundleDate else { + return cacheDate + } + return max(cacheDate, bundleDate) + } + + private func cacheModificationDate(forName name: Infrastructure.Name) -> Date? { + let url = cacheURL(forName: name) + return FileManager.default.modificationDate(of: url.path) + } + + private func bundleModificationDate(forName name: Infrastructure.Name) -> Date? { + guard let url = name.bundleURL else { + return nil + } + return FileManager.default.modificationDate(of: url.path) + } +} + +extension Infrastructure { + public var metadata: Metadata? { + return InfrastructureFactory.shared.metadata(forName: name) + } +} + +private extension Infrastructure.Name { + var bundleURL: URL? { + return WebServices.Endpoint.providerNetwork(self).bundleURL(in: Bundle(for: InfrastructureFactory.self)) + } +} + +extension ConnectionService { + public func availableProviders() -> [Infrastructure.Metadata] { + let names = Set(ids(forContext: .provider)) + return InfrastructureFactory.shared.cachedMetadata.filter { !names.contains($0.name) } + } + + public func hasAvailableProviders() -> Bool { + var allNames = Set(InfrastructureFactory.shared.cachedMetadata.map { $0.name }) + allNames.subtract(ids(forContext: .provider)) + return !allNames.isEmpty + } +} diff --git a/Passepartout/Core/Sources/Services/InfrastructurePreset.swift b/Passepartout/Core/Sources/Services/InfrastructurePreset.swift new file mode 100644 index 00000000..ae2abf0f --- /dev/null +++ b/Passepartout/Core/Sources/Services/InfrastructurePreset.swift @@ -0,0 +1,236 @@ +// +// InfrastructurePreset.swift +// Passepartout +// +// Created by Davide De Rosa on 8/30/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +// supports a subset of OpenVPNTunnelProvider.Configuration +// ignores new JSON keys + +public class InfrastructurePreset: Codable { + public enum ExternalKey: String, Codable { + case ca + + case client + + case key + + case wrapKeyData = "wrap.key.data" + + case hostname + } + + public enum PresetKeys: String, CodingKey { + case id + + case name + + case comment + + case configuration = "cfg" + + case external + } + + public enum ConfigurationKeys: String, CodingKey { + case endpointProtocols = "ep" + + case cipher + + case digest = "auth" + + case ca + + case clientCertificate = "client" + + case clientKey = "key" + + case compressionFraming = "frame" + + case compressionAlgorithm = "compression" + + case keepAliveSeconds = "ping" + + case keepAliveTimeoutSeconds = "pingTimeout" + + case renegotiatesAfterSeconds = "reneg" + + case tlsWrap = "wrap" + + case checksEKU = "eku" + + case randomizeEndpoint = "random" + + case usesPIAPatches = "pia" + } + + public let id: String + + public let name: String + + public let comment: String + + public let configuration: OpenVPNTunnelProvider.Configuration + + public let external: [ExternalKey: String]? + + public func hasProtocol(_ proto: EndpointProtocol) -> Bool { + return configuration.sessionConfiguration.endpointProtocols?.firstIndex(of: proto) != nil + } + + public func externalConfiguration(forKey key: ExternalKey, infrastructureName: Infrastructure.Name, pool: Pool) throws -> Any? { + guard let pattern = external?[key] else { + return nil + } + let baseURL = infrastructureName.externalURL + switch key { + case .ca: + let filename = pattern.replacingOccurrences(of: "${id}", with: pool.id) + let caURL = baseURL.appendingPathComponent(filename) + return OpenVPN.CryptoContainer(pem: try String(contentsOf: caURL)) + + case .wrapKeyData: + let filename = pattern.replacingOccurrences(of: "${id}", with: pool.id) + let tlsKeyURL = baseURL.appendingPathComponent(filename) + let file = try String(contentsOf: tlsKeyURL) + return OpenVPN.StaticKey(file: file, direction: .client) + + case .hostname: + return pattern.replacingOccurrences(of: "${id}", with: pool.id) + + default: + break + } + return nil + } + + public func injectExternalConfiguration(_ configuration: inout OpenVPNTunnelProvider.ConfigurationBuilder, with infrastructureName: Infrastructure.Name, pool: Pool) throws { + guard let external = external, !external.isEmpty else { + return + } + + var sessionBuilder = configuration.sessionConfiguration.builder() + if let _ = external[.ca] { + sessionBuilder.ca = try externalConfiguration(forKey: .ca, infrastructureName: infrastructureName, pool: pool) as? OpenVPN.CryptoContainer + } + if let _ = external[.wrapKeyData] { + if let dummyWrap = sessionBuilder.tlsWrap { + if let staticKey = try externalConfiguration(forKey: .wrapKeyData, infrastructureName: infrastructureName, pool: pool) as? OpenVPN.StaticKey { + sessionBuilder.tlsWrap = OpenVPN.TLSWrap(strategy: dummyWrap.strategy, key: staticKey) + } + } + } + if let _ = external[.hostname] { + sessionBuilder.hostname = try externalConfiguration(forKey: .hostname, infrastructureName: infrastructureName, pool: pool) as? String + } + configuration.sessionConfiguration = sessionBuilder.build() + } + + // MARK: Codable + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: PresetKeys.self) + id = try container.decode(String.self, forKey: .id) + name = try container.decode(String.self, forKey: .name) + comment = try container.decode(String.self, forKey: .comment) + if let rawExternal = try container.decodeIfPresent([String: String].self, forKey: .external) { + var remapped: [ExternalKey: String] = [:] + for entry in rawExternal { + guard let key = ExternalKey(rawValue: entry.key) else { + continue + } + remapped[key] = entry.value + } + external = remapped + } else { + external = nil + } + + let cfgContainer = try container.nestedContainer(keyedBy: ConfigurationKeys.self, forKey: .configuration) + + var sessionBuilder = OpenVPN.ConfigurationBuilder() + sessionBuilder.cipher = try cfgContainer.decode(OpenVPN.Cipher.self, forKey: .cipher) + if let digest = try cfgContainer.decodeIfPresent(OpenVPN.Digest.self, forKey: .digest) { + sessionBuilder.digest = digest + } + sessionBuilder.compressionFraming = try cfgContainer.decode(OpenVPN.CompressionFraming.self, forKey: .compressionFraming) + sessionBuilder.compressionAlgorithm = try cfgContainer.decodeIfPresent(OpenVPN.CompressionAlgorithm.self, forKey: .compressionAlgorithm) ?? .disabled + sessionBuilder.ca = try cfgContainer.decodeIfPresent(OpenVPN.CryptoContainer.self, forKey: .ca) + sessionBuilder.clientCertificate = try cfgContainer.decodeIfPresent(OpenVPN.CryptoContainer.self, forKey: .clientCertificate) + sessionBuilder.clientKey = try cfgContainer.decodeIfPresent(OpenVPN.CryptoContainer.self, forKey: .clientKey) + sessionBuilder.tlsWrap = try cfgContainer.decodeIfPresent(OpenVPN.TLSWrap.self, forKey: .tlsWrap) + sessionBuilder.keepAliveInterval = try cfgContainer.decodeIfPresent(TimeInterval.self, forKey: .keepAliveSeconds) + sessionBuilder.keepAliveTimeout = try cfgContainer.decodeIfPresent(TimeInterval.self, forKey: .keepAliveTimeoutSeconds) + sessionBuilder.renegotiatesAfter = try cfgContainer.decodeIfPresent(TimeInterval.self, forKey: .renegotiatesAfterSeconds) + sessionBuilder.endpointProtocols = try cfgContainer.decode([EndpointProtocol].self, forKey: .endpointProtocols) + sessionBuilder.checksEKU = try cfgContainer.decodeIfPresent(Bool.self, forKey: .checksEKU) ?? false + sessionBuilder.randomizeEndpoint = try cfgContainer.decodeIfPresent(Bool.self, forKey: .randomizeEndpoint) ?? false + sessionBuilder.usesPIAPatches = try cfgContainer.decodeIfPresent(Bool.self, forKey: .usesPIAPatches) ?? false + + // default to server settings + sessionBuilder.routingPolicies = nil + + let builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) + configuration = builder.build() + } + + public func encode(to encoder: Encoder) throws { + guard let ca = configuration.sessionConfiguration.ca else { + fatalError("Could not encode nil ca") + } + guard let endpointProtocols = configuration.sessionConfiguration.endpointProtocols else { + fatalError("Could not encode nil endpointProtocols") + } + + var container = encoder.container(keyedBy: PresetKeys.self) + try container.encode(id, forKey: .id) + try container.encode(name, forKey: .name) + try container.encode(comment, forKey: .comment) + if let external = external { + var rawExternal: [String: String] = [:] + for entry in external { + rawExternal[entry.key.rawValue] = entry.value + } + try container.encode(rawExternal, forKey: .external) + } + + var cfgContainer = container.nestedContainer(keyedBy: ConfigurationKeys.self, forKey: .configuration) + try cfgContainer.encode(configuration.sessionConfiguration.cipher, forKey: .cipher) + try cfgContainer.encode(configuration.sessionConfiguration.digest, forKey: .digest) + try cfgContainer.encode(configuration.sessionConfiguration.compressionFraming, forKey: .compressionFraming) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.compressionAlgorithm, forKey: .compressionAlgorithm) + try cfgContainer.encodeIfPresent(ca, forKey: .ca) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.clientCertificate, forKey: .clientCertificate) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.clientKey, forKey: .clientKey) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.tlsWrap, forKey: .tlsWrap) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.keepAliveInterval, forKey: .keepAliveSeconds) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.keepAliveTimeout, forKey: .keepAliveTimeoutSeconds) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.renegotiatesAfter, forKey: .renegotiatesAfterSeconds) + try cfgContainer.encode(endpointProtocols, forKey: .endpointProtocols) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.checksEKU, forKey: .checksEKU) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.randomizeEndpoint, forKey: .randomizeEndpoint) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.usesPIAPatches, forKey: .usesPIAPatches) + } +} diff --git a/Passepartout/Core/Sources/Services/Pool.swift b/Passepartout/Core/Sources/Services/Pool.swift new file mode 100644 index 00000000..e836da97 --- /dev/null +++ b/Passepartout/Core/Sources/Services/Pool.swift @@ -0,0 +1,179 @@ +// +// Pool.swift +// Passepartout +// +// Created by Davide De Rosa on 6/11/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import TunnelKit + +public class Pool: Codable, Hashable { + public enum CodingKeys: String, CodingKey { + case id + + case country + + case extraCountries = "extra_countries" + + case area + + case num + + case tags + +// case location + + case hostname + + case isResolved = "resolved" + + case numericAddresses = "addrs" + } + + public let id: String + + public let country: String + + public let extraCountries: [String]? + + public let area: String? + + public let num: Int? + + public let tags: [String]? + +// public let location: (Double, Double) + + public let hostname: String? + + public let isResolved: Bool? + + public let numericAddresses: [UInt32]? + + // XXX: inefficient but convenient field (not serialized) + public func category(in infrastructure: Infrastructure) -> PoolCategory? { + for category in infrastructure.categories { + for group in category.groups { + for pool in group.pools { + if pool.id == id { + return category + } + } + } + } + return nil + } + + public func supportedPresetIds(in infrastructure: Infrastructure) -> [String] { + let poolCategory = category(in: infrastructure) + return poolCategory?.presets ?? infrastructure.presets.map { $0.id } + } + + public func hasAddress(_ address: String) -> Bool { + guard let numericAddresses = numericAddresses else { + return false + } + guard let ipv4 = DNSResolver.ipv4(fromString: address) else { + return false + } + return numericAddresses.contains(ipv4) + } + + // XXX: inefficient, can't easily use lazy on struct + public func addresses() -> [String] { + var addrs = numericAddresses?.map { DNSResolver.string(fromIPv4: $0) } ?? [] + if let hostname = hostname { + addrs.insert(hostname, at: 0) + } + return addrs + } + + // MARK: Equatable + + public static func == (lhs: Pool, rhs: Pool) -> Bool { + return lhs.id == rhs.id + } + + // MARK: Hashable + + public func hash(into hasher: inout Hasher) { + id.hash(into: &hasher) + } +} + +extension Pool { + public var localizedCountry: String { + return Utils.localizedCountry(country) + } + + public var localizedId: String { + var comps: [String] = [localizedCountry] + if let secondaryId = optionalSecondaryId { + comps.append(secondaryId) + } + return comps.joined(separator: " - ") + } + + public var secondaryId: String { + return optionalSecondaryId ?? "" + } + + private var optionalSecondaryId: String? { + var comps: [String] = [] + if let extraCountries = extraCountries { + comps.append(contentsOf: extraCountries.map { Utils.localizedCountry($0) }) + } + if let area = area { +// comps.append(area.uppercased()) + comps.append(area.capitalized) + } + if let num = num { + comps.append("#\(num)") + } + guard !comps.isEmpty else { + return nil + } + var str = comps.joined(separator: " ") + if let tags = tags { + let suffix = tags.map { $0.uppercased() }.joined(separator: ",") + str = "\(str) (\(suffix))" + } + return str + } +} + +public extension Array where Element: Pool { + func sortedPools() -> [Element] { + return sorted { + guard let lnum = $0.num else { + return true + } + guard let rnum = $1.num else { + return false + } + guard lnum != rnum else { + return $0.secondaryId < $1.secondaryId + } + return lnum < rnum + } + } +} diff --git a/Passepartout/Core/Sources/Services/PoolGroup.swift b/Passepartout/Core/Sources/Services/PoolGroup.swift new file mode 100644 index 00000000..0d8a7ee0 --- /dev/null +++ b/Passepartout/Core/Sources/Services/PoolGroup.swift @@ -0,0 +1,92 @@ +// +// PoolGroup.swift +// Passepartout +// +// Created by Davide De Rosa on 4/6/19. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public class PoolGroup: Codable, Hashable, Comparable, CustomStringConvertible { + public let country: String + + public let area: String? + + public let pools: [Pool] + + private var id: String { + var id = country + if let area = area { + id += area + } + return id + } + + private var localizedId: String { + var localizedId = Utils.localizedCountry(country) + if let area = area { + localizedId += area + } + return localizedId + } + + // MARK: Equatable + + public static func ==(lhs: PoolGroup, rhs: PoolGroup) -> Bool { + return lhs.localizedId == rhs.localizedId + } + + // MARK: Hashable + + public func hash(into hasher: inout Hasher) { + id.hash(into: &hasher) + } + + // MARK: Comparable + + public static func <(lhs: PoolGroup, rhs: PoolGroup) -> Bool { + return lhs.localizedId < rhs.localizedId + } + + // MARK: CustomStringConvertible + + public var description: String { + return "{\(country), \(area ?? "--")}" + } +} + +extension PoolGroup { + public var localizedCountry: String { + return Utils.localizedCountry(country) + } +} + +extension PoolGroup { + public func uniqueId(in category: PoolCategory) -> String { + var components: [String] = [] + components.append(category.name) + components.append(country) + if let area = area { + components.append(area) + } + return components.joined(separator: "/") + } +} diff --git a/Passepartout/Core/Sources/Services/WebServices.swift b/Passepartout/Core/Sources/Services/WebServices.swift new file mode 100644 index 00000000..8f7b2851 --- /dev/null +++ b/Passepartout/Core/Sources/Services/WebServices.swift @@ -0,0 +1,97 @@ +// +// WebServices.swift +// Passepartout +// +// Created by Davide De Rosa on 9/14/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import Convenience + +public class WebServices { + public static let version = "v4" + + public enum Group: String { + case providers + } + + public enum Endpoint: Convenience.Endpoint { + case providersIndex + + case providerNetwork(Infrastructure.Name) + + var pathName: String { + switch self { + case .providersIndex: + return "\(Group.providers.rawValue)/index" + + case .providerNetwork(let name): + return "\(Group.providers.rawValue)/\(name)/net" + } + } + + var fileType: String { + return "json" + } + + var path: String { + return "\(pathName).\(fileType)" + } + + public func apiURL(relativeTo url: URL) -> URL { + return url.appendingPathComponent(AppConstants.Store.apiDirectory).appendingPathComponent(path) + } + + public func bundleURL(in bundle: Bundle) -> URL? { + return bundle.url(forResource: "\(AppConstants.Store.apiDirectory)/\(pathName)", withExtension: fileType) + } + + // MARK: Endpoint + + public var url: URL { + return AppConstants.Services.apiURL(version: WebServices.version, path: path) + } + } + + public static let shared = WebServices() + + private let ws: ReadonlyWebServices + + private init() { + ws = ReadonlyWebServices() + ws.timeout = AppConstants.Services.timeout + } + + public func providersIndex(completionHandler: @escaping ([Infrastructure.Metadata]?, Error?) -> Void) { + let request = ws.get(WebServices.Endpoint.providersIndex) + ws.parse([Infrastructure.Metadata].self, request: request) { + completionHandler($0?.value, $1) + } + } + + public func providerNetwork(with name: Infrastructure.Name, ifModifiedSince lastModified: Date?, completionHandler: @escaping (Response?, Error?) -> Void) { + var request = ws.get(WebServices.Endpoint.providerNetwork(name)) + if let lastModified = lastModified { + request.addValue(ResponseParser.lastModifiedString(date: lastModified), forHTTPHeaderField: "If-Modified-Since") + } + ws.parse(Infrastructure.self, request: request, completionHandler: completionHandler) + } +} diff --git a/Passepartout/Core/Sources/UI/TrustedNetworksUI.swift b/Passepartout/Core/Sources/UI/TrustedNetworksUI.swift new file mode 100644 index 00000000..09659ef1 --- /dev/null +++ b/Passepartout/Core/Sources/UI/TrustedNetworksUI.swift @@ -0,0 +1,219 @@ +// +// TrustedNetworksUI.swift +// Passepartout +// +// Created by Davide De Rosa on 6/21/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation + +public protocol TrustedNetworksUIDelegate: class { + func trustedNetworksCouldDisconnect(_: TrustedNetworksUI) -> Bool + + func trustedNetworksShouldConfirmDisconnection(_: TrustedNetworksUI, triggeredAt rowIndex: Int, completionHandler: @escaping () -> Void) + + func trustedNetworks(_: TrustedNetworksUI, shouldInsertWifiAt rowIndex: Int) + + func trustedNetworks(_: TrustedNetworksUI, shouldReloadWifiAt rowIndex: Int, isTrusted: Bool) + + func trustedNetworks(_: TrustedNetworksUI, shouldDeleteWifiAt rowIndex: Int) + + func trustedNetworksShouldReinstall(_: TrustedNetworksUI) +} + +public class TrustedNetworksUI { + public enum RowType { + case trustsMobile + + case trustedWiFi + + case addCurrentWiFi + } + + public private(set) var trustedWifis: [String: Bool] + + public private(set) var sortedWifis: [String] + + #if os(iOS) + private let hasMobileNetwork: Bool + + public private(set) var trustsMobileNetwork: Bool + + public private(set) var rows: [RowType] + #endif + + public weak var delegate: TrustedNetworksUIDelegate? + + public init() { + trustedWifis = [:] + sortedWifis = [] + + #if os(iOS) + hasMobileNetwork = Utils.hasCellularData() + trustsMobileNetwork = false + rows = [] + #endif + } + + public func load(from trustedNetworks: TrustedNetworks) { + trustedWifis = trustedNetworks.includedWiFis + sortedWifis = trustedWifis.keys.sorted() + + #if os(iOS) + trustsMobileNetwork = trustedNetworks.includesMobile + rows.removeAll() + if hasMobileNetwork { + rows.append(.trustsMobile) + } + for _ in sortedWifis { + rows.append(.trustedWiFi) + } + rows.append(.addCurrentWiFi) + #endif + } + + #if os(iOS) + public func setMobile(_ isTrusted: Bool) { + let completionHandler: () -> Void = { + self.trustsMobileNetwork = isTrusted + self.delegate?.trustedNetworksShouldReinstall(self) + } + guard !(isTrusted && mightDisconnect()) else { + delegate?.trustedNetworksShouldConfirmDisconnection(self, triggeredAt: 0, completionHandler: completionHandler) + return + } + completionHandler() + } + #endif + + public func wifi(at rowIndex: Int) -> (String, Bool) { + let index = indexForWifi(at: rowIndex) + let wifiName = sortedWifis[index] + let isTrusted = trustedWifis[wifiName] ?? false + return (wifiName, isTrusted) + } + + public func addCurrentWifi() -> Bool { + guard let currentWifi = Utils.currentWifiNetworkName() else { + return false + } + addWifi(currentWifi) + return true + } + + public func addWifi(_ wifiToAdd: String) { + var index = 0 + var isDuplicate = false + for wifi in sortedWifis { + guard wifiToAdd != wifi else { + isDuplicate = true + break + } + guard wifiToAdd > wifi else { + break + } + index += 1 + } + + guard !(trustedWifis[wifiToAdd] ?? false) else { + return + } + + let isTrusted = false + let rowIndex = rowIndexForWifi(at: index) + trustedWifis[wifiToAdd] = isTrusted + + if !isDuplicate { + sortedWifis.insert(wifiToAdd, at: index) + #if os(iOS) + rows.insert(.trustedWiFi, at: rowIndex) + #endif + delegate?.trustedNetworks(self, shouldInsertWifiAt: rowIndex) + } else { + delegate?.trustedNetworks(self, shouldReloadWifiAt: rowIndex, isTrusted: isTrusted) + } + + delegate?.trustedNetworksShouldReinstall(self) + } + + public func removeWifi(at rowIndex: Int) { + let index = indexForWifi(at: rowIndex) + let removedWifi = sortedWifis.remove(at: index) + trustedWifis.removeValue(forKey: removedWifi) + #if os(iOS) + rows.remove(at: rowIndex) + #endif + + delegate?.trustedNetworks(self, shouldDeleteWifiAt: rowIndex) + delegate?.trustedNetworksShouldReinstall(self) + } + + public func enableWifi(at rowIndex: Int) { + let index = indexForWifi(at: rowIndex) + let wifi = sortedWifis[index] + + let completionHandler: () -> Void = { + self.trustedWifis[wifi] = true + + self.delegate?.trustedNetworks(self, shouldReloadWifiAt: rowIndex, isTrusted: true) + self.delegate?.trustedNetworksShouldReinstall(self) + } + guard !mightDisconnect() else { + delegate?.trustedNetworksShouldConfirmDisconnection(self, triggeredAt: rowIndex, completionHandler: completionHandler) + return + } + completionHandler() + } + + public func disableWifi(at rowIndex: Int) { + let index = indexForWifi(at: rowIndex) + let wifi = sortedWifis[index] + + trustedWifis[wifi] = false + + delegate?.trustedNetworks(self, shouldReloadWifiAt: rowIndex, isTrusted: false) + delegate?.trustedNetworksShouldReinstall(self) + } + + public func isTrusted(wifi: String) -> Bool { + return trustedWifis[wifi] ?? false + } + + private func indexForWifi(at rowIndex: Int) -> Int { + #if os(iOS) + return hasMobileNetwork ? (rowIndex - 1) : rowIndex + #else + return rowIndex + #endif + } + + private func rowIndexForWifi(at index: Int) -> Int { + #if os(iOS) + return index + (hasMobileNetwork ? 1 : 0) + #else + return index + #endif + } + + private func mightDisconnect() -> Bool { + return delegate?.trustedNetworksCouldDisconnect(self) ?? false + } +} diff --git a/Passepartout/Core/Sources/Utils.swift b/Passepartout/Core/Sources/Utils.swift new file mode 100644 index 00000000..d49828b5 --- /dev/null +++ b/Passepartout/Core/Sources/Utils.swift @@ -0,0 +1,200 @@ +// +// Utils.swift +// Passepartout +// +// Created by Davide De Rosa on 6/16/18. +// Copyright (c) 2021 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +#if os(iOS) +import SystemConfiguration.CaptiveNetwork +#else +import CoreWLAN +#endif +import StoreKit +import SwiftyBeaver + +private let log = SwiftyBeaver.self + +public class Utils { + fileprivate static let timestampFormatter: DateFormatter = { + let fmt = DateFormatter() + fmt.dateStyle = .medium + fmt.timeStyle = .medium + return fmt + }() + + fileprivate static let componentsFormatter: DateComponentsFormatter = { + let fmt = DateComponentsFormatter() + fmt.unitsStyle = .full + return fmt + }() + + #if targetEnvironment(simulator) + public static func hasCellularData() -> Bool { + return true + } + #else + public static func hasCellularData() -> Bool { + var addrs: UnsafeMutablePointer? + guard getifaddrs(&addrs) == 0 else { + return false + } + var isFound = false + var cursor = addrs?.pointee + while let ifa = cursor { + let name = String(cString: ifa.ifa_name) + if name == "pdp_ip0" { + isFound = true + break + } + cursor = ifa.ifa_next?.pointee + } + freeifaddrs(addrs) + return isFound + } + #endif + + #if targetEnvironment(simulator) + public static func currentWifiNetworkName() -> String? { +// return nil + return ["My Home Network", "Safe Wi-Fi", "Friend's House"].randomElement() + } + #else + public static func currentWifiNetworkName() -> String? { + #if os(iOS) + guard let interfaceNames = CNCopySupportedInterfaces() as? [CFString] else { + return nil + } + for name in interfaceNames { + guard let iface = CNCopyCurrentNetworkInfo(name) as? [String: Any] else { + continue + } + guard let ssid = iface[kCNNetworkInfoKeySSID as String] as? String else { + continue + } + return ssid + } + return nil + #else + return CWWiFiClient.shared().interface()?.ssid() + #endif + } + #endif + + public static func regex(_ pattern: String) -> NSRegularExpression { + return try! NSRegularExpression(pattern: pattern, options: []) + } + + public static func checkConnectivityURL(_ url: URL, timeout: TimeInterval, completionHandler: @escaping (Bool) -> Void) { + let session = URLSession(configuration: .ephemeral) + let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: timeout) + + log.info("Check connectivity via \(url)") + session.dataTask(with: request) { (_, response, error) in + if let response = response as? HTTPURLResponse { + log.debug("Response code: \(response.statusCode)") + } + if let error = error { + log.error("Connectivity failed: \(error)") + } else { + log.info("Connectivity succeeded!") + } + DispatchQueue.main.async { + completionHandler(error == nil) + } + }.resume() + } + + public static func localizedCountry(_ code: String) -> String { + return Locale.current.localizedString(forRegionCode: code) ?? code + } + + public static func isFile(at url1: URL, newerThanFileAt url2: URL?) -> Bool { + guard let date1 = FileManager.default.modificationDate(of: url1.path) else { + return false + } + guard let url2 = url2, let date2 = FileManager.default.modificationDate(of: url2.path) else { + return true + } + return date1 > date2 + } + + private init() { + } +} + +public extension Date { + var timestamp: String { + return Utils.timestampFormatter.string(from: self) + } +} + +public extension TimeInterval { + var localized: String { + guard let str = Utils.componentsFormatter.string(from: self) else { + fatalError("Could not format a TimeInterval?") + } + return str + } +} + +public extension Sequence { + func stableSorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element] { + return try enumerated().sorted { + return try areInIncreasingOrder($0.element, $1.element) || + ($0.offset < $1.offset && !areInIncreasingOrder($1.element, $0.element)) + }.map { $0.element } + } +} + +public extension StringProtocol where Index == String.Index { + func nsRange(from range: Range) -> NSRange { + return NSRange(range, in: self) + } +} + +public extension CharacterSet { + static let filename: CharacterSet = { + var chars: CharacterSet = .decimalDigits + let english = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + let symbols = "-_." + chars.formUnion(CharacterSet(charactersIn: english)) + chars.formUnion(CharacterSet(charactersIn: english.lowercased())) + chars.formUnion(CharacterSet(charactersIn: symbols)) + return chars + }() +} + +public extension URL { + private static let illegalCharacterFallback = "_" + + var normalizedFilename: String { + let filename = deletingPathExtension().lastPathComponent + return filename.components(separatedBy: CharacterSet.filename.inverted).joined(separator: URL.illegalCharacterFallback) + } +} + +public extension Array where Element: CustomStringConvertible { + func sortedCaseInsensitive() -> [Element] { + return sorted { $0.description.lowercased() < $1.description.lowercased() } + } +} diff --git a/Passepartout/Tests/ConnectionService.json b/Passepartout/Tests/ConnectionService.json new file mode 100644 index 00000000..142883f8 --- /dev/null +++ b/Passepartout/Tests/ConnectionService.json @@ -0,0 +1 @@ +{"appGroup":"group.com.algoritmico.Passepartout","activeProfileId":"host.edu","tunnelConfiguration":{"endpointProtocols":["UDP:1194"],"compressionFraming":0,"digest":"SHA1","ca":"","lastErrorKey":"LastVPNError","debugLogFormat":"$DHH:mm:ss$d - $M","usesPIAPatches":false,"cipher":"AES-128-CBC","prefersResolvedAddresses":false,"shouldDebug":true,"mtu":1250,"debugLogKey":"LastVPNLog"},"preferences":{"trustPolicy":"ignore","trustsMobileNetwork":false,"disconnectsOnSleep":false,"trustedWifis":{},"resolvesHostname":true},"profiles":[{"provider":{"username":"p0000000","id":"provider.PIA","poolId":"ca-vancouver","name":"PIA","presetId":"recommended"}},{"host":{"username":"","title":"edu","hostname":"1.2.4.5","parameters":{"endpointProtocols":["UDP:1194","TCP:1194","TCP:443"],"compressionFraming":1,"digest":"SHA256","ca":"bogus+ca","clientCertificate":"bogus+client","usesPIAPatches":false,"tlsWrap":{"key":{"dir":1,"data":"bogus+static+key"},"strategy":"auth"},"cipher":"AES-256-CBC","prefersResolvedAddresses":false,"clientKey":"bogus+key","mtu":1500,"shouldDebug":false}}},{"host":{"username":"","title":"vps-udp-tc","hostname":"8.8.4.4","parameters":{"shouldDebug":false,"endpointProtocols":["UDP:1198"],"compressionFraming":1,"digest":"SHA512","ca":"bogus+ca","renegotiatesAfterSeconds":0,"usesPIAPatches":false,"tlsWrap":{"key":{"dir":1,"data":"bogus+static+key"},"strategy":"crypt"},"cipher":"AES-192-CBC","prefersResolvedAddresses":false,"clientKey":"bogus+key","mtu":1500,"keepAliveSeconds":25}}}]} diff --git a/Passepartout/Tests/ConnectionServiceTests.swift b/Passepartout/Tests/ConnectionServiceTests.swift new file mode 100644 index 00000000..45508afd --- /dev/null +++ b/Passepartout/Tests/ConnectionServiceTests.swift @@ -0,0 +1,64 @@ +// +// ConnectionServiceTests.swift +// PassepartoutTests +// +// Created by Davide De Rosa on 10/25/18. +// Copyright (c) 2020 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import XCTest +import TunnelKit +@testable import PassepartoutCore + +class ConnectionServiceTests: XCTestCase { + let url = Bundle(for: ConnectionServiceTests.self).url(forResource: "ConnectionService", withExtension: "json")! + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testParse() { + let jsonData = try! Data(contentsOf: url) + XCTAssertNoThrow(try JSONSerialization.jsonObject(with: jsonData, options: [])) + } + + func testPathExtension() { + XCTAssertTrue(privateTestPathExtension("file:///foo/bar/johndoe.json")) + XCTAssertFalse(privateTestPathExtension("file:///foo/bar/break.json.johndoe.json")) + } + + private func privateTestPathExtension(_ string: String) -> Bool { + let url = URL(string: string)! + let filename = url.lastPathComponent + guard let extRange = filename.range(of: ".json") else { + return false + } + guard url.pathExtension == "json" else { + return false + } + let name1 = String(filename[filename.startIndex..CFBundleName $(PRODUCT_NAME) CFBundlePackageType - FMWK + $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.13.1 + $(CFG_APP_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/Passepartout/Tests/InfrastructureTests.swift b/Passepartout/Tests/InfrastructureTests.swift new file mode 100644 index 00000000..6f38f2ec --- /dev/null +++ b/Passepartout/Tests/InfrastructureTests.swift @@ -0,0 +1,113 @@ +// +// InfrastructureTests.swift +// PassepartoutTests +// +// Created by Davide De Rosa on 6/11/18. +// Copyright (c) 2020 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import XCTest +import TunnelKit +@testable import PassepartoutCore + +class InfrastructureTests: XCTestCase { + private var infra: Infrastructure! + + override func setUp() { + InfrastructureFactory.shared.preload() + infra = InfrastructureFactory.shared.infrastructure(forName: .pia) + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testParsing() { + print(infra.categories) + XCTAssertEqual(infra.categories.count, 1) + } + + func testIdentifier() { + let id = "italy" + guard let pool = infra.pool(for: id) else { + XCTAssert(false) + return + } + print(pool) + XCTAssertEqual(pool.id, id) + } + + func testStableSort() { + let original: [EndpointProtocol] = [ + EndpointProtocol(.udp, 1194), + EndpointProtocol(.udp, 8080), + EndpointProtocol(.udp, 9201), + EndpointProtocol(.udp, 53), + EndpointProtocol(.udp, 1197), + EndpointProtocol(.udp, 198), + EndpointProtocol(.tcp, 443), + EndpointProtocol(.tcp, 110), + EndpointProtocol(.tcp, 80), + EndpointProtocol(.tcp, 500), + EndpointProtocol(.tcp, 501), + EndpointProtocol(.tcp, 502) + ] + var preferredType: SocketType + + preferredType = .udp + let sorted1 = original.stableSorted { + return ($0.socketType == preferredType) && ($1.socketType != preferredType) + } + XCTAssertEqual(sorted1, original) + + preferredType = .tcp + let sorted2 = original.stableSorted { + return ($0.socketType == preferredType) && ($1.socketType != preferredType) + } + XCTAssertNotEqual(sorted2, original) + } + + func testLastModified() { + let fmt = DateFormatter() + fmt.timeZone = TimeZone(abbreviation: "GMT") + fmt.dateFormat = "EEE, dd LLL yyyy HH:mm:ss zzz" + + let lmString = "Wed, 23 Oct 2019 17:06:54 GMT" + + fmt.locale = Locale(identifier: "en") + XCTAssertNotNil(fmt.date(from: lmString)) + fmt.locale = Locale(identifier: "fr-FR") + XCTAssertNil(fmt.date(from: lmString)) + } + + func testProvidersIndex() { + let ifactory = InfrastructureFactory.shared + XCTAssertNotNil(ifactory.metadata(forName: "nordvpn")) + XCTAssertNil(ifactory.metadata(forName: "expressvpn")) + + let update = expectation(description: "updateIndex") + ifactory.updateIndex { _ in + update.fulfill() + } + waitForExpectations(timeout: 10.0) { _ in + print(ifactory.allMetadata) + } + } +} diff --git a/Passepartout/Tests/UtilsTests.swift b/Passepartout/Tests/UtilsTests.swift new file mode 100644 index 00000000..e8fe04e3 --- /dev/null +++ b/Passepartout/Tests/UtilsTests.swift @@ -0,0 +1,69 @@ +// +// UtilsTests.swift +// PassepartoutTests +// +// Created by Davide De Rosa on 3/30/19. +// Copyright (c) 2020 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import XCTest +@testable import PassepartoutCore + +class UtilsTests: XCTestCase { + override func setUp() { + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testDataUnitDescription() { + XCTAssertEqual(0.dataUnitDescription, "0B") + XCTAssertEqual(1.dataUnitDescription, "1B") + XCTAssertEqual(1024.dataUnitDescription, "1kB") + XCTAssertEqual(1025.dataUnitDescription, "1kB") + XCTAssertEqual(548575.dataUnitDescription, "0.52MB") + XCTAssertEqual(1048575.dataUnitDescription, "1.00MB") + XCTAssertEqual(1048576.dataUnitDescription, "1.00MB") + XCTAssertEqual(1048577.dataUnitDescription, "1.00MB") + XCTAssertEqual(600000000.dataUnitDescription, "0.56GB") + XCTAssertEqual(1073741823.dataUnitDescription, "1.00GB") + XCTAssertEqual(1073741824.dataUnitDescription, "1.00GB") + XCTAssertEqual(1073741825.dataUnitDescription, "1.00GB") + } + + func testLanguageLocalization() { + let languages = ["en", "it", "de", "pt-BR", "ru"] + let english = Locale(identifier: "en") + let italian = Locale(identifier: "it") + + let languagesEN = privateSortedLanguages(languages, with: english) + let languagesIT = privateSortedLanguages(languages, with: italian) + + XCTAssertEqual(languagesEN, ["en", "de", "it", "pt-BR", "ru"]) + XCTAssertEqual(languagesIT, ["en", "it", "pt-BR", "ru", "de"]) + } + + private func privateSortedLanguages(_ languages: [String], with locale: Locale) -> [String] { + return languages.sorted { + return locale.localizedString(forLanguageCode: $0)! < locale.localizedString(forLanguageCode: $1)! + } + } +} diff --git a/Passepartout-iOS-Tunnel/Info.plist b/Passepartout/Tunnel/Info.plist similarity index 77% rename from Passepartout-iOS-Tunnel/Info.plist rename to Passepartout/Tunnel/Info.plist index b8e5141f..975dfb35 100644 --- a/Passepartout-iOS-Tunnel/Info.plist +++ b/Passepartout/Tunnel/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - Passepartout-iOS-Tunnel + PassepartoutTunnel CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -17,9 +17,11 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 1.13.1 + $(CFG_APP_VERSION) CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) NSExtension NSExtensionPointIdentifier @@ -27,5 +29,7 @@ NSExtensionPrincipalClass $(PRODUCT_MODULE_NAME).PacketTunnelProvider + NSHumanReadableCopyright + $(CFG_COPYRIGHT) diff --git a/Passepartout-iOS-Tunnel/PacketTunnelProvider.swift b/Passepartout/Tunnel/PacketTunnelProvider.swift similarity index 93% rename from Passepartout-iOS-Tunnel/PacketTunnelProvider.swift rename to Passepartout/Tunnel/PacketTunnelProvider.swift index 34db363e..18e49da5 100644 --- a/Passepartout-iOS-Tunnel/PacketTunnelProvider.swift +++ b/Passepartout/Tunnel/PacketTunnelProvider.swift @@ -1,8 +1,8 @@ // // PacketTunnelProvider.swift -// Passepartout-iOS-Tunnel +// Passepartout-macOS-Tunnel // -// Created by Davide De Rosa on 6/6/18. +// Created by Davide De Rosa on 6/17/18. // Copyright (c) 2021 Davide De Rosa. All rights reserved. // // https://github.com/passepartoutvpn @@ -31,7 +31,6 @@ class PacketTunnelProvider: OpenVPNTunnelProvider { dnsTimeout = GroupConstants.VPN.dnsTimeout logSeparator = GroupConstants.VPN.sessionMarker dataCountInterval = GroupConstants.VPN.dataCountInterval - fallbackDNSServers = [] super.startTunnel(options: options, completionHandler: completionHandler) } } diff --git a/Passepartout-iOS-Tunnel/Tunnel.entitlements b/Passepartout/Tunnel/Tunnel-iOS.entitlements similarity index 100% rename from Passepartout-iOS-Tunnel/Tunnel.entitlements rename to Passepartout/Tunnel/Tunnel-iOS.entitlements diff --git a/Passepartout/Tunnel/Tunnel-macOS.entitlements b/Passepartout/Tunnel/Tunnel-macOS.entitlements new file mode 100644 index 00000000..d6b0d9d9 --- /dev/null +++ b/Passepartout/Tunnel/Tunnel-macOS.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.app-sandbox + + com.apple.security.application-groups + + $(TeamIdentifierPrefix)group.com.algoritmico.Passepartout + + com.apple.security.network.client + + + diff --git a/Podfile b/Podfile index 802f4c5a..09d615f4 100644 --- a/Podfile +++ b/Podfile @@ -1,5 +1,4 @@ source 'https://github.com/cocoapods/specs.git' -platform :ios, '12.0' use_frameworks! load 'Podfile.include' @@ -12,20 +11,47 @@ def shared_pods #pod_git $tunnelkit_name, $tunnelkit_specs, 'e923382' #pod_path $tunnelkit_name, $tunnelkit_specs, '..' pod 'SSZipArchive' - + pod 'Kvitto', :git => 'https://github.com/keeshux/Kvitto', :branch => 'enable-macos-spec' +end +def shared_pods_ios + shared_pods for spec in ['About', 'Alerts', 'Dialogs', 'InApp', 'Misc', 'Options', 'Persistence', 'Reviewer', 'Tables', 'WebServices'] do pod "Convenience/#{spec}", :git => 'https://github.com/keeshux/convenience', :commit => 'b30816a' end end - -target 'PassepartoutCore-iOS' do +def shared_pods_macos shared_pods - pod 'Kvitto' + for spec in ['InApp', 'Misc', 'Persistence', 'Reviewer', 'WebServices'] do + pod "Convenience/#{spec}", :git => 'https://github.com/keeshux/convenience', :commit => 'b30816a' + end end -target 'Passepartout-iOS' do - pod 'MBProgressHUD' +abstract_target 'ios' do + platform :ios, '12.0' + target 'PassepartoutCore-iOS' do + shared_pods_ios + end + target 'PassepartoutCoreTests-iOS' do + end + target 'Passepartout-iOS' do + pod 'MBProgressHUD' + end + target 'PassepartoutTunnel-iOS' do + shared_pods_ios + end end -target 'Passepartout-iOS-Tunnel' do - shared_pods + +abstract_target 'macos' do + platform :osx, '10.15' + target 'PassepartoutCore-macOS' do + shared_pods_macos + end + target 'PassepartoutCoreTests-macOS' do + end + target 'Passepartout-macOS' do + #pod 'AppCenter' + end + target 'PassepartoutTunnel-macOS' do + shared_pods_macos + end end diff --git a/Podfile.lock b/Podfile.lock index 152c1f3c..5839123c 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -49,7 +49,7 @@ DEPENDENCIES: - Convenience/Reviewer (from `https://github.com/keeshux/convenience`, commit `b30816a`) - Convenience/Tables (from `https://github.com/keeshux/convenience`, commit `b30816a`) - Convenience/WebServices (from `https://github.com/keeshux/convenience`, commit `b30816a`) - - Kvitto + - Kvitto (from `https://github.com/keeshux/Kvitto`, branch `enable-macos-spec`) - MBProgressHUD - SSZipArchive - TunnelKit/Extra/LZO (~> 3.1.0) @@ -58,7 +58,6 @@ DEPENDENCIES: SPEC REPOS: https://github.com/cocoapods/specs.git: - DTFoundation - - Kvitto - MBProgressHUD - OpenSSL-Apple - SSZipArchive @@ -69,22 +68,28 @@ EXTERNAL SOURCES: Convenience: :commit: b30816a :git: https://github.com/keeshux/convenience + Kvitto: + :branch: enable-macos-spec + :git: https://github.com/keeshux/Kvitto CHECKOUT OPTIONS: Convenience: :commit: b30816a :git: https://github.com/keeshux/convenience + Kvitto: + :commit: e263fcd1f40a6a482a0f1e424ba98009c4ad2b96 + :git: https://github.com/keeshux/Kvitto SPEC CHECKSUMS: Convenience: c805c2aff569ff735c5d69c2c2b7a9bd110fa507 DTFoundation: e7781d9fd2f202bfd451fbbf8cab71ce83b46498 - Kvitto: e5c903c656cce6bfebbf337d992184cf03cb4853 + Kvitto: 5511954b22d6c710e1a04dcbdee44ae7b3d1caeb MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 OpenSSL-Apple: 8a8fcb06fb66f9c2f7aed45ce363668493b8e5f6 SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 SwiftyBeaver: 2e8acd6fc90c6d0a27055867a290794926d57c02 TunnelKit: 1d9494670d643fd447aa3fa208dae1a4dcab2b2e -PODFILE CHECKSUM: c7333249e02a01ebc26be633bfc8c95fc5d82229 +PODFILE CHECKSUM: 49cadeae6b11c6b4bb4ea7d10e7d70519211c659 COCOAPODS: 1.10.0 diff --git a/Submodules/fastlane-ci-templates b/Submodules/fastlane-ci-templates index 903dc61b..3e23f493 160000 --- a/Submodules/fastlane-ci-templates +++ b/Submodules/fastlane-ci-templates @@ -1 +1 @@ -Subproject commit 903dc61be5aae8e84ef63440b5c4e96c9b0f8a9d +Subproject commit 3e23f4938ab858316dfa88ae9145c9916b00c44c diff --git a/fastlane/Appfile b/fastlane/Appfile deleted file mode 100644 index c94e220e..00000000 --- a/fastlane/Appfile +++ /dev/null @@ -1,5 +0,0 @@ -app_identifier("com.algoritmico.ios.Passepartout") # The bundle identifier of your app - - -# For more information about the Appfile, see: -# https://docs.fastlane.tools/advanced/#appfile diff --git a/fastlane/Deliverfile b/fastlane/Deliverfile deleted file mode 100644 index d081bbc1..00000000 --- a/fastlane/Deliverfile +++ /dev/null @@ -1,8 +0,0 @@ -# The Deliverfile allows you to store various App Store Connect metadata -# For more information, check out the docs -# https://docs.fastlane.tools/actions/deliver/ - -skip_binary_upload true -skip_metadata false -skip_screenshots false -overwrite_screenshots true diff --git a/fastlane/Fastfile b/fastlane/Fastfile deleted file mode 120000 index 1fd532d1..00000000 --- a/fastlane/Fastfile +++ /dev/null @@ -1 +0,0 @@ -../Submodules/fastlane-ci-templates/include/Fastfile.include \ No newline at end of file diff --git a/fastlane/Gymfile b/fastlane/Gymfile deleted file mode 120000 index 3e37d7dd..00000000 --- a/fastlane/Gymfile +++ /dev/null @@ -1 +0,0 @@ -../Submodules/fastlane-ci-templates/include/Gymfile.include \ No newline at end of file diff --git a/fastlane/Matchfile b/fastlane/Matchfile deleted file mode 100644 index 7885fa90..00000000 --- a/fastlane/Matchfile +++ /dev/null @@ -1,9 +0,0 @@ -type "development" # The default type, can be: appstore, adhoc, enterprise or development - -app_identifier [ - "com.algoritmico.ios.Passepartout", - "com.algoritmico.ios.Passepartout.Tunnel" -] - -# For all available options run `fastlane match --help` -# Remove the # in the beginning of the line to enable the other options diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile deleted file mode 100644 index 756bff8e..00000000 --- a/fastlane/Pluginfile +++ /dev/null @@ -1,5 +0,0 @@ -# Autogenerated by fastlane -# -# Ensure this file is checked in to source control! - -gem 'fastlane-plugin-appcenter' diff --git a/fastlane/Precheckfile b/fastlane/Precheckfile deleted file mode 100644 index 4bbea73a..00000000 --- a/fastlane/Precheckfile +++ /dev/null @@ -1,29 +0,0 @@ -# For more information about this configuration visit -# https://docs.fastlane.tools/actions/precheck/ - -# In general, you can use the options available -# fastlane precheck --help - -# Remove the # in front of the line to enable the option - -# You have three possible values for each rule options -# :skip -# indicates that your metadata will not be checked by this rule - -# :warn -# when triggered, this rule will warn you of a potential problem - -# :error -# when triggered, this rule will cause an error to be displayed and it will prevent any further fastlane commands from running after precheck finishes - -# Examples: -# negative_apple_sentiment(level: :skip) -# curse_words(level: :warn) -# future_functionality(level: :error) -# other_platforms(level: :error) -# placeholder_text(level: :error) -# test_words(level: :error) -# unreachable_urls(level: :error) -# custom_text(data: ["fabric"], level: :warn) - -include_in_app_purchases false diff --git a/fastlane/metadata/app_icon.jpg b/fastlane/metadata/app_icon.jpg deleted file mode 100644 index ed687692..00000000 Binary files a/fastlane/metadata/app_icon.jpg and /dev/null differ diff --git a/fastlane/metadata/copyright.txt b/fastlane/metadata/copyright.txt deleted file mode 100644 index 840fc8f3..00000000 --- a/fastlane/metadata/copyright.txt +++ /dev/null @@ -1 +0,0 @@ -2021 Davide De Rosa diff --git a/fastlane/metadata/de-DE/apple_tv_privacy_policy.txt b/fastlane/metadata/de-DE/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/de-DE/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/de-DE/description.txt b/fastlane/metadata/de-DE/description.txt deleted file mode 100644 index 4f9a9932..00000000 --- a/fastlane/metadata/de-DE/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout ist ein smarter OpenVPN client der perfekt in die iOS-Plattform integriert ist. Passepartout ist die einzige App, die du brauchst um gängige OpenVPN-Anbieter als auch deinen persönlichen OpenVPN-Server zu nutzen. - -Mit vertrauenswürdigen Netzwerken und Siri Kurzbefehlen, eröffnet Passepartout die besten Möglichkeiten ein VPN unter iOS zu nutzen. - -Passepartout erzeugt keinerlei ungewollte Hintergrundaktivitäten außer dem VPN-Tunnel und ist daher sehr Firewall-freundlich. - -Passepartout ist Open Source: https://github.com/passepartoutvpn - -BENUTZBAR MIT VIELEN ANBIETERN - -Passepartout bietet Voreinstellungen für alle gängigen VPN-Anbieter: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -EINFACH ZU BENUTZEN - -- Unglaublich einfach zu benutzen, natives Aussehen und Integration. -- Verwalte alle Profile an einem Platz. -- Importiere .ovpn Konfigurationsdateien. -- Feintune die Verschlüsselung ohne Änderungen an der Konfigurationsdatei. -- Netzwerkeinstellungen schnell übersteuern (Standart-Gateway, DNS, Proxy, MTU). - -BETRIEBSSYSTEM-INTEGRATION - -- Vertraue Mobilfunknetzen oder WLANs für fein einstellbare Konnektivität. -- Intuitive Siri Kurzbefehle. - -PRIVATSPHÄREN-FREUNDLICH - -- Volle Transparenz zu welchen Servern du dich verbindest. -- Wähle vordefinierte Endpunkte aus wenn DNS ein Problem ist. -- Keine Webdienste, Werbung oder sonstirgendwie aufgebläht außer das VPN selbst. - -~ - -Passepartout ist ein inoffizieller Client und auf keine Art und Weise mit OpenVPN Inc. verbunden. - -© 2002-2018 OpenVPN Inc. - OpenVPN ist eine eingetragene Marke von OpenVPN Inc. diff --git a/fastlane/metadata/de-DE/keywords.txt b/fastlane/metadata/de-DE/keywords.txt deleted file mode 120000 index 43934280..00000000 --- a/fastlane/metadata/de-DE/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/de-DE/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/de-DE/marketing_url.txt b/fastlane/metadata/de-DE/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/de-DE/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/de-DE/name.txt b/fastlane/metadata/de-DE/name.txt deleted file mode 100644 index ae4103ba..00000000 --- a/fastlane/metadata/de-DE/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN Client diff --git a/fastlane/metadata/de-DE/privacy_url.txt b/fastlane/metadata/de-DE/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/de-DE/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/de-DE/promotional_text.txt b/fastlane/metadata/de-DE/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/de-DE/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/de-DE/release_notes.txt b/fastlane/metadata/de-DE/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/de-DE/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/de-DE/subtitle.txt b/fastlane/metadata/de-DE/subtitle.txt deleted file mode 100644 index 8d0734ae..00000000 --- a/fastlane/metadata/de-DE/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Verbinde .ovpn & VPN Anbieter diff --git a/fastlane/metadata/de-DE/support_url.txt b/fastlane/metadata/de-DE/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/de-DE/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/el/apple_tv_privacy_policy.txt b/fastlane/metadata/el/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/el/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/el/description.txt b/fastlane/metadata/el/description.txt deleted file mode 100644 index aac16730..00000000 --- a/fastlane/metadata/el/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Το Passepartout είναι ένας έξυπνος πελάτης OpenVPN που είναι απόλυτα ενσωματωμένος στην πλατφόρμα iOS. Το Passepartout είναι η μόνη εφαρμογή που χρειάζεστε για τους δύο γνωστούς παροχείς OpenVPN και τους προσωπικούς σας διακομιστές OpenVPN. - -Με τα Αξιόπιστα Δίκτυα και τις Συντομεύσεις Siri, η Passepartout ξεκλειδώνει το καλύτερο από τη χρήση ενός VPN στο iOS. - -Το Passepartout δεν εμπλέκεται σε οποιαδήποτε δραστηριότητα στο παρασκήνιο εκτός από τη σύνδεση για το VPN και έτσι είναι πιο φιλική προς τα τείχη προστασίας. - -To Passepartout βασίζετε σε ανοιχτό κώδικα: https://github.com/passepartoutvpn - -ΧΡΗΣΗ ΜΕ ΠΟΛΛΑΠΛΟΥΣ ΠΑΡΟΧΟΥΣ - -Το Passepartout προσφέρει προκαθορισμένες ρυθμίσεις για βασικούς VPN παρόχους: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -ΕΥΚΟΛΟ ΣΤΗ ΧΡΗΣΗ - -- Απίστευτη ευκολία χρήσης, με φυσική εμφάνιση και αίσθηση. -- Χειριστείτε τα προφίλ σας σε ένα μόνο μέρος. -- Εισαγωγή αρχείων ρυθμίσεων .ovpn. -- ΚΡυθμίστε την κρυπτογράφηση χωρίς να τροποποιήσετε οποιοδήποτε αρχείο ρυθμίσεων. -- Παρακάμψετε τις ρυθμίσεις δικτύου με ένα πρόγραμμα (default gateway, DNS, proxy, MTU). - -ΕΝΣΩΜΑΤΩΣΗ ΣΤΟ ΛΕΙΤΟΥΡΓΙΚΌ - -- Χαρακτηρίστε αξιόπιστα δίκτυα κινητής τηλεφωνίας ή Wi-Fi για να βελτιστοποιήσετε τη συνδεσιμότητά σας. -- Έξυπνες συντομεύσεις με τη Siri. - -Φιλικό Απόρρητο - -- Πλήρης διαφάνεια σχετικά με τους διακομιστές στους οποίους συνδέεστε. -- Διαλέξτε τα προκαθορισμένα τελικά σημεία όταν το DNS είναι προβληματικό. -- Δεν υπάρχουν υπηρεσίες ιστού, διαφημίσεις ή οποιαδήποτε ανεπιθύμητη λειτουργία εκτός από το ίδιο το VPN. - -~ - -Το Passepartout είναι ένας μη επίσημος πελάτης και σε καμία περίπτωση δεν είναι συνδεδεμένος με την OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN είναι εμπορικό σήμα κατατεθέν της OpenVPN Inc. diff --git a/fastlane/metadata/el/keywords.txt b/fastlane/metadata/el/keywords.txt deleted file mode 120000 index 15e8d007..00000000 --- a/fastlane/metadata/el/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/el/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/el/marketing_url.txt b/fastlane/metadata/el/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/el/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/el/name.txt b/fastlane/metadata/el/name.txt deleted file mode 100644 index ae4103ba..00000000 --- a/fastlane/metadata/el/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN Client diff --git a/fastlane/metadata/el/privacy_url.txt b/fastlane/metadata/el/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/el/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/el/promotional_text.txt b/fastlane/metadata/el/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/el/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/el/release_notes.txt b/fastlane/metadata/el/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/el/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/el/subtitle.txt b/fastlane/metadata/el/subtitle.txt deleted file mode 100644 index facc13a6..00000000 --- a/fastlane/metadata/el/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Σύνδεση .ovpn & VPN παρόχους diff --git a/fastlane/metadata/el/support_url.txt b/fastlane/metadata/el/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/el/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/en-US/apple_tv_privacy_policy.txt b/fastlane/metadata/en-US/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/en-US/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/en-US/description.txt b/fastlane/metadata/en-US/description.txt deleted file mode 100644 index d06248a4..00000000 --- a/fastlane/metadata/en-US/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout is a smart OpenVPN client perfectly integrated with the iOS platform. Passepartout is the only app you need for both well-known OpenVPN providers and your personal OpenVPN servers. - -With Trusted Networks and Siri Shortcuts, Passepartout unlocks the very best of using a VPN on iOS. - -Passepartout does not engage any unrequested background activity other than the VPN tunnel, thus being also friendlier to firewalls. - -Passepartout is open source: https://github.com/passepartoutvpn - -USE WITH MULTIPLE PROVIDERS - -Passepartout offers presets for major VPN providers: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -EASY TO USE - -- Incredible ease of use, with native look & feel. -- Handle your profiles in one single place. -- Import .ovpn configuration files. -- Fine-tune encryption without tweaking any configuration file. -- Override network settings in a snap (default gateway, DNS, proxy, MTU). - -OS INTEGRATION - -- Trust cellular or Wi-Fi networks to fine-grain your connectivity. -- Intuitive Siri Shortcuts. - -PRIVACY FRIENDLY - -- Full transparency on what servers you're connecting to. -- Pick pre-resolved endpoints when DNS is problematic. -- No web services, ads or any undesired bloat besides the VPN itself. - -~ - -Passepartout is a non-official client and is in no way affiliated with OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN is a registered trademark of OpenVPN Inc. diff --git a/fastlane/metadata/en-US/keywords.txt b/fastlane/metadata/en-US/keywords.txt deleted file mode 120000 index 84c76e2e..00000000 --- a/fastlane/metadata/en-US/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/en-US/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/en-US/marketing_url.txt b/fastlane/metadata/en-US/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/en-US/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/en-US/name.txt b/fastlane/metadata/en-US/name.txt deleted file mode 100644 index ae4103ba..00000000 --- a/fastlane/metadata/en-US/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN Client diff --git a/fastlane/metadata/en-US/privacy_url.txt b/fastlane/metadata/en-US/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/en-US/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/en-US/promotional_text.txt b/fastlane/metadata/en-US/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/en-US/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/en-US/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/en-US/subtitle.txt b/fastlane/metadata/en-US/subtitle.txt deleted file mode 100644 index 5c670931..00000000 --- a/fastlane/metadata/en-US/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Connect .ovpn & VPN providers diff --git a/fastlane/metadata/en-US/support_url.txt b/fastlane/metadata/en-US/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/en-US/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/es-MX/apple_tv_privacy_policy.txt b/fastlane/metadata/es-MX/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/es-MX/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/es-MX/description.txt b/fastlane/metadata/es-MX/description.txt deleted file mode 100644 index 80df445b..00000000 --- a/fastlane/metadata/es-MX/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout es un cliente OpenVPN inteligente perfectamente integrado con la plataforma iOS. Passepartout es la única aplicación que necesitas para conectarte con proveedores OpenVPN conocidos o con tu propio servidor OpenVPN. - -Con las Redes de Confianza y los Atajos Sugeridos, Passepartout saca lo mejor de iOS a la hora de usar un VPN. - -Passepartout no mantiene ninguna actividad en segundo plano que no sea el túnel VPN, siendo así compatible con los cortafuegos. - -Passepartout tiene código abierto: https://github.com/passepartoutvpn - -ÚSALO CON VARIOS PROVEEDORES - -Passepartout ofrece ajustes para estos proveedores VPN: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -FÁCIL DE USAR - -- Increíble facilidad de uso, con aspecto nativo. -- Gestiona tus perfiles en una sola pantalla. -- Importa ficheros de configuración .ovpn. -- Configura el cifrado sin retocar ningún fichero de configuración. -- Sobrescribe los ajustes de red en un chasquido (puerta de enlace, DNS, proxy, MTU). - -INTEGRACIÓN CON EL SISTEMA OPERATIVO - -- Añade la red móvil o una red Wi-Fi de confianza para refinar tu conectividad. -- Atajos Sugeridos intuitivos. - -RESPETUOSO CON TU PRIVACIDAD - -- Transparencia sobre los servidores conectados. -- Elige direcciones pre-resueltas cuando el DNS sea defectuoso. -- Sin servicios web, anuncios o cualquier actividad no deseada fuera del VPN. - -~ - -Passepartout es un cliente no oficial y no es afiliado de OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN es una marca registrada de OpenVPN Inc. diff --git a/fastlane/metadata/es-MX/keywords.txt b/fastlane/metadata/es-MX/keywords.txt deleted file mode 120000 index be6cbc25..00000000 --- a/fastlane/metadata/es-MX/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/es-MX/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/es-MX/marketing_url.txt b/fastlane/metadata/es-MX/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/es-MX/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/es-MX/name.txt b/fastlane/metadata/es-MX/name.txt deleted file mode 100644 index 1602c936..00000000 --- a/fastlane/metadata/es-MX/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - Cliente OpenVPN diff --git a/fastlane/metadata/es-MX/privacy_url.txt b/fastlane/metadata/es-MX/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/es-MX/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/es-MX/promotional_text.txt b/fastlane/metadata/es-MX/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/es-MX/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/es-MX/release_notes.txt b/fastlane/metadata/es-MX/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/es-MX/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/es-MX/subtitle.txt b/fastlane/metadata/es-MX/subtitle.txt deleted file mode 100644 index 0858e5f7..00000000 --- a/fastlane/metadata/es-MX/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Conecta .ovpn & proveedor VPN diff --git a/fastlane/metadata/es-MX/support_url.txt b/fastlane/metadata/es-MX/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/es-MX/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/fr-FR/apple_tv_privacy_policy.txt b/fastlane/metadata/fr-FR/apple_tv_privacy_policy.txt deleted file mode 100755 index 8b137891..00000000 --- a/fastlane/metadata/fr-FR/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/fr-FR/description.txt b/fastlane/metadata/fr-FR/description.txt deleted file mode 100644 index 7a286332..00000000 --- a/fastlane/metadata/fr-FR/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout est un client OpenVPN parfaitement intégré avec la plateforme iOs. Passepartout est le seul app dont vous aurez besoin, autant pour les fournisseurs connu OpenVPN, que pour vos serveurs OpenVPN privés. - -Avec les réseaux de confiance et les Raccourcis Siri, Passepartout ouvre toutes les possibilités d'utiliser un VPN avec iOS. - -Passepartout n'engage pas de requêtes non requises en arrière-plan, autre que le tunnel VPN, ce qui le rend plus accessible avec les coupe-feu. - -Passepartout est open source: https://github.com/passepartoutvpn - -UTILISEZ AVEC PLUSIEURS FOURNISSEURS - -Passepartout offre des réglages pré-conçu avec des fournisseurs VPN majeurs : - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -FACILE D'UTILISATION - -- Utilisation très simple, look natif iOS. -- S'occupe de vos profiles en un Seul endroit. -- Importer les fichiers de configuration .ovpn. -- Affiner l'encryption sans modifier les fichiers de configuration. -- Outrepasse les paramètres réseaux en un clin d'oeil (passerelle par défaut, DNS, proxy, MTU). - -INTÉGRATION OS - -- Faire confidence aux réseaux cellulaire ou Wi-Fi pour peaufiner vos connections. -- Raccourcis Siri intuitifs. - -VIE PRIVÉE - -- Transparence completes aux serveurs connectés. -- Choisissez des parametères pré-résolu lorsque le DNS est problématique. -- Aucun service web, pub où information non désirée, que le VPN. - -~ - -Passepartout best un client non-officiel et n'est aucunement affilié à OpenVPN inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN est une marque enregistrée de OpenVPN Inc. diff --git a/fastlane/metadata/fr-FR/keywords.txt b/fastlane/metadata/fr-FR/keywords.txt deleted file mode 120000 index d535dd8a..00000000 --- a/fastlane/metadata/fr-FR/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/fr-FR/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/fr-FR/marketing_url.txt b/fastlane/metadata/fr-FR/marketing_url.txt deleted file mode 100755 index 011d2c5f..00000000 --- a/fastlane/metadata/fr-FR/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/fr-FR/name.txt b/fastlane/metadata/fr-FR/name.txt deleted file mode 100755 index ef42d791..00000000 --- a/fastlane/metadata/fr-FR/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - Client OpenVPN diff --git a/fastlane/metadata/fr-FR/privacy_url.txt b/fastlane/metadata/fr-FR/privacy_url.txt deleted file mode 100755 index 03ebc6e8..00000000 --- a/fastlane/metadata/fr-FR/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/fr-FR/promotional_text.txt b/fastlane/metadata/fr-FR/promotional_text.txt deleted file mode 100755 index 8b137891..00000000 --- a/fastlane/metadata/fr-FR/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/fr-FR/release_notes.txt b/fastlane/metadata/fr-FR/release_notes.txt deleted file mode 100755 index 689876c4..00000000 --- a/fastlane/metadata/fr-FR/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/fr-FR/subtitle.txt b/fastlane/metadata/fr-FR/subtitle.txt deleted file mode 100755 index e33099bf..00000000 --- a/fastlane/metadata/fr-FR/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Connecter .ovpn & services VPN diff --git a/fastlane/metadata/fr-FR/support_url.txt b/fastlane/metadata/fr-FR/support_url.txt deleted file mode 100755 index d9c7dbb5..00000000 --- a/fastlane/metadata/fr-FR/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/it/apple_tv_privacy_policy.txt b/fastlane/metadata/it/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/it/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/it/description.txt b/fastlane/metadata/it/description.txt deleted file mode 100644 index c4233e65..00000000 --- a/fastlane/metadata/it/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout è un client OpenVPN intelligente perfettamente integrato con la piattaforma iOS. Passepartout è l'unica app di cui hai bisogno sia per provider OpenVPN conosciuti che per i tuoi server OpenVPN personali. - -Con le Reti Sicure ed i comandi rapidi Siri, Passepartout è il modo migliore di usare una VPN su iOS. - -Passepartout non avvia in background nessuna attività non richiesta che non sia la VPN, essendo per questo motivo anche più congeniale ai firewall. - -Passepartout è open source: https://github.com/passepartoutvpn - -USALO CON VARI PROVIDER - -Passepartout offre profili per i maggiori provider VPN: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -FACILE DA USARE - -- Incredibilmente semplice, con look nativo. -- Gestisci i tuoi profili in una singola schermata. -- Importa file di configurazione .ovpn. -- Regola la crittografia senza toccare alcun file di configurazione. -- Sovrascrivi le impostazioni di rete in un attimo (gateway predefinito, DNS, proxy, MTU). - -INTEGRAZIONE CON IL SISTEMA - -- Rendi la rete mobile o Wi-Fi sicura per personalizzare la tua connettività. -- Intuitivi comandi rapidi Siri. - -ORIENTATO ALLA PRIVACY - -- Completa trasparenza sui server a cui ti connetti. -- Scegli indirizzi pre-risolti quando il DNS è problematico. -- Nessun web service, pubblicità o altra aggiunta inutile oltre la VPN. - -~ - -Passepartout è un client non ufficiale e non è affiliato ad OpenVPN Inc. in alcuna maniera. - -© 2002-2018 OpenVPN Inc. - OpenVPN è un marchio registrato di OpenVPN Inc. diff --git a/fastlane/metadata/it/keywords.txt b/fastlane/metadata/it/keywords.txt deleted file mode 120000 index 05f25f37..00000000 --- a/fastlane/metadata/it/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/it/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/it/marketing_url.txt b/fastlane/metadata/it/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/it/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/it/name.txt b/fastlane/metadata/it/name.txt deleted file mode 100644 index ae4103ba..00000000 --- a/fastlane/metadata/it/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN Client diff --git a/fastlane/metadata/it/privacy_url.txt b/fastlane/metadata/it/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/it/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/it/promotional_text.txt b/fastlane/metadata/it/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/it/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/it/release_notes.txt b/fastlane/metadata/it/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/it/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/it/subtitle.txt b/fastlane/metadata/it/subtitle.txt deleted file mode 100644 index 3f4a4ff7..00000000 --- a/fastlane/metadata/it/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Connetti .ovpn & provider VPN diff --git a/fastlane/metadata/it/support_url.txt b/fastlane/metadata/it/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/it/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/nl-NL/apple_tv_privacy_policy.txt b/fastlane/metadata/nl-NL/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/nl-NL/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/nl-NL/description.txt b/fastlane/metadata/nl-NL/description.txt deleted file mode 100644 index dd80e103..00000000 --- a/fastlane/metadata/nl-NL/description.txt +++ /dev/null @@ -1,46 +0,0 @@ -Passepartout is een slimme OpenVPN-client die perfect is geïntegreerd met het iOS-platform. Passepartout is de enige app die je nodig hebt voor zowel bekende OpenVPN-providers als je persoonlijke OpenVPN-servers. - -Met Trusted Networks en Siri Shortcuts ontgrendelt Passepartout het beste van het gebruik van een VPN op iOS. - -Passepartout neemt geen andere ongevraagde achtergrondactiviteit op dan de VPN-tunnel en is hierdoor ook vriendelijker voor firewalls. - -Passepartout is open source: https://github.com/passepartoutvpn - -GEBRUIK MET MEERDERE PROVIDERS - -Passepartout biedt presets voor grote VPN-providers: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -MAKKELIJK IN GEBRUIK - -- Ongelooflijk gebruiksgemak, met native look & feel. -- Beheer uw profielen op één plek. -- Import .ovpn configuratie bestanden. -- Verfijn de codering zonder een configuratiebestand aan te passen. - -OS INTEGRATIE - -- Vertrouw op mobiele of Wi-Fi-netwerken om uw connectiviteit te verfijnen. -- Intuïtieve Siri-snelkoppelingen. - -PRIVACY FRIENDLY - -- Volledige transparantie over de servers waarmee u verbinding maakt. -- Kies vooraf vertaalde eindpunten wanneer DNS problematisch is. -- Geen web-services, advertenties of overbodige functionaliteit naast VPN zelf. - -~ - -Passepartout is een niet-officiële client en is op geen enkele manier verbonden aan OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN is a registered trademark of OpenVPN Inc. diff --git a/fastlane/metadata/nl-NL/keywords.txt b/fastlane/metadata/nl-NL/keywords.txt deleted file mode 120000 index 45dfc473..00000000 --- a/fastlane/metadata/nl-NL/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/nl/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/nl-NL/marketing_url.txt b/fastlane/metadata/nl-NL/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/nl-NL/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/nl-NL/name.txt b/fastlane/metadata/nl-NL/name.txt deleted file mode 100644 index ae4103ba..00000000 --- a/fastlane/metadata/nl-NL/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN Client diff --git a/fastlane/metadata/nl-NL/privacy_url.txt b/fastlane/metadata/nl-NL/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/nl-NL/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/nl-NL/promotional_text.txt b/fastlane/metadata/nl-NL/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/nl-NL/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/nl-NL/release_notes.txt b/fastlane/metadata/nl-NL/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/nl-NL/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/nl-NL/subtitle.txt b/fastlane/metadata/nl-NL/subtitle.txt deleted file mode 100644 index f0b18dbd..00000000 --- a/fastlane/metadata/nl-NL/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Verbind .ovpn & VPN providers diff --git a/fastlane/metadata/nl-NL/support_url.txt b/fastlane/metadata/nl-NL/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/nl-NL/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/pl/apple_tv_privacy_policy.txt b/fastlane/metadata/pl/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/pl/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/pl/description.txt b/fastlane/metadata/pl/description.txt deleted file mode 100644 index adab6605..00000000 --- a/fastlane/metadata/pl/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout to inteligentny klient OpenVPN, perfekcyjnie zintegrowany z platformą iOS. Passepartout to jedyna aplikacja dla znanych usługodawców OpenVPN i Twoich prywatnych serwerów OpenVPN. - -Passepartout, z obsługą skrótów Siri oraz konfiguracją sieci zaufanych, pozwala na najłatwiejsze użytkowanie VPN na iOS. - -Passepartout nie inicjuje połączeń innych niż tunel VPN, dlatego jest aplikacją przyjazną dla zapór sieciowych. - -Passepartout jest open source: https://github.com/passepartoutvpn - -UŻYWAJ Z WIELOMA USŁUGODAWCAMI - -Passepartout oferuje gotowe konfiguracje dla poniższych usługodawców: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -ŁATWY W UŻYCIU - -- Niesamowita łatwość w użytkowaniu z przejrzystym wyglądem -- Przechowuj swoje profile w jednym miejscu -- Importuj pliki konfiguracyjne .openvpn -- Optymalne szyfrowanie bez konieczności dodatkowej konfiguracji -- Napisz ustawienia sieciowe z łatwością (brama domyślna, DNS, Proxy, MTU) - -INTEGRACJA Z SYSTEMEM - -- Zaufaj wybranym połączeniom WiFi lub sieci komórkowej żeby kontrolować swoje połączenie -- Intuicyjne skróty Siri - -PRZYJAZNA PRYWATNOŚCI - -- Transparentność serwerów do których jesteś połączony/a -- Wybierz zdefiniowane węzły końcowe, gdy DNS jest problematyczne -- Żadnych reklam, śmieci, ani serwisów sieciowych - tylko protokół VPN - -~ - -Passepartout to nieoficjalny klient i nie jest powiązany z OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN to zarejestrowany znak towarowy OpenVPN Inc. diff --git a/fastlane/metadata/pl/keywords.txt b/fastlane/metadata/pl/keywords.txt deleted file mode 120000 index 055c2869..00000000 --- a/fastlane/metadata/pl/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/pl-PL/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/pl/marketing_url.txt b/fastlane/metadata/pl/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/pl/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/pl/name.txt b/fastlane/metadata/pl/name.txt deleted file mode 100644 index a9c148ef..00000000 --- a/fastlane/metadata/pl/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - Klient OpenVPN diff --git a/fastlane/metadata/pl/privacy_url.txt b/fastlane/metadata/pl/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/pl/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/pl/promotional_text.txt b/fastlane/metadata/pl/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/pl/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/pl/release_notes.txt b/fastlane/metadata/pl/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/pl/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/pl/subtitle.txt b/fastlane/metadata/pl/subtitle.txt deleted file mode 100644 index 3d2ec69f..00000000 --- a/fastlane/metadata/pl/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Połącz z .ovpn i serwisami VPN diff --git a/fastlane/metadata/pl/support_url.txt b/fastlane/metadata/pl/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/pl/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/primary_category.txt b/fastlane/metadata/primary_category.txt deleted file mode 100644 index 41f44c00..00000000 --- a/fastlane/metadata/primary_category.txt +++ /dev/null @@ -1 +0,0 @@ -UTILITIES diff --git a/fastlane/metadata/primary_first_sub_category.txt b/fastlane/metadata/primary_first_sub_category.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/primary_first_sub_category.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/primary_second_sub_category.txt b/fastlane/metadata/primary_second_sub_category.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/primary_second_sub_category.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/pt-BR/apple_tv_privacy_policy.txt b/fastlane/metadata/pt-BR/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/pt-BR/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/pt-BR/description.txt b/fastlane/metadata/pt-BR/description.txt deleted file mode 100644 index d5d15796..00000000 --- a/fastlane/metadata/pt-BR/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout é um cliente inteligente de OpenVPN perfeitamente integrado com iOS. Passepartout é o único aplicativo que possibilita serviços populares de OpenVPN ou de sua própria escolha. - -Com "Redes confiáveis" e "Atalhos da Siri", Passepartout possibilita uma melhor experiência VPN para iOS. - -Passepartout não executa nenhum processo em plano de fundo além do túnel VPN, onde os mesmos são amigáveis com firewall. - -Passepartout possui código aberto: https://github.com/passepartoutvpn - -UTILIZE DIVERSOS SERVIÇOS DE VPN - -Passepartout oferece configurações para os seguintes provedores de VPN: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -FÁCIL DE USAR - -- Fácil de usar com seu visual e experiência nativa. -- Controle seus perfis em um único lugar. -- Importe arquivos de configuração .ovpn. -- Habilite criptografia sem melhorar nenhum arquivo de configuração. -- Substitua configurações de rede em um piscar de olhos (gateway padrão, DNS, proxy, MTU). - -INTEGRAÇÃO COM O SISTEMA - -- Confie em redes celular e Wi-Fi para melhor configurar sua conectividade. -- Integração com "Atalhos da Siri". - -FOCO EM PRIVACIDADE - -- Absoluta transparência em quais servidores você se conecta. -- Escolha destinos pré-resolvidos quando DNS está problemático. -- Sem cadastro, propagandas ou qualquer funcionalidade indesejada que não seja VPN por si só. - -~ - -Passepartout não é um cliente oficial e não possui nenhuma afiliação com OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN é um marca registrada de OpenVPN Inc. diff --git a/fastlane/metadata/pt-BR/keywords.txt b/fastlane/metadata/pt-BR/keywords.txt deleted file mode 120000 index 51d15413..00000000 --- a/fastlane/metadata/pt-BR/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/pt-BR/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/pt-BR/marketing_url.txt b/fastlane/metadata/pt-BR/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/pt-BR/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/pt-BR/name.txt b/fastlane/metadata/pt-BR/name.txt deleted file mode 100644 index ef42d791..00000000 --- a/fastlane/metadata/pt-BR/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - Client OpenVPN diff --git a/fastlane/metadata/pt-BR/privacy_url.txt b/fastlane/metadata/pt-BR/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/pt-BR/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/pt-BR/promotional_text.txt b/fastlane/metadata/pt-BR/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/pt-BR/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/pt-BR/release_notes.txt b/fastlane/metadata/pt-BR/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/pt-BR/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/pt-BR/subtitle.txt b/fastlane/metadata/pt-BR/subtitle.txt deleted file mode 100644 index 141eb884..00000000 --- a/fastlane/metadata/pt-BR/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Conecte .ovpn e serviços VPN diff --git a/fastlane/metadata/pt-BR/support_url.txt b/fastlane/metadata/pt-BR/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/pt-BR/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/ru/apple_tv_privacy_policy.txt b/fastlane/metadata/ru/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/ru/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/ru/description.txt b/fastlane/metadata/ru/description.txt deleted file mode 100644 index c134a237..00000000 --- a/fastlane/metadata/ru/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout - это умный OpenVPN клиент, идеально интегрированный для работы с iOS. Passepartout - единственное приложения которое Вам понадобиться для большинства известных OpenVPN сервисов, и Ваших собственных OpenVPN серверов. - -С Доверенными Сетями и Командами Siri, Passepartout открывает лучшие возможности использования VPN на iOS. - -Passepartout не участвует в ненужной фоновой активности, кроме VPN туннелирования, тем самым являясь более дружелюбным к межсетевому экрану. - -Passepartout имеет открытый исходный код: https://github.com/passepartoutvpn - -ИСПОЛЬЗОВАНИЕ С НЕСКОЛЬКИМИ VPN ПРОВАЙДЕРАМИ - -Passepartout предлагает предустановленные настройки для основных VPN провайдеров: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -ЛЕГО ИСПОЛЬЗОВАТЬ - -- Невероятная простота в использовании, со знакомым видом интерфйеса. -- Управляйте Вашими профилями в одном месте. -- Импортируйте файлы конфигурации .ovpn . -- Тонкая настройка шифрования, без изменений в файлах конфигурации. -- Перенаправление настроек сети в одно мгновение (стандартный порт, DNS, прокси, MTU).| - -ИНТЕГРАЦИЯ С ОПЕРАЦИОННОЙ СИСТЕМОЙ - -- Доверие мобильным или Wi-Fi сетям для более точной настройки подключения. -- Интуитивные Команды Siri. - -ДРУЖЕЛЮбНОСТЬ К КОНФИДЕНЦИАЛЬНОСТИ - -- Полная прозрачность при подключении к серверам. -- Подключение к предварительно выбранным конечным точкам при проблемах с DNS. -- Никаких веб-сервисов, рекламы и другого ненужного мусора помимо самого VPN. - -~ - -Passepartout не является официальным клиентом, и никак не связан с OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN зарегистрированная торговая марка OpenVPN Inc. diff --git a/fastlane/metadata/ru/keywords.txt b/fastlane/metadata/ru/keywords.txt deleted file mode 120000 index c0cce26d..00000000 --- a/fastlane/metadata/ru/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/ru/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/ru/marketing_url.txt b/fastlane/metadata/ru/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/ru/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/ru/name.txt b/fastlane/metadata/ru/name.txt deleted file mode 100644 index 3792b636..00000000 --- a/fastlane/metadata/ru/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN клиент diff --git a/fastlane/metadata/ru/privacy_url.txt b/fastlane/metadata/ru/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/ru/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/ru/promotional_text.txt b/fastlane/metadata/ru/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/ru/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/ru/release_notes.txt b/fastlane/metadata/ru/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/ru/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/ru/subtitle.txt b/fastlane/metadata/ru/subtitle.txt deleted file mode 100644 index 1f41f0bf..00000000 --- a/fastlane/metadata/ru/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Подключить .ovpn и VPN сервисы diff --git a/fastlane/metadata/ru/support_url.txt b/fastlane/metadata/ru/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/ru/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/metadata/secondary_category.txt b/fastlane/metadata/secondary_category.txt deleted file mode 100644 index cd65e793..00000000 --- a/fastlane/metadata/secondary_category.txt +++ /dev/null @@ -1 +0,0 @@ -PRODUCTIVITY diff --git a/fastlane/metadata/secondary_first_sub_category.txt b/fastlane/metadata/secondary_first_sub_category.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/secondary_first_sub_category.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/secondary_second_sub_category.txt b/fastlane/metadata/secondary_second_sub_category.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/secondary_second_sub_category.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/sv/apple_tv_privacy_policy.txt b/fastlane/metadata/sv/apple_tv_privacy_policy.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/sv/apple_tv_privacy_policy.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/sv/description.txt b/fastlane/metadata/sv/description.txt deleted file mode 100644 index f4dce095..00000000 --- a/fastlane/metadata/sv/description.txt +++ /dev/null @@ -1,47 +0,0 @@ -Passepartout är en smart OpenVPN-klient som är helt integrerad med iOS-plattformen. Passepartout är den enda app du behöver för både kända OpenVPN-leverantörer och dina personliga OpenVPN-servrar. - -Med Betrodda Nätverk och Siri Shortcuts låser Passepartout det bästa av att använda en VPN på iOS. - -Passepartout engagerar inte någon oönskad bakgrundsaktivitet utom VPN-tunneln, vilket är också vänligare för andra brandväggar eller VPN-klienter. - -Passepartout är öppen källkod: https://github.com/passepartoutvpn - -ANVÄNDNING MED FLERA PROVIDERS - -Passepartout erbjuder förinställningar för större VPN-leverantörer: - -- Child Safe VPN -- Hide.me -- Mullvad -- NordVPN -- Private Internet Access -- ProtonVPN -- TorGuard -- TunnelBear -- VyprVPN -- Windscribe - -LÄTT ATT ANVÄNDA - -- Otroligt enkel att använda, med inbyggd se & känsla. -- Hantera dina profiler på ett enda ställe. -- Importera .ovpn konfigurationsfiler. -- Finjustera kryptering utan att ändra någon konfigurationsfil. -- Åsidosätta nätverksinställningar i en snap (normal gateway, DNS, proxy, MTU). - -OS INTEGRATION - -- Lita på mobil- eller Wi-Fi-nätverk för att finfina din anslutning. -- Intuitiva Siri Genvägar. - -PRIVATIV VÄNLIGT - -- Full insyn på vilka servrar du ansluter till. -- Välj förutbestämda slutpunkter när DNS är problematiskt. -- Inga webbtjänster, annonser eller oönskad upptrappning förutom VPN själv. - -~ - -Passepartout är en icke-officiell kund och är inte ansluten till OpenVPN Inc. - -© 2002-2018 OpenVPN Inc. - OpenVPN är ett registrerat varumärke som tillhör OpenVPN Inc. diff --git a/fastlane/metadata/sv/keywords.txt b/fastlane/metadata/sv/keywords.txt deleted file mode 120000 index 5b8d2f8a..00000000 --- a/fastlane/metadata/sv/keywords.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../metadata/sv/keywords.txt \ No newline at end of file diff --git a/fastlane/metadata/sv/marketing_url.txt b/fastlane/metadata/sv/marketing_url.txt deleted file mode 100644 index 011d2c5f..00000000 --- a/fastlane/metadata/sv/marketing_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app diff --git a/fastlane/metadata/sv/name.txt b/fastlane/metadata/sv/name.txt deleted file mode 100644 index f4f83c28..00000000 --- a/fastlane/metadata/sv/name.txt +++ /dev/null @@ -1 +0,0 @@ -Passepartout - OpenVPN Klient diff --git a/fastlane/metadata/sv/privacy_url.txt b/fastlane/metadata/sv/privacy_url.txt deleted file mode 100644 index 03ebc6e8..00000000 --- a/fastlane/metadata/sv/privacy_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://passepartoutvpn.app/privacy/ diff --git a/fastlane/metadata/sv/promotional_text.txt b/fastlane/metadata/sv/promotional_text.txt deleted file mode 100644 index 8b137891..00000000 --- a/fastlane/metadata/sv/promotional_text.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fastlane/metadata/sv/release_notes.txt b/fastlane/metadata/sv/release_notes.txt deleted file mode 100644 index 689876c4..00000000 --- a/fastlane/metadata/sv/release_notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -### Fixed - -- Losing profiles on upgrade. -- Twitch link does not work when Twitch app not installed. - diff --git a/fastlane/metadata/sv/subtitle.txt b/fastlane/metadata/sv/subtitle.txt deleted file mode 100644 index acb804bd..00000000 --- a/fastlane/metadata/sv/subtitle.txt +++ /dev/null @@ -1 +0,0 @@ -Annslut .ovpn & VPN tjänster diff --git a/fastlane/metadata/sv/support_url.txt b/fastlane/metadata/sv/support_url.txt deleted file mode 100644 index d9c7dbb5..00000000 --- a/fastlane/metadata/sv/support_url.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.reddit.com/r/passepartout diff --git a/fastlane/screenshots/en-US/ipad-01.png b/fastlane/screenshots/en-US/ipad-01.png deleted file mode 100644 index 56899668..00000000 Binary files a/fastlane/screenshots/en-US/ipad-01.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/ipad-02.png b/fastlane/screenshots/en-US/ipad-02.png deleted file mode 100644 index 838bcd63..00000000 Binary files a/fastlane/screenshots/en-US/ipad-02.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/ipad-03.png b/fastlane/screenshots/en-US/ipad-03.png deleted file mode 100644 index bb5e4f51..00000000 Binary files a/fastlane/screenshots/en-US/ipad-03.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/ipad-04.png b/fastlane/screenshots/en-US/ipad-04.png deleted file mode 100644 index 153cf2a7..00000000 Binary files a/fastlane/screenshots/en-US/ipad-04.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/ipad-05.png b/fastlane/screenshots/en-US/ipad-05.png deleted file mode 100644 index f618d04e..00000000 Binary files a/fastlane/screenshots/en-US/ipad-05.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone55-01.png b/fastlane/screenshots/en-US/iphone55-01.png deleted file mode 100644 index 752e6d77..00000000 Binary files a/fastlane/screenshots/en-US/iphone55-01.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone55-02.png b/fastlane/screenshots/en-US/iphone55-02.png deleted file mode 100644 index b6608a42..00000000 Binary files a/fastlane/screenshots/en-US/iphone55-02.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone55-03.png b/fastlane/screenshots/en-US/iphone55-03.png deleted file mode 100644 index df0c3714..00000000 Binary files a/fastlane/screenshots/en-US/iphone55-03.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone55-04.png b/fastlane/screenshots/en-US/iphone55-04.png deleted file mode 100644 index 95102812..00000000 Binary files a/fastlane/screenshots/en-US/iphone55-04.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone55-05.png b/fastlane/screenshots/en-US/iphone55-05.png deleted file mode 100644 index 6b4b983c..00000000 Binary files a/fastlane/screenshots/en-US/iphone55-05.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone65-01.png b/fastlane/screenshots/en-US/iphone65-01.png deleted file mode 100644 index 9c1f2d1d..00000000 Binary files a/fastlane/screenshots/en-US/iphone65-01.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone65-02.png b/fastlane/screenshots/en-US/iphone65-02.png deleted file mode 100644 index ba362dba..00000000 Binary files a/fastlane/screenshots/en-US/iphone65-02.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone65-03.png b/fastlane/screenshots/en-US/iphone65-03.png deleted file mode 100644 index 0f3b4c79..00000000 Binary files a/fastlane/screenshots/en-US/iphone65-03.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone65-04.png b/fastlane/screenshots/en-US/iphone65-04.png deleted file mode 100644 index 0884707a..00000000 Binary files a/fastlane/screenshots/en-US/iphone65-04.png and /dev/null differ diff --git a/fastlane/screenshots/en-US/iphone65-05.png b/fastlane/screenshots/en-US/iphone65-05.png deleted file mode 100644 index 55a2bcf2..00000000 Binary files a/fastlane/screenshots/en-US/iphone65-05.png and /dev/null differ diff --git a/scripts/export-for-translations.sh b/scripts/export-for-translations.sh deleted file mode 120000 index 306f13a0..00000000 --- a/scripts/export-for-translations.sh +++ /dev/null @@ -1 +0,0 @@ -../Submodules/Core/scripts/export-for-translations.sh \ No newline at end of file diff --git a/scripts/export-for-translations.sh b/scripts/export-for-translations.sh new file mode 100755 index 00000000..548ff868 --- /dev/null +++ b/scripts/export-for-translations.sh @@ -0,0 +1,33 @@ +#!/bin/sh +. .env + +DIST="l10n" +DIST_APP="$DIST/App" +DIST_META="$DIST/Meta" +OUTPUT="passepartout-translations.zip" + +rm -rf $OUTPUT $DIST +mkdir -p $DIST_APP +mkdir -p $DIST_META + +if [[ $1 == "all" ]]; then + cp Submodules/Core/Passepartout/Resources/en.lproj/Core.strings $DIST_APP/Core.txt + cp Submodules/Core/Passepartout/Resources/en.lproj/Intents.strings $DIST_APP/Intents.txt + cp $PROJECT/Global/en.lproj/App.strings $DIST_APP/App.txt + cp $PROJECT/en.lproj/InfoPlist.strings $DIST_APP/InfoPlist.txt + + cp fastlane/metadata/en-US/name.txt $DIST_META + cp fastlane/metadata/en-US/subtitle.txt $DIST_META + cp fastlane/metadata/en-US/description.txt $DIST_META +elif [[ $1 == "new" ]]; then + grep -f templates/new-strings.txt Submodules/Core/Passepartout/Resources/en.lproj/Core.strings >$DIST_APP/Core.txt + grep -f templates/new-strings.txt Submodules/Core/Passepartout/Resources/en.lproj/Intents.strings >$DIST_APP/Intents.txt + grep -f templates/new-strings.txt $PROJECT/Global/en.lproj/App.strings >$DIST_APP/App.txt + grep -f templates/new-strings.txt $PROJECT/en.lproj/InfoPlist.strings >$DIST_APP/InfoPlist.txt +else + echo "No argument given (all|new)" + exit +fi + +cp templates/iaps.txt $DIST/Products.txt +zip -r $OUTPUT $DIST diff --git a/scripts/list-untranslated.sh b/scripts/list-untranslated.sh deleted file mode 120000 index 348d61b0..00000000 --- a/scripts/list-untranslated.sh +++ /dev/null @@ -1 +0,0 @@ -../Submodules/Core/scripts/list-untranslated.sh \ No newline at end of file diff --git a/scripts/list-untranslated.sh b/scripts/list-untranslated.sh new file mode 100755 index 00000000..9c9e9c28 --- /dev/null +++ b/scripts/list-untranslated.sh @@ -0,0 +1,30 @@ +#!/bin/sh +. .env + +DIR_APP="$PROJECT/Global" +FILENAME_APP="App.strings" +DIR_CORE="Submodules/Core/Passepartout/Resources" +FILENAME_CORE="Core.strings" + +if [[ $2 = "core" ]]; then + DIR=$DIR_CORE + FILENAME=$FILENAME_CORE +else + DIR=$DIR_APP + FILENAME=$FILENAME_APP +fi + +LANG_BASE="en" +LANG_TARGET="$1" +STRINGS_BASE="$DIR/$LANG_BASE.lproj/$FILENAME" +STRINGS_TARGET="$DIR/$LANG_TARGET.lproj/$FILENAME" +IDS="string-ids.tmp" +TMPOUT="untranslated.tmp" + +sed -E "s/^(.+) = .*$/\1/" $STRINGS_BASE | sort | grep '^"' >$IDS.$LANG_BASE +sed -E "s/^(.+) = .*$/\1/" $STRINGS_TARGET | sort | grep '^"' >$IDS.$LANG_TARGET +diff $IDS.$LANG_BASE $IDS.$LANG_TARGET | grep "^<" | sed -E 's/^< "(.*)"$/\1/g' >$TMPOUT +rm -f $IDS.* + +grep -f $TMPOUT $STRINGS_BASE +rm $TMPOUT diff --git a/scripts/push-release.sh b/scripts/push-release.sh deleted file mode 120000 index 68eb3a93..00000000 --- a/scripts/push-release.sh +++ /dev/null @@ -1 +0,0 @@ -../Submodules/Core/scripts/push-release.sh \ No newline at end of file diff --git a/scripts/push-release.sh b/scripts/push-release.sh new file mode 100755 index 00000000..7585f1f2 --- /dev/null +++ b/scripts/push-release.sh @@ -0,0 +1,6 @@ +#!/bin/sh +git push && git push github +git push --tags && git push --tags github +git checkout stable && git merge master +git push github +git checkout master diff --git a/scripts/reset-archive.sh b/scripts/reset-archive.sh deleted file mode 120000 index c874f401..00000000 --- a/scripts/reset-archive.sh +++ /dev/null @@ -1 +0,0 @@ -../Submodules/Core/scripts/reset-archive.sh \ No newline at end of file diff --git a/scripts/reset-archive.sh b/scripts/reset-archive.sh new file mode 100755 index 00000000..0d0f4dcb --- /dev/null +++ b/scripts/reset-archive.sh @@ -0,0 +1,3 @@ +#!/bin/sh +git checkout Passepartout*/Info.plist +git checkout Passepartout*.pbxproj diff --git a/swiftgen.yml b/swiftgen.yml deleted file mode 100644 index fe9ab66e..00000000 --- a/swiftgen.yml +++ /dev/null @@ -1,29 +0,0 @@ -strings: - inputs: - - Submodules/Core/Passepartout/Resources/en.lproj/Core.strings - - Passepartout-iOS/Global/en.lproj/App.strings - outputs: - - templateName: structured-swift4 - output: Passepartout-iOS/Global/SwiftGen+Strings.swift - -ib: - inputs: - - Passepartout-iOS/Base.lproj/About.storyboard - - Passepartout-iOS/Base.lproj/Main.storyboard - - Passepartout-iOS/Base.lproj/Organizer.storyboard - - Passepartout-iOS/Base.lproj/Purchase.storyboard - - Passepartout-iOS/Base.lproj/Shortcuts.storyboard - outputs: - - templateName: scenes-swift4 - output: Passepartout-iOS/Global/SwiftGen+Scenes.swift - - templateName: segues-swift4 - output: Passepartout-iOS/Global/SwiftGen+Segues.swift - -xcassets: - inputs: - - Passepartout-iOS/Assets.xcassets - - Passepartout-iOS/Flags.xcassets - - Passepartout-iOS/Providers.xcassets - outputs: - - templateName: swift4 - output: Passepartout-iOS/Global/SwiftGen+Assets.swift