From ab0370fbe11d5023462ddef9f411e9c54e59e641 Mon Sep 17 00:00:00 2001 From: Muhsin <12408980+muhsin-k@users.noreply.github.com> Date: Thu, 30 Apr 2026 18:52:48 +0400 Subject: [PATCH] refactor(voice): make the whole call bubble the join target and switch active calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The bubble itself is now the click target with an inline Join/Rejoin caption, matching the original design intent — discoverable on hover without a separate footer button. - If the agent already has a different active call, end it first so the switch is clean (mirrors FloatingCallWidget.handleJoinCall). --- .../message/bubbles/VoiceCall.vue | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/app/javascript/dashboard/components-next/message/bubbles/VoiceCall.vue b/app/javascript/dashboard/components-next/message/bubbles/VoiceCall.vue index a2b0c3792..48b1fd469 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/VoiceCall.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/VoiceCall.vue @@ -38,9 +38,10 @@ const { t } = useI18n(); const store = useStore(); const { call, conversationId, currentUserId, inboxId, sender } = useMessageContext(); -const { activeCall, isJoining, joinCall } = useCallSession({ - manageSessionState: false, -}); +const { activeCall, hasActiveCall, isJoining, joinCall, endCall } = + useCallSession({ + manageSessionState: false, + }); const status = computed(() => call.value?.status); const isOutbound = computed(() => call.value?.direction === 'outgoing'); @@ -153,8 +154,23 @@ const joinLabel = computed(() => : t('CONVERSATION.VOICE_CALL.JOIN_CALL') ); +const activeConversation = computed(() => { + const id = activeCall.value?.conversationId; + return id ? store.getters.getConversationById?.(id) : null; +}); + const handleJoinClick = async () => { if (!canJoin.value || isJoining.value) return; + if (hasActiveCall.value && activeCall.value?.callSid !== callSid.value) { + const activeInboxId = activeConversation.value?.inbox_id; + if (activeCall.value?.conversationId && activeInboxId) { + await endCall({ + conversationId: activeCall.value.conversationId, + inboxId: activeInboxId, + callSid: activeCall.value.callSid, + }); + } + } await joinCall({ conversationId: conversationId.value, inboxId: resolvedInboxId.value, @@ -165,7 +181,18 @@ const handleJoinClick = async () => {