@trtc/calls-uikit-react 4.4.3-beta.2 → 4.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/Components/assets/aiAssistant/desktop/subtitleSettings.svg +4 -0
- package/src/Components/assets/aiAssistant/mobile/close-aiAssistant.svg +7 -0
- package/src/Components/assets/aiAssistant/mobile/open-aiAssistant.svg +7 -0
- package/src/Components/assets/aiAssistant/mobile/subtitleSettings.svg +3 -0
- package/src/Components/components/base/CustomSelect/CustomSelect.scss +116 -0
- package/src/Components/components/base/CustomSelect/CustomSelect.tsx +96 -0
- package/src/Components/components/common/AIAssistant/AISubtitle.scss +109 -0
- package/src/Components/components/common/AIAssistant/AISubtitle.tsx +52 -66
- package/src/Components/components/common/AIAssistant/components/AITranscriberSwitchH5.tsx +39 -0
- package/src/Components/components/common/AIAssistant/components/AITranscriberSwitchPC.scss +46 -0
- package/src/Components/components/common/AIAssistant/components/AITranscriberSwitchPC.tsx +42 -0
- package/src/Components/components/common/AIAssistant/components/SubtitleContent.scss +67 -0
- package/src/Components/components/common/AIAssistant/components/SubtitleContent.tsx +134 -0
- package/src/Components/components/common/AIAssistant/components/SubtitleSettingsH5.scss +275 -0
- package/src/Components/components/common/AIAssistant/components/SubtitleSettingsH5.tsx +265 -0
- package/src/Components/components/common/AIAssistant/components/SubtitleSettingsPC.scss +98 -0
- package/src/Components/components/common/AIAssistant/components/SubtitleSettingsPC.tsx +198 -0
- package/src/Components/components/common/AIAssistant/components/index.ts +5 -0
- package/src/Components/components/common/AIAssistant/index.ts +3 -1
- package/src/Components/components/common/TopBar/h5/TopBarH5.tsx +11 -1
- package/src/Components/components/common/TopBar/pc/TopBarPC.module.scss +20 -0
- package/src/Components/components/common/TopBar/pc/TopBarPC.tsx +14 -9
- package/src/Components/components/common/UIKitModal/UIKitModal.tsx +250 -0
- package/src/Components/components/common/UIKitModal/UIKitModalState.ts +177 -0
- package/src/Components/components/common/UIKitModal/index.module.scss +176 -0
- package/src/Components/components/common/UIKitModal/index.ts +3 -0
- package/src/Components/hooks/index.ts +2 -0
- package/src/Components/hooks/useAIAssistant.ts +174 -0
- package/src/TUICallService/CallService/AIAssistant.ts +285 -39
- package/src/TUICallService/CallService/UIKitModal.ts +72 -6
- package/src/TUICallService/CallService/bellContext.ts +25 -2
- package/src/TUICallService/CallService/engineEventHandler.ts +6 -1
- package/src/TUICallService/CallService/index.ts +72 -39
- package/src/TUICallService/CallService/miniProgram.ts +0 -12
- package/src/TUICallService/TUIStore/callStore.ts +6 -1
- package/src/TUICallService/UIKitModal/UIKitModal.ts +117 -0
- package/src/TUICallService/UIKitModal/index.ts +2 -0
- package/src/TUICallService/UIKitModal/type.ts +15 -0
- package/src/TUICallService/const/index.ts +4 -0
- package/src/TUICallService/interface/ICallStore.ts +5 -0
- package/src/TUICallService/locales/en.ts +17 -1
- package/src/TUICallService/locales/ja_JP.ts +17 -1
- package/src/TUICallService/locales/zh-cn.ts +17 -1
- package/src/TUICallService/utils/common-utils.ts +1 -1
- package/src/index.ts +1 -1
- package/tuicall-uikit-react.es.js +4009 -3940
- package/tuicall-uikit-react.umd.js +8 -33
- package/types/Components/components/base/CustomSelect/CustomSelect.d.ts +15 -0
- package/types/Components/components/common/AIAssistant/AISubtitle.d.ts +1 -0
- package/types/Components/components/common/AIAssistant/components/AITranscriberSwitchH5.d.ts +3 -0
- package/types/Components/components/common/AIAssistant/components/AITranscriberSwitchPC.d.ts +4 -0
- package/types/Components/components/common/AIAssistant/components/SubtitleContent.d.ts +8 -0
- package/types/Components/components/common/AIAssistant/components/SubtitleSettingsH5.d.ts +13 -0
- package/types/Components/components/common/AIAssistant/components/SubtitleSettingsPC.d.ts +13 -0
- package/types/Components/components/common/AIAssistant/components/index.d.ts +5 -0
- package/types/Components/components/common/AIAssistant/index.d.ts +1 -0
- package/types/Components/components/common/UIKitModal/UIKitModal.d.ts +21 -0
- package/types/Components/components/common/UIKitModal/UIKitModalState.d.ts +27 -0
- package/types/Components/components/common/UIKitModal/index.d.ts +3 -0
- package/types/Components/hooks/index.d.ts +2 -1
- package/types/Components/hooks/useAIAssistant.d.ts +22 -0
- package/types/TUICallService/CallService/AIAssistant.d.ts +72 -15
- package/types/TUICallService/CallService/bellContext.d.ts +3 -0
- package/types/TUICallService/CallService/index.d.ts +4 -3
- package/types/TUICallService/CallService/miniProgram.d.ts +0 -1
- package/types/TUICallService/UIKitModal/UIKitModal.d.ts +4 -0
- package/types/TUICallService/UIKitModal/index.d.ts +2 -0
- package/types/TUICallService/UIKitModal/type.d.ts +13 -0
- package/types/TUICallService/interface/ICallStore.d.ts +4 -0
- package/types/TUICallService/locales/en.d.ts +15 -0
- package/types/TUICallService/locales/ja_JP.d.ts +15 -0
- package/types/TUICallService/locales/zh-cn.d.ts +15 -0
- package/src/TUICallService/utils/validate/validateStatus.ts +0 -26
- package/types/TUICallService/utils/validate/validateStatus.d.ts +0 -5
|
@@ -90,6 +90,9 @@ export default class EngineEventHandler {
|
|
|
90
90
|
const callStatus = TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS);
|
|
91
91
|
|
|
92
92
|
if (callStatus === CallStatus.CALLING && callRole === CallRole.CALLER) {
|
|
93
|
+
// iOS 优化:主叫状态变更时立即停止铃声
|
|
94
|
+
this._callService?._bellContext?.stop();
|
|
95
|
+
|
|
93
96
|
TUIStore.update(StoreName.CALL, NAME.CALL_STATUS, CallStatus.CONNECTED);
|
|
94
97
|
this._callService?.startTimer();
|
|
95
98
|
}
|
|
@@ -183,14 +186,16 @@ export default class EngineEventHandler {
|
|
|
183
186
|
}, StoreName.CALL);
|
|
184
187
|
}
|
|
185
188
|
private async _handleOnCallBegin(event: any): Promise<void> {
|
|
189
|
+
// iOS 优化:ON_CALL_BEGIN 事件时立即停止铃声
|
|
190
|
+
this._callService?._bellContext?.stop();
|
|
186
191
|
this._callerChangeToConnected();
|
|
187
192
|
TUIStore.update(StoreName.CALL, NAME.CALL_TIPS, { text: 'answered', duration: 2000 });
|
|
188
193
|
await this._callService.openMicrophone();
|
|
189
194
|
console.log(`${NAME.PREFIX}accept event data: ${JSON.stringify(event)}.`);
|
|
190
195
|
}
|
|
191
196
|
private async _handleUserEnter(event: any): Promise<void> {
|
|
192
|
-
this._callerChangeToConnected();
|
|
193
197
|
const { userID: userId, data } = analyzeEventData(event);
|
|
198
|
+
this._callerChangeToConnected();
|
|
194
199
|
await this._addUserToRemoteUserInfoList(userId);
|
|
195
200
|
let remoteUserInfoList = TUIStore.getData(StoreName.CALL, NAME.REMOTE_USER_INFO_LIST);
|
|
196
201
|
remoteUserInfoList = remoteUserInfoList.map((obj: IUserInfo) => {
|
|
@@ -22,20 +22,20 @@ import TuiGlobal from '../TUIGlobal/tuiGlobal';
|
|
|
22
22
|
import TuiStore from '../TUIStore/tuiStore';
|
|
23
23
|
import { UIDesign } from './UIDesign';
|
|
24
24
|
import ChatCombine from './chatCombine';
|
|
25
|
-
import { AIAssistant } from './AIAssistant';
|
|
26
25
|
import EngineEventHandler from './engineEventHandler';
|
|
27
26
|
const TUIGlobal: ITUIGlobal = TuiGlobal.getInstance();
|
|
28
27
|
const TUIStore: ITUIStore = TuiStore.getInstance();
|
|
29
28
|
const uiDesign = UIDesign.getInstance();
|
|
30
29
|
uiDesign.setTUIStore(TUIStore);
|
|
31
|
-
const
|
|
32
|
-
|
|
30
|
+
const version = '4.4.4';
|
|
31
|
+
import AIAssistant from './AIAssistant'; // 仅 web 支持 AI 实时字幕
|
|
33
32
|
const frameWork = 'react';
|
|
34
33
|
export { TUIGlobal, TUIStore, uiDesign };
|
|
35
34
|
|
|
36
35
|
export default class TUICallService {
|
|
37
36
|
static instance: TUICallService;
|
|
38
37
|
public _tuiCallEngine: any;
|
|
38
|
+
public _aiAssistant: any = null;
|
|
39
39
|
private _tim: any = null;
|
|
40
40
|
private _TUICore: any = null;
|
|
41
41
|
private _timerId: number = -1;
|
|
@@ -62,6 +62,7 @@ export default class TUICallService {
|
|
|
62
62
|
this._engineEventHandler = EngineEventHandler.getInstance({ callService: this });
|
|
63
63
|
|
|
64
64
|
this._chatCombine = ChatCombine.getInstance({ callService: this });
|
|
65
|
+
this._aiAssistant = AIAssistant.getInstance({ callService: this });
|
|
65
66
|
initBrowserCloseDetection(this.handleExceptionExit.bind(this));
|
|
66
67
|
}
|
|
67
68
|
static getInstance() {
|
|
@@ -115,15 +116,15 @@ export default class TUICallService {
|
|
|
115
116
|
});
|
|
116
117
|
uiDesign.setEngineInstance(this._tuiCallEngine);
|
|
117
118
|
this._addListenTuiCallEngineEvent();
|
|
118
|
-
this._bellContext
|
|
119
|
+
if (this._bellContext) {
|
|
120
|
+
this._bellContext?.destroy();
|
|
121
|
+
}
|
|
122
|
+
this._bellContext = new BellContext();
|
|
119
123
|
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { userId: userID });
|
|
120
124
|
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, { userId: userID });
|
|
121
125
|
uiDesign.updateViewBackgroundUserId('local');
|
|
122
|
-
|
|
123
|
-
aiAssistant.setEngineInstance(this._tuiCallEngine);
|
|
124
|
-
aiAssistant.setImInstance(this.getTim());
|
|
126
|
+
this._aiAssistant?.bindEvent();
|
|
125
127
|
|
|
126
|
-
this.enableAISubtitle(true);
|
|
127
128
|
await this._tuiCallEngine.login({ userID, userSig, assetsPath: '' }); // web && mini
|
|
128
129
|
const uiConfig = TUIStore.getData(StoreName.CALL, NAME.CUSTOM_UI_CONFIG);
|
|
129
130
|
// close auto play dialog
|
|
@@ -155,6 +156,8 @@ export default class TUICallService {
|
|
|
155
156
|
await this._tuiCallEngine.destroyInstance();
|
|
156
157
|
this._tuiCallEngine = null;
|
|
157
158
|
}
|
|
159
|
+
this._aiAssistant?.unbindEvent();
|
|
160
|
+
this._aiAssistant?.reset();
|
|
158
161
|
this._bellContext?.destroy();
|
|
159
162
|
this._bellContext = null;
|
|
160
163
|
} catch (error) {
|
|
@@ -187,6 +190,7 @@ export default class TUICallService {
|
|
|
187
190
|
public async calls(callsParams: ICallsParams) {
|
|
188
191
|
if (TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS) !== CallStatus.IDLE) return; // avoid double click when application stuck
|
|
189
192
|
try {
|
|
193
|
+
TUIStore.update(StoreName.CALL, NAME.PUSHER_ID, NAME.NEW_PUSHER);
|
|
190
194
|
const { userIDList, type, chatGroupID, offlinePushInfo } = callsParams;
|
|
191
195
|
if (TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS) !== CallStatus.IDLE) return;
|
|
192
196
|
const remoteUserInfoList = userIDList.map(userId => ({ userId }));
|
|
@@ -204,10 +208,7 @@ export default class TUICallService {
|
|
|
204
208
|
public async join(params) {
|
|
205
209
|
if (TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS) === CallStatus.CONNECTED) return; // avoid double click when application stuck
|
|
206
210
|
try {
|
|
207
|
-
|
|
208
|
-
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true);
|
|
209
|
-
this.startTimer();
|
|
210
|
-
|
|
211
|
+
TUIStore.update(StoreName.CALL, NAME.PUSHER_ID, NAME.NEW_PUSHER);
|
|
211
212
|
const updateStoreParams = {
|
|
212
213
|
[NAME.CALL_ROLE]: CallRole.CALLEE,
|
|
213
214
|
[NAME.IS_GROUP]: true,
|
|
@@ -216,6 +217,10 @@ export default class TUICallService {
|
|
|
216
217
|
};
|
|
217
218
|
TUIStore.updateStore(updateStoreParams, StoreName.CALL);
|
|
218
219
|
|
|
220
|
+
const response = await this._tuiCallEngine.join(params);
|
|
221
|
+
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true);
|
|
222
|
+
this.startTimer();
|
|
223
|
+
|
|
219
224
|
updateDeviceList(this._tuiCallEngine);;
|
|
220
225
|
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION));
|
|
221
226
|
const localUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO);
|
|
@@ -271,6 +276,16 @@ export default class TUICallService {
|
|
|
271
276
|
throw error;
|
|
272
277
|
}
|
|
273
278
|
}
|
|
279
|
+
public async enableAITranscriber(enable: boolean) {
|
|
280
|
+
try {
|
|
281
|
+
// Update store to control UI translation switch and translation area visibility
|
|
282
|
+
TUIStore.update(StoreName.CALL, NAME.IS_AI_TRANSCRIBER_ENABLED, enable);
|
|
283
|
+
console.log(`${NAME.PREFIX}enableAITranscriber: ${enable}.`);
|
|
284
|
+
} catch (error: any) {
|
|
285
|
+
console.error(`${NAME.PREFIX}enableAITranscriber failed, error: ${error}.`);
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
274
289
|
// 修改默认铃声:只支持本地铃声文件,不支持在线铃声文件;修改铃声修改的是被叫的铃声
|
|
275
290
|
public async setCallingBell(filePath?: string) {
|
|
276
291
|
let isCheckFileExist: boolean = true;
|
|
@@ -306,9 +321,7 @@ export default class TUICallService {
|
|
|
306
321
|
public setCameraDefaultState(isOpen: boolean) {
|
|
307
322
|
uiDesign.setCameraDefaultState(isOpen);
|
|
308
323
|
}
|
|
309
|
-
|
|
310
|
-
aiAssistant.enableAISubtitle(enable);
|
|
311
|
-
}
|
|
324
|
+
// AI Subtitle functionality removed, focusing on real-time transcriber
|
|
312
325
|
// =============================【实验性接口】=============================
|
|
313
326
|
public callExperimentalAPI(jsonStr: string) {
|
|
314
327
|
const jsonObj = JSON.parse(jsonStr);
|
|
@@ -343,19 +356,7 @@ export default class TUICallService {
|
|
|
343
356
|
TUIStore.update(StoreName.CALL, NAME.CALL_STATUS, CallStatus.CONNECTED);
|
|
344
357
|
updateDeviceList(this._tuiCallEngine);;
|
|
345
358
|
const response = await this._tuiCallEngine.accept();
|
|
346
|
-
|
|
347
|
-
this._chatCombine?.callTUIService({ message: response?.data?.message });
|
|
348
|
-
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true);
|
|
349
|
-
this.startTimer();
|
|
350
|
-
const callMediaType = TUIStore.getData(StoreName.CALL, NAME.CALL_MEDIA_TYPE);
|
|
351
|
-
const isCameraDefaultStateClose = this._getFeatureButtonDefaultState(FeatureButton.Camera) === ButtonState.Close;
|
|
352
|
-
(callMediaType === CallMediaType.VIDEO) && !isCameraDefaultStateClose && await this.openCamera(NAME.LOCAL_VIDEO);
|
|
353
|
-
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION));
|
|
354
|
-
const localUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO);
|
|
355
|
-
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { ...localUserInfo, isEnter: true });
|
|
356
|
-
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, { ...localUserInfo, isEnter: true });
|
|
357
|
-
setLocalUserInfoAudioVideoAvailable(true, NAME.AUDIO); // web && mini default open audio
|
|
358
|
-
}
|
|
359
|
+
await this._handleAcceptResponse(response);
|
|
359
360
|
} catch (error) {
|
|
360
361
|
this._tuiCallEngine?.reportLog?.({
|
|
361
362
|
name: 'TUICallKit.accept.fail',
|
|
@@ -368,6 +369,21 @@ export default class TUICallService {
|
|
|
368
369
|
this._resetCallStore();
|
|
369
370
|
}
|
|
370
371
|
}
|
|
372
|
+
private async _handleAcceptResponse(response) {
|
|
373
|
+
if (response) {
|
|
374
|
+
this._chatCombine?.callTUIService({ message: response?.data?.message });
|
|
375
|
+
TUIStore.update(StoreName.CALL, NAME.IS_CLICKABLE, true);
|
|
376
|
+
this.startTimer();
|
|
377
|
+
const callMediaType = TUIStore.getData(StoreName.CALL, NAME.CALL_MEDIA_TYPE);
|
|
378
|
+
const isCameraDefaultStateClose = this._getFeatureButtonDefaultState(FeatureButton.Camera) === ButtonState.Close;
|
|
379
|
+
(callMediaType === CallMediaType.VIDEO) && !isCameraDefaultStateClose && await this.openCamera(NAME.LOCAL_VIDEO);
|
|
380
|
+
await this._tuiCallEngine.setVideoQuality(TUIStore.getData(StoreName.CALL, NAME.VIDEO_RESOLUTION));
|
|
381
|
+
const localUserInfo = TUIStore.getData(StoreName.CALL, NAME.LOCAL_USER_INFO);
|
|
382
|
+
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, { ...localUserInfo, isEnter: true });
|
|
383
|
+
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN, { ...localUserInfo, isEnter: true });
|
|
384
|
+
setLocalUserInfoAudioVideoAvailable(true, NAME.AUDIO); // web && mini default open audio
|
|
385
|
+
}
|
|
386
|
+
}
|
|
371
387
|
@avoidRepeatedCall()
|
|
372
388
|
public async hangup() {
|
|
373
389
|
if (TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS) === CallStatus.IDLE) return; // avoid double click when application stuck
|
|
@@ -696,21 +712,29 @@ export default class TUICallService {
|
|
|
696
712
|
}
|
|
697
713
|
}
|
|
698
714
|
// clear all use avoidRepeatCall decorator state
|
|
699
|
-
private
|
|
700
|
-
this._tuiCallEngine?.reportLog?.({ name: 'TUICallkit.
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
(this as any)
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
715
|
+
private _cleanupAvoidRepeatCallState(methodName?: string) {
|
|
716
|
+
this._tuiCallEngine?.reportLog?.({ name: 'TUICallkit._cleanupAvoidRepeatCallState', data: { methodName } });
|
|
717
|
+
let methodsToClean = [];
|
|
718
|
+
if (methodName) {
|
|
719
|
+
methodsToClean = [(this as any)[methodName]];
|
|
720
|
+
} else {
|
|
721
|
+
methodsToClean = [
|
|
722
|
+
(this as any).calls,
|
|
723
|
+
(this as any).accept,
|
|
724
|
+
(this as any).hangup,
|
|
725
|
+
(this as any).reject,
|
|
726
|
+
(this as any).join,
|
|
727
|
+
(this as any).inviteUser,
|
|
728
|
+
];
|
|
729
|
+
}
|
|
707
730
|
|
|
708
|
-
methodsToClean
|
|
731
|
+
methodsToClean?.forEach(method => {
|
|
709
732
|
method?.clearCallState?.(this);
|
|
710
733
|
});
|
|
711
734
|
}
|
|
712
735
|
private _resetCallStore() {
|
|
713
|
-
this.
|
|
736
|
+
this._cleanupAvoidRepeatCallState();
|
|
737
|
+
this._bellContext?.stop();
|
|
714
738
|
|
|
715
739
|
const oldStatusStr = generateStatusChangeText();
|
|
716
740
|
this._stopTimer();
|
|
@@ -729,6 +753,7 @@ export default class TUICallService {
|
|
|
729
753
|
case NAME.ENABLE_FLOAT_WINDOW:
|
|
730
754
|
case NAME.LOCAL_USER_INFO:
|
|
731
755
|
case NAME.IS_SHOW_ENABLE_VIRTUAL_BACKGROUND:
|
|
756
|
+
case NAME.IS_AI_TRANSCRIBER_ENABLED:
|
|
732
757
|
case NAME.IS_FORCE_USE_V2_API:
|
|
733
758
|
case NAME.LOCAL_USER_INFO_EXCLUDE_VOLUMN: {
|
|
734
759
|
return false;
|
|
@@ -744,6 +769,7 @@ export default class TUICallService {
|
|
|
744
769
|
callStatus !== CallStatus.IDLE && TUIStore.reset(StoreName.CALL, [NAME.CALL_STATUS], true); // callStatus reset need notify
|
|
745
770
|
TUIStore.reset(StoreName.CALL, [NAME.IS_MINIMIZED], true); // isMinimized reset need notify
|
|
746
771
|
TUIStore.reset(StoreName.CALL, [NAME.IS_EAR_PHONE], true); // isEarPhone reset need notify
|
|
772
|
+
TUIStore.reset(StoreName.CALL, [NAME.PUSHER_ID], true); // pusher unload reset need notify
|
|
747
773
|
TUIStore.reset(StoreName.CALL, [NAME.ENABLE_VIRTUAL_BACKGROUND], true); // ENABLE_VIRTUAL_BACKGROUND reset need notify
|
|
748
774
|
TUIStore.reset(StoreName.CALL, [NAME.IS_MUTE_SPEAKER], true); // IS_MUTE_SPEAKER reset need notify
|
|
749
775
|
TUIStore.update(StoreName.CALL, NAME.LOCAL_USER_INFO, {
|
|
@@ -784,10 +810,17 @@ export default class TUICallService {
|
|
|
784
810
|
callRole: TUIStore.getData(StoreName.CALL, NAME.CALL_ROLE),
|
|
785
811
|
callStatus: TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS),
|
|
786
812
|
};
|
|
813
|
+
this._tuiCallEngine?.reportLog?.({
|
|
814
|
+
name: 'TUICallkit._handleCallStatusChange.start',
|
|
815
|
+
data: { bellParams }
|
|
816
|
+
});
|
|
787
817
|
this._bellContext.setBellProperties(bellParams);
|
|
788
818
|
if (value === CallStatus.CALLING) {
|
|
789
|
-
|
|
819
|
+
this?._bellContext?.play();
|
|
790
820
|
} else {
|
|
821
|
+
this._tuiCallEngine?.reportLog?.({
|
|
822
|
+
name: 'TUICallkit._bellContext.stop',
|
|
823
|
+
});
|
|
791
824
|
// 状态变更通知
|
|
792
825
|
if (value === CallStatus.CONNECTED) {
|
|
793
826
|
const isGroup = TUIStore.getData(StoreName.CALL, NAME.IS_GROUP);
|
|
@@ -41,18 +41,6 @@ export async function beforeCall(type: CallMediaType, that: any) {
|
|
|
41
41
|
return CallStatus.IDLE;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
// 套餐问题提示, 小程序最低需要群组通话版, 1v1 通话版本使用 TRTC 就会报错
|
|
45
|
-
export function handlePackageError(error) {
|
|
46
|
-
if (error?.code === -1002) {
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
wx.showModal({
|
|
49
|
-
icon: 'none',
|
|
50
|
-
title: 'error',
|
|
51
|
-
content: error?.message || '',
|
|
52
|
-
showCancel: false,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
44
|
|
|
57
45
|
export function handleNoPusherCapabilityError(){
|
|
58
46
|
// @ts-ignore
|
|
@@ -41,7 +41,7 @@ export default class CallStore {
|
|
|
41
41
|
pusher: {},
|
|
42
42
|
player: [],
|
|
43
43
|
isEarPhone: false, // 是否是听筒, 默认: false
|
|
44
|
-
pusherId:
|
|
44
|
+
pusherId: '', // 重新渲染 live-Pusher 的标识位
|
|
45
45
|
// 是否开启虚拟背景, 目前仅 web 支持
|
|
46
46
|
isShowEnableVirtualBackground: false, // 是否显示虚拟背景图标, 默认: false
|
|
47
47
|
enableVirtualBackground: false, // 是否开启虚拟背景, 默认: false
|
|
@@ -54,6 +54,11 @@ export default class CallStore {
|
|
|
54
54
|
// translate function
|
|
55
55
|
translate: t,
|
|
56
56
|
isForceUseV2API: false,
|
|
57
|
+
// AI Transcriber related fields
|
|
58
|
+
transcriberRobotId: null,
|
|
59
|
+
realtimeMessageList: [],
|
|
60
|
+
isAITranscriberEnabled: false,
|
|
61
|
+
isAITranscriberRunning: false,
|
|
57
62
|
};
|
|
58
63
|
public store: ICallStore = deepClone(this.defaultStore);
|
|
59
64
|
public prevStore: ICallStore = deepClone(this.defaultStore);
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import type { UIKitModalOptions, UIKitModalResult } from './type';
|
|
3
|
+
import TUICallKitServer from '../CallService';
|
|
4
|
+
|
|
5
|
+
const URL_REGEX = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/i;
|
|
6
|
+
const FULL_URL_REGEX = /(https?:\/\/[^\s]+)/g;
|
|
7
|
+
|
|
8
|
+
function isDevEnvironment(): boolean {
|
|
9
|
+
const accountInfo = uni.getAccountInfoSync?.();
|
|
10
|
+
const envVersion = accountInfo?.miniProgram?.envVersion;
|
|
11
|
+
return envVersion === 'develop' || envVersion === 'trial';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function extractUrlFromContent(content: string): string | null {
|
|
15
|
+
if (!content || typeof content !== 'string') {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (content.includes('<a ') || content.includes('<a>')) {
|
|
20
|
+
const hrefMatch = content.match(/href=["']([^"']+)["']/);
|
|
21
|
+
return hrefMatch ? hrefMatch[1] : null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (URL_REGEX.test(content.trim())) {
|
|
25
|
+
return content.trim();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const urlMatch = content.match(FULL_URL_REGEX);
|
|
29
|
+
return urlMatch ? urlMatch[0] : null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function processContent(content: string): string {
|
|
33
|
+
if (!content || typeof content !== 'string') {
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let text = content.replace(/<[^>]+>/g, '');
|
|
38
|
+
text = text
|
|
39
|
+
.replace(/ /g, ' ')
|
|
40
|
+
.replace(/</g, '<')
|
|
41
|
+
.replace(/>/g, '>')
|
|
42
|
+
.replace(/&/g, '&')
|
|
43
|
+
.replace(/"/g, '"');
|
|
44
|
+
text = text.replace(/\s+/g, ' ').trim();
|
|
45
|
+
|
|
46
|
+
const url = extractUrlFromContent(content);
|
|
47
|
+
if (url && !text.includes(url)) {
|
|
48
|
+
return text ? `${text}\n${url}` : url;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return text;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function reportModalView(options: UIKitModalOptions): void {
|
|
55
|
+
try {
|
|
56
|
+
const tim = TUICallKitServer?.getTim?.();
|
|
57
|
+
if (tim && typeof tim.callExperimentalAPI === 'function') {
|
|
58
|
+
const reportData = {
|
|
59
|
+
id: options.id,
|
|
60
|
+
title: options.title,
|
|
61
|
+
type: options.type,
|
|
62
|
+
content: options.content,
|
|
63
|
+
platform: 'miniprogram',
|
|
64
|
+
};
|
|
65
|
+
tim.callExperimentalAPI('reportModalView', JSON.stringify(reportData));
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.warn('[UIKitModal] reportModalView failed:', error);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const createUIKitModal = (options: UIKitModalOptions): Promise<UIKitModalResult> => {
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
reportModalView(options);
|
|
75
|
+
|
|
76
|
+
if (!isDevEnvironment()) {
|
|
77
|
+
resolve({ action: 'confirm' });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const url = extractUrlFromContent(options.content);
|
|
82
|
+
const processedContent = processContent(options.content);
|
|
83
|
+
const hasLink = !!url;
|
|
84
|
+
|
|
85
|
+
uni.showModal({
|
|
86
|
+
title: options.title || '',
|
|
87
|
+
content: processedContent,
|
|
88
|
+
cancelText: '取消',
|
|
89
|
+
confirmText: hasLink ? '复制链接' : '确认',
|
|
90
|
+
success: (res) => {
|
|
91
|
+
const action = res.confirm ? 'confirm' : 'cancel';
|
|
92
|
+
if (res.confirm) {
|
|
93
|
+
if (hasLink && url) {
|
|
94
|
+
uni.setClipboardData({
|
|
95
|
+
data: url,
|
|
96
|
+
success: () => {
|
|
97
|
+
uni.showToast({ title: '链接已复制', icon: 'success' });
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
options.onConfirm?.();
|
|
102
|
+
} else {
|
|
103
|
+
options.onCancel?.();
|
|
104
|
+
}
|
|
105
|
+
resolve({ action, raw: res });
|
|
106
|
+
},
|
|
107
|
+
fail: () => {
|
|
108
|
+
options.onCancel?.();
|
|
109
|
+
resolve({ action: 'cancel' });
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const UIKitModal = {
|
|
116
|
+
openModal: (config: UIKitModalOptions) => createUIKitModal(config),
|
|
117
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ModalType = 'info' | 'warning' | 'error' | 'success';
|
|
2
|
+
|
|
3
|
+
export interface UIKitModalOptions {
|
|
4
|
+
id: number;
|
|
5
|
+
title: string;
|
|
6
|
+
content: string;
|
|
7
|
+
type: ModalType;
|
|
8
|
+
onConfirm?: () => void;
|
|
9
|
+
onCancel?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface UIKitModalResult {
|
|
13
|
+
action: 'confirm' | 'cancel';
|
|
14
|
+
raw?: any;
|
|
15
|
+
}
|
|
@@ -39,6 +39,10 @@ export const CALL_DATA_KEY: any = {
|
|
|
39
39
|
PUSHER_ID: 'pusherId',
|
|
40
40
|
IS_FORCE_USE_V2_API: 'isForceUseV2API',
|
|
41
41
|
MODAL_ERROR: 'modalError',
|
|
42
|
+
TRANSCRIBER_ROBOT_ID: 'transcriberRobotId',
|
|
43
|
+
REALTIME_MESSAGE_LIST: 'realtimeMessageList',
|
|
44
|
+
IS_AI_TRANSCRIBER_ENABLED: 'isAITranscriberEnabled', // Controls UI visibility
|
|
45
|
+
IS_AI_TRANSCRIBER_RUNNING: 'isAITranscriberRunning', // Controls AI transcriber running state
|
|
42
46
|
};
|
|
43
47
|
|
|
44
48
|
export const CHAT_DATA_KEY: any = {
|
|
@@ -52,4 +52,9 @@ export interface ICallStore {
|
|
|
52
52
|
// translate function
|
|
53
53
|
translate: Function,
|
|
54
54
|
isForceUseV2API: boolean, // 是否使用 call/groupCall 接口, 默认: false
|
|
55
|
+
// AI Transcriber related fields
|
|
56
|
+
transcriberRobotId: string | null, // AI 转写机器人 ID
|
|
57
|
+
realtimeMessageList: [], // 实时转写消息列表
|
|
58
|
+
isAITranscriberEnabled: boolean, // AI 转写UI是否显示
|
|
59
|
+
isAITranscriberRunning: boolean, // AI transcriber running state
|
|
55
60
|
}
|
|
@@ -135,7 +135,7 @@ export const en = {
|
|
|
135
135
|
'accept-device-error': 'Accept failed, unable to auth calling device',
|
|
136
136
|
'call-error': 'Start call failed',
|
|
137
137
|
// 错误提示
|
|
138
|
-
'error.10001': "Your application has not enabled audio/video call (TUICallKit) capability.
|
|
138
|
+
'error.10001': "Your application has not enabled audio/video call (TUICallKit) capability. For first-time use, you can go to <a href='https://cloud.tencent.com/document/product/647/104662'>Enable Service</a> to apply for a free trial, or purchase call capability packages: <a href='https://console.cloud.tencent.com/trtc'>Purchase Page</a>",
|
|
139
139
|
'error.10002': "You do not currently support using this capability. Please go to the <a href='https://buy.cloud.tencent.com/avc?addRavLicense=1&position=1600110000&ravLicenseType=1®ionId=1'>purchase page</a> to buy and activate it",
|
|
140
140
|
'error.10004': "Camera/microphone permission was denied. Please check browser settings to ensure camera and microphone access is allowed. If you have confirmed permission is granted, please go to <a href='https://web.sdk.qcloud.com/trtc/webrtc/demo/detect/index.html'>Audio/Video Capability Detection</a> to check if your device and environment support calls",
|
|
141
141
|
'error.10005': "No microphone device detected. Please ensure your device has a microphone connected and check if the microphone is available in system or browser settings.",
|
|
@@ -144,5 +144,21 @@ export const en = {
|
|
|
144
144
|
'error.10008': "TUICallEngine has not completed initialization or login. Please ensure you have successfully executed init or login operations before calling this function. Solution: <a href='https://cloud.tencent.com/document/product/647/78769#3a61f42b-e06f-49af-88bf-362d40025887'>View Documentation</a>",
|
|
145
145
|
'error.10012': "Detected that the current page is under HTTP protocol. To ensure smooth access and full functionality of TUICallEngine SDK for production environment users, please use HTTPS protocol (or localhost) to access the audio/video application page. For details, please visit: <a href='https://web.sdk.qcloud.com/trtc/webrtc/v5/doc/zh-cn/tutorial-05-info-browser.html#h2-3'>View Documentation</a>",
|
|
146
146
|
'error.10013': "Call failed: You have been blocked by the other party or you have blocked the other party",
|
|
147
|
+
'error.10014': "Call initiation failed. User ID is invalid. Please confirm that the user is registered.",
|
|
147
148
|
'error': 'Error',
|
|
149
|
+
// AI Subtitle Settings
|
|
150
|
+
'ai-subtitle': 'AI Subtitle',
|
|
151
|
+
'ai-subtitle-settings': 'AI Subtitle Settings',
|
|
152
|
+
'recognition-language': 'Recognition Language',
|
|
153
|
+
'translation-language': 'Translation Language',
|
|
154
|
+
'subtitle-display-settings': 'Subtitle Display Settings',
|
|
155
|
+
'subtitle-display-bilingual': 'Show Bilingual Subtitles',
|
|
156
|
+
'no-translation': 'No Translation',
|
|
157
|
+
'show-bilingual': 'Show Bilingual',
|
|
158
|
+
'show-original-only': 'Show Original Only',
|
|
159
|
+
'save': 'Save',
|
|
160
|
+
'select-recognition-language': 'Please select recognition language',
|
|
161
|
+
'select-translation-language': 'Please select translation language',
|
|
162
|
+
'confirm': 'Confirm',
|
|
163
|
+
'recognition-and-translation-settings': 'Recognition & Translation Settings',
|
|
148
164
|
};
|
|
@@ -134,7 +134,7 @@ export const ja_JP = {
|
|
|
134
134
|
'accept-device-error': '接続できませんでした。発信側デバイスを認証できません',
|
|
135
135
|
'call-error': '通話が開始できませんでした',
|
|
136
136
|
// 错误提示
|
|
137
|
-
'error.10001': "あなたのアプリケーションは音声・ビデオ通話(TUICallKit
|
|
137
|
+
'error.10001': "あなたのアプリケーションは音声・ビデオ通話(TUICallKit)機能を有効にしていません。初めてご利用の場合、<a href='https://cloud.tencent.com/document/product/647/104662'>サービスを有効にする</a>で無料体験を申請するか、通話機能パッケージを購入してください:<a href='https://console.cloud.tencent.com/trtc'>購入ページ</a>",
|
|
138
138
|
'error.10002': "現在この機能を使用することはできません。<a href='https://buy.cloud.tencent.com/avc?addRavLicense=1&position=1600110000&ravLicenseType=1®ionId=1'>購入ページ</a>で購入して有効にしてください",
|
|
139
139
|
'error.10004': "カメラ/マイクのアクセス許可が拒否されました。ブラウザ設定を確認し、カメラとマイクの使用が許可されていることを確認してください。許可されている場合は、<a href='https://web.sdk.qcloud.com/trtc/webrtc/demo/detect/index.html'>音声・ビデオ機能検出</a>にアクセスして、お使いのデバイスと環境が通話をサポートしているか確認してください",
|
|
140
140
|
'error.10005': "マイクデバイスが検出されませんでした。デバイスにマイクが接続されていることを確認し、システムまたはブラウザ設定でマイクが利用可能かどうかを確認してください。",
|
|
@@ -143,5 +143,21 @@ export const ja_JP = {
|
|
|
143
143
|
'error.10008': "TUICallEngineが初期化またはログインを完了していません。この機能を呼び出す前に、initまたはlogin操作が正常に実行されていることを確認してください。解決策:<a href='https://cloud.tencent.com/document/product/647/78769#3a61f42b-e06f-49af-88bf-362d40025887'>ドキュメントを確認</a>",
|
|
144
144
|
'error.10012': "現在のページがHTTPプロトコル下にあることが検出されました。本番環境のユーザーがTUICallEngine SDKの全機能をスムーズに利用できるようにするため、音声・ビデオアプリケーションページにはHTTPSプロトコル(またはlocalhost)を使用してアクセスしてください。詳細については、<a href='https://web.sdk.qcloud.com/trtc/webrtc/v5/doc/zh-cn/tutorial-05-info-browser.html#h2-3'>ドキュメントを確認</a>してください",
|
|
145
145
|
'error.10013': "通話失敗:相手にブロックされているか、または相手をブロックしています",
|
|
146
|
+
'error.10014': "通話の開始に失敗しました。ユーザーIDが無効です。ユーザーが登録されていることを確認してください。",
|
|
146
147
|
'error': 'エラー',
|
|
148
|
+
// AI Subtitle Settings
|
|
149
|
+
'ai-subtitle': 'AI字幕',
|
|
150
|
+
'ai-subtitle-settings': 'AI字幕設定',
|
|
151
|
+
'recognition-language': '認識言語',
|
|
152
|
+
'translation-language': '翻訳言語',
|
|
153
|
+
'subtitle-display-settings': '字幕表示設定',
|
|
154
|
+
'subtitle-display-bilingual': 'バイリンガル字幕を表示',
|
|
155
|
+
'no-translation': '翻訳しない',
|
|
156
|
+
'show-bilingual': 'バイリンガル表示',
|
|
157
|
+
'show-original-only': '原文のみ表示',
|
|
158
|
+
'save': '保存',
|
|
159
|
+
'select-recognition-language': '認識言語を選択してください',
|
|
160
|
+
'select-translation-language': '翻訳言語を選択してください',
|
|
161
|
+
'confirm': '確認',
|
|
162
|
+
'recognition-and-translation-settings': '認識と翻訳の設定',
|
|
147
163
|
};
|
|
@@ -130,7 +130,7 @@ export const zh = {
|
|
|
130
130
|
'accept-device-error': '接通失败,通话设备获取失败',
|
|
131
131
|
'call-error': '发起通话失败',
|
|
132
132
|
// 错误提示
|
|
133
|
-
'error.10001': "您的应用还未开通音视频通话(TUICallKit
|
|
133
|
+
'error.10001': "您的应用还未开通音视频通话(TUICallKit)能力,首次使用,您可以去<a href='https://cloud.tencent.com/document/product/647/104662'>开通服务</a>申请免费体验,或购买通话能力套餐包:<a href='https://console.cloud.tencent.com/trtc'>购买页面</a>",
|
|
134
134
|
'error.10002': "您暂不支持使用该能力,请前往<a href='https://buy.cloud.tencent.com/avc?addRavLicense=1&position=1600110000&ravLicenseType=1®ionId=1'>购买页</a>购买开通",
|
|
135
135
|
'error.10004': "摄像头/麦克风权限被拒绝,请检查浏览器设置,确保已允许使用您的摄像头和麦克风。如果您确认已授予权限,请前往<a href='https://web.sdk.qcloud.com/trtc/webrtc/demo/detect/index.html'>音视频能力检测</a>检查您的设备和环境是否支持通话",
|
|
136
136
|
'error.10005': "未检测到麦克风设备。请确保您的设备已连接麦克风,并检查系统或浏览器设置中麦克风是否可用。",
|
|
@@ -139,5 +139,21 @@ export const zh = {
|
|
|
139
139
|
'error.10008': "TUICallEngine 尚未完成初始化或登录。请确保在调用此功能前,已成功执行 init 或 login 操作。解决方案:<a href='https://cloud.tencent.com/document/product/647/78769#3a61f42b-e06f-49af-88bf-362d40025887'>查看文档</a>",
|
|
140
140
|
'error.10012': "检测到当前页面正处于 http 协议下,为确保生产环境用户顺畅接入和体验 TUICallEngine SDK 的全部功能,请使用 https 协议(或 localhost)访问音视频应用页面。详情请前往:<a href='https://web.sdk.qcloud.com/trtc/webrtc/v5/doc/zh-cn/tutorial-05-info-browser.html#h2-3'>查看文档</a>",
|
|
141
141
|
'error.10013': "呼叫失败:您已被对方拉黑或您拉黑了对方",
|
|
142
|
+
'error.10014': "发起通话失败,用户 ID 无效,请确认该用户已注册。",
|
|
142
143
|
'error': '错误',
|
|
144
|
+
// AI Subtitle Settings
|
|
145
|
+
'ai-subtitle': 'AI 字幕',
|
|
146
|
+
'ai-subtitle-settings': 'AI 字幕设置',
|
|
147
|
+
'recognition-language': '识别语言',
|
|
148
|
+
'translation-language': '翻译语言',
|
|
149
|
+
'subtitle-display-settings': '字幕显示设置',
|
|
150
|
+
'subtitle-display-bilingual': '字幕显示双语',
|
|
151
|
+
'no-translation': '不翻译',
|
|
152
|
+
'show-bilingual': '显示双语',
|
|
153
|
+
'show-original-only': '仅显示原文',
|
|
154
|
+
'save': '保存',
|
|
155
|
+
'select-recognition-language': '请选择识别语言',
|
|
156
|
+
'select-translation-language': '请选择翻译语言',
|
|
157
|
+
'confirm': '确定',
|
|
158
|
+
'recognition-and-translation-settings': '识别与翻译设置',
|
|
143
159
|
};
|
|
@@ -155,7 +155,7 @@ export function handleRepeatedCallError(error: any) {
|
|
|
155
155
|
*/
|
|
156
156
|
export function handleNoDevicePermissionError(error: any) {
|
|
157
157
|
const { message } = error;
|
|
158
|
-
if (message
|
|
158
|
+
if (message?.indexOf('NotAllowedError: Permission denied') !== -1) {
|
|
159
159
|
return true;
|
|
160
160
|
}
|
|
161
161
|
return false;
|