Restore CDModulePreferencesV3 to track the history of module prefrences.
This way, excluded endpoints may be saved globally to Core Data as a
starting point. Then in Profile.userInfo we only save the relevant
exclusions for the current configuration.
The .excludedEndpoints relationship is therefore moved out of
CDProviderPreferencesV3.
Further refactoring:
- ModuleViewParameters now includes a ModulePreferences observable that
module views can observe
- Tunnel doesn't need access to PreferencesManager anymore (exclusions
are in Profile.userInfo)
Sort out the increasing mess coming from:
- AppContext*
- Dependencies
- Shared*
by doing the following:
- Keep in the "Shared" folder only the entities actually shared by
App/Tunnel
- Create TunnelContext
- Move AppContext and related to the App/Context folder
- Move TunnelContext and related to the Tunnel/Context folder
- Delete Shared+* extensions, use AppContext/TunnelContext singletons
from the app
- Create a Dependencies factory singleton to create entities in a single
place
- Split extensions by domain
- Make it clear with `func` vs `var` when a dependency method returns a
new instance
Formerly via blocks, now with final classes.
App:
- ProfileProcessor
- AppTunnelProcessor
- Implemented by DefaultAppProcessor in app
- Implemented by MockAppProcessor in UILibrary (for previews)
Tunnel:
- PacketTunnelProcessor
- Implemented by DefaultTunnelProcessor
Clarify the use of contexts:
- **Production** (.shared)
- **Previews** (.mock → .forPreviews)
- ONLY use it in UILibrary for, well, previews
- This context has dumb profiles with UUIDs as names
- Registry is fake
- **UI Tests** (.forUITesting)
- Add new context for UI testing
- Selected based on command line arguments
- This context has mock data tuned for decent screenshots
- Registry is real
Share the same InAppProcessor in .shared and .forTesting contexts
because the app behavior was inconsistent regarding e.g. in-app
purchases.
Ready for screenshots generation, except for the tests themselves and
the TV target.
- More customizations while UI testing
- Act as full version user in IAPManager
- Override layout with default to .grid if isBigDevice
- Show module names in profile list/grid
- Improve mock Profile/ProfileManager
- Meaningful profile names
- iCloud/TV icons
- Initial modules
- Improve XCTest extensions
- Screenshot destination (attachment/temporary)
- Screenshot target (window/sheet)
- Print saved temporary URL at the end (may help with CI)
- Append device name to screenshot filename
- Tests
- Refactor actions with the [Page Object
pattern](https://swiftwithmajid.com/2021/03/24/ui-testing-using-page-object-pattern-in-swift/)
- Perform iPad screenshots in landscape
- Split simple flow tests and screenshots
- Add "Connect to" test
Closes#681
Create UITesting target with:
- AppCommandLine/AppEnvironment: strongly typed refactoring of PP_*
environment values
- AccessibilityInfo: identifies and locates elements for UI testing
Make the app behave differently when launched with `.uiTesting`, and
expose the flag to SwiftUI via `.environment(\.isUITesting)` to:
- Use the mock AppContext
- Skip onboarding
Add PassepartoutUITests target with two screenshot tests:
- Connected screen
- Profile modal
- Define separate IAPManager instances for app and tunnel (different
receipt URLs)
- Copy app receipt URL over to tunnel before install/connect
- Use AppTransaction to get original build number so that
FallbackReceiptReader is also much simpler now
Fixes#869
The Library package offers the PassepartoutImplementations target for
OpenVPN/OpenSSL and WireGuard/Go, but it doesn't need it itself. Only
the main app does, so move the dependency there.
On the other side, drop the potentially problematic AppUI meta target.
Move platform filters to the Xcode project.
Indirectly fixes a crash with Xcode 16 Previews on iOS (forced to use
legacy previews before):
https://forums.developer.apple.com/forums/thread/756681
Move Core Data tests out of the Library package so that we can still use
the more efficient `swift test` for most tests.
Create a PassepartoutTests target only for tests that require
`xcodebuild`, like Core Data tests.
Eventually:
- PRs only run SwiftPM tests
- Releases run ALL tests with `scan` before `gym`
Restore .sharing feature:
- Merge "Apple TV" into "iCloud" section
- "Enabled", disabled if ineligible for .sharing
- "Apple TV", disabled if ineligible for .appleTV || !isShared
- Footer about TV restrictions
Paywalls:
- "Share on iCloud" if ineligible for .sharing
- "Drop TV restriction" if eligible for .sharing but not for .appleTV
- Applies to full version products (user level 2)
- Suggest Apple TV product
Restrictions:
- Toggle CloudKit sync on remote repository based on .sharing
eligibility
- Do not start tunnel on Apple TV if ineligible for .appleTV
Fixes:
- Incorrect zip() publishers in remote repository
- Resolve duplicates in Core Data, first profile wins sorted by
lastUpdate descending
- Reload receipt on OOB IAPManager events
Refactoring:
- Get receipts from StoreKit Transaction.currentEntitlements
- Search for the originally purchased build in the local receipt anyway
(Kvitto)
- Fall back to release receipt (Kvitto), if any, for feature eligibility
in TestFlight builds
- Parse and verify expiration date in subscriptions
- Decouple in-app identifier composition from BundleConfiguration
- Fix user level features only applied when a receipt was not found
Testing:
- Add StoreKit configuration
- Fake purchases with PP_FAKE_IAP
- Fake user level with PP_USER_LEVEL
Then for reactive receipt reload, detect app activation differently:
- iOS/tvOS on .scenePhase
- macOS on launch and NSWorkspace.didActivateApplicationNotification
As to features:
- Credit former "Full version" purchasers with all current AND future
features, except the Apple TV