Files
chatwoot/app/javascript/dashboard/composables/useVoiceCallHelpers.js
2025-05-04 06:02:51 -07:00

180 lines
5.1 KiB
JavaScript

import { computed } from 'vue';
export const useVoiceCallHelpers = (props, { t }) => {
// Check if the conversation is from a voice channel
const isVoiceChannelConversation = computed(() => {
// First check the meta.inbox.channel_type
if (props.conversation?.meta?.inbox?.channel_type === 'Channel::Voice') {
return true;
}
// Also check the inbox_id to find the channel type
// This is useful when the meta.inbox is not fully populated
if (props.conversation?.inbox_id && props.conversation?.meta?.channel_type === 'Channel::Voice') {
return true;
}
return false;
});
// Function to check if a conversation is a voice channel conversation (non-computed version)
const isConversationFromVoiceChannel = (conversation) => {
if (!conversation) return false;
// Check meta inbox channel type
if (conversation.meta?.inbox?.channel_type === 'Channel::Voice') {
return true;
}
// Check meta channel type
if (conversation.meta?.channel_type === 'Channel::Voice') {
return true;
}
return false;
};
// Helper function to find call information from various sources
const getCallData = (conversation) => {
if (!conversation) return {};
// First check for data directly in conversation attributes
const conversationAttributes = conversation.custom_attributes || conversation.additional_attributes || {};
if (conversationAttributes.call_data) {
return conversationAttributes.call_data;
}
return {};
};
// Check if a message has an arrow prefix
const hasArrow = (message) => {
if (!message?.content) return false;
return (
typeof message.content === 'string' &&
(message.content.startsWith('←') ||
message.content.startsWith('→') ||
message.content.startsWith('↔️'))
);
};
// Determine if it's an incoming call
const isIncomingCall = (callData, message) => {
if (!message) return null;
// Check for arrow in content
if (hasArrow(message)) {
return message.content.startsWith('←');
}
// Try to use the direction stored in the call data
if (callData?.call_direction) {
return callData.call_direction === 'inbound';
}
// Fall back to message_type
return message.message_type === 0;
};
// Get normalized call status from multiple sources
const normalizeCallStatus = (status, isIncoming) => {
// Map from Twilio status to our UI status
const statusMap = {
'in-progress': 'active',
'completed': 'ended',
'canceled': 'ended',
'failed': 'ended',
'busy': 'no-answer',
'no-answer': isIncoming ? 'missed' : 'no-answer',
'active': 'active',
'missed': 'missed',
'ended': 'ended',
'ringing': 'ringing'
};
return statusMap[status] || status;
};
// Get the appropriate icon for a call status
const getCallIconName = (status, isIncoming) => {
if (status === 'missed' || status === 'no-answer') {
return 'i-ph-phone-x-fill';
}
if (status === 'active') {
return 'i-ph-phone-call-fill';
}
if (status === 'ended' || status === 'completed') {
return isIncoming ? 'i-ph-phone-incoming-fill' : 'i-ph-phone-outgoing-fill';
}
// Default phone icon for ringing state
return isIncoming
? 'i-ph-phone-incoming-fill'
: 'i-ph-phone-outgoing-fill';
};
// Get the appropriate text for a call status
const getStatusText = (status, isIncoming) => {
if (status === 'active') {
return t('CONVERSATION.VOICE_CALL.CALL_IN_PROGRESS');
}
if (isIncoming) {
if (status === 'ringing') {
return t('CONVERSATION.VOICE_CALL.INCOMING_CALL');
}
if (status === 'missed') {
return t('CONVERSATION.VOICE_CALL.MISSED_CALL');
}
if (status === 'ended') {
return t('CONVERSATION.VOICE_CALL.CALL_ENDED');
}
} else {
if (status === 'ringing') {
return t('CONVERSATION.VOICE_CALL.OUTGOING_CALL');
}
if (status === 'no-answer') {
return t('CONVERSATION.VOICE_CALL.NO_ANSWER');
}
if (status === 'ended') {
return t('CONVERSATION.VOICE_CALL.CALL_ENDED');
}
}
return isIncoming
? t('CONVERSATION.VOICE_CALL.INCOMING_CALL')
: t('CONVERSATION.VOICE_CALL.OUTGOING_CALL');
};
// Process message content with arrow prefix
const processArrowContent = (content, isIncoming, normalizedStatus) => {
// Remove arrows and clean up the text
let text = content.replace(/^[←→↔️]/, '').trim();
// If it only says "Voice Call" or "jo", add more descriptive status info
if (text === 'Voice Call' || text === 'jo' || text === '') {
return getStatusText(normalizedStatus, isIncoming);
}
return text;
};
return {
isVoiceChannelConversation,
isConversationFromVoiceChannel,
getCallData,
hasArrow,
isIncomingCall,
normalizeCallStatus,
getCallIconName,
getStatusText,
processArrowContent,
};
};