Suggest whenever .fullTV is suggested. For this reason, subscriptions
are not suggested to existing full version purchasers, because they only
miss the one-time .appleTV purchase. Group purchases by feature products
and full version products, e.g.:
- Features
- Apple TV
- Full version
- Yearly
- Monthly
- Full
- Full + TV
Additionally, fix reloadReceipt() slowing down onLaunch() sometimes. The
warning sign would appear on restricted profiles until the receipt is
loaded.
- Move non-CI scripts to "scripts"
- Use lowercase variables consistently
- Work with relative paths
- Work with environment
- Parametrize Xcode build/version number (move uniq last)
- Present paywall only on save/connect because PurchaseRequiredButton
instances were presenting paywalls with partial requirements
- Retain PurchaseRequiredButton just to flag paid features visually, but
do nothing on tap
- Suggest paywall products via IAPManager and required features, rather
than from views
- Handle .sharing/.appleTV requirements in ProfileCoordinator, rather
than in StorageSection
- Discontinue platform purchases, but treat as full if iOS + macOS
Before anything, remove any code related to App Group containers from
tvOS target because they are not available. Include the beta receipt
override, it's broken for that reason.
In short:
- Store all Core Data containers locally. Do not use the App Group for
Core Data for consistency across platforms.
- Store logs in the App Group on iOS/macOS, but locally on tvOS (see
`urlForCaches`).
Then, rather than one container per model, merge models into:
- Local: Providers
- Remote: Profiles + Preferences (now in the same CloudKit container)
Reuse the remote model for backups too.
This change is safe because:
- Local profiles are stored via Network Extension in the keychain, not
Core Data
- Remote profiles are re-imported via CloudKit sync
- Providers are re-downloaded on first use
- Preferences are lost, but they are "cheap" data
- Profile backups are lost, but they were hidden anyway
- Simplify badges
- Drop app description, annoying to maintain (refer to the website)
- Drop screenshots (refer to the App Store)
- Update Credits
- Inform about private PassepartoutKit
Fixes#613
Revert #996 and do something midway:
- When set, use preset filter as selection (disambiguate compatible
presets)
- Set initial preset filter with current selected server preset
Server selection still picks a random preset if:
- Preset filter is "Any"
- More than one preset is compatible
Could not create the Preferences Core Data container in the App Group
because sub-directories did not exist. Create them upfront when using
App Group URLs.
This was not an issue with other Core Data containers because they are
stored in the app directories, where "Library/Documents" already exists.
Add TV screenshots and organize PassepartoutUITests with two test plans
for generating iOS/macOS (Main) and tvOS (TV) screenshots. Revert to the
.attachment destination and use `xcparse` to export the screenshots.
Change iPad screenshots to portrait.
Then autogenerate framed screenshots in two steps:
- Export the UITests screenshots per device (`export.sh`)
- Embed the results in a HTML/CSS template and take snapshots with
Chrome headless (`compose.sh`)
- Repeat for all devices (iPhone, iPad, Mac and Apple TV)
- Save framed screenshots to the `fastlane` screenshots directory
Unframed for now.
- Split Main/TV targets
- Extend ProfileManager for screenshot scenarios
- Rename UITesting to UIAccessibility
Active profile looks very big on TV simulator, temporarily commented
`.padding(.top, 50)` in ActiveProfileView.
Closes#974
Drop "Any" to rather make the preset filter an explicit preset
selection.
Regardless of `filtersWithSelection`, _always_ enforce the preset filter
to:
- The preset of the currently selected entity
- The first among available presets (normally non-empty)
Fixes#995
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)
Store module preferences in the Profile.userInfo field for atomicity.
Access and modification are dramatically simplified, and synchronization
comes for free.
On the other side, fix provider preferences synchronization by using
viewContext for the CloudKit container.
Fixes#992
- Save/rollback was done outside of MOC
- Use different contexts for module/provider preferences
- Save providers → also saves modules
- Discard modules → also discards providers
- Use background context because it's not automatically merged (can
rollback)
- Expose ModulePreferences in OpenVPNView as StateObject
- Rework Blacklist to a more reusable ObservableList
- Reapply #988