diff --git a/WireGuard/Shared/LegacyConfigMigration.swift b/WireGuard/Shared/LegacyConfigMigration.swift index e7588a2..6d27fa5 100644 --- a/WireGuard/Shared/LegacyConfigMigration.swift +++ b/WireGuard/Shared/LegacyConfigMigration.swift @@ -7,17 +7,17 @@ import NetworkExtension protocol LegacyModel: Decodable { associatedtype Model - + var migrated: Model { get } } struct LegacyDNSServer: LegacyModel { let address: IPAddress - + var migrated: DNSServer { return DNSServer(address: address) } - + init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() var data = try container.decode(Data.self) @@ -33,7 +33,7 @@ struct LegacyDNSServer: LegacyModel { } address = ipAddress } - + enum DecodingError: Error { case invalidData } @@ -48,11 +48,11 @@ extension Array where Element == LegacyDNSServer { struct LegacyEndpoint: LegacyModel { let host: Network.NWEndpoint.Host let port: Network.NWEndpoint.Port - + var migrated: Endpoint { return Endpoint(host: host, port: port) } - + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let endpointString = try container.decode(String.self) @@ -81,7 +81,7 @@ struct LegacyEndpoint: LegacyModel { host = NWEndpoint.Host(hostString) port = endpointPort } - + enum DecodingError: Error { case invalidData } @@ -94,7 +94,7 @@ struct LegacyInterfaceConfiguration: LegacyModel { let listenPort: UInt16? let mtu: UInt16? let dns: [LegacyDNSServer] - + var migrated: InterfaceConfiguration { var interface = InterfaceConfiguration(name: name, privateKey: privateKey) interface.addresses = addresses.migrated @@ -108,11 +108,11 @@ struct LegacyInterfaceConfiguration: LegacyModel { struct LegacyIPAddressRange: LegacyModel { let address: IPAddress let networkPrefixLength: UInt8 - + var migrated: IPAddressRange { return IPAddressRange(address: address, networkPrefixLength: networkPrefixLength) } - + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() var data = try container.decode(Data.self) @@ -127,7 +127,7 @@ struct LegacyIPAddressRange: LegacyModel { guard let ipAddress = ipAddressFromData else { throw DecodingError.invalidData } address = ipAddress } - + enum DecodingError: Error { case invalidData } @@ -145,7 +145,7 @@ struct LegacyPeerConfiguration: LegacyModel { let allowedIPs: [LegacyIPAddressRange] let endpoint: LegacyEndpoint? let persistentKeepAlive: UInt16? - + var migrated: PeerConfiguration { var configuration = PeerConfiguration(publicKey: publicKey) configuration.preSharedKey = preSharedKey @@ -165,14 +165,14 @@ extension Array where Element == LegacyPeerConfiguration { final class LegacyTunnelConfiguration: LegacyModel { let interface: LegacyInterfaceConfiguration let peers: [LegacyPeerConfiguration] - + var migrated: TunnelConfiguration { return TunnelConfiguration(interface: interface.migrated, peers: peers.migrated) } } extension NETunnelProviderProtocol { - + @discardableResult func migrateConfigurationIfNeeded() -> Bool { guard let configurationVersion = providerConfiguration?["tunnelConfigurationVersion"] as? Int else { return false } @@ -183,11 +183,11 @@ extension NETunnelProviderProtocol { } return true } - + private func migrateFromConfigurationV1() { guard let serializedTunnelConfiguration = providerConfiguration?["tunnelConfiguration"] as? Data else { return } - guard let configuration = try? JSONDecoder().decode(LegacyTunnelConfiguration.self, from: serializedTunnelConfiguration) else { return } + guard let configuration = try? JSONDecoder().decode(LegacyTunnelConfiguration.self, from: serializedTunnelConfiguration) else { return } providerConfiguration = [Keys.wgQuickConfig.rawValue: configuration.migrated.asWgQuickConfig()] } - + } diff --git a/WireGuard/Shared/Logging/Logger.swift b/WireGuard/Shared/Logging/Logger.swift index 026ec09..f2c0371 100644 --- a/WireGuard/Shared/Logging/Logger.swift +++ b/WireGuard/Shared/Logging/Logger.swift @@ -8,7 +8,7 @@ public class Logger { enum LoggerError: Error { case openFailure } - + static var global: Logger? var log: OpaquePointer diff --git a/WireGuard/Shared/Model/DNSServer.swift b/WireGuard/Shared/Model/DNSServer.swift index 9078b59..710c656 100644 --- a/WireGuard/Shared/Model/DNSServer.swift +++ b/WireGuard/Shared/Model/DNSServer.swift @@ -6,7 +6,7 @@ import Network struct DNSServer { let address: IPAddress - + init(address: IPAddress) { self.address = address } @@ -16,7 +16,7 @@ extension DNSServer { var stringRepresentation: String { return "\(address)" } - + init?(from addressString: String) { if let addr = IPv4Address(addressString) { address = addr diff --git a/WireGuard/Shared/Model/Endpoint.swift b/WireGuard/Shared/Model/Endpoint.swift index b29a5a8..03de131 100644 --- a/WireGuard/Shared/Model/Endpoint.swift +++ b/WireGuard/Shared/Model/Endpoint.swift @@ -7,7 +7,7 @@ import Network struct Endpoint { let host: NWEndpoint.Host let port: NWEndpoint.Port - + init(host: NWEndpoint.Host, port: NWEndpoint.Port) { self.host = host self.port = port @@ -25,7 +25,7 @@ extension Endpoint { return "[\(address)]:\(port)" } } - + init?(from string: String) { // Separation of host and port is based on 'parse_endpoint' function in // https://git.zx2c4.com/WireGuard/tree/src/tools/config.c diff --git a/WireGuard/Shared/Model/IPAddressRange.swift b/WireGuard/Shared/Model/IPAddressRange.swift index 28f3d00..7d3e5ec 100644 --- a/WireGuard/Shared/Model/IPAddressRange.swift +++ b/WireGuard/Shared/Model/IPAddressRange.swift @@ -7,7 +7,7 @@ import Network struct IPAddressRange { let address: IPAddress var networkPrefixLength: UInt8 - + init(address: IPAddress, networkPrefixLength: UInt8) { self.address = address self.networkPrefixLength = networkPrefixLength @@ -18,13 +18,13 @@ extension IPAddressRange { var stringRepresentation: String { return "\(address)/\(networkPrefixLength)" } - + init?(from string: String) { guard let parsed = IPAddressRange.parseAddressString(string) else { return nil } address = parsed.0 networkPrefixLength = parsed.1 } - + private static func parseAddressString(_ string: String) -> (IPAddress, UInt8)? { let endOfIPAddress = string.lastIndex(of: "/") ?? string.endIndex let addressString = String(string[string.startIndex ..< endOfIPAddress]) @@ -36,7 +36,7 @@ extension IPAddressRange { } else { return nil } - + let maxNetworkPrefixLength: UInt8 = address is IPv4Address ? 32 : 128 var networkPrefixLength: UInt8 if endOfIPAddress < string.endIndex { // "/" was located @@ -48,7 +48,7 @@ extension IPAddressRange { } else { networkPrefixLength = maxNetworkPrefixLength } - + return (address, networkPrefixLength) } } diff --git a/WireGuard/Shared/Model/InterfaceConfiguration.swift b/WireGuard/Shared/Model/InterfaceConfiguration.swift index 9094d14..ff804a6 100644 --- a/WireGuard/Shared/Model/InterfaceConfiguration.swift +++ b/WireGuard/Shared/Model/InterfaceConfiguration.swift @@ -10,7 +10,7 @@ struct InterfaceConfiguration { var listenPort: UInt16? var mtu: UInt16? var dns = [DNSServer]() - + init(name: String?, privateKey: Data) { self.name = name self.privateKey = privateKey diff --git a/WireGuard/Shared/Model/PeerConfiguration.swift b/WireGuard/Shared/Model/PeerConfiguration.swift index a113821..2e969e6 100644 --- a/WireGuard/Shared/Model/PeerConfiguration.swift +++ b/WireGuard/Shared/Model/PeerConfiguration.swift @@ -17,7 +17,7 @@ struct PeerConfiguration { var allowedIPs = [IPAddressRange]() var endpoint: Endpoint? var persistentKeepAlive: UInt16? - + init(publicKey: Data) { self.publicKey = publicKey if publicKey.count != TunnelConfiguration.keyLength { diff --git a/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift b/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift index 4f3e122..2f6ea1f 100644 --- a/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift +++ b/WireGuard/Shared/NETunnelProviderProtocol+Extension.swift @@ -6,18 +6,18 @@ import NetworkExtension private var tunnelNameKey: Void? extension NETunnelProviderProtocol { - + enum Keys: String { case wgQuickConfig = "WgQuickConfig" } - + convenience init?(tunnelConfiguration: TunnelConfiguration) { self.init() - + let appId = Bundle.main.bundleIdentifier! providerBundleIdentifier = "\(appId).network-extension" providerConfiguration = [Keys.wgQuickConfig.rawValue: tunnelConfiguration.asWgQuickConfig()] - + let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint } if endpoints.count == 1 { serverAddress = endpoints[0].stringRepresentation @@ -26,14 +26,14 @@ extension NETunnelProviderProtocol { } else { serverAddress = "Multiple endpoints" } - + username = tunnelConfiguration.interface.name } - + func tunnelConfiguration(name: String?) -> TunnelConfiguration? { migrateConfigurationIfNeeded() guard let serializedConfig = providerConfiguration?[Keys.wgQuickConfig.rawValue] as? String else { return nil } return try? TunnelConfiguration(serializedConfig, name: name) } - + } diff --git a/WireGuard/Shared/String+ArrayConversion.swift b/WireGuard/Shared/String+ArrayConversion.swift index 9b69cf4..6a3e794 100644 --- a/WireGuard/Shared/String+ArrayConversion.swift +++ b/WireGuard/Shared/String+ArrayConversion.swift @@ -4,7 +4,7 @@ import Foundation extension String { - + func splitToArray(separator: Character = ",", trimmingCharacters: CharacterSet? = nil) -> [String] { return split(separator: separator) .map { @@ -15,11 +15,11 @@ extension String { } } } - + } extension Optional where Wrapped == String { - + func splitToArray(separator: Character = ",", trimmingCharacters: CharacterSet? = nil) -> [String] { switch self { case .none: @@ -28,5 +28,5 @@ extension Optional where Wrapped == String { return wrapped.splitToArray(separator: separator, trimmingCharacters: trimmingCharacters) } } - + } diff --git a/WireGuard/Shared/TunnelConfiguration+WgQuickConfig.swift b/WireGuard/Shared/TunnelConfiguration+WgQuickConfig.swift index 9121426..96b5413 100644 --- a/WireGuard/Shared/TunnelConfiguration+WgQuickConfig.swift +++ b/WireGuard/Shared/TunnelConfiguration+WgQuickConfig.swift @@ -4,13 +4,13 @@ import Foundation extension TunnelConfiguration { - + enum ParserState { case inInterfaceSection case inPeerSection case notInASection } - + enum ParseError: Error { case invalidLine(_ line: String.SubSequence) case noInterface @@ -19,17 +19,17 @@ extension TunnelConfiguration { case multiplePeersWithSamePublicKey case invalidPeer } - + //swiftlint:disable:next cyclomatic_complexity function_body_length convenience init(_ wgQuickConfig: String, name: String?) throws { var interfaceConfiguration: InterfaceConfiguration? var peerConfigurations = [PeerConfiguration]() - + let lines = wgQuickConfig.split(separator: "\n") - + var parserState = ParserState.notInASection var attributes = [String: String]() - + for (lineIndex, line) in lines.enumerated() { var trimmedLine: String if let commentRange = line.range(of: "#") { @@ -37,12 +37,12 @@ extension TunnelConfiguration { } else { trimmedLine = String(line) } - + trimmedLine = trimmedLine.trimmingCharacters(in: .whitespaces) - + guard !trimmedLine.isEmpty else { continue } let lowercasedLine = line.lowercased() - + if let equalsIndex = line.firstIndex(of: "=") { // Line contains an attribute let key = line[..(peerPublicKeysArray) if peerPublicKeysArray.count != peerPublicKeysSet.count { throw ParseError.multiplePeersWithSamePublicKey } - + if let interfaceConfiguration = interfaceConfiguration { self.init(interface: interfaceConfiguration, peers: peerConfigurations) } else { throw ParseError.noInterface } } - + func asWgQuickConfig() -> String { var output = "[Interface]\n" output.append("PrivateKey = \(interface.privateKey.base64EncodedString())\n") @@ -110,7 +110,7 @@ extension TunnelConfiguration { if let mtu = interface.mtu { output.append("MTU = \(mtu)\n") } - + for peer in peers { output.append("\n[Peer]\n") output.append("PublicKey = \(peer.publicKey.base64EncodedString())\n") @@ -128,10 +128,10 @@ extension TunnelConfiguration { output.append("PersistentKeepalive = \(persistentKeepAlive)\n") } } - + return output } - + //swiftlint:disable:next cyclomatic_complexity private static func collate(interfaceAttributes attributes: [String: String], name: String?) -> InterfaceConfiguration? { // required wg fields @@ -166,7 +166,7 @@ extension TunnelConfiguration { } return interface } - + //swiftlint:disable:next cyclomatic_complexity private static func collate(peerAttributes attributes: [String: String]) -> PeerConfiguration? { // required wg fields @@ -196,5 +196,5 @@ extension TunnelConfiguration { } return peer } - + } diff --git a/WireGuard/WireGuard/Tunnel/TunnelErrors.swift b/WireGuard/WireGuard/Tunnel/TunnelErrors.swift index 9b2b574..77b0410 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelErrors.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelErrors.swift @@ -53,7 +53,7 @@ enum TunnelsManagerActivationAttemptError: WireGuardAppError { enum TunnelsManagerActivationError: WireGuardAppError { case activationFailed(wasOnDemandEnabled: Bool) case activationFailedWithExtensionError(title: String, message: String, wasOnDemandEnabled: Bool) - + var alertText: AlertText { switch self { case .activationFailed(let wasOnDemandEnabled): diff --git a/WireGuard/WireGuard/Tunnel/TunnelStatus.swift b/WireGuard/WireGuard/Tunnel/TunnelStatus.swift index 9f03417..cfa1307 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelStatus.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelStatus.swift @@ -12,7 +12,7 @@ import NetworkExtension 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: diff --git a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift index 903dfad..5fa8e7e 100644 --- a/WireGuard/WireGuard/Tunnel/TunnelsManager.swift +++ b/WireGuard/WireGuard/Tunnel/TunnelsManager.swift @@ -41,7 +41,7 @@ class TunnelsManager { completionHandler(.failure(TunnelsManagerError.systemErrorOnListingTunnels(systemError: error))) return } - + let tunnelManagers = managers ?? [] tunnelManagers.forEach { tunnelManager in if (tunnelManager.protocolConfiguration as? NETunnelProviderProtocol)?.migrateConfigurationIfNeeded() == true { @@ -78,9 +78,9 @@ class TunnelsManager { completionHandler(.failure(TunnelsManagerError.systemErrorOnAddTunnel(systemError: error!))) return } - + guard let self = self else { return } - + let tunnel = TunnelContainer(tunnel: tunnelProviderManager) self.tunnels.append(tunnel) self.tunnels.sort { $0.name < $1.name } @@ -126,7 +126,7 @@ class TunnelsManager { tunnelProviderManager.protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration) tunnelProviderManager.localizedDescription = (tunnelConfiguration).interface.name tunnelProviderManager.isEnabled = true - + let isActivatingOnDemand = !tunnelProviderManager.isOnDemandEnabled && activateOnDemandSetting.isActivateOnDemandEnabled activateOnDemandSetting.apply(on: tunnelProviderManager) @@ -137,7 +137,7 @@ class TunnelsManager { return } guard let self = self else { return } - + if isNameChanged { let oldIndex = self.tunnels.firstIndex(of: tunnel)! self.tunnels.sort { $0.name < $1.name } @@ -351,11 +351,11 @@ class TunnelContainer: NSObject { var tunnelConfiguration: TunnelConfiguration? { return (tunnelProvider.protocolConfiguration as? NETunnelProviderProtocol)?.tunnelConfiguration(name: tunnelProvider.localizedDescription) } - + var activateOnDemandSetting: ActivateOnDemandSetting { return ActivateOnDemandSetting(from: tunnelProvider) } - + init(tunnel: NETunnelProviderManager) { name = tunnel.localizedDescription ?? "Unnamed" let status = TunnelStatus(from: tunnel.connection.status) diff --git a/WireGuard/WireGuard/UI/iOS/View/BorderedTextButton.swift b/WireGuard/WireGuard/UI/iOS/View/BorderedTextButton.swift index ab6dcc5..b1951e4 100644 --- a/WireGuard/WireGuard/UI/iOS/View/BorderedTextButton.swift +++ b/WireGuard/WireGuard/UI/iOS/View/BorderedTextButton.swift @@ -10,42 +10,42 @@ class BorderedTextButton: UIView { button.titleLabel?.adjustsFontForContentSizeCategory = true return button }() - + override var intrinsicContentSize: CGSize { let buttonSize = button.intrinsicContentSize return CGSize(width: buttonSize.width + 32, height: buttonSize.height + 16) } - + var title: String { get { return button.title(for: .normal) ?? "" } set(value) { button.setTitle(value, for: .normal) } } - + var onTapped: (() -> Void)? - + init() { super.init(frame: CGRect.zero) - + layer.borderWidth = 1 layer.cornerRadius = 5 layer.borderColor = button.tintColor.cgColor - + addSubview(button) button.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ button.centerXAnchor.constraint(equalTo: centerXAnchor), button.centerYAnchor.constraint(equalTo: centerYAnchor) ]) - + button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + @objc func buttonTapped() { onTapped?() } - + } diff --git a/WireGuard/WireGuard/UI/iOS/View/ButtonCell.swift b/WireGuard/WireGuard/UI/iOS/View/ButtonCell.swift index aff17ee..5d9ab92 100644 --- a/WireGuard/WireGuard/UI/iOS/View/ButtonCell.swift +++ b/WireGuard/WireGuard/UI/iOS/View/ButtonCell.swift @@ -13,20 +13,20 @@ class ButtonCell: UITableViewCell { set(value) { button.tintColor = value ? .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([ @@ -34,18 +34,18 @@ class ButtonCell: UITableViewCell { 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 = "" diff --git a/WireGuard/WireGuard/UI/iOS/View/CheckmarkCell.swift b/WireGuard/WireGuard/UI/iOS/View/CheckmarkCell.swift index db4b6c9..77cd501 100644 --- a/WireGuard/WireGuard/UI/iOS/View/CheckmarkCell.swift +++ b/WireGuard/WireGuard/UI/iOS/View/CheckmarkCell.swift @@ -13,16 +13,16 @@ class CheckmarkCell: UITableViewCell { accessoryType = isChecked ? .checkmark : .none } } - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { isChecked = false super.init(style: .default, reuseIdentifier: reuseIdentifier) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func prepareForReuse() { super.prepareForReuse() message = "" diff --git a/WireGuard/WireGuard/UI/iOS/View/KeyValueCell.swift b/WireGuard/WireGuard/UI/iOS/View/KeyValueCell.swift index a456de1..81a1712 100644 --- a/WireGuard/WireGuard/UI/iOS/View/KeyValueCell.swift +++ b/WireGuard/WireGuard/UI/iOS/View/KeyValueCell.swift @@ -4,7 +4,7 @@ import UIKit class KeyValueCell: UITableViewCell { - + let keyLabel: UILabel = { let keyLabel = UILabel() keyLabel.font = UIFont.preferredFont(forTextStyle: .body) @@ -13,7 +13,7 @@ class KeyValueCell: UITableViewCell { keyLabel.textAlignment = .left return keyLabel }() - + let valueLabelScrollView: UIScrollView = { let scrollView = UIScrollView(frame: .zero) scrollView.isDirectionalLockEnabled = true @@ -21,7 +21,7 @@ class KeyValueCell: UITableViewCell { scrollView.showsVerticalScrollIndicator = false return scrollView }() - + let valueTextField: UITextField = { let valueTextField = UITextField() valueTextField.textAlignment = .right @@ -34,7 +34,7 @@ class KeyValueCell: UITableViewCell { valueTextField.textColor = .gray return valueTextField }() - + var copyableGesture = true var key: String { @@ -53,7 +53,7 @@ class KeyValueCell: UITableViewCell { get { return valueTextField.keyboardType } set(value) { valueTextField.keyboardType = value } } - + var isValueValid = true { didSet { if isValueValid { @@ -63,26 +63,26 @@ class KeyValueCell: UITableViewCell { } } } - + var isStackedHorizontally = false var isStackedVertically = false var contentSizeBasedConstraints = [NSLayoutConstraint]() - + var onValueChanged: ((String) -> Void)? var onValueBeingEdited: ((String) -> Void)? - + private var textFieldValueOnBeginEditing: String = "" - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - + contentView.addSubview(keyLabel) keyLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ keyLabel.leftAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leftAnchor), keyLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 0.5) ]) - + valueTextField.delegate = self valueLabelScrollView.addSubview(valueTextField) valueTextField.translatesAutoresizingMaskIntoConstraints = false @@ -96,31 +96,31 @@ class KeyValueCell: UITableViewCell { let expandToFitValueLabelConstraint = NSLayoutConstraint(item: valueTextField, attribute: .width, relatedBy: .equal, toItem: valueLabelScrollView, attribute: .width, multiplier: 1, constant: 0) expandToFitValueLabelConstraint.priority = .defaultLow + 1 expandToFitValueLabelConstraint.isActive = true - + contentView.addSubview(valueLabelScrollView) - + contentView.addSubview(valueLabelScrollView) valueLabelScrollView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ valueLabelScrollView.rightAnchor.constraint(equalTo: contentView.layoutMarginsGuide.rightAnchor), contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: valueLabelScrollView.bottomAnchor, multiplier: 0.5) ]) - + keyLabel.setContentCompressionResistancePriority(.defaultHigh + 1, for: .horizontal) keyLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) valueLabelScrollView.setContentHuggingPriority(.defaultLow, for: .horizontal) - + let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:))) addGestureRecognizer(gestureRecognizer) isUserInteractionEnabled = true - + configureForContentSize() } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func configureForContentSize() { var constraints = [NSLayoutConstraint]() if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { @@ -152,13 +152,13 @@ class KeyValueCell: UITableViewCell { contentSizeBasedConstraints = constraints } } - + @objc func handleTapGesture(_ recognizer: UIGestureRecognizer) { if !copyableGesture { return } guard recognizer.state == .recognized else { return } - + if let recognizerView = recognizer.view, let recognizerSuperView = recognizerView.superview, recognizerView.becomeFirstResponder() { let menuController = UIMenuController.shared @@ -166,19 +166,19 @@ class KeyValueCell: UITableViewCell { menuController.setMenuVisible(true, animated: true) } } - + override var canBecomeFirstResponder: Bool { return true } - + override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { return (action == #selector(UIResponderStandardEditActions.copy(_:))) } - + override func copy(_ sender: Any?) { UIPasteboard.general.string = valueTextField.text } - + override func prepareForReuse() { super.prepareForReuse() copyableGesture = true @@ -194,18 +194,18 @@ class KeyValueCell: UITableViewCell { } extension KeyValueCell: UITextFieldDelegate { - + func textFieldDidBeginEditing(_ textField: UITextField) { textFieldValueOnBeginEditing = textField.text ?? "" isValueValid = true } - + func textFieldDidEndEditing(_ textField: UITextField) { let isModified = textField.text ?? "" != textFieldValueOnBeginEditing guard isModified else { return } onValueChanged?(textField.text ?? "") } - + 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) @@ -213,5 +213,5 @@ extension KeyValueCell: UITextFieldDelegate { } return true } - + } diff --git a/WireGuard/WireGuard/UI/iOS/View/SwitchCell.swift b/WireGuard/WireGuard/UI/iOS/View/SwitchCell.swift index d0c29aa..68939a7 100644 --- a/WireGuard/WireGuard/UI/iOS/View/SwitchCell.swift +++ b/WireGuard/WireGuard/UI/iOS/View/SwitchCell.swift @@ -19,14 +19,14 @@ class SwitchCell: UITableViewCell { textLabel?.textColor = value ? .black : .gray } } - + var onSwitchToggled: ((Bool) -> Void)? - + let switchView = UISwitch() - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: .default, reuseIdentifier: reuseIdentifier) - + accessoryView = switchView switchView.addTarget(self, action: #selector(switchToggled), for: .valueChanged) } @@ -34,11 +34,11 @@ class SwitchCell: UITableViewCell { required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + @objc func switchToggled() { onSwitchToggled?(switchView.isOn) } - + override func prepareForReuse() { super.prepareForReuse() isEnabled = true diff --git a/WireGuard/WireGuard/UI/iOS/View/TunnelEditKeyValueCell.swift b/WireGuard/WireGuard/UI/iOS/View/TunnelEditKeyValueCell.swift index fc9595f..57132d6 100644 --- a/WireGuard/WireGuard/UI/iOS/View/TunnelEditKeyValueCell.swift +++ b/WireGuard/WireGuard/UI/iOS/View/TunnelEditKeyValueCell.swift @@ -4,40 +4,40 @@ import UIKit class TunnelEditKeyValueCell: KeyValueCell { - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - + keyLabel.textAlignment = .right valueTextField.textAlignment = .left - + let widthRatioConstraint = NSLayoutConstraint(item: keyLabel, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 0.4, constant: 0) // In case the key doesn't fit into 0.4 * width, // set a CR priority > the 0.4-constraint's priority. widthRatioConstraint.priority = .defaultHigh + 1 widthRatioConstraint.isActive = true } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } class TunnelEditEditableKeyValueCell: TunnelEditKeyValueCell { - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - + copyableGesture = false valueTextField.textColor = .black valueTextField.isEnabled = true valueLabelScrollView.isScrollEnabled = false valueTextField.widthAnchor.constraint(equalTo: valueLabelScrollView.widthAnchor).isActive = true } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/WireGuard/WireGuard/UI/iOS/View/TunnelListCell.swift b/WireGuard/WireGuard/UI/iOS/View/TunnelListCell.swift index d13346a..2965476 100644 --- a/WireGuard/WireGuard/UI/iOS/View/TunnelListCell.swift +++ b/WireGuard/WireGuard/UI/iOS/View/TunnelListCell.swift @@ -19,7 +19,7 @@ class TunnelListCell: UITableViewCell { } } var onSwitchToggled: ((Bool) -> Void)? - + let nameLabel: UILabel = { let nameLabel = UILabel() nameLabel.font = UIFont.preferredFont(forTextStyle: .body) @@ -27,35 +27,35 @@ class TunnelListCell: UITableViewCell { nameLabel.numberOfLines = 0 return nameLabel }() - + let busyIndicator: UIActivityIndicatorView = { let busyIndicator = UIActivityIndicatorView(style: .gray) busyIndicator.hidesWhenStopped = true return busyIndicator }() - + let statusSwitch = UISwitch() - + private var statusObservationToken: AnyObject? private var nameObservationToken: AnyObject? - + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - + contentView.addSubview(statusSwitch) statusSwitch.translatesAutoresizingMaskIntoConstraints = false 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 nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) @@ -67,16 +67,16 @@ class TunnelListCell: UITableViewCell { busyIndicator.leftAnchor.constraint(equalToSystemSpacingAfter: nameLabel.rightAnchor, multiplier: 1), bottomAnchorConstraint ]) - + accessoryType = .disclosureIndicator - + statusSwitch.addTarget(self, action: #selector(switchToggled), for: .valueChanged) } - + @objc func switchToggled() { onSwitchToggled?(statusSwitch.isOn) } - + private func update(from status: TunnelStatus?) { guard let status = status else { reset() @@ -93,17 +93,17 @@ class TunnelListCell: UITableViewCell { } } } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + private func reset() { statusSwitch.isOn = false statusSwitch.isUserInteractionEnabled = false busyIndicator.stopAnimating() } - + override func prepareForReuse() { super.prepareForReuse() reset() diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift index 426e053..58f8611 100644 --- a/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift @@ -58,12 +58,12 @@ class SettingsTableViewController: UITableViewController { override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() 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) - + let imageAspectRatio = logo.intrinsicContentSize.width / logo.intrinsicContentSize.height - + var height = tableView.estimatedRowHeight * 1.5 var width = height * imageAspectRatio let maxWidth = view.bounds.size.width - max(tableView.layoutMargins.left + tableView.layoutMargins.right, 20) @@ -71,11 +71,11 @@ class SettingsTableViewController: UITableViewController { width = maxWidth height = width / imageAspectRatio } - + let needsReload = height != logo.frame.height - + logo.frame = CGRect(x: (view.bounds.size.width - width) / 2, y: fullHeight - height, width: width, height: height) - + if needsReload { tableView.tableFooterView = logo } diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift index 8378311..187f7fd 100644 --- a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift @@ -43,7 +43,7 @@ class TunnelDetailTableViewController: UITableViewController { required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + deinit { onDemandStatusObservationToken = nil statusObservationToken = nil @@ -166,7 +166,7 @@ extension TunnelDetailTableViewController { private func statusCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { let cell: SwitchCell = tableView.dequeueReusableCell(for: indexPath) - + let statusUpdate: (SwitchCell, TunnelStatus) -> Void = { cell, status in let text: String switch status { @@ -192,13 +192,13 @@ extension TunnelDetailTableViewController { } cell.isEnabled = status == .active || status == .inactive } - + statusUpdate(cell, tunnel.status) statusObservationToken = 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 { diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelsListTableViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelsListTableViewController.swift index 6dd8e9c..77952c8 100644 --- a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelsListTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelsListTableViewController.swift @@ -17,27 +17,27 @@ class TunnelsListTableViewController: UIViewController { tableView.register(TunnelListCell.self) return tableView }() - + let centeredAddButton: BorderedTextButton = { let button = BorderedTextButton() button.title = tr("tunnelsListCenteredAddTunnelButtonTitle") button.isHidden = true return button }() - + let busyIndicator: UIActivityIndicatorView = { let busyIndicator = UIActivityIndicatorView(style: .gray) busyIndicator.hidesWhenStopped = true return busyIndicator }() - + override func loadView() { view = UIView() view.backgroundColor = .white - + tableView.dataSource = self tableView.delegate = self - + view.addSubview(tableView) tableView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ @@ -53,22 +53,22 @@ class TunnelsListTableViewController: UIViewController { busyIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor), busyIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) - + view.addSubview(centeredAddButton) centeredAddButton.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ centeredAddButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), centeredAddButton.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) - + centeredAddButton.onTapped = { [weak self] in guard let self = self else { return } self.addButtonTapped(sender: self.centeredAddButton) } - + busyIndicator.startAnimating() } - + override func viewDidLoad() { super.viewDidLoad() @@ -82,7 +82,7 @@ class TunnelsListTableViewController: UIViewController { func setTunnelsManager(tunnelsManager: TunnelsManager) { self.tunnelsManager = tunnelsManager tunnelsManager.tunnelsListDelegate = self - + busyIndicator.stopAnimating() tableView.reloadData() centeredAddButton.isHidden = tunnelsManager.numberOfTunnels() > 0 @@ -96,7 +96,7 @@ class TunnelsListTableViewController: UIViewController { @objc func addButtonTapped(sender: AnyObject) { guard tunnelsManager != nil else { return } - + let alert = UIAlertController(title: "", message: tr("addTunnelMenuHeader"), preferredStyle: .actionSheet) let importFileAction = UIAlertAction(title: tr("addTunnelMenuImportFile"), style: .default) { [weak self] _ in self?.presentViewControllerForFileImport() @@ -129,7 +129,7 @@ class TunnelsListTableViewController: UIViewController { @objc func settingsButtonTapped(sender: UIBarButtonItem) { guard tunnelsManager != nil else { return } - + let settingsVC = SettingsTableViewController(tunnelsManager: tunnelsManager) let settingsNC = UINavigationController(rootViewController: settingsVC) settingsNC.modalPresentationStyle = .formSheet diff --git a/WireGuard/WireGuard/WireGuardAppError.swift b/WireGuard/WireGuard/WireGuardAppError.swift index 8b725d7..7f80240 100644 --- a/WireGuard/WireGuard/WireGuardAppError.swift +++ b/WireGuard/WireGuard/WireGuardAppError.swift @@ -3,6 +3,6 @@ protocol WireGuardAppError: Error { typealias AlertText = (title: String, message: String) - + var alertText: AlertText { get } } diff --git a/WireGuard/WireGuardNetworkExtension/DNSResolver.swift b/WireGuard/WireGuardNetworkExtension/DNSResolver.swift index 3929862..0a76c20 100644 --- a/WireGuard/WireGuardNetworkExtension/DNSResolver.swift +++ b/WireGuard/WireGuardNetworkExtension/DNSResolver.swift @@ -62,7 +62,7 @@ class DNSResolver { extension DNSResolver { // Based on DNS resolution code by Jason Donenfeld // in parse_endpoint() in src/tools/config.c in the WireGuard codebase - + //swiftlint:disable:next cyclomatic_complexity private static func resolveSync(endpoint: Endpoint) -> Endpoint? { switch endpoint.host { diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift index b2df440..df5dd90 100644 --- a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift @@ -14,7 +14,7 @@ enum PacketTunnelProviderError: Error { } class PacketTunnelProvider: NEPacketTunnelProvider { - + private var wgHandle: Int32? private var networkMonitor: NWPathMonitor? private var lastFirstInterface: NWInterface?