Refactor library into domain + impl
This commit is contained in:
parent
8504998bbb
commit
9a8477225e
|
@ -1,6 +1,6 @@
|
|||
[submodule "Submodules/fastlane-ci-templates"]
|
||||
path = Submodules/fastlane-ci-templates
|
||||
url = https://github.com/keeshux/fastlane-ci-templates
|
||||
[submodule "PassepartoutCore/Sources/PassepartoutServices/API"]
|
||||
path = PassepartoutCore/Sources/PassepartoutServices/API
|
||||
[submodule "PassepartoutLibrary/Sources/PassepartoutServices/API"]
|
||||
path = PassepartoutLibrary/Sources/PassepartoutServices/API
|
||||
url = https://github.com/passepartoutvpn/api
|
||||
|
|
2
API
2
API
|
@ -1 +1 @@
|
|||
PassepartoutCore/Sources/PassepartoutServices/API/
|
||||
PassepartoutLibrary/Sources/PassepartoutServices/API/
|
|
@ -47,7 +47,6 @@
|
|||
0E49F6BF27D764AF00385834 /* EndpointAdvancedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49F6BE27D764AF00385834 /* EndpointAdvancedView.swift */; };
|
||||
0E53249927D26B51002565C3 /* ProductManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E53249627D26B51002565C3 /* ProductManager.swift */; };
|
||||
0E53249D27D28FC7002565C3 /* Kvitto in Frameworks */ = {isa = PBXBuildFile; productRef = 0E53249C27D28FC7002565C3 /* Kvitto */; };
|
||||
0E5324A627D297BB002565C3 /* InApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5324A527D297BB002565C3 /* InApp.swift */; };
|
||||
0E5324A927D2AC55002565C3 /* LongContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5324A827D2AC55002565C3 /* LongContentView.swift */; };
|
||||
0E5349BE27C16A4500C71BB3 /* StyledPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5349BD27C16A4500C71BB3 /* StyledPicker.swift */; };
|
||||
0E5349C627C176C200C71BB3 /* EndpointView+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5349C527C176C200C71BB3 /* EndpointView+OpenVPN.swift */; };
|
||||
|
@ -98,6 +97,7 @@
|
|||
0EBC075D27EC529000208AD9 /* DebugLog+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075C27EC529000208AD9 /* DebugLog+Constants.swift */; };
|
||||
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075F27EC587900208AD9 /* SwiftGen+Strings.swift */; };
|
||||
0EBE880F281B18DE0090D9E6 /* ProfileRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE880E281B18DE0090D9E6 /* ProfileRow.swift */; };
|
||||
0ECB78EC2863A21600B0E460 /* PassepartoutLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */; };
|
||||
0ECF71EE27B6A99300CDB528 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECF71ED27B6A99300CDB528 /* AccountView.swift */; };
|
||||
0ED1D6DC27DBA41700983466 /* DiagnosticsView+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED1D6DB27DBA41700983466 /* DiagnosticsView+OpenVPN.swift */; };
|
||||
0ED1D6DE27DBA42100983466 /* DiagnosticsView+WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED1D6DD27DBA42100983466 /* DiagnosticsView+WireGuard.swift */; };
|
||||
|
@ -119,7 +119,6 @@
|
|||
0EDE02C227F61C79000FBE3C /* EditableTextList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE02C127F61C79000FBE3C /* EditableTextList.swift */; };
|
||||
0EE11CD2280D8317003BE431 /* InfoMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE11CD1280D8317003BE431 /* InfoMenu.swift */; };
|
||||
0EE8B7E327FF340F00B68621 /* VPNProtocolType+FileExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE8B7E227FF340F00B68621 /* VPNProtocolType+FileExtensions.swift */; };
|
||||
0EED0BB92733CEDA00C9FC68 /* PassepartoutCore in Frameworks */ = {isa = PBXBuildFile; productRef = 0EED0BB82733CEDA00C9FC68 /* PassepartoutCore */; };
|
||||
0EF0FAF627DD0211007EB181 /* PaywallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF0FAF527DD0211007EB181 /* PaywallView.swift */; };
|
||||
0EF0FAF727DD159C007EB181 /* IntentDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA591122733DD4E0096F796 /* IntentDispatcher.swift */; };
|
||||
0EF0FAF927DD212C007EB181 /* IntentActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF0FAF827DD212C007EB181 /* IntentActivity.swift */; };
|
||||
|
@ -131,13 +130,6 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
0E6059C627FCC33D003F4063 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 0E9AAA60259F7D7E003FAFF1;
|
||||
remoteInfo = "PassepartoutLauncher-macOS";
|
||||
};
|
||||
0EB2B1492733FB6F007705AB /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
|
||||
|
@ -236,7 +228,6 @@
|
|||
0E49F6BC27D7639000385834 /* EndpointAdvancedView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EndpointAdvancedView+WireGuard.swift"; sourceTree = "<group>"; };
|
||||
0E49F6BE27D764AF00385834 /* EndpointAdvancedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndpointAdvancedView.swift; sourceTree = "<group>"; };
|
||||
0E53249627D26B51002565C3 /* ProductManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductManager.swift; sourceTree = "<group>"; };
|
||||
0E5324A527D297BB002565C3 /* InApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InApp.swift; sourceTree = "<group>"; };
|
||||
0E5324A827D2AC55002565C3 /* LongContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongContentView.swift; sourceTree = "<group>"; };
|
||||
0E5349BD27C16A4500C71BB3 /* StyledPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StyledPicker.swift; sourceTree = "<group>"; };
|
||||
0E5349C527C176C200C71BB3 /* EndpointView+OpenVPN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EndpointView+OpenVPN.swift"; sourceTree = "<group>"; };
|
||||
|
@ -282,7 +273,6 @@
|
|||
0E9E5AED27B44CF1008C95DA /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
0E9E5AEE27B44CF1008C95DA /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
0E9ED48027FD9BAE003B2316 /* CopySavingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopySavingButton.swift; sourceTree = "<group>"; };
|
||||
0EA26DC827353020000F251A /* PassepartoutCore */ = {isa = PBXFileReference; lastKnownFileType = folder; path = PassepartoutCore; sourceTree = "<group>"; };
|
||||
0EA591122733DD4E0096F796 /* IntentDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentDispatcher.swift; sourceTree = "<group>"; };
|
||||
0EA591152733DDDA0096F796 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = "<group>"; };
|
||||
0EA591182733DDF60096F796 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = "<group>"; };
|
||||
|
@ -321,6 +311,7 @@
|
|||
0EBE2FD72360F89600F0D5AB /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
0EBE2FD82360F89600F0D5AB /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
0EBE880E281B18DE0090D9E6 /* ProfileRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileRow.swift; sourceTree = "<group>"; };
|
||||
0ECB78EA2861D1F300B0E460 /* PassepartoutLibrary */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PassepartoutLibrary; sourceTree = "<group>"; };
|
||||
0ECF71ED27B6A99300CDB528 /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = "<group>"; };
|
||||
0ED1D6DB27DBA41700983466 /* DiagnosticsView+OpenVPN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiagnosticsView+OpenVPN.swift"; sourceTree = "<group>"; };
|
||||
0ED1D6DD27DBA42100983466 /* DiagnosticsView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiagnosticsView+WireGuard.swift"; sourceTree = "<group>"; };
|
||||
|
@ -358,8 +349,8 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0E9C3B6F27FC573E00D0F02E /* CloudKit.framework in Frameworks */,
|
||||
0EED0BB92733CEDA00C9FC68 /* PassepartoutCore in Frameworks */,
|
||||
0E53249D27D28FC7002565C3 /* Kvitto in Frameworks */,
|
||||
0ECB78EC2863A21600B0E460 /* PassepartoutLibrary in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -602,7 +593,6 @@
|
|||
0E293859285A7489002A6E0E /* Context */,
|
||||
0E92781227E7CD530057BB81 /* InApp */,
|
||||
0E34A2B827CAA8EA00C73B67 /* L10n */,
|
||||
0ECB78D5285F508B00B0E460 /* Reusable */,
|
||||
0E9E5AE227B44CF1008C95DA /* Localizable.strings */,
|
||||
);
|
||||
path = AppShared;
|
||||
|
@ -626,14 +616,6 @@
|
|||
path = Constants;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0ECB78D5285F508B00B0E460 /* Reusable */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0E5324A527D297BB002565C3 /* InApp.swift */,
|
||||
);
|
||||
path = Reusable;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0ED2B33C27D3C52900FD8EA9 /* OpenVPN */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -673,7 +655,7 @@
|
|||
0EE315DB2733104700F5D461 /* Packages */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0EA26DC827353020000F251A /* PassepartoutCore */,
|
||||
0ECB78EA2861D1F300B0E460 /* PassepartoutLibrary */,
|
||||
);
|
||||
name = Packages;
|
||||
sourceTree = "<group>";
|
||||
|
@ -726,12 +708,11 @@
|
|||
0ECF71FC27B6DA6700CDB528 /* PBXTargetDependency */,
|
||||
0EB2B14A2733FB6F007705AB /* PBXTargetDependency */,
|
||||
0ED2B36227D3C99100FD8EA9 /* PBXTargetDependency */,
|
||||
0E6059C727FCC33D003F4063 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Passepartout;
|
||||
packageProductDependencies = (
|
||||
0EED0BB82733CEDA00C9FC68 /* PassepartoutCore */,
|
||||
0E53249C27D28FC7002565C3 /* Kvitto */,
|
||||
0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */,
|
||||
);
|
||||
productName = Passepartout;
|
||||
productReference = 0E57F63820C83FC5008323CF /* Passepartout.app */;
|
||||
|
@ -944,7 +925,6 @@
|
|||
0EF2213127E674BD001D0BD7 /* AddProviderViewModel.swift in Sources */,
|
||||
0E90DFE627BACC1500EF5078 /* AddHostViewModel.swift in Sources */,
|
||||
0E34AC8227F892C40042F2AB /* OnDemandView+SSID.swift in Sources */,
|
||||
0E5324A627D297BB002565C3 /* InApp.swift in Sources */,
|
||||
0E3B7FCD27E47B3700C66F13 /* AddHostView+Name.swift in Sources */,
|
||||
0E7577D72816A3B200081CBE /* DestructiveButton.swift in Sources */,
|
||||
0EF2212D27E66EB5001D0BD7 /* AddProviderView.swift in Sources */,
|
||||
|
@ -1059,11 +1039,6 @@
|
|||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
0E6059C727FCC33D003F4063 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
platformFilter = ios;
|
||||
targetProxy = 0E6059C627FCC33D003F4063 /* PBXContainerItemProxy */;
|
||||
};
|
||||
0EB2B14A2733FB6F007705AB /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 0EDE8DBE20C86910004C739C /* OpenVPNTunnel */;
|
||||
|
@ -1509,6 +1484,10 @@
|
|||
package = 0E53249B27D28FC7002565C3 /* XCRemoteSwiftPackageReference "Kvitto" */;
|
||||
productName = Kvitto;
|
||||
};
|
||||
0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = PassepartoutLibrary;
|
||||
};
|
||||
0ED2B33827D3C49800FD8EA9 /* OpenVPNAppExtension */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = OpenVPNAppExtension;
|
||||
|
@ -1517,10 +1496,6 @@
|
|||
isa = XCSwiftPackageProductDependency;
|
||||
productName = WireGuardAppExtension;
|
||||
};
|
||||
0EED0BB82733CEDA00C9FC68 /* PassepartoutCore */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = PassepartoutCore;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 0E57F63020C83FC5008323CF /* Project object */;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension View {
|
||||
var themeIdiom: UIUserInterfaceIdiom {
|
||||
|
|
|
@ -25,9 +25,8 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
@MainActor
|
||||
class AppContext {
|
||||
private let logManager: LogManager
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutUtils
|
||||
import PassepartoutLibrary
|
||||
|
||||
enum AppPreference: String, KeyStoreDomainLocation {
|
||||
case isShowingFavorites
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension DebugLog {
|
||||
func decoratedString() -> String {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProviderMetadata: Identifiable, Comparable, Hashable {
|
||||
public var id: String {
|
||||
|
|
|
@ -24,17 +24,15 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
protocol ProviderProfileAvailability {
|
||||
var profile: Profile { get }
|
||||
|
||||
var providerManager: ProviderManager { get }
|
||||
var providerManager: Impl.ProviderManager { get }
|
||||
}
|
||||
|
||||
extension ProviderProfileAvailability {
|
||||
|
||||
@MainActor
|
||||
var isProviderProfileAvailable: Bool {
|
||||
guard !profile.isPlaceholder else {
|
||||
return false
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension VPNProtocolType {
|
||||
static let knownFileExtensions: [String] = {
|
||||
|
|
|
@ -25,9 +25,8 @@
|
|||
|
||||
import Foundation
|
||||
import Intents
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
@MainActor
|
||||
extension IntentDispatcher {
|
||||
private enum IntentError: Error {
|
||||
case notProvider(UUID)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
import Intents
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
class IntentDispatcher {
|
||||
private struct Groups {
|
||||
|
@ -78,7 +78,6 @@ class IntentDispatcher {
|
|||
|
||||
// MARK: Donations
|
||||
|
||||
@MainActor
|
||||
static func donateConnection(with profile: Profile, providerManager: ProviderManager) {
|
||||
let genericIntent: INIntent
|
||||
if let providerName = profile.header.providerName {
|
||||
|
|
|
@ -28,7 +28,6 @@ import Intents
|
|||
import IntentsUI
|
||||
import Combine
|
||||
|
||||
@MainActor
|
||||
class IntentsManager: NSObject, ObservableObject {
|
||||
@Published private(set) var isReloadingShortcuts = false
|
||||
|
||||
|
@ -36,7 +35,6 @@ class IntentsManager: NSObject, ObservableObject {
|
|||
|
||||
let shouldDismissIntentView = PassthroughSubject<Void, Never>()
|
||||
|
||||
@MainActor
|
||||
override init() {
|
||||
super.init()
|
||||
reloadShortcuts()
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
@main
|
||||
struct PassepartoutApp: App {
|
||||
|
@ -45,8 +45,6 @@ struct PassepartoutApp: App {
|
|||
}
|
||||
|
||||
extension View {
|
||||
|
||||
@MainActor
|
||||
fileprivate func onIntentActivity(_ activity: IntentActivity<VPNManager>) -> some View {
|
||||
onContinueUserActivity(activity.name) { userActivity in
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
@MainActor
|
||||
public class Reviewer: ObservableObject {
|
||||
private struct Keys {
|
||||
static let eventCount = "Reviewer.EventCount"
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct AccountView: View {
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
private let providerName: ProviderName?
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import TunnelKitOpenVPN
|
||||
import TunnelKitWireGuard
|
||||
|
||||
extension AddHostView {
|
||||
struct NameView: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
private let url: URL
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import TunnelKitOpenVPN
|
||||
import TunnelKitWireGuard
|
||||
|
||||
|
@ -52,7 +52,6 @@ extension AddHostView {
|
|||
profileName = url.normalizedFilename
|
||||
}
|
||||
|
||||
@MainActor
|
||||
mutating func processURL(
|
||||
_ url: URL,
|
||||
with profileManager: ProfileManager,
|
||||
|
@ -97,7 +96,6 @@ extension AddHostView {
|
|||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
mutating func addProcessedProfile(to profileManager: ProfileManager) -> Bool {
|
||||
guard !processedProfile.isPlaceholder else {
|
||||
assertionFailure("Saving profile without processing first?")
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct AddProfileMenu: View {
|
||||
enum ModalType: Identifiable {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
enum AddProfileView {
|
||||
struct Bindings {
|
||||
|
@ -71,7 +71,7 @@ enum AddProfileView {
|
|||
}
|
||||
|
||||
struct AccountWrapperView: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@Binding private var profile: Profile
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension AddProviderView {
|
||||
struct NameView: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@Binding private var profile: Profile
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct AddProviderView: View {
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var productManager: ProductManager
|
||||
|
||||
|
@ -112,7 +112,7 @@ struct AddProviderView: View {
|
|||
Button {
|
||||
presentOrPurchaseProvider(metadata)
|
||||
} label: {
|
||||
Label(metadata.description, image: themeAssetsProviderImage(metadata.name))
|
||||
Label(metadata.fullName, image: themeAssetsProviderImage(metadata.name))
|
||||
}.withTrailingProgress(when: viewModel.isFetchingProvider(metadata.name))
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension AddProviderView {
|
||||
class ViewModel: ObservableObject {
|
||||
|
@ -67,7 +67,6 @@ extension AddProviderView {
|
|||
|
||||
@Published private(set) var errorMessage: String?
|
||||
|
||||
@MainActor
|
||||
func selectProvider(_ metadata: ProviderMetadata, _ providerManager: ProviderManager) {
|
||||
errorMessage = nil
|
||||
guard let server = providerManager.anyDefaultServer(
|
||||
|
@ -82,7 +81,6 @@ extension AddProviderView {
|
|||
doSelectProvider(metadata, server)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func selectProviderAfterFetchingInfrastructure(_ metadata: ProviderMetadata, _ providerManager: ProviderManager) async {
|
||||
errorMessage = nil
|
||||
pendingOperation = .provider(metadata.name)
|
||||
|
@ -114,7 +112,6 @@ extension AddProviderView {
|
|||
selectedProvider = metadata
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func updateIndex(_ providerManager: ProviderManager) {
|
||||
errorMessage = nil
|
||||
pendingOperation = .index
|
||||
|
@ -154,7 +151,6 @@ extension AddProviderView.NameView {
|
|||
profileName = metadata.fullName
|
||||
}
|
||||
|
||||
@MainActor
|
||||
mutating func addProfile(
|
||||
_ profile: Profile,
|
||||
to profileManager: ProfileManager,
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct DebugLogView: View {
|
||||
private let url: URL
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import TunnelKitOpenVPN
|
||||
|
||||
extension DiagnosticsView {
|
||||
|
@ -37,11 +37,11 @@ extension DiagnosticsView {
|
|||
}
|
||||
}
|
||||
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
@ObservedObject private var vpnManager: Impl.VPNManager
|
||||
|
||||
@ObservedObject private var currentVPNState: VPNManager.ObservableState
|
||||
@ObservedObject private var currentVPNState: ObservableVPNState
|
||||
|
||||
@ObservedObject private var productManager: ProductManager
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import TunnelKitWireGuard
|
||||
|
||||
extension DiagnosticsView {
|
||||
struct WireGuardView: View {
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
@ObservedObject private var vpnManager: Impl.VPNManager
|
||||
|
||||
private let providerName: ProviderName?
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct DiagnosticsView: View {
|
||||
let vpnProtocol: VPNProtocolType
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import StoreKit
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct DonateView: View {
|
||||
enum AlertType: Identifiable {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import TunnelKitOpenVPN
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension EndpointAdvancedView {
|
||||
struct OpenVPNView: View {
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import TunnelKitOpenVPN
|
||||
|
||||
extension EndpointView {
|
||||
struct OpenVPNView: View {
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
@ -53,7 +53,7 @@ extension EndpointView {
|
|||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
let providerManager: Impl.ProviderManager = .shared
|
||||
|
||||
self.providerManager = providerManager
|
||||
self.currentProfile = currentProfile
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import TunnelKitWireGuard
|
||||
|
||||
extension EndpointView {
|
||||
struct WireGuardView: View {
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
@ -41,7 +41,7 @@ extension EndpointView {
|
|||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile, isReadonly: Bool) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
let providerManager: Impl.ProviderManager = .shared
|
||||
|
||||
self.providerManager = providerManager
|
||||
self.currentProfile = currentProfile
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct EndpointView: View {
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct InfoMenu: View {
|
||||
enum ModalType: Identifiable {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct NetworkSettingsView: View {
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension OnDemandView {
|
||||
struct SSIDList: View {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct OnDemandView: View {
|
||||
@ObservedObject private var productManager: ProductManager
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension OrganizerView {
|
||||
struct ProfilesList: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
init() {
|
||||
profileManager = .shared
|
||||
|
|
|
@ -24,15 +24,15 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension OrganizerView {
|
||||
struct SceneView: View {
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
@ObservedObject private var vpnManager: Impl.VPNManager
|
||||
|
||||
@ObservedObject private var productManager: ProductManager
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct OrganizerView: View {
|
||||
enum AlertType: Identifiable {
|
||||
|
@ -81,7 +81,7 @@ struct OrganizerView: View {
|
|||
.themePrimaryView()
|
||||
|
||||
// VPN configuration error publisher (no need to observe VPNManager)
|
||||
.onReceive(VPNManager.shared.configurationError) {
|
||||
.onReceive(Impl.VPNManager.shared.configurationError) {
|
||||
alertType = .error($0.profile.header.name, $0.error.localizedAppDescription)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import StoreKit
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension PaywallView {
|
||||
struct PurchaseView: View {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct ProfileRow: View {
|
||||
let header: Profile.Header
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct ConfigurationSection: View {
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct DiagnosticsSection: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct ExtraSection: View {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct MainMenu: View {
|
||||
|
@ -38,9 +38,9 @@ extension ProfileView {
|
|||
}
|
||||
}
|
||||
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
@ObservedObject private var vpnManager: Impl.VPNManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
@ -200,7 +200,7 @@ extension ProfileView {
|
|||
}
|
||||
|
||||
struct DuplicateButton: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
private let header: Profile.Header
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct ProviderSection: View, ProviderProfileAvailability {
|
||||
@ObservedObject var providerManager: ProviderManager
|
||||
@ObservedObject var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct RenameView: View {
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProfileView {
|
||||
struct VPNSection: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
private let profileId: UUID
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct ProfileView: View {
|
||||
enum ModalType: Int, Identifiable {
|
||||
|
@ -56,7 +56,7 @@ struct ProfileView: View {
|
|||
@State private var modalType: ModalType?
|
||||
|
||||
init() {
|
||||
currentProfile = ProfileManager.shared.currentProfile
|
||||
currentProfile = Impl.ProfileManager.shared.currentProfile
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct ProviderLocationView: View, ProviderProfileAvailability {
|
||||
@ObservedObject var providerManager: ProviderManager
|
||||
@ObservedObject var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
@ -64,7 +64,7 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
|
|||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile, isEditable: Bool, isPresented: Binding<Bool>) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
let providerManager: Impl.ProviderManager = .shared
|
||||
|
||||
self.providerManager = providerManager
|
||||
self.currentProfile = currentProfile
|
||||
|
@ -268,7 +268,7 @@ extension ProviderLocationView {
|
|||
}
|
||||
|
||||
struct ServerListView: View {
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
private let location: ProviderLocation
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct ProviderPresetView: View {
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
|
@ -39,7 +39,7 @@ struct ProviderPresetView: View {
|
|||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
let providerManager: Impl.ProviderManager = .shared
|
||||
|
||||
self.providerManager = providerManager
|
||||
self.currentProfile = currentProfile
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import MessageUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct ReportIssueView: View {
|
||||
@Binding private var isPresented: Bool
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
import SwiftUI
|
||||
import Intents
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ShortcutsView {
|
||||
struct AddView: View {
|
||||
@ObservedObject private var providerManager: ProviderManager
|
||||
@ObservedObject private var providerManager: Impl.ProviderManager
|
||||
|
||||
@StateObject private var pendingProfile = ObservableProfile()
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import SwiftUI
|
||||
import Intents
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct ShortcutsView: View {
|
||||
enum ModalType: Identifiable {
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct VPNStatusText: View {
|
||||
@ObservedObject private var currentVPNState: VPNManager.ObservableState
|
||||
@ObservedObject private var currentVPNState: ObservableVPNState
|
||||
|
||||
let isActiveProfile: Bool
|
||||
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct VPNToggle: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
@ObservedObject private var profileManager: Impl.ProfileManager
|
||||
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
@ObservedObject private var vpnManager: Impl.VPNManager
|
||||
|
||||
@ObservedObject private var currentVPNState: VPNManager.ObservableState
|
||||
@ObservedObject private var currentVPNState: ObservableVPNState
|
||||
|
||||
@ObservedObject private var productManager: ProductManager
|
||||
|
||||
|
@ -113,7 +113,7 @@ struct VPNToggle: View {
|
|||
IntentDispatcher.donateDisableVPN()
|
||||
IntentDispatcher.donateConnection(
|
||||
with: profile,
|
||||
providerManager: .shared
|
||||
providerManager: Impl.ProviderManager.shared
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import SwiftyBeaver
|
||||
|
||||
extension View {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
import UniformTypeIdentifiers
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import SwiftyBeaver
|
||||
|
||||
extension Constants {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension CoreContext {
|
||||
static let shared = CoreContext(store: UserDefaultsStore(defaults: .standard))
|
||||
|
@ -34,20 +34,18 @@ extension UpgradeManager {
|
|||
static let shared = CoreContext.shared.upgradeManager
|
||||
}
|
||||
|
||||
extension ProfileManager {
|
||||
extension Impl.ProfileManager {
|
||||
static let shared = CoreContext.shared.profileManager
|
||||
}
|
||||
|
||||
extension ProviderManager {
|
||||
extension Impl.ProviderManager {
|
||||
static let shared = CoreContext.shared.providerManager
|
||||
}
|
||||
|
||||
extension VPNManager {
|
||||
extension Impl.VPNManager {
|
||||
static let shared = CoreContext.shared.vpnManager
|
||||
}
|
||||
|
||||
extension VPNManager.ObservableState {
|
||||
|
||||
@MainActor
|
||||
extension ObservableVPNState {
|
||||
static let shared = CoreContext.shared.vpnManager.currentState
|
||||
}
|
||||
|
|
|
@ -25,10 +25,16 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
import PassepartoutCore
|
||||
import PassepartoutServices
|
||||
import PassepartoutLibrary
|
||||
|
||||
enum Impl {
|
||||
typealias ProfileManager = DefaultProfileManager
|
||||
|
||||
typealias ProviderManager = DefaultProviderManager
|
||||
|
||||
typealias VPNManager = DefaultVPNManager<DefaultProfileManager>
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class CoreContext {
|
||||
let store: KeyValueStore
|
||||
|
||||
|
@ -46,11 +52,11 @@ class CoreContext {
|
|||
|
||||
let upgradeManager: UpgradeManager
|
||||
|
||||
let providerManager: ProviderManager
|
||||
let providerManager: Impl.ProviderManager
|
||||
|
||||
let profileManager: ProfileManager
|
||||
let profileManager: Impl.ProfileManager
|
||||
|
||||
let vpnManager: VPNManager
|
||||
let vpnManager: Impl.VPNManager
|
||||
|
||||
private var cancellables: Set<AnyCancellable> = []
|
||||
|
||||
|
@ -67,7 +73,7 @@ class CoreContext {
|
|||
|
||||
upgradeManager = UpgradeManager(store: store)
|
||||
|
||||
providerManager = ProviderManager(
|
||||
providerManager = DefaultProviderManager(
|
||||
appBuild: Constants.Global.appBuildNumber,
|
||||
bundleServices: DefaultWebServices.bundledServices(
|
||||
withVersion: Constants.Services.version
|
||||
|
@ -80,12 +86,12 @@ class CoreContext {
|
|||
persistence: providersPersistence
|
||||
)
|
||||
|
||||
profileManager = ProfileManager(
|
||||
profileManager = DefaultProfileManager(
|
||||
store: store,
|
||||
providerManager: providerManager,
|
||||
appGroup: Constants.App.appGroupId,
|
||||
keychainLabel: Unlocalized.Keychain.passwordLabel,
|
||||
strategy: ProfileManager.CoreDataStrategy(
|
||||
strategy: CoreDataProfileManagerStrategy(
|
||||
persistence: profilesPersistence
|
||||
)
|
||||
)
|
||||
|
@ -93,12 +99,13 @@ class CoreContext {
|
|||
#if targetEnvironment(simulator)
|
||||
let strategy = VPNManager.MockStrategy()
|
||||
#else
|
||||
let strategy = VPNManager.TunnelKitStrategy(
|
||||
let strategy = TunnelKitVPNManagerStrategy(
|
||||
appGroup: Constants.App.appGroupId,
|
||||
tunnelBundleIdentifier: Constants.App.tunnelBundleId
|
||||
)
|
||||
#endif
|
||||
vpnManager = VPNManager(
|
||||
vpnManager = DefaultVPNManager(
|
||||
appGroup: Constants.App.appGroupId,
|
||||
store: store,
|
||||
profileManager: profileManager,
|
||||
providerManager: providerManager,
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
import Foundation
|
||||
import StoreKit
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
struct LocalProduct: RawRepresentable, Equatable, Hashable {
|
||||
private static let bundleSubdomain = "ios"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
import StoreKit
|
||||
import Kvitto
|
||||
|
||||
|
@ -34,7 +34,6 @@ enum ProductError: Error {
|
|||
case beta
|
||||
}
|
||||
|
||||
@MainActor
|
||||
class ProductManager: NSObject, ObservableObject {
|
||||
enum AppType: Int {
|
||||
case freemium = 0
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension Error {
|
||||
var localizedAppDescription: String {
|
||||
|
@ -57,7 +57,7 @@ extension PassepartoutError {
|
|||
}
|
||||
}
|
||||
|
||||
extension VPNManager.ObservableState {
|
||||
extension ObservableVPNState {
|
||||
func localizedStatusDescription(isActiveProfile: Bool, withErrors: Bool, dataCountIfAvailable: Bool) -> String {
|
||||
|
||||
// FIXME: l10n, sure about this wording?
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension ProviderManager {
|
||||
// func localizedLocation(forProfile profile: Profile) -> String? {
|
||||
|
@ -59,7 +59,7 @@ extension ProviderMetadata {
|
|||
format = NSLocalizedString(defaultKey, bundle: .main, comment: "")
|
||||
}
|
||||
|
||||
return String(format: format, locale: .current, description)
|
||||
return String(format: format, locale: .current, fullName)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import TunnelKitManager
|
|||
import TunnelKitOpenVPN
|
||||
import TunnelKitWireGuard
|
||||
import NetworkExtension
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
extension VPNStatus {
|
||||
var localizedDescription: String {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutCore
|
||||
import PassepartoutLibrary
|
||||
|
||||
enum Unlocalized {
|
||||
static let appName = Constants.Global.appName
|
||||
|
|
|
@ -1,289 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1330"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore_PassepartoutServices"
|
||||
BuildableName = "PassepartoutCore_PassepartoutServices"
|
||||
BlueprintName = "PassepartoutCore_PassepartoutServices"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore_PassepartoutProviders"
|
||||
BuildableName = "PassepartoutCore_PassepartoutProviders"
|
||||
BlueprintName = "PassepartoutCore_PassepartoutProviders"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore_PassepartoutProfiles"
|
||||
BuildableName = "PassepartoutCore_PassepartoutProfiles"
|
||||
BlueprintName = "PassepartoutCore_PassepartoutProfiles"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore_PassepartoutUtilsTests"
|
||||
BuildableName = "PassepartoutCore_PassepartoutUtilsTests"
|
||||
BlueprintName = "PassepartoutCore_PassepartoutUtilsTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "OpenVPNAppExtension"
|
||||
BuildableName = "OpenVPNAppExtension"
|
||||
BlueprintName = "OpenVPNAppExtension"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore"
|
||||
BuildableName = "PassepartoutCore"
|
||||
BlueprintName = "PassepartoutCore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "WireGuardAppExtension"
|
||||
BuildableName = "WireGuardAppExtension"
|
||||
BlueprintName = "WireGuardAppExtension"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutProvidersTests"
|
||||
BuildableName = "PassepartoutProvidersTests"
|
||||
BlueprintName = "PassepartoutProvidersTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutServicesTests"
|
||||
BuildableName = "PassepartoutServicesTests"
|
||||
BlueprintName = "PassepartoutServicesTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutUtilsTests"
|
||||
BuildableName = "PassepartoutUtilsTests"
|
||||
BlueprintName = "PassepartoutUtilsTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutProfiles"
|
||||
BuildableName = "PassepartoutProfiles"
|
||||
BlueprintName = "PassepartoutProfiles"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutProviders"
|
||||
BuildableName = "PassepartoutProviders"
|
||||
BlueprintName = "PassepartoutProviders"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutServices"
|
||||
BuildableName = "PassepartoutServices"
|
||||
BlueprintName = "PassepartoutServices"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutUtils"
|
||||
BuildableName = "PassepartoutUtils"
|
||||
BlueprintName = "PassepartoutUtils"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutProvidersTests"
|
||||
BuildableName = "PassepartoutProvidersTests"
|
||||
BlueprintName = "PassepartoutProvidersTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutServicesTests"
|
||||
BuildableName = "PassepartoutServicesTests"
|
||||
BlueprintName = "PassepartoutServicesTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutUtilsTests"
|
||||
BuildableName = "PassepartoutUtilsTests"
|
||||
BlueprintName = "PassepartoutUtilsTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutProfilesTests"
|
||||
BuildableName = "PassepartoutProfilesTests"
|
||||
BlueprintName = "PassepartoutProfilesTests"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore_PassepartoutServices"
|
||||
BuildableName = "PassepartoutCore_PassepartoutServices"
|
||||
BlueprintName = "PassepartoutCore_PassepartoutServices"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -1,67 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1320"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore"
|
||||
BuildableName = "PassepartoutCore"
|
||||
BlueprintName = "PassepartoutCore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "PassepartoutCore"
|
||||
BuildableName = "PassepartoutCore"
|
||||
BlueprintName = "PassepartoutCore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -1,108 +0,0 @@
|
|||
//
|
||||
// VPNManagerStrategy+Mock.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 2/9/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import TunnelKitManager
|
||||
|
||||
extension VPNManager {
|
||||
|
||||
// XXX: mock connect/disconnect tasks overlap, should cancel other pending task
|
||||
|
||||
public class MockStrategy: VPNManagerStrategy {
|
||||
private var currentState: ObservableState?
|
||||
|
||||
private var dataCountTimer: AnyCancellable?
|
||||
|
||||
public init() {
|
||||
}
|
||||
|
||||
public func observe(into state: VPNManager.ObservableState) {
|
||||
currentState = state
|
||||
}
|
||||
|
||||
public func reinstate(configuration: VPNConfiguration) {
|
||||
}
|
||||
|
||||
public func connect(configuration: VPNConfiguration) {
|
||||
guard currentState?.vpnStatus != .connected else {
|
||||
return
|
||||
}
|
||||
Task {
|
||||
currentState?.isEnabled = true
|
||||
currentState?.vpnStatus = .connecting
|
||||
await Task.maybeWait(forMilliseconds: 1000)
|
||||
currentState?.vpnStatus = .connected
|
||||
startCountingData()
|
||||
}
|
||||
}
|
||||
|
||||
public func disconnect() {
|
||||
stopCountingData()
|
||||
guard currentState?.vpnStatus != .disconnected else {
|
||||
return
|
||||
}
|
||||
Task {
|
||||
currentState?.isEnabled = false
|
||||
currentState?.vpnStatus = .disconnecting
|
||||
await Task.maybeWait(forMilliseconds: 1000)
|
||||
currentState?.vpnStatus = .disconnected
|
||||
currentState?.dataCount = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func startCountingData() {
|
||||
guard currentState?.vpnStatus == .connected else {
|
||||
return
|
||||
}
|
||||
guard dataCountTimer == nil else {
|
||||
return
|
||||
}
|
||||
dataCountTimer = Timer.TimerPublisher(interval: 2.0, runLoop: .main, mode: .common)
|
||||
.autoconnect()
|
||||
.sink(receiveValue: { _ in
|
||||
let previous = self.currentState?.dataCount ?? DataCount(0, 0)
|
||||
self.currentState?.dataCount = DataCount(previous.received + 4000, previous.sent + 2000)
|
||||
})
|
||||
}
|
||||
|
||||
private func stopCountingData() {
|
||||
dataCountTimer?.cancel()
|
||||
dataCountTimer = nil
|
||||
}
|
||||
|
||||
public func removeConfigurations() {
|
||||
disconnect()
|
||||
}
|
||||
|
||||
public func serverConfiguration(forProtocol vpnProtocol: VPNProtocolType) -> Any? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func debugLogURL(forProtocol vpnProtocol: VPNProtocolType) -> URL? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,316 +0,0 @@
|
|||
//
|
||||
// VPNManagerStrategy+TunnelKit.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 3/4/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import NetworkExtension
|
||||
import TunnelKitManager
|
||||
import TunnelKitOpenVPNCore
|
||||
|
||||
extension VPNManager {
|
||||
public class TunnelKitStrategy: VPNManagerStrategy {
|
||||
private struct AtomicState: Equatable {
|
||||
let isEnabled: Bool
|
||||
|
||||
let vpnStatus: VPNStatus
|
||||
|
||||
init(isEnabled: Bool = false, vpnStatus: VPNStatus = .disconnected) {
|
||||
self.isEnabled = isEnabled
|
||||
self.vpnStatus = vpnStatus
|
||||
}
|
||||
}
|
||||
|
||||
private let appGroup: String
|
||||
|
||||
private let tunnelBundleIdentifier: (VPNProtocolType) -> String
|
||||
|
||||
private let defaults: UserDefaults
|
||||
|
||||
private let vpn: NetworkExtensionVPN
|
||||
|
||||
private let dataCountInterval: TimeInterval
|
||||
|
||||
// MARK: State
|
||||
|
||||
private var currentState: ObservableState?
|
||||
|
||||
private let vpnState = CurrentValueSubject<AtomicState, Never>(.init())
|
||||
|
||||
private var dataCountTimer: AnyCancellable?
|
||||
|
||||
private var cancellables: Set<AnyCancellable> = []
|
||||
|
||||
// MARK: Protocol specific
|
||||
|
||||
private var currentBundleIdentifier: String?
|
||||
|
||||
public init(appGroup: String, tunnelBundleIdentifier: @escaping (VPNProtocolType) -> String, dataCountInterval: TimeInterval = 3.0) {
|
||||
self.appGroup = appGroup
|
||||
self.tunnelBundleIdentifier = tunnelBundleIdentifier
|
||||
guard let defaults = UserDefaults(suiteName: appGroup) else {
|
||||
fatalError("No entitlements for group '\(appGroup)'")
|
||||
}
|
||||
self.defaults = defaults
|
||||
vpn = NetworkExtensionVPN()
|
||||
self.dataCountInterval = dataCountInterval
|
||||
|
||||
registerNotification(withName: VPNNotification.didReinstall) {
|
||||
self.onVPNReinstall($0)
|
||||
}
|
||||
registerNotification(withName: VPNNotification.didChangeStatus) {
|
||||
self.onVPNStatus($0)
|
||||
}
|
||||
registerNotification(withName: VPNNotification.didFail) {
|
||||
self.onVPNFail($0)
|
||||
}
|
||||
Task {
|
||||
await vpn.prepare()
|
||||
}
|
||||
}
|
||||
|
||||
private func registerNotification(withName name: Notification.Name, perform: @escaping (Notification) -> Void) {
|
||||
NotificationCenter.default.publisher(for: name, object: nil)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: perform)
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
// MARK: Strategy
|
||||
|
||||
public func observe(into state: VPNManager.ObservableState) {
|
||||
currentState = state
|
||||
|
||||
// use this to drop redundant NE notifications
|
||||
vpnState
|
||||
.removeDuplicates()
|
||||
.sink {
|
||||
self.currentState?.isEnabled = $0.isEnabled
|
||||
self.currentState?.vpnStatus = $0.vpnStatus
|
||||
}.store(in: &cancellables)
|
||||
}
|
||||
|
||||
public func reinstate(configuration: VPNConfiguration) async {
|
||||
guard let vpnType = configuration.neConfiguration as? VPNProtocolProviding else {
|
||||
fatalError("Configuration must implement VPNProtocolProviding")
|
||||
}
|
||||
let bundleIdentifier = tunnelBundleIdentifier(vpnType.vpnProtocol)
|
||||
currentBundleIdentifier = bundleIdentifier
|
||||
|
||||
pp_log.verbose("Configuration: \(configuration)")
|
||||
pp_log.info("Reinstating VPN...")
|
||||
do {
|
||||
try await vpn.install(
|
||||
bundleIdentifier,
|
||||
configuration: configuration.neConfiguration,
|
||||
extra: configuration.neExtra
|
||||
)
|
||||
} catch {
|
||||
pp_log.error("Unable to install: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
public func connect(configuration: VPNConfiguration) async {
|
||||
guard let vpnType = configuration.neConfiguration as? VPNProtocolProviding else {
|
||||
fatalError("Configuration must implement VPNProtocolProviding")
|
||||
}
|
||||
let bundleIdentifier = tunnelBundleIdentifier(vpnType.vpnProtocol)
|
||||
currentBundleIdentifier = bundleIdentifier
|
||||
|
||||
pp_log.verbose("Configuration: \(configuration)")
|
||||
pp_log.info("Reconnecting VPN...")
|
||||
do {
|
||||
try await vpn.reconnect(
|
||||
bundleIdentifier,
|
||||
configuration: configuration.neConfiguration,
|
||||
extra: configuration.neExtra,
|
||||
after: .seconds(2)
|
||||
)
|
||||
} catch {
|
||||
pp_log.error("Unable to connect: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
public func disconnect() async {
|
||||
await vpn.disconnect()
|
||||
}
|
||||
|
||||
public func removeConfigurations() async {
|
||||
await vpn.uninstall()
|
||||
|
||||
// XXX: force isEnabled to false as it's not properly notified by NetworkExtension
|
||||
vpnState.send(AtomicState(
|
||||
isEnabled: false,
|
||||
vpnStatus: vpnState.value.vpnStatus
|
||||
))
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
private func onVPNReinstall(_ notification: Notification) {
|
||||
guard isRelevantNotification(notification) else {
|
||||
return
|
||||
}
|
||||
|
||||
vpnState.send(AtomicState(
|
||||
isEnabled: notification.vpnIsEnabled,
|
||||
vpnStatus: vpnState.value.vpnStatus
|
||||
))
|
||||
}
|
||||
|
||||
private func onVPNStatus(_ notification: Notification) {
|
||||
|
||||
// assume first notified identifier to be the relevant one
|
||||
// in order to restore VPN status on app launch
|
||||
if currentBundleIdentifier == nil {
|
||||
currentBundleIdentifier = notification.vpnBundleIdentifier
|
||||
}
|
||||
guard isRelevantNotification(notification) else {
|
||||
return
|
||||
}
|
||||
|
||||
var error: Error?
|
||||
|
||||
switch notification.vpnStatus {
|
||||
case .connected:
|
||||
startCountingData()
|
||||
|
||||
case .disconnecting:
|
||||
error = lastError(withBundleIdentifier: notification.vpnBundleIdentifier)
|
||||
|
||||
case .disconnected:
|
||||
error = lastError(withBundleIdentifier: notification.vpnBundleIdentifier)
|
||||
stopCountingData()
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
vpnState.send(AtomicState(
|
||||
isEnabled: notification.vpnIsEnabled,
|
||||
vpnStatus: notification.vpnStatus
|
||||
))
|
||||
currentState?.lastError = error
|
||||
}
|
||||
|
||||
private func onVPNFail(_ notification: Notification) {
|
||||
vpnState.send(AtomicState(
|
||||
isEnabled: notification.vpnIsEnabled,
|
||||
vpnStatus: vpnState.value.vpnStatus
|
||||
))
|
||||
currentState?.lastError = notification.vpnError
|
||||
}
|
||||
|
||||
private func isRelevantNotification(_ notification: Notification) -> Bool {
|
||||
guard let notificationTunnelIdentifier = notification.vpnBundleIdentifier else {
|
||||
return false
|
||||
}
|
||||
guard notificationTunnelIdentifier == currentBundleIdentifier else {
|
||||
pp_log.debug("Skipping not relevant notification from \(notificationTunnelIdentifier)")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// MARK: Data count
|
||||
|
||||
private func onDataCount(_: Date) {
|
||||
switch vpnState.value.vpnStatus {
|
||||
case .connected:
|
||||
guard let currentDataCount = currentDataCount else {
|
||||
return
|
||||
}
|
||||
currentState?.dataCount = currentDataCount
|
||||
|
||||
default:
|
||||
currentState?.dataCount = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func startCountingData() {
|
||||
guard dataCountTimer == nil else {
|
||||
return
|
||||
}
|
||||
dataCountTimer = Timer.TimerPublisher(interval: dataCountInterval, runLoop: .main, mode: .common)
|
||||
.autoconnect()
|
||||
.sink {
|
||||
self.onDataCount($0)
|
||||
}
|
||||
}
|
||||
|
||||
private func stopCountingData() {
|
||||
dataCountTimer?.cancel()
|
||||
dataCountTimer = nil
|
||||
|
||||
currentState?.dataCount = nil
|
||||
}
|
||||
|
||||
// MARK: Pulled
|
||||
|
||||
public func serverConfiguration(forProtocol vpnProtocol: VPNProtocolType) -> Any? {
|
||||
switch vpnProtocol {
|
||||
case .openVPN:
|
||||
return defaults.openVPNServerConfiguration
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func debugLogURL(forProtocol vpnProtocol: VPNProtocolType) -> URL? {
|
||||
switch vpnProtocol {
|
||||
case .openVPN:
|
||||
return defaults.openVPNURLForDebugLog(appGroup: appGroup)
|
||||
|
||||
default:
|
||||
return defaults.wireGuardURLForDebugLog(appGroup: appGroup)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Callbacks
|
||||
|
||||
private func lastError(withBundleIdentifier bundleIdentifier: String?) -> Error? {
|
||||
switch bundleIdentifier {
|
||||
case tunnelBundleIdentifier(.openVPN):
|
||||
return defaults.openVPNLastError
|
||||
|
||||
case tunnelBundleIdentifier(.wireGuard):
|
||||
return defaults.wireGuardLastError
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private var currentDataCount: DataCount? {
|
||||
switch currentBundleIdentifier {
|
||||
case tunnelBundleIdentifier(.openVPN):
|
||||
return defaults.openVPNDataCount
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
//
|
||||
// ProfileManagerStrategy+CoreData.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 4/9/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import PassepartoutUtils
|
||||
|
||||
extension ProfileManager {
|
||||
public class CoreDataStrategy: ProfileManagerStrategy {
|
||||
private let profileRepository: ProfileRepository
|
||||
|
||||
private let fetchedHeaders: FetchedValueHolder<[UUID: Profile.Header]>
|
||||
|
||||
public init(persistence: Persistence) {
|
||||
profileRepository = ProfileRepository(persistence.context)
|
||||
fetchedHeaders = profileRepository.fetchedHeaders()
|
||||
}
|
||||
|
||||
public var allHeaders: [UUID: Profile.Header] {
|
||||
fetchedHeaders.value
|
||||
}
|
||||
|
||||
public func profile(withId id: UUID) -> Profile? {
|
||||
profileRepository.profile(withId: id)
|
||||
}
|
||||
|
||||
public func saveProfiles(_ profiles: [Profile]) {
|
||||
do {
|
||||
try profileRepository.saveProfiles(profiles)
|
||||
} catch {
|
||||
pp_log.error("Unable to save profile: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
public func removeProfiles(withIds ids: [UUID]) {
|
||||
profileRepository.removeProfiles(withIds: ids)
|
||||
}
|
||||
|
||||
public func willUpdateProfiles() -> AnyPublisher<[UUID : Profile.Header], Never> {
|
||||
fetchedHeaders.$value
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,15 +4,15 @@
|
|||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "PassepartoutCore",
|
||||
name: "PassepartoutLibrary",
|
||||
platforms: [
|
||||
.iOS(.v14), .macOS(.v11)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "PassepartoutCore",
|
||||
targets: ["PassepartoutCore"]),
|
||||
name: "PassepartoutLibrary",
|
||||
targets: ["PassepartoutLibrary"]),
|
||||
.library(
|
||||
name: "OpenVPNAppExtension",
|
||||
targets: ["OpenVPNAppExtension"]),
|
||||
|
@ -33,26 +33,41 @@ let package = Package(
|
|||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
name: "PassepartoutCore",
|
||||
name: "PassepartoutLibrary",
|
||||
dependencies: [
|
||||
"PassepartoutVPN"
|
||||
]),
|
||||
.target(
|
||||
name: "PassepartoutVPN",
|
||||
dependencies: [
|
||||
"PassepartoutProfiles",
|
||||
"PassepartoutProviders"
|
||||
.product(name: "TunnelKitLZO", package: "TunnelKit")
|
||||
]),
|
||||
.target(
|
||||
name: "PassepartoutProfiles",
|
||||
dependencies: [
|
||||
"PassepartoutProviders",
|
||||
.product(name: "TunnelKit", package: "TunnelKit"),
|
||||
.product(name: "TunnelKitOpenVPN", package: "TunnelKit"),
|
||||
.product(name: "TunnelKitWireGuard", package: "TunnelKit"),
|
||||
.product(name: "TunnelKitLZO", package: "TunnelKit")
|
||||
"PassepartoutProviders"
|
||||
]),
|
||||
.target(
|
||||
name: "PassepartoutProviders",
|
||||
dependencies: ["PassepartoutServices"]),
|
||||
dependencies: [
|
||||
"PassepartoutCore",
|
||||
"PassepartoutServices"
|
||||
]),
|
||||
.target(
|
||||
name: "PassepartoutCore",
|
||||
dependencies: [
|
||||
.product(name: "TunnelKit", package: "TunnelKit"),
|
||||
.product(name: "TunnelKitOpenVPN", package: "TunnelKit"),
|
||||
.product(name: "TunnelKitWireGuard", package: "TunnelKit"),
|
||||
.product(name: "GenericJSON", package: "generic-json-swift")
|
||||
]),
|
||||
//
|
||||
.target(
|
||||
name: "PassepartoutServices",
|
||||
dependencies: ["PassepartoutUtils"],
|
||||
dependencies: [
|
||||
"PassepartoutUtils",
|
||||
],
|
||||
resources: [
|
||||
.copy("API")
|
||||
]),
|
||||
|
@ -62,6 +77,7 @@ let package = Package(
|
|||
.product(name: "GenericJSON", package: "generic-json-swift"),
|
||||
"SwiftyBeaver"
|
||||
]),
|
||||
//
|
||||
.target(
|
||||
name: "OpenVPNAppExtension",
|
||||
dependencies: [
|
||||
|
@ -74,8 +90,8 @@ let package = Package(
|
|||
.product(name: "TunnelKitWireGuardAppExtension", package: "TunnelKit")
|
||||
]),
|
||||
// .testTarget(
|
||||
// name: "PassepartoutCoreTests",
|
||||
// dependencies: ["PassepartoutCore"]),
|
||||
// name: "PassepartoutLibraryTests",
|
||||
// dependencies: ["PassepartoutLibrary"]),
|
||||
// .testTarget(
|
||||
// name: "PassepartoutProfilesTests",
|
||||
// dependencies: ["PassepartoutProfiles"]),
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
import Foundation
|
||||
import TunnelKitCore
|
||||
import PassepartoutProviders
|
||||
|
||||
extension Profile {
|
||||
public func hostAccount() -> Profile.Account? {
|
||||
|
@ -99,8 +98,4 @@ extension Profile.Host: ProfileSubtype {
|
|||
fatalError("No VPN settings found")
|
||||
}
|
||||
}
|
||||
|
||||
public func requiresCredentials(forProtocol vpnProtocol: VPNProtocolType) -> Bool {
|
||||
return vpnProtocol == .openVPN && (ovpnSettings?.configuration.authUserPass ?? false)
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutUtils
|
||||
|
||||
extension Profile.NetworkSettings {
|
||||
public var isAutomaticGateway: Bool {
|
|
@ -24,7 +24,6 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutUtils
|
||||
|
||||
extension Profile.OnDemand {
|
||||
public var withMobileNetwork: Bool {
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Profile+Extensions.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 3/13/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Profile {
|
||||
public var isProvider: Bool {
|
||||
return provider != nil
|
||||
}
|
||||
|
||||
public var vpnProtocols: [VPNProtocolType] {
|
||||
if isProvider {
|
||||
return provider?.vpnProtocols ?? []
|
||||
} else {
|
||||
return host?.vpnProtocols ?? []
|
||||
}
|
||||
}
|
||||
|
||||
public var account: Profile.Account {
|
||||
get {
|
||||
if isProvider {
|
||||
return providerAccount() ?? .init()
|
||||
} else {
|
||||
return hostAccount() ?? .init()
|
||||
}
|
||||
}
|
||||
set {
|
||||
if isProvider {
|
||||
setProviderAccount(newValue)
|
||||
} else {
|
||||
setHostAccount(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
import Foundation
|
||||
import TunnelKitCore
|
||||
import PassepartoutProviders
|
||||
import PassepartoutUtils
|
||||
|
||||
extension Profile {
|
||||
public init(_ providerMetadata: ProviderMetadata, server: ProviderServer) {
|
||||
|
@ -42,8 +40,11 @@ extension Profile {
|
|||
|
||||
self.init(name: providerMetadata.fullName, provider: provider)
|
||||
}
|
||||
|
||||
public var providerName: String? {
|
||||
provider?.name
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public func providerServer(_ providerManager: ProviderManager) -> ProviderServer? {
|
||||
guard let serverId = provider?.vpnSettings[currentVPNProtocol]?.serverId else {
|
||||
return nil
|
||||
|
@ -102,52 +103,8 @@ extension Profile {
|
|||
}
|
||||
}
|
||||
|
||||
extension Profile {
|
||||
|
||||
@MainActor
|
||||
public func providerOpenVPNSettings(withManager providerManager: ProviderManager) throws -> Profile.OpenVPNSettings {
|
||||
guard let _ = provider else {
|
||||
fatalError("Not a provider")
|
||||
}
|
||||
|
||||
// infer remotes from preset + server
|
||||
guard let server = providerServer(providerManager) else {
|
||||
throw PassepartoutError.missingProviderServer
|
||||
}
|
||||
guard let preset = providerPreset(server) else {
|
||||
throw PassepartoutError.missingProviderPreset
|
||||
}
|
||||
guard var builder = preset.openVPNConfiguration?.builder() else {
|
||||
fatalError("Preset \(preset.id) has no OpenVPN configuration")
|
||||
}
|
||||
try builder.setRemotes(from: preset, with: server, excludingHostname: !networkSettings.resolvesHostname)
|
||||
|
||||
// enforce default gateway
|
||||
builder.routingPolicies = [.IPv4, .IPv6]
|
||||
|
||||
// apply provider settings (username, custom endpoint)
|
||||
let cfg = builder.build()
|
||||
return OpenVPNSettings(
|
||||
configuration: cfg,
|
||||
account: providerAccount(),
|
||||
customEndpoint: providerCustomEndpoint()
|
||||
)
|
||||
}
|
||||
|
||||
public func providerWireGuardSettings(withManager providerManager: ProviderManager) throws -> Profile.WireGuardSettings {
|
||||
guard let _ = provider else {
|
||||
fatalError("Not a provider")
|
||||
}
|
||||
fatalError("WireGuard not yet implemented for providers")
|
||||
}
|
||||
}
|
||||
|
||||
extension Profile.Provider: ProfileSubtype {
|
||||
public var vpnProtocols: [VPNProtocolType] {
|
||||
return vpnSettings.keys.sorted()
|
||||
}
|
||||
|
||||
public func requiresCredentials(forProtocol vpnProtocol: VPNProtocolType) -> Bool {
|
||||
return name.requiresCredentials(forProtocol: vpnProtocol)
|
||||
Array(vpnSettings.keys)
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// VPNProtocolType+Extensions.swift
|
||||
// CurrentProfileProviding.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 4/7/22.
|
||||
// Created by Davide De Rosa on 6/22/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
|
@ -25,8 +25,8 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
extension VPNProtocolType: Comparable {
|
||||
public static func <(lhs: Self, rhs: Self) -> Bool {
|
||||
return lhs.description < rhs.description
|
||||
}
|
||||
public protocol CurrentProfileProviding {
|
||||
associatedtype WrappedType: WrappedProfile
|
||||
|
||||
var currentProfile: WrappedType { get }
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// CurrentVPNStateProviding.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/22/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol CurrentVPNStateProviding {
|
||||
associatedtype WrappedType: WrappedVPNState
|
||||
|
||||
var currentState: WrappedType { get }
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// ProfileManager.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/20/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
public protocol ProfileManager {
|
||||
typealias ProfileEx = (profile: Profile, isReady: Bool)
|
||||
|
||||
var activeProfileId: UUID? { get }
|
||||
|
||||
var activeProfileIdPublisher: Published<UUID?>.Publisher { get }
|
||||
|
||||
var currentProfileId: UUID? { get set }
|
||||
|
||||
var didCreateProfile: PassthroughSubject<Profile, Never> { get }
|
||||
|
||||
var headers: [Profile.Header] { get }
|
||||
|
||||
func isExistingProfile(withId id: UUID) -> Bool
|
||||
|
||||
func isExistingProfile(withName name: String) -> Bool
|
||||
|
||||
func liveProfileEx(withId id: UUID) throws -> ProfileEx
|
||||
|
||||
func makeProfileReady(_ profile: Profile) async throws
|
||||
|
||||
func saveProfile(_ profile: Profile, isActive: Bool?, updateIfCurrent: Bool)
|
||||
|
||||
func savePassword(forProfile profile: Profile)
|
||||
|
||||
func passwordReference(forProfile profile: Profile) -> Data?
|
||||
|
||||
func removeProfiles(withIds ids: [UUID])
|
||||
|
||||
@available(*, deprecated, message: "only use for testing")
|
||||
func removeAllProfiles()
|
||||
|
||||
func duplicateProfile(withId id: UUID, setAsCurrent: Bool)
|
||||
|
||||
func profile(withHeader header: Profile.Header, fromContents contents: String, originalURL: URL?, passphrase: String?) throws -> Profile
|
||||
|
||||
func persist()
|
||||
|
||||
func observeUpdates()
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// ProfileManagerWithCurrentProfile.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/22/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol ProfileManagerWithCurrentProfile: ProfileManager, CurrentProfileProviding {
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// ProviderManager.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/19/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
public protocol ProviderManager {
|
||||
func allProviders() -> [ProviderMetadata]
|
||||
|
||||
func provider(withName name: ProviderName) -> ProviderMetadata?
|
||||
|
||||
func isAvailable(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> Bool
|
||||
|
||||
func defaultUsername(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> String?
|
||||
|
||||
func lastUpdate(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> Date?
|
||||
|
||||
func categories(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> [ProviderCategory]
|
||||
|
||||
func servers(forLocation location: ProviderLocation) -> [ProviderServer]
|
||||
|
||||
func server(_ name: ProviderName, vpnProtocol: VPNProtocolType, apiId: String) -> ProviderServer?
|
||||
|
||||
func anyDefaultServer(_ name: ProviderName, vpnProtocol: VPNProtocolType) -> ProviderServer?
|
||||
|
||||
func server(withId id: String) -> ProviderServer?
|
||||
|
||||
func fetchProvidersIndexPublisher(priority: ProviderManagerFetchPriority) -> AnyPublisher<Void, Error>
|
||||
|
||||
func fetchProviderPublisher(
|
||||
withName providerName: ProviderName,
|
||||
vpnProtocol: VPNProtocolType,
|
||||
priority: ProviderManagerFetchPriority
|
||||
) -> AnyPublisher<Void, Error>
|
||||
|
||||
func reset()
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// ProviderManagerFetchPriority.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/22/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum ProviderManagerFetchPriority {
|
||||
case bundle
|
||||
|
||||
case remote
|
||||
|
||||
case remoteThenBundle
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// VPNManager.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/22/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
public protocol VPNManager {
|
||||
var lastError: Error? { get }
|
||||
|
||||
var configurationError: PassthroughSubject<VPNConfigurationError, Never> { get }
|
||||
|
||||
var tunnelLogPath: String? { get set }
|
||||
|
||||
var tunnelLogFormat: String? { get set }
|
||||
|
||||
var masksPrivateData: Bool { get set }
|
||||
|
||||
func connectWithActiveProfile() async throws
|
||||
|
||||
@discardableResult
|
||||
func connect(with profileId: UUID) async throws -> Profile
|
||||
|
||||
@discardableResult
|
||||
func connect(with profileId: UUID, toServer newServerId: String) async throws -> Profile
|
||||
|
||||
func modifyActiveProfile(_ block: (inout Profile) -> Void) async throws
|
||||
|
||||
func toggle() -> Bool
|
||||
|
||||
func disable() async
|
||||
|
||||
func uninstall() async
|
||||
|
||||
func serverConfiguration(forProtocol vpnProtocol: VPNProtocolType) -> Any?
|
||||
|
||||
func debugLogURL(forProtocol vpnProtocol: VPNProtocolType) -> URL?
|
||||
|
||||
func observeUpdates()
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// VPNManagerWithCurrentState.swift
|
||||
// Passepartout
|
||||
//
|
||||
// Created by Davide De Rosa on 6/22/22.
|
||||
// Copyright (c) 2022 Davide De Rosa. All rights reserved.
|
||||
//
|
||||
// https://github.com/passepartoutvpn
|
||||
//
|
||||
// This file is part of Passepartout.
|
||||
//
|
||||
// Passepartout is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Passepartout is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol VPNManagerWithCurrentState: VPNManager, CurrentVPNStateProviding {
|
||||
}
|
|
@ -24,7 +24,6 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PassepartoutProviders
|
||||
|
||||
extension Profile {
|
||||
public struct Header: Codable, Identifiable, Hashable {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue