Implement Mac bundle with system menu

Use bundle as a means to provide Mac APIs to Catalyst app.

In order to cross the @objc wall set by the Mac Bundle mechanism,
Swift structures cannot be used directly and must be bridged
through ObjC facades.

Create NSMenu in MVVM style and install it on app launch. Make
sure to do it in AppDelegate.applicationDidFinishLaunching(),
because doing it as early as in PassepartoutApp.init() would
crash Mac code.

Use .representedObject to own view models.

With menu in place, app can be sent to background when main window
is closed. Requires multiple documents support for app not to die
instantly.
This commit is contained in:
Davide De Rosa 2022-06-25 22:11:45 +02:00
parent 7d5f3e63c8
commit 3f4b55a003
586 changed files with 7867 additions and 125 deletions

View File

@ -28,6 +28,7 @@
CFG_TEAM_ID = DTDYD63ZX9
CFG_APP_ID = com.algoritmico.ios.Passepartout
CFG_MAC_ID = com.algoritmico.ios.PassepartoutMac
CFG_LAUNCHER_ID = com.algoritmico.ios.PassepartoutLauncher
CFG_GROUP_ID = com.algoritmico.Passepartout
CFG_APPSTORE_ID = 1433648537

View File

@ -12,12 +12,19 @@
0E0392772818732D00827C10 /* BuildProducts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0392762818732D00827C10 /* BuildProducts.swift */; };
0E039279281890B100827C10 /* AddHostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E039278281890B100827C10 /* AddHostView.swift */; };
0E065F112813269500062CAF /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E065F102813269500062CAF /* WelcomeView.swift */; };
0E0838F22872C5FB00A34EC0 /* ItemGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0838F12872C5FB00A34EC0 /* ItemGroup.swift */; };
0E0838F82874147F00A34EC0 /* PassepartoutMenu+StatusButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0838F72874147F00A34EC0 /* PassepartoutMenu+StatusButton.swift */; };
0E0838FA2877325A00A34EC0 /* LightProviderManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0838F92877325A00A34EC0 /* LightProviderManager.swift */; };
0E0838FB2877325A00A34EC0 /* LightProviderManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0838F92877325A00A34EC0 /* LightProviderManager.swift */; };
0E0838FD2877334300A34EC0 /* DefaultLightProviderManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0838FC2877334300A34EC0 /* DefaultLightProviderManager.swift */; };
0E09E35D2834172800BE1BAE /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 0E09E35C2834172800BE1BAE /* Credits.rtf */; };
0E0BD27327B2EA2C00583AC5 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27227B2EA2C00583AC5 /* MainView.swift */; };
0E0BD27627B2EB2200583AC5 /* DonateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27527B2EB2200583AC5 /* DonateView.swift */; };
0E0BD27927B2EBE500583AC5 /* ShortcutsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27827B2EBE500583AC5 /* ShortcutsView.swift */; };
0E0C0729236087A100155AAC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E0C072B236087A100155AAC /* InfoPlist.strings */; };
0E12BC8F27F62C8600B2F912 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E12BC8E27F62C8500B2F912 /* Validators.swift */; };
0E1F5628287F0ECB00F8ADD7 /* ProviderProfileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1F5627287F0ECB00F8ADD7 /* ProviderProfileItem.swift */; };
0E1F562B287F0EF100F8ADD7 /* ProviderProfileItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1F5629287F0EEE00F8ADD7 /* ProviderProfileItem+ViewModel.swift */; };
0E293851285A70AC002A6E0E /* AppPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E293850285A70AC002A6E0E /* AppPreference.swift */; };
0E293857285A73BC002A6E0E /* AppContext+Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E293856285A73BC002A6E0E /* AppContext+Shared.swift */; };
0E29385C285A8B30002A6E0E /* CoreContext+Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E29385B285A8B30002A6E0E /* CoreContext+Shared.swift */; };
@ -40,6 +47,7 @@
0E3B7FDA27E51A0200C66F13 /* ProfileView+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3B7FD927E51A0200C66F13 /* ProfileView+Provider.swift */; };
0E3CD47F280DA14B007075C0 /* AddProfileMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3CD47E280DA14B007075C0 /* AddProfileMenu.swift */; };
0E3CD483280DAE92007075C0 /* ProfileView+MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3CD482280DAE92007075C0 /* ProfileView+MainMenu.swift */; };
0E3FC6862867A3F9009B851C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3FC6852867A3F9009B851C /* AppDelegate.swift */; };
0E41BD9A286711C3006346B4 /* PassepartoutLauncherApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E41BD99286711C3006346B4 /* PassepartoutLauncherApp.swift */; };
0E41BDA72867128A006346B4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E41BDA62867128A006346B4 /* AppDelegate.swift */; };
0E41BDA928671356006346B4 /* PassepartoutLauncher.app in Embed Launcher */ = {isa = PBXBuildFile; fileRef = 0E41BD97286711C3006346B4 /* PassepartoutLauncher.app */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -54,6 +62,21 @@
0E5349BE27C16A4500C71BB3 /* StyledPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5349BD27C16A4500C71BB3 /* StyledPicker.swift */; };
0E5349C627C176C200C71BB3 /* EndpointView+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5349C527C176C200C71BB3 /* EndpointView+OpenVPN.swift */; };
0E5349C827C176D100C71BB3 /* EndpointView+WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5349C727C176D100C71BB3 /* EndpointView+WireGuard.swift */; };
0E5467F02867A4C300F74D1C /* PassepartoutMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467EE2867A49B00F74D1C /* PassepartoutMac.swift */; };
0E5467F32867A54600F74D1C /* MacBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467F22867A54600F74D1C /* MacBundle.swift */; };
0E5467F72867A57000F74D1C /* MacBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467F62867A57000F74D1C /* MacBridge.swift */; };
0E5467F82867A57000F74D1C /* MacBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467F62867A57000F74D1C /* MacBridge.swift */; };
0E5467FA2867AA0A00F74D1C /* MacBundleDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467F92867AA0A00F74D1C /* MacBundleDelegate.swift */; };
0E5467FE2867AC4900F74D1C /* ProcessTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467FD2867AC4900F74D1C /* ProcessTransformer.m */; };
0E5468002867AC9A00F74D1C /* MacUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467FF2867AC9900F74D1C /* MacUtils.swift */; };
0E5468012867AC9A00F74D1C /* MacUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5467FF2867AC9900F74D1C /* MacUtils.swift */; };
0E5468042867AD3500F74D1C /* DefaultMacUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5468032867AD3500F74D1C /* DefaultMacUtils.swift */; };
0E5468062867AEC500F74D1C /* MacMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5468052867AEC500F74D1C /* MacMenu.swift */; };
0E5468072867AEC500F74D1C /* MacMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5468052867AEC500F74D1C /* MacMenu.swift */; };
0E5468092867AEF800F74D1C /* DefaultMacMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5468082867AEF800F74D1C /* DefaultMacMenu.swift */; };
0E546810286BAF3100F74D1C /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E54680F286BAF3100F74D1C /* Item.swift */; };
0E546814286BAF3D00F74D1C /* TextItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E54680D286B676E00F74D1C /* TextItem.swift */; };
0E54681F286CA53C00F74D1C /* SeparatorItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E54681E286CA53C00F74D1C /* SeparatorItem.swift */; };
0E5683B927C2825D00EAF1CD /* DiagnosticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5683B827C2825D00EAF1CD /* DiagnosticsView.swift */; };
0E6059CB27FCC5DE003F4063 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E6059C827FCC5DD003F4063 /* Flags.xcassets */; };
0E6059CC27FCC5DE003F4063 /* Providers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E6059C927FCC5DE003F4063 /* Providers.xcassets */; };
@ -76,13 +99,39 @@
0E92D7C627F103300033CB7B /* ProfileView+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E92D7C527F103300033CB7B /* ProfileView+Configuration.swift */; };
0E92D7C927F1042A0033CB7B /* ProfileView+Extra.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E92D7C827F1042A0033CB7B /* ProfileView+Extra.swift */; };
0E92D7F427F104B80033CB7B /* ProfileView+Diagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E92D7F327F104B80033CB7B /* ProfileView+Diagnostics.swift */; };
0E96D2DE28704C3B005EFBCF /* TextItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2DD28704C3B005EFBCF /* TextItem+ViewModel.swift */; };
0E96D2E028718E44005EFBCF /* VPNItemGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2DF28718E44005EFBCF /* VPNItemGroup.swift */; };
0E96D2E228718E78005EFBCF /* VPNItemGroup+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2E128718E78005EFBCF /* VPNItemGroup+ViewModel.swift */; };
0E96D2E628718EF3005EFBCF /* ProfileItemGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2E528718EF3005EFBCF /* ProfileItemGroup.swift */; };
0E96D2EC2871A0AD005EFBCF /* HostProfileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2EB2871A0AD005EFBCF /* HostProfileItem.swift */; };
0E96D2EE2871B68C005EFBCF /* HostProfileItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2ED2871B68C005EFBCF /* HostProfileItem+ViewModel.swift */; };
0E96D2F02871C563005EFBCF /* PassepartoutMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2EF2871C563005EFBCF /* PassepartoutMenu.swift */; };
0E96D2F22871C5CA005EFBCF /* StaticSystemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2F12871C5CA005EFBCF /* StaticSystemMenu.swift */; };
0E96D2F42871CDAD005EFBCF /* VisibilityItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2F32871CDAD005EFBCF /* VisibilityItem.swift */; };
0E96D2F62871D1FE005EFBCF /* VisibilityItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2F52871D1FE005EFBCF /* VisibilityItem+ViewModel.swift */; };
0E96D2F92871D874005EFBCF /* LightProfileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2F82871D874005EFBCF /* LightProfileManager.swift */; };
0E96D2FC2871D94E005EFBCF /* DefaultLightProfileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2FB2871D94E005EFBCF /* DefaultLightProfileManager.swift */; };
0E96D2FD2871D964005EFBCF /* LightProfileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D2F82871D874005EFBCF /* LightProfileManager.swift */; };
0E96D2FE2871F688005EFBCF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E9E5AE227B44CF1008C95DA /* Localizable.strings */; };
0E96D2FF2871F68B005EFBCF /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075F27EC587900208AD9 /* SwiftGen+Strings.swift */; };
0E96D3002871F6C8005EFBCF /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB17EA127D2263700D473B5 /* Constants.swift */; };
0E96D30228720067005EFBCF /* LightVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D30128720067005EFBCF /* LightVPNManager.swift */; };
0E96D30328720067005EFBCF /* LightVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D30128720067005EFBCF /* LightVPNManager.swift */; };
0E96D3052872010A005EFBCF /* DefaultLightVPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D3042872010A005EFBCF /* DefaultLightVPNManager.swift */; };
0E96D30B28720ED9005EFBCF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E96D30628720AA1005EFBCF /* Assets.xcassets */; };
0E96D30D287212FE005EFBCF /* LaunchOnLoginItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D30C287212FE005EFBCF /* LaunchOnLoginItem.swift */; };
0E96D30F28721333005EFBCF /* LaunchOnLoginItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D30E28721333005EFBCF /* LaunchOnLoginItem+ViewModel.swift */; };
0E96D31128721855005EFBCF /* Constants+Mac.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D31028721855005EFBCF /* Constants+Mac.swift */; };
0E96D31428721FC3005EFBCF /* ObservableProcessTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E96D31328721FC3005EFBCF /* ObservableProcessTransformer.swift */; };
0E9AA978259F756A003FAFF1 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9AA977259F756A003FAFF1 /* PacketTunnelProvider.swift */; };
0E9C233027F47032007D5FC7 /* IntentsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9C232F27F47032007D5FC7 /* IntentsManager.swift */; };
0E9C233327F47E95007D5FC7 /* IntentDispatcher+Activities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9C233227F47E95007D5FC7 /* IntentDispatcher+Activities.swift */; };
0E9C3B6F27FC573E00D0F02E /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E9C3B6E27FC573E00D0F02E /* CloudKit.framework */; };
0E9E5AEF27B44CF1008C95DA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E9E5AE227B44CF1008C95DA /* Localizable.strings */; };
0E9ED48127FD9BAE003B2316 /* CopySavingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9ED48027FD9BAE003B2316 /* CopySavingButton.swift */; };
0EA1D84728805EAE00F3CA48 /* Flags.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0EA1D84628805EAE00F3CA48 /* Flags.xcassets */; };
0EA591162733DDDA0096F796 /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 0EA591142733DDDA0096F796 /* Intents.intentdefinition */; };
0EA9030B287045F70087BC73 /* SystemMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA9030A287045F70087BC73 /* SystemMenu.swift */; };
0EB17EA727D226B400D473B5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB17EA127D2263700D473B5 /* Constants.swift */; };
0EB17EA927D226C900D473B5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB17EA127D2263700D473B5 /* Constants.swift */; };
0EB17EAA27D226C900D473B5 /* Constants+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB17EA527D2263700D473B5 /* Constants+App.swift */; };
@ -100,6 +149,7 @@
0EBC075D27EC529000208AD9 /* DebugLog+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075C27EC529000208AD9 /* DebugLog+Constants.swift */; };
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBC075F27EC587900208AD9 /* SwiftGen+Strings.swift */; };
0EBE880F281B18DE0090D9E6 /* ProfileRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE880E281B18DE0090D9E6 /* ProfileRow.swift */; };
0ECB78E9285F5DE300B0E460 /* PassepartoutMac.bundle in Embed Plugins */ = {isa = PBXBuildFile; fileRef = 0ECB78DA285F52F700B0E460 /* PassepartoutMac.bundle */; platformFilter = maccatalyst; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
0ECB78EC2863A21600B0E460 /* PassepartoutLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 0ECB78EB2863A21600B0E460 /* PassepartoutLibrary */; };
0ECF71EE27B6A99300CDB528 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECF71ED27B6A99300CDB528 /* AccountView.swift */; };
0ED1D6DC27DBA41700983466 /* DiagnosticsView+OpenVPN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED1D6DB27DBA41700983466 /* DiagnosticsView+OpenVPN.swift */; };
@ -133,6 +183,11 @@
0EF2212F27E66F60001D0BD7 /* AddProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF2212E27E66F60001D0BD7 /* AddProfileView.swift */; };
0EF2213127E674BD001D0BD7 /* AddProviderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF2213027E674BD001D0BD7 /* AddProviderViewModel.swift */; };
0EF8C5A828213C510053CE89 /* OrganizerView+Profiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF8C5A728213C510053CE89 /* OrganizerView+Profiles.swift */; };
A3A7CC462878DC8300172D7D /* ProviderServerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC452878DC8300172D7D /* ProviderServerItem.swift */; };
A3A7CC482878DC9F00172D7D /* ProviderServerItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC472878DC9F00172D7D /* ProviderServerItem+ViewModel.swift */; };
A3A7CC4A28790BD900172D7D /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC4928790BD900172D7D /* Theme.swift */; };
A3A7CC56287D56E800172D7D /* ProviderLocationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC55287D56E800172D7D /* ProviderLocationItem.swift */; };
A3A7CC58287D576400172D7D /* ProviderLocationItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC57287D576400172D7D /* ProviderLocationItem+ViewModel.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -148,32 +203,50 @@
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0EDE8DBE20C86910004C739C;
remoteInfo = "PassepartoutTunnel-iOS";
remoteInfo = PassepartoutTunnel;
};
0ECB78E6285F5CC400B0E460 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0ECB78D9285F52F700B0E460;
remoteInfo = PassepartoutMac;
};
0ECF71FB27B6DA6700CDB528 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0ECF71F327B6D9CD00CDB528;
remoteInfo = "PassepartoutWireGuard-iOS";
remoteInfo = PassepartoutWireGuard;
};
0ED2B36127D3C99100FD8EA9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0ED2B33E27D3C77800FD8EA9;
remoteInfo = "WireGuardTunnel-iOS";
remoteInfo = WireGuardTunnel;
};
0ED2B36A27D3CAB100FD8EA9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0E57F63020C83FC5008323CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = 0ECF71F327B6D9CD00CDB528;
remoteInfo = "WireGuardGo-iOS";
remoteInfo = WireGuardGo;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
0E3152B7223F9EF500F61841 /* Embed Plugins */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
0ECB78E9285F5DE300B0E460 /* PassepartoutMac.bundle in Embed Plugins */,
);
name = "Embed Plugins";
runOnlyForDeploymentPostprocessing = 0;
};
0E41BDA828671339006346B4 /* Embed Launcher */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@ -205,6 +278,10 @@
0E0392762818732D00827C10 /* BuildProducts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildProducts.swift; sourceTree = "<group>"; };
0E039278281890B100827C10 /* AddHostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddHostView.swift; sourceTree = "<group>"; };
0E065F102813269500062CAF /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = "<group>"; };
0E0838F12872C5FB00A34EC0 /* ItemGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemGroup.swift; sourceTree = "<group>"; };
0E0838F72874147F00A34EC0 /* PassepartoutMenu+StatusButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PassepartoutMenu+StatusButton.swift"; sourceTree = "<group>"; };
0E0838F92877325A00A34EC0 /* LightProviderManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightProviderManager.swift; sourceTree = "<group>"; };
0E0838FC2877334300A34EC0 /* DefaultLightProviderManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultLightProviderManager.swift; sourceTree = "<group>"; };
0E09E35C2834172800BE1BAE /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
0E0BD27227B2EA2C00583AC5 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
0E0BD27527B2EB2200583AC5 /* DonateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DonateView.swift; sourceTree = "<group>"; };
@ -213,6 +290,8 @@
0E0C072C236087C800155AAC /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0E12BC8E27F62C8500B2F912 /* Validators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validators.swift; sourceTree = "<group>"; };
0E1C0A52238FFF97009FC087 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0E1F5627287F0ECB00F8ADD7 /* ProviderProfileItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderProfileItem.swift; sourceTree = "<group>"; };
0E1F5629287F0EEE00F8ADD7 /* ProviderProfileItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProviderProfileItem+ViewModel.swift"; sourceTree = "<group>"; };
0E23B4A12298559800304C30 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
0E293850285A70AC002A6E0E /* AppPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPreference.swift; sourceTree = "<group>"; };
0E293856285A73BC002A6E0E /* AppContext+Shared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppContext+Shared.swift"; sourceTree = "<group>"; };
@ -236,6 +315,8 @@
0E3B7FD927E51A0200C66F13 /* ProfileView+Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Provider.swift"; sourceTree = "<group>"; };
0E3CD47E280DA14B007075C0 /* AddProfileMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddProfileMenu.swift; sourceTree = "<group>"; };
0E3CD482280DAE92007075C0 /* ProfileView+MainMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+MainMenu.swift"; sourceTree = "<group>"; };
0E3FC6842867A3BA009B851C /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
0E3FC6852867A3F9009B851C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
0E41BD97286711C3006346B4 /* PassepartoutLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PassepartoutLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; };
0E41BD99286711C3006346B4 /* PassepartoutLauncherApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassepartoutLauncherApp.swift; sourceTree = "<group>"; };
0E41BDA2286711C6006346B4 /* Launcher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Launcher.entitlements; sourceTree = "<group>"; };
@ -251,6 +332,19 @@
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>"; };
0E5349C727C176D100C71BB3 /* EndpointView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EndpointView+WireGuard.swift"; sourceTree = "<group>"; };
0E5467EE2867A49B00F74D1C /* PassepartoutMac.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassepartoutMac.swift; sourceTree = "<group>"; };
0E5467F22867A54600F74D1C /* MacBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacBundle.swift; sourceTree = "<group>"; };
0E5467F62867A57000F74D1C /* MacBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacBridge.swift; sourceTree = "<group>"; };
0E5467F92867AA0A00F74D1C /* MacBundleDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacBundleDelegate.swift; sourceTree = "<group>"; };
0E5467FC2867AC4900F74D1C /* ProcessTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessTransformer.h; sourceTree = "<group>"; };
0E5467FD2867AC4900F74D1C /* ProcessTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProcessTransformer.m; sourceTree = "<group>"; };
0E5467FF2867AC9900F74D1C /* MacUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacUtils.swift; sourceTree = "<group>"; };
0E5468032867AD3500F74D1C /* DefaultMacUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultMacUtils.swift; sourceTree = "<group>"; };
0E5468052867AEC500F74D1C /* MacMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacMenu.swift; sourceTree = "<group>"; };
0E5468082867AEF800F74D1C /* DefaultMacMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultMacMenu.swift; sourceTree = "<group>"; };
0E54680D286B676E00F74D1C /* TextItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextItem.swift; sourceTree = "<group>"; };
0E54680F286BAF3100F74D1C /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
0E54681E286CA53C00F74D1C /* SeparatorItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorItem.swift; sourceTree = "<group>"; };
0E5683B827C2825D00EAF1CD /* DiagnosticsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiagnosticsView.swift; sourceTree = "<group>"; };
0E57F63820C83FC5008323CF /* Passepartout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passepartout.app; sourceTree = BUILT_PRODUCTS_DIR; };
0E57F64720C83FC7008323CF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -275,6 +369,25 @@
0E92D7C527F103300033CB7B /* ProfileView+Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Configuration.swift"; sourceTree = "<group>"; };
0E92D7C827F1042A0033CB7B /* ProfileView+Extra.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Extra.swift"; sourceTree = "<group>"; };
0E92D7F327F104B80033CB7B /* ProfileView+Diagnostics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Diagnostics.swift"; sourceTree = "<group>"; };
0E96D2DD28704C3B005EFBCF /* TextItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextItem+ViewModel.swift"; sourceTree = "<group>"; };
0E96D2DF28718E44005EFBCF /* VPNItemGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNItemGroup.swift; sourceTree = "<group>"; };
0E96D2E128718E78005EFBCF /* VPNItemGroup+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPNItemGroup+ViewModel.swift"; sourceTree = "<group>"; };
0E96D2E528718EF3005EFBCF /* ProfileItemGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileItemGroup.swift; sourceTree = "<group>"; };
0E96D2EB2871A0AD005EFBCF /* HostProfileItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostProfileItem.swift; sourceTree = "<group>"; };
0E96D2ED2871B68C005EFBCF /* HostProfileItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HostProfileItem+ViewModel.swift"; sourceTree = "<group>"; };
0E96D2EF2871C563005EFBCF /* PassepartoutMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassepartoutMenu.swift; sourceTree = "<group>"; };
0E96D2F12871C5CA005EFBCF /* StaticSystemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticSystemMenu.swift; sourceTree = "<group>"; };
0E96D2F32871CDAD005EFBCF /* VisibilityItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibilityItem.swift; sourceTree = "<group>"; };
0E96D2F52871D1FE005EFBCF /* VisibilityItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisibilityItem+ViewModel.swift"; sourceTree = "<group>"; };
0E96D2F82871D874005EFBCF /* LightProfileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightProfileManager.swift; sourceTree = "<group>"; };
0E96D2FB2871D94E005EFBCF /* DefaultLightProfileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultLightProfileManager.swift; sourceTree = "<group>"; };
0E96D30128720067005EFBCF /* LightVPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightVPNManager.swift; sourceTree = "<group>"; };
0E96D3042872010A005EFBCF /* DefaultLightVPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultLightVPNManager.swift; sourceTree = "<group>"; };
0E96D30628720AA1005EFBCF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
0E96D30C287212FE005EFBCF /* LaunchOnLoginItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchOnLoginItem.swift; sourceTree = "<group>"; };
0E96D30E28721333005EFBCF /* LaunchOnLoginItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LaunchOnLoginItem+ViewModel.swift"; sourceTree = "<group>"; };
0E96D31028721855005EFBCF /* Constants+Mac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Constants+Mac.swift"; sourceTree = "<group>"; };
0E96D31328721FC3005EFBCF /* ObservableProcessTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableProcessTransformer.swift; sourceTree = "<group>"; };
0E9AA977259F756A003FAFF1 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
0E9C232F27F47032007D5FC7 /* IntentsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentsManager.swift; sourceTree = "<group>"; };
0E9C233227F47E95007D5FC7 /* IntentDispatcher+Activities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IntentDispatcher+Activities.swift"; sourceTree = "<group>"; };
@ -292,6 +405,7 @@
0E9E5AED27B44CF1008C95DA /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
0E9E5AEE27B44CF1008C95DA /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
0E9ED48027FD9BAE003B2316 /* CopySavingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopySavingButton.swift; sourceTree = "<group>"; };
0EA1D84628805EAE00F3CA48 /* Flags.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flags.xcassets; sourceTree = "<group>"; };
0EA591122733DD4E0096F796 /* IntentDispatcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentDispatcher.swift; sourceTree = "<group>"; };
0EA591152733DDDA0096F796 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = "<group>"; };
0EA591182733DDF60096F796 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = "<group>"; };
@ -306,6 +420,7 @@
0EA5912A2733DDFC0096F796 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Intents.strings; sourceTree = "<group>"; };
0EA5912C2733DDFC0096F796 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Intents.strings; sourceTree = "<group>"; };
0EA5912E2733DDFD0096F796 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Intents.strings; sourceTree = "<group>"; };
0EA9030A287045F70087BC73 /* SystemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemMenu.swift; sourceTree = "<group>"; };
0EB17EA127D2263700D473B5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
0EB17EA327D2263700D473B5 /* LocalProduct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalProduct.swift; sourceTree = "<group>"; };
0EB17EA527D2263700D473B5 /* Constants+App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Constants+App.swift"; sourceTree = "<group>"; };
@ -330,6 +445,8 @@
0EBE2FD72360F89600F0D5AB /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0EBE2FD82360F89600F0D5AB /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0EBE880E281B18DE0090D9E6 /* ProfileRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileRow.swift; sourceTree = "<group>"; };
0ECB78DA285F52F700B0E460 /* PassepartoutMac.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PassepartoutMac.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
0ECB78E1285F53ED00B0E460 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
0ECB78EA2861D1F300B0E460 /* PassepartoutLibrary */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PassepartoutLibrary; sourceTree = "<group>"; };
0ECF71ED27B6A99300CDB528 /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = "<group>"; };
0ED1D6DB27DBA41700983466 /* DiagnosticsView+OpenVPN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiagnosticsView+OpenVPN.swift"; sourceTree = "<group>"; };
@ -362,6 +479,11 @@
0EF2212E27E66F60001D0BD7 /* AddProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddProfileView.swift; sourceTree = "<group>"; };
0EF2213027E674BD001D0BD7 /* AddProviderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddProviderViewModel.swift; sourceTree = "<group>"; };
0EF8C5A728213C510053CE89 /* OrganizerView+Profiles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OrganizerView+Profiles.swift"; sourceTree = "<group>"; };
A3A7CC452878DC8300172D7D /* ProviderServerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderServerItem.swift; sourceTree = "<group>"; };
A3A7CC472878DC9F00172D7D /* ProviderServerItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProviderServerItem+ViewModel.swift"; sourceTree = "<group>"; };
A3A7CC4928790BD900172D7D /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
A3A7CC55287D56E800172D7D /* ProviderLocationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderLocationItem.swift; sourceTree = "<group>"; };
A3A7CC57287D576400172D7D /* ProviderLocationItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProviderLocationItem+ViewModel.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -382,6 +504,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
0ECB78D7285F52F700B0E460 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
0ED2B34327D3C77800FD8EA9 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -543,6 +672,77 @@
path = Extensions;
sourceTree = "<group>";
};
0E5467F12867A52B00F74D1C /* Mac */ = {
isa = PBXGroup;
children = (
0E96D2FA2871D93B005EFBCF /* Models */,
0E5467F92867AA0A00F74D1C /* MacBundleDelegate.swift */,
0E5467F22867A54600F74D1C /* MacBundle.swift */,
);
path = Mac;
sourceTree = "<group>";
};
0E5467F52867A55F00F74D1C /* Mac */ = {
isa = PBXGroup;
children = (
0E96D2F72871D868005EFBCF /* Models */,
0E5467F62867A57000F74D1C /* MacBridge.swift */,
0E5468052867AEC500F74D1C /* MacMenu.swift */,
0E5467FF2867AC9900F74D1C /* MacUtils.swift */,
);
path = Mac;
sourceTree = "<group>";
};
0E5467FB2867AC4900F74D1C /* Reusable */ = {
isa = PBXGroup;
children = (
0E54680F286BAF3100F74D1C /* Item.swift */,
0E0838F12872C5FB00A34EC0 /* ItemGroup.swift */,
0E96D31328721FC3005EFBCF /* ObservableProcessTransformer.swift */,
0E54681E286CA53C00F74D1C /* SeparatorItem.swift */,
0E96D2F12871C5CA005EFBCF /* StaticSystemMenu.swift */,
0EA9030A287045F70087BC73 /* SystemMenu.swift */,
0E54680D286B676E00F74D1C /* TextItem.swift */,
0E96D2DD28704C3B005EFBCF /* TextItem+ViewModel.swift */,
0E5467FC2867AC4900F74D1C /* ProcessTransformer.h */,
0E5467FD2867AC4900F74D1C /* ProcessTransformer.m */,
);
path = Reusable;
sourceTree = "<group>";
};
0E5468022867AD2100F74D1C /* Mac */ = {
isa = PBXGroup;
children = (
0E5468082867AEF800F74D1C /* DefaultMacMenu.swift */,
0E5468032867AD3500F74D1C /* DefaultMacUtils.swift */,
);
path = Mac;
sourceTree = "<group>";
};
0E54680C286B675F00F74D1C /* Menu */ = {
isa = PBXGroup;
children = (
0E96D2EB2871A0AD005EFBCF /* HostProfileItem.swift */,
0E96D2ED2871B68C005EFBCF /* HostProfileItem+ViewModel.swift */,
0E96D30C287212FE005EFBCF /* LaunchOnLoginItem.swift */,
0E96D30E28721333005EFBCF /* LaunchOnLoginItem+ViewModel.swift */,
0E96D2EF2871C563005EFBCF /* PassepartoutMenu.swift */,
0E0838F72874147F00A34EC0 /* PassepartoutMenu+StatusButton.swift */,
0E96D2E528718EF3005EFBCF /* ProfileItemGroup.swift */,
A3A7CC55287D56E800172D7D /* ProviderLocationItem.swift */,
A3A7CC57287D576400172D7D /* ProviderLocationItem+ViewModel.swift */,
0E1F5627287F0ECB00F8ADD7 /* ProviderProfileItem.swift */,
0E1F5629287F0EEE00F8ADD7 /* ProviderProfileItem+ViewModel.swift */,
A3A7CC452878DC8300172D7D /* ProviderServerItem.swift */,
A3A7CC472878DC9F00172D7D /* ProviderServerItem+ViewModel.swift */,
0E96D2F32871CDAD005EFBCF /* VisibilityItem.swift */,
0E96D2F52871D1FE005EFBCF /* VisibilityItem+ViewModel.swift */,
0E96D2DF28718E44005EFBCF /* VPNItemGroup.swift */,
0E96D2E128718E78005EFBCF /* VPNItemGroup+ViewModel.swift */,
);
path = Menu;
sourceTree = "<group>";
};
0E57F62F20C83FC5008323CF = {
isa = PBXGroup;
children = (
@ -561,6 +761,7 @@
0EDE8DBF20C86910004C739C /* PassepartoutOpenVPNTunnel.appex */,
0ED2B34A27D3C77800FD8EA9 /* PassepartoutWireGuardTunnel.appex */,
0E41BD97286711C3006346B4 /* PassepartoutLauncher.app */,
0ECB78DA285F52F700B0E460 /* PassepartoutMac.bundle */,
);
name = Products;
sourceTree = "<group>";
@ -575,12 +776,42 @@
path = InApp;
sourceTree = "<group>";
};
0E96D2F72871D868005EFBCF /* Models */ = {
isa = PBXGroup;
children = (
0E96D2F82871D874005EFBCF /* LightProfileManager.swift */,
0E0838F92877325A00A34EC0 /* LightProviderManager.swift */,
0E96D30128720067005EFBCF /* LightVPNManager.swift */,
);
path = Models;
sourceTree = "<group>";
};
0E96D2FA2871D93B005EFBCF /* Models */ = {
isa = PBXGroup;
children = (
0E96D2FB2871D94E005EFBCF /* DefaultLightProfileManager.swift */,
0E0838FC2877334300A34EC0 /* DefaultLightProviderManager.swift */,
0E96D3042872010A005EFBCF /* DefaultLightVPNManager.swift */,
);
path = Models;
sourceTree = "<group>";
};
0E96D3122872185E005EFBCF /* Constants */ = {
isa = PBXGroup;
children = (
0E96D31028721855005EFBCF /* Constants+Mac.swift */,
A3A7CC4928790BD900172D7D /* Theme.swift */,
);
path = Constants;
sourceTree = "<group>";
};
0E9AA982259F7674003FAFF1 /* Passepartout */ = {
isa = PBXGroup;
children = (
0E9AA983259F76C5003FAFF1 /* App */,
0ECB78D1285F4F4000B0E460 /* AppShared */,
0E41BD98286711C3006346B4 /* Launcher */,
0ECB78DE285F536B00B0E460 /* Mac */,
0EDE8DC020C86910004C739C /* Tunnel */,
0EB17EA127D2263700D473B5 /* Constants.swift */,
);
@ -595,6 +826,7 @@
0E49F6C927DB398100385834 /* Extensions */,
0E92781227E7CD530057BB81 /* InApp */,
0EA591112733DD4E0096F796 /* Intents */,
0E5467F12867A52B00F74D1C /* Mac */,
0E2C171C27CB6307007E8488 /* Reusable */,
0E35C0AE280EF8A80071FA35 /* Views */,
0E6059CA27FCC5DE003F4063 /* Assets.xcassets */,
@ -605,6 +837,7 @@
0E09E35C2834172800BE1BAE /* Credits.rtf */,
0E57F64720C83FC7008323CF /* Info.plist */,
0E0C072B236087A100155AAC /* InfoPlist.strings */,
0E3FC6852867A3F9009B851C /* AppDelegate.swift */,
0E2A8D4727ADF87F00207D04 /* PassepartoutApp.swift */,
);
path = App;
@ -627,6 +860,7 @@
0ECB78D3285F4F9600B0E460 /* Constants */,
0E293859285A7489002A6E0E /* Context */,
0E34A2B827CAA8EA00C73B67 /* L10n */,
0E5467F52867A55F00F74D1C /* Mac */,
0E9E5AE227B44CF1008C95DA /* Localizable.strings */,
);
path = AppShared;
@ -651,6 +885,22 @@
path = Constants;
sourceTree = "<group>";
};
0ECB78DE285F536B00B0E460 /* Mac */ = {
isa = PBXGroup;
children = (
0E96D3122872185E005EFBCF /* Constants */,
0E5468022867AD2100F74D1C /* Mac */,
0E54680C286B675F00F74D1C /* Menu */,
0E5467FB2867AC4900F74D1C /* Reusable */,
0E96D30628720AA1005EFBCF /* Assets.xcassets */,
0EA1D84628805EAE00F3CA48 /* Flags.xcassets */,
0ECB78E1285F53ED00B0E460 /* Info.plist */,
0E5467EE2867A49B00F74D1C /* PassepartoutMac.swift */,
0E3FC6842867A3BA009B851C /* Bridging-Header.h */,
);
path = Mac;
sourceTree = "<group>";
};
0ED2B33C27D3C52900FD8EA9 /* OpenVPN */ = {
isa = PBXGroup;
children = (
@ -676,14 +926,6 @@
path = Constants;
sourceTree = "<group>";
};
0ED7D630286733A1009F2F8F /* Constants */ = {
isa = PBXGroup;
children = (
0ED7D631286733AF009F2F8F /* Constants+Launcher.swift */,
);
path = Constants;
sourceTree = "<group>";
};
0EDE8DC020C86910004C739C /* Tunnel */ = {
isa = PBXGroup;
children = (
@ -728,7 +970,7 @@
);
name = WireGuardGo;
passBuildSettingsInEnvironment = 1;
productName = "PassepartoutWireGuard-iOS";
productName = PassepartoutWireGuard;
};
/* End PBXLegacyTarget section */
@ -759,12 +1001,14 @@
0E57F63520C83FC5008323CF /* Frameworks */,
0E57F63620C83FC5008323CF /* Resources */,
0E41BDA828671339006346B4 /* Embed Launcher */,
0E3152B7223F9EF500F61841 /* Embed Plugins */,
0EB2B14B2733FB6F007705AB /* Embed App Extensions */,
0EBEF138274E4C7F00EAC689 /* Drop Extra Frameworks In Extensions */,
);
buildRules = (
);
dependencies = (
0ECB78E7285F5CC400B0E460 /* PBXTargetDependency */,
0E41BDAB286713F6006346B4 /* PBXTargetDependency */,
0ECF71FC27B6DA6700CDB528 /* PBXTargetDependency */,
0EB2B14A2733FB6F007705AB /* PBXTargetDependency */,
@ -779,6 +1023,25 @@
productReference = 0E57F63820C83FC5008323CF /* Passepartout.app */;
productType = "com.apple.product-type.application";
};
0ECB78D9285F52F700B0E460 /* PassepartoutMac */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0ECB78DD285F52F700B0E460 /* Build configuration list for PBXNativeTarget "PassepartoutMac" */;
buildPhases = (
0E5467EF2867A4B100F74D1C /* Sources */,
0ECB78D7285F52F700B0E460 /* Frameworks */,
0ECB78D8285F52F700B0E460 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = PassepartoutMac;
packageProductDependencies = (
);
productName = PassepartoutMac;
productReference = 0ECB78DA285F52F700B0E460 /* PassepartoutMac.bundle */;
productType = "com.apple.product-type.bundle";
};
0ED2B33E27D3C77800FD8EA9 /* WireGuardTunnel */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0ED2B34727D3C77800FD8EA9 /* Build configuration list for PBXNativeTarget "WireGuardTunnel" */;
@ -796,7 +1059,7 @@
packageProductDependencies = (
0ED2B36627D3C9A300FD8EA9 /* WireGuardAppExtension */,
);
productName = "Passepartout-iOS-Tunnel";
productName = PassepartoutWireGuardTunnel;
productReference = 0ED2B34A27D3C77800FD8EA9 /* PassepartoutWireGuardTunnel.appex */;
productType = "com.apple.product-type.app-extension";
};
@ -816,7 +1079,7 @@
packageProductDependencies = (
0ED2B33827D3C49800FD8EA9 /* OpenVPNAppExtension */,
);
productName = "Passepartout-iOS-Tunnel";
productName = PassepartoutOpenVPNTunnel;
productReference = 0EDE8DBF20C86910004C739C /* PassepartoutOpenVPNTunnel.appex */;
productType = "com.apple.product-type.app-extension";
};
@ -851,6 +1114,10 @@
};
};
};
0ECB78D9285F52F700B0E460 = {
CreatedOnToolsVersion = 13.4;
LastSwiftMigration = 1340;
};
0ECF71F327B6D9CD00CDB528 = {
CreatedOnToolsVersion = 13.2;
};
@ -896,6 +1163,7 @@
projectRoot = "";
targets = (
0E57F63720C83FC5008323CF /* Passepartout */,
0ECB78D9285F52F700B0E460 /* PassepartoutMac */,
0E41BD96286711C3006346B4 /* PassepartoutLauncher */,
0EDE8DBE20C86910004C739C /* OpenVPNTunnel */,
0ECF71F327B6D9CD00CDB528 /* WireGuardGo */,
@ -926,6 +1194,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
0ECB78D8285F52F700B0E460 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E96D30B28720ED9005EFBCF /* Assets.xcassets in Resources */,
0EA1D84728805EAE00F3CA48 /* Flags.xcassets in Resources */,
0E96D2FE2871F688005EFBCF /* Localizable.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0ED2B34627D3C77800FD8EA9 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -994,6 +1272,52 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
0E5467EF2867A4B100F74D1C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A3A7CC462878DC8300172D7D /* ProviderServerItem.swift in Sources */,
0E96D31128721855005EFBCF /* Constants+Mac.swift in Sources */,
0E96D3002871F6C8005EFBCF /* Constants.swift in Sources */,
0E96D2E228718E78005EFBCF /* VPNItemGroup+ViewModel.swift in Sources */,
0E96D2F02871C563005EFBCF /* PassepartoutMenu.swift in Sources */,
0E96D2E028718E44005EFBCF /* VPNItemGroup.swift in Sources */,
0E96D2F62871D1FE005EFBCF /* VisibilityItem+ViewModel.swift in Sources */,
0E96D30F28721333005EFBCF /* LaunchOnLoginItem+ViewModel.swift in Sources */,
0E5467F82867A57000F74D1C /* MacBridge.swift in Sources */,
0E5468042867AD3500F74D1C /* DefaultMacUtils.swift in Sources */,
0E5468092867AEF800F74D1C /* DefaultMacMenu.swift in Sources */,
0E0838FB2877325A00A34EC0 /* LightProviderManager.swift in Sources */,
0E1F5628287F0ECB00F8ADD7 /* ProviderProfileItem.swift in Sources */,
A3A7CC482878DC9F00172D7D /* ProviderServerItem+ViewModel.swift in Sources */,
0E5467FE2867AC4900F74D1C /* ProcessTransformer.m in Sources */,
0EA9030B287045F70087BC73 /* SystemMenu.swift in Sources */,
0E96D2DE28704C3B005EFBCF /* TextItem+ViewModel.swift in Sources */,
0E0838F22872C5FB00A34EC0 /* ItemGroup.swift in Sources */,
A3A7CC4A28790BD900172D7D /* Theme.swift in Sources */,
0E0838F82874147F00A34EC0 /* PassepartoutMenu+StatusButton.swift in Sources */,
0E5468012867AC9A00F74D1C /* MacUtils.swift in Sources */,
0E546810286BAF3100F74D1C /* Item.swift in Sources */,
A3A7CC56287D56E800172D7D /* ProviderLocationItem.swift in Sources */,
0E96D30328720067005EFBCF /* LightVPNManager.swift in Sources */,
0E96D2F42871CDAD005EFBCF /* VisibilityItem.swift in Sources */,
0E1F562B287F0EF100F8ADD7 /* ProviderProfileItem+ViewModel.swift in Sources */,
0E5468072867AEC500F74D1C /* MacMenu.swift in Sources */,
0E96D2EC2871A0AD005EFBCF /* HostProfileItem.swift in Sources */,
0E96D2F22871C5CA005EFBCF /* StaticSystemMenu.swift in Sources */,
A3A7CC58287D576400172D7D /* ProviderLocationItem+ViewModel.swift in Sources */,
0E5467F02867A4C300F74D1C /* PassepartoutMac.swift in Sources */,
0E96D30D287212FE005EFBCF /* LaunchOnLoginItem.swift in Sources */,
0E96D2F92871D874005EFBCF /* LightProfileManager.swift in Sources */,
0E54681F286CA53C00F74D1C /* SeparatorItem.swift in Sources */,
0E96D2E628718EF3005EFBCF /* ProfileItemGroup.swift in Sources */,
0E96D31428721FC3005EFBCF /* ObservableProcessTransformer.swift in Sources */,
0E96D2FF2871F68B005EFBCF /* SwiftGen+Strings.swift in Sources */,
0E546814286BAF3D00F74D1C /* TextItem.swift in Sources */,
0E96D2EE2871B68C005EFBCF /* HostProfileItem+ViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0E57F63420C83FC5008323CF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -1016,6 +1340,7 @@
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */,
0E0392772818732D00827C10 /* BuildProducts.swift in Sources */,
0E5683B927C2825D00EAF1CD /* DiagnosticsView.swift in Sources */,
0E3FC6862867A3F9009B851C /* AppDelegate.swift in Sources */,
0E71ACFD27C1321A00F85C4B /* ActivityView.swift in Sources */,
0E44689627B051C300A14CE4 /* ProfileView.swift in Sources */,
0EDE02C227F61C79000FBE3C /* EditableTextList.swift in Sources */,
@ -1033,26 +1358,33 @@
0EB17EAA27D226C900D473B5 /* Constants+App.swift in Sources */,
0E3B7FD627E5173A00C66F13 /* ProfileView+VPN.swift in Sources */,
0ED89C1E27DE3F8D008B36D6 /* IntentAddView.swift in Sources */,
0E5468002867AC9A00F74D1C /* MacUtils.swift in Sources */,
0E96D3052872010A005EFBCF /* DefaultLightVPNManager.swift in Sources */,
0EBE880F281B18DE0090D9E6 /* ProfileRow.swift in Sources */,
0ED30DCF27EA1EF80057D8A3 /* PaywallView+Beta.swift in Sources */,
0ECF71EE27B6A99300CDB528 /* AccountView.swift in Sources */,
0E71ACF727C107CA00F85C4B /* DebugLogView.swift in Sources */,
0EF0FAF927DD212C007EB181 /* IntentActivity.swift in Sources */,
0EBC075B27EC4FFF00208AD9 /* ReportIssueView.swift in Sources */,
0E96D30228720067005EFBCF /* LightVPNManager.swift in Sources */,
0ED89C1727DE0E05008B36D6 /* IntentEditView.swift in Sources */,
0E70589B28377DC40075D1D2 /* VPNStatusText.swift in Sources */,
0E71ACE927C1055300F85C4B /* NetworkSettingsView.swift in Sources */,
0EB34BCA27C6A70200B126DA /* OnDemandView.swift in Sources */,
0E0838FA2877325A00A34EC0 /* LightProviderManager.swift in Sources */,
0ED7D62F2867328A009F2F8F /* Constants+Library.swift in Sources */,
0E5467FA2867AA0A00F74D1C /* MacBundleDelegate.swift in Sources */,
0E0BD27327B2EA2C00583AC5 /* MainView.swift in Sources */,
0EB17EBA27D2560300D473B5 /* PassepartoutProviders+Extensions.swift in Sources */,
0E3B7FDA27E51A0200C66F13 /* ProfileView+Provider.swift in Sources */,
0E5468062867AEC500F74D1C /* MacMenu.swift in Sources */,
0E71ACE327C0F2E400F85C4B /* Providers+L10n.swift in Sources */,
0E71ACF127C1073800F85C4B /* ProviderLocationView.swift in Sources */,
0E2A8D4F27B04BBA00207D04 /* OrganizerView.swift in Sources */,
0E49F6BB27D7638300385834 /* EndpointAdvancedView+OpenVPN.swift in Sources */,
0E71ACEF27C106B500F85C4B /* ProviderPresetView.swift in Sources */,
0EF2212F27E66F60001D0BD7 /* AddProfileView.swift in Sources */,
0E96D2FC2871D94E005EFBCF /* DefaultLightProfileManager.swift in Sources */,
0EF0FAF627DD0211007EB181 /* PaywallView.swift in Sources */,
0E293851285A70AC002A6E0E /* AppPreference.swift in Sources */,
0E5349BE27C16A4500C71BB3 /* StyledPicker.swift in Sources */,
@ -1061,12 +1393,15 @@
0E021D9C284E68580077EF5D /* CoreContext.swift in Sources */,
0E34A2B627CAA8CC00C73B67 /* Core+L10n.swift in Sources */,
0E7577DF2817E22C00081CBE /* VPNToggle.swift in Sources */,
0E5467F32867A54600F74D1C /* MacBundle.swift in Sources */,
0E6059CF27FCC618003F4063 /* SwiftGen+Assets.swift in Sources */,
0E2A8D4927ADF87F00207D04 /* PassepartoutApp.swift in Sources */,
0EBC075527EBC83800208AD9 /* MailComposerView.swift in Sources */,
0EF0FAF727DD159C007EB181 /* IntentDispatcher.swift in Sources */,
0E12BC8F27F62C8600B2F912 /* Validators.swift in Sources */,
0E0838FD2877334300A34EC0 /* DefaultLightProviderManager.swift in Sources */,
0E039279281890B100827C10 /* AddHostView.swift in Sources */,
0E5467F72867A57000F74D1C /* MacBridge.swift in Sources */,
0E9ED48127FD9BAE003B2316 /* CopySavingButton.swift in Sources */,
0EE11CD2280D8317003BE431 /* InfoMenu.swift in Sources */,
0E44689C27B11B5300A14CE4 /* AboutView.swift in Sources */,
@ -1087,6 +1422,7 @@
0E065F112813269500062CAF /* WelcomeView.swift in Sources */,
0E2DE71F27DCD0290067B9E1 /* TunnelKit+L10n.swift in Sources */,
0E49F6BF27D764AF00385834 /* EndpointAdvancedView.swift in Sources */,
0E96D2FD2871D964005EFBCF /* LightProfileManager.swift in Sources */,
0E0BD27627B2EB2200583AC5 /* DonateView.swift in Sources */,
0E2C171B27CB5A3B007E8488 /* GenericCreditsView.swift in Sources */,
0ED30DD227EA1F650057D8A3 /* PaywallView+Purchase.swift in Sources */,
@ -1134,6 +1470,12 @@
target = 0EDE8DBE20C86910004C739C /* OpenVPNTunnel */;
targetProxy = 0EB2B1492733FB6F007705AB /* PBXContainerItemProxy */;
};
0ECB78E7285F5CC400B0E460 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
platformFilter = maccatalyst;
target = 0ECB78D9285F52F700B0E460 /* PassepartoutMac */;
targetProxy = 0ECB78E6285F5CC400B0E460 /* PBXContainerItemProxy */;
};
0ECF71FC27B6DA6700CDB528 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 0ECF71F327B6D9CD00CDB528 /* WireGuardGo */;
@ -1392,6 +1734,7 @@
0E57F65620C83FC7008323CF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
@ -1418,6 +1761,7 @@
0E57F65720C83FC7008323CF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
@ -1440,6 +1784,69 @@
};
name = Release;
};
0ECB78DB285F52F700B0E460 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 3240;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Passepartout/Mac/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_MAC_ID)";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Passepartout/Mac/Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
0ECB78DC285F52F700B0E460 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 3240;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Passepartout/Mac/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "$(CFG_MAC_ID)";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Passepartout/Mac/Bridging-Header.h";
SWIFT_VERSION = 5.0;
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
0ECF71F527B6D9CD00CDB528 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1589,6 +1996,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0ECB78DD285F52F700B0E460 /* Build configuration list for PBXNativeTarget "PassepartoutMac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0ECB78DB285F52F700B0E460 /* Debug */,
0ECB78DC285F52F700B0E460 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0ECF71F427B6D9CD00CDB528 /* Build configuration list for PBXLegacyTarget "WireGuardGo" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1340"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0ECB78D9285F52F700B0E460"
BuildableName = "PassepartoutMac.bundle"
BlueprintName = "PassepartoutMac"
ReferencedContainer = "container:Passepartout.xcodeproj">
</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 = "0ECB78D9285F52F700B0E460"
BuildableName = "PassepartoutMac.bundle"
BlueprintName = "PassepartoutMac"
ReferencedContainer = "container:Passepartout.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,39 @@
//
// AppDelegate.swift
// Passepartout
//
// Created by Davide De Rosa on 6/25/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 UIKit
class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
private let mac = MacBundle.shared
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
#if targetEnvironment(macCatalyst)
mac.configure()
mac.menu.install()
#endif
return true
}
}

View File

@ -44,6 +44,10 @@ extension Constants {
Bundle.main.isTestFlight
}()
}
enum Plugins {
static let macBridgeName = "PassepartoutMac.bundle"
}
enum InApp {
static var appType: ProductManager.AppType {

View File

@ -27,6 +27,8 @@ import Foundation
import PassepartoutLibrary
enum AppPreference: String, KeyStoreDomainLocation {
case launchesOnLogin // placeholder, hardcoded in PassepartoutMac
case isShowingFavorites
case didHandleSubreddit

View File

@ -61,6 +61,11 @@
<string>UntrustCellularNetworkIntent</string>
<string>UntrustCurrentNetworkIntent</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>

View File

@ -43,7 +43,7 @@ extension IntentDispatcher {
Task {
do {
try await vpnManager.connectWithActiveProfile()
try await vpnManager.connectWithActiveProfile(toServer: nil)
} catch {
pp_log.error("Unable to connect with active profile: \(error)")
}

View File

@ -0,0 +1,56 @@
//
// MacBundle.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
class MacBundle {
static let shared = MacBundle()
private var bridge: MacBridge!
private lazy var bridgeDelegate = MacBundleDelegate(bundle: self)
func configure() {
guard let bundleURL = Bundle.main.builtInPlugInsURL?.appendingPathComponent(Constants.Plugins.macBridgeName) else {
fatalError("Unable to find Mac bundle in plugins")
}
guard let bundle = Bundle(url: bundleURL) else {
fatalError("Unable to build Mac bundle")
}
guard let bridgeClass = bundle.principalClass as? MacBridge.Type else {
fatalError("Unable to find principal class in Mac bundle")
}
bridge = bridgeClass.init()
bridge.menu.delegate = bridgeDelegate
}
var utils: MacUtils {
bridge.utils
}
var menu: MacMenu {
bridge.menu
}
}

View File

@ -0,0 +1,46 @@
//
// MacBundleDelegate.swift
// Passepartout
//
// Created by Davide De Rosa on 6/25/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
class MacBundleDelegate: MacMenuDelegate {
private weak var bundle: MacBundle?
var profileManager: LightProfileManager {
DefaultLightProfileManager()
}
var providerManager: LightProviderManager {
DefaultLightProviderManager()
}
var vpnManager: LightVPNManager {
DefaultLightVPNManager()
}
init(bundle: MacBundle?) {
self.bundle = bundle
}
}

View File

@ -0,0 +1,106 @@
//
// DefaultLightProfileManager.swift
// Passepartout
//
// Created by Davide De Rosa on 7/3/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 PassepartoutLibrary
import Combine
class DefaultLightProfile: LightProfile {
let id: UUID
let name: String
let vpnProtocol: String
let isActive: Bool
let providerName: String?
let providerServer: LightProviderServer?
init(_ header: Profile.Header, vpnProtocol: String, isActive: Bool, providerServer: LightProviderServer?) {
id = header.id
name = header.name
self.vpnProtocol = vpnProtocol
self.isActive = isActive
providerName = header.providerName
self.providerServer = providerServer
}
}
class DefaultLightProfileManager: LightProfileManager {
private let profileManager = Impl.ProfileManager.shared
private let providerManager = Impl.ProviderManager.shared
private var subscriptions: Set<AnyCancellable> = []
weak var delegate: LightProfileManagerDelegate?
init() {
profileManager.didUpdateProfiles
.receive(on: DispatchQueue.main)
.sink {
self.delegate?.didUpdateProfiles()
}.store(in: &subscriptions)
}
var hasProfiles: Bool {
profileManager.hasProfiles
}
var profiles: [LightProfile] {
profileManager.profiles
.sorted {
$0.header < $1.header
}.map {
let server: ProviderServer?
if let serverId = $0.providerServerId() {
server = providerManager.server(withId: serverId)
} else {
server = nil
}
return DefaultLightProfile(
$0.header,
vpnProtocol: $0.currentVPNProtocol.rawValue,
isActive: profileManager.isActiveProfile($0.id),
providerServer: server.map(DefaultLightProviderServer.init)
)
}
}
var activeProfileId: UUID? {
profileManager.activeProfileId
}
var activeProfileName: String? {
guard let header = profileManager.headers.first(where: {
$0.id == profileManager.activeProfileId
}) else {
return nil
}
return header.name
}
}

View File

@ -0,0 +1,114 @@
//
// DefaultLightProviderManager.swift
// Passepartout
//
// Created by Davide De Rosa on 7/7/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 PassepartoutLibrary
class DefaultLightProviderCategory: LightProviderCategory {
let name: String
var locations: [LightProviderLocation]
init(_ category: ProviderCategory) {
name = category.name
locations = category.locations
.sorted()
.map(DefaultLightProviderLocation.init)
}
}
class DefaultLightProviderLocation: LightProviderLocation {
let description: String
let id: String
let countryCode: String
let servers: [LightProviderServer]
init(_ location: ProviderLocation) {
description = location.localizedCountry
id = location.id
countryCode = location.countryCode
servers = location.servers?
.sorted()
.map(DefaultLightProviderServer.init) ?? []
}
}
class DefaultLightProviderServer: LightProviderServer {
let description: String
let categoryName: String
let locationId: String
let serverId: String
init(_ server: ProviderServer) {
description = server.localizedDescription
categoryName = server.categoryName
locationId = server.locationId
serverId = server.id
}
}
class DefaultLightProviderManager: LightProviderManager {
private let providerManager = Impl.ProviderManager.shared
private var subscriptions: Set<AnyCancellable> = []
weak var delegate: LightProviderManagerDelegate?
init() {
providerManager.didUpdateProviders
.receive(on: DispatchQueue.main)
.sink {
self.delegate?.didUpdateProviders()
}.store(in: &subscriptions)
}
func categories(_ name: String, vpnProtocol: String) -> [LightProviderCategory] {
guard let vpnProtocolType = VPNProtocolType(rawValue: vpnProtocol) else {
fatalError("Unrecognized VPN protocol: \(vpnProtocol)")
}
return providerManager.categories(name, vpnProtocol: vpnProtocolType)
.map(DefaultLightProviderCategory.init)
}
@MainActor
func downloadIfNeeded(_ name: String, vpnProtocol: String) {
guard let vpnProtocolType = VPNProtocolType(rawValue: vpnProtocol) else {
fatalError("Unrecognized VPN protocol: \(vpnProtocol)")
}
guard !providerManager.isAvailable(name, vpnProtocol: vpnProtocolType) else {
return
}
Task {
try await providerManager.fetchProviderPublisher(withName: name, vpnProtocol: vpnProtocolType, priority: .remoteThenBundle).async()
}
}
}

View File

@ -0,0 +1,120 @@
//
// DefaultLightVPNManager.swift
// Passepartout
//
// Created by Davide De Rosa on 7/3/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 PassepartoutLibrary
import Combine
class DefaultLightVPNManager: LightVPNManager {
private let vpnManager = Impl.VPNManager.shared
private var subscriptions: Set<AnyCancellable> = []
var isEnabled: Bool {
vpnManager.currentState.isEnabled
}
var vpnStatus: LightVPNStatus {
vpnManager.currentState.vpnStatus.asLightVPNStatus
}
weak var delegate: LightVPNManagerDelegate?
init() {
vpnManager.currentState.$isEnabled
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink {
self.delegate?.didUpdateState(
isEnabled: $0,
vpnStatus: self.vpnManager.currentState.vpnStatus.asLightVPNStatus
)
}.store(in: &subscriptions)
vpnManager.currentState.$vpnStatus
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink {
self.delegate?.didUpdateState(
isEnabled: self.vpnManager.currentState.isEnabled,
vpnStatus: $0.asLightVPNStatus
)
}.store(in: &subscriptions)
}
@MainActor
func connect(with profileId: UUID) {
Task {
try? await vpnManager.connect(with: profileId)
}
}
@MainActor
func connect(with profileId: UUID, to serverId: String) {
Task {
try? await vpnManager.connect(with: profileId, toServer: serverId)
}
}
@MainActor
func toggle() {
Task {
if !isEnabled {
try? await vpnManager.connectWithActiveProfile(toServer: nil)
} else {
await vpnManager.disable()
}
}
}
@MainActor
func reconnect() {
Task {
if isEnabled {
await vpnManager.disable()
try? await Task.sleep(nanoseconds: 2 * NSEC_PER_SEC)
}
try? await vpnManager.connectWithActiveProfile(toServer: nil)
}
}
}
private extension VPNStatus {
var asLightVPNStatus: LightVPNStatus {
switch self {
case .connected:
return .connected
case .connecting:
return .connecting
case .disconnected:
return .disconnected
case .disconnecting:
return .disconnecting
}
}
}

View File

@ -28,6 +28,10 @@ import PassepartoutLibrary
@main
struct PassepartoutApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
@Environment(\.scenePhase) private var scenePhase
@SceneBuilder var body: some Scene {
WindowGroup {
MainView()
@ -40,6 +44,18 @@ struct PassepartoutApp: App {
.onIntentActivity(IntentDispatcher.trustCurrentNetwork)
.onIntentActivity(IntentDispatcher.untrustCellularNetwork)
.onIntentActivity(IntentDispatcher.untrustCurrentNetwork)
}.onChange(of: scenePhase, perform: onScenePhase)
}
private func onScenePhase(_ scenePhase: ScenePhase) {
switch scenePhase {
case .background:
#if targetEnvironment(macCatalyst)
MacBundle.shared.utils.sendAppToBackground()
#endif
default:
break
}
}
}

View File

@ -1,8 +0,0 @@
xcassets:
inputs:
- Assets.xcassets
- Flags.xcassets
- Providers.xcassets
outputs:
- templateName: swift4
output: Constants/SwiftGen+Assets.swift

View File

@ -435,16 +435,22 @@ internal enum L10n {
internal static let cancel = L10n.tr("Localizable", "global.strings.cancel")
/// Configuration
internal static let configuration = L10n.tr("Localizable", "global.strings.configuration")
/// Connect
internal static let connect = L10n.tr("Localizable", "global.strings.connect")
/// Default
internal static let `default` = L10n.tr("Localizable", "global.strings.default")
/// Delete
internal static let delete = L10n.tr("Localizable", "global.strings.delete")
/// Disabled
internal static let disabled = L10n.tr("Localizable", "global.strings.disabled")
/// Disconnect
internal static let disconnect = L10n.tr("Localizable", "global.strings.disconnect")
/// Domain
internal static let domain = L10n.tr("Localizable", "global.strings.domain")
/// Domains
internal static let domains = L10n.tr("Localizable", "global.strings.domains")
/// Download
internal static let download = L10n.tr("Localizable", "global.strings.download")
/// Duplicate
internal static let duplicate = L10n.tr("Localizable", "global.strings.duplicate")
/// Enabled
@ -453,6 +459,8 @@ internal enum L10n {
internal static let encryption = L10n.tr("Localizable", "global.strings.encryption")
/// Endpoint
internal static let endpoint = L10n.tr("Localizable", "global.strings.endpoint")
/// Hide
internal static let hide = L10n.tr("Localizable", "global.strings.hide")
/// Interface
internal static let interface = L10n.tr("Localizable", "global.strings.interface")
/// Keep-alive
@ -493,6 +501,8 @@ internal enum L10n {
internal static let save = L10n.tr("Localizable", "global.strings.save")
/// Servers
internal static let servers = L10n.tr("Localizable", "global.strings.servers")
/// Show
internal static let show = L10n.tr("Localizable", "global.strings.show")
/// Translations
internal static let translations = L10n.tr("Localizable", "global.strings.translations")
/// Uninstall
@ -540,63 +550,11 @@ internal enum L10n {
}
}
internal enum System {
internal enum ActiveProfile {
internal enum Items {
internal enum Customize {
/// Customize...
internal static let title = L10n.tr("Localizable", "menu.system.active_profile.items.customize.title")
}
}
internal enum Messages {
/// No account configured
internal static let missingCredentials = L10n.tr("Localizable", "menu.system.active_profile.messages.missing_credentials")
}
internal enum Title {
/// No active profile
internal static let `none` = L10n.tr("Localizable", "menu.system.active_profile.title.none")
}
}
internal enum Organizer {
/// Organizer
internal static let title = L10n.tr("Localizable", "menu.system.organizer.title")
}
internal enum Preferences {
/// Preferences
internal static let title = L10n.tr("Localizable", "menu.system.preferences.title")
}
internal enum Quit {
/// Quit %@
internal static func title(_ p1: Any) -> String {
return L10n.tr("Localizable", "menu.system.quit.title", String(describing: p1))
}
internal enum Messages {
/// The VPN, if enabled, will still run in the background. Do you want to quit?
internal static let confirm = L10n.tr("Localizable", "menu.system.quit.messages.confirm")
}
}
internal enum ShareGeneric {
/// Invite a friend
internal static let caption = L10n.tr("Localizable", "menu.system.share_generic.caption")
}
internal enum ShareTwitter {
/// Tweet about it!
internal static let caption = L10n.tr("Localizable", "menu.system.share_twitter.caption")
}
internal enum Show {
/// Show
internal static let title = L10n.tr("Localizable", "menu.system.show.title")
}
internal enum Support {
/// Make a donation
internal static let donate = L10n.tr("Localizable", "menu.system.support.donate")
/// Join community
internal static let joinCommunity = L10n.tr("Localizable", "menu.system.support.join_community")
/// Write a review
internal static let writeReview = L10n.tr("Localizable", "menu.system.support.write_review")
}
internal enum SwitchProfile {
/// Active profile
internal static let title = L10n.tr("Localizable", "menu.system.switch_profile.title")
}
}
}

View File

@ -0,0 +1,35 @@
//
// MacBridge.swift
// Passepartout
//
// Created by Davide De Rosa on 6/25/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
@objc(MacBridge)
public protocol MacBridge: NSObjectProtocol {
init()
var utils: MacUtils { get }
var menu: MacMenu { get }
}

View File

@ -0,0 +1,42 @@
//
// MacMenu.swift
// Passepartout
//
// Created by Davide De Rosa on 6/25/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
@objc
public protocol MacMenu {
var delegate: MacMenuDelegate? { get set }
func install()
}
@objc
public protocol MacMenuDelegate {
var profileManager: LightProfileManager { get }
var providerManager: LightProviderManager { get }
var vpnManager: LightVPNManager { get }
}

View File

@ -0,0 +1,41 @@
//
// MacUtils.swift
// Passepartout
//
// Created by Davide De Rosa on 6/25/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
@objc
public protocol MacUtils {
var isForeground: Bool { get }
func toggleForeground()
func bringAppToForeground()
func sendAppToBackground()
}
@objc
public protocol MacUtilsDelegate {
}

View File

@ -0,0 +1,65 @@
//
// LightProfileManager.swift
// Passepartout
//
// Created by Davide De Rosa on 7/3/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
@objc(LightProfile)
public protocol LightProfile {
var id: UUID { get }
var name: String { get }
var vpnProtocol: String { get }
var isActive: Bool { get }
var providerName: String? { get }
var providerServer: LightProviderServer? { get }
}
extension LightProfile {
public var isProvider: Bool {
providerName != nil
}
}
@objc
public protocol LightProfileManager {
var hasProfiles: Bool { get }
var profiles: [LightProfile] { get }
var activeProfileId: UUID? { get }
var activeProfileName: String? { get }
var delegate: LightProfileManagerDelegate? { get set }
}
@objc
public protocol LightProfileManagerDelegate {
func didUpdateProfiles()
}

View File

@ -0,0 +1,69 @@
//
// DefaultLightProviderManager.swift
// Passepartout
//
// Created by Davide De Rosa on 7/7/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
@objc(LightProviderCategory)
public protocol LightProviderCategory {
var name: String { get }
var locations: [LightProviderLocation] { get }
}
@objc(LightProviderLocation)
public protocol LightProviderLocation {
var description: String { get }
var id: String { get }
var countryCode: String { get }
var servers: [LightProviderServer] { get }
}
@objc(LightProviderServer)
public protocol LightProviderServer {
var description: String { get }
var categoryName: String { get }
var locationId: String { get }
var serverId: String { get }
}
@objc
public protocol LightProviderManager {
var delegate: LightProviderManagerDelegate? { get set }
func categories(_ name: String, vpnProtocol: String) -> [LightProviderCategory]
func downloadIfNeeded(_ name: String, vpnProtocol: String)
}
@objc
public protocol LightProviderManagerDelegate {
func didUpdateProviders()
}

View File

@ -0,0 +1,59 @@
//
// LightVPNManager.swift
// Passepartout
//
// Created by Davide De Rosa on 7/3/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
@objc(LightVPNStatus)
public enum LightVPNStatus: Int {
case connecting
case connected
case disconnecting
case disconnected
}
@objc
public protocol LightVPNManager {
var isEnabled: Bool { get }
var vpnStatus: LightVPNStatus { get }
func connect(with profileId: UUID)
func connect(with profileId: UUID, to serverId: String)
func toggle()
func reconnect()
var delegate: LightVPNManagerDelegate? { get set }
}
@objc
public protocol LightVPNManagerDelegate {
func didUpdateState(isEnabled: Bool, vpnStatus: LightVPNStatus)
}

View File

@ -0,0 +1,37 @@
//
// MenuBuilder.swift
// Passepartout
//
// Created by Davide De Rosa on 6/24/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
@objc(MenuBuilder)
public protocol MenuBuilder: NSObjectProtocol {
weak var delegate: MenuDelegate? { get set }
init()
func sendAppToBackground()
func buildMenu()
}

View File

@ -0,0 +1,31 @@
//
// MenuDelegate.swift
// Passepartout
//
// Created by Davide De Rosa on 6/24/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
@objc(MenuDelegate)
public protocol MenuDelegate {
func toggleForegroundClicked(isForeground: Bool)
}

View File

@ -46,6 +46,11 @@
"global.strings.keepalive" = "Keep-alive";
"global.strings.advanced" = "Advanced";
"global.strings.translations" = "Translations";
"global.strings.show" = "Show";
"global.strings.hide" = "Hide";
"global.strings.connect" = "Connect";
"global.strings.disconnect" = "Disconnect";
"global.strings.download" = "Download";
"global.messages.email_not_configured" = "No e-mail account is configured.";
"global.messages.share" = "Passepartout is a user-friendly, open source OpenVPN / WireGuard client for iOS and macOS";
@ -71,21 +76,20 @@
"menu.contextual.share_twitter" = "Tweet";
"menu.contextual.share_generic" = "Invite";
"menu.system.show.title" = "Show";
"menu.system.switch_profile.title" = "Active profile";
"menu.system.active_profile.title.none" = "No active profile";
"menu.system.active_profile.items.customize.title" = "Customize...";
"menu.system.active_profile.messages.missing_credentials" = "No account configured";
"menu.system.organizer.title" = "Organizer";
"menu.system.preferences.title" = "Preferences";
"menu.system.support.donate" = "Make a donation";
"menu.system.support.join_community" = "Join community";
"menu.system.support.write_review" = "Write a review";
//"menu.system.switch_profile.title" = "Active profile";
//"menu.system.active_profile.title.none" = "No active profile";
//"menu.system.active_profile.items.customize.title" = "Customize...";
//"menu.system.active_profile.messages.missing_credentials" = "No account configured";
//"menu.system.organizer.title" = "Organizer";
//"menu.system.preferences.title" = "Preferences";
//"menu.system.support.donate" = "Make a donation";
//"menu.system.support.join_community" = "Join community";
//"menu.system.support.write_review" = "Write a review";
// "menu.system.support.translate" = "Offer to translate";
"menu.system.share_twitter.caption" = "Tweet about it!";
"menu.system.share_generic.caption" = "Invite a friend";
//"menu.system.share_twitter.caption" = "Tweet about it!";
//"menu.system.share_generic.caption" = "Invite a friend";
"menu.system.quit.title" = "Quit %@";
"menu.system.quit.messages.confirm" = "The VPN, if enabled, will still run in the background. Do you want to quit?";
//"menu.system.quit.messages.confirm" = "The VPN, if enabled, will still run in the background. Do you want to quit?";
/* MARK: TunnelKit */

View File

@ -1,6 +0,0 @@
strings:
inputs:
- en.lproj/Localizable.strings
outputs:
- templateName: structured-swift4
output: Constants/SwiftGen+Strings.swift

View File

@ -0,0 +1,20 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "StatusActive@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

View File

@ -0,0 +1,20 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "StatusPending@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,31 @@
//
// Bridging-Header.h
// Passepartout
//
// Created by Davide De Rosa on 6/25/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/>.
//
#ifndef BridgingHeader_h
#define BridgingHeader_h
#import "ProcessTransformer.h"
#endif /* BridgingHeader_h */

View File

@ -0,0 +1,36 @@
//
// Constants+Mac.swift
// Passepartout
//
// Created by Davide De Rosa on 7/3/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 Constants {
enum Mac {
private static var bundle: Bundle {
Bundle(for: PassepartoutMac.self)
}
static let appLauncherId: String = bundleConfig("launcher_id", in: bundle)
}
}

View File

@ -0,0 +1,82 @@
//
// Theme.swift
// Passepartout
//
// Created by Davide De Rosa on 7/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 AppKit
private var bundle: Bundle {
Bundle(for: PassepartoutMenu.StatusButton.self)
}
extension LightVPNStatus {
var localizedDescription: String {
switch self {
case .connecting:
return L10n.Tunnelkit.Vpn.connecting
case .connected:
return L10n.Tunnelkit.Vpn.active
case .disconnecting:
return L10n.Tunnelkit.Vpn.disconnecting
case .disconnected:
return L10n.Tunnelkit.Vpn.inactive
}
}
}
extension LightVPNStatus {
var image: NSImage {
let resourceName: String
switch self {
case .connected, .disconnected:
resourceName = "StatusActive"
case .connecting, .disconnecting:
resourceName = "StatusPending"
}
guard let image = bundle.image(forResource: resourceName) else {
fatalError("Resource not found: \(resourceName)")
}
return image
}
var imageAlpha: Double {
switch self {
case .disconnected:
return 0.5
default:
return 1.0
}
}
}
extension LightProviderLocation {
var nsImage: NSImage? {
bundle.image(forResource: "flags/\(countryCode.lowercased())")
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ad@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ae@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "af@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ag@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ai@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "al@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "am@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ao@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "aq@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ar@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "as@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "at@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "au@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "aw@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ax@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "az@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "ba@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bb@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bd@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "be@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bf@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bg@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bh@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bi@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bj@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bl@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bm@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bn@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bo@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bq@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "br@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bs@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

View File

@ -0,0 +1,17 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x"
},
{
"filename" : "bt@2x.png",
"idiom" : "mac",
"scale" : "2x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

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