393 lines
16 KiB
JavaScript
393 lines
16 KiB
JavaScript
|
|
import { watch, computed } from 'vue';
|
|||
|
|
import useAgoraChannelStore from './stores/channelManger';
|
|||
|
|
import { CALLSTATUS, ANSWER_TYPE, CALL_ACTIONS_TYPE } from './contants';
|
|||
|
|
import useCallKitEvent from './callKitManage/useCallKitEvent';
|
|||
|
|
/* 频道信令发送 */
|
|||
|
|
import useSendSignalMsgs from './callKitManage/useSendSignalMsgs';
|
|||
|
|
let CallKitEMClient = null;
|
|||
|
|
let CallKitCreateMsgFun = null;
|
|||
|
|
const {
|
|||
|
|
EVENT_NAME,
|
|||
|
|
EVENT_LEVEL,
|
|||
|
|
CALLKIT_EVENT_TYPE,
|
|||
|
|
CALLKIT_EVENT_CODE,
|
|||
|
|
PUB_CHANNEL_EVENT,
|
|||
|
|
} = useCallKitEvent();
|
|||
|
|
//监听本地状态改变做出不同的状态处理。
|
|||
|
|
export const useInitCallKit = () => {
|
|||
|
|
const agoraChannelStore = useAgoraChannelStore();
|
|||
|
|
const { updateChannelInfos, updateLocalStatus } = agoraChannelStore;
|
|||
|
|
const callKitStatus = computed(() => agoraChannelStore.callKitStatus);
|
|||
|
|
const callKitTimer = computed(() => agoraChannelStore.callKitTimer);
|
|||
|
|
//监听频道状态变更做出对应操作。
|
|||
|
|
const onCallKitStatusChangeListener = () => {
|
|||
|
|
console.log('>>>>>频道状态监听已挂载');
|
|||
|
|
watch(
|
|||
|
|
() => callKitStatus.value.localClientStatus,
|
|||
|
|
(newClientStatus, oldClientStatus) => {
|
|||
|
|
handleClientStatusForAction(newClientStatus);
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
//处理不同clientstatus执行不同的操作
|
|||
|
|
const handleClientStatusForAction = (clientStatus) => {
|
|||
|
|
switch (clientStatus) {
|
|||
|
|
case CALLSTATUS.idle:
|
|||
|
|
console.log('%c >>>监听新状态为空闲处理,执行初始化', 'color:red');
|
|||
|
|
// initChannelInfos();
|
|||
|
|
agoraChannelStore.initChannelInfos();
|
|||
|
|
break;
|
|||
|
|
case CALLSTATUS.inviting:
|
|||
|
|
// if (callKitStatus.value.channelInfos.callType <= 1) {
|
|||
|
|
// }
|
|||
|
|
// if (callKitStatus.value.channelInfos.callType === 2) {
|
|||
|
|
// }
|
|||
|
|
// console.log('>>>>>可以展开邀请窗口');
|
|||
|
|
break;
|
|||
|
|
case CALLSTATUS.receivedConfirmRing:
|
|||
|
|
const eventParams = {
|
|||
|
|
type: CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.ALERT_SCREEN],
|
|||
|
|
ext: { message: '可以弹出通话接听UI组件' },
|
|||
|
|
callType: callKitStatus.value.channelInfos.callType,
|
|||
|
|
eventHxId: '',
|
|||
|
|
};
|
|||
|
|
PUB_CHANNEL_EVENT(EVENT_NAME, { ...eventParams });
|
|||
|
|
break;
|
|||
|
|
case CALLSTATUS.answerCall:
|
|||
|
|
console.log('>>>>>可以弹出通话接听UI组件');
|
|||
|
|
// if (callKitStatus.value.channelInfos.callType <= 1) {
|
|||
|
|
// console.log('>>>>>>>展示单人音视频组件');
|
|||
|
|
// // callComponents.value = 'singleCall';
|
|||
|
|
// }
|
|||
|
|
// if (callKitStatus.value.channelInfos.callType === 2) {
|
|||
|
|
// console.log('》》》》》展示多人音视频组件');
|
|||
|
|
// // callComponents.value = 'multiCall';
|
|||
|
|
// }
|
|||
|
|
break;
|
|||
|
|
case CALLSTATUS.confirmCallee:
|
|||
|
|
{
|
|||
|
|
// console.log('%c >>>>>可以加入房间了', 'color:green;');
|
|||
|
|
// console.log(
|
|||
|
|
// '++++++将入的频道类型是',
|
|||
|
|
// callKitStatus.value.channelInfos.callType
|
|||
|
|
// );
|
|||
|
|
// console.log(
|
|||
|
|
// '++++++频道名是',
|
|||
|
|
// callKitStatus.value.channelInfos.channelName
|
|||
|
|
// );
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
//初始化EMClient之Callkit内
|
|||
|
|
const setCallKitClient = (EMClient, CreateMsgFun) => {
|
|||
|
|
CallKitEMClient = EMClient;
|
|||
|
|
CallKitCreateMsgFun = CreateMsgFun;
|
|||
|
|
mountSignallingListener();
|
|||
|
|
};
|
|||
|
|
//挂载Callkit信令相关监听
|
|||
|
|
const mountSignallingListener = () => {
|
|||
|
|
console.log('>>>>>>>callkit 监听已挂载');
|
|||
|
|
const { sendAnswerMsg, sendAlertMsg, sendConfirmRing, sendConfirmCallee } =
|
|||
|
|
useSendSignalMsgs();
|
|||
|
|
onCallKitStatusChangeListener();
|
|||
|
|
CallKitEMClient.addEventHandler('callkitConnected', {
|
|||
|
|
onConnected: () => {
|
|||
|
|
//连接成功初始化emClient信息
|
|||
|
|
agoraChannelStore.initEmClientInfos(CallKitEMClient);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
CallKitEMClient.addEventHandler('callkitSignal', {
|
|||
|
|
onTextMessage: (message) => {
|
|||
|
|
const { ext } = message;
|
|||
|
|
if (ext && ext?.action === CALL_ACTIONS_TYPE.INVITE)
|
|||
|
|
handleCallKitInvite(message);
|
|||
|
|
console.log('>>>>>收到文本信令消息', message);
|
|||
|
|
},
|
|||
|
|
onCmdMessage: (msg) => {
|
|||
|
|
console.log('>>>>>收到命令信令消息', msg);
|
|||
|
|
if (msg && msg?.action === CALL_ACTIONS_TYPE.RTC_CALL)
|
|||
|
|
handleCallKitCommand(msg);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
//处理收到为文本的邀请信息
|
|||
|
|
const handleCallKitInvite = (msgBody) => {
|
|||
|
|
console.log('>>>>>开始处理被邀请消息');
|
|||
|
|
const { from, ext } = msgBody || {};
|
|||
|
|
//邀请消息发送者为自己则忽略
|
|||
|
|
if (from === CallKitEMClient.user) return;
|
|||
|
|
//非空闲回复busy
|
|||
|
|
if (callKitStatus.value.localClientStatus > CALLSTATUS.idle) {
|
|||
|
|
const payload = {
|
|||
|
|
targetId: from,
|
|||
|
|
sendBody: ext,
|
|||
|
|
};
|
|||
|
|
sendAnswerMsg(payload, ANSWER_TYPE.BUSY);
|
|||
|
|
} else {
|
|||
|
|
//更新当前频道信息
|
|||
|
|
updateChannelInfos(msgBody);
|
|||
|
|
//更新呼叫状态为alerting
|
|||
|
|
updateLocalStatus(CALLSTATUS.alerting);
|
|||
|
|
//通知呼叫方可以调起通话窗口
|
|||
|
|
sendAlertMsg(msgBody);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
//处理接收到通话交互过程的CMD命令消息
|
|||
|
|
const handleCallKitCommand = (msgBody) => {
|
|||
|
|
//多端状态下信令消息发送者为自己则忽略
|
|||
|
|
if (msgBody.from === CallKitEMClient.user) return;
|
|||
|
|
const cmdMsgBody = Object.assign({}, msgBody.ext) || {};
|
|||
|
|
const { calleeDevId, callerDevId } = cmdMsgBody;
|
|||
|
|
const clientResource = CallKitEMClient.context.jid.clientResource;
|
|||
|
|
const { action } = cmdMsgBody;
|
|||
|
|
const { localClientStatus, channelInfos } = callKitStatus.value;
|
|||
|
|
//当前有效会议ID
|
|||
|
|
const currentCallKitCallId = callKitStatus.value.channelInfos.callId;
|
|||
|
|
//返回给对方的confirmRing状态
|
|||
|
|
let status = true;
|
|||
|
|
const params = {
|
|||
|
|
targetId: msgBody.from,
|
|||
|
|
sendBody: cmdMsgBody,
|
|||
|
|
status,
|
|||
|
|
};
|
|||
|
|
//对方发布事件所需参数
|
|||
|
|
const eventParams = {
|
|||
|
|
type: {},
|
|||
|
|
ext: {},
|
|||
|
|
callType: 0,
|
|||
|
|
eventHxId: '',
|
|||
|
|
};
|
|||
|
|
switch (action) {
|
|||
|
|
case CALL_ACTIONS_TYPE.ALERT: //回复confirmring
|
|||
|
|
updateLocalStatus(CALLSTATUS.alerting);
|
|||
|
|
if (cmdMsgBody.callId !== currentCallKitCallId) {
|
|||
|
|
status = false;
|
|||
|
|
console.warn('callId 于当前呼叫端callId 不一致');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (
|
|||
|
|
localClientStatus > CALLSTATUS.receivedConfirmRing &&
|
|||
|
|
channelInfos.callType !== 2
|
|||
|
|
) {
|
|||
|
|
status = false;
|
|||
|
|
}
|
|||
|
|
if (callerDevId !== clientResource) {
|
|||
|
|
console.warn('callerDevId 设备不相同');
|
|||
|
|
status = false;
|
|||
|
|
}
|
|||
|
|
//如果status为true表明为有效的邀请,再更改为inviting,false表示无效邀请则更改为空闲状态。
|
|||
|
|
if (status) {
|
|||
|
|
sendConfirmRing(params);
|
|||
|
|
updateLocalStatus(CALLSTATUS.inviting);
|
|||
|
|
} else {
|
|||
|
|
sendConfirmRing(params);
|
|||
|
|
updateLocalStatus(CALLSTATUS.idle);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
break;
|
|||
|
|
case CALL_ACTIONS_TYPE.CONFIRM_RING: //回复 receivedConfirmRing
|
|||
|
|
{
|
|||
|
|
//调起confirm待接听界面
|
|||
|
|
if (calleeDevId !== clientResource) return; //【多端情况】被叫方设备id 如果不为当前用户登陆设备ID,则不处理。
|
|||
|
|
if (
|
|||
|
|
!cmdMsgBody.status &&
|
|||
|
|
callKitStatus.value.localClientStatus <
|
|||
|
|
CALLSTATUS.receivedConfirmRing
|
|||
|
|
) {
|
|||
|
|
updateLocalStatus(CALLSTATUS.idle); //重置为闲置状态
|
|||
|
|
} //邀请失效,不弹出接听确认框
|
|||
|
|
//有效邀请则设置状态为收到confirmRing
|
|||
|
|
updateLocalStatus(CALLSTATUS.receivedConfirmRing);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case CALL_ACTIONS_TYPE.ANSWER: //回复 confirmCallee
|
|||
|
|
{
|
|||
|
|
if (callerDevId !== clientResource) return; //【多端情况】呼叫方设备id 如果不为当前用户登陆设备ID,则不处理。
|
|||
|
|
updateLocalStatus(CALLSTATUS.receivedAnswerCall);
|
|||
|
|
callKitTimer.value && clearTimeout(callKitTimer.value);
|
|||
|
|
const params = {
|
|||
|
|
targetId: msgBody.from,
|
|||
|
|
sendBody: cmdMsgBody,
|
|||
|
|
};
|
|||
|
|
console.log('>>>>>>>>>收到answer信令', params);
|
|||
|
|
if (
|
|||
|
|
!callKitStatus.value.channelInfos.calleeDevId &&
|
|||
|
|
callKitStatus.value.channelInfos.callType !== 2
|
|||
|
|
) {
|
|||
|
|
//如果calleeDevId不存在,并且非多人音视频模式,主动更新频道信息
|
|||
|
|
if (cmdMsgBody.videoToVoice) {
|
|||
|
|
callKitStatus.value.channelInfos.callType = 0;
|
|||
|
|
}
|
|||
|
|
updateChannelInfos(msgBody);
|
|||
|
|
} else if (
|
|||
|
|
callKitStatus.value.channelInfos.calleeDevId !==
|
|||
|
|
cmdMsgBody.calleeDevId &&
|
|||
|
|
callKitStatus.value.channelInfos.callType !== 2
|
|||
|
|
) {
|
|||
|
|
//如果存在频道信息,但是与待呼叫确认的calleeDevId不一致直接发送拒绝应答。
|
|||
|
|
params.sendBody.result = ANSWER_TYPE.REFUSE;
|
|||
|
|
}
|
|||
|
|
sendConfirmCallee(params);
|
|||
|
|
updateLocalStatus(CALLSTATUS.confirmCallee);
|
|||
|
|
if (cmdMsgBody.result !== ANSWER_TYPE.ACCPET) {
|
|||
|
|
if (callKitStatus.value.channelInfos.callType !== 2) {
|
|||
|
|
//无论对方是忙碌还是拒接都讲通话状态更改为闲置。
|
|||
|
|
if (cmdMsgBody.result === ANSWER_TYPE.BUSY) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '对方正忙',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000,
|
|||
|
|
});
|
|||
|
|
eventParams.type =
|
|||
|
|
CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.CALLEE_BUSY];
|
|||
|
|
eventParams.ext = { message: '对方正忙' };
|
|||
|
|
}
|
|||
|
|
if (cmdMsgBody.result === ANSWER_TYPE.REFUSE) {
|
|||
|
|
eventParams.type =
|
|||
|
|
CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.CALLEE_REFUSE];
|
|||
|
|
eventParams.ext = { message: '对方拒绝接听' };
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '对方拒绝接听',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
eventParams.callType =
|
|||
|
|
callKitStatus.value.channelInfos.callType;
|
|||
|
|
eventParams.eventHxId = msgBody.from || '';
|
|||
|
|
PUB_CHANNEL_EVENT(EVENT_NAME, { ...eventParams });
|
|||
|
|
//修改当前状态为空闲
|
|||
|
|
console.log('>>>>>修改当前状态为空闲');
|
|||
|
|
return updateLocalStatus(CALLSTATUS.idle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case CALL_ACTIONS_TYPE.CONFIRM_CALLEE: //被叫方认证
|
|||
|
|
{
|
|||
|
|
//如果calleeDevId不等于当前设备resource
|
|||
|
|
if (msgBody.to === CallKitEMClient.user) {
|
|||
|
|
if (cmdMsgBody.result && cmdMsgBody.result === ANSWER_TYPE.BUSY) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (cmdMsgBody.calleeDevId !== clientResource) {
|
|||
|
|
updateLocalStatus(CALLSTATUS.idle); //更改状态为闲置
|
|||
|
|
console.log('%c 已在其他设备处理', 'color:red;');
|
|||
|
|
eventParams.type =
|
|||
|
|
CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.OTHER_HANDLE];
|
|||
|
|
eventParams.ext = { message: '已在其他设备处理' };
|
|||
|
|
eventParams.callType =
|
|||
|
|
callKitStatus.value.channelInfos.callType;
|
|||
|
|
eventParams.eventHxId = msgBody.from || '';
|
|||
|
|
PUB_CHANNEL_EVENT(EVENT_NAME, { ...eventParams });
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '该通话已在其他设备处理',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000,
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 防止通话中收到 busy refuse时挂断
|
|||
|
|
if (
|
|||
|
|
cmdMsgBody.result !== ANSWER_TYPE.ACCPET &&
|
|||
|
|
callKitStatus.value.localClientStatus !== CALLSTATUS.confirmCallee
|
|||
|
|
) {
|
|||
|
|
return updateLocalStatus(CALLSTATUS.idle); //更改状态为闲置
|
|||
|
|
}
|
|||
|
|
//变更状态为confirmCallee
|
|||
|
|
updateLocalStatus(CALLSTATUS.confirmCallee);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
case CALL_ACTIONS_TYPE.CANCEL: {
|
|||
|
|
if (msgBody.from === CallKitEMClient.user) return; //【多端情况】被叫方设备id 如果不为当前用户登陆设备ID,则不处理。
|
|||
|
|
if (msgBody.from === callKitStatus.value.channelInfos.callerIMName)
|
|||
|
|
return updateLocalStatus(CALLSTATUS.idle);
|
|||
|
|
eventParams.type =
|
|||
|
|
CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.CALLER_CANCEL];
|
|||
|
|
eventParams.ext = { message: '对方取消呼叫' };
|
|||
|
|
eventParams.callType = callKitStatus.value.channelInfos.callType;
|
|||
|
|
eventParams.eventHxId = msgBody.from || '';
|
|||
|
|
PUB_CHANNEL_EVENT(EVENT_NAME, { ...eventParams });
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
case CALL_ACTIONS_TYPE.VIDEO_TO_VOICE: {
|
|||
|
|
if (cmdMsgBody.callId !== callKitStatus.value.channelInfos.callType)
|
|||
|
|
return;
|
|||
|
|
callKitStatus.value.channelInfos.callType = CALL_TYPES.SINGLE_VOICE;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
default:
|
|||
|
|
console.log('>>>其他未知状态');
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
//发送接听或者拒接信令
|
|||
|
|
const handleSendAnswerMsg = (sendType) => {
|
|||
|
|
const { sendAnswerMsg } = useSendSignalMsgs();
|
|||
|
|
const channelInfos = callKitStatus.value.channelInfos;
|
|||
|
|
const payload = {
|
|||
|
|
targetId: channelInfos.callerIMName,
|
|||
|
|
sendBody: {
|
|||
|
|
callerDevId: channelInfos.callerDevId,
|
|||
|
|
callId: channelInfos.callId,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
if (sendType === ANSWER_TYPE.ACCPET) {
|
|||
|
|
sendAnswerMsg(payload, ANSWER_TYPE.ACCPET);
|
|||
|
|
updateLocalStatus(CALLSTATUS.answerCall); //更改状态为已应答
|
|||
|
|
console.log('>>>>开始发送接听信令', payload);
|
|||
|
|
//对外频道接听事件发布事件
|
|||
|
|
const eventParams = {
|
|||
|
|
type: CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.CALLEE_ACCPET],
|
|||
|
|
ext: { message: '通话已接听' },
|
|||
|
|
callType: callKitStatus.value.channelInfos.callType,
|
|||
|
|
eventHxId: channelInfos.callerIMName,
|
|||
|
|
};
|
|||
|
|
//如果是多人就取对应群组ID
|
|||
|
|
if (callKitStatus.value.channelInfos.callType === 2) {
|
|||
|
|
eventParams.eventHxId = callKitStatus.value.channelInfos.groupId;
|
|||
|
|
}
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '通话已接听',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000,
|
|||
|
|
});
|
|||
|
|
PUB_CHANNEL_EVENT(EVENT_NAME, { ...eventParams });
|
|||
|
|
}
|
|||
|
|
if (sendType === ANSWER_TYPE.REFUSE) {
|
|||
|
|
sendAnswerMsg(payload, ANSWER_TYPE.REFUSE);
|
|||
|
|
updateLocalStatus(CALLSTATUS.idle); //更改状态为闲置
|
|||
|
|
console.log('>>>>开始发送挂断信令');
|
|||
|
|
//对外频道接听事件发布事件
|
|||
|
|
const eventParams = {
|
|||
|
|
type: CALLKIT_EVENT_TYPE[CALLKIT_EVENT_CODE.CALLEE_REFUSE],
|
|||
|
|
ext: { message: '已拒绝通话邀请' },
|
|||
|
|
callType: callKitStatus.value.channelInfos.callType,
|
|||
|
|
eventHxId: channelInfos.callerIMName,
|
|||
|
|
};
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '已拒绝通话邀请',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000,
|
|||
|
|
});
|
|||
|
|
//如果是多人就取对应群组ID
|
|||
|
|
if (callKitStatus.value.channelInfos.callType === 2) {
|
|||
|
|
eventParams.eventHxId = callKitStatus.value.channelInfos.groupId;
|
|||
|
|
}
|
|||
|
|
PUB_CHANNEL_EVENT(EVENT_NAME, { ...eventParams });
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
return {
|
|||
|
|
CallKitEMClient,
|
|||
|
|
CallKitCreateMsgFun,
|
|||
|
|
setCallKitClient,
|
|||
|
|
handleSendAnswerMsg,
|
|||
|
|
};
|
|||
|
|
};
|