refactor: introduce pause method to socket service to preserve event listeners during idle disconnects
This commit is contained in:
@@ -44,7 +44,11 @@ export function PresenceProvider({ children }: { children: React.ReactNode }) {
|
||||
const disconnectForIdle = useCallback(() => {
|
||||
if (!isConnectedRef.current) return;
|
||||
isIdleRef.current = true;
|
||||
socketService.disconnect();
|
||||
// Use pause() instead of disconnect() so subscriber handlers
|
||||
// (useMessaging listeners) survive the reconnect. Otherwise the
|
||||
// user would have to refresh the page after returning from idle
|
||||
// to see new messages in real time again.
|
||||
socketService.pause();
|
||||
}, []);
|
||||
|
||||
// Track socket connection state
|
||||
|
||||
@@ -176,17 +176,18 @@ class SocketService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully disconnect and clear every subscriber handler. Use ONLY on logout
|
||||
* — this invalidates every registered listener across the app.
|
||||
*
|
||||
* For transient disconnects (tab hidden, user idle), use `pause()` instead
|
||||
* so React-registered listeners survive the reconnect.
|
||||
*/
|
||||
disconnect(): void {
|
||||
if (this.socket) {
|
||||
this.socket.removeAllListeners();
|
||||
this.socket.disconnect();
|
||||
this.socket = null;
|
||||
}
|
||||
this.pause();
|
||||
this.currentToken = null;
|
||||
this.isConnecting = false;
|
||||
this.connectPromise = null;
|
||||
this.listenersAttached = false;
|
||||
// Clear all handler sets to prevent leaks
|
||||
// Clear all handler sets — only safe on logout because every subscriber
|
||||
// must re-register after a fresh login.
|
||||
this.messageHandlers.clear();
|
||||
this.typingStartHandlers.clear();
|
||||
this.typingStopHandlers.clear();
|
||||
@@ -199,6 +200,26 @@ class SocketService {
|
||||
this.authErrorHandlers.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down the socket without clearing subscriber handler sets.
|
||||
* Used for idle/visibility disconnects so that when we reconnect,
|
||||
* the existing React hooks' handlers automatically resume receiving
|
||||
* events without needing to re-register.
|
||||
*/
|
||||
pause(): void {
|
||||
if (this.socket) {
|
||||
this.socket.removeAllListeners();
|
||||
this.socket.disconnect();
|
||||
this.socket = null;
|
||||
}
|
||||
this.isConnecting = false;
|
||||
this.connectPromise = null;
|
||||
this.listenersAttached = false;
|
||||
// Intentionally keep: currentToken, messageHandlers, typingStart/StopHandlers,
|
||||
// statusHandlers, readHandlers, deliveredHandlers, connectionRequest/ResponseHandlers,
|
||||
// connectionHandlers, authErrorHandlers
|
||||
}
|
||||
|
||||
isConnected(): boolean {
|
||||
return this.socket?.connected || false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user