177 lines
5.4 KiB
JavaScript
177 lines
5.4 KiB
JavaScript
const state = {
|
|
activeCall: null,
|
|
incomingCall: null,
|
|
};
|
|
|
|
const getters = {
|
|
getActiveCall: $state => $state.activeCall,
|
|
hasActiveCall: $state => !!$state.activeCall,
|
|
getIncomingCall: $state => $state.incomingCall,
|
|
hasIncomingCall: $state => !!$state.incomingCall,
|
|
};
|
|
|
|
const actions = {
|
|
// This action will handle both message updates and direct call status changes
|
|
/**
|
|
* Handles all call status changes from ActionCable.
|
|
* Closes the widget and clears state for terminal statuses.
|
|
* Only this action should manipulate widget visibility for call end.
|
|
*/
|
|
handleCallStatusChanged({ state, dispatch }, { callSid, status }) {
|
|
// Debug logging for conference call widget close issue
|
|
// eslint-disable-next-line no-console
|
|
console.log('[CALL DEBUG] handleCallStatusChanged invoked', { callSid, status, activeCall: state.activeCall });
|
|
const isActiveCall = callSid === state.activeCall?.callSid;
|
|
const terminalStatuses = [
|
|
'ended',
|
|
'missed',
|
|
'completed',
|
|
'failed',
|
|
'busy',
|
|
'no_answer',
|
|
];
|
|
if (isActiveCall && terminalStatuses.includes(status)) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[CALL DEBUG] Terminal status match. Closing widget.', { callSid, status, activeCall: state.activeCall });
|
|
// Clean up active call state
|
|
dispatch('clearActiveCall');
|
|
// Hide floating widget reactively
|
|
if (window.app && window.app.$data) {
|
|
window.app.$data.showCallWidget = false;
|
|
}
|
|
// Emit event for any listeners
|
|
if (window.app) {
|
|
window.app.$emit('callEnded');
|
|
}
|
|
// Outbound call cleanup
|
|
if (state.activeCall?.isOutbound && window.globalCallStatus) {
|
|
window.globalCallStatus.active = false;
|
|
window.globalCallStatus.incoming = false;
|
|
}
|
|
}
|
|
},
|
|
|
|
setActiveCall({ commit, dispatch, state }, callData) {
|
|
if (!callData || !callData.callSid) {
|
|
throw new Error('Invalid call data provided');
|
|
}
|
|
|
|
// If the call has a status, check if it's a terminal status
|
|
if (callData.status && ['ended', 'missed', 'completed'].includes(callData.status)) {
|
|
// If the call is already in a terminal state, clear any active call
|
|
if (callData.callSid === state.activeCall?.callSid) {
|
|
return dispatch('clearActiveCall');
|
|
}
|
|
// Otherwise just ignore it - don't set an already ended call as active
|
|
return;
|
|
}
|
|
|
|
commit('SET_ACTIVE_CALL', callData);
|
|
|
|
// Update app state if in browser environment
|
|
if (typeof window !== 'undefined' && window.app?.$data) {
|
|
window.app.$data.showCallWidget = true;
|
|
}
|
|
},
|
|
|
|
clearActiveCall({ commit }) {
|
|
// Store the messageId before clearing the call
|
|
const messageId = state.activeCall?.messageId;
|
|
|
|
commit('CLEAR_ACTIVE_CALL');
|
|
|
|
// Update app state if in browser environment
|
|
if (typeof window !== 'undefined' && window.app?.$data) {
|
|
window.app.$data.showCallWidget = false;
|
|
}
|
|
|
|
// We no longer need to update call widget status as we'll use reactive Vue props
|
|
// and updates will come through Chatwoot's standard message update events
|
|
},
|
|
|
|
setIncomingCall({ commit, state }, callData) {
|
|
if (!callData || !callData.callSid) {
|
|
throw new Error('Invalid call data provided');
|
|
}
|
|
|
|
// Don't set as incoming if call is already active
|
|
if (state.activeCall?.callSid === callData.callSid) {
|
|
return;
|
|
}
|
|
|
|
// Don't set as incoming if call is already incoming
|
|
if (state.incomingCall?.callSid === callData.callSid) {
|
|
return;
|
|
}
|
|
|
|
const enrichedCallData = {
|
|
...callData,
|
|
receivedAt: Date.now(),
|
|
};
|
|
|
|
commit('SET_INCOMING_CALL', enrichedCallData);
|
|
|
|
// Update app state if in browser environment
|
|
if (typeof window !== 'undefined' && window.app && window.app.$data) {
|
|
window.app.$data.showCallWidget = true;
|
|
}
|
|
|
|
// We no longer need to update call widget status as we'll use reactive Vue props
|
|
// and updates will come through Chatwoot's standard message update events
|
|
},
|
|
|
|
clearIncomingCall({ commit }) {
|
|
// Store the messageId before clearing the call
|
|
const messageId = state.incomingCall?.messageId;
|
|
|
|
commit('CLEAR_INCOMING_CALL');
|
|
|
|
// We no longer need to update call widget status as we'll use reactive Vue props
|
|
// and updates will come through Chatwoot's standard message update events
|
|
},
|
|
|
|
acceptIncomingCall({ commit, state }) {
|
|
const incomingCall = state.incomingCall;
|
|
if (!incomingCall) {
|
|
throw new Error('No incoming call to accept');
|
|
}
|
|
|
|
// Move incoming call to active call
|
|
commit('SET_ACTIVE_CALL', {
|
|
...incomingCall,
|
|
isJoined: true,
|
|
startedAt: Date.now(),
|
|
});
|
|
commit('CLEAR_INCOMING_CALL');
|
|
|
|
// We no longer need to update call widget status as we'll use reactive Vue props
|
|
// and updates will come through Chatwoot's standard message update events
|
|
},
|
|
};
|
|
|
|
const mutations = {
|
|
SET_ACTIVE_CALL($state, callData) {
|
|
$state.activeCall = callData;
|
|
},
|
|
CLEAR_ACTIVE_CALL($state) {
|
|
$state.activeCall = null;
|
|
},
|
|
SET_INCOMING_CALL($state, callData) {
|
|
$state.incomingCall = callData;
|
|
},
|
|
CLEAR_INCOMING_CALL($state) {
|
|
$state.incomingCall = null;
|
|
},
|
|
// We no longer need to update call widget status as we'll use reactive Vue props
|
|
|
|
// We no longer need subscription mutations
|
|
};
|
|
|
|
export default {
|
|
namespaced: true,
|
|
state,
|
|
getters,
|
|
actions,
|
|
mutations,
|
|
};
|