Flashing on activation was caused by VPNManager.disable() in
ProfileView+VPN, because by setting lastError to nil it would
notify a change to ProfileRow (via VPNStateView) during the
profile row activation animation. That caused the flicker.
Instead, disable VPN first, then start the animation.
Anyway, avoid clearing a nil lastError.
ProfileView is not interested in changes in other profiles
notified by ProfileManager. Set isLoading inside
ObservableObject for observable to be self-contained.
Loses observation of profile deletion, but dismiss on removal is
actually handled by OrganizerView, not ProfileView.
Also drop unused presentationMode.
- Mac
- Drop all styles
- Tweak hide title bar
- Hide navigation bar
- Restore single section for all profiles
- Allows using NavigationLink safely
- Indirectly fixes multitasking
- Retains selection on profile activation
- Clean up presentActiveProfile
- Leave active profile in its position
- Fixes Mac flashing row selection on profile activation
- Unify profile row appearance
- Use fixed .headline font
- Add subtitles to inactive profiles
- Use padding rather than fixed row height
CAVEATS:
- Do not preselect active profile on iPad launch, as doing so
seems to present two ProfileView on top of each other, one from
MainView and one from the NavigationLink.
- Do not touch .listStyle() of master view, as it seems to break
navigation esp. in iPad multitasking.
Make action sync, but internally async (makeProfileReady). If not
doing so, UI on launch will not be able to show active profile
immediately. WelcomeView would appear for a moment.
Observe isReloadingCurrentProfile.
See 2b1efb8fec
- Update TunnelKit
- Receive TunnelKit notifications on main queue
- Bind VPN toggle to VPNManager directly (implicit animations)
- Update state on VPN didFail
- Set isEnabled = false after uninstalling VPN (not notified)
Works around a crash in iPadOS 14 portrait when removing section
containing first responder (profile name TextField). It happened
when submitting profile name via keyboard rather than "Save".
- Drop unused AppManager from OrganizerView
- Do not notify ProfileManager subscribers on activeProfileId
Saved active profile is already notified by:
- Core Data
- AppManager
- Move Localizable.strings above to share *.lproj folders
- Reorg menus into contextual/system
- Shorten titles of contextual menus
- Update sharing message with WireGuard
- Drop AlternativeTo
7 phrases left to translate into 9 languages.
Otherwise:
- Switch from former active profile A to B
- Connect to now active profile B
- Kill app
- Reopen app
- App shows connected to profile A
Because active profile was not saved immediately on switch.
Unnecessary now to also save it on background persist().
Infinite loop on init(), but horrible practice in general.
- DonateView
- PaywallView+Purchase
Also show a ProgressView while rows are loading.
DO NOT animate on .products value because animation won't work
if products are empty and stay empty after refresh. Instead,
observe .isRefreshingProducts.
Lastly, to avoid annoying animation when products are actually
available, do not refresh products if non-empty. They certainly
do not change during the application lifecycle.
Make sure to update localHeaders contextually with
removeProfiles() to avoid a second update in onChange(). The
equality check in onChange() guards against setting localHeaders
twice.
Not doing so may break animation in swipe-to-delete due to the
overlapping animations (it certainly does break on iOS 14).
- Fix missing PlugIns in Catalyst build
Hence the VPN failure, there was a "iOS" filter on embed.
- Fix complaint about file access permission
Seems to need R/W when importing VPN configuration files.
- Drop macOS target from Package.swift
- Drop @available attributes
- UI idiom
- Intents API
- Swipe actions in ProviderLocationView
- Review os(iOS)
- DebugLog, append idiom to tell Mac from iPad
- Drop redundant canImport
Content inside ScrollViewReader does not seem to be reload on
favorites toggle, for reasons I will review later. No big deal as
scrolling was already disabled.
Swipe to delete. Address a couple things on iPad though:
1. Also check provider availability before showing view
fatalError hit on iPad when navigating from a ready provider
profile to a non-ready one. Similar to when navigating between
different VPN protocols.
2. Suppress assertion on deleted profile
Deleting current profile via swipe seems to re-render a new
NavigationLink with the deleted profile, which results in
loading a deleted profile and hitting the assertion. Not sure if
this is a programming error or a glitch in ForEach.
- Drop status / navigation bars colors
- Restore large title on iPad
- Overlay organizer with "No profiles" when empty
- Uninstall VPN from ProfileView