Skip to content

Instantly share code, notes, and snippets.

@poberwong
Created October 24, 2018 14:42
Show Gist options
  • Save poberwong/6134c6728035902971ec6588d5fa0303 to your computer and use it in GitHub Desktop.
Save poberwong/6134c6728035902971ec6588d5fa0303 to your computer and use it in GitHub Desktop.
IM 新升级内容
import { observable, action } from 'mobx'
import config from 'app/config'
import { message } from 'antd'
import NIM from 'app/utils/NIM_Web_NIM_v5.2.1.js'
import WebRTC from 'app/utils/NIM_Web_WebRTC_v5.2.1.js'
import globalStore, { PLAY_TYPE } from 'app/stores/global'
import { getToken } from 'app/utils/localTools'
import { computed } from 'mobx'
const FREE = 'free'
const WAITING = 'waiting'
const CALLING = 'busy'
const BECALLED = 'receive call'
export const STATUS = {
free: FREE,
waiting: WAITING,
calling: CALLING,
beCalled: BECALLED
}
const TYPE_VIDEO = 'video'
const TYPE_AUDIO = 'audio'
const typeMap = new Map([
[WebRTC.NETCALL_TYPE_VIDEO, TYPE_VIDEO],
[WebRTC.NETCALL_TYPE_AUDIO, TYPE_AUDIO],
])
class CommunicateStore {
medicalRecordStore
amIChatting = false // 该量只应用于话单的发送功能模块上,不会对其他模块产生影响
globalStore
@observable accid = ''
@observable targetAccid = ''
@observable status = FREE
@observable ready = false
@observable duration = [0, 0]
@observable sessionConfig = {
recordVideo: true,
recordAudio: true,
videoQuality: WebRTC.CHAT_VIDEO_QUALITY_480P,
}
@observable videoMini = false
@observable visible = false
@observable callType = ''
@observable chatStore
constructor () {
NIM.use(WebRTC)
}
setIamChatting = (amIChatting) => {
this.amIChatting = amIChatting
}
@computed get avatar() {
if (this.chatStore && this.chatStore.membersInfoCache.get(this.targetAccid)) {
return this.chatStore.membersInfoCache.get(this.targetAccid).avatar
} else {
return null
}
}
@action maxVideoView = () => {
console.log('放大了')
this.videoMini = false
}
@action minVideoView = () => {
this.videoMini = true
}
@action hidden = () => {
this.visible = false
}
@action show = () => {
this.visible = true
}
@action setSessionConfig = (obj) => {
this.sessionConfig = {...this.sessionConfig, ...obj}
}
@action setNim = () => {
const { firstAccid } = this.chatStore
this.nim = this.chatStore[firstAccid].nim
}
@action setStatus = (status) => {
this.status = status
}
@action listenEvent = () => {
// this.netcall.on('beCalling', obj => {
// const { channelId } = obj
// console.log('正在被呼叫...')
//
// if (!this.netcall.calling && !this.beCalling) {
// this.beCalling = true
// this.beCalledInfo = obj
// globalStore.play(PLAY_TYPE.RING)
// this.setStatus(BECALLED)
// } else {
// console.log('我在通话中,拒绝通话外的人')
// this.netcall.control({
// channelId: channelId,
// command: WebRTC.NETCALL_CONTROL_COMMAND_BUSY
// })
// }
// })
this.netcall.on('callAccepted', obj => {
console.log('接听成功')
globalStore.pause('ringMp3')
this.setStatus(CALLING)
clearTimeout(this.overtimetimer)
this.startTimer()
this.netcall.startRtc().then(() => {
this.startDeviceVideo()
.then(() => {
// 开启本地视频预览
this.netcall.startLocalStream(document.getElementById('local'))
})
.catch(err => console.log('启动摄像头失败', err))
.then(() => this.startDeviceAudioIn())
}).catch((err) => {
console.log('发生错误, 挂断通话')
console.log(err)
this.hangup()
})
})
// 在回调里监听对方加入通话,并显示对方的视频画面
this.netcall.on('remoteTrack', (obj) => {
console.log('user join', obj)
// 播放对方声音
this.netcall.startDevice({
type: WebRTC.DEVICE_TYPE_AUDIO_OUT_CHAT
}).catch((err) => {
console.log('播放对方的声音失败')
console.error(err)
})
// 预览对方视频画面
this.netcall.startRemoteStream({
account: obj.account,
node: document.getElementById('remote')
})
this.netcall.setVideoViewRemoteSize({
width: 500,
height: 500,
cut: true
})
})
this.netcall.on('callRejected', obj => { // TODO, 抽象
console.log('被拒绝了')
this.resetAll()
})
this.netcall.on('hangup', obj => {
console.log('obj', obj)
console.log('被挂断了1')
globalStore.pause('ringMp3')
this.resetAll()
})
// this.netcall.on('control', obj => {
// console.log('obj', obj)
// switch(obj.type) {
// case WebRTC.NETCALL_CONTROL_COMMAND_SWITCH_AUDIO_TO_VIDEO:
// console.log('video: ')
//
// this.type = TYPE_VIDEO
// this.openVideo()
// break
// case WebRTC.NETCALL_CONTROL_COMMAND_SWITCH_VIDEO_TO_AUDIO:
// console.log('audio')
// this.type = TYPE_AUDIO
// this.closeVideo()
// break
// case WebRTC.NETCALL_CONTROL_COMMAND_BUSY:
// console.log('占线')
// // this.disposeMultiLogin()
// break
// default: console.log('other command')
// }
// })
}
@action init = () => {
this.netcall = WebRTC.getInstance({
nim: this.nim,
container: document.getElementById('local'),
remoteContainer: document.getElementById('remote'),
debug: true,
})
this.ready = true
}
switchType = (type) => {
this.type = type
if (type === TYPE_VIDEO) {
this.switchAudioToVideo()
} else {
this.switchVideoToAudio()
}
}
switchAudioToVideo = () => {
this.netcall.control({
command: WebRTC.NETCALL_CONTROL_COMMAND_SWITCH_AUDIO_TO_VIDEO
})
this.openVideo()
}
switchVideoToAudio = () => {
this.netcall.control({
command: WebRTC.NETCALL_CONTROL_COMMAND_SWITCH_VIDEO_TO_AUDIO
})
this.closeVideo()
}
openVideo = () => {
this.startDeviceVideo()
.then(() => this.netcall.startLocalStream())
.then(() => this.netcall.switchAudioToVideo())
.then(() => this.netcall.startRemoteStream())
.catch(err => message.error(err))
}
closeVideo = () => {
this.netcall.stopLocalStream()
this.netcall.stopRemoteStream()
this.netcall.switchVideoToAudio()
}
startTimer = () => {
this.resetTimer()
this.timer = setInterval(() => {
const [mins, seconds] = this.duration
if (seconds + 1 === 60) {
this.duration = [
mins + 1,
0
]
} else {
this.duration = [
mins,
seconds + 1
]
}
}, 1000)
}
resetTimer = () => {
if(this.timer) {
clearTimeout(this.timer)
this.timer = null
}
this.duration = [0, 0]
}
@action setUserData = (userData) => {
this.userData = userData
this.accid = userData.doctorAccid
this.targetAccid = userData.accid
this.tid = userData.tid
}
@action setCallType = (type) => {
this.callType = +type
}
@action loadAvatar = () => {
this.chatStore.updateCache({from: this.targetAccid})
}
@action connectWebsocket = (type) => {
if(!this.websocket) {
this.websocket = new WebSocket(`${config.wsUri}/chats/${this.accid}?jwt=${getToken()}`)
}
this.websocket.onmessage = (msg) => {
const isCalling = JSON.parse(msg.data).calling
if (!isCalling) {
if (this.avatar === null) {
this.loadAvatar()
}
this.setCallType(type)
if (!this.ready) {
this.setNim()
this.init()
this.listenEvent()
}
this.setIamChatting(true)
this.startChatting()
} else {
alert('当前账号正在通话')
}
}
}
@action closeConnection = () => {
console.log('close ws connection')
if(this.websocket) {
this.websocket.close()
this.websocket = null
}
}
resetAll = () => {
this.resetTimer()
clearTimeout(this.overtimetimer)
setTimeout(() => { // 不论是否收到通知话单,使用定时器强制恢复状态(避免因为云信服务器未发出的原因无法恢复状态,允许重复恢复)
this.setIamChatting(false)
}, 1500)
this.setStatus(FREE)
this.beCalling = false
this.beCalledInfo = null
globalStore.pause('ringMp3')
this.closeConnection()
if (this.medicalRecordStore) { // 写到
this.hidden()
}
}
@action startChatting = (type) => {
this.setStatus(WAITING)
this.netcall.call({
type: this.callType,
account: this.chatStore.targetAccid,
pushConfig: {
pushContent: `护士正邀请您进行${type === WebRTC.NETCALL_TYPE_VIDEO ? '视频' : '语音'}问诊`,
custom: JSON.stringify({
key: 'value'
}),
pushPayload: JSON.stringify({
type: typeMap[this.callType]
}),
sound: 'video_chat_tip_sender.aac'
},
webrtcEnable: true,
sessionConfig: this.sessionConfig
})
.then(
res => { // reject: 对方无人接听;
globalStore.play(PLAY_TYPE.RING)
if (this.medicalRecordStore) {
this.show()
}
this.overtimetimer = setTimeout(() => { // 对方未响应60秒超时
if (!this.netcall.callAccepted) {
this.hangup()
globalStore.play(PLAY_TYPE.NO_RESPONSE) // 播放:对方无人接听音频
this.setStatus(FREE)
console.log('对方无人接听')
}
}, 60000) // 60 秒超时
},
err => { // reject: 对方不在线;
if (err.event.code === 11001) {
globalStore.play(PLAY_TYPE.OFFLINE)
} else {
message.error('通话不可达:' + err.event.code)
}
this.hangup()
}
)
}
hangup = () => { // 主叫方挂断
console.log('我是主叫方 我挂断了')
this.netcall.hangup()
this.resetAll()
return Promise.resolve()
}
rejectCall = () => { // 被叫方拒绝接听
console.log('我是被叫方 我挂断了')
this.netcall.control({
channelId: this.beCalledInfo.channelId,
command: WebRTC.NETCALL_CONTROL_COMMAND_BUSY
})
this.netcall.response({
accepted: false,
beCalledInfo: this.beCalledInfo
})
this.resetAll()
}
startDeviceAudioIn = () => {
return this.netcall.startDevice({
type: WebRTC.DEVICE_TYPE_AUDIO_IN
}).then(() => {
// 通知对方自己开启了麦克风
this.netcall.control({
command: WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_ON
})
// 设置采集音量
this.netcall.setCaptureVolume(255)
}).catch(() => {
console.log('启动麦克风失败')
})
}
startDeviceVideo = () => {
return this.netcall.startDevice({
type: WebRTC.DEVICE_TYPE_VIDEO
}).then(() => {
// 通知对方自己开启了摄像头
this.netcall.control({
command: WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_ON
})
}).catch(() => {
// 通知对方自己的摄像头不可用
this.netcall.control({
command: WebRTC.NETCALL_CONTROL_COMMAND_SELF_CAMERA_INVALID
})
console.log('启动摄像头失败')
})
}
}
export default new CommunicateStore()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment