fix(realtime): debounce the reconnecting toast to stop transient-blip flashes#5111
Conversation
… flashes The "Reconnecting..." persistent toast fired the instant isReconnecting flipped true, so sub-second transport blips that self-heal on the first retry flashed a scary alert. Add useStableFlag, an anti-flicker boolean that delays the rising edge (2s, so brief blips never surface) and holds the falling edge (1.5s min visible, so a drop just past the delay does not flash-and-vanish). The socket flag stays accurate; only the user-facing alarm is smoothed. State machine extracted into a framework-agnostic controller with unit coverage for both flicker modes.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryLow Risk Overview Adds Includes 10 Vitest tests on the controller (flash-on/off, boundaries, mid-hold flap, idempotency, dispose). Reviewed by Cursor Bugbot for commit 030b6c0. Configure here. |
|
@greptile review |
Greptile SummaryThis PR fixes a UX issue where the "Reconnecting…" persistent toast would flash briefly during sub-second Socket.IO transport hiccups that self-heal before users can even read the message. It introduces
Confidence Score: 5/5Safe to merge — a narrow, well-tested addition that touches only the toast display path and does not affect socket state, permissions, or data flow. The change is a self-contained UI smoothing layer. The controller logic is deterministic and exhaustively covered by unit tests with fake timers. All previously raised review concerns have been addressed in the head commit. No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "fix(realtime): reset stable-flag React s..." | Re-trigger Greptile |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 978bac1. Configure here.
…cuous blip test Address Greptile review: - useStableFlag: reset React state to the fresh controller's baseline when the controller is recreated on an options change, so a dynamic consumer changing delayMs/minVisibleMs while active with value already false can no longer strand the flag at true. - test: read the live probe.active getter in the blip test instead of a destructured snapshot, which was bound to false at destructure time and made the assertion vacuous.
|
@greptile review |
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 030b6c0. Configure here.
Summary
isReconnectingflipped true. Socket.IO flips that flag on any disconnect — including sub-second transport hiccups that recover on the very first retry (reconnectionDelay: 1000) — so a momentary blip flashed a scary alert that vanished a beat later.useStableFlag, an anti-flicker boolean that smooths both edges:valuemust stay true fordelayMs(2000ms) before the flag turns on, so blips that self-heal within the window never surface.minVisibleMs(1500ms), so a drop that lasts just past the delay doesn't flash-and-vanish.createStableFlagController) and covered by 10 unit tests: both flicker modes, genuine outage, mid-hold flap (reconnect bouncing during the hold window), idempotent re-feeds, and dispose cancellation.Why this is the canonical pattern (not a hack)
This is the textbook anti-flicker fix for connection indicators, confirmed from two angles:
socket.activeexists precisely to distinguish temporary (self-healing) from terminal failures. Delaying the UI aligns with that intent rather than papering over it. → https://socket.io/docs/v4/tutorial/handling-disconnectionsComplementary / out of scope (noted for reviewers): Socket.IO connection state recovery addresses data continuity across drops (missed events), not the UI alarm — a separate concern from this change. → https://socket.io/docs/v4/connection-state-recovery
Type of Change
Testing
createStableFlagControllerstate machine (fake timers, no DOM) covering both flicker modes, genuine outage, mid-hold flap, idempotency, and dispose — all passing.Checklist