Verification was only performed for interactive login, not for provider
server selection. Do that before a connection attempt, so that the
paywall always appears first.
Regressed recently in library. When a profile was "Inactive
(on-demand)", saving it would revert to "Inactive" because the
underlying manager was being disabled.
Merge former ContainerView into main view and define platform-specific
subviews:
- ContainerView (composition of content + filters)
- ContentView
- FiltersView
Reuse the same receipt trick from iOS.
Also, fix a regression in IAPManager.fetchLevelIfNeeded() from #903,
where a guard after an await was dropped leading to reentrancy issues.
- PaywallView is the paywall content
- PaywallModifier attaches paywall with optional confirmation
- PurchaseRequiredButton presents paywall explicitly
- PaywallReason is the compound input
Refactoring:
- PurchaseRequiredButton takes a custom view
- PurchaseAlertModifier was merged into PaywallModifier
- PurchaseButtonModifier was merged into PurchaseRequiredButton
- Modal options were packed into a single struct
Confirmation alert presented on:
- Connect to ineligible profile (AppCoordinator)
- Save ineligible profile (ProfileCoordinator)
Includes:
- Credits
- Donations
- Diagnostics
- Version
Had to:
- Wrap tab view into a NavigationStack for full-screen navigation
- Take out navigation titles of about subviews
- Customize donations view layout with modifier
- Fix credits and debug log to support scrolling
Closes#914
- Move about subviews to UILibrary
- Refactor about to single coordinator + platform views
- Refactor debug log to single view + content views
- Take out debug log routes from about routes
- Rename Settings* to Preferences*
- Reuse empty modifier in debug log
- Fix a visual bug in .themeTrailingValue() (extra Spacer)
Preparation for #914
To get access to modules, try to avoid full Profile objects. Instead,
replace the coupled ProfileHeader occurrences with a new intermediary
ProfilePreview everywhere.
This way, a ProfileProcessor can inject the localized modules
descriptions from above with the preview() method.