mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-18 05:42:16 +00:00
Merge branch 'simplify-host-wizard'
This commit is contained in:
commit
675cfe1b14
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
|
- Improved host import flow.
|
||||||
- Use active profile name in iOS settings.
|
- Use active profile name in iOS settings.
|
||||||
|
|
||||||
## 1.11.5 (2020-06-23)
|
## 1.11.5 (2020-06-23)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Sge-vR-hZB">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Sge-vR-hZB">
|
||||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
@ -206,11 +206,6 @@
|
|||||||
<action selector="close" destination="c0p-pg-Arz" id="yVS-jW-gwZ"/>
|
<action selector="close" destination="c0p-pg-Arz" id="yVS-jW-gwZ"/>
|
||||||
</connections>
|
</connections>
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
<barButtonItem key="rightBarButtonItem" systemItem="organize" id="Lcp-oT-AOy">
|
|
||||||
<connections>
|
|
||||||
<action selector="openConfigurationFile" destination="c0p-pg-Arz" id="E7s-pJ-8y6"/>
|
|
||||||
</connections>
|
|
||||||
</barButtonItem>
|
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="c40-c8-YA4" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="c40-c8-YA4" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
@ -238,7 +233,7 @@
|
|||||||
<objects>
|
<objects>
|
||||||
<navigationController storyboardIdentifier="WizardHostIdentifier" id="xKb-d1-xzB" sceneMemberID="viewController">
|
<navigationController storyboardIdentifier="WizardHostIdentifier" id="xKb-d1-xzB" sceneMemberID="viewController">
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="7oY-rT-q4A">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="7oY-rT-q4A">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="56"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<connections>
|
<connections>
|
||||||
@ -247,7 +242,7 @@
|
|||||||
</navigationController>
|
</navigationController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="BvG-Pe-O1S" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="BvG-Pe-O1S" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="-1727" y="-357"/>
|
<point key="canvasLocation" x="-1700" y="-357"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Donation View Controller-->
|
<!--Donation View Controller-->
|
||||||
<scene sceneID="NrW-UF-gN3">
|
<scene sceneID="NrW-UF-gN3">
|
||||||
@ -388,6 +383,7 @@
|
|||||||
<segue destination="POR-9u-PsE" kind="presentation" identifier="AboutSegueIdentifier" modalPresentationStyle="formSheet" id="78g-ra-Yhp"/>
|
<segue destination="POR-9u-PsE" kind="presentation" identifier="AboutSegueIdentifier" modalPresentationStyle="formSheet" id="78g-ra-Yhp"/>
|
||||||
<segue destination="5ku-HX-5yk" kind="presentation" identifier="DonateSegueIdentifier" modalPresentationStyle="formSheet" id="H4q-BS-PmK"/>
|
<segue destination="5ku-HX-5yk" kind="presentation" identifier="DonateSegueIdentifier" modalPresentationStyle="formSheet" id="H4q-BS-PmK"/>
|
||||||
<segue destination="pel-Q7-aOe" kind="showDetail" identifier="SelectProfileSegueIdentifier" id="bkI-h9-mGF"/>
|
<segue destination="pel-Q7-aOe" kind="showDetail" identifier="SelectProfileSegueIdentifier" id="bkI-h9-mGF"/>
|
||||||
|
<segue destination="xKb-d1-xzB" kind="presentation" identifier="ImportHostSegueIdentifier" id="lvz-gb-YiL"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="bGp-H5-24W" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="bGp-H5-24W" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
@ -58,13 +58,17 @@ internal enum L10n {
|
|||||||
internal enum Organizer {
|
internal enum Organizer {
|
||||||
internal enum Cells {
|
internal enum Cells {
|
||||||
internal enum AddHost {
|
internal enum AddHost {
|
||||||
/// Add new host
|
/// Add from Files
|
||||||
internal static let caption = L10n.tr("App", "organizer.cells.add_host.caption")
|
internal static let caption = L10n.tr("App", "organizer.cells.add_host.caption")
|
||||||
}
|
}
|
||||||
internal enum AddProvider {
|
internal enum AddProvider {
|
||||||
/// Add new provider
|
/// Add new provider
|
||||||
internal static let caption = L10n.tr("App", "organizer.cells.add_provider.caption")
|
internal static let caption = L10n.tr("App", "organizer.cells.add_provider.caption")
|
||||||
}
|
}
|
||||||
|
internal enum ImportHost {
|
||||||
|
/// Add from imported
|
||||||
|
internal static let caption = L10n.tr("App", "organizer.cells.import_host.caption")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal enum Provider {
|
internal enum Provider {
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Neuen Anbieter hinzufügen";
|
"organizer.cells.add_provider.caption" = "Neuen Anbieter hinzufügen";
|
||||||
"organizer.cells.add_host.caption" = "Neuen Host hinzufügen";
|
"organisator.cells.add_host.caption" = "Aus Dateien hinzufügen";
|
||||||
|
"organisator.cells.import_host.caption" = "Vom Import hinzufügen";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Titel";
|
"wizards.host.cells.title_input.caption" = "Titel";
|
||||||
"wizards.host.sections.existing.header" = "Bestehende Profile";
|
"wizards.host.sections.existing.header" = "Bestehende Profile";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Προσθήκη νέου παρόχου";
|
"organizer.cells.add_provider.caption" = "Προσθήκη νέου παρόχου";
|
||||||
"organizer.cells.add_host.caption" = "Προσθήκη νέου διακομιστή";
|
"organizer.cells.add_host.caption" = "Προσθήκη από αρχεία";
|
||||||
|
"organizer.cells.import_host.caption" = "Προσθήκη από εισαγωγή";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Τίτλος";
|
"wizards.host.cells.title_input.caption" = "Τίτλος";
|
||||||
"wizards.host.sections.existing.header" = "Υπάρχον Προφίλ";
|
"wizards.host.sections.existing.header" = "Υπάρχον Προφίλ";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Add new provider";
|
"organizer.cells.add_provider.caption" = "Add new provider";
|
||||||
"organizer.cells.add_host.caption" = "Add new host";
|
"organizer.cells.add_host.caption" = "Add from Files";
|
||||||
|
"organizer.cells.import_host.caption" = "Add from imported";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Title";
|
"wizards.host.cells.title_input.caption" = "Title";
|
||||||
"wizards.host.sections.existing.header" = "Existing profiles";
|
"wizards.host.sections.existing.header" = "Existing profiles";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Añadir proveedor";
|
"organizer.cells.add_provider.caption" = "Añadir proveedor";
|
||||||
"organizer.cells.add_host.caption" = "Añadir host";
|
"organizer.cells.add_host.caption" = "Añadir desde Ficheros";
|
||||||
|
"organizer.cells.import_host.caption" = "Añadir desde importados";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Título";
|
"wizards.host.cells.title_input.caption" = "Título";
|
||||||
"wizards.host.sections.existing.header" = "Perfiles existentes";
|
"wizards.host.sections.existing.header" = "Perfiles existentes";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Ajouter un nouveau fournisseur";
|
"organizer.cells.add_provider.caption" = "Ajouter un nouveau fournisseur";
|
||||||
"organizer.cells.add_host.caption" = "Ajouter un nouvel hôte";
|
"organizer.cells.add_host.caption" = "Ajouter de Fichiers";
|
||||||
|
"organizer.cells.import_host.caption" = "Ajouter depuis importé";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Titre";
|
"wizards.host.cells.title_input.caption" = "Titre";
|
||||||
"wizards.host.sections.existing.header" = "Profiles existants";
|
"wizards.host.sections.existing.header" = "Profiles existants";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Aggiungi provider";
|
"organizer.cells.add_provider.caption" = "Aggiungi provider";
|
||||||
"organizer.cells.add_host.caption" = "Aggiungi host";
|
"organizer.cells.add_host.caption" = "Aggiungi da Files";
|
||||||
|
"organizer.cells.import_host.caption" = "Aggiungi da importati";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Titolo";
|
"wizards.host.cells.title_input.caption" = "Titolo";
|
||||||
"wizards.host.sections.existing.header" = "Profili esistenti";
|
"wizards.host.sections.existing.header" = "Profili esistenti";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Voeg nieuwe aanbieder toe";
|
"organizer.cells.add_provider.caption" = "Voeg nieuwe aanbieder toe";
|
||||||
"organizer.cells.add_host.caption" = "Voeg nieuwe host toe";
|
"organizer.cells.add_host.caption" = "Toevoegen vanuit Bestanden";
|
||||||
|
"organizer.cells.import_host.caption" = "Toevoegen vanuit geïmporteerd";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Titel";
|
"wizards.host.cells.title_input.caption" = "Titel";
|
||||||
"wizards.host.sections.existing.header" = "Bestaande profielen";
|
"wizards.host.sections.existing.header" = "Bestaande profielen";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Dodaj nowego usługodawcę";
|
"organizer.cells.add_provider.caption" = "Dodaj nowego usługodawcę";
|
||||||
"organizer.cells.add_host.caption" = "Dodaj nowy host";
|
"organizer.cells.add_host.caption" = "Dodaj z Plików";
|
||||||
|
"organizer.cells.import_host.caption" = "Dodaj z zaimportowanych";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Tytuł";
|
"wizards.host.cells.title_input.caption" = "Tytuł";
|
||||||
"wizards.host.sections.existing.header" = "Istniejące profile";
|
"wizards.host.sections.existing.header" = "Istniejące profile";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Adicionar novo perfil";
|
"organizer.cells.add_provider.caption" = "Adicionar novo perfil";
|
||||||
"organizer.cells.add_host.caption" = "Adicionar novo host";
|
"organizer.cells.add_host.caption" = "Adicionar dos Arquivos";
|
||||||
|
"organizer.cells.import_host.caption" = "Adicionar dos importados";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Título";
|
"wizards.host.cells.title_input.caption" = "Título";
|
||||||
"wizards.host.sections.existing.header" = "Perfis existentes";
|
"wizards.host.sections.existing.header" = "Perfis existentes";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Добавить нового провайдера";
|
"organizer.cells.add_provider.caption" = "Добавить нового провайдера";
|
||||||
"organizer.cells.add_host.caption" = "Добавить новый хост";
|
"organizer.cells.add_host.caption" = "Добавить из файлов";
|
||||||
|
"organizer.cells.import_host.caption" = "Добавить из импортированных";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Название";
|
"wizards.host.cells.title_input.caption" = "Название";
|
||||||
"wizards.host.sections.existing.header" = "Существующие профили";
|
"wizards.host.sections.existing.header" = "Существующие профили";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "Lägg till ny leverantör";
|
"organizer.cells.add_provider.caption" = "Lägg till ny leverantör";
|
||||||
"organizer.cells.add_host.caption" = "Lägg till ny värd";
|
"organizer.cells.add_host.caption" = "Lägg till från Filer";
|
||||||
|
"organizer.cells.import_host.caption" = "Lägg till från importerad";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "Namn";
|
"wizards.host.cells.title_input.caption" = "Namn";
|
||||||
"wizards.host.sections.existing.header" = "Befintliga profiler";
|
"wizards.host.sections.existing.header" = "Befintliga profiler";
|
||||||
|
@ -24,7 +24,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
"organizer.cells.add_provider.caption" = "添加新的提供商配置";
|
"organizer.cells.add_provider.caption" = "添加新的提供商配置";
|
||||||
"organizer.cells.add_host.caption" = "添加新的主机配置";
|
"organizer.cells.add_host.caption" = "从文件添加";
|
||||||
|
"organizer.cells.import_host.caption" = "从导入中添加";
|
||||||
|
|
||||||
"wizards.host.cells.title_input.caption" = "名称";
|
"wizards.host.cells.title_input.caption" = "名称";
|
||||||
"wizards.host.sections.existing.header" = "已存在的配置";
|
"wizards.host.sections.existing.header" = "已存在的配置";
|
||||||
|
@ -30,12 +30,14 @@ import PassepartoutCore
|
|||||||
|
|
||||||
private let log = SwiftyBeaver.self
|
private let log = SwiftyBeaver.self
|
||||||
|
|
||||||
|
protocol ImportedHostsViewControllerDelegate: class {
|
||||||
|
func importedHostsController(_: ImportedHostsViewController, didImport url: URL)
|
||||||
|
}
|
||||||
|
|
||||||
class ImportedHostsViewController: UITableViewController {
|
class ImportedHostsViewController: UITableViewController {
|
||||||
private lazy var pendingConfigurationURLs = TransientStore.shared.service.pendingConfigurationURLs().sortedCaseInsensitive()
|
private lazy var pendingConfigurationURLs = TransientStore.shared.service.pendingConfigurationURLs().sortedCaseInsensitive()
|
||||||
|
|
||||||
private var importer: HostImporter?
|
weak var delegate: ImportedHostsViewControllerDelegate?
|
||||||
|
|
||||||
private var parsingResult: OpenVPN.ConfigurationParser.Result?
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@ -43,72 +45,8 @@ class ImportedHostsViewController: UITableViewController {
|
|||||||
title = L10n.App.ImportedHosts.title
|
title = L10n.App.ImportedHosts.title
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
private func selectHost(withUrl url: URL) {
|
||||||
super.viewWillAppear(animated)
|
delegate?.importedHostsController(self, didImport: url)
|
||||||
|
|
||||||
parsingResult = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
|
||||||
super.viewDidAppear(animated)
|
|
||||||
|
|
||||||
// guard !pendingConfigurationURLs.isEmpty else {
|
|
||||||
// let alert = UIAlertController.asAlert(
|
|
||||||
// title,
|
|
||||||
// L10n.Core.Organizer.Alerts.AddHost.message
|
|
||||||
// )
|
|
||||||
// alert.addCancelAction(L10n.Core.Global.ok) {
|
|
||||||
// self.close()
|
|
||||||
// }
|
|
||||||
// present(alert, animated: true, completion: nil)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
if let selectedIP = tableView.indexPathForSelectedRow {
|
|
||||||
tableView.deselectRow(at: selectedIP, animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Actions
|
|
||||||
|
|
||||||
@IBAction private func openConfigurationFile() {
|
|
||||||
let picker = UIDocumentPickerViewController(documentTypes: AppConstants.URLs.filetypes, in: .import)
|
|
||||||
picker.allowsMultipleSelection = false
|
|
||||||
picker.delegate = self
|
|
||||||
present(picker, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
|
||||||
|
|
||||||
// segue parses configuration file if not yet
|
|
||||||
if parsingResult == nil {
|
|
||||||
guard let cell = sender as? UITableViewCell, let indexPath = tableView.indexPath(for: cell) else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
let url = pendingConfigurationURLs[indexPath.row]
|
|
||||||
return tryParseURL(url, cell: cell)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private func tryParseURL(_ url: URL, cell: UITableViewCell?) -> Bool {
|
|
||||||
deselectSelectedRow()
|
|
||||||
|
|
||||||
importer = HostImporter(withConfigurationURL: url, parentViewController: self)
|
|
||||||
importer?.importHost(withPassphrase: nil, removeOnError: false, removeOnCancel: false) {
|
|
||||||
self.parsingResult = $0
|
|
||||||
self.perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
|
||||||
guard let wizard = segue.destination as? WizardHostViewController else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wizard.parsingResult = parsingResult
|
|
||||||
|
|
||||||
// retain back button
|
|
||||||
wizard.navigationItem.leftBarButtonItem = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction private func close() {
|
@IBAction private func close() {
|
||||||
@ -133,6 +71,11 @@ extension ImportedHostsViewController {
|
|||||||
cell.leftText = url.normalizedFilename
|
cell.leftText = url.normalizedFilename
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
let url = pendingConfigurationURLs[indexPath.row]
|
||||||
|
selectHost(withUrl: url)
|
||||||
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||||
return true
|
return true
|
||||||
@ -145,15 +88,3 @@ extension ImportedHostsViewController {
|
|||||||
tableView.deleteRows(at: [indexPath], with: .top)
|
tableView.deleteRows(at: [indexPath], with: .top)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ImportedHostsViewController: UIDocumentPickerDelegate {
|
|
||||||
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
|
||||||
guard let url = urls.first else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_ = tryParseURL(url, cell: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -41,6 +41,10 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
|
|||||||
private var hosts: [String] = []
|
private var hosts: [String] = []
|
||||||
|
|
||||||
private var didShowSubreddit = false
|
private var didShowSubreddit = false
|
||||||
|
|
||||||
|
private var importer: HostImporter?
|
||||||
|
|
||||||
|
private var hostParsingResult: OpenVPN.ConfigurationParser.Result?
|
||||||
|
|
||||||
// MARK: StrongTableHost
|
// MARK: StrongTableHost
|
||||||
|
|
||||||
@ -93,6 +97,7 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
|
|||||||
var hostRows = [RowType](repeating: .profile, count: hosts.count)
|
var hostRows = [RowType](repeating: .profile, count: hosts.count)
|
||||||
providerRows.append(.addProvider)
|
providerRows.append(.addProvider)
|
||||||
hostRows.append(.addHost)
|
hostRows.append(.addHost)
|
||||||
|
hostRows.append(.importHost)
|
||||||
|
|
||||||
model.set(providerRows, forSection: .providers)
|
model.set(providerRows, forSection: .providers)
|
||||||
model.set(hostRows, forSection: .hosts)
|
model.set(hostRows, forSection: .hosts)
|
||||||
@ -170,6 +175,10 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vc.setProfile(selectedProfile)
|
vc.setProfile(selectedProfile)
|
||||||
|
} else if let vc = destination as? ImportedHostsViewController {
|
||||||
|
vc.delegate = self
|
||||||
|
} else if let vc = destination as? WizardHostViewController {
|
||||||
|
vc.parsingResult = hostParsingResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +209,27 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func addNewHost() {
|
private func addNewHost() {
|
||||||
|
if TransientStore.shared.service.hasReachedMaximumNumberOfHosts {
|
||||||
|
guard ProductManager.shared.isEligible(forFeature: .unlimitedHosts) else {
|
||||||
|
presentPurchaseScreen(forProduct: .unlimitedHosts)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let picker = UIDocumentPickerViewController(documentTypes: AppConstants.URLs.filetypes, in: .import)
|
||||||
|
picker.allowsMultipleSelection = false
|
||||||
|
picker.delegate = self
|
||||||
|
present(picker, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func tryParseHostURL(_ url: URL) {
|
||||||
|
importer = HostImporter(withConfigurationURL: url, parentViewController: self)
|
||||||
|
importer?.importHost(withPassphrase: nil, removeOnError: false, removeOnCancel: false) {
|
||||||
|
self.hostParsingResult = $0
|
||||||
|
self.perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func importNewHost() {
|
||||||
if TransientStore.shared.service.hasReachedMaximumNumberOfHosts {
|
if TransientStore.shared.service.hasReachedMaximumNumberOfHosts {
|
||||||
guard ProductManager.shared.isEligible(forFeature: .unlimitedHosts) else {
|
guard ProductManager.shared.isEligible(forFeature: .unlimitedHosts) else {
|
||||||
presentPurchaseScreen(forProduct: .unlimitedHosts)
|
presentPurchaseScreen(forProduct: .unlimitedHosts)
|
||||||
@ -419,6 +449,8 @@ extension OrganizerViewController {
|
|||||||
|
|
||||||
case addHost
|
case addHost
|
||||||
|
|
||||||
|
case importHost
|
||||||
|
|
||||||
case siriShortcuts
|
case siriShortcuts
|
||||||
|
|
||||||
case donate
|
case donate
|
||||||
@ -499,6 +531,12 @@ extension OrganizerViewController {
|
|||||||
cell.leftText = L10n.App.Organizer.Cells.AddHost.caption
|
cell.leftText = L10n.App.Organizer.Cells.AddHost.caption
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
|
case .importHost:
|
||||||
|
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
||||||
|
cell.applyAction(.current)
|
||||||
|
cell.leftText = L10n.App.Organizer.Cells.ImportHost.caption
|
||||||
|
return cell
|
||||||
|
|
||||||
case .siriShortcuts:
|
case .siriShortcuts:
|
||||||
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
||||||
cell.applyAction(.current)
|
cell.applyAction(.current)
|
||||||
@ -572,6 +610,9 @@ extension OrganizerViewController {
|
|||||||
case .addHost:
|
case .addHost:
|
||||||
addNewHost()
|
addNewHost()
|
||||||
|
|
||||||
|
case .importHost:
|
||||||
|
importNewHost()
|
||||||
|
|
||||||
case .siriShortcuts:
|
case .siriShortcuts:
|
||||||
addShortcuts()
|
addShortcuts()
|
||||||
|
|
||||||
@ -737,6 +778,26 @@ extension OrganizerViewController: ConnectionServiceDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension OrganizerViewController: UIDocumentPickerDelegate {
|
||||||
|
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||||
|
guard let url = urls.first else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tryParseHostURL(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension OrganizerViewController: ImportedHostsViewControllerDelegate {
|
||||||
|
func importedHostsController(_: ImportedHostsViewController, didImport url: URL) {
|
||||||
|
dismiss(animated: true) {
|
||||||
|
self.tryParseHostURL(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension OrganizerViewController: MFMailComposeViewControllerDelegate {
|
extension OrganizerViewController: MFMailComposeViewControllerDelegate {
|
||||||
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||||
dismiss(animated: true, completion: nil)
|
dismiss(animated: true, completion: nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user