mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
fix: prevent StrictMode double-mount from killing SIP WebSocket connection
This commit is contained in:
@@ -71,6 +71,11 @@ export const useSipPhone = (config?: Partial<SIPConfig>) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't reconnect if already connected or connecting
|
||||||
|
if (sipClientRef.current?.isConnected() || sipClientRef.current?.isRegistered()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sipClientRef.current) {
|
if (sipClientRef.current) {
|
||||||
sipClientRef.current.disconnect();
|
sipClientRef.current.disconnect();
|
||||||
}
|
}
|
||||||
@@ -127,11 +132,15 @@ export const useSipPhone = (config?: Partial<SIPConfig>) => {
|
|||||||
setIsOnHold(!isOnHold);
|
setIsOnHold(!isOnHold);
|
||||||
}, [isOnHold]);
|
}, [isOnHold]);
|
||||||
|
|
||||||
// Cleanup on unmount
|
// Cleanup only on actual page unload, not StrictMode remount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
const handleUnload = () => {
|
||||||
sipClientRef.current?.disconnect();
|
sipClientRef.current?.disconnect();
|
||||||
};
|
};
|
||||||
|
window.addEventListener('beforeunload', handleUnload);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('beforeunload', handleUnload);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -15,15 +15,26 @@ export class SIPClient {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
connect(): void {
|
connect(): void {
|
||||||
|
// Enable JsSIP debug logging to diagnose connection issues
|
||||||
|
JsSIP.debug.enable('JsSIP:*');
|
||||||
|
|
||||||
const socket = new JsSIP.WebSocketInterface(this.config.wsServer);
|
const socket = new JsSIP.WebSocketInterface(this.config.wsServer);
|
||||||
|
|
||||||
|
// Extract SIP ID from URI for authorization_user
|
||||||
|
// URI format: sip:521814@blr-pub-rtc4.ozonetel.com
|
||||||
|
const sipId = this.config.uri.replace('sip:', '').split('@')[0];
|
||||||
|
|
||||||
const configuration: UAConfiguration = {
|
const configuration: UAConfiguration = {
|
||||||
sockets: [socket],
|
sockets: [socket],
|
||||||
uri: this.config.uri,
|
uri: this.config.uri,
|
||||||
password: this.config.password,
|
password: this.config.password,
|
||||||
|
authorization_user: sipId,
|
||||||
display_name: this.config.displayName,
|
display_name: this.config.displayName,
|
||||||
register: true,
|
register: true,
|
||||||
register_expires: 120,
|
register_expires: 120,
|
||||||
|
session_timers: false,
|
||||||
|
connection_recovery_min_interval: 2,
|
||||||
|
connection_recovery_max_interval: 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.ua = new JsSIP.UA(configuration);
|
this.ua = new JsSIP.UA(configuration);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createContext, useContext, useEffect, type PropsWithChildren } from 'react';
|
import { createContext, useContext, useEffect, useRef, type PropsWithChildren } from 'react';
|
||||||
import { useSipPhone } from '@/hooks/use-sip-phone';
|
import { useSipPhone } from '@/hooks/use-sip-phone';
|
||||||
|
|
||||||
type SipContextType = ReturnType<typeof useSipPhone>;
|
type SipContextType = ReturnType<typeof useSipPhone>;
|
||||||
@@ -7,10 +7,15 @@ const SipContext = createContext<SipContextType | null>(null);
|
|||||||
|
|
||||||
export const SipProvider = ({ children }: PropsWithChildren) => {
|
export const SipProvider = ({ children }: PropsWithChildren) => {
|
||||||
const sipPhone = useSipPhone();
|
const sipPhone = useSipPhone();
|
||||||
|
const hasConnected = useRef(false);
|
||||||
|
|
||||||
// Auto-connect on mount
|
// Auto-connect on mount — skip StrictMode double-fire
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!hasConnected.current) {
|
||||||
|
hasConnected.current = true;
|
||||||
sipPhone.connect();
|
sipPhone.connect();
|
||||||
|
}
|
||||||
|
// Do NOT disconnect on cleanup — the SIP connection should persist
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user