@trtc/calls-uikit-vue2 4.4.6 → 4.4.7
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 +2 -2
- package/src/Components/hooks/useCustomUIButtonConfig.ts +37 -2
- package/src/TUICallService/CallService/index.ts +12 -5
- package/src/TUICallService/serve/callManager.ts +6 -2
- package/src/TUICallService/utils/common-utils.ts +156 -11
- package/src/index.ts +1 -1
- package/tuicall-uikit-vue2.es.js +2410 -2360
- package/tuicall-uikit-vue2.umd.js +2 -2
- package/types/TUICallService/CallService/engineEventHandler.d.ts +1 -0
- package/types/TUICallService/utils/common-utils.d.ts +9 -0
- package/types/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trtc/calls-uikit-vue2",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.7",
|
|
4
4
|
"main": "./tuicall-uikit-vue2.umd.js",
|
|
5
5
|
"module": "./tuicall-uikit-vue2.es.js",
|
|
6
6
|
"types": "./types/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@tencentcloud/tui-core-lite": "1.0.0",
|
|
17
|
-
"@trtc/call-engine-lite-js": "~3.5.
|
|
17
|
+
"@trtc/call-engine-lite-js": "~3.5.8",
|
|
18
18
|
"@tencentcloud/lite-chat": "^1.6.3",
|
|
19
19
|
"@trtc/call-engine-lite-wx": "~3.4.8"
|
|
20
20
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { watch, ref, toRefs, computed } from '../../adapter-vue';
|
|
2
2
|
import { useCustomUI } from './useCustomUI';
|
|
3
|
-
import { TUIGlobal, CallStatus } from '../../TUICallService';
|
|
3
|
+
import { TUIGlobal, CallStatus, TUIStore, StoreName, NAME } from '../../TUICallService';
|
|
4
4
|
import { add, deepClone, findValues, modify } from '../util';
|
|
5
5
|
import { VirtualBackgroundMobileConfig } from '../components/common/ButtonPanel/config/VirtualBackgroundMobileConfig';
|
|
6
6
|
import { useCallInfoContext } from './useCallInfoContext';
|
|
@@ -36,15 +36,46 @@ function setCloseCameraConfig(config, isVideoAvailable, isShowVirtualBackgroundI
|
|
|
36
36
|
return newConfig;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Hide inviteUser button when groupID is empty (not a Chat group call)
|
|
41
|
+
* This prevents showing the invite button when there's no group member list available
|
|
42
|
+
*/
|
|
43
|
+
function setInviteUserVisibility(config, groupID) {
|
|
44
|
+
const newConfig = deepClone(config);
|
|
45
|
+
const hasValidGroupID = groupID && typeof groupID === 'string' && groupID.trim() !== '';
|
|
46
|
+
|
|
47
|
+
if (!hasValidGroupID) {
|
|
48
|
+
// Hide inviteUser button in all group call scenarios when no valid groupID
|
|
49
|
+
// PC group call video
|
|
50
|
+
modify(newConfig, 'pc.groupCall.video.calling[0][2].props.show', false);
|
|
51
|
+
modify(newConfig, 'pc.groupCall.video.connected[0][3].props.show', false);
|
|
52
|
+
// PC group call audio
|
|
53
|
+
modify(newConfig, 'pc.groupCall.audio.calling[0][2].props.show', false);
|
|
54
|
+
modify(newConfig, 'pc.groupCall.audio.connected[0][3].props.show', false);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return newConfig;
|
|
58
|
+
}
|
|
59
|
+
|
|
39
60
|
export function useCustomUIButtonConfig() {
|
|
40
61
|
const { isShowEnableVirtualBackground, callStatus } = toRefs(useCallInfoContext());
|
|
41
62
|
const customUIConfig = useCustomUI();
|
|
42
63
|
const { localUserInfoExcludeVolume: localUserInfo } = toRefs(useUserInfoExcludeVolumeContext());
|
|
43
64
|
const isVideoAvailable = computed(() => localUserInfo?.value.isVideoAvailable || false);
|
|
44
65
|
const isShowVirtualBackgroundIcon = computed(() => isShowEnableVirtualBackground.value && !TUIGlobal.isH5);
|
|
66
|
+
const groupID = ref(TUIStore.getData(StoreName.CALL, NAME.GROUP_ID));
|
|
45
67
|
const results = ref([]);
|
|
46
68
|
|
|
47
|
-
|
|
69
|
+
// Watch groupID changes from TUIStore
|
|
70
|
+
const handleGroupIDChange = (value) => {
|
|
71
|
+
groupID.value = value;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
TUIStore.watch(StoreName.CALL, {
|
|
75
|
+
[NAME.GROUP_ID]: handleGroupIDChange,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
watch([customUIConfig, isShowEnableVirtualBackground, isVideoAvailable, groupID], () => {
|
|
48
79
|
let initConfig = deepClone(ButtonPanelConfig);
|
|
49
80
|
if (isShowVirtualBackgroundIcon.value) {
|
|
50
81
|
initConfig = setVirtualBackgroundConfig(ButtonPanelConfig);
|
|
@@ -52,6 +83,10 @@ export function useCustomUIButtonConfig() {
|
|
|
52
83
|
if(callStatus.value === CallStatus.CONNECTED) {
|
|
53
84
|
initConfig = setCloseCameraConfig(initConfig, isVideoAvailable.value, isShowVirtualBackgroundIcon.value);
|
|
54
85
|
}
|
|
86
|
+
|
|
87
|
+
// Hide inviteUser button when not in a Chat group (no groupID)
|
|
88
|
+
initConfig = setInviteUserVisibility(initConfig, groupID.value);
|
|
89
|
+
|
|
55
90
|
const { button: buttonsConfig } = customUIConfig.value;
|
|
56
91
|
const rs = [];
|
|
57
92
|
function condition(value) {
|
|
@@ -27,7 +27,7 @@ const TUIGlobal: ITUIGlobal = TuiGlobal.getInstance();
|
|
|
27
27
|
const TUIStore: ITUIStore = TuiStore.getInstance();
|
|
28
28
|
const uiDesign = UIDesign.getInstance();
|
|
29
29
|
uiDesign.setTUIStore(TUIStore);
|
|
30
|
-
const version = '4.4.
|
|
30
|
+
const version = '4.4.7';
|
|
31
31
|
import AIAssistant from './AIAssistant'; // 仅 web 支持 AI 实时字幕
|
|
32
32
|
const frameWork = 'vue2.7';
|
|
33
33
|
export { TUIGlobal, TUIStore, uiDesign };
|
|
@@ -581,15 +581,22 @@ export default class TUICallService {
|
|
|
581
581
|
public executeExternalAfterCalling(): void {
|
|
582
582
|
this.afterCalling && this.afterCalling();
|
|
583
583
|
}
|
|
584
|
-
//
|
|
584
|
+
// Handle exception exit: mini program "swipe right", "exit from top left"; web close browser or close tab
|
|
585
585
|
public async handleExceptionExit(event?: any) {
|
|
586
586
|
try {
|
|
587
587
|
const callStatus = TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS);
|
|
588
588
|
const callRole = TUIStore.getData(StoreName.CALL, NAME.CALL_ROLE);
|
|
589
|
-
|
|
589
|
+
|
|
590
|
+
this._tuiCallEngine?.reportLog?.({
|
|
591
|
+
name: 'TUICallkit.handleExceptionExit',
|
|
592
|
+
data: { callStatus, callRole, source: event?.type || 'unknown' }
|
|
593
|
+
});
|
|
590
594
|
|
|
591
595
|
if (callStatus === CallStatus.IDLE) return;
|
|
592
|
-
|
|
596
|
+
|
|
597
|
+
console.log(`${NAME.PREFIX} handleExceptionExit triggered, status: ${callStatus}, role: ${callRole}, event: ${event?.type}`);
|
|
598
|
+
|
|
599
|
+
// Execute hangup/reject based on call status and role
|
|
593
600
|
if (callStatus === CallStatus.CALLING) {
|
|
594
601
|
if (callRole === CallRole.CALLER) {
|
|
595
602
|
await this?.hangup();
|
|
@@ -629,7 +636,7 @@ export default class TUICallService {
|
|
|
629
636
|
}
|
|
630
637
|
}
|
|
631
638
|
// =========================【private methods for service use】=========================
|
|
632
|
-
// 处理
|
|
639
|
+
// 处理 "呼叫" 抛出的异常
|
|
633
640
|
private _handleCallError(error: any, methodName?: string) {
|
|
634
641
|
this._permissionCheckTimer && clearInterval(this._permissionCheckTimer);
|
|
635
642
|
|
|
@@ -72,11 +72,15 @@ export class CallManager {
|
|
|
72
72
|
// @ts-ignore
|
|
73
73
|
wx.navigateTo({
|
|
74
74
|
url: `/${this._globalCallPagePath}`,
|
|
75
|
-
success: () => {
|
|
75
|
+
success: () => {
|
|
76
|
+
const callStatus = TUIStore.getData(StoreName.CALL, NAME.CALL_STATUS);
|
|
77
|
+
if (callStatus === CallStatus.IDLE) {
|
|
78
|
+
this._handleCallStatusToIdle();
|
|
79
|
+
}
|
|
80
|
+
},
|
|
76
81
|
fail: () => {
|
|
77
82
|
console.error(`${PREFIX} navigateTo fail!`);
|
|
78
83
|
},
|
|
79
|
-
complete: () => {},
|
|
80
84
|
});
|
|
81
85
|
}
|
|
82
86
|
|
|
@@ -252,18 +252,163 @@ export function interpolate(str, data) {
|
|
|
252
252
|
return data[key] !== undefined ? String(data[key]) : match;
|
|
253
253
|
});
|
|
254
254
|
}
|
|
255
|
-
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Detect current runtime environment
|
|
258
|
+
*/
|
|
259
|
+
function detectEnvironment(): 'pc-browser' | 'mobile-browser' | 'webview' | 'miniprogram' {
|
|
260
|
+
const ua = navigator.userAgent || '';
|
|
261
|
+
const uaLower = ua.toLowerCase();
|
|
262
|
+
|
|
263
|
+
// WeChat MiniProgram WebView
|
|
264
|
+
if (uaLower.includes('miniprogram') ||
|
|
265
|
+
(window as any).__wxjs_environment === 'miniprogram') {
|
|
266
|
+
return 'miniprogram';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// App WebView
|
|
270
|
+
if (uaLower.includes('webview') ||
|
|
271
|
+
uaLower.includes(' wv') ||
|
|
272
|
+
(window as any).webkit?.messageHandlers) {
|
|
273
|
+
return 'webview';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Mobile browser
|
|
277
|
+
if (/Android|iPhone|iPad|iPod|Mobile/i.test(ua)) {
|
|
278
|
+
return 'mobile-browser';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return 'pc-browser';
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Detect if current device is iOS
|
|
286
|
+
*/
|
|
287
|
+
function isIOS(): boolean {
|
|
288
|
+
return /iPad|iPhone|iPod/.test(navigator.userAgent || '');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Detect if current device is Android
|
|
293
|
+
*/
|
|
294
|
+
function isAndroid(): boolean {
|
|
295
|
+
return /Android/.test(navigator.userAgent || '');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Enhanced browser/webview close detection for exception exit handling
|
|
300
|
+
* Supports: PC browsers (Chrome/Safari/Firefox/Edge), Mobile browsers (Android/iOS), WebView
|
|
301
|
+
*
|
|
302
|
+
* Note: Mobile background switching (visibilitychange to hidden) will NOT trigger hangup,
|
|
303
|
+
* only actual page close/navigation events will trigger the callback.
|
|
304
|
+
*
|
|
305
|
+
* @param callback - Function to call when exit is detected
|
|
306
|
+
*/
|
|
256
307
|
export function initBrowserCloseDetection(callback: Function) {
|
|
257
|
-
if (window
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
308
|
+
if (typeof window === 'undefined') return;
|
|
309
|
+
|
|
310
|
+
let isExiting = false;
|
|
311
|
+
const env = detectEnvironment();
|
|
312
|
+
|
|
313
|
+
console.log(`[ExitDetection] Environment: ${env}, iOS: ${isIOS()}, Android: ${isAndroid()}`);
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Trigger exit handler with deduplication
|
|
317
|
+
*/
|
|
318
|
+
const triggerExit = (source: string, event?: Event) => {
|
|
319
|
+
if (isExiting) return;
|
|
320
|
+
isExiting = true;
|
|
321
|
+
|
|
322
|
+
console.log(`[ExitDetection] Exit triggered by: ${source}`);
|
|
323
|
+
|
|
324
|
+
try {
|
|
266
325
|
callback(event);
|
|
267
|
-
})
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.error(`[ExitDetection] Callback error:`, error);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Reset flag after delay (for bfcache scenarios)
|
|
331
|
+
setTimeout(() => {
|
|
332
|
+
isExiting = false;
|
|
333
|
+
}, 1000);
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Handle beforeunload event
|
|
338
|
+
* Best for: PC browsers, Android browsers
|
|
339
|
+
*/
|
|
340
|
+
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
|
341
|
+
// Skip if it's just navigation (not actual page close)
|
|
342
|
+
const navigationEntries = performance?.getEntriesByType?.('navigation') || [];
|
|
343
|
+
const navigationEntry = navigationEntries[0] as PerformanceNavigationTiming;
|
|
344
|
+
if (navigationEntry && navigationEntry.type === 'navigate') {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
triggerExit('beforeunload', event);
|
|
349
|
+
|
|
350
|
+
// Required for some browsers to trigger the event
|
|
351
|
+
event.returnValue = '';
|
|
352
|
+
return '';
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Handle pagehide event
|
|
357
|
+
* Best for: iOS Safari, all modern browsers
|
|
358
|
+
* More reliable than beforeunload on iOS
|
|
359
|
+
*/
|
|
360
|
+
const handlePageHide = (event: PageTransitionEvent) => {
|
|
361
|
+
// persisted=true means page might be restored from bfcache
|
|
362
|
+
if (!event.persisted) {
|
|
363
|
+
triggerExit('pagehide', event);
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Handle visibilitychange event
|
|
369
|
+
* Note: We only log this event, do NOT trigger hangup on mobile background switch
|
|
370
|
+
* Because user may just switch apps temporarily and come back
|
|
371
|
+
*/
|
|
372
|
+
const handleVisibilityChange = () => {
|
|
373
|
+
if (document.visibilityState === 'hidden') {
|
|
374
|
+
// Only log, do NOT trigger exit on visibility change
|
|
375
|
+
// Mobile users often switch apps temporarily during calls
|
|
376
|
+
console.log(`[ExitDetection] Visibility changed to hidden (not triggering exit)`);
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Handle freeze event (Page Lifecycle API, Chrome 68+)
|
|
382
|
+
* This indicates the page is being frozen, which is a strong signal of exit
|
|
383
|
+
*/
|
|
384
|
+
const handleFreeze = () => {
|
|
385
|
+
triggerExit('freeze');
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
// ============ Register event listeners based on environment ============
|
|
389
|
+
|
|
390
|
+
// 1. pagehide - Most reliable for iOS, works on all modern browsers
|
|
391
|
+
if (window.addEventListener) {
|
|
392
|
+
window.addEventListener('pagehide', handlePageHide, { capture: true });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// 2. beforeunload - Best for PC browsers and Android
|
|
396
|
+
if (env === 'pc-browser' || isAndroid()) {
|
|
397
|
+
window.addEventListener('beforeunload', handleBeforeUnload);
|
|
268
398
|
}
|
|
399
|
+
|
|
400
|
+
// 3. visibilitychange - Only for logging, not triggering exit
|
|
401
|
+
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
402
|
+
|
|
403
|
+
// 4. freeze - Page Lifecycle API (Chrome 68+)
|
|
404
|
+
if ('onfreeze' in document) {
|
|
405
|
+
document.addEventListener('freeze', handleFreeze as EventListener);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 5. unload - Legacy fallback (deprecated but still useful in some cases)
|
|
409
|
+
window.addEventListener('unload', (event) => {
|
|
410
|
+
triggerExit('unload', event);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
console.log(`[ExitDetection] Listeners registered for environment: ${env}`);
|
|
269
414
|
}
|