From 7a450089c0a0cda91b87c567c441af305ae12a58 Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Wed, 27 Feb 2019 13:25:53 +0530 Subject: [PATCH] on-demand: Introducing ActivateOnDemandViewModel Signed-off-by: Roopesh Chander --- WireGuard/WireGuard.xcodeproj/project.pbxproj | 6 + .../WireGuard/Base.lproj/Localizable.strings | 11 ++ .../UI/ActivateOnDemandViewModel.swift | 128 ++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 WireGuard/WireGuard/UI/ActivateOnDemandViewModel.swift diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index 5a76107..a499298 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 = ""; }; 6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusItemController.swift; sourceTree = ""; }; 6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsTracker.swift; sourceTree = ""; }; + 6F8F0D7022258153000E8335 /* ActivateOnDemandViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandViewModel.swift; sourceTree = ""; }; 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = ""; }; 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = ""; }; 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = ""; }; @@ -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 e9658d2..ace9646 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 0000000..b5ce633 --- /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) + } + } +}