diff --git a/src/providers/sip-provider.tsx b/src/providers/sip-provider.tsx index dcc9bf5..eb1d874 100644 --- a/src/providers/sip-provider.tsx +++ b/src/providers/sip-provider.tsx @@ -125,14 +125,14 @@ export const SipProvider = ({ children }: PropsWithChildren) => { } }; - const handleUnload = () => disconnectSip(); + const handleUnload = () => disconnectSip(true); window.addEventListener('beforeunload', handleBeforeUnload); window.addEventListener('unload', handleUnload); return () => { window.removeEventListener('beforeunload', handleBeforeUnload); window.removeEventListener('unload', handleUnload); - disconnectSip(); + disconnectSip(true); // force — component is unmounting }; }, []); // empty deps — runs once on mount, cleanup only on unmount diff --git a/src/state/sip-manager.ts b/src/state/sip-manager.ts index be2438c..0edc9eb 100644 --- a/src/state/sip-manager.ts +++ b/src/state/sip-manager.ts @@ -81,8 +81,16 @@ export function connectSip(config: SIPConfig): void { sipClient.connect(); } -export function disconnectSip(): void { - console.log('[SIP-MGR] Disconnecting SIP'); +export function disconnectSip(force = false): void { + // Guard: don't disconnect SIP during an active or pending call + // unless explicitly forced (e.g., logout, page unload). + // This prevents React re-render cycles from killing the + // SIP WebSocket mid-dial. + if (!force && (outboundPending || outboundActive)) { + console.log('[SIP-MGR] Disconnect blocked — call in progress'); + return; + } + console.log('[SIP-MGR] Disconnecting SIP' + (force ? ' (forced)' : '')); sipClient?.disconnect(); sipClient = null; connected = false;