Refactor ModuleType to be a single source of truth (#800)
Rather than defining a new enum, tie ModuleType to ModuleHandler names from PassepartoutKit. Also a way to reuse ModuleType.localizedDescription on both Module and ModuleBuilder implementations.
This commit is contained in:
parent
f286ed8ff9
commit
454efb8e50
|
@ -49,6 +49,6 @@ private extension ProfileEditor {
|
|||
assertionFailure("\(type(of: module)) does not provide a default view")
|
||||
return nil
|
||||
}
|
||||
return (provider, module.typeDescription)
|
||||
return (provider, module.moduleType.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ private extension OpenVPNView {
|
|||
isImporting = true
|
||||
}
|
||||
.alert(
|
||||
module.typeDescription,
|
||||
module.moduleType.localizedDescription,
|
||||
isPresented: $requiresPassphrase,
|
||||
presenting: importURL,
|
||||
actions: { url in
|
||||
|
@ -194,7 +194,7 @@ private extension OpenVPNView {
|
|||
pp_log(.app, .error, "Unable to import OpenVPN configuration: \(error)")
|
||||
errorHandler.handle(
|
||||
(error as? StandardOpenVPNParserError)?.asPassepartoutError ?? error,
|
||||
title: module.typeDescription
|
||||
title: module.moduleType.localizedDescription
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ struct ModuleViewModifier<T>: ViewModifier where T: ModuleBuilder & Equatable {
|
|||
if withName {
|
||||
NameSection(
|
||||
name: editor.binding(forNameOf: draft.id),
|
||||
placeholder: draft.typeDescription
|
||||
placeholder: draft.moduleType.localizedDescription
|
||||
)
|
||||
}
|
||||
content
|
||||
|
|
|
@ -117,6 +117,9 @@ private extension ProfileCoordinator {
|
|||
|
||||
case .onDemand:
|
||||
break
|
||||
|
||||
default:
|
||||
fatalError("Unhandled module type: \(moduleType)")
|
||||
}
|
||||
guard paywallReason == nil else {
|
||||
return
|
||||
|
|
|
@ -71,9 +71,6 @@ public final class ProfileEditor: ObservableObject {
|
|||
extension ProfileEditor {
|
||||
public var moduleTypes: [ModuleType] {
|
||||
editableProfile.modules
|
||||
.compactMap {
|
||||
$0 as? ModuleTypeProviding
|
||||
}
|
||||
.map(\.moduleType)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// ModuleTypeProviding.swift
|
||||
// Module+ModuleType.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 8/10/24.
|
||||
// Created by Davide De Rosa on 11/2/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
|
@ -26,6 +26,14 @@
|
|||
import Foundation
|
||||
import PassepartoutKit
|
||||
|
||||
protocol ModuleTypeProviding {
|
||||
var moduleType: ModuleType { get }
|
||||
extension Module {
|
||||
public var moduleType: ModuleType {
|
||||
ModuleType(moduleHandler)
|
||||
}
|
||||
}
|
||||
|
||||
extension ModuleBuilder {
|
||||
public var moduleType: ModuleType {
|
||||
ModuleType(BuiltType.moduleHandler)
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// DescriptiveModule+L10n.swift
|
||||
// ModuleType+Known.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 8/10/24.
|
||||
// Created by Davide De Rosa on 11/2/24.
|
||||
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
|
@ -26,38 +26,25 @@
|
|||
import Foundation
|
||||
import PassepartoutKit
|
||||
|
||||
extension OpenVPNModule.Builder: ModuleTypeProviding {
|
||||
var moduleType: ModuleType {
|
||||
.openVPN
|
||||
}
|
||||
}
|
||||
|
||||
extension WireGuardModule.Builder: ModuleTypeProviding {
|
||||
var moduleType: ModuleType {
|
||||
.wireGuard
|
||||
}
|
||||
}
|
||||
|
||||
extension DNSModule.Builder: ModuleTypeProviding {
|
||||
var moduleType: ModuleType {
|
||||
.dns
|
||||
}
|
||||
}
|
||||
|
||||
extension HTTPProxyModule.Builder: ModuleTypeProviding {
|
||||
var moduleType: ModuleType {
|
||||
.httpProxy
|
||||
}
|
||||
}
|
||||
|
||||
extension IPModule.Builder: ModuleTypeProviding {
|
||||
var moduleType: ModuleType {
|
||||
.ip
|
||||
}
|
||||
}
|
||||
|
||||
extension OnDemandModule.Builder: ModuleTypeProviding {
|
||||
var moduleType: ModuleType {
|
||||
extension ModuleType: CaseIterable {
|
||||
public static let allCases: [ModuleType] = [
|
||||
.openVPN,
|
||||
.wireGuard,
|
||||
.dns,
|
||||
.httpProxy,
|
||||
.ip,
|
||||
.onDemand
|
||||
}
|
||||
]
|
||||
|
||||
public static let openVPN = ModuleType(OpenVPNModule.self)
|
||||
|
||||
public static let wireGuard = ModuleType(WireGuardModule.self)
|
||||
|
||||
public static let dns = ModuleType(DNSModule.self)
|
||||
|
||||
public static let httpProxy = ModuleType(HTTPProxyModule.self)
|
||||
|
||||
public static let ip = ModuleType(IPModule.self)
|
||||
|
||||
public static let onDemand = ModuleType(OnDemandModule.self)
|
||||
}
|
|
@ -46,6 +46,9 @@ extension ModuleType {
|
|||
|
||||
case .onDemand:
|
||||
return OnDemandModule.Builder()
|
||||
|
||||
default:
|
||||
fatalError("Unknown module type: \(rawValue)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,18 +27,20 @@ import Foundation
|
|||
import PassepartoutKit
|
||||
import PassepartoutWireGuardGo
|
||||
|
||||
public enum ModuleType: String, CaseIterable {
|
||||
case openVPN
|
||||
public struct ModuleType: RawRepresentable, Hashable {
|
||||
public let rawValue: String
|
||||
|
||||
case wireGuard
|
||||
public init?(rawValue: String) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
case dns
|
||||
init(_ moduleType: Module.Type) {
|
||||
self.init(moduleType.moduleHandler)
|
||||
}
|
||||
|
||||
case httpProxy
|
||||
|
||||
case ip
|
||||
|
||||
case onDemand
|
||||
init(_ moduleHandler: ModuleHandler) {
|
||||
rawValue = moduleHandler.id.name
|
||||
}
|
||||
}
|
||||
|
||||
extension ModuleType: Identifiable {
|
||||
|
@ -46,3 +48,9 @@ extension ModuleType: Identifiable {
|
|||
rawValue
|
||||
}
|
||||
}
|
||||
|
||||
extension ModuleType: Equatable {
|
||||
public static func == (lhs: Self, rhs: Self) -> Bool {
|
||||
lhs.rawValue == rhs.rawValue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ extension AppError: LocalizedError {
|
|||
return V.emptyProfileName
|
||||
|
||||
case .malformedModule(let module, let error):
|
||||
return V.malformedModule(module.typeDescription, error.localizedDescription)
|
||||
return V.malformedModule(module.moduleType.localizedDescription, error.localizedDescription)
|
||||
|
||||
case .permissionDenied:
|
||||
return V.default
|
||||
|
|
|
@ -30,15 +30,6 @@ extension ModuleBuilder {
|
|||
|
||||
@MainActor
|
||||
public func description(inEditor editor: ProfileEditor) -> String {
|
||||
editor.profile.displayName(forModuleWithId: id) ?? typeDescription
|
||||
}
|
||||
}
|
||||
|
||||
extension ModuleBuilder {
|
||||
public var typeDescription: String {
|
||||
guard let providing = self as? ModuleTypeProviding else {
|
||||
return String(describing: self)
|
||||
}
|
||||
return providing.moduleType.localizedDescription
|
||||
editor.profile.displayName(forModuleWithId: id) ?? moduleType.localizedDescription
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
import CommonUtils
|
||||
import Foundation
|
||||
import PassepartoutKit
|
||||
|
||||
extension ModuleType: LocalizableEntity {
|
||||
public var localizedDescription: String {
|
||||
|
@ -46,6 +47,10 @@ extension ModuleType: LocalizableEntity {
|
|||
|
||||
case .onDemand:
|
||||
return Strings.Global.onDemand
|
||||
|
||||
default:
|
||||
assertionFailure("Missing localization for ModuleType: \(rawValue)")
|
||||
return rawValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ public final class UILibrary: UILibraryConfiguring {
|
|||
logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key)
|
||||
)
|
||||
|
||||
assertMissingImplementations()
|
||||
uiConfiguring?.configure(with: context)
|
||||
|
||||
Task {
|
||||
|
@ -58,14 +57,3 @@ public final class UILibrary: UILibraryConfiguring {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension UILibrary {
|
||||
func assertMissingImplementations() {
|
||||
ModuleType.allCases.forEach { moduleType in
|
||||
let builder = moduleType.newModule()
|
||||
guard builder is ModuleTypeProviding else {
|
||||
fatalError("\(moduleType): is not ModuleTypeProviding")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue