← Back to PRs

#16767: fix: auto-resync webchat on reconnect and prevent message flicker on stream complete

by alewcock open 2026-02-15 03:01 View on GitHub →
app: web-ui stale size: S
## Bug 1: Message flicker on stream complete When a streamed chat response finishes, the streamed content disappears briefly before `loadChatHistory` completes — the user sees a gap where the message vanishes then reappears. **Root cause:** `handleChatEvent` clears `chatStream` on "final" state before the history reload finishes. **Fix:** In `handleChatEvent`, when state is "final" and `payload.message` exists, immediately append the final message to `chatMessages` *before* clearing `chatStream`. The subsequent `loadChatHistory` replaces the array with the authoritative server copy, but the user sees no flicker. ## Bug 2: iOS Safari backgrounding — no automatic resync When Safari is backgrounded on iOS, the WebSocket dies. On return, the client reconnects but the chat shows stale messages. **Root cause:** The reconnect path resets stream state but never reloads chat history. The `onGap` handler only sets an error message without recovering. **Fix:** - **`gateway.ts`:** Add `onReconnect` callback to `GatewayBrowserClientOptions`, fired after a successful `connect` on reconnections (not the initial connection). Tracked via a `hasConnectedOnce` flag. - **`app-gateway.ts`:** Wire `onReconnect` to call `refreshChat()`. Update `onGap` to also trigger `refreshChat()` (and auto-clear the gap error). Add a `visibilitychange` listener that refreshes chat when the user returns to the tab (debounced at 300ms). <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixes two webchat bugs: message flicker on stream completion and missing chat resync after iOS Safari backgrounding. The flicker fix appends the final message to `chatMessages` before clearing `chatStream`, preventing the gap where streamed content vanishes while `loadChatHistory` completes. The resync fix adds an `onReconnect` callback to the gateway client (triggered after successful reconnects, not initial connections) and wires it to refresh chat history. Also adds a `visibilitychange` listener that refreshes chat when users return to the tab, addressing iOS Safari backgrounding. The `onGap` handler now triggers `refreshChat()` and auto-clears the error message after sync completes. <h3>Confidence Score: 3/5</h3> - This PR fixes real bugs but introduces a memory leak that should be addressed before merging - The fixes for message flicker and chat resync are sound and address real user-facing issues. However, the `visibilitychange` listener is never removed, causing listener accumulation if `connectGateway` is called multiple times. This is already noted in previous review threads but remains unaddressed. - `ui/src/ui/app-gateway.ts` requires cleanup of the visibilitychange listener to prevent memory leak <sub>Last reviewed commit: 4af8dac</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs