on-demand: iOS: Support for SSIDs
This commit is contained in:
parent
008975de06
commit
8ef69cd82d
|
@ -48,6 +48,8 @@
|
||||||
6BD5C97C220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
6BD5C97C220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
||||||
6BD5C97D220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
6BD5C97D220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
||||||
6BD5C97E220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
6BD5C97E220D1AE200784E08 /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 6BD5C979220D1AE100784E08 /* key.c */; };
|
||||||
|
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44C8222D55BB00B0FF04 /* TextCell.swift */; };
|
||||||
|
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
|
||||||
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
|
||||||
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
|
||||||
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
|
||||||
|
@ -79,6 +81,8 @@
|
||||||
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */; };
|
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */; };
|
||||||
6F8F0D7122258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; };
|
6F8F0D7122258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; };
|
||||||
6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; };
|
6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; };
|
||||||
|
6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7322267AD2000E8335 /* ChevronCell.swift */; };
|
||||||
|
6F8F0D7722267C57000E8335 /* SSIDOptionEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */; };
|
||||||
6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */; };
|
6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */; };
|
||||||
6F919ED9218C65C50023B400 /* wireguard_doc_logo_22x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */; };
|
6F919ED9218C65C50023B400 /* wireguard_doc_logo_22x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */; };
|
||||||
6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; };
|
6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; };
|
||||||
|
@ -262,6 +266,8 @@
|
||||||
6BAC16E42216324B00A5FB78 /* AppStorePrivacyNotice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStorePrivacyNotice.swift; sourceTree = "<group>"; };
|
6BAC16E42216324B00A5FB78 /* AppStorePrivacyNotice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStorePrivacyNotice.swift; sourceTree = "<group>"; };
|
||||||
6BD5C979220D1AE100784E08 /* key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key.c; sourceTree = "<group>"; };
|
6BD5C979220D1AE100784E08 /* key.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = key.c; sourceTree = "<group>"; };
|
||||||
6BD5C97A220D1AE200784E08 /* key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; };
|
6BD5C97A220D1AE200784E08 /* key.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = "<group>"; };
|
||||||
|
6F0F44C8222D55BB00B0FF04 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; };
|
||||||
|
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
|
||||||
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
|
||||||
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
|
||||||
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -297,6 +303,8 @@
|
||||||
6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusItemController.swift; sourceTree = "<group>"; };
|
6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusItemController.swift; sourceTree = "<group>"; };
|
||||||
6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsTracker.swift; sourceTree = "<group>"; };
|
6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsTracker.swift; sourceTree = "<group>"; };
|
||||||
6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandViewModel.swift; sourceTree = "<group>"; };
|
6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
6F8F0D7322267AD2000E8335 /* ChevronCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChevronCell.swift; sourceTree = "<group>"; };
|
||||||
|
6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSIDOptionEditTableViewController.swift; sourceTree = "<group>"; };
|
||||||
6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = "<group>"; };
|
6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = "<group>"; };
|
||||||
6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = "<group>"; };
|
6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = "<group>"; };
|
||||||
6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = "<group>"; };
|
6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = "<group>"; };
|
||||||
|
@ -402,6 +410,9 @@
|
||||||
5F4541A521C4449E00994C13 /* ButtonCell.swift */,
|
5F4541A521C4449E00994C13 /* ButtonCell.swift */,
|
||||||
5F45419121C2D55800994C13 /* CheckmarkCell.swift */,
|
5F45419121C2D55800994C13 /* CheckmarkCell.swift */,
|
||||||
5F4541A121C2D6DF00994C13 /* BorderedTextButton.swift */,
|
5F4541A121C2D6DF00994C13 /* BorderedTextButton.swift */,
|
||||||
|
6F8F0D7322267AD2000E8335 /* ChevronCell.swift */,
|
||||||
|
6F0F44C8222D55BB00B0FF04 /* TextCell.swift */,
|
||||||
|
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */,
|
||||||
);
|
);
|
||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -415,6 +426,7 @@
|
||||||
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */,
|
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */,
|
||||||
6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */,
|
6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */,
|
||||||
6F7774DF217181B1006A79B3 /* MainViewController.swift */,
|
6F7774DF217181B1006A79B3 /* MainViewController.swift */,
|
||||||
|
6F8F0D7622267C57000E8335 /* SSIDOptionEditTableViewController.swift */,
|
||||||
);
|
);
|
||||||
path = ViewController;
|
path = ViewController;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1231,6 +1243,7 @@
|
||||||
files = (
|
files = (
|
||||||
6FE1765A21C90E87002690EA /* LocalizationHelper.swift in Sources */,
|
6FE1765A21C90E87002690EA /* LocalizationHelper.swift in Sources */,
|
||||||
6FF3527221C2616C0008484E /* ringlogger.c in Sources */,
|
6FF3527221C2616C0008484E /* ringlogger.c in Sources */,
|
||||||
|
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */,
|
||||||
6FF3527321C2616C0008484E /* Logger.swift in Sources */,
|
6FF3527321C2616C0008484E /* Logger.swift in Sources */,
|
||||||
6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */,
|
6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */,
|
||||||
6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */,
|
6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */,
|
||||||
|
@ -1238,12 +1251,14 @@
|
||||||
5F45419221C2D55800994C13 /* CheckmarkCell.swift in Sources */,
|
5F45419221C2D55800994C13 /* CheckmarkCell.swift in Sources */,
|
||||||
6FE254FF219C60290028284D /* ZipExporter.swift in Sources */,
|
6FE254FF219C60290028284D /* ZipExporter.swift in Sources */,
|
||||||
6F8F0D7122258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */,
|
6F8F0D7122258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */,
|
||||||
|
6F8F0D7722267C57000E8335 /* SSIDOptionEditTableViewController.swift in Sources */,
|
||||||
6B586C53220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */,
|
6B586C53220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */,
|
||||||
6F693A562179E556008551C1 /* Endpoint.swift in Sources */,
|
6F693A562179E556008551C1 /* Endpoint.swift in Sources */,
|
||||||
6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */,
|
6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */,
|
||||||
6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */,
|
6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */,
|
||||||
5FF7B96221CC95DE00A7DD74 /* InterfaceConfiguration.swift in Sources */,
|
5FF7B96221CC95DE00A7DD74 /* InterfaceConfiguration.swift in Sources */,
|
||||||
5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */,
|
5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */,
|
||||||
|
6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */,
|
||||||
6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */,
|
6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */,
|
||||||
6F6899A62180447E0012E523 /* x25519.c in Sources */,
|
6F6899A62180447E0012E523 /* x25519.c in Sources */,
|
||||||
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
|
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
|
||||||
|
@ -1265,6 +1280,7 @@
|
||||||
6F7774E82172020C006A79B3 /* TunnelConfiguration.swift in Sources */,
|
6F7774E82172020C006A79B3 /* TunnelConfiguration.swift in Sources */,
|
||||||
6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */,
|
6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */,
|
||||||
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */,
|
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */,
|
||||||
|
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */,
|
||||||
5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */,
|
5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */,
|
||||||
5F9696B021CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
|
5F9696B021CD7128008063FE /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
|
||||||
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */,
|
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */,
|
||||||
|
|
|
@ -92,6 +92,11 @@
|
||||||
"tunnelOnDemandOnlySelectedSSIDs" = "Only selected SSIDs";
|
"tunnelOnDemandOnlySelectedSSIDs" = "Only selected SSIDs";
|
||||||
"tunnelOnDemandExceptSelectedSSIDs" = "Except selected SSIDs";
|
"tunnelOnDemandExceptSelectedSSIDs" = "Except selected SSIDs";
|
||||||
|
|
||||||
|
"tunnelOnDemandSelectionViewTitle" = "Select SSIDs";
|
||||||
|
"tunnelOnDemandSectionTitleSelectedSSIDs" = "Selected SSIDs";
|
||||||
|
"tunnelOnDemandSectionTitleAddSSIDs" = "Add SSIDs";
|
||||||
|
"tunnelOnDemandAddMessageAddNew" = "Add manually";
|
||||||
|
|
||||||
"tunnelOnDemandKey" = "Activate on demand";
|
"tunnelOnDemandKey" = "Activate on demand";
|
||||||
"tunnelOnDemandOptionOff" = "Off";
|
"tunnelOnDemandOptionOff" = "Off";
|
||||||
"tunnelOnDemandOptionWiFiOnly" = "Wi-Fi only";
|
"tunnelOnDemandOptionWiFiOnly" = "Wi-Fi only";
|
||||||
|
|
|
@ -132,3 +132,13 @@ private func ssidOnDemandRules(option: ActivateOnDemandSSIDOption) -> [NEOnDeman
|
||||||
NEOnDemandRuleConnect(interfaceType: .wiFi)]
|
NEOnDemandRuleConnect(interfaceType: .wiFi)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ActivateOnDemandSetting {
|
||||||
|
init(with option: ActivateOnDemandOption) {
|
||||||
|
if option == .none {
|
||||||
|
self = ActivateOnDemandSetting(isActivateOnDemandEnabled: false, activateOnDemandOption: option)
|
||||||
|
} else {
|
||||||
|
self = ActivateOnDemandSetting(isActivateOnDemandEnabled: true, activateOnDemandOption: option)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class ChevronCell: UITableViewCell {
|
||||||
|
var message: String {
|
||||||
|
get { return textLabel?.text ?? "" }
|
||||||
|
set(value) { textLabel?.text = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: .default, reuseIdentifier: reuseIdentifier)
|
||||||
|
accessoryType = .disclosureIndicator
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
message = ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class EditableTextCell: UITableViewCell {
|
||||||
|
var message: String {
|
||||||
|
get { return valueTextField.text ?? "" }
|
||||||
|
set(value) { valueTextField.text = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
let valueTextField: UITextField = {
|
||||||
|
let valueTextField = UITextField()
|
||||||
|
valueTextField.textAlignment = .left
|
||||||
|
valueTextField.isEnabled = true
|
||||||
|
valueTextField.font = UIFont.preferredFont(forTextStyle: .body)
|
||||||
|
valueTextField.adjustsFontForContentSizeCategory = true
|
||||||
|
valueTextField.autocapitalizationType = .none
|
||||||
|
valueTextField.autocorrectionType = .no
|
||||||
|
valueTextField.spellCheckingType = .no
|
||||||
|
return valueTextField
|
||||||
|
}()
|
||||||
|
|
||||||
|
var onValueBeingEdited: ((String) -> Void)?
|
||||||
|
|
||||||
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
|
||||||
|
valueTextField.delegate = self
|
||||||
|
contentView.addSubview(valueTextField)
|
||||||
|
valueTextField.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
let bottomAnchorConstraint = contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: valueTextField.bottomAnchor, multiplier: 1)
|
||||||
|
bottomAnchorConstraint.priority = .defaultLow
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
valueTextField.leadingAnchor.constraint(equalToSystemSpacingAfter: contentView.layoutMarginsGuide.leadingAnchor, multiplier: 1),
|
||||||
|
contentView.layoutMarginsGuide.trailingAnchor.constraint(equalToSystemSpacingAfter: valueTextField.trailingAnchor, multiplier: 1),
|
||||||
|
valueTextField.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 1),
|
||||||
|
bottomAnchorConstraint
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func beginEditing() {
|
||||||
|
valueTextField.becomeFirstResponder()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
message = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension EditableTextCell: UITextFieldDelegate {
|
||||||
|
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
if let onValueBeingEdited = onValueBeingEdited {
|
||||||
|
let modifiedText = ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string)
|
||||||
|
onValueBeingEdited(modifiedText)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class TextCell: UITableViewCell {
|
||||||
|
var message: String {
|
||||||
|
get { return textLabel?.text ?? "" }
|
||||||
|
set(value) { textLabel!.text = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: .default, reuseIdentifier: reuseIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
message = ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
protocol SSIDOptionEditTableViewControllerDelegate: class {
|
||||||
|
func ssidOptionSaved(option: ActivateOnDemandViewModel.OnDemandSSIDOption, ssids: [String])
|
||||||
|
}
|
||||||
|
|
||||||
|
class SSIDOptionEditTableViewController: UITableViewController {
|
||||||
|
private enum Section {
|
||||||
|
case ssidOption
|
||||||
|
case selectedSSIDs
|
||||||
|
case addSSIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
weak var delegate: SSIDOptionEditTableViewControllerDelegate?
|
||||||
|
|
||||||
|
private var sections = [Section]()
|
||||||
|
|
||||||
|
let ssidOptionFields: [ActivateOnDemandViewModel.OnDemandSSIDOption] = [
|
||||||
|
.anySSID,
|
||||||
|
.onlySpecificSSIDs,
|
||||||
|
.exceptSpecificSSIDs
|
||||||
|
]
|
||||||
|
|
||||||
|
var selectedOption: ActivateOnDemandViewModel.OnDemandSSIDOption
|
||||||
|
var selectedSSIDs: [String]
|
||||||
|
|
||||||
|
init(option: ActivateOnDemandViewModel.OnDemandSSIDOption, ssids: [String]) {
|
||||||
|
selectedOption = option
|
||||||
|
selectedSSIDs = ssids
|
||||||
|
super.init(style: .grouped)
|
||||||
|
loadSections()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
title = tr("tunnelOnDemandSelectionViewTitle")
|
||||||
|
|
||||||
|
tableView.estimatedRowHeight = 44
|
||||||
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
|
|
||||||
|
tableView.register(CheckmarkCell.self)
|
||||||
|
tableView.register(EditableTextCell.self)
|
||||||
|
tableView.register(TextCell.self)
|
||||||
|
tableView.isEditing = true
|
||||||
|
tableView.allowsSelectionDuringEditing = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSections() {
|
||||||
|
sections.removeAll()
|
||||||
|
sections.append(.ssidOption)
|
||||||
|
if selectedOption != .anySSID {
|
||||||
|
if !selectedSSIDs.isEmpty {
|
||||||
|
sections.append(.selectedSSIDs)
|
||||||
|
}
|
||||||
|
sections.append(.addSSIDs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
delegate?.ssidOptionSaved(option: selectedOption, ssids: selectedSSIDs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SSIDOptionEditTableViewController {
|
||||||
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
return sections.count
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
switch sections[section] {
|
||||||
|
case .ssidOption:
|
||||||
|
return ssidOptionFields.count
|
||||||
|
case .selectedSSIDs:
|
||||||
|
return selectedSSIDs.count
|
||||||
|
case .addSSIDs:
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
switch sections[indexPath.section] {
|
||||||
|
case .ssidOption:
|
||||||
|
return ssidOptionCell(for: tableView, at: indexPath)
|
||||||
|
case .selectedSSIDs:
|
||||||
|
return selectedSSIDCell(for: tableView, at: indexPath)
|
||||||
|
case .addSSIDs:
|
||||||
|
return addSSIDCell(for: tableView, at: indexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||||
|
switch sections[indexPath.section] {
|
||||||
|
case .ssidOption:
|
||||||
|
return false
|
||||||
|
case .selectedSSIDs, .addSSIDs:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
|
||||||
|
switch sections[indexPath.section] {
|
||||||
|
case .ssidOption:
|
||||||
|
return .none
|
||||||
|
case .selectedSSIDs:
|
||||||
|
return .delete
|
||||||
|
case .addSSIDs:
|
||||||
|
return .insert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||||
|
switch sections[section] {
|
||||||
|
case .ssidOption:
|
||||||
|
return nil
|
||||||
|
case .selectedSSIDs:
|
||||||
|
return tr("tunnelOnDemandSectionTitleSelectedSSIDs")
|
||||||
|
case .addSSIDs:
|
||||||
|
return tr("tunnelOnDemandSectionTitleAddSSIDs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func ssidOptionCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let field = ssidOptionFields[indexPath.row]
|
||||||
|
let cell: CheckmarkCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
|
cell.message = field.localizedUIString
|
||||||
|
cell.isChecked = selectedOption == field
|
||||||
|
cell.isEditing = false
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
private func selectedSSIDCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let cell: EditableTextCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
|
cell.message = selectedSSIDs[indexPath.row]
|
||||||
|
cell.isEditing = true
|
||||||
|
cell.onValueBeingEdited = { [weak self, weak cell] text in
|
||||||
|
guard let self = self, let cell = cell else { return }
|
||||||
|
if let row = self.tableView.indexPath(for: cell)?.row {
|
||||||
|
self.selectedSSIDs[row] = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
private func addSSIDCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let cell: TextCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
|
cell.message = tr("tunnelOnDemandAddMessageAddNew")
|
||||||
|
cell.isEditing = true
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
|
||||||
|
switch sections[indexPath.section] {
|
||||||
|
case .ssidOption:
|
||||||
|
assertionFailure()
|
||||||
|
case .selectedSSIDs:
|
||||||
|
assert(editingStyle == .delete)
|
||||||
|
selectedSSIDs.remove(at: indexPath.row)
|
||||||
|
loadSections()
|
||||||
|
let hasSelectedSSIDsSection = sections.contains(.selectedSSIDs)
|
||||||
|
if hasSelectedSSIDsSection {
|
||||||
|
tableView.deleteRows(at: [indexPath], with: .automatic)
|
||||||
|
} else {
|
||||||
|
tableView.deleteSections(IndexSet(integer: indexPath.section), with: .automatic)
|
||||||
|
}
|
||||||
|
case .addSSIDs:
|
||||||
|
assert(editingStyle == .insert)
|
||||||
|
let hasSelectedSSIDsSection = sections.contains(.selectedSSIDs)
|
||||||
|
selectedSSIDs.append("")
|
||||||
|
loadSections()
|
||||||
|
let selectedSSIDsSection = sections.firstIndex(of: .selectedSSIDs)!
|
||||||
|
let indexPath = IndexPath(row: selectedSSIDs.count - 1, section: selectedSSIDsSection)
|
||||||
|
if !hasSelectedSSIDsSection {
|
||||||
|
tableView.insertSections(IndexSet(integer: selectedSSIDsSection), with: .automatic)
|
||||||
|
} else {
|
||||||
|
tableView.insertRows(at: [indexPath], with: .automatic)
|
||||||
|
}
|
||||||
|
if let selectedSSIDCell = tableView.cellForRow(at: indexPath) as? EditableTextCell {
|
||||||
|
selectedSSIDCell.beginEditing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func lastSelectedSSIDItemIndexPath() -> IndexPath? {
|
||||||
|
guard !selectedSSIDs.isEmpty else { return nil }
|
||||||
|
guard let section = sections.firstIndex(of: .selectedSSIDs) else { return nil }
|
||||||
|
return IndexPath(row: selectedSSIDs.count - 1, section: section)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SSIDOptionEditTableViewController {
|
||||||
|
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||||
|
switch sections[indexPath.section] {
|
||||||
|
case .ssidOption:
|
||||||
|
return indexPath
|
||||||
|
case .selectedSSIDs, .addSSIDs:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
switch sections[indexPath.section] {
|
||||||
|
case .ssidOption:
|
||||||
|
let previousOption = selectedOption
|
||||||
|
let previousSectionCount = sections.count
|
||||||
|
selectedOption = ssidOptionFields[indexPath.row]
|
||||||
|
loadSections()
|
||||||
|
if previousOption == .anySSID {
|
||||||
|
let indexSet = selectedSSIDs.isEmpty ? IndexSet(integer: 1) : IndexSet(1 ... 2)
|
||||||
|
tableView.insertSections(indexSet, with: .fade)
|
||||||
|
}
|
||||||
|
if selectedOption == .anySSID {
|
||||||
|
let indexSet = previousSectionCount == 2 ? IndexSet(integer: 1) : IndexSet(1 ... 2)
|
||||||
|
tableView.deleteSections(indexSet, with: .fade)
|
||||||
|
}
|
||||||
|
tableView.reloadSections(IndexSet(integer: indexPath.section), with: .none)
|
||||||
|
case .selectedSSIDs, .addSSIDs:
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,16 +43,16 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
.deletePeer
|
.deletePeer
|
||||||
]
|
]
|
||||||
|
|
||||||
let activateOnDemandOptions: [ActivateOnDemandOption] = [
|
let onDemandFields: [ActivateOnDemandViewModel.OnDemandField] = [
|
||||||
.anyInterface(.anySSID),
|
.nonWiFiInterface,
|
||||||
.wiFiInterfaceOnly(.anySSID),
|
.wiFiInterface,
|
||||||
.nonWiFiInterfaceOnly
|
.ssidEdit
|
||||||
]
|
]
|
||||||
|
|
||||||
let tunnelsManager: TunnelsManager
|
let tunnelsManager: TunnelsManager
|
||||||
let tunnel: TunnelContainer?
|
let tunnel: TunnelContainer?
|
||||||
let tunnelViewModel: TunnelViewModel
|
let tunnelViewModel: TunnelViewModel
|
||||||
var activateOnDemandSetting: ActivateOnDemandSetting
|
var onDemandViewModel: ActivateOnDemandViewModel
|
||||||
private var sections = [Section]()
|
private var sections = [Section]()
|
||||||
|
|
||||||
// Use this initializer to edit an existing tunnel.
|
// Use this initializer to edit an existing tunnel.
|
||||||
|
@ -60,7 +60,8 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
self.tunnelsManager = tunnelsManager
|
self.tunnelsManager = tunnelsManager
|
||||||
self.tunnel = tunnel
|
self.tunnel = tunnel
|
||||||
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration)
|
||||||
activateOnDemandSetting = tunnel.activateOnDemandSetting
|
let onDemandOption = tunnel.activateOnDemandSetting.isActivateOnDemandEnabled ? tunnel.activateOnDemandSetting.activateOnDemandOption : .none
|
||||||
|
onDemandViewModel = ActivateOnDemandViewModel(from: onDemandOption)
|
||||||
super.init(style: .grouped)
|
super.init(style: .grouped)
|
||||||
loadSections()
|
loadSections()
|
||||||
}
|
}
|
||||||
|
@ -70,7 +71,7 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
self.tunnelsManager = tunnelsManager
|
self.tunnelsManager = tunnelsManager
|
||||||
tunnel = nil
|
tunnel = nil
|
||||||
tunnelViewModel = TunnelViewModel(tunnelConfiguration: nil)
|
tunnelViewModel = TunnelViewModel(tunnelConfiguration: nil)
|
||||||
activateOnDemandSetting = ActivateOnDemandSetting.defaultSetting
|
onDemandViewModel = ActivateOnDemandViewModel()
|
||||||
super.init(style: .grouped)
|
super.init(style: .grouped)
|
||||||
loadSections()
|
loadSections()
|
||||||
}
|
}
|
||||||
|
@ -92,7 +93,7 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
tableView.register(TunnelEditEditableKeyValueCell.self)
|
tableView.register(TunnelEditEditableKeyValueCell.self)
|
||||||
tableView.register(ButtonCell.self)
|
tableView.register(ButtonCell.self)
|
||||||
tableView.register(SwitchCell.self)
|
tableView.register(SwitchCell.self)
|
||||||
tableView.register(CheckmarkCell.self)
|
tableView.register(ChevronCell.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func loadSections() {
|
private func loadSections() {
|
||||||
|
@ -113,6 +114,7 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
ErrorPresenter.showErrorAlert(title: alertTitle, message: errorMessage, from: self)
|
ErrorPresenter.showErrorAlert(title: alertTitle, message: errorMessage, from: self)
|
||||||
tableView.reloadData() // Highlight erroring fields
|
tableView.reloadData() // Highlight erroring fields
|
||||||
case .saved(let tunnelConfiguration):
|
case .saved(let tunnelConfiguration):
|
||||||
|
let activateOnDemandSetting = ActivateOnDemandSetting(with: onDemandViewModel.toOnDemandOption())
|
||||||
if let tunnel = tunnel {
|
if let tunnel = tunnel {
|
||||||
// We're modifying an existing tunnel
|
// We're modifying an existing tunnel
|
||||||
tunnelsManager.modify(tunnel: tunnel, tunnelConfiguration: tunnelConfiguration, activateOnDemandSetting: activateOnDemandSetting) { [weak self] error in
|
tunnelsManager.modify(tunnel: tunnel, tunnelConfiguration: tunnelConfiguration, activateOnDemandSetting: activateOnDemandSetting) { [weak self] error in
|
||||||
|
@ -161,10 +163,10 @@ extension TunnelEditTableViewController {
|
||||||
case .addPeer:
|
case .addPeer:
|
||||||
return 1
|
return 1
|
||||||
case .onDemand:
|
case .onDemand:
|
||||||
if activateOnDemandSetting.isActivateOnDemandEnabled {
|
if onDemandViewModel.isWiFiInterfaceEnabled {
|
||||||
return 4
|
return 3
|
||||||
} else {
|
} else {
|
||||||
return 1
|
return 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,36 +421,28 @@ extension TunnelEditTableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell {
|
||||||
if indexPath.row == 0 {
|
let field = onDemandFields[indexPath.row]
|
||||||
|
if indexPath.row < 2 {
|
||||||
let cell: SwitchCell = tableView.dequeueReusableCell(for: indexPath)
|
let cell: SwitchCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
cell.message = tr("tunnelOnDemandKey")
|
cell.message = field.localizedUIString
|
||||||
cell.isOn = activateOnDemandSetting.isActivateOnDemandEnabled
|
cell.isOn = onDemandViewModel.isEnabled(field: field)
|
||||||
cell.onSwitchToggled = { [weak self] isOn in
|
cell.onSwitchToggled = { [weak self] isOn in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
guard isOn != self.activateOnDemandSetting.isActivateOnDemandEnabled else { return }
|
self.onDemandViewModel.setEnabled(field: field, isEnabled: isOn)
|
||||||
|
|
||||||
self.activateOnDemandSetting.isActivateOnDemandEnabled = isOn
|
|
||||||
self.loadSections()
|
|
||||||
|
|
||||||
let section = self.sections.firstIndex { $0 == .onDemand }!
|
let section = self.sections.firstIndex { $0 == .onDemand }!
|
||||||
let indexPaths = (1 ..< 4).map { IndexPath(row: $0, section: section) }
|
let indexPath = IndexPath(row: 2, section: section)
|
||||||
|
if field == .wiFiInterface {
|
||||||
if isOn {
|
if isOn {
|
||||||
if self.activateOnDemandSetting.activateOnDemandOption == .none {
|
tableView.insertRows(at: [indexPath], with: .fade)
|
||||||
self.activateOnDemandSetting.activateOnDemandOption = TunnelViewModel.defaultActivateOnDemandOption()
|
|
||||||
}
|
|
||||||
self.tableView.insertRows(at: indexPaths, with: .fade)
|
|
||||||
} else {
|
} else {
|
||||||
self.tableView.deleteRows(at: indexPaths, with: .fade)
|
tableView.deleteRows(at: [indexPath], with: .fade)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cell
|
return cell
|
||||||
} else {
|
} else {
|
||||||
let cell: CheckmarkCell = tableView.dequeueReusableCell(for: indexPath)
|
let cell: ChevronCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
let rowOption = activateOnDemandOptions[indexPath.row - 1]
|
cell.message = field.localizedUIString
|
||||||
let selectedOption = activateOnDemandSetting.activateOnDemandOption
|
|
||||||
assert(selectedOption != .none)
|
|
||||||
cell.message = TunnelViewModel.activateOnDemandOptionText(for: rowOption)
|
|
||||||
cell.isChecked = selectedOption == rowOption
|
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,7 +478,7 @@ extension TunnelEditTableViewController {
|
||||||
|
|
||||||
extension TunnelEditTableViewController {
|
extension TunnelEditTableViewController {
|
||||||
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||||
if case .onDemand = sections[indexPath.section], indexPath.row > 0 {
|
if case .onDemand = sections[indexPath.section], indexPath.row == 2 {
|
||||||
return indexPath
|
return indexPath
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -494,16 +488,21 @@ extension TunnelEditTableViewController {
|
||||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
switch sections[indexPath.section] {
|
switch sections[indexPath.section] {
|
||||||
case .onDemand:
|
case .onDemand:
|
||||||
let option = activateOnDemandOptions[indexPath.row - 1]
|
assert(indexPath.row == 2)
|
||||||
assert(option != .none)
|
tableView.deselectRow(at: indexPath, animated: true)
|
||||||
activateOnDemandSetting.activateOnDemandOption = option
|
let ssidOptionVC = SSIDOptionEditTableViewController(option: onDemandViewModel.ssidOption, ssids: onDemandViewModel.selectedSSIDs)
|
||||||
|
ssidOptionVC.delegate = self
|
||||||
let indexPaths = (1 ..< 4).map { IndexPath(row: $0, section: indexPath.section) }
|
navigationController?.pushViewController(ssidOptionVC, animated: true)
|
||||||
UIView.performWithoutAnimation {
|
|
||||||
tableView.reloadRows(at: indexPaths, with: .none)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension TunnelEditTableViewController: SSIDOptionEditTableViewControllerDelegate {
|
||||||
|
func ssidOptionSaved(option: ActivateOnDemandViewModel.OnDemandSSIDOption, ssids: [String]) {
|
||||||
|
let validSSIDs = ssids.filter { !$0.isEmpty }
|
||||||
|
onDemandViewModel.selectedSSIDs = validSSIDs
|
||||||
|
onDemandViewModel.ssidOption = validSSIDs.isEmpty ? .anySSID : option
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue