List imported .ovpn if any, fall back to alert
Use .formSheet presentation (iPad).
This commit is contained in:
parent
25523b5f61
commit
0e7c0b6388
|
@ -22,18 +22,75 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import TunnelKit
|
||||||
|
import SwiftyBeaver
|
||||||
|
|
||||||
|
private let log = SwiftyBeaver.self
|
||||||
|
|
||||||
class ImportedHostsViewController: UITableViewController {
|
class ImportedHostsViewController: UITableViewController {
|
||||||
|
private lazy var pendingConfigurationURLs = TransientStore.shared.service.pendingConfigurationURLs()
|
||||||
|
|
||||||
|
private var parsedFile: ParsedFile?
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
title = L10n.ImportedHosts.title
|
title = L10n.ImportedHosts.title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
guard !pendingConfigurationURLs.isEmpty else {
|
||||||
|
let alert = Macros.alert(
|
||||||
|
L10n.ImportedHosts.title,
|
||||||
|
L10n.Organizer.Alerts.AddHost.message
|
||||||
|
)
|
||||||
|
alert.addCancelAction(L10n.Global.ok) {
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
present(alert, animated: true, completion: nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Actions
|
// MARK: Actions
|
||||||
|
|
||||||
|
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||||
|
guard let cell = sender as? UITableViewCell, let indexPath = tableView.indexPath(for: cell) else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let url = pendingConfigurationURLs[indexPath.row]
|
||||||
|
guard let parsedFile = ParsedFile.from(url, withErrorAlertIn: self) else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
self.parsedFile = parsedFile
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||||
|
guard let wizard = segue.destination as? WizardHostViewController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wizard.parsedFile = parsedFile
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction private func close() {
|
@IBAction private func close() {
|
||||||
dismiss(animated: true, completion: nil)
|
dismiss(animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ImportedHostsViewController {
|
||||||
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return pendingConfigurationURLs.count
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let url = pendingConfigurationURLs[indexPath.row]
|
||||||
|
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
|
||||||
|
cell.leftText = url.normalizedFilename
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -174,12 +174,7 @@ class OrganizerViewController: UITableViewController, TableModelHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addNewHost() {
|
private func addNewHost() {
|
||||||
let alert = Macros.alert(
|
perform(segue: StoryboardSegue.Organizer.importHostSegueIdentifier)
|
||||||
L10n.Organizer.Sections.Hosts.header,
|
|
||||||
L10n.Organizer.Alerts.AddHost.message
|
|
||||||
)
|
|
||||||
alert.addCancelAction(L10n.Global.ok)
|
|
||||||
present(alert, animated: true, completion: nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func removeProfile(at indexPath: IndexPath) {
|
private func removeProfile(at indexPath: IndexPath) {
|
||||||
|
|
|
@ -293,7 +293,7 @@
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="NVA-bQ-iIE" kind="presentation" identifier="AddProviderSegueIdentifier" modalPresentationStyle="formSheet" id="Win-5U-mIc"/>
|
<segue destination="NVA-bQ-iIE" kind="presentation" identifier="AddProviderSegueIdentifier" modalPresentationStyle="formSheet" id="Win-5U-mIc"/>
|
||||||
<segue destination="a3d-vD-Pr7" kind="presentation" identifier="AboutSegueIdentifier" id="fd4-we-46n"/>
|
<segue destination="a3d-vD-Pr7" kind="presentation" identifier="AboutSegueIdentifier" id="fd4-we-46n"/>
|
||||||
<segue destination="z6E-m6-Op0" kind="presentation" identifier="ImportHostSegueIdentifier" id="TZv-OK-8vU"/>
|
<segue destination="z6E-m6-Op0" kind="presentation" identifier="ImportHostSegueIdentifier" modalPresentationStyle="formSheet" id="TZv-OK-8vU"/>
|
||||||
</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"/>
|
||||||
|
@ -567,6 +567,6 @@
|
||||||
</resources>
|
</resources>
|
||||||
<inferredMetricsTieBreakers>
|
<inferredMetricsTieBreakers>
|
||||||
<segue reference="HW6-RJ-VFY"/>
|
<segue reference="HW6-RJ-VFY"/>
|
||||||
<segue reference="kwN-PZ-Zg5"/>
|
<segue reference="qQl-B5-moM"/>
|
||||||
</inferredMetricsTieBreakers>
|
</inferredMetricsTieBreakers>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
"organizer.cells.about.caption" = "About %@";
|
"organizer.cells.about.caption" = "About %@";
|
||||||
"organizer.cells.uninstall.caption" = "Delete VPN profile";
|
"organizer.cells.uninstall.caption" = "Delete VPN profile";
|
||||||
"organizer.alerts.exhausted_providers.message" = "You have created profiles for any available network.";
|
"organizer.alerts.exhausted_providers.message" = "You have created profiles for any available network.";
|
||||||
"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.";
|
"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.delete_vpn_profile.message" = "Do you really want to delete the VPN profile from the device?";
|
"organizer.alerts.delete_vpn_profile.message" = "Do you really want to delete the VPN profile from the device?";
|
||||||
|
|
||||||
"account.suggestion_footer.infrastructure.pia" = "Use your website credentials. Your username is usually numeric with a \"p\" prefix.";
|
"account.suggestion_footer.infrastructure.pia" = "Use your website credentials. Your username is usually numeric with a \"p\" prefix.";
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import SwiftyBeaver
|
||||||
|
|
||||||
|
private let log = SwiftyBeaver.self
|
||||||
|
|
||||||
extension ConnectionService {
|
extension ConnectionService {
|
||||||
func save(configurationURL: URL, for profile: ConnectionProfile) throws -> URL {
|
func save(configurationURL: URL, for profile: ConnectionProfile) throws -> URL {
|
||||||
|
@ -46,4 +49,14 @@ extension ConnectionService {
|
||||||
let contextURL = ConnectionService.ProfileKey(profile).contextURL(in: self)
|
let contextURL = ConnectionService.ProfileKey(profile).contextURL(in: self)
|
||||||
return contextURL.appendingPathComponent(profile.id).appendingPathExtension("ovpn")
|
return contextURL.appendingPathComponent(profile.id).appendingPathExtension("ovpn")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pendingConfigurationURLs() -> [URL] {
|
||||||
|
do {
|
||||||
|
let list = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil, options: [])
|
||||||
|
return list.filter { $0.pathExtension == "ovpn" }
|
||||||
|
} catch let e {
|
||||||
|
log.error("Could not list imported configurations: \(e)")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,7 +343,7 @@ internal enum L10n {
|
||||||
internal enum Alerts {
|
internal enum Alerts {
|
||||||
|
|
||||||
internal enum AddHost {
|
internal enum AddHost {
|
||||||
/// Open an URL to an .ovpn configuration file from Safari, Mail or another app to set up a host profile.
|
/// 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("Localizable", "organizer.alerts.add_host.message")
|
internal static let message = L10n.tr("Localizable", "organizer.alerts.add_host.message")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue