diff --git a/client/lib/voip/QueueAggregator.ts b/client/lib/voip/QueueAggregator.ts index e0facda36b1..676517eb1f8 100644 --- a/client/lib/voip/QueueAggregator.ts +++ b/client/lib/voip/QueueAggregator.ts @@ -28,7 +28,7 @@ export class QueueAggregator { // Maintains the history of the queue that the agent has served private sessionQueueCallServingHistory: IQueueServingRecord[]; - private currentlyServing: IQueueServingRecord | undefined; + private currentlyServing: IQueueServingRecord; private currentQueueMembershipStatus: Record; @@ -97,17 +97,24 @@ export class QueueAggregator { return totalCallWaitingCount; } - callRinging(queueInfo: { queuename: string; callerId: { id: string; name: string } }): void { + getCurrentQueueName(): string { + if (this.currentlyServing.queueInfo) { + return this.currentlyServing.queueInfo.queueName; + } + + return ''; + } + + callRinging(queueInfo: { queuename: string; callerid: { id: string; name: string } }): void { if (!this.currentQueueMembershipStatus[queueInfo.queuename]) { - // something is wrong. Queue is not found in the membership details. return; } const queueServing: IQueueServingRecord = { queueInfo: this.currentQueueMembershipStatus[queueInfo.queuename], callerId: { - callerId: queueInfo.callerId.id, - callerName: queueInfo.callerId.name, + callerId: queueInfo.callerid.id, + callerName: queueInfo.callerid.name, }, callStarted: undefined, callEnded: undefined, diff --git a/client/lib/voip/VoIPUser.ts b/client/lib/voip/VoIPUser.ts index 673b09f6191..dcc2c9b41ba 100644 --- a/client/lib/voip/VoIPUser.ts +++ b/client/lib/voip/VoIPUser.ts @@ -64,7 +64,7 @@ export class VoIPUser extends Emitter implements OutgoingRequestDele private mode: WorkflowTypes; - private queueInfo?: QueueAggregator; + private queueInfo: QueueAggregator; get callState(): CallStates { return this._callState; @@ -649,7 +649,7 @@ export class VoIPUser extends Emitter implements OutgoingRequestDele this.queueInfo?.setMembership(subscription); } - getAggregator(): QueueAggregator | undefined { + getAggregator(): QueueAggregator { return this.queueInfo; } diff --git a/client/providers/CallProvider/CallProvider.tsx b/client/providers/CallProvider/CallProvider.tsx index 84f5667749e..d597abec328 100644 --- a/client/providers/CallProvider/CallProvider.tsx +++ b/client/providers/CallProvider/CallProvider.tsx @@ -16,7 +16,8 @@ import { useEndpoint, useStream } from '../../contexts/ServerContext'; import { useSetting } from '../../contexts/SettingsContext'; import { useUser } from '../../contexts/UserContext'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; -import { isUseVoipClientResultError, isUseVoipClientResultLoading, useVoipClient } from './hooks/useVoipClient'; +import { QueueAggregator } from '../../lib/voip/QueueAggregator'; +import { useVoipClient } from './hooks/useVoipClient'; const startRingback = (user: IUser): void => { const audioVolume = getUserPreference(user, 'notificationsSoundVolume'); @@ -44,8 +45,8 @@ export const CallProvider: FC = ({ children }) => { const AudioTagPortal: FC = ({ children }) => useMemo(() => createPortal(children, document.body), [children]); - const [queueName, setQueueName] = useState(''); const [queueCounter, setQueueCounter] = useState(0); + const [queueName, setQueueName] = useState(''); const setModal = useSetModal(); @@ -53,17 +54,35 @@ export const CallProvider: FC = ({ children }) => { setModal(); }, [setModal]); + const [queueAggregator, setQueueAggregator] = useState(); + useEffect(() => { - if (!voipEnabled || !user) { + if (!result?.voipClient) { return; } - if (isUseVoipClientResultError(result) || isUseVoipClientResultLoading(result)) { + setQueueAggregator(result.voipClient.getAggregator()); + }, [result]); + + useEffect(() => { + if (!voipEnabled || !user || !queueAggregator) { return; } - const queueAggregator = result.voipClient.getAggregator(); - if (!queueAggregator) { + const handleAgentCalled = async (queue: { + queuename: string; + callerId: { id: string; name: string }; + queuedcalls: string; + }): Promise => { + queueAggregator.callRinging({ queuename: queue.queuename, callerid: queue.callerId }); + setQueueName(queueAggregator.getCurrentQueueName()); + }; + + return subscribeToNotifyUser(`${user._id}/agentcalled`, handleAgentCalled); + }, [subscribeToNotifyUser, user, voipEnabled, queueAggregator]); + + useEffect(() => { + if (!voipEnabled || !user || !queueAggregator) { return; } @@ -73,69 +92,42 @@ export const CallProvider: FC = ({ children }) => { queuedcalls: string; }): Promise => { queueAggregator.queueJoined(joiningDetails); - setQueueName(joiningDetails.queuename); setQueueCounter(queueAggregator.getCallWaitingCount()); }; return subscribeToNotifyUser(`${user._id}/callerjoined`, handleQueueJoined); - }, [result, subscribeToNotifyUser, user, voipEnabled]); + }, [subscribeToNotifyUser, user, voipEnabled, queueAggregator]); useEffect(() => { - if (!voipEnabled || !user) { - return; - } - - if (isUseVoipClientResultError(result) || isUseVoipClientResultLoading(result)) { - return; - } - - const queueAggregator = result.voipClient.getAggregator(); - if (!queueAggregator) { + if (!voipEnabled || !user || !queueAggregator) { return; } const handleAgentConnected = (queue: { queuename: string; queuedcalls: string; waittimeinqueue: string }): void => { queueAggregator.callPickedup(queue); + setQueueName(queueAggregator.getCurrentQueueName()); setQueueCounter(queueAggregator.getCallWaitingCount()); }; return subscribeToNotifyUser(`${user._id}/agentconnected`, handleAgentConnected); - }, [result, subscribeToNotifyUser, user, voipEnabled]); + }, [queueAggregator, subscribeToNotifyUser, user, voipEnabled]); useEffect(() => { - if (!voipEnabled || !user) { - return; - } - - if (isUseVoipClientResultError(result) || isUseVoipClientResultLoading(result)) { - return; - } - - const queueAggregator = result.voipClient.getAggregator(); - if (!queueAggregator) { + if (!voipEnabled || !user || !queueAggregator) { return; } const handleMemberAdded = (queue: { queuename: string; queuedcalls: string }): void => { queueAggregator.memberAdded(queue); - setQueueName(queue.queuename); + setQueueName(queueAggregator.getCurrentQueueName()); setQueueCounter(queueAggregator.getCallWaitingCount()); }; return subscribeToNotifyUser(`${user._id}/queuememberadded`, handleMemberAdded); - }, [result, subscribeToNotifyUser, user, voipEnabled]); + }, [queueAggregator, subscribeToNotifyUser, user, voipEnabled]); useEffect(() => { - if (!voipEnabled || !user) { - return; - } - - if (isUseVoipClientResultError(result) || isUseVoipClientResultLoading(result)) { - return; - } - - const queueAggregator = result.voipClient.getAggregator(); - if (!queueAggregator) { + if (!voipEnabled || !user || !queueAggregator) { return; } @@ -145,48 +137,37 @@ export const CallProvider: FC = ({ children }) => { }; return subscribeToNotifyUser(`${user._id}/queuememberremoved`, handleMemberRemoved); - }, [result, subscribeToNotifyUser, user, voipEnabled]); + }, [queueAggregator, subscribeToNotifyUser, user, voipEnabled]); useEffect(() => { - if (!voipEnabled || !user) { - return; - } - - if (isUseVoipClientResultError(result) || isUseVoipClientResultLoading(result)) { - return; - } - - const queueAggregator = result.voipClient.getAggregator(); - if (!queueAggregator) { + if (!voipEnabled || !user || !queueAggregator) { return; } const handleCallAbandon = (queue: { queuename: string; queuedcallafterabandon: string }): void => { queueAggregator.queueAbandoned(queue); + setQueueName(queueAggregator.getCurrentQueueName()); setQueueCounter(queueAggregator.getCallWaitingCount()); }; return subscribeToNotifyUser(`${user._id}/callabandoned`, handleCallAbandon); - }, [result, subscribeToNotifyUser, user, voipEnabled]); + }, [queueAggregator, subscribeToNotifyUser, user, voipEnabled]); useEffect(() => { - if (!voipEnabled || !user) { + if (!voipEnabled || !user || !queueAggregator) { return; } const handleCallHangup = (_event: { roomId: string }): void => { + setQueueName(queueAggregator.getCurrentQueueName()); openWrapUpModal(); }; return subscribeToNotifyUser(`${user._id}/call.callerhangup`, handleCallHangup); - }, [openWrapUpModal, result, subscribeToNotifyUser, user, voipEnabled]); + }, [openWrapUpModal, queueAggregator, subscribeToNotifyUser, user, voipEnabled]); useEffect(() => { - if (isUseVoipClientResultError(result)) { - return; - } - - if (isUseVoipClientResultLoading(result)) { + if (!result.voipClient) { return; } @@ -256,7 +237,7 @@ export const CallProvider: FC = ({ children }) => { }; } - if (isUseVoipClientResultError(result)) { + if (result.error) { return { enabled: true, ready: false, @@ -264,7 +245,7 @@ export const CallProvider: FC = ({ children }) => { }; } - if (isUseVoipClientResultLoading(result)) { + if (!result.voipClient) { return { enabled: true, ready: false, @@ -281,8 +262,8 @@ export const CallProvider: FC = ({ children }) => { enabled: true, ready: true, openedRoomInfo: roomInfo, - registrationInfo, voipClient, + registrationInfo, queueCounter, queueName, actions: { @@ -308,7 +289,7 @@ export const CallProvider: FC = ({ children }) => { const voipRoom = visitor && (await voipEndpoint({ token: visitor.token, agentId: user._id })); openRoom(voipRoom.room._id); voipRoom.room && setRoomInfo({ v: { token: voipRoom.room.v.token }, rid: voipRoom.room._id }); - const queueAggregator = result.voipClient.getAggregator(); + const queueAggregator = voipClient.getAggregator(); if (queueAggregator) { queueAggregator.callStarted(); } @@ -319,7 +300,7 @@ export const CallProvider: FC = ({ children }) => { closeRoom: async ({ comment, tags }: { comment: string; tags: string[] }): Promise => { roomInfo && (await voipCloseRoomEndpoint({ rid: roomInfo.rid, token: roomInfo.v.token || '', comment: comment || '', tags })); homeRoute.push({}); - const queueAggregator = result.voipClient.getAggregator(); + const queueAggregator = voipClient.getAggregator(); if (queueAggregator) { queueAggregator.callEnded(); } @@ -328,12 +309,12 @@ export const CallProvider: FC = ({ children }) => { }; }, [ voipEnabled, + user, result, roomInfo, queueCounter, queueName, openWrapUpModal, - user, visitorEndpoint, voipEndpoint, voipCloseRoomEndpoint, diff --git a/client/providers/CallProvider/hooks/useVoipClient.ts b/client/providers/CallProvider/hooks/useVoipClient.ts index 09b7e1e4633..3dd5df96263 100644 --- a/client/providers/CallProvider/hooks/useVoipClient.ts +++ b/client/providers/CallProvider/hooks/useVoipClient.ts @@ -11,20 +11,11 @@ import { SimpleVoipUser } from '../../../lib/voip/SimpleVoipUser'; import { VoIPUser } from '../../../lib/voip/VoIPUser'; import { useWebRtcServers } from './useWebRtcServers'; -type UseVoipClientResult = UseVoipClientResultResolved | UseVoipClientResultError | UseVoipClientResultLoading; - -type UseVoipClientResultResolved = { - voipClient: VoIPUser; - registrationInfo: IRegistrationInfo; +type UseVoipClientResult = { + voipClient?: VoIPUser; + registrationInfo?: IRegistrationInfo; + error?: Error | unknown; }; -type UseVoipClientResultError = { error: Error }; -type UseVoipClientResultLoading = Record; - -export const isUseVoipClientResultError = (result: UseVoipClientResult): result is UseVoipClientResultError => - !!(result as UseVoipClientResultError).error; - -export const isUseVoipClientResultLoading = (result: UseVoipClientResult): result is UseVoipClientResultLoading => - !result || !Object.keys(result).length; const isSignedResponse = (data: any): data is { result: string } => typeof data?.result === 'string'; @@ -70,13 +61,13 @@ export const useVoipClient = (): UseVoipClientResult => { client.setWorkflowMode(WorkflowTypes.CONTACT_CENTER_USER); client.setMembershipSubscription(subscription); setResult({ voipClient: client, registrationInfo: parsedData }); - } catch (e) { - setResult({ error: e as Error }); + } catch (error) { + setResult({ error }); } })(); }, - (error) => { - setResult({ error: error as Error }); + (error: Error) => { + setResult({ error }); }, ); return (): void => { diff --git a/client/sidebar/footer/voip/index.tsx b/client/sidebar/footer/voip/index.tsx index bc6a6fb3e20..e7ccd217afd 100644 --- a/client/sidebar/footer/voip/index.tsx +++ b/client/sidebar/footer/voip/index.tsx @@ -52,7 +52,7 @@ export const VoipFooter = (): ReactElement | null => { case 'IN_CALL': return t('In_progress'); case 'OFFER_RECEIVED': - return t('Calling'); + return t('Ringing'); case 'ON_HOLD': return t('On_Hold'); } diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 9ff0e01cfc6..29a885baf58 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -714,9 +714,9 @@ "Call": "Call", "Calling": "Calling", "Call_Center": "Call Center", - "Calls_in_queue": "__calls__ Call In Queue", - "Calls_in_queue_plural": "__calls__ Calls In Queue", - "Calls_in_queue_empty": "Queue Is Empty", + "Calls_in_queue": "__calls__ call in queue", + "Calls_in_queue_plural": "__calls__ calls in queue", + "Calls_in_queue_empty": "Queue is empty", "Call_declined": "Call Declined!", "Call_Information": "Call Information", "Call_provider": "Call Provider", @@ -3270,7 +3270,7 @@ "Omnichannel_External_Frame_Encryption_JWK_Description": "If provided it will encrypt the user's token with the provided key and the external system will need to decrypt the data to access the token", "Omnichannel_External_Frame_URL": "External frame URL", "On": "On", - "On_Hold": "On Hold", + "On_Hold": "On hold", "On_Hold_Chats": "On Hold", "On_Hold_conversations": "On hold conversations", "online": "online", @@ -3663,6 +3663,7 @@ "Return_to_home": "Return to home", "Return_to_previous_page": "Return to previous page", "Return_to_the_queue": "Return back to the Queue", + "Ringing": "Ringing", "Robot_Instructions_File_Content": "Robots.txt File Contents", "Default_Referrer_Policy": "Default Referrer Policy", "Default_Referrer_Policy_Description": "This controls the 'referrer' header that's sent when requesting embedded media from other servers. For more information, refer to this link from MDN. Remember, a full page refresh is required for this to take effect",