diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 00000000..8377b8ff --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,10 @@ +included: + - Passepartout +disabled_rules: + - cyclomatic_complexity + - file_length + - force_cast + - identifier_name + - line_length + - nesting + - todo diff --git a/Config.xcconfig b/Config.xcconfig index 5f5ab3ee..723c0fcb 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -32,8 +32,9 @@ CFG_MAC_ID = com.algoritmico.ios.PassepartoutMac CFG_LAUNCHER_ID = com.algoritmico.ios.PassepartoutLauncher CFG_GROUP_ID = com.algoritmico.Passepartout CFG_APPSTORE_ID = 1433648537 -CFG_COPYRIGHT = Copyright © 2022 Davide De Rosa. All rights reserved. +CFG_COPYRIGHT = Copyright © 2023 Davide De Rosa. All rights reserved. PATH = $(PATH):/opt/homebrew/bin:/usr/local/bin:/usr/local/go/bin +CUSTOM_SCRIPT_PATH = $(PATH) #include? "Secret.xcconfig" diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index db721583..b08a7a4c 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -1314,7 +1314,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + shellScript = "PATH=$CUSTOM_SCRIPT_PATH\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; 0EADDC7227F0677F0093E303 /* Copy Core Data codegen */ = { isa = PBXShellScriptBuildPhase; diff --git a/Passepartout/App/Constants/Theme.swift b/Passepartout/App/Constants/Theme.swift index 47dcd21d..a8fcc54f 100644 --- a/Passepartout/App/Constants/Theme.swift +++ b/Passepartout/App/Constants/Theme.swift @@ -418,15 +418,9 @@ extension View { } func themeSaveButtonLabel() -> some View { -// themeCheckmarkImage.asSystemImage Text(L10n.Global.Strings.save) } -// func themeDoneButtonLabel() -> some View { -//// themeCheckmarkImage.asSystemImage -// Text(L10n.Global.Strings.ok) -// } - func themeTextPicker(_ title: String, selection: Binding, values: [T], description: @escaping (T) -> String) -> some View { StyledPicker(title: title, selection: selection, values: values) { Text(description($0)) diff --git a/Passepartout/App/Extensions/PassepartoutProviders+Extensions.swift b/Passepartout/App/Extensions/PassepartoutProviders+Extensions.swift index 1569d224..bede367e 100644 --- a/Passepartout/App/Extensions/PassepartoutProviders+Extensions.swift +++ b/Passepartout/App/Extensions/PassepartoutProviders+Extensions.swift @@ -31,11 +31,11 @@ extension ProviderMetadata: Identifiable, Comparable, Hashable { name } - public static func ==(lhs: Self, rhs: Self) -> Bool { + public static func == (lhs: Self, rhs: Self) -> Bool { lhs.name == rhs.name } - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { lhs.fullName.lowercased() < rhs.fullName.lowercased() } @@ -45,32 +45,32 @@ extension ProviderMetadata: Identifiable, Comparable, Hashable { } extension ProviderCategory: Comparable { - public static func ==(lhs: Self, rhs: Self) -> Bool { + public static func == (lhs: Self, rhs: Self) -> Bool { lhs.name.lowercased() == rhs.name.lowercased() } - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { lhs.name.lowercased() < rhs.name.lowercased() } } extension ProviderLocation: Comparable { - public static func ==(lhs: Self, rhs: Self) -> Bool { + public static func == (lhs: Self, rhs: Self) -> Bool { lhs.countryCode == rhs.countryCode } - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { lhs.localizedCountry < rhs.localizedCountry } } extension ProviderServer: Comparable { - public static func ==(lhs: Self, rhs: Self) -> Bool { + public static func == (lhs: Self, rhs: Self) -> Bool { lhs.id == rhs.id } // "Default" comes first (nil localizedName) - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { guard lhs.localizedName != rhs.localizedName else { guard let li = lhs.serverIndex else { return true @@ -97,11 +97,11 @@ extension ProviderServer: Comparable { } extension ProviderServer.Preset: Comparable { - public static func ==(lhs: Self, rhs: Self) -> Bool { + public static func == (lhs: Self, rhs: Self) -> Bool { lhs.name == rhs.name } - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { lhs.name < rhs.name } } diff --git a/Passepartout/App/Reusable/Binding+Extensions.swift b/Passepartout/App/Reusable/Binding+Extensions.swift index 9ab401f7..580523fc 100644 --- a/Passepartout/App/Reusable/Binding+Extensions.swift +++ b/Passepartout/App/Reusable/Binding+Extensions.swift @@ -25,7 +25,7 @@ import SwiftUI -func ??(lhs: Binding, rhs: T) -> Binding { +func ?? (lhs: Binding, rhs: T) -> Binding { Binding { lhs.wrappedValue ?? rhs } set: { diff --git a/Passepartout/App/Reusable/EditableTextList.swift b/Passepartout/App/Reusable/EditableTextList.swift index 0539d84b..3277e2fa 100644 --- a/Passepartout/App/Reusable/EditableTextList.swift +++ b/Passepartout/App/Reusable/EditableTextList.swift @@ -192,9 +192,9 @@ extension EditableTextList { commit() } - private func onMove(indexSet: IndexSet, to: Int) { + private func onMove(indexSet: IndexSet, to offset: Int) { var mapped = mapping(identifiableElements) - mapped.move(fromOffsets: indexSet, toOffset: to) + mapped.move(fromOffsets: indexSet, toOffset: offset) identifiableElements = mapped commit() } diff --git a/Passepartout/App/Reusable/Shortcut.swift b/Passepartout/App/Reusable/Shortcut.swift index 735fb980..813b88ae 100644 --- a/Passepartout/App/Reusable/Shortcut.swift +++ b/Passepartout/App/Reusable/Shortcut.swift @@ -37,11 +37,11 @@ struct Shortcut: Identifiable, Hashable, Comparable { native.identifier } - static func ==(lhs: Self, rhs: Self) -> Bool { + static func == (lhs: Self, rhs: Self) -> Bool { lhs.phrase == rhs.phrase } - static func <(lhs: Self, rhs: Self) -> Bool { + static func < (lhs: Self, rhs: Self) -> Bool { lhs.phrase < rhs.phrase } diff --git a/Passepartout/App/Reusable/Validators.swift b/Passepartout/App/Reusable/Validators.swift index 71ea2b17..ff7904d7 100644 --- a/Passepartout/App/Reusable/Validators.swift +++ b/Passepartout/App/Reusable/Validators.swift @@ -39,7 +39,7 @@ struct Validators { } static func notNil(_ string: String?) throws { - guard let _ = string else { + guard string != nil else { throw ValidationError.notSet } } @@ -73,7 +73,7 @@ struct Validators { } static func url(_ string: String) throws { - guard let _ = URL(string: string) else { + guard URL(string: string) != nil else { throw ValidationError.url } } diff --git a/Passepartout/App/Views/AddProviderView.swift b/Passepartout/App/Views/AddProviderView.swift index d4a7800a..30ce06b8 100644 --- a/Passepartout/App/Views/AddProviderView.swift +++ b/Passepartout/App/Views/AddProviderView.swift @@ -143,7 +143,7 @@ struct AddProviderView: View { } private func onErrorMessage(_ message: String?, _ scrollProxy: ScrollViewProxy) { - guard let _ = message else { + guard message != nil else { return } scrollToErrorMessage(scrollProxy) diff --git a/Passepartout/App/Views/EndpointAdvancedView+OpenVPN.swift b/Passepartout/App/Views/EndpointAdvancedView+OpenVPN.swift index fe3ea1f8..8e6fb632 100644 --- a/Passepartout/App/Views/EndpointAdvancedView+OpenVPN.swift +++ b/Passepartout/App/Views/EndpointAdvancedView+OpenVPN.swift @@ -320,40 +320,89 @@ extension EndpointAdvancedView.OpenVPNView { } } -extension OpenVPN.Configuration { - var communicationSettings: (cipher: OpenVPN.Cipher?, digest: OpenVPN.Digest?, xor: OpenVPN.XORMethod?)? { +private extension OpenVPN.Configuration { + struct CommunicationOptions { + let cipher: OpenVPN.Cipher? + + let digest: OpenVPN.Digest? + + let xor: OpenVPN.XORMethod? + } + + struct CompressionOptions { + let framing: OpenVPN.CompressionFraming? + + let algorithm: OpenVPN.CompressionAlgorithm? + } + + struct DNSOptions { + let servers: [String] + + let domains: [String] + } + + struct ProxyOptions { + let proxy: Proxy? + + let pac: URL? + + let bypass: [String] + } + + struct OtherOptions { + let keepAlive: TimeInterval? + + let reneg: TimeInterval? + + let randomizeEndpoint: Bool? + + let randomizeHostnames: Bool? + } + + var communicationSettings: CommunicationOptions? { guard cipher != nil || digest != nil || xorMethod != nil else { return nil } - return (cipher, digest, xorMethod) + return .init(cipher: cipher, digest: digest, xor: xorMethod) } - var compressionSettings: (framing: OpenVPN.CompressionFraming?, algorithm: OpenVPN.CompressionAlgorithm?)? { + var compressionSettings: CompressionOptions? { guard compressionFraming != nil || compressionAlgorithm != nil else { return nil } - return (compressionFraming, compressionAlgorithm) + return .init(framing: compressionFraming, algorithm: compressionAlgorithm) } - var dnsSettings: (servers: [String], domains: [String])? { + var dnsSettings: DNSOptions? { guard !(dnsServers?.isEmpty ?? true) || !(searchDomains?.isEmpty ?? true) else { return nil } - return (dnsServers ?? [], searchDomains ?? []) + return .init(servers: dnsServers ?? [], domains: searchDomains ?? []) } - var proxySettings: (proxy: Proxy?, pac: URL?, bypass: [String])? { - guard httpsProxy != nil || httpProxy != nil || proxyAutoConfigurationURL != nil || !(proxyBypassDomains?.isEmpty ?? true) else { + var proxySettings: ProxyOptions? { + guard httpsProxy != nil || httpProxy != nil || + proxyAutoConfigurationURL != nil || !(proxyBypassDomains?.isEmpty ?? true) else { return nil } - return (httpsProxy ?? httpProxy, proxyAutoConfigurationURL, proxyBypassDomains ?? []) + return .init( + proxy: httpsProxy ?? httpProxy, + pac: proxyAutoConfigurationURL, + bypass: proxyBypassDomains ?? [] + ) } - var otherSettings: (keepAlive: TimeInterval?, reneg: TimeInterval?, randomizeEndpoint: Bool?, randomizeHostnames: Bool?)? { - guard keepAliveInterval != nil || renegotiatesAfter != nil || randomizeEndpoint != nil || randomizeHostnames != nil else { + var otherSettings: OtherOptions? { + guard keepAliveInterval != nil || renegotiatesAfter != nil || + randomizeEndpoint != nil || randomizeHostnames != nil else { return nil } - return (keepAliveInterval, renegotiatesAfter, randomizeEndpoint, randomizeHostnames) + return .init( + keepAlive: keepAliveInterval, + reneg: renegotiatesAfter, + randomizeEndpoint: randomizeEndpoint, + randomizeHostnames: randomizeHostnames + ) } } diff --git a/Passepartout/App/Views/EndpointAdvancedView+WireGuard.swift b/Passepartout/App/Views/EndpointAdvancedView+WireGuard.swift index 6c277aef..347944a1 100644 --- a/Passepartout/App/Views/EndpointAdvancedView+WireGuard.swift +++ b/Passepartout/App/Views/EndpointAdvancedView+WireGuard.swift @@ -89,11 +89,17 @@ extension EndpointAdvancedView.WireGuardView { } } -extension WireGuard.Configuration { - var dnsSettings: (servers: [String], domains: [String])? { +private extension WireGuard.Configuration { + struct DNSOptions { + let servers: [String] + + let domains: [String] + } + + var dnsSettings: DNSOptions? { guard !dnsServers.isEmpty || !dnsSearchDomains.isEmpty else { return nil } - return (dnsServers, dnsSearchDomains) + return .init(servers: dnsServers, domains: dnsSearchDomains) } } diff --git a/Passepartout/App/Views/OnDemandView+SSID.swift b/Passepartout/App/Views/OnDemandView+SSID.swift index 41e7c571..a9ea0ce8 100644 --- a/Passepartout/App/Views/OnDemandView+SSID.swift +++ b/Passepartout/App/Views/OnDemandView+SSID.swift @@ -111,7 +111,7 @@ extension OnDemandView.SSIDList { } set: { newValue in withSSIDs.forEach { guard newValue.contains($0.key) else { - if let _ = withSSIDs[$0.key] { + if withSSIDs[$0.key] != nil { withSSIDs[$0.key] = false } else { withSSIDs.removeValue(forKey: $0.key) diff --git a/Passepartout/App/Views/ProviderLocationView.swift b/Passepartout/App/Views/ProviderLocationView.swift index 0c114ecb..3a992b03 100644 --- a/Passepartout/App/Views/ProviderLocationView.swift +++ b/Passepartout/App/Views/ProviderLocationView.swift @@ -255,7 +255,7 @@ extension ProviderLocationView { HStack { themeAssetsCountryImage(location.countryCode).asAssetImage VStack { - if let singleServer = location.onlyServer, let _ = singleServer.localizedShortDescription { + if let singleServer = location.onlyServer, singleServer.localizedShortDescription != nil { Text(location.localizedCountry) .frame(maxWidth: .infinity, alignment: .leading) Text(singleServer.localizedShortDescription ?? "") diff --git a/Passepartout/AppShared/L10n/Core+L10n.swift b/Passepartout/AppShared/L10n/Core+L10n.swift index aa17c220..f6951476 100644 --- a/Passepartout/AppShared/L10n/Core+L10n.swift +++ b/Passepartout/AppShared/L10n/Core+L10n.swift @@ -75,13 +75,13 @@ extension ObservableVPNState { } extension Profile: Comparable { - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { lhs.header < rhs.header } } extension Profile.Header: Comparable { - public static func <(lhs: Self, rhs: Self) -> Bool { + public static func < (lhs: Self, rhs: Self) -> Bool { lhs.name.lowercased() < rhs.name.lowercased() } } diff --git a/Passepartout/Mac/Menu/PassepartoutMenu.swift b/Passepartout/Mac/Menu/PassepartoutMenu.swift index 48bdde59..6151a514 100644 --- a/Passepartout/Mac/Menu/PassepartoutMenu.swift +++ b/Passepartout/Mac/Menu/PassepartoutMenu.swift @@ -79,7 +79,7 @@ class PassepartoutMenu { ] as [ItemGroup]) } - if let _ = profileManager.activeProfileId { + if profileManager.activeProfileId != nil { children.append(contentsOf: [ SeparatorItem(), VPNItemGroup(