chore(voice): split FE changes out to feat/whatsapp-call-ui (PR #14346)

This commit is contained in:
Tanmay Deep Sharma
2026-05-02 14:31:13 +07:00
parent d9077c64d3
commit 0e0e0868d7
15 changed files with 155 additions and 845 deletions
@@ -1,19 +1,14 @@
import { computed, ref, watch, onUnmounted, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import VoiceAPI from 'dashboard/api/channel/voice/voiceAPIClient';
import TwilioVoiceClient from 'dashboard/api/channel/voice/twilioVoiceClient';
import { useCallsStore } from 'dashboard/stores/calls';
import {
useWhatsappCallSession,
sendWhatsappTerminateBeacon,
cleanupWhatsappSession,
} from 'dashboard/composables/useWhatsappCallSession';
import { useAlert } from 'dashboard/composables';
import Timer from 'dashboard/helper/Timer';
const isWhatsappCall = call => call?.provider === 'whatsapp';
export function useCallSession() {
const callsStore = useCallsStore();
const whatsappSession = useWhatsappCallSession();
const { t } = useI18n();
const isJoining = ref(false);
const callDuration = ref(0);
const durationTimer = new Timer(elapsed => {
@@ -37,52 +32,20 @@ export function useCallSession() {
{ immediate: true }
);
// Browser-native confirm prompt when reload/close happens mid-call. Reload
// tears down the WebRTC session permanently for WhatsApp (no rejoin) and
// drops the agent leg for Twilio, so warn either way.
const handleBeforeUnload = event => {
if (!hasActiveCall.value) return;
event.preventDefault();
event.returnValue = '';
};
// pagehide fires after the user confirms the prompt. Let the WhatsApp session
// best-effort sendBeacon a terminate so the server doesn't keep the call open.
const handlePageHide = () => {
sendWhatsappTerminateBeacon();
};
const handleTwilioDisconnected = () => callsStore.clearActiveCall();
onMounted(() => {
TwilioVoiceClient.addEventListener(
'call:disconnected',
handleTwilioDisconnected
TwilioVoiceClient.addEventListener('call:disconnected', () =>
callsStore.clearActiveCall()
);
window.addEventListener('beforeunload', handleBeforeUnload);
window.addEventListener('pagehide', handlePageHide);
});
onUnmounted(() => {
durationTimer.stop();
TwilioVoiceClient.removeEventListener(
'call:disconnected',
handleTwilioDisconnected
TwilioVoiceClient.removeEventListener('call:disconnected', () =>
callsStore.clearActiveCall()
);
window.removeEventListener('beforeunload', handleBeforeUnload);
window.removeEventListener('pagehide', handlePageHide);
});
const findCall = callSid => callsStore.calls.find(c => c.callSid === callSid);
const endCall = async ({ conversationId, inboxId, callSid }) => {
if (isWhatsappCall(findCall(callSid))) {
await whatsappSession.endActiveCall();
durationTimer.stop();
callsStore.clearActiveCall();
return;
}
await VoiceAPI.leaveConference({ inboxId, conversationId, callSid });
TwilioVoiceClient.endClientCall();
durationTimer.stop();
@@ -94,18 +57,6 @@ export function useCallSession() {
isJoining.value = true;
try {
const call = findCall(callSid);
if (isWhatsappCall(call)) {
await whatsappSession.acceptIncomingCall({
callId: call.callId,
sdpOffer: call.sdpOffer,
iceServers: call.iceServers,
});
callsStore.setCallActive(callSid);
durationTimer.start();
return { callId: call.callId };
}
const device = await TwilioVoiceClient.initializeDevice(inboxId);
if (!device) return null;
@@ -126,12 +77,13 @@ export function useCallSession() {
return { conferenceSid: joinResponse?.conference_sid };
} catch (error) {
useAlert(error?.response?.data?.error || t('CONTACT_PANEL.CALL_FAILED'));
if (error?.response?.status === 409) {
TwilioVoiceClient.endClientCall();
callsStore.dismissCall(callSid);
}
// eslint-disable-next-line no-console
console.error('Failed to join call:', error);
// Tear down any half-built WebRTC state so the user's next click starts
// fresh; otherwise the leftover pc + mic stream survives and confuses
// the second-attempt SDP exchange.
cleanupWhatsappSession();
return null;
} finally {
isJoining.value = false;
@@ -139,12 +91,7 @@ export function useCallSession() {
};
const rejectIncomingCall = callSid => {
const call = findCall(callSid);
if (isWhatsappCall(call) && call?.callId) {
whatsappSession.rejectIncomingCall(call.callId);
} else {
TwilioVoiceClient.endClientCall();
}
TwilioVoiceClient.endClientCall();
callsStore.dismissCall(callSid);
};