Introduce a timing buffer for the Check for Updates flow to avoid jarring UI.#2879
Introduce a timing buffer for the Check for Updates flow to avoid jarring UI.#2879danielpunkass wants to merge 7 commits into
Conversation
02fd0a4 to
9b81430
Compare
…ring UI. When a check completes or fails very quickly, the "Checking for Updates" window flashes briefly before being replaced by the next alert. This PR introduces a buffering mechanism whereby SPUStandardUserDriver defers presenting the progress window for 0.3 seconds. If a result is obtained within that time frame, the progress window is never displayed. When and if the checking window has actually appeared on screen, a minimum visible duration of 0.7 seconds must elapse before the panel is dismissed.
9b81430 to
7d78e7e
Compare
|
I do wonder a bit if this behavior should be UI driver agnostic or not. In other words, can we imagine any type of custom UI where it's beneficial to not have this sort of timing buffer logic? For example Other custom UIs may use the same UI element (button, window, ..) for both checking and show update states. On the other hand, some custom UI implementors may have done their own time buffering deferral and may have to think about compatibility. |
|
Well I didn't have to go far to find an app with custom UI that a timing buffer deferral approach would not be suitable, so scratch that. custom-progress.mov |
| _pendingPostCheckingCancellation = nil; | ||
| } | ||
|
|
||
| - (BOOL)_finishPendingPostCheckingTransition SPU_OBJC_DIRECT |
There was a problem hiding this comment.
Return value is unused from caller.
There was a problem hiding this comment.
Actually this method is only used in one place and probably shouldn't be a method on its own. It's not helpful to separate it out. Also _pendingPostCheckingCompletion probably is not needed to store as an ivar.
There was a problem hiding this comment.
Superseded by new approach.
…ndardUserDriver and into SUStatusController so that most of the same show/dismiss patterns can be applied, with the buffered timing happened automatically. Some special care was needed to ensure that edge case scenarios like when the user clicks "Cancel" after the underlying check had already completed, that it doesn't continue to show them the checking results.
…inimize noise in the patch.
|
I believe showUpdateInFocus needs to be able to show the status window immediately when _retryTerminatingApplication != nil. An edge case I can think of is when you "Install and Relaunch" (which closes the window) but the app cancels the quit request, and the user checks for updates again and can retry that request. Similarly the status window controller is used from the Updater.app (installer progress agent). That is already on a delayed timing buffer (~0.7 seconds I will probably need to look at this PR multiple times. |
My comparative lack of understanding of Sparkle nuances is showing! Sorry about missing the subtleties. I'll take a closer look again.
Understandable, and if you think the gain is not worth the effort I totally get it. |
|
I had missed that the progress agent is imposing its own display delay, and it seems like the best solution would be if it can leverage the same internal buffering that |
…ide the checking window completion block.
|
The delay in the installation side is intertwined with IPC from Autoupdate between the host app and the progress agent, so I think it'd be less risky to have a way to invoke an immediate way of showing the window, which would be needed for the _retryTerminatingApplication != nil path as well. |
|
Does it seem like parameterizing the delay constant would be suitable? Then any client who needs it immediately could set the delay to 0? |
|
Sounds logical. |
When a check completes or fails very quickly, the "Checking for Updates" window flashes briefly before being replaced by the next alert.
This PR introduces a buffering mechanism whereby SPUStandardUserDriver defers presenting the progress window for 0.3 seconds. If a result is obtained within that time frame, the progress window is never displayed.
When and if the checking window has actually appeared on screen, a minimum visible duration of 0.7 seconds must elapse before the panel is dismissed.
Fixes #2878
Misc Checklist
Testing
I tested and verified my change by using one or multiple of these methods:
To replicate/confirm the various states for this UI flow, you can edit the SUCheckingWindowShowDelay and SUCheckingWindowMinDisplayTime const variables in SPUStandardUserDriver.m.
macOS version tested: macOS 26.5 (25F71)