diff options
author | 2018-12-14 17:12:59 -0600 | |
---|---|---|
committer | 2018-12-14 17:15:22 -0600 | |
commit | 7a24f18eb753180800f9b44a767b0d59e4e702b7 (patch) | |
tree | 0e02b3ff59a672b0b25eb7bcc195e23730abec40 /WireGuard/WireGuard | |
parent | Prettier log time format (diff) | |
download | wireguard-apple-7a24f18eb753180800f9b44a767b0d59e4e702b7.tar.xz wireguard-apple-7a24f18eb753180800f9b44a767b0d59e4e702b7.zip |
Most similar views now shared between ViewControllers
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
Diffstat (limited to '')
27 files changed, 277 insertions, 505 deletions
diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index 53f2524..311a1b8 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -8,19 +8,15 @@ /* Begin PBXBuildFile section */ 5F45417D21C1B23600994C13 /* UITableViewCell+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45417C21C1B23600994C13 /* UITableViewCell+Reuse.swift */; }; - 5F45418A21C2D45B00994C13 /* TunnelEditKeyValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45418921C2D45B00994C13 /* TunnelEditKeyValueCell.swift */; }; + 5F45418A21C2D45B00994C13 /* EditableKeyValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45418921C2D45B00994C13 /* EditableKeyValueCell.swift */; }; 5F45418C21C2D48200994C13 /* TunnelEditReadOnlyKeyValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45418B21C2D48200994C13 /* TunnelEditReadOnlyKeyValueCell.swift */; }; - 5F45418E21C2D51100994C13 /* TunnelEditButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45418D21C2D51100994C13 /* TunnelEditButtonCell.swift */; }; - 5F45419021C2D53800994C13 /* TunnelEditSwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45418F21C2D53800994C13 /* TunnelEditSwitchCell.swift */; }; - 5F45419221C2D55800994C13 /* TunnelEditSectionListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419121C2D55800994C13 /* TunnelEditSectionListCell.swift */; }; - 5F45419421C2D5C500994C13 /* TunnelDetailActivateOnDemandCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419321C2D5C500994C13 /* TunnelDetailActivateOnDemandCell.swift */; }; - 5F45419621C2D5DB00994C13 /* TunnelDetailButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419521C2D5DB00994C13 /* TunnelDetailButtonCell.swift */; }; - 5F45419821C2D60500994C13 /* TunnelDetailKeyValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419721C2D60500994C13 /* TunnelDetailKeyValueCell.swift */; }; - 5F45419A21C2D61D00994C13 /* TunnelDetailStatusCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419921C2D61D00994C13 /* TunnelDetailStatusCell.swift */; }; - 5F45419C21C2D64800994C13 /* SettingsButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419B21C2D64800994C13 /* SettingsButtonCell.swift */; }; - 5F45419E21C2D66400994C13 /* SettingsKeyValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419D21C2D66400994C13 /* SettingsKeyValueCell.swift */; }; + 5F45419021C2D53800994C13 /* SwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45418F21C2D53800994C13 /* SwitchCell.swift */; }; + 5F45419221C2D55800994C13 /* CheckmarkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419121C2D55800994C13 /* CheckmarkCell.swift */; }; + 5F45419821C2D60500994C13 /* KeyValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419721C2D60500994C13 /* KeyValueCell.swift */; }; 5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F45419F21C2D6B700994C13 /* TunnelListCell.swift */; }; 5F4541A221C2D6DF00994C13 /* BorderedTextButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A121C2D6DF00994C13 /* BorderedTextButton.swift */; }; + 5F4541A621C4449E00994C13 /* ButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A521C4449E00994C13 /* ButtonCell.swift */; }; + 5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4541A821C451D100994C13 /* TunnelStatus.swift */; }; 6BB8400421892C920003598F /* CopyableLabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BB8400321892C920003598F /* CopyableLabelTableViewCell.swift */; }; 6F0068572191AFD200419BE9 /* ScrollableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0068562191AFD200419BE9 /* ScrollableLabel.swift */; }; 6F5A2B4621AFDED40081EDD8 /* FileManager+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */; }; @@ -109,19 +105,15 @@ /* Begin PBXFileReference section */ 5F45417C21C1B23600994C13 /* UITableViewCell+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewCell+Reuse.swift"; sourceTree = "<group>"; }; - 5F45418921C2D45B00994C13 /* TunnelEditKeyValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditKeyValueCell.swift; sourceTree = "<group>"; }; + 5F45418921C2D45B00994C13 /* EditableKeyValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableKeyValueCell.swift; sourceTree = "<group>"; }; 5F45418B21C2D48200994C13 /* TunnelEditReadOnlyKeyValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditReadOnlyKeyValueCell.swift; sourceTree = "<group>"; }; - 5F45418D21C2D51100994C13 /* TunnelEditButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditButtonCell.swift; sourceTree = "<group>"; }; - 5F45418F21C2D53800994C13 /* TunnelEditSwitchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditSwitchCell.swift; sourceTree = "<group>"; }; - 5F45419121C2D55800994C13 /* TunnelEditSectionListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditSectionListCell.swift; sourceTree = "<group>"; }; - 5F45419321C2D5C500994C13 /* TunnelDetailActivateOnDemandCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailActivateOnDemandCell.swift; sourceTree = "<group>"; }; - 5F45419521C2D5DB00994C13 /* TunnelDetailButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailButtonCell.swift; sourceTree = "<group>"; }; - 5F45419721C2D60500994C13 /* TunnelDetailKeyValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailKeyValueCell.swift; sourceTree = "<group>"; }; - 5F45419921C2D61D00994C13 /* TunnelDetailStatusCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelDetailStatusCell.swift; sourceTree = "<group>"; }; - 5F45419B21C2D64800994C13 /* SettingsButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsButtonCell.swift; sourceTree = "<group>"; }; - 5F45419D21C2D66400994C13 /* SettingsKeyValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKeyValueCell.swift; sourceTree = "<group>"; }; + 5F45418F21C2D53800994C13 /* SwitchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchCell.swift; sourceTree = "<group>"; }; + 5F45419121C2D55800994C13 /* CheckmarkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckmarkCell.swift; sourceTree = "<group>"; }; + 5F45419721C2D60500994C13 /* KeyValueCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueCell.swift; sourceTree = "<group>"; }; 5F45419F21C2D6B700994C13 /* TunnelListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListCell.swift; sourceTree = "<group>"; }; 5F4541A121C2D6DF00994C13 /* BorderedTextButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BorderedTextButton.swift; sourceTree = "<group>"; }; + 5F4541A521C4449E00994C13 /* ButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonCell.swift; sourceTree = "<group>"; }; + 5F4541A821C451D100994C13 /* TunnelStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelStatus.swift; sourceTree = "<group>"; }; 6BB8400321892C920003598F /* CopyableLabelTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CopyableLabelTableViewCell.swift; sourceTree = "<group>"; }; 6F0068562191AFD200419BE9 /* ScrollableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollableLabel.swift; sourceTree = "<group>"; }; 6F5A2B4421AFDE020081EDD8 /* FileManager+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Extension.swift"; sourceTree = "<group>"; }; @@ -136,7 +128,7 @@ 6F61F1EA21B937EF00483816 /* WireGuardResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuardResult.swift; sourceTree = "<group>"; }; 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelViewModel.swift; sourceTree = "<group>"; }; 6F628C3E217F3413003482A3 /* DNSServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSServer.swift; sourceTree = "<group>"; }; - 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; }; + 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TunnelDetailTableViewController.swift; path = TunnelDetail/TunnelDetailTableViewController.swift; sourceTree = "<group>"; }; 6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; }; 6F6899A42180447E0012E523 /* x25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = "<group>"; }; 6F6899A52180447E0012E523 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = "<group>"; }; @@ -202,49 +194,37 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 5F45418521C2C6AB00994C13 /* Settings */ = { - isa = PBXGroup; - children = ( - 6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */, - 5F45419B21C2D64800994C13 /* SettingsButtonCell.swift */, - 5F45419D21C2D66400994C13 /* SettingsKeyValueCell.swift */, - ); - path = Settings; - sourceTree = "<group>"; - }; 5F45418621C2C6B400994C13 /* EditTunnel */ = { isa = PBXGroup; children = ( 6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */, - 5F45418921C2D45B00994C13 /* TunnelEditKeyValueCell.swift */, 5F45418B21C2D48200994C13 /* TunnelEditReadOnlyKeyValueCell.swift */, - 5F45418D21C2D51100994C13 /* TunnelEditButtonCell.swift */, - 5F45418F21C2D53800994C13 /* TunnelEditSwitchCell.swift */, - 5F45419121C2D55800994C13 /* TunnelEditSectionListCell.swift */, ); path = EditTunnel; sourceTree = "<group>"; }; - 5F45418721C2C6C100994C13 /* TunnelDetail */ = { + 5F45418821C2C6CC00994C13 /* TunnelList */ = { isa = PBXGroup; children = ( - 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */, - 5F45419321C2D5C500994C13 /* TunnelDetailActivateOnDemandCell.swift */, - 5F45419521C2D5DB00994C13 /* TunnelDetailButtonCell.swift */, - 5F45419721C2D60500994C13 /* TunnelDetailKeyValueCell.swift */, - 5F45419921C2D61D00994C13 /* TunnelDetailStatusCell.swift */, + 6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */, + 5F45419F21C2D6B700994C13 /* TunnelListCell.swift */, ); - path = TunnelDetail; + path = TunnelList; sourceTree = "<group>"; }; - 5F45418821C2C6CC00994C13 /* TunnelList */ = { + 5F4541A721C44F5B00994C13 /* SharedViews */ = { isa = PBXGroup; children = ( - 6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */, - 5F45419F21C2D6B700994C13 /* TunnelListCell.swift */, + 6BB8400321892C920003598F /* CopyableLabelTableViewCell.swift */, + 6F0068562191AFD200419BE9 /* ScrollableLabel.swift */, + 5F45418F21C2D53800994C13 /* SwitchCell.swift */, + 5F45419721C2D60500994C13 /* KeyValueCell.swift */, + 5F4541A521C4449E00994C13 /* ButtonCell.swift */, + 5F45419121C2D55800994C13 /* CheckmarkCell.swift */, + 5F45418921C2D45B00994C13 /* EditableKeyValueCell.swift */, 5F4541A121C2D6DF00994C13 /* BorderedTextButton.swift */, ); - path = TunnelList; + path = SharedViews; sourceTree = "<group>"; }; 6F5D0C1B218352EF000F85AD /* WireGuardNetworkExtension */ = { @@ -303,16 +283,15 @@ 6F7774DE217181B1006A79B3 /* iOS */ = { isa = PBXGroup; children = ( + 5F4541A721C44F5B00994C13 /* SharedViews */, 5F45418821C2C6CC00994C13 /* TunnelList */, - 5F45418721C2C6C100994C13 /* TunnelDetail */, 5F45418621C2C6B400994C13 /* EditTunnel */, - 5F45418521C2C6AB00994C13 /* Settings */, - 6BB8400321892C920003598F /* CopyableLabelTableViewCell.swift */, 6FDEF7E52185EFAF00D8FBF6 /* QRScanViewController.swift */, + 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */, + 6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */, 6F7774E0217181B1006A79B3 /* AppDelegate.swift */, 6F7774DF217181B1006A79B3 /* MainViewController.swift */, 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */, - 6F0068562191AFD200419BE9 /* ScrollableLabel.swift */, 5F45417C21C1B23600994C13 /* UITableViewCell+Reuse.swift */, ); path = iOS; @@ -334,6 +313,7 @@ children = ( 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */, 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandSetting.swift */, + 5F4541A821C451D100994C13 /* TunnelStatus.swift */, ); path = Tunnel; sourceTree = "<group>"; @@ -692,47 +672,42 @@ 6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */, 6BB8400421892C920003598F /* CopyableLabelTableViewCell.swift in Sources */, 5F45417D21C1B23600994C13 /* UITableViewCell+Reuse.swift in Sources */, - 5F45419221C2D55800994C13 /* TunnelEditSectionListCell.swift in Sources */, + 5F45419221C2D55800994C13 /* CheckmarkCell.swift in Sources */, 6FE254FF219C60290028284D /* ZipExporter.swift in Sources */, 6F693A562179E556008551C1 /* Endpoint.swift in Sources */, - 5F45418E21C2D51100994C13 /* TunnelEditButtonCell.swift in Sources */, 6F0068572191AFD200419BE9 /* ScrollableLabel.swift in Sources */, 6FDEF7E62185EFB200D8FBF6 /* QRScanViewController.swift in Sources */, 6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */, + 5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */, 6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */, - 5F45418A21C2D45B00994C13 /* TunnelEditKeyValueCell.swift in Sources */, + 5F45418A21C2D45B00994C13 /* EditableKeyValueCell.swift in Sources */, 6F6899A62180447E0012E523 /* x25519.c in Sources */, 6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */, 6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */, 6FDEF7FC21863B6100D8FBF6 /* zip.c in Sources */, 6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */, - 5F45419C21C2D64800994C13 /* SettingsButtonCell.swift in Sources */, 6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */, - 5F45419821C2D60500994C13 /* TunnelDetailKeyValueCell.swift in Sources */, + 5F4541A621C4449E00994C13 /* ButtonCell.swift in Sources */, + 5F45419821C2D60500994C13 /* KeyValueCell.swift in Sources */, 6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */, 6F5A2B4821AFF49A0081EDD8 /* FileManager+Extension.swift in Sources */, 5F45418C21C2D48200994C13 /* TunnelEditReadOnlyKeyValueCell.swift in Sources */, 6FDEF8082187442100D8FBF6 /* WgQuickConfigFileWriter.swift in Sources */, 6FE254FB219C10800028284D /* ZipImporter.swift in Sources */, - 5F45419A21C2D61D00994C13 /* TunnelDetailStatusCell.swift in Sources */, 6F7774EA217229DB006A79B3 /* IPAddressRange.swift in Sources */, - 5F45419621C2D5DB00994C13 /* TunnelDetailButtonCell.swift in Sources */, 6F7774E82172020C006A79B3 /* Configuration.swift in Sources */, 6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */, - 5F45419E21C2D66400994C13 /* SettingsKeyValueCell.swift in Sources */, 6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */, 5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */, 6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */, 6F61F1EB21B937EF00483816 /* WireGuardResult.swift in Sources */, 6F7774F321774263006A79B3 /* TunnelEditTableViewController.swift in Sources */, 6FDEF802218646BA00D8FBF6 /* ZipArchive.swift in Sources */, - 5F45419021C2D53800994C13 /* TunnelEditSwitchCell.swift in Sources */, + 5F45419021C2D53800994C13 /* SwitchCell.swift in Sources */, 6FDEF806218725D200D8FBF6 /* SettingsTableViewController.swift in Sources */, 5F4541A221C2D6DF00994C13 /* BorderedTextButton.swift in Sources */, 6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */, 6FFA5DA42197085D0001E2F7 /* ActivateOnDemandSetting.swift in Sources */, - 5F45419421C2D5C500994C13 /* TunnelDetailActivateOnDemandCell.swift in Sources */, - 6FF717E521B2CB1E0045A474 /* InternetReachability.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/WireGuard/WireGuard/Tunnel/ActivateOnDemandSetting.swift b/WireGuard/WireGuard/Tunnel/ActivateOnDemandSetting.swift index 0aeda6f..9071098 100644 --- a/WireGuard/WireGuard/Tunnel/ActivateOnDemandSetting.swift +++ b/WireGuard/WireGuard/Tunnel/ActivateOnDemandSetting.swift @@ -63,9 +63,9 @@ extension ActivateOnDemandSetting { } self.activateOnDemandOption = activateOnDemandOption if activateOnDemandOption == .none { - self.isActivateOnDemandEnabled = false + isActivateOnDemandEnabled = false } else { - self.isActivateOnDemandEnabled = tunnelProviderManager.isOnDemandEnabled + isActivateOnDemandEnabled = tunnelProviderManager.isOnDemandEnabled } } } diff --git a/WireGuard/WireGuard/Tunnel/TunnelStatus.swift b/WireGuard/WireGuard/Tunnel/TunnelStatus.swift new file mode 100644 index 0000000..9f03417 --- /dev/null +++ b/WireGuard/WireGuard/Tunnel/TunnelStatus.swift @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +// Copyright © 2018 WireGuard LLC. All Rights Reserved. + +import Foundation +import NetworkExtension + +@objc enum TunnelStatus: Int { + case inactive + case activating + case active + case deactivating + case reasserting // Not a possible state at present + case restarting // Restarting tunnel (done after saving modifications to an active tunnel) + case waiting // Waiting for another tunnel to be brought down + + init(from systemStatus: NEVPNStatus) { + switch systemStatus { + case .connected: + self = .active + case .connecting: + self = .activating + case .disconnected: + self = .inactive + case .disconnecting: + self = .deactivating + case .reasserting: + self = .reasserting + case .invalid: + self = .inactive + } + } +} + +extension TunnelStatus: CustomDebugStringConvertible { + public var debugDescription: String { + switch self { + case .inactive: return "inactive" + case .activating: return "activating" + case .active: return "active" + case .deactivating: return "deactivating" + case .reasserting: return "reasserting" + case .restarting: return "restarting" + case .waiting: return "waiting" + } + } +} diff --git a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift index 6f93267..4c2f2ed 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift @@ -86,8 +86,8 @@ class TunnelsManager { private var statusObservationToken: AnyObject? init(tunnelProviders: [NETunnelProviderManager]) { - self.tunnels = tunnelProviders.map { TunnelContainer(tunnel: $0) }.sorted { $0.name < $1.name } - self.startObservingTunnelStatuses() + tunnels = tunnelProviders.map { TunnelContainer(tunnel: $0) }.sorted { $0.name < $1.name } + startObservingTunnelStatuses() } static func create(completionHandler: @escaping (WireGuardResult<TunnelsManager>) -> Void) { @@ -112,7 +112,7 @@ class TunnelsManager { return } - if self.tunnels.contains(where: { $0.name == tunnelName }) { + if tunnels.contains(where: { $0.name == tunnelName }) { completionHandler(.failure(TunnelsManagerError.tunnelAlreadyExistsWithThatName)) return } @@ -151,7 +151,7 @@ class TunnelsManager { return } let tail = tunnelConfigurations.dropFirst() - self.add(tunnelConfiguration: head) { [weak self, tail] result in + add(tunnelConfiguration: head) { [weak self, tail] result in DispatchQueue.main.async { self?.addMultiple(tunnelConfigurations: tail, numberSuccessful: numberSuccessful + (result.isSuccess ? 1 : 0), completionHandler: completionHandler) } @@ -168,7 +168,7 @@ class TunnelsManager { let tunnelProviderManager = tunnel.tunnelProvider let isNameChanged = (tunnelName != tunnelProviderManager.localizedDescription) if isNameChanged { - if self.tunnels.contains(where: { $0.name == tunnelName }) { + if tunnels.contains(where: { $0.name == tunnelName }) { completionHandler(TunnelsManagerError.tunnelAlreadyExistsWithThatName) return } @@ -249,13 +249,13 @@ class TunnelsManager { } func tunnel(named tunnelName: String) -> TunnelContainer? { - return self.tunnels.first { $0.name == tunnelName } + return tunnels.first { $0.name == tunnelName } } func startActivation(of tunnel: TunnelContainer) { guard tunnels.contains(tunnel) else { return } // Ensure it's not deleted guard tunnel.status == .inactive else { - self.activationDelegate?.tunnelActivationAttemptFailed(tunnel: tunnel, error: .tunnelIsNotInactive) + activationDelegate?.tunnelActivationAttemptFailed(tunnel: tunnel, error: .tunnelIsNotInactive) return } @@ -272,7 +272,7 @@ class TunnelsManager { return } - tunnel.startActivation(activationDelegate: self.activationDelegate) + tunnel.startActivation(activationDelegate: activationDelegate) } func startDeactivation(of tunnel: TunnelContainer) { @@ -346,7 +346,7 @@ class TunnelsManager { } deinit { - if let statusObservationToken = self.statusObservationToken { + if let statusObservationToken = statusObservationToken { NotificationCenter.default.removeObserver(statusObservationToken) } } @@ -371,8 +371,8 @@ class TunnelContainer: NSObject { self.activationTimer = activationTimer RunLoop.main.add(activationTimer, forMode: .default) } else { - self.activationTimer?.invalidate() - self.activationTimer = nil + activationTimer?.invalidate() + activationTimer = nil } } } @@ -383,11 +383,11 @@ class TunnelContainer: NSObject { private var lastTunnelConnectionStatus: NEVPNStatus? init(tunnel: NETunnelProviderManager) { - self.name = tunnel.localizedDescription ?? "Unnamed" + name = tunnel.localizedDescription ?? "Unnamed" let status = TunnelStatus(from: tunnel.connection.status) self.status = status - self.isActivateOnDemandEnabled = tunnel.isOnDemandEnabled - self.tunnelProvider = tunnel + isActivateOnDemandEnabled = tunnel.isOnDemandEnabled + tunnelProvider = tunnel super.init() } @@ -400,9 +400,9 @@ class TunnelContainer: NSObject { } func refreshStatus() { - let status = TunnelStatus(from: self.tunnelProvider.connection.status) + let status = TunnelStatus(from: tunnelProvider.connection.status) self.status = status - self.isActivateOnDemandEnabled = self.tunnelProvider.isOnDemandEnabled + isActivateOnDemandEnabled = tunnelProvider.isOnDemandEnabled } //swiftlint:disable:next function_body_length @@ -413,9 +413,9 @@ class TunnelContainer: NSObject { return } - wg_log(.debug, message: "startActivation: Entering (tunnel: \(self.name))") + wg_log(.debug, message: "startActivation: Entering (tunnel: \(name))") - self.status = .activating // Ensure that no other tunnel can attempt activation until this tunnel is done trying + status = .activating // Ensure that no other tunnel can attempt activation until this tunnel is done trying guard tunnelProvider.isEnabled else { // In case the tunnel had gotten disabled, re-enable and save it, @@ -440,14 +440,14 @@ class TunnelContainer: NSObject { // Start the tunnel do { wg_log(.debug, staticMessage: "startActivation: Starting tunnel") - self.isAttemptingActivation = true + isAttemptingActivation = true let activationAttemptId = UUID().uuidString self.activationAttemptId = activationAttemptId try (tunnelProvider.connection as? NETunnelProviderSession)?.startTunnel(options: ["activationAttemptId": activationAttemptId]) wg_log(.debug, staticMessage: "startActivation: Success") activationDelegate?.tunnelActivationAttemptSucceeded(tunnel: self) } catch let error { - self.isAttemptingActivation = false + isAttemptingActivation = false guard let systemError = error as? NEVPNError else { wg_log(.error, message: "Failed to activate tunnel: Error: \(error)") status = .inactive @@ -481,47 +481,6 @@ class TunnelContainer: NSObject { } } -@objc enum TunnelStatus: Int { - case inactive - case activating - case active - case deactivating - case reasserting // Not a possible state at present - case restarting // Restarting tunnel (done after saving modifications to an active tunnel) - case waiting // Waiting for another tunnel to be brought down - - init(from systemStatus: NEVPNStatus) { - switch systemStatus { - case .connected: - self = .active - case .connecting: - self = .activating - case .disconnected: - self = .inactive - case .disconnecting: - self = .deactivating - case .reasserting: - self = .reasserting - case .invalid: - self = .inactive - } - } -} - -extension TunnelStatus: CustomDebugStringConvertible { - public var debugDescription: String { - switch self { - case .inactive: return "inactive" - case .activating: return "activating" - case .active: return "active" - case .deactivating: return "deactivating" - case .reasserting: return "reasserting" - case .restarting: return "restarting" - case .waiting: return "waiting" - } - } -} - extension NEVPNStatus: CustomDebugStringConvertible { public var debugDescription: String { switch self { diff --git a/WireGuard/WireGuard/UI/iOS/AppDelegate.swift b/WireGuard/WireGuard/UI/iOS/AppDelegate.swift index 3146346..428f732 100644 --- a/WireGuard/WireGuard/UI/iOS/AppDelegate.swift +++ b/WireGuard/WireGuard/UI/iOS/AppDelegate.swift @@ -15,7 +15,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { Logger.configureGlobal(withFilePath: FileManager.appLogFileURL?.path) let window = UIWindow(frame: UIScreen.main.bounds) - window.backgroundColor = UIColor.white + window.backgroundColor = .white self.window = window let mainVC = MainViewController() diff --git a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditReadOnlyKeyValueCell.swift b/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditReadOnlyKeyValueCell.swift index 48c8798..15d58d6 100644 --- a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditReadOnlyKeyValueCell.swift +++ b/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditReadOnlyKeyValueCell.swift @@ -6,29 +6,36 @@ import UIKit class TunnelEditReadOnlyKeyValueCell: CopyableLabelTableViewCell { var key: String { get { return keyLabel.text ?? "" } - set(value) {keyLabel.text = value } + set(value) { keyLabel.text = value } } var value: String { get { return valueLabel.text } set(value) { valueLabel.text = value } } - let keyLabel: UILabel - let valueLabel: ScrollableLabel + override var textToCopy: String? { + return valueLabel.text + } - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - keyLabel = UILabel() + let keyLabel: UILabel = { + let keyLabel = UILabel() keyLabel.font = UIFont.preferredFont(forTextStyle: .body) keyLabel.adjustsFontForContentSizeCategory = true - valueLabel = ScrollableLabel() + keyLabel.textColor = .gray + return keyLabel + }() + + let valueLabel: ScrollableLabel = { + let valueLabel = ScrollableLabel() valueLabel.label.font = UIFont.preferredFont(forTextStyle: .body) valueLabel.label.adjustsFontForContentSizeCategory = true - + valueLabel.textColor = .gray + return valueLabel + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - keyLabel.textColor = UIColor.gray - valueLabel.textColor = UIColor.gray - contentView.addSubview(keyLabel) keyLabel.translatesAutoresizingMaskIntoConstraints = false keyLabel.textAlignment = .right @@ -44,7 +51,7 @@ class TunnelEditReadOnlyKeyValueCell: CopyableLabelTableViewCell { keyLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), keyLabel.leftAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leftAnchor), widthRatioConstraint - ]) + ]) contentView.addSubview(valueLabel) valueLabel.translatesAutoresizingMaskIntoConstraints = false @@ -52,11 +59,7 @@ class TunnelEditReadOnlyKeyValueCell: CopyableLabelTableViewCell { valueLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), valueLabel.leftAnchor.constraint(equalToSystemSpacingAfter: keyLabel.rightAnchor, multiplier: 1), valueLabel.rightAnchor.constraint(equalTo: contentView.layoutMarginsGuide.rightAnchor) - ]) - } - - override var textToCopy: String? { - return self.valueLabel.text + ]) } required init?(coder aDecoder: NSCoder) { diff --git a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditTableViewController.swift b/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditTableViewController.swift index 8d055d2..393294e 100644 --- a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditTableViewController.swift @@ -72,18 +72,18 @@ class TunnelEditTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() - self.title = tunnel == nil ? "New configuration" : "Edit configuration" - self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveTapped)) - self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelTapped)) - - self.tableView.estimatedRowHeight = 44 - self.tableView.rowHeight = UITableView.automaticDimension - - self.tableView.register(TunnelEditKeyValueCell.self) - self.tableView.register(TunnelEditReadOnlyKeyValueCell.self) - self.tableView.register(TunnelEditButtonCell.self) - self.tableView.register(TunnelEditSwitchCell.self) - self.tableView.register(TunnelEditSelectionListCell.self) + title = tunnel == nil ? "New configuration" : "Edit configuration" + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveTapped)) + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelTapped)) + + tableView.estimatedRowHeight = 44 + tableView.rowHeight = UITableView.automaticDimension + + tableView.register(EditableKeyValueCell.self) + tableView.register(TunnelEditReadOnlyKeyValueCell.self) + tableView.register(ButtonCell.self) + tableView.register(SwitchCell.self) + tableView.register(CheckmarkCell.self) } private func loadSections() { @@ -95,13 +95,13 @@ class TunnelEditTableViewController: UITableViewController { } @objc func saveTapped() { - self.tableView.endEditing(false) + tableView.endEditing(false) let tunnelSaveResult = tunnelViewModel.save() switch tunnelSaveResult { case .error(let errorMessage): let erroringConfiguration = (tunnelViewModel.interfaceData.validatedConfiguration == nil) ? "Interface" : "Peer" ErrorPresenter.showErrorAlert(title: "Invalid \(erroringConfiguration)", message: errorMessage, from: self) - self.tableView.reloadData() // Highlight erroring fields + tableView.reloadData() // Highlight erroring fields case .saved(let tunnelConfiguration): if let tunnel = tunnel { // We're modifying an existing tunnel @@ -133,7 +133,7 @@ class TunnelEditTableViewController: UITableViewController { @objc func cancelTapped() { dismiss(animated: true, completion: nil) - self.delegate?.tunnelEditingCancelled() + delegate?.tunnelEditingCancelled() } } @@ -201,7 +201,7 @@ extension TunnelEditTableViewController { } private func generateKeyPairCell(for tableView: UITableView, at indexPath: IndexPath, with field: TunnelViewModel.InterfaceField) -> UITableViewCell { - let cell: TunnelEditButtonCell = tableView.dequeueReusableCell(for: indexPath) + let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) cell.buttonText = field.rawValue cell.onTapped = { [weak self] in guard let self = self else { return } @@ -225,7 +225,7 @@ extension TunnelEditTableViewController { } private func interfaceFieldKeyValueCell(for tableView: UITableView, at indexPath: IndexPath, with field: TunnelViewModel.InterfaceField) -> UITableViewCell { - let cell: TunnelEditKeyValueCell = tableView.dequeueReusableCell(for: indexPath) + let cell: EditableKeyValueCell = tableView.dequeueReusableCell(for: indexPath) cell.key = field.rawValue switch field { @@ -287,7 +287,7 @@ extension TunnelEditTableViewController { } private func deletePeerCell(for tableView: UITableView, at indexPath: IndexPath, peerData: TunnelViewModel.PeerData, field: TunnelViewModel.PeerField) -> UITableViewCell { - let cell: TunnelEditButtonCell = tableView.dequeueReusableCell(for: indexPath) + let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) cell.buttonText = field.rawValue cell.hasDestructiveAction = true cell.onTapped = { [weak self, weak peerData] in @@ -313,7 +313,7 @@ extension TunnelEditTableViewController { } private func excludePrivateIPsCell(for tableView: UITableView, at indexPath: IndexPath, peerData: TunnelViewModel.PeerData, field: TunnelViewModel.PeerField) -> UITableViewCell { - let cell: TunnelEditSwitchCell = tableView.dequeueReusableCell(for: indexPath) + let cell: SwitchCell = tableView.dequeueReusableCell(for: indexPath) cell.message = field.rawValue cell.isEnabled = peerData.shouldAllowExcludePrivateIPsControl cell.isOn = peerData.excludePrivateIPsValue @@ -328,7 +328,7 @@ extension TunnelEditTableViewController { } private func peerFieldKeyValueCell(for tableView: UITableView, at indexPath: IndexPath, peerData: TunnelViewModel.PeerData, field: TunnelViewModel.PeerField) -> UITableViewCell { - let cell: TunnelEditKeyValueCell = tableView.dequeueReusableCell(for: indexPath) + let cell: EditableKeyValueCell = tableView.dequeueReusableCell(for: indexPath) cell.key = field.rawValue switch field { @@ -377,7 +377,7 @@ extension TunnelEditTableViewController { } private func addPeerCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell: TunnelEditButtonCell = tableView.dequeueReusableCell(for: indexPath) + let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) cell.buttonText = "Add peer" cell.onTapped = { [weak self] in guard let self = self else { return } @@ -398,7 +398,7 @@ extension TunnelEditTableViewController { private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { if indexPath.row == 0 { - let cell: TunnelEditSwitchCell = tableView.dequeueReusableCell(for: indexPath) + let cell: SwitchCell = tableView.dequeueReusableCell(for: indexPath) cell.message = "Activate on demand" cell.isOn = activateOnDemandSetting.isActivateOnDemandEnabled cell.onSwitchToggled = { [weak self] isOn in @@ -419,7 +419,7 @@ extension TunnelEditTableViewController { } return cell } else { - let cell: TunnelEditSelectionListCell = tableView.dequeueReusableCell(for: indexPath) + let cell: CheckmarkCell = tableView.dequeueReusableCell(for: indexPath) let rowOption = activateOnDemandOptions[indexPath.row - 1] let selectedOption = activateOnDemandSetting.activateOnDemandOption assert(selectedOption != .none) @@ -455,7 +455,7 @@ extension TunnelEditTableViewController { alert.popoverPresentationController?.sourceView = sourceView alert.popoverPresentationController?.sourceRect = sourceView.bounds - self.present(alert, animated: true, completion: nil) + present(alert, animated: true, completion: nil) } } diff --git a/WireGuard/WireGuard/UI/iOS/MainViewController.swift b/WireGuard/WireGuard/UI/iOS/MainViewController.swift index 2fc46b2..82e6f81 100644 --- a/WireGuard/WireGuard/UI/iOS/MainViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/MainViewController.swift @@ -12,20 +12,20 @@ class MainViewController: UISplitViewController { init() { let detailVC = UIViewController() - detailVC.view.backgroundColor = UIColor.white + detailVC.view.backgroundColor = .white let detailNC = UINavigationController(rootViewController: detailVC) let masterVC = TunnelsListTableViewController() let masterNC = UINavigationController(rootViewController: masterVC) - self.tunnelsListVC = masterVC + tunnelsListVC = masterVC super.init(nibName: nil, bundle: nil) - self.viewControllers = [ masterNC, detailNC ] + viewControllers = [ masterNC, detailNC ] // State restoration - self.restorationIdentifier = "MainVC" + restorationIdentifier = "MainVC" masterNC.restorationIdentifier = "MasterNC" detailNC.restorationIdentifier = "DetailNC" } @@ -35,10 +35,10 @@ class MainViewController: UISplitViewController { } override func viewDidLoad() { - self.delegate = self + delegate = self // On iPad, always show both masterVC and detailVC, even in portrait mode, like the Settings app - self.preferredDisplayMode = .allVisible + preferredDisplayMode = .allVisible // Create the tunnels manager, and when it's ready, inform tunnelsListVC TunnelsManager.create { [weak self] result in @@ -56,7 +56,7 @@ class MainViewController: UISplitViewController { tunnelsManager.activationDelegate = self self.onTunnelsManagerReady?(tunnelsManager) - self.onTunnelsManagerReady = nil + self.onTunnelsManagerReady = nil } } } diff --git a/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift b/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift index a03b709..1e231ec 100644 --- a/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift @@ -2,7 +2,6 @@ // Copyright © 2018 WireGuard LLC. All Rights Reserved. import AVFoundation -import CoreData import UIKit protocol QRScanViewControllerDelegate: class { @@ -18,8 +17,8 @@ class QRScanViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - self.title = "Scan QR code" - self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelTapped)) + title = "Scan QR code" + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelTapped)) let tipLabel = UILabel() tipLabel.text = "Tip: Generate with `qrencode -t ansiutf8 < tunnel.conf`" @@ -102,7 +101,7 @@ class QRScanViewController: UIViewController { } } - previewLayer?.frame = self.view.bounds + previewLayer?.frame = view.bounds } func scanDidComplete(withCode code: String) { diff --git a/WireGuard/WireGuard/UI/iOS/Settings/SettingsButtonCell.swift b/WireGuard/WireGuard/UI/iOS/Settings/SettingsButtonCell.swift deleted file mode 100644 index d795ab4..0000000 --- a/WireGuard/WireGuard/UI/iOS/Settings/SettingsButtonCell.swift +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2018 WireGuard LLC. All Rights Reserved. - -import UIKit - -class SettingsButtonCell: UITableViewCell { - var buttonText: String { - get { return button.title(for: .normal) ?? "" } - set(value) { button.setTitle(value, for: .normal) } - } - var onTapped: (() -> Void)? - - let button: UIButton = { - let button = UIButton(type: .system) - button.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body) - button.titleLabel?.adjustsFontForContentSizeCategory = true - return button - }() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - - contentView.addSubview(button) - button.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - button.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor), - contentView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: button.bottomAnchor), - button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor) - ]) - - button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) - } - - @objc func buttonTapped() { - onTapped?() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func prepareForReuse() { - super.prepareForReuse() - buttonText = "" - onTapped = nil - } -} diff --git a/WireGuard/WireGuard/UI/iOS/Settings/SettingsKeyValueCell.swift b/WireGuard/WireGuard/UI/iOS/Settings/SettingsKeyValueCell.swift deleted file mode 100644 index 532f1d1..0000000 --- a/WireGuard/WireGuard/UI/iOS/Settings/SettingsKeyValueCell.swift +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2018 WireGuard LLC. All Rights Reserved. - -import UIKit - -class SettingsKeyValueCell: UITableViewCell { - var key: String { - get { return textLabel?.text ?? "" } - set(value) { textLabel?.text = value } - } - var value: String { - get { return detailTextLabel?.text ?? "" } - set(value) { detailTextLabel?.text = value } - } - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: .value1, reuseIdentifier: SettingsKeyValueCell.reuseIdentifier) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func prepareForReuse() { - super.prepareForReuse() - key = "" - value = "" - } -} diff --git a/WireGuard/WireGuard/UI/iOS/Settings/SettingsTableViewController.swift b/WireGuard/WireGuard/UI/iOS/SettingsTableViewController.swift index 5e8aee6..b583c5b 100644 --- a/WireGuard/WireGuard/UI/iOS/Settings/SettingsTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/SettingsTableViewController.swift @@ -40,15 +40,15 @@ class SettingsTableViewController: UITableViewController { tableView.rowHeight = UITableView.automaticDimension tableView.allowsSelection = false - tableView.register(SettingsKeyValueCell.self) - tableView.register(SettingsButtonCell.self) + tableView.register(KeyValueCell.self) + tableView.register(ButtonCell.self) tableView.tableFooterView = UIImageView(image: UIImage(named: "wireguard.pdf")) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - guard let logo = self.tableView.tableFooterView else { return } + guard let logo = tableView.tableFooterView else { return } let bottomPadding = max(tableView.layoutMargins.bottom, 10) let fullHeight = max(tableView.contentSize.height, tableView.bounds.size.height - tableView.layoutMargins.top - bottomPadding) @@ -167,7 +167,8 @@ extension SettingsTableViewController { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let field = settingsFieldsBySection[indexPath.section][indexPath.row] if field == .iosAppVersion || field == .goBackendVersion { - let cell: SettingsKeyValueCell = tableView.dequeueReusableCell(for: indexPath) + let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath) + cell.copyableGesture = false cell.key = field.rawValue if field == .iosAppVersion { var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown version" @@ -180,7 +181,7 @@ extension SettingsTableViewController { } return cell } else if field == .exportZipArchive { - let cell: SettingsButtonCell = tableView.dequeueReusableCell(for: indexPath) + let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) cell.buttonText = field.rawValue cell.onTapped = { [weak self] in self?.exportConfigurationsAsZipFile(sourceView: cell.button) @@ -188,7 +189,7 @@ extension SettingsTableViewController { return cell } else { assert(field == .exportLogFile) - let cell: SettingsButtonCell = tableView.dequeueReusableCell(for: indexPath) + let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) cell.buttonText = field.rawValue cell.onTapped = { [weak self] in self?.exportLogForLastActivatedTunnel(sourceView: cell.button) diff --git a/WireGuard/WireGuard/UI/iOS/TunnelList/BorderedTextButton.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/BorderedTextButton.swift index 5114c09..94b76d6 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelList/BorderedTextButton.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/BorderedTextButton.swift @@ -33,9 +33,9 @@ class BorderedTextButton: UIView { addSubview(button) button.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ - button.centerXAnchor.constraint(equalTo: self.centerXAnchor), - button.centerYAnchor.constraint(equalTo: self.centerYAnchor) - ]) + button.centerXAnchor.constraint(equalTo: centerXAnchor), + button.centerYAnchor.constraint(equalTo: centerYAnchor) + ]) button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) } diff --git a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditButtonCell.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/ButtonCell.swift index af70183..4702993 100644 --- a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditButtonCell.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/ButtonCell.swift @@ -3,14 +3,14 @@ import UIKit -class TunnelEditButtonCell: UITableViewCell { +class ButtonCell: UITableViewCell { var buttonText: String { get { return button.title(for: .normal) ?? "" } set(value) { button.setTitle(value, for: .normal) } } var hasDestructiveAction: Bool { - get { return button.tintColor == UIColor.red } - set(value) { button.tintColor = value ? UIColor.red : buttonStandardTintColor } + get { return button.tintColor == .red } + set(value) { button.tintColor = value ? .red : buttonStandardTintColor } } var onTapped: (() -> Void)? diff --git a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditSectionListCell.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/CheckmarkCell.swift index ca0352e..db4b6c9 100644 --- a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditSectionListCell.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/CheckmarkCell.swift @@ -3,7 +3,7 @@ import UIKit -class TunnelEditSelectionListCell: UITableViewCell { +class CheckmarkCell: UITableViewCell { var message: String { get { return textLabel?.text ?? "" } set(value) { textLabel!.text = value } @@ -13,6 +13,7 @@ class TunnelEditSelectionListCell: UITableViewCell { accessoryType = isChecked ? .checkmark : .none } } + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { isChecked = false super.init(style: .default, reuseIdentifier: reuseIdentifier) diff --git a/WireGuard/WireGuard/UI/iOS/CopyableLabelTableViewCell.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/CopyableLabelTableViewCell.swift index daddf0a..93a9ef7 100644 --- a/WireGuard/WireGuard/UI/iOS/CopyableLabelTableViewCell.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/CopyableLabelTableViewCell.swift @@ -17,13 +17,13 @@ class CopyableLabelTableViewCell: UITableViewCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:))) - self.addGestureRecognizer(gestureRecognizer) - self.isUserInteractionEnabled = true + addGestureRecognizer(gestureRecognizer) + isUserInteractionEnabled = true } // MARK: - UIGestureRecognizer @objc func handleTapGesture(_ recognizer: UIGestureRecognizer) { - if !self.copyableGesture { + if !copyableGesture { return } guard recognizer.state == .recognized else { return } @@ -31,7 +31,7 @@ class CopyableLabelTableViewCell: UITableViewCell { if let recognizerView = recognizer.view, let recognizerSuperView = recognizerView.superview, recognizerView.becomeFirstResponder() { let menuController = UIMenuController.shared - menuController.setTargetRect(self.detailTextLabel?.frame ?? recognizerView.frame, in: self.detailTextLabel?.superview ?? recognizerSuperView) + menuController.setTargetRect(detailTextLabel?.frame ?? recognizerView.frame, in: detailTextLabel?.superview ?? recognizerSuperView) menuController.setMenuVisible(true, animated: true) } } @@ -50,6 +50,6 @@ class CopyableLabelTableViewCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() - self.copyableGesture = true + copyableGesture = true } } diff --git a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditKeyValueCell.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/EditableKeyValueCell.swift index 432d75b..48956eb 100644 --- a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditKeyValueCell.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/EditableKeyValueCell.swift @@ -3,10 +3,10 @@ import UIKit -class TunnelEditKeyValueCell: UITableViewCell { +class EditableKeyValueCell: UITableViewCell { var key: String { get { return keyLabel.text ?? "" } - set(value) {keyLabel.text = value } + set(value) { keyLabel.text = value } } var value: String { get { return valueTextField.text ?? "" } @@ -89,7 +89,7 @@ class TunnelEditKeyValueCell: UITableViewCell { func configureForContentSize() { var constraints = [NSLayoutConstraint]() - if self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory { + if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { // Stack vertically if !isStackedVertically { constraints = [ @@ -113,9 +113,9 @@ class TunnelEditKeyValueCell: UITableViewCell { } } if !constraints.isEmpty { - NSLayoutConstraint.deactivate(self.contentSizeBasedConstraints) + NSLayoutConstraint.deactivate(contentSizeBasedConstraints) NSLayoutConstraint.activate(constraints) - self.contentSizeBasedConstraints = constraints + contentSizeBasedConstraints = constraints } } @@ -136,7 +136,7 @@ class TunnelEditKeyValueCell: UITableViewCell { } } -extension TunnelEditKeyValueCell: UITextFieldDelegate { +extension EditableKeyValueCell: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { textFieldValueOnBeginEditing = textField.text ?? "" isValueValid = true diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailKeyValueCell.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/KeyValueCell.swift index cbe1c14..78026ea 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailKeyValueCell.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/KeyValueCell.swift @@ -3,7 +3,7 @@ import UIKit -class TunnelDetailKeyValueCell: CopyableLabelTableViewCell { +class KeyValueCell: CopyableLabelTableViewCell { var key: String { get { return keyLabel.text ?? "" } set(value) { keyLabel.text = value } @@ -14,7 +14,7 @@ class TunnelDetailKeyValueCell: CopyableLabelTableViewCell { } override var textToCopy: String? { - return self.valueLabel.text + return valueLabel.text } let keyLabel: UILabel = { @@ -46,14 +46,14 @@ class TunnelDetailKeyValueCell: CopyableLabelTableViewCell { NSLayoutConstraint.activate([ keyLabel.leftAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leftAnchor), keyLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 0.5) - ]) + ]) contentView.addSubview(valueLabel) valueLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ valueLabel.rightAnchor.constraint(equalTo: contentView.layoutMarginsGuide.rightAnchor), contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: valueLabel.bottomAnchor, multiplier: 0.5) - ]) + ]) keyLabel.setContentCompressionResistancePriority(.defaultHigh + 1, for: .horizontal) keyLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) @@ -64,7 +64,7 @@ class TunnelDetailKeyValueCell: CopyableLabelTableViewCell { func configureForContentSize() { var constraints = [NSLayoutConstraint]() - if self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory { + if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { // Stack vertically if !isStackedVertically { constraints = [ @@ -88,9 +88,9 @@ class TunnelDetailKeyValueCell: CopyableLabelTableViewCell { } } if !constraints.isEmpty { - NSLayoutConstraint.deactivate(self.contentSizeBasedConstraints) + NSLayoutConstraint.deactivate(contentSizeBasedConstraints) NSLayoutConstraint.activate(constraints) - self.contentSizeBasedConstraints = constraints + contentSizeBasedConstraints = constraints } } diff --git a/WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/ScrollableLabel.swift index bd6f547..bd6f547 100644 --- a/WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/ScrollableLabel.swift diff --git a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditSwitchCell.swift b/WireGuard/WireGuard/UI/iOS/SharedViews/SwitchCell.swift index 658fb95..d0c29aa 100644 --- a/WireGuard/WireGuard/UI/iOS/EditTunnel/TunnelEditSwitchCell.swift +++ b/WireGuard/WireGuard/UI/iOS/SharedViews/SwitchCell.swift @@ -3,10 +3,10 @@ import UIKit -class TunnelEditSwitchCell: UITableViewCell { +class SwitchCell: UITableViewCell { var message: String { get { return textLabel?.text ?? "" } - set(value) { textLabel!.text = value } + set(value) { textLabel?.text = value } } var isOn: Bool { get { return switchView.isOn } @@ -16,31 +16,32 @@ class TunnelEditSwitchCell: UITableViewCell { get { return switchView.isEnabled } set(value) { switchView.isEnabled = value - textLabel?.textColor = value ? UIColor.black : UIColor.gray + textLabel?.textColor = value ? .black : .gray } } var onSwitchToggled: ((Bool) -> Void)? - let switchView: UISwitch + let switchView = UISwitch() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - switchView = UISwitch() super.init(style: .default, reuseIdentifier: reuseIdentifier) + accessoryView = switchView switchView.addTarget(self, action: #selector(switchToggled), for: .valueChanged) } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } @objc func switchToggled() { onSwitchToggled?(switchView.isOn) } - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - override func prepareForReuse() { super.prepareForReuse() + isEnabled = true message = "" isOn = false } diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailActivateOnDemandCell.swift b/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailActivateOnDemandCell.swift deleted file mode 100644 index 9507c45..0000000 --- a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailActivateOnDemandCell.swift +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2018 WireGuard LLC. All Rights Reserved. - -import UIKit - -class TunnelDetailActivateOnDemandCell: UITableViewCell { - var tunnel: TunnelContainer? { - didSet(value) { - update(from: tunnel?.activateOnDemandSetting()) - onDemandStatusObservervationToken = tunnel?.observe(\.isActivateOnDemandEnabled) { [weak self] tunnel, _ in - self?.update(from: tunnel.activateOnDemandSetting()) - } - } - } - - var onDemandStatusObservervationToken: AnyObject? - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: .value1, reuseIdentifier: reuseIdentifier) - textLabel?.text = "Activate on demand" - textLabel?.font = UIFont.preferredFont(forTextStyle: .body) - textLabel?.adjustsFontForContentSizeCategory = true - detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body) - detailTextLabel?.adjustsFontForContentSizeCategory = true - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func update(from activateOnDemandSetting: ActivateOnDemandSetting?) { - detailTextLabel?.text = TunnelViewModel.activateOnDemandDetailText(for: activateOnDemandSetting) - } - - override func prepareForReuse() { - super.prepareForReuse() - textLabel?.text = "Activate on demand" - detailTextLabel?.text = "" - } -} diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailButtonCell.swift b/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailButtonCell.swift deleted file mode 100644 index 8710616..0000000 --- a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailButtonCell.swift +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2018 WireGuard LLC. All Rights Reserved. - -import UIKit - -class TunnelDetailButtonCell: UITableViewCell { - var buttonText: String { - get { return button.title(for: .normal) ?? "" } - set(value) { button.setTitle(value, for: .normal) } - } - var hasDestructiveAction: Bool { - get { return button.tintColor == UIColor.red } - set(value) { button.tintColor = value ? UIColor.red : buttonStandardTintColor } - } - var onTapped: (() -> Void)? - - let button: UIButton = { - let button = UIButton(type: .system) - button.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body) - button.titleLabel?.adjustsFontForContentSizeCategory = true - return button - }() - - var buttonStandardTintColor: UIColor - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - buttonStandardTintColor = button.tintColor - super.init(style: style, reuseIdentifier: reuseIdentifier) - - contentView.addSubview(button) - button.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - button.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor), - contentView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: button.bottomAnchor), - button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor) - ]) - - button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) - } - - @objc func buttonTapped() { - onTapped?() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func prepareForReuse() { - super.prepareForReuse() - buttonText = "" - onTapped = nil - hasDestructiveAction = false - } -} diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailStatusCell.swift b/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailStatusCell.swift deleted file mode 100644 index 0dd1ee9..0000000 --- a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailStatusCell.swift +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copyright © 2018 WireGuard LLC. All Rights Reserved. - -import UIKit - -class TunnelDetailStatusCell: UITableViewCell { - var tunnel: TunnelContainer? { - didSet(value) { - update(from: tunnel?.status) - statusObservervationToken = tunnel?.observe(\.status) { [weak self] tunnel, _ in - self?.update(from: tunnel.status) - } - } - } - var isSwitchInteractionEnabled: Bool { - get { return statusSwitch.isUserInteractionEnabled } - set(value) { statusSwitch.isUserInteractionEnabled = value } - } - var onSwitchToggled: ((Bool) -> Void)? - private var isOnSwitchToggledHandlerEnabled = true - - let statusSwitch: UISwitch - private var statusObservervationToken: AnyObject? - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - statusSwitch = UISwitch() - super.init(style: .default, reuseIdentifier: TunnelDetailKeyValueCell.reuseIdentifier) - accessoryView = statusSwitch - - statusSwitch.addTarget(self, action: #selector(switchToggled), for: .valueChanged) - } - - @objc func switchToggled() { - if isOnSwitchToggledHandlerEnabled { - onSwitchToggled?(statusSwitch.isOn) - } - } - - private func update(from status: TunnelStatus?) { - guard let status = status else { - reset() - return - } - let text: String - switch status { - case .inactive: - text = "Inactive" - case .activating: - text = "Activating" - case .active: - text = "Active" - case .deactivating: - text = "Deactivating" - case .reasserting: - text = "Reactivating" - case .restarting: - text = "Restarting" - case .waiting: - text = "Waiting" - } - textLabel?.text = text - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak statusSwitch] in - guard let statusSwitch = statusSwitch else { return } - statusSwitch.isOn = !(status == .deactivating || status == .inactive) - statusSwitch.isUserInteractionEnabled = (status == .inactive || status == .active) - } - textLabel?.textColor = (status == .active || status == .inactive) ? UIColor.black : UIColor.gray - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func reset() { - textLabel?.text = "Invalid" - statusSwitch.isOn = false - textLabel?.textColor = UIColor.gray - statusSwitch.isUserInteractionEnabled = false - } - - override func prepareForReuse() { - super.prepareForReuse() - reset() - } -} diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailTableViewController.swift index af4cf83..ed48d0f 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelDetail/TunnelDetailTableViewController.swift @@ -29,6 +29,8 @@ class TunnelDetailTableViewController: UITableViewController { let tunnel: TunnelContainer var tunnelViewModel: TunnelViewModel private var sections = [Section]() + private var onDemandStatusObservervationToken: AnyObject? + private var statusObservervationToken: AnyObject? init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer) { self.tunnelsManager = tunnelsManager @@ -41,22 +43,26 @@ class TunnelDetailTableViewController: UITableViewController { required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + deinit { + onDemandStatusObservervationToken = nil + statusObservervationToken = nil + } override func viewDidLoad() { super.viewDidLoad() - self.title = tunnelViewModel.interfaceData[.name] - self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editTapped)) + title = tunnelViewModel.interfaceData[.name] + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editTapped)) - self.tableView.estimatedRowHeight = 44 - self.tableView.rowHeight = UITableView.automaticDimension - self.tableView.allowsSelection = false - self.tableView.register(TunnelDetailStatusCell.self) - self.tableView.register(TunnelDetailKeyValueCell.self) - self.tableView.register(TunnelDetailButtonCell.self) - self.tableView.register(TunnelDetailActivateOnDemandCell.self) + tableView.estimatedRowHeight = 44 + tableView.rowHeight = UITableView.automaticDimension + tableView.allowsSelection = false + tableView.register(SwitchCell.self) + tableView.register(KeyValueCell.self) + tableView.register(ButtonCell.self) // State restoration - self.restorationIdentifier = "TunnelDetailVC:\(tunnel.name)" + restorationIdentifier = "TunnelDetailVC:\(tunnel.name)" } private func loadSections() { @@ -76,8 +82,7 @@ class TunnelDetailTableViewController: UITableViewController { present(editNC, animated: true) } - func showConfirmationAlert(message: String, buttonTitle: String, from sourceView: UIView, - onConfirmed: @escaping (() -> Void)) { + func showConfirmationAlert(message: String, buttonTitle: String, from sourceView: UIView, onConfirmed: @escaping (() -> Void)) { let destroyAction = UIAlertAction(title: buttonTitle, style: .destructive) { _ in onConfirmed() } @@ -90,7 +95,7 @@ class TunnelDetailTableViewController: UITableViewController { alert.popoverPresentationController?.sourceView = sourceView alert.popoverPresentationController?.sourceRect = sourceView.bounds - self.present(alert, animated: true, completion: nil) + present(alert, animated: true, completion: nil) } } @@ -100,8 +105,8 @@ extension TunnelDetailTableViewController: TunnelEditTableViewControllerDelegate func tunnelSaved(tunnel: TunnelContainer) { tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration()) loadSections() - self.title = tunnel.name - self.tableView.reloadData() + title = tunnel.name + tableView.reloadData() } func tunnelEditingCancelled() { // Nothing to do @@ -161,8 +166,40 @@ extension TunnelDetailTableViewController { } private func statusCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell: TunnelDetailStatusCell = tableView.dequeueReusableCell(for: indexPath) - cell.tunnel = self.tunnel + let cell: SwitchCell = tableView.dequeueReusableCell(for: indexPath) + + let statusUpdate: (SwitchCell, TunnelStatus) -> Void = { cell, status in + let text: String + switch status { + case .inactive: + text = "Inactive" + case .activating: + text = "Activating" + case .active: + text = "Active" + case .deactivating: + text = "Deactivating" + case .reasserting: + text = "Reactivating" + case .restarting: + text = "Restarting" + case .waiting: + text = "Waiting" + } + cell.textLabel?.text = text + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak cell] in + cell?.switchView.isOn = !(status == .deactivating || status == .inactive) + cell?.switchView.isUserInteractionEnabled = (status == .inactive || status == .active) + } + cell.isEnabled = status == .active || status == .inactive + } + + statusUpdate(cell, tunnel.status) + statusObservervationToken = tunnel.observe(\.status) { [weak cell] tunnel, _ in + guard let cell = cell else { return } + statusUpdate(cell, tunnel.status) + } + cell.onSwitchToggled = { [weak self] isOn in guard let self = self else { return } if isOn { @@ -176,7 +213,7 @@ extension TunnelDetailTableViewController { private func interfaceCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { let field = tunnelViewModel.interfaceData.filterFieldsWithValueOrControl(interfaceFields: interfaceFields)[indexPath.row] - let cell: TunnelDetailKeyValueCell = tableView.dequeueReusableCell(for: indexPath) + let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath) cell.key = field.rawValue cell.value = tunnelViewModel.interfaceData[field] return cell @@ -184,20 +221,24 @@ extension TunnelDetailTableViewController { private func peerCell(for tableView: UITableView, at indexPath: IndexPath, with peerData: TunnelViewModel.PeerData) -> UITableViewCell { let field = peerData.filterFieldsWithValueOrControl(peerFields: peerFields)[indexPath.row] - let cell: TunnelDetailKeyValueCell = tableView.dequeueReusableCell(for: indexPath) + let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath) cell.key = field.rawValue cell.value = peerData[field] return cell } private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell: TunnelDetailActivateOnDemandCell = tableView.dequeueReusableCell(for: indexPath) - cell.tunnel = self.tunnel + let cell: KeyValueCell = tableView.dequeueReusableCell(for: indexPath) + cell.key = "Activate on demand" + cell.value = TunnelViewModel.activateOnDemandDetailText(for: tunnel.activateOnDemandSetting()) + onDemandStatusObservervationToken = tunnel.observe(\.isActivateOnDemandEnabled) { [weak cell] tunnel, _ in + cell?.value = TunnelViewModel.activateOnDemandDetailText(for: tunnel.activateOnDemandSetting()) + } return cell } private func deleteConfigurationCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell: TunnelDetailButtonCell = tableView.dequeueReusableCell(for: indexPath) + let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath) cell.buttonText = "Delete tunnel" cell.hasDestructiveAction = true cell.onTapped = { [weak self] in diff --git a/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelListCell.swift b/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelListCell.swift index f0a16bf..14a7194 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelListCell.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelListCell.swift @@ -47,14 +47,14 @@ class TunnelListCell: UITableViewCell { NSLayoutConstraint.activate([ statusSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), contentView.rightAnchor.constraint(equalTo: statusSwitch.rightAnchor) - ]) + ]) contentView.addSubview(busyIndicator) busyIndicator.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ busyIndicator.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), statusSwitch.leftAnchor.constraint(equalToSystemSpacingAfter: busyIndicator.rightAnchor, multiplier: 1) - ]) + ]) contentView.addSubview(nameLabel) nameLabel.translatesAutoresizingMaskIntoConstraints = false @@ -66,7 +66,7 @@ class TunnelListCell: UITableViewCell { nameLabel.leftAnchor.constraint(equalToSystemSpacingAfter: contentView.layoutMarginsGuide.leftAnchor, multiplier: 1), busyIndicator.leftAnchor.constraint(equalToSystemSpacingAfter: nameLabel.rightAnchor, multiplier: 1), bottomAnchorConstraint - ]) + ]) accessoryType = .disclosureIndicator diff --git a/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelsListTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelsListTableViewController.swift index eda09af..0188c62 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelsListTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelList/TunnelsListTableViewController.swift @@ -96,7 +96,8 @@ class TunnelsListTableViewController: UIViewController { } @objc func addButtonTapped(sender: AnyObject) { - if self.tunnelsManager == nil { return } // Do nothing until we've loaded the tunnels + guard tunnelsManager != nil else { return } + let alert = UIAlertController(title: "", message: "Add a new WireGuard tunnel", preferredStyle: .actionSheet) let importFileAction = UIAlertAction(title: "Create from file or archive", style: .default) { [weak self] _ in self?.presentViewControllerForFileImport() @@ -125,29 +126,30 @@ class TunnelsListTableViewController: UIViewController { alert.popoverPresentationController?.sourceView = sender alert.popoverPresentationController?.sourceRect = sender.bounds } - self.present(alert, animated: true, completion: nil) + present(alert, animated: true, completion: nil) } @objc func settingsButtonTapped(sender: UIBarButtonItem!) { - if self.tunnelsManager == nil { return } // Do nothing until we've loaded the tunnels + guard tunnelsManager != nil else { return } + let settingsVC = SettingsTableViewController(tunnelsManager: tunnelsManager) let settingsNC = UINavigationController(rootViewController: settingsVC) settingsNC.modalPresentationStyle = .formSheet - self.present(settingsNC, animated: true) + present(settingsNC, animated: true) } func presentViewControllerForTunnelCreation(tunnelsManager: TunnelsManager, tunnelConfiguration: TunnelConfiguration?) { let editVC = TunnelEditTableViewController(tunnelsManager: tunnelsManager, tunnelConfiguration: tunnelConfiguration) let editNC = UINavigationController(rootViewController: editVC) editNC.modalPresentationStyle = .formSheet - self.present(editNC, animated: true) + present(editNC, animated: true) } func presentViewControllerForFileImport() { let documentTypes = ["com.wireguard.config.quick", String(kUTTypeText), String(kUTTypeZipArchive)] let filePicker = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import) filePicker.delegate = self - self.present(filePicker, animated: true) + present(filePicker, animated: true) } func presentViewControllerForScanningQRCode() { @@ -155,7 +157,7 @@ class TunnelsListTableViewController: UIViewController { scanQRCodeVC.delegate = self let scanQRCodeNC = UINavigationController(rootViewController: scanQRCodeVC) scanQRCodeNC.modalPresentationStyle = .fullScreen - self.present(scanQRCodeNC, animated: true) + present(scanQRCodeNC, animated: true) } func importFromFile(url: URL, completionHandler: (() -> Void)?) { diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift index e2588f8..0bc7915 100644 --- a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift @@ -33,7 +33,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { let activationAttemptId = options?["activationAttemptId"] as? String let errorNotifier = ErrorNotifier(activationAttemptId: activationAttemptId, tunnelProvider: self) - guard let tunnelProviderProtocol = self.protocolConfiguration as? NETunnelProviderProtocol, + guard let tunnelProviderProtocol = protocolConfiguration as? NETunnelProviderProtocol, let tunnelConfiguration = tunnelProviderProtocol.tunnelConfiguration() else { errorNotifier.notify(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid) startTunnelCompletionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid) |