Refactor library into domain + impl

This commit is contained in:
Davide De Rosa 2022-06-23 23:31:01 +02:00
parent 8504998bbb
commit 9a8477225e
239 changed files with 1713 additions and 1415 deletions

4
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "Submodules/fastlane-ci-templates"] [submodule "Submodules/fastlane-ci-templates"]
path = Submodules/fastlane-ci-templates path = Submodules/fastlane-ci-templates
url = https://github.com/keeshux/fastlane-ci-templates url = https://github.com/keeshux/fastlane-ci-templates
[submodule "PassepartoutCore/Sources/PassepartoutServices/API"] [submodule "PassepartoutLibrary/Sources/PassepartoutServices/API"]
path = PassepartoutCore/Sources/PassepartoutServices/API path = PassepartoutLibrary/Sources/PassepartoutServices/API
url = https://github.com/passepartoutvpn/api url = https://github.com/passepartoutvpn/api

2
API
View File

@ -1 +1 @@
PassepartoutCore/Sources/PassepartoutServices/API/ PassepartoutLibrary/Sources/PassepartoutServices/API/

View File

@ -47,7 +47,6 @@
0E49F6BF27D764AF00385834 /* EndpointAdvancedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49F6BE27D764AF00385834 /* EndpointAdvancedView.swift */; }; 0E49F6BF27D764AF00385834 /* EndpointAdvancedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49F6BE27D764AF00385834 /* EndpointAdvancedView.swift */; };
0E53249927D26B51002565C3 /* ProductManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E53249627D26B51002565C3 /* ProductManager.swift */; }; 0E53249927D26B51002565C3 /* ProductManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E53249627D26B51002565C3 /* ProductManager.swift */; };
0E53249D27D28FC7002565C3 /* Kvitto in Frameworks */ = {isa = PBXBuildFile; productRef = 0E53249C27D28FC7002565C3 /* Kvitto */; }; 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 */; }; 0E5324A927D2AC55002565C3 /* LongContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5324A827D2AC55002565C3 /* LongContentView.swift */; };
0E5349BE27C16A4500C71BB3 /* StyledPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5349BD27C16A4500C71BB3 /* StyledPicker.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 */; }; 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 */; }; 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 */; }; 0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075F27EC587900208AD9 /* SwiftGen+Strings.swift */; };
0EBE880F281B18DE0090D9E6 /* ProfileRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE880E281B18DE0090D9E6 /* ProfileRow.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 */; }; 0ECF71EE27B6A99300CDB528 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECF71ED27B6A99300CDB528 /* AccountView.swift */; };
0ED1D6DC27DBA41700983466 /* DiagnosticsView+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED1D6DB27DBA41700983466 /* DiagnosticsView+OpenVPN.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 */; }; 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 */; }; 0EDE02C227F61C79000FBE3C /* EditableTextList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE02C127F61C79000FBE3C /* EditableTextList.swift */; };
0EE11CD2280D8317003BE431 /* InfoMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE11CD1280D8317003BE431 /* InfoMenu.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 */; }; 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 */; }; 0EF0FAF627DD0211007EB181 /* PaywallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF0FAF527DD0211007EB181 /* PaywallView.swift */; };
0EF0FAF727DD159C007EB181 /* IntentDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA591122733DD4E0096F796 /* IntentDispatcher.swift */; }; 0EF0FAF727DD159C007EB181 /* IntentDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA591122733DD4E0096F796 /* IntentDispatcher.swift */; };
0EF0FAF927DD212C007EB181 /* IntentActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF0FAF827DD212C007EB181 /* IntentActivity.swift */; }; 0EF0FAF927DD212C007EB181 /* IntentActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF0FAF827DD212C007EB181 /* IntentActivity.swift */; };
@ -131,13 +130,6 @@
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
0E6059C627FCC33D003F4063 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0E9AAA60259F7D7E003FAFF1;
remoteInfo = "PassepartoutLauncher-macOS";
};
0EB2B1492733FB6F007705AB /* PBXContainerItemProxy */ = { 0EB2B1492733FB6F007705AB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = 0E57F63020C83FC5008323CF /* Project object */; containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
@ -236,7 +228,6 @@
0E49F6BC27D7639000385834 /* EndpointAdvancedView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EndpointAdvancedView+WireGuard.swift"; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 0ED1D6DD27DBA42100983466 /* DiagnosticsView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiagnosticsView+WireGuard.swift"; sourceTree = "<group>"; };
@ -358,8 +349,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0E9C3B6F27FC573E00D0F02E /* CloudKit.framework in Frameworks */, 0E9C3B6F27FC573E00D0F02E /* CloudKit.framework in Frameworks */,
0EED0BB92733CEDA00C9FC68 /* PassepartoutCore in Frameworks */,
0E53249D27D28FC7002565C3 /* Kvitto in Frameworks */, 0E53249D27D28FC7002565C3 /* Kvitto in Frameworks */,
0ECB78EC2863A21600B0E460 /* PassepartoutLibrary in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -602,7 +593,6 @@
0E293859285A7489002A6E0E /* Context */, 0E293859285A7489002A6E0E /* Context */,
0E92781227E7CD530057BB81 /* InApp */, 0E92781227E7CD530057BB81 /* InApp */,
0E34A2B827CAA8EA00C73B67 /* L10n */, 0E34A2B827CAA8EA00C73B67 /* L10n */,
0ECB78D5285F508B00B0E460 /* Reusable */,
0E9E5AE227B44CF1008C95DA /* Localizable.strings */, 0E9E5AE227B44CF1008C95DA /* Localizable.strings */,
); );
path = AppShared; path = AppShared;
@ -626,14 +616,6 @@
path = Constants; path = Constants;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
0ECB78D5285F508B00B0E460 /* Reusable */ = {
isa = PBXGroup;
children = (
0E5324A527D297BB002565C3 /* InApp.swift */,
);
path = Reusable;
sourceTree = "<group>";
};
0ED2B33C27D3C52900FD8EA9 /* OpenVPN */ = { 0ED2B33C27D3C52900FD8EA9 /* OpenVPN */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -673,7 +655,7 @@
0EE315DB2733104700F5D461 /* Packages */ = { 0EE315DB2733104700F5D461 /* Packages */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0EA26DC827353020000F251A /* PassepartoutCore */, 0ECB78EA2861D1F300B0E460 /* PassepartoutLibrary */,
); );
name = Packages; name = Packages;
sourceTree = "<group>"; sourceTree = "<group>";
@ -726,12 +708,11 @@
0ECF71FC27B6DA6700CDB528 /* PBXTargetDependency */, 0ECF71FC27B6DA6700CDB528 /* PBXTargetDependency */,
0EB2B14A2733FB6F007705AB /* PBXTargetDependency */, 0EB2B14A2733FB6F007705AB /* PBXTargetDependency */,
0ED2B36227D3C99100FD8EA9 /* PBXTargetDependency */, 0ED2B36227D3C99100FD8EA9 /* PBXTargetDependency */,
0E6059C727FCC33D003F4063 /* PBXTargetDependency */,
); );
name = Passepartout; name = Passepartout;
packageProductDependencies = ( packageProductDependencies = (
0EED0BB82733CEDA00C9FC68 /* PassepartoutCore */,
0E53249C27D28FC7002565C3 /* Kvitto */, 0E53249C27D28FC7002565C3 /* Kvitto */,
0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */,
); );
productName = Passepartout; productName = Passepartout;
productReference = 0E57F63820C83FC5008323CF /* Passepartout.app */; productReference = 0E57F63820C83FC5008323CF /* Passepartout.app */;
@ -944,7 +925,6 @@
0EF2213127E674BD001D0BD7 /* AddProviderViewModel.swift in Sources */, 0EF2213127E674BD001D0BD7 /* AddProviderViewModel.swift in Sources */,
0E90DFE627BACC1500EF5078 /* AddHostViewModel.swift in Sources */, 0E90DFE627BACC1500EF5078 /* AddHostViewModel.swift in Sources */,
0E34AC8227F892C40042F2AB /* OnDemandView+SSID.swift in Sources */, 0E34AC8227F892C40042F2AB /* OnDemandView+SSID.swift in Sources */,
0E5324A627D297BB002565C3 /* InApp.swift in Sources */,
0E3B7FCD27E47B3700C66F13 /* AddHostView+Name.swift in Sources */, 0E3B7FCD27E47B3700C66F13 /* AddHostView+Name.swift in Sources */,
0E7577D72816A3B200081CBE /* DestructiveButton.swift in Sources */, 0E7577D72816A3B200081CBE /* DestructiveButton.swift in Sources */,
0EF2212D27E66EB5001D0BD7 /* AddProviderView.swift in Sources */, 0EF2212D27E66EB5001D0BD7 /* AddProviderView.swift in Sources */,
@ -1059,11 +1039,6 @@
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */ /* Begin PBXTargetDependency section */
0E6059C727FCC33D003F4063 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
platformFilter = ios;
targetProxy = 0E6059C627FCC33D003F4063 /* PBXContainerItemProxy */;
};
0EB2B14A2733FB6F007705AB /* PBXTargetDependency */ = { 0EB2B14A2733FB6F007705AB /* PBXTargetDependency */ = {
isa = PBXTargetDependency; isa = PBXTargetDependency;
target = 0EDE8DBE20C86910004C739C /* OpenVPNTunnel */; target = 0EDE8DBE20C86910004C739C /* OpenVPNTunnel */;
@ -1509,6 +1484,10 @@
package = 0E53249B27D28FC7002565C3 /* XCRemoteSwiftPackageReference "Kvitto" */; package = 0E53249B27D28FC7002565C3 /* XCRemoteSwiftPackageReference "Kvitto" */;
productName = Kvitto; productName = Kvitto;
}; };
0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */ = {
isa = XCSwiftPackageProductDependency;
productName = PassepartoutLibrary;
};
0ED2B33827D3C49800FD8EA9 /* OpenVPNAppExtension */ = { 0ED2B33827D3C49800FD8EA9 /* OpenVPNAppExtension */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = OpenVPNAppExtension; productName = OpenVPNAppExtension;
@ -1517,10 +1496,6 @@
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = WireGuardAppExtension; productName = WireGuardAppExtension;
}; };
0EED0BB82733CEDA00C9FC68 /* PassepartoutCore */ = {
isa = XCSwiftPackageProductDependency;
productName = PassepartoutCore;
};
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
}; };
rootObject = 0E57F63020C83FC5008323CF /* Project object */; rootObject = 0E57F63020C83FC5008323CF /* Project object */;

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension View { extension View {
var themeIdiom: UIUserInterfaceIdiom { var themeIdiom: UIUserInterfaceIdiom {

View File

@ -25,9 +25,8 @@
import Foundation import Foundation
import Combine import Combine
import PassepartoutCore import PassepartoutLibrary
@MainActor
class AppContext { class AppContext {
private let logManager: LogManager private let logManager: LogManager

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutUtils import PassepartoutLibrary
enum AppPreference: String, KeyStoreDomainLocation { enum AppPreference: String, KeyStoreDomainLocation {
case isShowingFavorites case isShowingFavorites

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension DebugLog { extension DebugLog {
func decoratedString() -> String { func decoratedString() -> String {

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension ProviderMetadata: Identifiable, Comparable, Hashable { extension ProviderMetadata: Identifiable, Comparable, Hashable {
public var id: String { public var id: String {

View File

@ -24,17 +24,15 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
protocol ProviderProfileAvailability { protocol ProviderProfileAvailability {
var profile: Profile { get } var profile: Profile { get }
var providerManager: ProviderManager { get } var providerManager: Impl.ProviderManager { get }
} }
extension ProviderProfileAvailability { extension ProviderProfileAvailability {
@MainActor
var isProviderProfileAvailable: Bool { var isProviderProfileAvailable: Bool {
guard !profile.isPlaceholder else { guard !profile.isPlaceholder else {
return false return false

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension VPNProtocolType { extension VPNProtocolType {
static let knownFileExtensions: [String] = { static let knownFileExtensions: [String] = {

View File

@ -25,9 +25,8 @@
import Foundation import Foundation
import Intents import Intents
import PassepartoutCore import PassepartoutLibrary
@MainActor
extension IntentDispatcher { extension IntentDispatcher {
private enum IntentError: Error { private enum IntentError: Error {
case notProvider(UUID) case notProvider(UUID)

View File

@ -25,7 +25,7 @@
import Foundation import Foundation
import Intents import Intents
import PassepartoutCore import PassepartoutLibrary
class IntentDispatcher { class IntentDispatcher {
private struct Groups { private struct Groups {
@ -78,7 +78,6 @@ class IntentDispatcher {
// MARK: Donations // MARK: Donations
@MainActor
static func donateConnection(with profile: Profile, providerManager: ProviderManager) { static func donateConnection(with profile: Profile, providerManager: ProviderManager) {
let genericIntent: INIntent let genericIntent: INIntent
if let providerName = profile.header.providerName { if let providerName = profile.header.providerName {

View File

@ -28,7 +28,6 @@ import Intents
import IntentsUI import IntentsUI
import Combine import Combine
@MainActor
class IntentsManager: NSObject, ObservableObject { class IntentsManager: NSObject, ObservableObject {
@Published private(set) var isReloadingShortcuts = false @Published private(set) var isReloadingShortcuts = false
@ -36,7 +35,6 @@ class IntentsManager: NSObject, ObservableObject {
let shouldDismissIntentView = PassthroughSubject<Void, Never>() let shouldDismissIntentView = PassthroughSubject<Void, Never>()
@MainActor
override init() { override init() {
super.init() super.init()
reloadShortcuts() reloadShortcuts()

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
@main @main
struct PassepartoutApp: App { struct PassepartoutApp: App {
@ -45,8 +45,6 @@ struct PassepartoutApp: App {
} }
extension View { extension View {
@MainActor
fileprivate func onIntentActivity(_ activity: IntentActivity<VPNManager>) -> some View { fileprivate func onIntentActivity(_ activity: IntentActivity<VPNManager>) -> some View {
onContinueUserActivity(activity.name) { userActivity in onContinueUserActivity(activity.name) { userActivity in

View File

@ -26,7 +26,6 @@
import UIKit import UIKit
import StoreKit import StoreKit
@MainActor
public class Reviewer: ObservableObject { public class Reviewer: ObservableObject {
private struct Keys { private struct Keys {
static let eventCount = "Reviewer.EventCount" static let eventCount = "Reviewer.EventCount"

View File

@ -24,10 +24,10 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct AccountView: View { struct AccountView: View {
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
private let providerName: ProviderName? private let providerName: ProviderName?

View File

@ -24,13 +24,13 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
import TunnelKitOpenVPN import TunnelKitOpenVPN
import TunnelKitWireGuard import TunnelKitWireGuard
extension AddHostView { extension AddHostView {
struct NameView: View { struct NameView: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
private let url: URL private let url: URL

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
import TunnelKitOpenVPN import TunnelKitOpenVPN
import TunnelKitWireGuard import TunnelKitWireGuard
@ -52,7 +52,6 @@ extension AddHostView {
profileName = url.normalizedFilename profileName = url.normalizedFilename
} }
@MainActor
mutating func processURL( mutating func processURL(
_ url: URL, _ url: URL,
with profileManager: ProfileManager, with profileManager: ProfileManager,
@ -97,7 +96,6 @@ extension AddHostView {
} }
} }
@MainActor
mutating func addProcessedProfile(to profileManager: ProfileManager) -> Bool { mutating func addProcessedProfile(to profileManager: ProfileManager) -> Bool {
guard !processedProfile.isPlaceholder else { guard !processedProfile.isPlaceholder else {
assertionFailure("Saving profile without processing first?") assertionFailure("Saving profile without processing first?")

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct AddProfileMenu: View { struct AddProfileMenu: View {
enum ModalType: Identifiable { enum ModalType: Identifiable {

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
enum AddProfileView { enum AddProfileView {
struct Bindings { struct Bindings {
@ -71,7 +71,7 @@ enum AddProfileView {
} }
struct AccountWrapperView: View { struct AccountWrapperView: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
@Binding private var profile: Profile @Binding private var profile: Profile

View File

@ -24,11 +24,11 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension AddProviderView { extension AddProviderView {
struct NameView: View { struct NameView: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
@Binding private var profile: Profile @Binding private var profile: Profile

View File

@ -24,10 +24,10 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct AddProviderView: View { struct AddProviderView: View {
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
@ObservedObject private var productManager: ProductManager @ObservedObject private var productManager: ProductManager
@ -112,7 +112,7 @@ struct AddProviderView: View {
Button { Button {
presentOrPurchaseProvider(metadata) presentOrPurchaseProvider(metadata)
} label: { } label: {
Label(metadata.description, image: themeAssetsProviderImage(metadata.name)) Label(metadata.fullName, image: themeAssetsProviderImage(metadata.name))
}.withTrailingProgress(when: viewModel.isFetchingProvider(metadata.name)) }.withTrailingProgress(when: viewModel.isFetchingProvider(metadata.name))
} }

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension AddProviderView { extension AddProviderView {
class ViewModel: ObservableObject { class ViewModel: ObservableObject {
@ -67,7 +67,6 @@ extension AddProviderView {
@Published private(set) var errorMessage: String? @Published private(set) var errorMessage: String?
@MainActor
func selectProvider(_ metadata: ProviderMetadata, _ providerManager: ProviderManager) { func selectProvider(_ metadata: ProviderMetadata, _ providerManager: ProviderManager) {
errorMessage = nil errorMessage = nil
guard let server = providerManager.anyDefaultServer( guard let server = providerManager.anyDefaultServer(
@ -82,7 +81,6 @@ extension AddProviderView {
doSelectProvider(metadata, server) doSelectProvider(metadata, server)
} }
@MainActor
private func selectProviderAfterFetchingInfrastructure(_ metadata: ProviderMetadata, _ providerManager: ProviderManager) async { private func selectProviderAfterFetchingInfrastructure(_ metadata: ProviderMetadata, _ providerManager: ProviderManager) async {
errorMessage = nil errorMessage = nil
pendingOperation = .provider(metadata.name) pendingOperation = .provider(metadata.name)
@ -114,7 +112,6 @@ extension AddProviderView {
selectedProvider = metadata selectedProvider = metadata
} }
@MainActor
func updateIndex(_ providerManager: ProviderManager) { func updateIndex(_ providerManager: ProviderManager) {
errorMessage = nil errorMessage = nil
pendingOperation = .index pendingOperation = .index
@ -154,7 +151,6 @@ extension AddProviderView.NameView {
profileName = metadata.fullName profileName = metadata.fullName
} }
@MainActor
mutating func addProfile( mutating func addProfile(
_ profile: Profile, _ profile: Profile,
to profileManager: ProfileManager, to profileManager: ProfileManager,

View File

@ -25,7 +25,7 @@
import SwiftUI import SwiftUI
import Combine import Combine
import PassepartoutCore import PassepartoutLibrary
struct DebugLogView: View { struct DebugLogView: View {
private let url: URL private let url: URL

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
import TunnelKitOpenVPN import TunnelKitOpenVPN
extension DiagnosticsView { 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 @ObservedObject private var productManager: ProductManager

View File

@ -24,12 +24,12 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
import TunnelKitWireGuard import TunnelKitWireGuard
extension DiagnosticsView { extension DiagnosticsView {
struct WireGuardView: View { struct WireGuardView: View {
@ObservedObject private var vpnManager: VPNManager @ObservedObject private var vpnManager: Impl.VPNManager
private let providerName: ProviderName? private let providerName: ProviderName?

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct DiagnosticsView: View { struct DiagnosticsView: View {
let vpnProtocol: VPNProtocolType let vpnProtocol: VPNProtocolType

View File

@ -25,6 +25,7 @@
import SwiftUI import SwiftUI
import StoreKit import StoreKit
import PassepartoutLibrary
struct DonateView: View { struct DonateView: View {
enum AlertType: Identifiable { enum AlertType: Identifiable {

View File

@ -25,7 +25,7 @@
import SwiftUI import SwiftUI
import TunnelKitOpenVPN import TunnelKitOpenVPN
import PassepartoutCore import PassepartoutLibrary
extension EndpointAdvancedView { extension EndpointAdvancedView {
struct OpenVPNView: View { struct OpenVPNView: View {

View File

@ -24,14 +24,14 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
import TunnelKitOpenVPN import TunnelKitOpenVPN
extension EndpointView { extension EndpointView {
struct OpenVPNView: View { struct OpenVPNView: View {
@Environment(\.presentationMode) private var presentationMode @Environment(\.presentationMode) private var presentationMode
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -53,7 +53,7 @@ extension EndpointView {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile) { init(currentProfile: ObservableProfile) {
let providerManager: ProviderManager = .shared let providerManager: Impl.ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile

View File

@ -24,12 +24,12 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
import TunnelKitWireGuard import TunnelKitWireGuard
extension EndpointView { extension EndpointView {
struct WireGuardView: View { struct WireGuardView: View {
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -41,7 +41,7 @@ extension EndpointView {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile, isReadonly: Bool) { init(currentProfile: ObservableProfile, isReadonly: Bool) {
let providerManager: ProviderManager = .shared let providerManager: Impl.ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct EndpointView: View { struct EndpointView: View {
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct InfoMenu: View { struct InfoMenu: View {
enum ModalType: Identifiable { enum ModalType: Identifiable {

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct NetworkSettingsView: View { struct NetworkSettingsView: View {
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension OnDemandView { extension OnDemandView {
struct SSIDList: View { struct SSIDList: View {

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct OnDemandView: View { struct OnDemandView: View {
@ObservedObject private var productManager: ProductManager @ObservedObject private var productManager: ProductManager

View File

@ -24,11 +24,11 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension OrganizerView { extension OrganizerView {
struct ProfilesList: View { struct ProfilesList: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
init() { init() {
profileManager = .shared profileManager = .shared

View File

@ -24,15 +24,15 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension OrganizerView { extension OrganizerView {
struct SceneView: View { struct SceneView: View {
@Environment(\.scenePhase) private var scenePhase @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 @ObservedObject private var productManager: ProductManager

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct OrganizerView: View { struct OrganizerView: View {
enum AlertType: Identifiable { enum AlertType: Identifiable {
@ -81,7 +81,7 @@ struct OrganizerView: View {
.themePrimaryView() .themePrimaryView()
// VPN configuration error publisher (no need to observe VPNManager) // 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) alertType = .error($0.profile.header.name, $0.error.localizedAppDescription)
} }
} }

View File

@ -25,7 +25,7 @@
import SwiftUI import SwiftUI
import StoreKit import StoreKit
import PassepartoutCore import PassepartoutLibrary
extension PaywallView { extension PaywallView {
struct PurchaseView: View { struct PurchaseView: View {

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct ProfileRow: View { struct ProfileRow: View {
let header: Profile.Header let header: Profile.Header

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct ConfigurationSection: View { struct ConfigurationSection: View {

View File

@ -24,11 +24,11 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct DiagnosticsSection: View { struct DiagnosticsSection: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct ExtraSection: View { struct ExtraSection: View {

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct MainMenu: View { 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 @ObservedObject private var currentProfile: ObservableProfile
@ -200,7 +200,7 @@ extension ProfileView {
} }
struct DuplicateButton: View { struct DuplicateButton: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
private let header: Profile.Header private let header: Profile.Header

View File

@ -24,11 +24,11 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct ProviderSection: View, ProviderProfileAvailability { struct ProviderSection: View, ProviderProfileAvailability {
@ObservedObject var providerManager: ProviderManager @ObservedObject var providerManager: Impl.ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -24,13 +24,13 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct RenameView: View { struct RenameView: View {
@Environment(\.presentationMode) private var presentationMode @Environment(\.presentationMode) private var presentationMode
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile

View File

@ -24,11 +24,11 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
extension ProfileView { extension ProfileView {
struct VPNSection: View { struct VPNSection: View {
@ObservedObject private var profileManager: ProfileManager @ObservedObject private var profileManager: Impl.ProfileManager
private let profileId: UUID private let profileId: UUID

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct ProfileView: View { struct ProfileView: View {
enum ModalType: Int, Identifiable { enum ModalType: Int, Identifiable {
@ -56,7 +56,7 @@ struct ProfileView: View {
@State private var modalType: ModalType? @State private var modalType: ModalType?
init() { init() {
currentProfile = ProfileManager.shared.currentProfile currentProfile = Impl.ProfileManager.shared.currentProfile
} }
var body: some View { var body: some View {

View File

@ -24,10 +24,10 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct ProviderLocationView: View, ProviderProfileAvailability { struct ProviderLocationView: View, ProviderProfileAvailability {
@ObservedObject var providerManager: ProviderManager @ObservedObject var providerManager: Impl.ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -64,7 +64,7 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile, isEditable: Bool, isPresented: Binding<Bool>) { init(currentProfile: ObservableProfile, isEditable: Bool, isPresented: Binding<Bool>) {
let providerManager: ProviderManager = .shared let providerManager: Impl.ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile
@ -268,7 +268,7 @@ extension ProviderLocationView {
} }
struct ServerListView: View { struct ServerListView: View {
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
private let location: ProviderLocation private let location: ProviderLocation

View File

@ -24,12 +24,12 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct ProviderPresetView: View { struct ProviderPresetView: View {
@Environment(\.presentationMode) private var presentationMode @Environment(\.presentationMode) private var presentationMode
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
@ObservedObject private var currentProfile: ObservableProfile @ObservedObject private var currentProfile: ObservableProfile
@ -39,7 +39,7 @@ struct ProviderPresetView: View {
// XXX: do not escape mutating 'self', use constant providerManager // XXX: do not escape mutating 'self', use constant providerManager
init(currentProfile: ObservableProfile) { init(currentProfile: ObservableProfile) {
let providerManager: ProviderManager = .shared let providerManager: Impl.ProviderManager = .shared
self.providerManager = providerManager self.providerManager = providerManager
self.currentProfile = currentProfile self.currentProfile = currentProfile

View File

@ -25,7 +25,7 @@
import SwiftUI import SwiftUI
import MessageUI import MessageUI
import PassepartoutCore import PassepartoutLibrary
struct ReportIssueView: View { struct ReportIssueView: View {
@Binding private var isPresented: Bool @Binding private var isPresented: Bool

View File

@ -25,11 +25,11 @@
import SwiftUI import SwiftUI
import Intents import Intents
import PassepartoutCore import PassepartoutLibrary
extension ShortcutsView { extension ShortcutsView {
struct AddView: View { struct AddView: View {
@ObservedObject private var providerManager: ProviderManager @ObservedObject private var providerManager: Impl.ProviderManager
@StateObject private var pendingProfile = ObservableProfile() @StateObject private var pendingProfile = ObservableProfile()

View File

@ -25,7 +25,7 @@
import SwiftUI import SwiftUI
import Intents import Intents
import PassepartoutCore import PassepartoutLibrary
struct ShortcutsView: View { struct ShortcutsView: View {
enum ModalType: Identifiable { enum ModalType: Identifiable {

View File

@ -24,10 +24,10 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct VPNStatusText: View { struct VPNStatusText: View {
@ObservedObject private var currentVPNState: VPNManager.ObservableState @ObservedObject private var currentVPNState: ObservableVPNState
let isActiveProfile: Bool let isActiveProfile: Bool

View File

@ -24,14 +24,14 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
struct VPNToggle: View { 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 @ObservedObject private var productManager: ProductManager
@ -113,7 +113,7 @@ struct VPNToggle: View {
IntentDispatcher.donateDisableVPN() IntentDispatcher.donateDisableVPN()
IntentDispatcher.donateConnection( IntentDispatcher.donateConnection(
with: profile, with: profile,
providerManager: .shared providerManager: Impl.ProviderManager.shared
) )
} }
} }

View File

@ -24,7 +24,7 @@
// //
import SwiftUI import SwiftUI
import PassepartoutCore import PassepartoutLibrary
import SwiftyBeaver import SwiftyBeaver
extension View { extension View {

View File

@ -25,7 +25,7 @@
import Foundation import Foundation
import UniformTypeIdentifiers import UniformTypeIdentifiers
import PassepartoutCore import PassepartoutLibrary
import SwiftyBeaver import SwiftyBeaver
extension Constants { extension Constants {

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension CoreContext { extension CoreContext {
static let shared = CoreContext(store: UserDefaultsStore(defaults: .standard)) static let shared = CoreContext(store: UserDefaultsStore(defaults: .standard))
@ -34,20 +34,18 @@ extension UpgradeManager {
static let shared = CoreContext.shared.upgradeManager static let shared = CoreContext.shared.upgradeManager
} }
extension ProfileManager { extension Impl.ProfileManager {
static let shared = CoreContext.shared.profileManager static let shared = CoreContext.shared.profileManager
} }
extension ProviderManager { extension Impl.ProviderManager {
static let shared = CoreContext.shared.providerManager static let shared = CoreContext.shared.providerManager
} }
extension VPNManager { extension Impl.VPNManager {
static let shared = CoreContext.shared.vpnManager static let shared = CoreContext.shared.vpnManager
} }
extension VPNManager.ObservableState { extension ObservableVPNState {
@MainActor
static let shared = CoreContext.shared.vpnManager.currentState static let shared = CoreContext.shared.vpnManager.currentState
} }

View File

@ -25,10 +25,16 @@
import Foundation import Foundation
import Combine import Combine
import PassepartoutCore import PassepartoutLibrary
import PassepartoutServices
enum Impl {
typealias ProfileManager = DefaultProfileManager
typealias ProviderManager = DefaultProviderManager
typealias VPNManager = DefaultVPNManager<DefaultProfileManager>
}
@MainActor
class CoreContext { class CoreContext {
let store: KeyValueStore let store: KeyValueStore
@ -46,11 +52,11 @@ class CoreContext {
let upgradeManager: UpgradeManager 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> = [] private var cancellables: Set<AnyCancellable> = []
@ -67,7 +73,7 @@ class CoreContext {
upgradeManager = UpgradeManager(store: store) upgradeManager = UpgradeManager(store: store)
providerManager = ProviderManager( providerManager = DefaultProviderManager(
appBuild: Constants.Global.appBuildNumber, appBuild: Constants.Global.appBuildNumber,
bundleServices: DefaultWebServices.bundledServices( bundleServices: DefaultWebServices.bundledServices(
withVersion: Constants.Services.version withVersion: Constants.Services.version
@ -80,12 +86,12 @@ class CoreContext {
persistence: providersPersistence persistence: providersPersistence
) )
profileManager = ProfileManager( profileManager = DefaultProfileManager(
store: store, store: store,
providerManager: providerManager, providerManager: providerManager,
appGroup: Constants.App.appGroupId, appGroup: Constants.App.appGroupId,
keychainLabel: Unlocalized.Keychain.passwordLabel, keychainLabel: Unlocalized.Keychain.passwordLabel,
strategy: ProfileManager.CoreDataStrategy( strategy: CoreDataProfileManagerStrategy(
persistence: profilesPersistence persistence: profilesPersistence
) )
) )
@ -93,12 +99,13 @@ class CoreContext {
#if targetEnvironment(simulator) #if targetEnvironment(simulator)
let strategy = VPNManager.MockStrategy() let strategy = VPNManager.MockStrategy()
#else #else
let strategy = VPNManager.TunnelKitStrategy( let strategy = TunnelKitVPNManagerStrategy(
appGroup: Constants.App.appGroupId, appGroup: Constants.App.appGroupId,
tunnelBundleIdentifier: Constants.App.tunnelBundleId tunnelBundleIdentifier: Constants.App.tunnelBundleId
) )
#endif #endif
vpnManager = VPNManager( vpnManager = DefaultVPNManager(
appGroup: Constants.App.appGroupId,
store: store, store: store,
profileManager: profileManager, profileManager: profileManager,
providerManager: providerManager, providerManager: providerManager,

View File

@ -25,7 +25,7 @@
import Foundation import Foundation
import StoreKit import StoreKit
import PassepartoutCore import PassepartoutLibrary
struct LocalProduct: RawRepresentable, Equatable, Hashable { struct LocalProduct: RawRepresentable, Equatable, Hashable {
private static let bundleSubdomain = "ios" private static let bundleSubdomain = "ios"

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
import StoreKit import StoreKit
import Kvitto import Kvitto
@ -34,7 +34,6 @@ enum ProductError: Error {
case beta case beta
} }
@MainActor
class ProductManager: NSObject, ObservableObject { class ProductManager: NSObject, ObservableObject {
enum AppType: Int { enum AppType: Int {
case freemium = 0 case freemium = 0

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension Error { extension Error {
var localizedAppDescription: String { var localizedAppDescription: String {
@ -57,7 +57,7 @@ extension PassepartoutError {
} }
} }
extension VPNManager.ObservableState { extension ObservableVPNState {
func localizedStatusDescription(isActiveProfile: Bool, withErrors: Bool, dataCountIfAvailable: Bool) -> String { func localizedStatusDescription(isActiveProfile: Bool, withErrors: Bool, dataCountIfAvailable: Bool) -> String {
// FIXME: l10n, sure about this wording? // FIXME: l10n, sure about this wording?

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
extension ProviderManager { extension ProviderManager {
// func localizedLocation(forProfile profile: Profile) -> String? { // func localizedLocation(forProfile profile: Profile) -> String? {
@ -59,7 +59,7 @@ extension ProviderMetadata {
format = NSLocalizedString(defaultKey, bundle: .main, comment: "") format = NSLocalizedString(defaultKey, bundle: .main, comment: "")
} }
return String(format: format, locale: .current, description) return String(format: format, locale: .current, fullName)
} }
} }

View File

@ -28,7 +28,7 @@ import TunnelKitManager
import TunnelKitOpenVPN import TunnelKitOpenVPN
import TunnelKitWireGuard import TunnelKitWireGuard
import NetworkExtension import NetworkExtension
import PassepartoutCore import PassepartoutLibrary
extension VPNStatus { extension VPNStatus {
var localizedDescription: String { var localizedDescription: String {

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import PassepartoutCore import PassepartoutLibrary
enum Unlocalized { enum Unlocalized {
static let appName = Constants.Global.appName static let appName = Constants.Global.appName

View File

@ -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>

View File

@ -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>

View File

@ -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
}
}
}

View File

@ -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
}
}
}
}

View File

@ -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()
}
}
}

View File

@ -4,15 +4,15 @@
import PackageDescription import PackageDescription
let package = Package( let package = Package(
name: "PassepartoutCore", name: "PassepartoutLibrary",
platforms: [ platforms: [
.iOS(.v14), .macOS(.v11) .iOS(.v14), .macOS(.v11)
], ],
products: [ products: [
// Products define the executables and libraries a package produces, and make them visible to other packages. // Products define the executables and libraries a package produces, and make them visible to other packages.
.library( .library(
name: "PassepartoutCore", name: "PassepartoutLibrary",
targets: ["PassepartoutCore"]), targets: ["PassepartoutLibrary"]),
.library( .library(
name: "OpenVPNAppExtension", name: "OpenVPNAppExtension",
targets: ["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 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. // Targets can depend on other targets in this package, and on products in packages this package depends on.
.target( .target(
name: "PassepartoutCore", name: "PassepartoutLibrary",
dependencies: [
"PassepartoutVPN"
]),
.target(
name: "PassepartoutVPN",
dependencies: [ dependencies: [
"PassepartoutProfiles", "PassepartoutProfiles",
"PassepartoutProviders" .product(name: "TunnelKitLZO", package: "TunnelKit")
]), ]),
.target( .target(
name: "PassepartoutProfiles", name: "PassepartoutProfiles",
dependencies: [ dependencies: [
"PassepartoutProviders", "PassepartoutProviders"
.product(name: "TunnelKit", package: "TunnelKit"),
.product(name: "TunnelKitOpenVPN", package: "TunnelKit"),
.product(name: "TunnelKitWireGuard", package: "TunnelKit"),
.product(name: "TunnelKitLZO", package: "TunnelKit")
]), ]),
.target( .target(
name: "PassepartoutProviders", 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( .target(
name: "PassepartoutServices", name: "PassepartoutServices",
dependencies: ["PassepartoutUtils"], dependencies: [
"PassepartoutUtils",
],
resources: [ resources: [
.copy("API") .copy("API")
]), ]),
@ -62,6 +77,7 @@ let package = Package(
.product(name: "GenericJSON", package: "generic-json-swift"), .product(name: "GenericJSON", package: "generic-json-swift"),
"SwiftyBeaver" "SwiftyBeaver"
]), ]),
//
.target( .target(
name: "OpenVPNAppExtension", name: "OpenVPNAppExtension",
dependencies: [ dependencies: [
@ -74,8 +90,8 @@ let package = Package(
.product(name: "TunnelKitWireGuardAppExtension", package: "TunnelKit") .product(name: "TunnelKitWireGuardAppExtension", package: "TunnelKit")
]), ]),
// .testTarget( // .testTarget(
// name: "PassepartoutCoreTests", // name: "PassepartoutLibraryTests",
// dependencies: ["PassepartoutCore"]), // dependencies: ["PassepartoutLibrary"]),
// .testTarget( // .testTarget(
// name: "PassepartoutProfilesTests", // name: "PassepartoutProfilesTests",
// dependencies: ["PassepartoutProfiles"]), // dependencies: ["PassepartoutProfiles"]),

View File

@ -25,7 +25,6 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import PassepartoutProviders
extension Profile { extension Profile {
public func hostAccount() -> Profile.Account? { public func hostAccount() -> Profile.Account? {
@ -99,8 +98,4 @@ extension Profile.Host: ProfileSubtype {
fatalError("No VPN settings found") fatalError("No VPN settings found")
} }
} }
public func requiresCredentials(forProtocol vpnProtocol: VPNProtocolType) -> Bool {
return vpnProtocol == .openVPN && (ovpnSettings?.configuration.authUserPass ?? false)
}
} }

View File

@ -24,7 +24,6 @@
// //
import Foundation import Foundation
import PassepartoutUtils
extension Profile.NetworkSettings { extension Profile.NetworkSettings {
public var isAutomaticGateway: Bool { public var isAutomaticGateway: Bool {

View File

@ -24,7 +24,6 @@
// //
import Foundation import Foundation
import PassepartoutUtils
extension Profile.OnDemand { extension Profile.OnDemand {
public var withMobileNetwork: Bool { public var withMobileNetwork: Bool {

View File

@ -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)
}
}
}
}

View File

@ -25,8 +25,6 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import PassepartoutProviders
import PassepartoutUtils
extension Profile { extension Profile {
public init(_ providerMetadata: ProviderMetadata, server: ProviderServer) { public init(_ providerMetadata: ProviderMetadata, server: ProviderServer) {
@ -42,8 +40,11 @@ extension Profile {
self.init(name: providerMetadata.fullName, provider: provider) self.init(name: providerMetadata.fullName, provider: provider)
} }
public var providerName: String? {
provider?.name
}
@MainActor
public func providerServer(_ providerManager: ProviderManager) -> ProviderServer? { public func providerServer(_ providerManager: ProviderManager) -> ProviderServer? {
guard let serverId = provider?.vpnSettings[currentVPNProtocol]?.serverId else { guard let serverId = provider?.vpnSettings[currentVPNProtocol]?.serverId else {
return nil 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 { extension Profile.Provider: ProfileSubtype {
public var vpnProtocols: [VPNProtocolType] { public var vpnProtocols: [VPNProtocolType] {
return vpnSettings.keys.sorted() Array(vpnSettings.keys)
}
public func requiresCredentials(forProtocol vpnProtocol: VPNProtocolType) -> Bool {
return name.requiresCredentials(forProtocol: vpnProtocol)
} }
} }

View File

@ -1,8 +1,8 @@
// //
// VPNProtocolType+Extensions.swift // CurrentProfileProviding.swift
// Passepartout // 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. // Copyright (c) 2022 Davide De Rosa. All rights reserved.
// //
// https://github.com/passepartoutvpn // https://github.com/passepartoutvpn
@ -25,8 +25,8 @@
import Foundation import Foundation
extension VPNProtocolType: Comparable { public protocol CurrentProfileProviding {
public static func <(lhs: Self, rhs: Self) -> Bool { associatedtype WrappedType: WrappedProfile
return lhs.description < rhs.description
} var currentProfile: WrappedType { get }
} }

View File

@ -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 }
}

View File

@ -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()
}

View File

@ -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 {
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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()
}

View File

@ -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 {
}

View File

@ -24,7 +24,6 @@
// //
import Foundation import Foundation
import PassepartoutProviders
extension Profile { extension Profile {
public struct Header: Codable, Identifiable, Hashable { public struct Header: Codable, Identifiable, Hashable {

Some files were not shown because too many files have changed in this diff Show More