aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WireGuard/WireGuard.xcodeproj/project.pbxproj6
-rw-r--r--WireGuard/WireGuard/Base.lproj/Localizable.strings11
-rw-r--r--WireGuard/WireGuard/UI/ActivateOnDemandViewModel.swift128
3 files changed, 145 insertions, 0 deletions
diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj
index 5a76107d..a499298d 100644
--- a/WireGuard/WireGuard.xcodeproj/project.pbxproj
+++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj
@@ -77,6 +77,8 @@
6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */; };
6F89E17A21EDEB0E00C97BB9 /* StatusItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */; };
6F89E17C21F090CC00C97BB9 /* TunnelsTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */; };
+ 6F8F0D7122258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */; };
+ 6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.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 */; };
6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; };
@@ -294,6 +296,7 @@
6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelErrors.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>"; };
+ 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandViewModel.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>"; };
6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = "<group>"; };
@@ -474,6 +477,7 @@
6FB1BD5E21D2607A00A991BF /* macOS */,
6F7774DE217181B1006A79B3 /* iOS */,
6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */,
+ 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */,
6FBA103D21D6B6D70051C35F /* TunnelImporter.swift */,
6FBA103A21D6B4280051C35F /* ErrorPresenterProtocol.swift */,
6B62E45E220A6FA900EF34A6 /* PrivateDataConfirmation.swift */,
@@ -1132,6 +1136,7 @@
files = (
6FBA101521D613F90051C35F /* Application.swift in Sources */,
6FB1BDCC21D50F5300A991BF /* TunnelsManager.swift in Sources */,
+ 6F8F0D7222258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */,
6FB1BDCD21D50F5300A991BF /* ActivateOnDemandSetting.swift in Sources */,
6FB1BDCE21D50F5300A991BF /* TunnelStatus.swift in Sources */,
6FB1BDD021D50F5300A991BF /* TunnelErrors.swift in Sources */,
@@ -1232,6 +1237,7 @@
5F45417D21C1B23600994C13 /* UITableViewCell+Reuse.swift in Sources */,
5F45419221C2D55800994C13 /* CheckmarkCell.swift in Sources */,
6FE254FF219C60290028284D /* ZipExporter.swift in Sources */,
+ 6F8F0D7122258153000E8335 /* ActivateOnDemandViewModel.swift in Sources */,
6B586C53220CBA6D00427C51 /* Data+KeyEncoding.swift in Sources */,
6F693A562179E556008551C1 /* Endpoint.swift in Sources */,
6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */,
diff --git a/WireGuard/WireGuard/Base.lproj/Localizable.strings b/WireGuard/WireGuard/Base.lproj/Localizable.strings
index e9658d26..ace96465 100644
--- a/WireGuard/WireGuard/Base.lproj/Localizable.strings
+++ b/WireGuard/WireGuard/Base.lproj/Localizable.strings
@@ -81,6 +81,17 @@
"tunnelSectionTitleOnDemand" = "On-Demand Activation";
+"tunnelOnDemandCellular" = "Cellular";
+"tunnelOnDemandEthernet" = "Ethernet";
+"tunnelOnDemandWiFi" = "Wi-Fi";
+"tunnelOnDemandSSIDDescription" = "Selected SSIDs";
+"tunnelOnDemandSSIDescriptionMac" = "SSIDs";
+"tunnelOnDemandSSIDEdit" = "Select SSIDs";
+
+"tunnelOnDemandAnySSID" = "Any SSID";
+"tunnelOnDemandOnlySelectedSSIDs" = "Only selected SSIDs";
+"tunnelOnDemandExceptSelectedSSIDs" = "Except selected SSIDs";
+
"tunnelOnDemandKey" = "Activate on demand";
"tunnelOnDemandOptionOff" = "Off";
"tunnelOnDemandOptionWiFiOnly" = "Wi-Fi only";
diff --git a/WireGuard/WireGuard/UI/ActivateOnDemandViewModel.swift b/WireGuard/WireGuard/UI/ActivateOnDemandViewModel.swift
new file mode 100644
index 00000000..b5ce6331
--- /dev/null
+++ b/WireGuard/WireGuard/UI/ActivateOnDemandViewModel.swift
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
+
+import Foundation
+
+class ActivateOnDemandViewModel {
+ enum OnDemandField {
+ case nonWiFiInterface
+ case wiFiInterface
+ case ssidDescription
+ case ssidEdit
+
+ var localizedUIString: String {
+ switch self {
+ case .nonWiFiInterface:
+ #if os(iOS)
+ return tr("tunnelOnDemandCellular")
+ #elseif os(macOS)
+ return tr("tunnelOnDemandEthernet")
+ #else
+ #error("Unimplemented")
+ #endif
+ case .wiFiInterface: return tr("tunnelOnDemandWiFi")
+ case .ssidDescription: return tr("tunnelOnDemandSSIDDescription")
+ case .ssidEdit: return tr("tunnelOnDemandSSIDEdit")
+ }
+ }
+ }
+
+ enum OnDemandSSIDOption {
+ case anySSID
+ case onlySpecificSSIDs
+ case exceptSpecificSSIDs
+
+ var localizedUIString: String {
+ switch self {
+ case .anySSID: return tr("tunnelOnDemandAnySSID")
+ case .onlySpecificSSIDs: return tr("tunnelOnDemandOnlySelectedSSIDs")
+ case .exceptSpecificSSIDs: return tr("tunnelOnDemandExceptSelectedSSIDs")
+ }
+ }
+ }
+
+ var isNonWiFiInterfaceEnabled = false
+ var isWiFiInterfaceEnabled = false
+ var selectedSSIDs = [String]()
+ var ssidOption: OnDemandSSIDOption = .anySSID
+}
+
+extension ActivateOnDemandViewModel {
+ convenience init(from option: ActivateOnDemandOption) {
+ self.init()
+ switch option {
+ case .none:
+ break
+ case .wiFiInterfaceOnly(let onDemandSSIDOption):
+ isWiFiInterfaceEnabled = true
+ (ssidOption, selectedSSIDs) = ssidViewModel(from: onDemandSSIDOption)
+ case .nonWiFiInterfaceOnly:
+ isNonWiFiInterfaceEnabled = true
+ case .anyInterface(let onDemandSSIDOption):
+ isWiFiInterfaceEnabled = true
+ isNonWiFiInterfaceEnabled = true
+ (ssidOption, selectedSSIDs) = ssidViewModel(from: onDemandSSIDOption)
+ }
+ }
+
+ func toOnDemandOption() -> ActivateOnDemandOption {
+ switch (isWiFiInterfaceEnabled, isNonWiFiInterfaceEnabled) {
+ case (false, false):
+ return .none
+ case (false, true):
+ return .nonWiFiInterfaceOnly
+ case (true, false):
+ return .wiFiInterfaceOnly(toSSIDOption())
+ case (true, true):
+ return .anyInterface(toSSIDOption())
+ }
+ }
+}
+
+extension ActivateOnDemandViewModel {
+ func isEnabled(field: OnDemandField) -> Bool {
+ switch field {
+ case .nonWiFiInterface:
+ return isNonWiFiInterfaceEnabled
+ case .wiFiInterface:
+ return isWiFiInterfaceEnabled
+ default:
+ return false
+ }
+ }
+
+ func setEnabled(field: OnDemandField, isEnabled: Bool) {
+ switch field {
+ case .nonWiFiInterface:
+ isNonWiFiInterfaceEnabled = isEnabled
+ case .wiFiInterface:
+ isWiFiInterfaceEnabled = isEnabled
+ default:
+ break
+ }
+ }
+}
+
+private extension ActivateOnDemandViewModel {
+ func ssidViewModel(from ssidOption: ActivateOnDemandSSIDOption) -> (OnDemandSSIDOption, [String]) {
+ switch ssidOption {
+ case .anySSID:
+ return (.anySSID, [])
+ case .onlySpecificSSIDs(let ssids):
+ return (.onlySpecificSSIDs, ssids)
+ case .exceptSpecificSSIDs(let ssids):
+ return (.exceptSpecificSSIDs, ssids)
+ }
+ }
+
+ func toSSIDOption() -> ActivateOnDemandSSIDOption {
+ switch ssidOption {
+ case .anySSID:
+ return .anySSID
+ case .onlySpecificSSIDs:
+ return .onlySpecificSSIDs(selectedSSIDs)
+ case .exceptSpecificSSIDs:
+ return .exceptSpecificSSIDs(selectedSSIDs)
+ }
+ }
+}