diff --git a/apps/meteor/client/contexts/VoipAgentContext.ts b/apps/meteor/client/contexts/VoIPAgentContext.ts similarity index 86% rename from apps/meteor/client/contexts/VoipAgentContext.ts rename to apps/meteor/client/contexts/VoIPAgentContext.ts index 374c07d83e2d..ef27a32e09c3 100644 --- a/apps/meteor/client/contexts/VoipAgentContext.ts +++ b/apps/meteor/client/contexts/VoIPAgentContext.ts @@ -1,6 +1,6 @@ import { createContext, Dispatch, SetStateAction } from 'react'; -export type VoipAgentContextValue = { +export type VoIPAgentContextValue = { agentEnabled: boolean; registered: boolean; networkStatus: 'online' | 'offline'; @@ -11,7 +11,7 @@ export type VoipAgentContextValue = { setVoipButtonEnabled: Dispatch>; }; -export const VoipAgentContext = createContext({ +export const VoIPAgentContext = createContext({ agentEnabled: false, registered: false, networkStatus: 'offline', diff --git a/apps/meteor/client/lib/voip/VoIPUser.ts b/apps/meteor/client/lib/voip/VoIPUser.ts index 7b5708b895aa..b9e4a1850db9 100644 --- a/apps/meteor/client/lib/voip/VoIPUser.ts +++ b/apps/meteor/client/lib/voip/VoIPUser.ts @@ -750,7 +750,7 @@ export class VoIPUser extends Emitter { return this.queueInfo; } - getRegisterState(): string | undefined { + getRegistrarState(): string | undefined { return this.registerer?.state.toString().toLocaleLowerCase(); } diff --git a/apps/meteor/client/providers/CallProvider/CallProvider.tsx b/apps/meteor/client/providers/CallProvider/CallProvider.tsx index 76bbd8c96c0e..daa1f9d496c5 100644 --- a/apps/meteor/client/providers/CallProvider/CallProvider.tsx +++ b/apps/meteor/client/providers/CallProvider/CallProvider.tsx @@ -24,7 +24,7 @@ import { WrapUpCallModal } from '../../components/voip/modal/WrapUpCallModal'; import { CallContext, CallContextValue } from '../../contexts/CallContext'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; import { QueueAggregator } from '../../lib/voip/QueueAggregator'; -import VoipAgentProvider from '../VoipAgentProvider'; +import VoIPAgentProvider from '../VoIPAgentProvider'; import { useVoipClient } from './hooks/useVoipClient'; const startRingback = (user: IUser): void => { @@ -343,10 +343,17 @@ export const CallProvider: FC = ({ children }) => { return ( - - {children} - {contextValue.enabled && createPortal( + {voipEnabled ? ( + + {children} + {contextValue.enabled && createPortal( + ) : ( + <> + {children} + {contextValue.enabled && createPortal( ); }; diff --git a/apps/meteor/client/providers/MeteorProvider.tsx b/apps/meteor/client/providers/MeteorProvider.tsx index ef0e5885cf7c..56273b2f854a 100644 --- a/apps/meteor/client/providers/MeteorProvider.tsx +++ b/apps/meteor/client/providers/MeteorProvider.tsx @@ -31,15 +31,15 @@ const MeteorProvider: FC = ({ children }) => ( - - + + {children} - - + + diff --git a/apps/meteor/client/providers/VoIPAgentProvider.tsx b/apps/meteor/client/providers/VoIPAgentProvider.tsx new file mode 100644 index 000000000000..79f45cf32dfd --- /dev/null +++ b/apps/meteor/client/providers/VoIPAgentProvider.tsx @@ -0,0 +1,102 @@ +import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; + +import { useCallActions, useCallClient } from '../contexts/CallContext'; +import { VoIPAgentContext } from '../contexts/VoIPAgentContext'; + +const VoIPAgentProvider: FC = ({ children }) => { + const [agentEnabled, setAgentEnabled] = useState(false); + const [registered, setRegistered] = useState(false); + const [networkStatus, setNetworkStatus] = useState<'online' | 'offline'>('online'); + const [voipButtonEnabled, setVoipButtonEnabled] = useState(false); + const callActions = useCallActions(); + + const voipClient = useCallClient(); + const registerState = useMemo(() => voipClient.getRegistrarState(), [voipClient]); + + const toggleRegistered = useCallback((): void => { + setRegistered((registered) => !registered); + }, []); + + const toggleRegistrationError = useCallback((): void => { + setRegistered(false); + setAgentEnabled(false); + }, []); + + const onNetworkConnected = useCallback((): void => { + setVoipButtonEnabled(['IN_CALL', 'ON_HOLD'].includes(voipClient.callerInfo.state)); + setNetworkStatus('online'); + }, [setNetworkStatus, setVoipButtonEnabled, voipClient.callerInfo.state]); + + const onNetworkDisconnected = useCallback((): void => { + setVoipButtonEnabled(true); + setNetworkStatus('offline'); + }, [setNetworkStatus, setVoipButtonEnabled]); + + useEffect(() => { + if (!agentEnabled) { + return; + } + + voipClient.register(); + + return (): void => voipClient.unregister(); + }, [agentEnabled, voipClient]); + + useEffect(() => { + setVoipButtonEnabled(['IN_CALL', 'ON_HOLD'].includes(voipClient.callerInfo.state)); + }, [setVoipButtonEnabled, voipClient.callerInfo.state]); + + useEffect(() => { + setRegistered(registerState === 'registered'); + }, [registerState]); + + useEffect(() => { + if (voipButtonEnabled) { + return; + } + + voipClient.callerInfo.state === 'OFFER_RECEIVED' && callActions.reject(); + }, [callActions, voipButtonEnabled, voipClient.callerInfo.state]); + + useEffect(() => { + voipClient.on('registered', toggleRegistered); + voipClient.on('unregistered', toggleRegistered); + voipClient.on('registrationerror', toggleRegistrationError); + voipClient.on('unregistrationerror', toggleRegistrationError); + voipClient.onNetworkEvent('connected', onNetworkConnected); + voipClient.onNetworkEvent('disconnected', onNetworkDisconnected); + voipClient.onNetworkEvent('connectionerror', onNetworkDisconnected); + voipClient.onNetworkEvent('localnetworkonline', onNetworkConnected); + voipClient.onNetworkEvent('localnetworkoffline', onNetworkDisconnected); + + return (): void => { + voipClient.off('registered', toggleRegistered); + voipClient.off('unregistered', toggleRegistered); + voipClient.off('registrationerror', toggleRegistrationError); + voipClient.off('unregistrationerror', toggleRegistrationError); + voipClient.offNetworkEvent('connected', onNetworkConnected); + voipClient.offNetworkEvent('disconnected', onNetworkDisconnected); + voipClient.offNetworkEvent('connectionerror', onNetworkDisconnected); + voipClient.offNetworkEvent('localnetworkonline', onNetworkConnected); + voipClient.offNetworkEvent('localnetworkoffline', onNetworkDisconnected); + }; + }, [voipClient, onNetworkConnected, onNetworkDisconnected, toggleRegistered, toggleRegistrationError]); + + return ( + + ); +}; + +export default VoIPAgentProvider; diff --git a/apps/meteor/client/providers/VoipAgentProvider.tsx b/apps/meteor/client/providers/VoipAgentProvider.tsx deleted file mode 100644 index 67cc816255b8..000000000000 --- a/apps/meteor/client/providers/VoipAgentProvider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { FC, useState } from 'react'; - -import { VoipAgentContext } from '../contexts/VoipAgentContext'; - -const VoipAgentProvider: FC = ({ children }) => { - const [agentEnabled, setAgentEnabled] = useState(false); - const [registered, setRegistered] = useState(false); - const [networkStatus, setNetworkStatus] = useState<'online' | 'offline'>('online'); - const [voipButtonEnabled, setVoipButtonEnabled] = useState(false); - - return ( - - ); -}; - -export default VoipAgentProvider; diff --git a/apps/meteor/client/sidebar/sections/components/OmnichannelCallToggleReady.tsx b/apps/meteor/client/sidebar/sections/components/OmnichannelCallToggleReady.tsx index 4f28e126b42c..08b917ea58e2 100644 --- a/apps/meteor/client/sidebar/sections/components/OmnichannelCallToggleReady.tsx +++ b/apps/meteor/client/sidebar/sections/components/OmnichannelCallToggleReady.tsx @@ -1,99 +1,21 @@ import { Sidebar } from '@rocket.chat/fuselage'; -import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; -import React, { ReactElement, useCallback, useEffect, useMemo } from 'react'; +import React, { ReactElement, useCallback } from 'react'; -import { useCallActions, useCallClient } from '../../../contexts/CallContext'; +// import { useCallActions, useCallClient } from '../../../contexts/CallContext'; import { useVoipAgent } from '../hooks/useVoipAgent'; export const OmnichannelCallToggleReady = (): ReactElement => { const t = useTranslation(); - const { - agentEnabled, - networkStatus, - registered, - voipButtonEnabled, - setAgentEnabled, - setRegistered, - setNetworkStatus, - setVoipButtonEnabled, - } = useVoipAgent(); - const voipClient = useCallClient(); - const callActions = useCallActions(); - - const registerState = useMemo(() => voipClient.getRegisterState(), [voipClient]); - - const toogleRegistered = useMutableCallback((): void => { - setRegistered(!registered); - }); - - const toogleRegistrationError = useCallback((): void => { - setRegistered(false); - setAgentEnabled(false); - }, [setAgentEnabled, setRegistered]); - - const onNetworkConnected = useCallback((): void => { - setVoipButtonEnabled(['IN_CALL', 'ON_HOLD'].includes(voipClient.callerInfo.state)); - setNetworkStatus('online'); - }, [setNetworkStatus, setVoipButtonEnabled, voipClient.callerInfo.state]); - - const onNetworkDisconnected = useCallback((): void => { - setVoipButtonEnabled(true); - setNetworkStatus('offline'); - }, [setNetworkStatus, setVoipButtonEnabled]); - + const { agentEnabled, networkStatus, registered, voipButtonEnabled, setAgentEnabled } = useVoipAgent(); const onClickVoipButton = useCallback((): void => { if (voipButtonEnabled) { return; } setAgentEnabled(!agentEnabled); - - voipClient.callerInfo.state === 'OFFER_RECEIVED' && callActions.reject(); - }, [agentEnabled, callActions, setAgentEnabled, voipButtonEnabled, voipClient.callerInfo.state]); - - useEffect(() => { - if (!agentEnabled) { - return; - } - - voipClient.register(); - - return (): void => voipClient.unregister(); - }, [agentEnabled, voipClient]); - - useEffect(() => { - setVoipButtonEnabled(['IN_CALL', 'ON_HOLD'].includes(voipClient.callerInfo.state)); - }, [setVoipButtonEnabled, voipClient.callerInfo.state]); - - useEffect(() => { - setRegistered(registerState === 'registered'); - }, [registerState, setRegistered]); - - useEffect(() => { - voipClient.on('registered', toogleRegistered); - voipClient.on('unregistered', toogleRegistered); - voipClient.on('registrationerror', toogleRegistrationError); - voipClient.on('unregistrationerror', toogleRegistrationError); - voipClient.onNetworkEvent('connected', onNetworkConnected); - voipClient.onNetworkEvent('disconnected', onNetworkDisconnected); - voipClient.onNetworkEvent('connectionerror', onNetworkDisconnected); - voipClient.onNetworkEvent('localnetworkonline', onNetworkConnected); - voipClient.onNetworkEvent('localnetworkoffline', onNetworkDisconnected); - - return (): void => { - voipClient.off('registered', toogleRegistered); - voipClient.off('unregistered', toogleRegistered); - voipClient.off('registrationerror', toogleRegistrationError); - voipClient.off('unregistrationerror', toogleRegistrationError); - voipClient.offNetworkEvent('connected', onNetworkConnected); - voipClient.offNetworkEvent('disconnected', onNetworkDisconnected); - voipClient.offNetworkEvent('connectionerror', onNetworkDisconnected); - voipClient.offNetworkEvent('localnetworkonline', onNetworkConnected); - voipClient.offNetworkEvent('localnetworkoffline', onNetworkDisconnected); - }; - }, [voipClient, onNetworkConnected, onNetworkDisconnected, toogleRegistered, toogleRegistrationError]); + }, [agentEnabled, setAgentEnabled, voipButtonEnabled]); const getTitle = (): string => { if (networkStatus === 'offline') {