Fix iOS connection loss: track WebSocket state and show reconnecting …#906
Fix iOS connection loss: track WebSocket state and show reconnecting …#906marcodejongh wants to merge 8 commits intomainfrom
Conversation
Claude Review✅ Ready to merge - Minor issues noted below, but nothing blocking. Issues
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27d953fc2b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Claude Review✅ Ready to merge - Minor issues noted below, but nothing blocking. Issues
Notes
|
Claude Review✅ Ready to merge - Well-implemented iOS reconnection handling with proper state tracking, documentation, and tests. Minor issues:
Notes:
|
Claude Review✅ Ready to merge - Minor issues noted below, but nothing blocking. Issues
DocumentationDocumentation update to |
…overlay When iOS Safari backgrounds the app, the OS silently kills the WebSocket connection. Previously the UI stayed fully interactive while changes silently failed to sync. This adds real-time WebSocket connection state tracking via graphql-ws on.connected/on.closed callbacks, a visibilitychange handler to proactively detect dead sockets on iOS foreground return, and a "Reconnecting..." overlay on the queue control bar that blocks interaction until the connection recovers. https://claude.ai/code/session_016bdrJ2mAmjzSmZ2z6vWGN9
The on.connected callback was setting isWebSocketConnected=true immediately, before handleReconnect could finish its async joinSession/delta-sync path. This caused isReconnecting to become false prematurely, re-enabling queue mutations while stale state was still being replayed. Fix: onConnectionStateChange now receives an isReconnect flag. On reconnections, the persistent session defers setting isWebSocketConnected=true until handleReconnect's finally block, keeping the reconnecting overlay and viewOnlyMode active throughout the entire resync. Also adds iOS background connection loss documentation to docs/websocket-implementation.md (section 7 under Failure States). https://claude.ai/code/session_016bdrJ2mAmjzSmZ2z6vWGN9
- graphql-client.test.ts: Tests onConnectionStateChange callback fires with correct (connected, isReconnect) flags across initial connect, disconnect, and reconnection sequences. Verifies callback ordering (stateChange fires before onReconnect). - connection-state.test.ts: Tests isReconnecting derivation truth table, reconnect lock timing (isReconnecting stays true during resync), and visibilitychange debounce behavior (300ms delay, rapid-fire cancellation, hidden state ignored). https://claude.ai/code/session_016bdrJ2mAmjzSmZ2z6vWGN9
The full-page overlay blocked all user interaction. Replace it with a bottom-center Snackbar/Alert that shows "Reconnecting..." with a spinner and automatically disappears when the connection is re-established. Queue mutations are still prevented by viewOnlyMode during reconnection. https://claude.ai/code/session_016bdrJ2mAmjzSmZ2z6vWGN9
Break the BoardSessionBridge reactivation loop that caused infinite connect/disconnect cycles after join failures. Track failed session IDs so the bridge doesn't re-activate a session that was just cleared. Also harden getSessionMembers() against partial Redis data (missing username would violate String! schema constraint) and add production-safe logging to the joinSession resolver. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72f6d02 to
dd0b4f6
Compare
Claude Review✅ Ready to merge - Well-designed iOS connection recovery with good test coverage and documentation. Minor issues:
Verification notes:
|
The "detect failed session" effect in BoardSessionBridge was marking sessions as failed on initial mount when activeSession is null (not yet set), preventing the activation effect from ever running. Now only marks a session as failed after it was previously active and then cleared. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude Review✅ Ready to merge - Solid implementation for iOS connection loss detection with proper state management, tests, and documentation. Notes (non-blocking)
|
The EVENTS_REPLAY query was using GraphQL field aliases (addedItem: item, currentItem: item), so the response already had aliased field names. But transformToSubscriptionEvent was reading event.item (the un-aliased name), which was undefined at runtime. Remove the aliases so the response matches the QueueEvent type, and the transform function correctly remaps the fields. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…overlay
When iOS Safari backgrounds the app, the OS silently kills the WebSocket connection. Previously the UI stayed fully interactive while changes silently failed to sync. This adds real-time WebSocket connection state tracking via graphql-ws on.connected/on.closed callbacks, a visibilitychange handler to proactively detect dead sockets on iOS foreground return, and a "Reconnecting..." overlay on the queue control bar that blocks interaction until the connection recovers.
https://claude.ai/code/session_016bdrJ2mAmjzSmZ2z6vWGN9