@tencentcloud/call-uikit-vue2
Advanced tools
Comparing version 2.3.4 to 2.3.5
{ | ||
"name": "@tencentcloud/call-uikit-vue2", | ||
"version": "2.3.4", | ||
"main": "./tuicall-uikit-vue2.umd.js", | ||
"module": "./tuicall-uikit-vue2.es.js", | ||
"version": "2.3.5", | ||
"main": "./tuicall-uikit-vue.umd.js", | ||
"module": "./tuicall-uikit-vue.es.js", | ||
"types": "./types/src/index.d.ts", | ||
@@ -7,0 +7,0 @@ "description": "An Open-source Voice & Video Calling UI Component Based on Tencent Cloud Service.", |
@@ -1,9 +0,5 @@ | ||
import { TUIGlobal, TUIStore, StoreName, TUICallKitServer, NAME, StatusChange as STATUS, CallRole, CallMediaType, VideoResolution, VideoDisplayMode, t } from './TUICallService/index'; | ||
// @if process.env.BUILD_TARGET!='MINI' | ||
// @ts-ignore | ||
import TUICallKit from './Components/TUICallKit-vue2/TUICallKit.vue'; | ||
import { TUICallType } from "tuicall-engine-webrtc"; // ≤v2.2.1 抛出的字段 | ||
// 原 web callKit 融合 chat 方法. ref: https://tapd.woa.com/20396022/prong/stories/view/1020396022885708891 | ||
// @ts-ignore | ||
import TUICallKit from './Components/TUICallKit.vue'; | ||
const plugin = (TUICore) => { | ||
@@ -14,3 +10,2 @@ TUICore.component("TUICallKit", { server: TUICallKitServer }); | ||
}; | ||
// @ts-ignore | ||
const install = (app) => { | ||
@@ -22,3 +17,9 @@ app.component("TUICallKit", TUICallKit); | ||
TUICallKit.install = install; | ||
const Version = '2.3.4'; // basic-demo 原来上报使用 | ||
const TUICallType = { // Web TUICallKit ≤v2.2.1 抛出的字段 | ||
AUDIO_CALL: 1, | ||
VIDEO_CALL: 2, | ||
} | ||
// @endif | ||
const Version = '2.3.5'; // basic-demo 原来上报使用 | ||
// 输出产物 | ||
@@ -30,5 +31,8 @@ export { | ||
TUICallKitServer, | ||
// @if process.env.BUILD_TARGET!='MINI' | ||
// uni-app 打包小程序无法引入 vue 组件, 只能在使用侧单独引入 vue 文件 | ||
TUICallKit, | ||
plugin, | ||
install, | ||
// @endif | ||
NAME, | ||
@@ -35,0 +39,0 @@ STATUS, |
import { ITUICallService, ICallParams, IGroupCallParams, IUserInfo, ICallbackParam, ISelfInfoParams } from '../interface/ICallService'; | ||
import { StoreName, TUIStore, TUIGlobal } from '../index'; | ||
import { CallStatus, CallMediaType, NAME, CALL_DATA_KEY, LanguageType, CallRole, LOG_LEVEL, VideoDisplayMode, VideoResolution, StatusChange, DEVICE_STATUS } from '../const'; | ||
// @ts-ignore | ||
import { StoreName, TUIStore } from '../index'; | ||
import { CallStatus, CallMediaType, NAME, CALL_DATA_KEY, LanguageType, CallRole, LOG_LEVEL, VideoDisplayMode, VideoResolution, StatusChange, AudioCallIcon, VideoCallIcon, ErrorCode, ErrorMessage, AudioPlayBackDevice } from '../const'; | ||
import { TUICallEngine, TUICallEvent } from 'tuicall-engine-webrtc'; | ||
import { CallTips } from '../locales'; | ||
import { beforeCall, BellContext } from './miniProgram'; | ||
import { BellContext } from './web'; | ||
import { checkLocalMP3FileExists } from '../utils'; | ||
import { avoidRepeatedCall } from '../utils/validate'; | ||
@@ -12,5 +12,5 @@ import { handleRepeatedCallError, handleNoDevicePermissionError, setDefaultUserInfo, formatTime, formatTimeInverse } from '../utils/common-utils'; | ||
import { t } from '../locales'; | ||
const version = '2.3.4'; | ||
let INVITER_BELL_FILEPATH = '../static/phone_dialing.mp3'; | ||
let INVITEE_BELL_FILEPATH = '../static/phone_ringing.mp3'; | ||
const version = '2.3.5'; | ||
import DEFAULT_CALLER_BELL_FILEPATH from '../assets/phone_dialing.mp3'; | ||
import DEFAULT_CALLEE_BELL_FILEPATH from '../assets/phone_ringing.mp3'; | ||
@@ -24,2 +24,3 @@ export default class TUICallService implements ITUICallService { | ||
private _callingBell: any = null; | ||
private _bellFilePath: string | undefined; | ||
constructor() { | ||
@@ -35,4 +36,7 @@ console.log(`${NAME.PREFIX}version: ${version}`); | ||
} | ||
@avoidRepeatedCall() | ||
public async init(params: any = {}) { | ||
try { | ||
if (this._tuiCallEngine) return; | ||
this._watchTUIStore(); | ||
let { sdkAppID, tim, userID, userSig, SDKAppID } = params; | ||
@@ -44,12 +48,11 @@ if (this._TUICore) { | ||
this._tim = tim; | ||
console.warn(`${NAME.PREFIX}init params: ${JSON.stringify(params)}`); | ||
if (!this._tuiCallEngine) { | ||
this._tuiCallEngine = TUICallEngine.createInstance({ | ||
tim, | ||
SDKAppID: sdkAppID || SDKAppID, // 兼容传入 SDKAppID 的问题, | ||
}); | ||
} | ||
console.log(`${NAME.PREFIX}init sdkAppId: ${sdkAppID || SDKAppID}, userId: ${userID}`); | ||
this._tuiCallEngine = TUICallEngine.createInstance({ | ||
tim, | ||
SDKAppID: sdkAppID || SDKAppID, // 兼容传入 SDKAppID 的问题 | ||
}); | ||
this._addListenTuiCallEngineEvent(); | ||
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { userId: userID }); | ||
await this._tuiCallEngine.login({ userID, userSig, assetsPath: '' }) | ||
await this._tuiCallEngine.login({ userID, userSig, assetsPath: '' }); // web && mini | ||
this._callingBell = new BellContext(); | ||
} catch (error) { | ||
@@ -65,3 +68,3 @@ console.error(`${NAME.PREFIX}init failed, error: ${JSON.stringify(error)}.`); | ||
if (currentCallStatus !== CallStatus.IDLE) { | ||
throw new Error(`please destroyed when status is idle, now status: ${currentCallStatus}`); | ||
throw new Error(`please destroyed when status is idle, current status: ${currentCallStatus}`); | ||
} | ||
@@ -80,4 +83,4 @@ if (this._tuiCallEngine) { | ||
} | ||
// ==============================【通话操作】============================== | ||
@avoidRepeatedCall() // ref: https://tapd.woa.com/TerWebG/prong/stories/view/1020396022885692351 | ||
// ===============================【通话操作】=============================== | ||
@avoidRepeatedCall() | ||
public async call(callParams: ICallParams) { | ||
@@ -87,12 +90,6 @@ try { | ||
if (TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS) !== CallStatus.IDLE) return; | ||
this._updateCallStoreBeforeCall(type, [{ userId: userID }]); | ||
await this._updateCallStoreBeforeCall(type, [{ userId: userID }]); | ||
this._executeExternalBeforeCalling(); // 执行外部传入的 beforeCall 方法 | ||
const response = await this._tuiCallEngine.call(callParams); | ||
// web callEngine 返回的是邀请信令的返回值. groupCall 同理 | ||
if (response?.code === 0) { | ||
(type === CallMediaType.VIDEO) && await this.openCamera(NAME.LOCAL_VIDEO); | ||
await this._updateCallStoreAfterCall([userID]); | ||
} else { | ||
this._resetCallStore(); | ||
} | ||
await this._updateCallStoreAfterCall([userID], response); | ||
} catch (error: any) { | ||
@@ -112,11 +109,6 @@ if (handleRepeatedCallError(error)) return; | ||
const remoteUserInfoList = userIDList.map(userId => ({ userId })) | ||
this._updateCallStoreBeforeCall(type, remoteUserInfoList, groupID); | ||
await this._updateCallStoreBeforeCall(type, remoteUserInfoList, groupID); | ||
this._executeExternalBeforeCalling(); | ||
const response = await this._tuiCallEngine.groupCall(groupCallParams); | ||
if (response?.code === 0) { | ||
(type === CallMediaType.VIDEO) && await this.openCamera(NAME.LOCAL_VIDEO); | ||
await this._updateCallStoreAfterCall(userIDList); | ||
} else { | ||
this._resetCallStore(); | ||
} | ||
await this._updateCallStoreAfterCall(userIDList, response); | ||
} catch (error: any) { | ||
@@ -154,3 +146,3 @@ if (handleRepeatedCallError(error)) return; | ||
} | ||
// ==============================【其它对外接口】============================== | ||
// ===============================【其它对外接口】=============================== | ||
public setLogLevel(level: LOG_LEVEL) { | ||
@@ -160,3 +152,5 @@ this?._tuiCallEngine?.setLogLevel(level); | ||
public setLanguage(language: LanguageType) { | ||
TUIStore.update(StoreName.CALL, NAME.LANGUAGE, language); | ||
if (language && Object.values(LanguageType).includes(language)) { | ||
TUIStore.update(StoreName.CALL, NAME.LANGUAGE, language); | ||
} | ||
} | ||
@@ -180,3 +174,3 @@ public async setSelfInfo(params: ISelfInfoParams) { | ||
} | ||
// ==============================【内部按钮操作方法】============================== | ||
// =============================【内部按钮操作方法】============================= | ||
@avoidRepeatedCall() | ||
@@ -188,14 +182,11 @@ public async accept() { | ||
if (response) { | ||
const callMediaType = TUIStore.getData(StoreName.CALL, NAME.CALL_MEDIA_TYPE); | ||
// 只有pc下才有摄像头的开关状态记录,h5和小程序默认都是打开 | ||
const isCameraOpen = TUIGlobal.isPC | ||
? TUIStore.getData(StoreName.CALL, NAME.CAMERA_STATUS) === DEVICE_STATUS.OPEN | ||
: true; | ||
(callMediaType === CallMediaType.VIDEO) && isCameraOpen && await this.openCamera(NAME.LOCAL_VIDEO); | ||
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true); | ||
this._setLocalUserInfoAudioVideoAvailable(true, NAME.AUDIO); // 呼叫默认是打开 audio 的 | ||
this._startTimer(); | ||
const callMediaType = TUIStore.getData(StoreName.CALL, NAME.CALL_MEDIA_TYPE); | ||
(callMediaType === CallMediaType.VIDEO) && await this.openCamera(NAME.LOCAL_VIDEO); | ||
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION)); | ||
const localUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO); | ||
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { ...localUserInfo, isEnter: true }); | ||
this._setLocalUserInfoAudioVideoAvailable(true, NAME.AUDIO); // web && mini default open audio | ||
} | ||
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION)); | ||
} catch (error) { | ||
@@ -210,4 +201,6 @@ if (handleRepeatedCallError(error)) return; | ||
try { | ||
await this._tuiCallEngine.hangup(); | ||
} catch (error) {} // catch 不需要处理 | ||
const response = await this._tuiCallEngine.hangup(); | ||
} catch (error) { | ||
console.debug(error); | ||
} | ||
this._resetCallStore() | ||
@@ -218,4 +211,6 @@ } | ||
try { | ||
await this._tuiCallEngine.reject(); | ||
} catch (error) {} | ||
const response = await this._tuiCallEngine.reject(); | ||
} catch (error) { | ||
console.debug(error); | ||
} | ||
this._resetCallStore() | ||
@@ -239,3 +234,3 @@ } | ||
} catch (error: any) { | ||
console.error(`${NAME.PREFIX}openCamera error: ${JSON.stringify(error)}.`); | ||
console.error(`${NAME.PREFIX}closeCamera error: ${JSON.stringify(error)}.`); | ||
} | ||
@@ -270,6 +265,6 @@ } | ||
} | ||
await this._tuiCallEngine.switchCallMediaType(CallMediaType.AUDIO); | ||
const response = await this._tuiCallEngine.switchCallMediaType(CallMediaType.AUDIO); | ||
TUIStore.update(StoreName.CALL, NAME.CALL_MEDIA_TYPE, CallMediaType.AUDIO); | ||
const isGroup = TUIStore.getData(StoreName.CALL, NAME.IS_GROUP); | ||
const oldStatus = isGroup ? StatusChange.CALLING_GROUP_VIDEO : StatusChange.CALLING_C2C_VIDEO; | ||
const oldStatus = isGroup ? StatusChange.CALLING_GROUP_VIDEO : StatusChange.CALLING_C2C_VIDEO; | ||
this.statusChanged && this.statusChanged({ oldStatus, newStatus: this._generateStatusChangeText() }); | ||
@@ -287,5 +282,18 @@ } catch (error: any) { | ||
} | ||
return this._tuiCallEngine.tim; | ||
return this._tuiCallEngine?.tim || this._tuiCallEngine?.getTim(); // mini support getTim interface | ||
} | ||
// ==============================【TUICallEngine 事件处理】============================== | ||
// 修改默认铃声:只支持本地铃声文件,不支持在线铃声文件;修改铃声修改的是被叫的铃声 | ||
public async setCallingBell(filePath?: string) { | ||
// @ts-ignore | ||
let result = await checkLocalMP3FileExists(filePath); | ||
if (result) { | ||
this._bellFilePath = filePath; | ||
} else { | ||
this._bellFilePath = DEFAULT_CALLEE_BELL_FILEPATH; | ||
console.warn(`${NAME.PREFIX}setCallingBell: ${filePath} The media ringtone file does not exist or has an incorrect format.`); | ||
} | ||
this._callingBell.setBellSrc(this._bellFilePath); | ||
} | ||
// ==========================【TUICallEngine 事件处理】========================== | ||
private _addListenTuiCallEngineEvent() { | ||
@@ -301,3 +309,2 @@ if (!this._tuiCallEngine) { | ||
this._tuiCallEngine.on(TUICallEvent.USER_LEAVE, this._handleUserLeave, this); // 有用户离开通话事件 | ||
// this._tuiCallEngine.on(TUICallEvent.USER_UPDATE, this.handleUserUpdate, this); | ||
this._tuiCallEngine.on(TUICallEvent.REJECT, this._handleInviteeReject, this); // 主叫收到被叫的拒绝通话事件 | ||
@@ -307,13 +314,12 @@ this._tuiCallEngine.on(TUICallEvent.NO_RESP, this._handleNoResponse, this); // 主叫收到被叫的无应答事件 | ||
this._tuiCallEngine.on(TUICallEvent.CALLING_CANCEL, this._handleCallingCancel, this); // 主被叫在通话未建立时, 收到的取消事件 | ||
this._tuiCallEngine.on(TUICallEvent.CALL_END, this._handleCallingEnd, this); // 主被叫在通话结束时, 收到的通话结束事件 | ||
this._tuiCallEngine.on(TUICallEvent.SDK_READY, this._handleSDKReady, this); // SDK Ready 回调 | ||
this._tuiCallEngine.on(TUICallEvent.KICKED_OUT, this._handleKickedOut, this); // 未开启多端登录时, 多端登录收到的被踢事件 | ||
this._tuiCallEngine.on(TUICallEvent.CALL_TYPE_CHANGED, this._handleCallTypeChange, this); // 切换通话事件 miniProgram CALL_MODE | ||
this._tuiCallEngine.on(TUICallEvent.MESSAGE_SENT_BY_ME, this._messageSentByMe, this); | ||
this._tuiCallEngine.on(TUICallEvent.CALLING_END, this._handleCallingEnd, this); // 主被叫在通话结束时, 收到的通话结束事件 | ||
this._tuiCallEngine.on(TUICallEvent.CALL_TYPE_CHANGED, this._handleCallTypeChange, this); | ||
this._tuiCallEngine.on(TUICallEvent.USER_VIDEO_AVAILABLE, this._handleUserVideoAvailable, this); | ||
this._tuiCallEngine.on(TUICallEvent.USER_AUDIO_AVAILABLE, this._handleUserAudioAvailable, this); | ||
this._tuiCallEngine.on(TUICallEvent.MESSAGE_SENT_BY_ME, this._messageSentByMe, this); // miniProgram 才有 | ||
this._tuiCallEngine.on(TUICallEvent.USER_VOICE_VOLUME, this._handleUserVoiceVolume, this); // web | ||
this._tuiCallEngine.on(TUICallEvent.USER_VOICE_VOLUME, this._handleUserVoiceVolume, this); | ||
} | ||
private _removeListenTuiCallEngineEvent() { | ||
// this._tuiCallEngine.off('*'); | ||
this._tuiCallEngine.off(TUICallEvent.ERROR, this._handleError); | ||
@@ -324,3 +330,2 @@ this._tuiCallEngine.off(TUICallEvent.INVITED, this._handleNewInvitationReceived); | ||
this._tuiCallEngine.off(TUICallEvent.USER_LEAVE, this._handleUserLeave); | ||
// this._tuiCallEngine.off(TUICallEvent.USER_UPDATE, this.handleUserUpdate); // TODO: 小程序抛出该事件意义 | ||
this._tuiCallEngine.off(TUICallEvent.REJECT, this._handleInviteeReject); | ||
@@ -330,25 +335,33 @@ this._tuiCallEngine.off(TUICallEvent.NO_RESP, this._handleNoResponse); | ||
this._tuiCallEngine.off(TUICallEvent.CALLING_CANCEL, this._handleCallingCancel); | ||
this._tuiCallEngine.off(TUICallEvent.CALL_END, this._handleCallingEnd); | ||
this._tuiCallEngine.off(TUICallEvent.SDK_READY, this._handleSDKReady); | ||
this._tuiCallEngine.off(TUICallEvent.KICKED_OUT, this._handleKickedOut); | ||
this._tuiCallEngine.off(TUICallEvent.MESSAGE_SENT_BY_ME, this._messageSentByMe); | ||
this._tuiCallEngine.off(TUICallEvent.CALLING_END, this._handleCallingEnd); | ||
this._tuiCallEngine.off(TUICallEvent.CALL_TYPE_CHANGED, this._handleCallTypeChange); // TODO: web 是 CALL_TYPE_CHANGED 事件, miniProgram 为 CALL_MODE | ||
this._tuiCallEngine.off(TUICallEvent.USER_VIDEO_AVAILABLE, this._handleUserVideoAvailable); | ||
this._tuiCallEngine.off(TUICallEvent.USER_AUDIO_AVAILABLE, this._handleUserAudioAvailable); | ||
this._tuiCallEngine.off(TUICallEvent.MESSAGE_SENT_BY_ME, this._messageSentByMe); | ||
this._tuiCallEngine.off(TUICallEvent.USER_VOICE_VOLUME, this._handleUserVoiceVolume); // web | ||
} | ||
private _handleError(event: any): void { | ||
console.error(`${NAME.PREFIX}_handleError, error: ${JSON.stringify(event)}.`); | ||
const { code, message } = event || {}; | ||
const index = Object.values(ErrorCode).indexOf(code); | ||
let callTips = ''; | ||
if (index !== -1) { | ||
const key = Object.keys(ErrorCode)[index]; | ||
callTips = t(ErrorMessage[key]); | ||
callTips && TUIStore.update(StoreName.CALL, NAME.TOAST_INFO, { text: callTips, type: NAME.ERROR }); | ||
} | ||
console.error(`${NAME.PREFIX}_handleError, errorCode: ${code}; errorMessage: ${callTips || message}.`); | ||
} | ||
private async _handleNewInvitationReceived(event: any) { | ||
console.warn(`${NAME.PREFIX}onCallReceived event data: ${JSON.stringify(event)}.`); | ||
const { sponsor = '', isFromGroup, callMediaType, inviteData = {}, userIDList = [] } = event || event.data || {}; | ||
console.log(`${NAME.PREFIX}onCallReceived event data: ${JSON.stringify(event)}.`); | ||
const { sponsor = '', isFromGroup, callMediaType, inviteData = {}, calleeIdList = [] } = this._analyzeEventData(event); | ||
const currentUserInfo: IUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO); | ||
const remoteUserIdList: string[] = [sponsor, ...userIDList.filter((userId: string) => userId !== currentUserInfo.userId)]; | ||
const remoteUserIdList: string[] = [sponsor, ...calleeIdList.filter((userId: string) => userId !== currentUserInfo.userId)]; | ||
const type = callMediaType || inviteData.callType; | ||
const callTipsKey = type === CallMediaType.AUDIO ? CallTips.CALLEE_CALLING_AUDIO_MSG : CallTips.CALLEE_CALLING_VIDEO_MSG; | ||
const updateStoreParams = { | ||
let updateStoreParams = { | ||
[NAME.CALL_ROLE]: CallRole.CALLEE, | ||
[NAME.IS_GROUP]: isFromGroup, | ||
[NAME.CALL_STATUS]: CallStatus.CALLING, | ||
[NAME.CALL_ROLE]: CallRole.CALLEE, | ||
[NAME.CALL_MEDIA_TYPE]: type, | ||
@@ -374,7 +387,7 @@ [NAME.CALL_TIPS]: t(callTipsKey), | ||
this._callerChangeToConnected(); | ||
console.warn(`${NAME.PREFIX}accept event data: ${JSON.stringify(event)}.`); | ||
console.log(`${NAME.PREFIX}accept event data: ${JSON.stringify(event)}.`); | ||
} | ||
private _handleUserEnter(event: any): void { | ||
this._callerChangeToConnected(); | ||
const { userID: userId } = event; | ||
const { userID: userId, data } = this._analyzeEventData(event); | ||
let remoteUserInfoList = TUIStore.getData(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST); | ||
@@ -386,3 +399,3 @@ remoteUserInfoList = remoteUserInfoList.map((obj: IUserInfo) => { | ||
remoteUserInfoList.length > 0 && TUIStore.update(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList); | ||
console.warn(`${NAME.PREFIX}userEnter event data: ${JSON.stringify(event)}.`); | ||
console.log(`${NAME.PREFIX}userEnter event data: ${JSON.stringify(event)}.`); | ||
} | ||
@@ -398,11 +411,12 @@ private _callerChangeToConnected() { | ||
private _handleUserLeave(event: any): void { | ||
console.warn(`${NAME.PREFIX}userLeave event data: ${JSON.stringify(event)}.`); | ||
console.log(`${NAME.PREFIX}userLeave event data: ${JSON.stringify(event)}.`); | ||
const { data, userID: userId } = this._analyzeEventData(event); | ||
if (TUIStore.getData(StoreName.CALL, NAME.IS_GROUP)) { | ||
const text = this._generateText(CallTips.END_CALL, event.userID); | ||
const text = this._generateText(CallTips.END_CALL, userId); | ||
TUIStore.update(StoreName.CALL, NAME.TOAST_INFO, { text }); | ||
} | ||
event.userID && this._deleteRemoteUser([event.userID]); | ||
userId && this._deleteRemoteUser([userId]); | ||
} | ||
private _unNormalEventsManager(event: any, eventName: TUICallEvent): void { | ||
console.warn(`${NAME.PREFIX}${eventName} event data: ${JSON.stringify(event)}.`); | ||
console.log(`${NAME.PREFIX}${eventName} event data: ${JSON.stringify(event)}.`); | ||
const isGroup = TUIStore.getData(StoreName.CALL, NAME.IS_GROUP); | ||
@@ -412,3 +426,3 @@ switch(eventName) { | ||
case TUICallEvent.LINE_BUSY: { | ||
const { userID: userId } = event; | ||
const { userID: userId } = this._analyzeEventData(event); | ||
let callTipsKey = eventName === TUICallEvent.REJECT ? CallTips.OTHER_SIDE_REJECT_CALL : CallTips.OTHER_SIDE_LINE_BUSY; | ||
@@ -425,3 +439,3 @@ let text = this._generateText(callTipsKey); | ||
case TUICallEvent.NO_RESP: { | ||
const { userIDList = [] } = event; | ||
const { userIDList = [] } = this._analyzeEventData(event); | ||
const callTipsKey = isGroup ? CallTips.TIMEOUT : CallTips.CALL_TIMEOUT; | ||
@@ -454,3 +468,3 @@ const text = isGroup ? this._generateText(callTipsKey, userIDList.join()) : this._generateText(callTipsKey); | ||
private _handleCallingEnd(event: any): void { | ||
console.warn(`${NAME.PREFIX}callEnd event data: ${JSON.stringify(event)}.`); | ||
console.log(`${NAME.PREFIX}callEnd event data: ${JSON.stringify(event)}.`); | ||
this._executeExternalAfterCalling(); | ||
@@ -466,3 +480,3 @@ this._resetCallStore() | ||
private _handleKickedOut(event: any): void { | ||
console.warn(`${NAME.PREFIX}kickOut event data: ${JSON.stringify(event)}.`); | ||
console.log(`${NAME.PREFIX}kickOut event data: ${JSON.stringify(event)}.`); | ||
this.kickedOut && this.kickedOut(event); | ||
@@ -473,7 +487,12 @@ TUIStore.update(StoreName.CALL, NAME.CALL_TIPS, this._generateText(CallTips.KICK_OUT)); | ||
private _handleCallTypeChange(event: any): void { | ||
const { newCallType } = event; | ||
TUIStore.update(StoreName.CALL, NAME.CALL_MEDIA_TYPE, newCallType); | ||
const { newCallType , type } = this._analyzeEventData(event); | ||
TUIStore.update(StoreName.CALL, NAME.CALL_MEDIA_TYPE, newCallType || type); | ||
} | ||
private _messageSentByMe(event: any): void { | ||
const message = event?.data; | ||
this.onMessageSentByMe && this.onMessageSentByMe(message); | ||
} | ||
// =============================【 WEB 私有事件】============================== | ||
private async _handleUserVideoAvailable(event: any): Promise<any> { | ||
const { userID: userId, isVideoAvailable } = event; | ||
const { userID: userId, isVideoAvailable } = this._analyzeEventData(event); | ||
console.log(`${NAME.PREFIX}_handleUserVideoAvailable event data: ${JSON.stringify(event)}.`); | ||
@@ -484,13 +503,9 @@ isVideoAvailable && await this._startRemoteView(userId); | ||
private _handleUserAudioAvailable(event: any): void { | ||
const { userID: userId, isAudioAvailable } = event; | ||
const { userID: userId, isAudioAvailable } = this._analyzeEventData(event); | ||
console.log(`${NAME.PREFIX}_handleUserAudioAvailable event data: ${JSON.stringify(event)}.`); | ||
this._setRemoteUserInfoAudioVideoAvailable(isAudioAvailable, NAME.AUDIO, userId); | ||
} | ||
private _messageSentByMe(event: any): void { | ||
const message = event?.data; | ||
this.onMessageSentByMe && this.onMessageSentByMe(message); | ||
} | ||
private _handleUserVoiceVolume(event: any): void { | ||
try { | ||
const { volumeMap: volumeList } = event; | ||
const { volumeMap: volumeList } = this._analyzeEventData(event); | ||
if ((volumeList || []).length === 0) return; // 减少不必要的更新 | ||
@@ -518,5 +533,8 @@ let localUserInfo: IUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO); | ||
TUIStore.updateStore(updateStoreParams, StoreName.CALL); | ||
} catch (error) {} | ||
} catch (error) { | ||
console.debug(error); | ||
} | ||
} | ||
// =======================【原 Web CallKit 提供的方法】======================= | ||
// ==========================【 miniProgram 私有事件】========================== | ||
// ========================【原 Web CallKit 提供的方法】======================== | ||
public beforeCalling: ((...args: any[]) => void) | undefined; // 原来 | ||
@@ -544,8 +562,8 @@ public afterCalling: ((...args: any[]) => void) | undefined; | ||
private _executeExternalBeforeCalling(): void { | ||
this.beforeCalling && this.beforeCalling(); // ref: https://tapd.woa.com/TerWebG/prong/stories/view/1020396022885604991 | ||
this.beforeCalling && this.beforeCalling(); | ||
} | ||
private _executeExternalAfterCalling(): void { | ||
this.afterCalling && this.afterCalling(); // ref: https://tapd.woa.com/TerWebG/prong/stories/view/1020396022885604991 | ||
this.afterCalling && this.afterCalling(); | ||
} | ||
// =========================【TUICallKit 组件属性设置方法】======================== | ||
// ========================【TUICallKit 组件属性设置方法】======================== | ||
public setVideoDisplayMode(displayMode: VideoDisplayMode) { | ||
@@ -563,4 +581,3 @@ TUIStore.update(StoreName.CALL, NAME.DISPLAY_MODE, displayMode); | ||
} | ||
// ==============================【私有公共方法】============================== | ||
// web, miniProgram not | ||
// =============================【 WEB 私有公共方法】============================= | ||
private async _startRemoteView(userId: string) { | ||
@@ -582,6 +599,21 @@ if (!userId) { | ||
} | ||
private _setRemoteUserInfoAudioVideoAvailable(isAvailable: boolean, type: string, userId: string) { | ||
let remoteUserInfoList = TUIStore.getData(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST); | ||
remoteUserInfoList = remoteUserInfoList.map((obj: IUserInfo) => { | ||
if (obj.userId === userId) { | ||
if (type === NAME.AUDIO) { | ||
return { ...obj, isAudioAvailable: isAvailable }; | ||
} | ||
if (type === NAME.VIDEO) { | ||
return { ...obj, isVideoAvailable: isAvailable }; | ||
} | ||
} | ||
return obj; | ||
}); | ||
remoteUserInfoList.length > 0 && TUIStore.update(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList); | ||
} | ||
private async _getMyProfile(myselfUserId: string): Promise<IUserInfo> { | ||
const localUserInfo: IUserInfo = setDefaultUserInfo(myselfUserId, NAME.LOCAL_VIDEO); | ||
try { | ||
const tim = this._tuiCallEngine.tim; | ||
const tim = this.getTim(); | ||
if (!tim) return localUserInfo; | ||
@@ -606,3 +638,3 @@ const res = await tim.getMyProfile(); | ||
try { | ||
const tim = this._tuiCallEngine.tim; | ||
const tim = this.getTim(); | ||
if (!tim) return remoteUserInfoList; | ||
@@ -636,19 +668,4 @@ const res = await tim.getUserProfile({ userIDList: userIdList }); | ||
} | ||
private _setRemoteUserInfoAudioVideoAvailable(isAvailable: boolean, type: string, userId: string) { | ||
let remoteUserInfoList = TUIStore.getData(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST); | ||
remoteUserInfoList = remoteUserInfoList.map((obj: IUserInfo) => { | ||
if (obj.userId === userId) { | ||
if (type === NAME.AUDIO) { | ||
return { ...obj, isAudioAvailable: isAvailable }; | ||
} | ||
if (type === NAME.VIDEO) { | ||
return { ...obj, isVideoAvailable: isAvailable }; | ||
} | ||
} | ||
return obj; | ||
}); | ||
remoteUserInfoList.length > 0 && TUIStore.update(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList); | ||
} | ||
private _updateCallStoreBeforeCall(type: number, remoteUserInfoList: IUserInfo[], groupID?: string): void { | ||
const updateStoreParams = { | ||
private async _updateCallStoreBeforeCall(type: number, remoteUserInfoList: IUserInfo[], groupID?: string): void { | ||
let updateStoreParams: any = { | ||
[NAME.CALL_MEDIA_TYPE]: type, | ||
@@ -666,14 +683,27 @@ [NAME.CALL_ROLE]: CallRole.CALLER, | ||
} | ||
private async _updateCallStoreAfterCall(userIdList: string[]) { | ||
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true); | ||
this._setLocalUserInfoAudioVideoAvailable(true, NAME.AUDIO); // 呼叫默认是打开 audio 的 | ||
const remoteUserInfoList = await this._getRemoteUserProfile(userIdList); | ||
remoteUserInfoList.length > 0 && TUIStore.update(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList); | ||
try { | ||
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION)); | ||
} catch (error) { | ||
console.warn(`${NAME.PREFIX}setVideoQuality failed, error: ${JSON.stringify(error)}.`); | ||
private async _updateCallStoreAfterCall(userIdList: string[], response: any) { | ||
if (response) { | ||
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true); | ||
if (response.code === 0) { | ||
const callMediaType = TUIStore.getData(StoreName.CALL, NAME.CALL_MEDIA_TYPE); | ||
(callMediaType === CallMediaType.VIDEO) && await this.openCamera(NAME.LOCAL_VIDEO); | ||
try { | ||
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION)); | ||
} catch (error) { | ||
console.warn(`${NAME.PREFIX}setVideoQuality failed, error: ${JSON.stringify(error)}.`); | ||
} | ||
} else { | ||
this._resetCallStore(); | ||
return; | ||
} | ||
const localUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO); | ||
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { ...localUserInfo, isEnter: true }); | ||
this._setLocalUserInfoAudioVideoAvailable(true, NAME.AUDIO); // web && mini, default open audio | ||
const remoteUserInfoList = await this._getRemoteUserProfile(userIdList); | ||
remoteUserInfoList.length > 0 && TUIStore.update(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST, remoteUserInfoList); | ||
} else { | ||
this._resetCallStore(); | ||
} | ||
} | ||
// ref: https://tapd.woa.com/TerWebG/prong/stories/view/1020396022885485083 | ||
// 生成弹框提示文案 | ||
private _generateText(key: string, prefix?: string, suffix?: string): string { | ||
@@ -706,4 +736,6 @@ let callTips = `${t(key)}`; | ||
this._stopTimer(); | ||
// localUserInfo, language 在通话结束后不需要清除, callStatus 清除需要通知, isGroup 也不清除(engine 先抛 cancel 事件, 再抛 reject 事件) | ||
// displayMode、videoResolution 也不能清除, 组件不卸载, 这些属性也需保留, 否则采用默认值. ref: https://tapd.woa.com/10155901/bugtrace/bugs/view?bug_id=1010155901114183539 | ||
// localUserInfo, language 在通话结束后不需要清除 | ||
// callStatus 清除需要通知; isMinimized 也需要通知(basic-vue3 中切小窗关闭后, 再呼叫还是小窗, 因此需要通知到组件侧) | ||
// isGroup 也不清除(engine 先抛 cancel 事件, 再抛 reject 事件) | ||
// displayMode、videoResolution 也不能清除, 组件不卸载, 这些属性也需保留, 否则采用默认值. | ||
let notResetOrNotifyKeys = Object.keys(CALL_DATA_KEY).filter(key => { | ||
@@ -726,9 +758,10 @@ switch (CALL_DATA_KEY[key]) { | ||
TUIStore.reset(StoreName.CALL, notResetOrNotifyKeys); | ||
TUIStore.reset(StoreName.CALL, [NAME.CALL_STATUS], true); // callStatus reset need notify | ||
const callStatus = TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS); | ||
callStatus !== CallStatus.IDLE && TUIStore.reset(StoreName.CALL, [NAME.CALL_STATUS], true); // callStatus reset need notify | ||
TUIStore.reset(StoreName.CALL, [NAME.IS_MINIMIZED], true); // isMinimized reset need notify | ||
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { | ||
...TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO), | ||
isVideoAvailable: false, | ||
isAudioAvailable: false, | ||
isVideoAvailable: false, | ||
}); | ||
TUIStore.reset(StoreName.CALL, [NAME.CAMERA_STATUS], true); | ||
const newStatusStr = this._generateStatusChangeText(); | ||
@@ -778,2 +811,5 @@ if (oldStatusStr !== newStatusStr) { | ||
} | ||
private _analyzeEventData(event: any): any { | ||
return event || {}; // web INVITED | ||
} | ||
// =========================【监听 TUIStore 中的状态】========================= | ||
@@ -783,7 +819,10 @@ private _handleCallStatusChange = async (value: CallStatus) => { | ||
const callRole = TUIStore.getData(StoreName.CALL, NAME.CALL_ROLE); | ||
const musicFilePath = callRole === CallRole.CALLER ? INVITER_BELL_FILEPATH : INVITEE_BELL_FILEPATH; | ||
this?._callingBell?.setBellSrc(musicFilePath); | ||
this?._callingBell?.play(); | ||
const bellFilePath = callRole === CallRole.CALLEE ? this._bellFilePath : DEFAULT_CALLER_BELL_FILEPATH; | ||
await this?.setCallingBell(bellFilePath); | ||
if (TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS) === CallStatus.CALLING) { | ||
// 连续两个异步请求,会导致 play 和 stop 的调用顺序混乱,因此再多加一次状态判断 | ||
await this?._callingBell?.play(); | ||
} | ||
} else { | ||
this?._callingBell?.stop(); | ||
await this?._callingBell?.stop(); | ||
// 状态变更通知 | ||
@@ -798,3 +837,3 @@ if (value === CallStatus.CONNECTED) { | ||
private _watchTUIStore() { | ||
TUIStore.watch(StoreName.CALL, { | ||
TUIStore?.watch(StoreName.CALL, { | ||
[NAME.CALL_STATUS]: this._handleCallStatusChange, | ||
@@ -804,3 +843,3 @@ }); | ||
private _unwatchTUIStore() { | ||
TUIStore.unwatch(StoreName.CALL, { | ||
TUIStore?.unwatch(StoreName.CALL, { | ||
[NAME.CALL_STATUS]: this._handleCallStatusChange, | ||
@@ -812,3 +851,3 @@ }); | ||
this._TUICore = TUICore; | ||
} | ||
} | ||
} |
import { CallMediaType, CallStatus, NAME } from '../const'; | ||
const wx: any = {}; | ||
export function initialUI() { | ||
// 收起键盘 | ||
wx.hideKeyboard(); | ||
// 隐藏 tabBar | ||
// if (shouldHideTabBar) { | ||
// wx.hideTabBar(); | ||
// } | ||
wx.hideKeyboard({ | ||
complete: res => {}, | ||
}); | ||
}; | ||
// 检测运行时环境, 当是微信开发者工具时, 提示用户需要手机调试 | ||
@@ -17,3 +13,3 @@ export function checkRunPlatform() { | ||
if (systemInfo.platform === 'devtools') { | ||
// 当前运行在微信开发者工具里 | ||
// 当前运行在微信开发者工具里 | ||
wx.showModal({ | ||
@@ -27,7 +23,9 @@ icon: 'none', | ||
}; | ||
export function initAndCheckRunEnv() { | ||
initialUI(); // miniProgram 收起键盘, 隐藏 tabBar | ||
checkRunPlatform() // miniProgram 检测运行时环境 | ||
} | ||
export async function beforeCall(type: CallMediaType, that: any) { | ||
try { | ||
initialUI(); // miniProgram 收起键盘, 隐藏 tabBar | ||
checkRunPlatform() // miniProgram 检测运行时环境 | ||
initAndCheckRunEnv(); | ||
// 检查设备权限 | ||
@@ -41,2 +39,3 @@ const deviceMap = { | ||
} catch (error) { | ||
console.debug(error); | ||
return CallStatus.IDLE; | ||
@@ -61,2 +60,3 @@ } | ||
} catch (e) { | ||
console.debug(e); | ||
console.warn(`${NAME.PREFIX}setCallingBell: 媒体铃声路径错误`, filePath); | ||
@@ -93,5 +93,5 @@ } | ||
} | ||
destroyInstance() { | ||
destroy() { | ||
this.context.destroy(); | ||
} | ||
} |
@@ -1,12 +0,4 @@ | ||
export * from './callMediaType'; | ||
export * from './callStatus'; | ||
export * from './errorCode'; | ||
export * from './errorMsg'; | ||
export * from './storeName'; | ||
export * from './callRole'; | ||
export * from './language'; | ||
export * from './logLevel'; | ||
export * from './videoDisplayMode'; | ||
export * from './videoResolution'; | ||
export * from './statusChange'; | ||
export * from './call'; | ||
export * from './error'; | ||
export * from './log'; | ||
@@ -33,3 +25,5 @@ // import { keys } from 'ts-transformer-keys'; | ||
VIDEO_RESOLUTION: 'videoResolution', | ||
CAMERA_STATUS: 'cameraStatus', | ||
PUSHER: 'pusher', | ||
PLAYER: 'player', | ||
IS_EAR_PHONE: 'isEarPhone', | ||
}; | ||
@@ -53,8 +47,8 @@ | ||
FUNCTION: 'function', | ||
ALL: 'all', | ||
MYSELF: 'myself', | ||
...CALL_DATA_KEY, | ||
}; | ||
export enum DEVICE_STATUS { | ||
OPEN = 'open', | ||
CLOSE = 'close', | ||
}; | ||
export const AudioCallIcon = 'https://web.sdk.qcloud.com/component/TUIKit/assets/call.png'; | ||
export const VideoCallIcon = 'https://web.sdk.qcloud.com/component/TUIKit/assets/call-video-reverse.svg'; |
@@ -7,3 +7,3 @@ import { ITUIGlobal } from './interface/ITUIGlobal'; | ||
import TUICallService from './CallService'; | ||
import { NAME, CallRole, CallMediaType, CallStatus, StatusChange, VideoResolution, VideoDisplayMode } from './const'; | ||
import { NAME, CallRole, CallMediaType, CallStatus, StatusChange, VideoResolution, VideoDisplayMode, AudioPlayBackDevice } from './const'; | ||
import { t } from './locales'; | ||
@@ -16,10 +16,2 @@ | ||
// 输出 service 方法参数和 model 声明文件 | ||
// export * from './type'; | ||
// export * from './interface/model'; | ||
// TODO: 发布时, 下面的进行删除, 调式使用 | ||
(window as any).$TUIStore = tuiStore; | ||
(window as any).$TUIGlobal = tuiGlobal; | ||
// 输出产物 | ||
@@ -38,3 +30,4 @@ export { | ||
VideoDisplayMode, | ||
AudioPlayBackDevice, | ||
t, | ||
}; |
@@ -45,6 +45,6 @@ /** | ||
avatar?: string; | ||
isAudioAvailable?: boolean; | ||
isVideoAvailable?: boolean; | ||
isAudioAvailable?: boolean; // 用来设置: 麦克风是否打开 | ||
isVideoAvailable?: boolean; // 用来设置: 摄像头是否打开 | ||
volume?: number; | ||
isEnter?: boolean; | ||
isEnter?: boolean; // 远端用户, 用来控制预览远端是否显示 loading 效果; 本地用户, 用来控制 "呼叫"、"接通" 接通后显示的 loading 效果 | ||
domId?: string; // 播放流 dom 节点, localUserInfo 的 domId = 'localVideo'; remoteUserInfo 的 domId 就是 userId | ||
@@ -51,0 +51,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { CallStatus, CallRole, CallMediaType, VideoDisplayMode, VideoResolution, DEVICE_STATUS } from '../const'; | ||
import { CallStatus, CallRole, CallMediaType, VideoDisplayMode, VideoResolution } from '../const'; | ||
import { IUserInfo } from './index'; | ||
@@ -12,5 +12,7 @@ | ||
callMediaType: CallMediaType; // 通话类型 | ||
localUserInfo: IUserInfo; // 自己的信息, 默认: {} | ||
localUserInfo: IUserInfo; // 自己的信息, 默认: { userId: '' } | ||
remoteUserInfoList: Array<IUserInfo>; // 远端用户信息列表, 默认: [] | ||
callerUserInfo: IUserInfo; // 添加原因: https://tapd.woa.com/TerWebG/prong/stories/view/1020396022885976377 | ||
// 被叫在未接通时,展示主叫的 userId、头像。但是如果主叫进入通话后再挂断,此时被叫无法知道主叫的信息了。 | ||
// 因为目前 store 中仅提供了 remoteUserInfoList 数据,主叫离开后,被叫就没有主叫的信息了。因此考虑在 store 中增加 callerUserInfo 字段。 | ||
callerUserInfo: IUserInfo; | ||
isGroup: boolean; // 是否是群组通话, 默认: false | ||
@@ -26,4 +28,6 @@ callDuration: string; // 通话时长, 默认: '00:00:00' | ||
videoResolution: VideoResolution; // 设置视频分辨率, 默认: VideoResolution.RESOLUTION_480P | ||
// 摄像头开关状态 | ||
cameraStatus: DEVICE_STATUS; | ||
// 小程序相关属性 | ||
pusher: any; | ||
player: any[]; | ||
isEarPhone: boolean; // 是否是听筒, 默认: false | ||
} |
@@ -22,2 +22,4 @@ import { StoreName } from '../const'; | ||
* @param {IOptions} options UI 组件注册的监听信息 | ||
* @param {Object} params 扩展参数 | ||
* @param {String} params.notifyRangeWhenWatch 注册时监听时的通知范围 | ||
* @example | ||
@@ -32,3 +34,3 @@ * // UI 层监听会话列表更新通知 | ||
*/ | ||
watch(storeName: StoreName, options: IOptions): void; | ||
watch(storeName: StoreName, options: IOptions, params?: any): void; | ||
@@ -35,0 +37,0 @@ /** |
@@ -61,4 +61,6 @@ export const en = { | ||
'environment-detection-failed': 'Failed to check the environment', | ||
'call-failed': 'call method failed', | ||
'switchToAudioCall-call-failed': 'switch to audio call method failed', | ||
'switchToVideoCall-call-failed': 'switch to video call method failed', | ||
'microphone-unavailable': 'No mic found', | ||
'camera-unavailable': 'No camera found', | ||
'ban-device': 'Device access denied', | ||
@@ -65,0 +67,0 @@ 'not-supported-webrtc': 'Your current environment does not support WebRTC', |
@@ -1,3 +0,1 @@ | ||
import { CallTips } from './index'; | ||
export const zh = { | ||
@@ -67,4 +65,6 @@ 'hangup': '挂断', | ||
'environment-detection-failed': '环境检测失败', | ||
'call-failed': '调用失败', | ||
'switchToAudioCall-call-failed': '切语音调用失败', | ||
'switchToVideoCall-call-failed': '切视频调用失败', | ||
'microphone-unavailable': '没有可用的麦克风设备', | ||
'camera-unavailable': '没有可用的摄像头设备', | ||
'ban-device': '用户禁止使用设备', | ||
@@ -77,3 +77,3 @@ 'not-supported-webrtc': '当前环境不支持 WebRTC', | ||
'accept-device-error': '接通失败,通话设备获取失败', | ||
'call-error': '发起通话失败' | ||
'call-error': '发起通话失败', | ||
} |
@@ -1,3 +0,4 @@ | ||
import { CallStatus, CallRole, CallMediaType, NAME, VideoDisplayMode, VideoResolution, DEVICE_STATUS } from '../const'; | ||
import { CallStatus, CallRole, CallMediaType, NAME, VideoDisplayMode, VideoResolution } from '../const'; | ||
import { ICallStore } from '../interface/ICallStore'; | ||
import { getLanguage } from '../utils/common-utils'; | ||
@@ -16,10 +17,12 @@ export default class CallStore { | ||
toastInfo: { text: '' }, // 远端用户挂断、拒绝、超时、忙线等的 toast 提示信息 | ||
isMinimized: false, | ||
language: 'zh-cn', // en, zh-cn | ||
isClickable: false, // 是否可点击, ref: https://tapd.woa.com/TerWebG/prong/stories/view/1020396022885692719 | ||
isMinimized: false, // 用来记录 web 是否是小窗模式 | ||
language: getLanguage(), // en, zh-cn | ||
isClickable: false, // 是否可点击, 用于按钮增加 loading 效果,不可点击 | ||
// TUICallKit 组件上的属性 | ||
displayMode: VideoDisplayMode.COVER, // 设置预览远端的画面显示模式 | ||
videoResolution: VideoResolution.RESOLUTION_480P, | ||
// 摄像头开关状态 | ||
cameraStatus: DEVICE_STATUS.CLOSE, | ||
// 小程序相关属性 | ||
pusher: {}, | ||
player: [], | ||
isEarPhone: false, // 是否是听筒, 默认: false | ||
}; | ||
@@ -26,0 +29,0 @@ public store: ICallStore = Object.assign({}, this.defaultStore);; |
@@ -33,4 +33,6 @@ import { ITUIStore, IOptions, Task } from '../interface/ITUIStore'; | ||
* @param {IOptions} options 监听信息 | ||
* @param {Object} params 扩展参数 | ||
* @param {String} params.notifyRangeWhenWatch 注册时监听时的通知范围, 'all' - 通知所有注册该 key 的监听; 'myself' - 通知本次注册该 key 的监听; 默认不通知 | ||
*/ | ||
watch(storeName: StoreName, options: IOptions) { | ||
watch(storeName: StoreName, options: IOptions, params?: any) { | ||
if (!this.task[storeName]) { | ||
@@ -46,4 +48,12 @@ this.task[storeName] = {}; | ||
watcher[key].set(callback, 1); | ||
// 注册监听后立即通知一次默认数据,避免UI层初始化调用 getData | ||
this.notify(storeName, key); | ||
const { notifyRangeWhenWatch } = params || {}; | ||
// 注册监听后, 通知所有注册该 key 的监听,使用 'all' 时要特别注意是否对其他地方的监听产生影响 | ||
if (notifyRangeWhenWatch === NAME.ALL) { | ||
this.notify(storeName, key); | ||
} | ||
// 注册监听后, 仅通知自己本次监听该 key 的数据 | ||
if (notifyRangeWhenWatch === NAME.MYSELF) { | ||
const data = this.getData(storeName, key); | ||
callback.call(this, data); | ||
} | ||
}); | ||
@@ -91,3 +101,2 @@ } | ||
const currentData = this.storeMap[storeName]['store'][key]; | ||
const te = this.getData(StoreName.CALL, key); | ||
if (currentData === data) return; | ||
@@ -94,0 +103,0 @@ } |
@@ -83,2 +83,3 @@ import { IUserInfo } from '../interface'; | ||
} catch (error) { | ||
console.debug(error); | ||
return false; | ||
@@ -197,1 +198,15 @@ } | ||
}; | ||
/* | ||
* 获取浏览器语言 | ||
* @export | ||
* @return {zh-cn | en} | ||
*/ | ||
export const getLanguage = () => { | ||
// @ts-ignore | ||
let lang = navigator?.language || navigator?.userLanguage || ''; | ||
lang = lang.substr(0, 2); | ||
return lang === 'zh' ? 'zh-cn' : 'en'; | ||
}; | ||
export function noop(e: any) {} |
@@ -40,3 +40,3 @@ // eslint-disable-next-line | ||
const USER_AGENT = IN_BROWSER && window && window.navigator && window.navigator.userAgent || ''; | ||
const USER_AGENT = IN_BROWSER && window && window.navigator && window.navigator.userAgent || '' | ||
const IS_ANDROID = /Android/i.test(USER_AGENT); | ||
@@ -43,0 +43,0 @@ const IS_WIN_PHONE = /(?:Windows Phone)/.test(USER_AGENT); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
876248
7361
126
1
54