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)
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
Simplify preferences model by doing a bulk load/save together with
load/save Profile. ModulePreferences is now a struct rather than an
ObservableObject, because it doesn't need ad hoc observation. It's just
a binding to ProfileEditor.preferences
Fix:
- Disable CloudKit in tunnel singleton of PreferencesManager
(.sharedForTunnel)
Additionally:
- Replace MainActor in PreferencesManager with Sendable (immutable)
- Replace MainActor from ProviderPreferencesRepository with Sendable
(syncs on NSManagedObjectContext)
- Drop ModuleMetadata for good
Replace favorites entities with a PreferencesManager, that returns
observables for:
- Module preferences (by module UUID)
- Provider preferences (by ProviderID)
Automate preferences availability in:
- Module views (empty for now)
- VPN server view (favorites)
Synchronize preferences by making this a CloudKit container. Preferences
are also available in the Tunnel by storing the container in the App
Group.
Let the AppCoordinator take care of the connection requirements via
modals:
- onInteractiveLogin() - now presented on AppError
- onProviderEntityRequired()
- onPurchaseRequired()
- Any other connection error
Subviews must not use tunnel.connect(), rather they route connection
requests via the ConnectionFlow callbacks. In particular, migrate to the
AppCoordinator the connection logic from:
- TunnelToggleButton.perform()
- ProviderEntitySelector.onSelect()
onInteractiveLogin() and onPurchaseRequired() are now handled
internally, while onProviderEntityRequired() is kept public because it's
how subviews may present the entity selector.
Extras:
- Avoid modals overlap with a 500ms delay
- Shrink interactive login size on macOS