fix: handleDownloadStarted silently drops download state when completed auto-dismiss fires - #236
Conversation
…ed auto-dismiss fires
When a download started while the recommendation phase was 'completed'
(within the 1500ms auto-dismiss window), handleDownloadStarted
transitioned the phase to 'downloading' but left the
completedTimeoutRef armed. When that timer later fired, it
unconditionally called setRecommendation(null) and
setRecommendationPhase('idle'), wiping out the in-progress download
state.
handleManualDownloading already calls clearHotswapTimeout() and
clearCompletedTimeout() before transitioning; handleDownloadStarted
was missing the same cleanup. Add the two clear calls so stale timeouts
can never overwrite a fresh download phase.
Added test: 'clears the completed auto-dismiss timer when a download
starts mid-success'.
|
Thanks for this, @Ayush7614 — you traced an actual state-machine hole here, not a theoretical one, and the write-up made it easy to verify. 🙏 I walked the code path before reading the prose:
Two things to clean up. 1. The diff is 90% whitespaceThe entire Prettier will fight this. Please rebase the change so the diff is just the two added 2.
|
…ccess - handleDownloadStarted now calls clearHotswapTimeout() + clearCompletedTimeout() before transitioning to 'downloading', matching handleManualDownloading, so a stale completed timeout can never wipe out a fresh download phase. - Add clearCompletedTimeout to the effect deps array. - Restore original indentation so the diff is just the two clear calls.
|
Thanks for the review @Vect0rM Addressed both review points on branch
Verified locally: |
|
Both points addressed exactly as asked — thanks for the quick turnaround, @Ayush7614. 🙏 I re-verified
Approving and merging. Thanks for chasing down a timer-outliving-its-state bug and then writing the test that pins it — that's the harder half, and it's the half most contributions skip. ⏱️ |
When a download started while the recommendation phase was 'completed' (within the 1500ms auto-dismiss window), handleDownloadStarted transitioned the phase to 'downloading' but left the completedTimeoutRef armed. When that timer later fired, it unconditionally called setRecommendation(null) and setRecommendationPhase('idle'), wiping out the in-progress download state.
handleManualDownloading already calls clearHotswapTimeout() and clearCompletedTimeout() before transitioning; handleDownloadStarted was missing the same cleanup. Add the two clear calls so stale timeouts can never overwrite a fresh download phase.
Added test: 'clears the completed auto-dismiss timer when a download starts mid-success'.