@trtc/calls-uikit-react 4.4.6 → 4.4.8
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/style/theme/_dark.scss +4 -4
- package/src/Components/style/theme/_light.scss +7 -7
- package/src/TUICallService/CallService/index.ts +13 -6
- package/src/TUICallService/TUIGlobal/tuiGlobal.ts +3 -1
- package/src/TUICallService/interface/ITUIGlobal.ts +2 -0
- package/src/TUICallService/serve/callManager.ts +6 -2
- package/src/TUICallService/utils/common-utils.ts +156 -11
- package/src/TUICallService/utils/env.ts +6 -0
- package/src/index.ts +1 -1
- package/tuicall-uikit-react.es.js +2678 -2632
- package/tuicall-uikit-react.umd.js +4 -4
- package/types/TUICallService/CallService/engineEventHandler.d.ts +1 -0
- package/types/TUICallService/TUIGlobal/tuiGlobal.d.ts +1 -0
- package/types/TUICallService/interface/ITUIGlobal.d.ts +2 -0
- package/types/TUICallService/utils/common-utils.d.ts +9 -0
- package/types/TUICallService/utils/env.d.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trtc/calls-uikit-react",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.8",
|
|
4
4
|
"main": "./tuicall-uikit-react.umd.js",
|
|
5
5
|
"module": "./tuicall-uikit-react.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,17 +1,17 @@
|
|
|
1
1
|
$dark-colors: (
|
|
2
2
|
// bg
|
|
3
|
-
--uikit-theme-dark-bg-color-topbar: #
|
|
3
|
+
--uikit-theme-dark-bg-color-topbar: #131417,
|
|
4
4
|
--uikit-theme-dark-bg-color-operate: #1f2024,
|
|
5
5
|
--uikit-theme-dark-bg-color-input: #2b2c30,
|
|
6
6
|
--uikit-theme-dark-bg-color-bubble-reciprocal: #2b2c30,
|
|
7
7
|
--uikit-theme-dark-bg-color-bubble-own: #5c9dff,
|
|
8
|
-
--uikit-theme-dark-bg-color-default: #
|
|
8
|
+
--uikit-theme-dark-bg-color-default: #131417,
|
|
9
9
|
--uikit-theme-dark-bg-color-tag-mask: rgba(0, 0, 0, 55%),
|
|
10
10
|
--uikit-theme-dark-bg-color-mask: rgba(0, 0, 0, 55%),
|
|
11
11
|
// text
|
|
12
12
|
--uikit-theme-dark-text-color-primary: rgba(255, 255, 255, 93%),
|
|
13
|
-
--uikit-theme-dark-text-color-secondary: rgba(255, 255, 255,
|
|
14
|
-
--uikit-theme-dark-text-color-tertiary: rgba(255, 255, 255,
|
|
13
|
+
--uikit-theme-dark-text-color-secondary: rgba(255, 255, 255, 55%),
|
|
14
|
+
--uikit-theme-dark-text-color-tertiary: rgba(255, 255, 255, 30%),
|
|
15
15
|
--uikit-theme-dark-text-color-disable: rgba(255, 255, 255, 28%),
|
|
16
16
|
--uikit-theme-dark-text-color-link: #4086ff,
|
|
17
17
|
--uikit-theme-dark-text-color-link-hover: #2b6ad6,
|
|
@@ -9,8 +9,8 @@ $light-colors: (
|
|
|
9
9
|
--uikit-theme-light-bg-color-tag-mask: rgba(255, 255, 255, 55%),
|
|
10
10
|
--uikit-theme-light-bg-color-mask: rgba(0, 0, 0, 55%),
|
|
11
11
|
// text
|
|
12
|
-
--uikit-theme-light-text-color-primary: rgba(0, 0, 0,
|
|
13
|
-
--uikit-theme-light-text-color-secondary: rgba(0, 0, 0,
|
|
12
|
+
--uikit-theme-light-text-color-primary: rgba(0, 0, 0, 90%),
|
|
13
|
+
--uikit-theme-light-text-color-secondary: rgba(0, 0, 0, 55%),
|
|
14
14
|
--uikit-theme-light-text-color-tertiary: rgba(0, 0, 0, 40%),
|
|
15
15
|
--uikit-theme-light-text-color-disable: rgba(0, 0, 0, 28%),
|
|
16
16
|
--uikit-theme-light-text-color-link: #1c66e5,
|
|
@@ -24,14 +24,14 @@ $light-colors: (
|
|
|
24
24
|
// dropdown
|
|
25
25
|
--uikit-theme-light-dropdown-color-default: #fff,
|
|
26
26
|
--uikit-theme-light-dropdown-color-hover: #f9fafc,
|
|
27
|
-
--uikit-theme-light-dropdown-color-active: #
|
|
27
|
+
--uikit-theme-light-dropdown-color-active: #cce2ff,
|
|
28
28
|
// list
|
|
29
29
|
--uikit-theme-light-list-color-default: #fff,
|
|
30
30
|
--uikit-theme-light-list-color-hover: #f9fafc,
|
|
31
31
|
--uikit-theme-light-list-color-active: #ebf3ff,
|
|
32
32
|
// border
|
|
33
|
-
--uikit-theme-light-stroke-color-primary: #
|
|
34
|
-
--uikit-theme-light-stroke-color-secondary:
|
|
33
|
+
--uikit-theme-light-stroke-color-primary: #e6e9f0,
|
|
34
|
+
--uikit-theme-light-stroke-color-secondary: #f0f2f7,
|
|
35
35
|
// box-shadow
|
|
36
36
|
--uikit-theme-light-shadow-color: rgba(0, 0, 0, 6%),
|
|
37
37
|
// floatWindow
|
|
@@ -40,8 +40,8 @@ $light-colors: (
|
|
|
40
40
|
// toast
|
|
41
41
|
--uikit-theme-light-toast-color-default: #EBF3FF,
|
|
42
42
|
--uikit-theme-light-toast-color-success: #DCFAE9,
|
|
43
|
-
--uikit-theme-light-toast-color-warning: #
|
|
44
|
-
--uikit-theme-light-toast-color-error: #
|
|
43
|
+
--uikit-theme-light-toast-color-warning: #ffd6b2,
|
|
44
|
+
--uikit-theme-light-toast-color-error: #ffe7e6,
|
|
45
45
|
// btn
|
|
46
46
|
--uikit-theme-light-button-color-hangup: #E54545,
|
|
47
47
|
--uikit-theme-light-button-color-accept: #0ABF77,
|
|
@@ -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.8';
|
|
31
31
|
import AIAssistant from './AIAssistant'; // 仅 web 支持 AI 实时字幕
|
|
32
32
|
const frameWork = 'react';
|
|
33
33
|
export { TUIGlobal, TUIStore, uiDesign };
|
|
@@ -83,7 +83,7 @@ export default class TUICallService {
|
|
|
83
83
|
await this._wasmReadyPromise;
|
|
84
84
|
|
|
85
85
|
if (!this._isInitialized) {
|
|
86
|
-
this._doInit(params);
|
|
86
|
+
await this._doInit(params);
|
|
87
87
|
this._isInitialized = true;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -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
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APP_NAMESPACE, IS_PC, IS_H5, IN_WX_MINI_APP, IN_UNI_NATIVE_APP, IN_UNI_APP, IS_MAC, IS_WIN } from '../utils/env';
|
|
1
|
+
import { APP_NAMESPACE, IS_PC, IS_H5, IN_WX_MINI_APP, IN_UNI_NATIVE_APP, IN_UNI_APP, IS_MAC, IS_WIN, IS_WX_HARMONY } from '../utils/env';
|
|
2
2
|
import { ITUIGlobal } from '../interface/ITUIGlobal';
|
|
3
3
|
|
|
4
4
|
export default class TUIGlobal implements ITUIGlobal {
|
|
@@ -12,6 +12,7 @@ export default class TUIGlobal implements ITUIGlobal {
|
|
|
12
12
|
public isOfficial: boolean = false;
|
|
13
13
|
public isWIN: boolean = false;
|
|
14
14
|
public isMAC: boolean = false;
|
|
15
|
+
public isWxHarmony: boolean = false;
|
|
15
16
|
constructor() {
|
|
16
17
|
this.initEnv();
|
|
17
18
|
}
|
|
@@ -35,6 +36,7 @@ export default class TUIGlobal implements ITUIGlobal {
|
|
|
35
36
|
this.isUniPlatform = IN_UNI_APP;
|
|
36
37
|
this.isWIN = IS_WIN;
|
|
37
38
|
this.isMAC = IS_MAC;
|
|
39
|
+
this.isWxHarmony = IS_WX_HARMONY;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
initOfficial(SDKAppID: number) {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @property {Boolean} isOfficial true 标识是腾讯云官网 Demo 应用
|
|
10
10
|
* @property {Boolean} isWIN true 标识是window系统pc
|
|
11
11
|
* @property {Boolean} isMAC true 标识是mac os系统pc
|
|
12
|
+
* @property {Boolean} isWxHarmony true 标识是微信小程序运行在鸿蒙系统
|
|
12
13
|
*/
|
|
13
14
|
export interface ITUIGlobal {
|
|
14
15
|
global: any; // 挂在 wx、uni、window 对象
|
|
@@ -20,6 +21,7 @@ export interface ITUIGlobal {
|
|
|
20
21
|
isOfficial: boolean;
|
|
21
22
|
isWIN: boolean;
|
|
22
23
|
isMAC: boolean;
|
|
24
|
+
isWxHarmony: boolean;
|
|
23
25
|
/**
|
|
24
26
|
* 初始化 TUIGlobal 环境变量
|
|
25
27
|
* @function
|
|
@@ -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
|
}
|
|
@@ -49,3 +49,9 @@ export const IS_H5 = IS_ANDROID || IS_WIN_PHONE || IS_SYMBIAN || IS_IOS;
|
|
|
49
49
|
export const IS_PC = IN_BROWSER && !IS_H5;
|
|
50
50
|
export const IS_WIN = IS_PC && USER_AGENT.includes('Windows NT');
|
|
51
51
|
export const IS_MAC = IS_PC && USER_AGENT.includes('Mac');
|
|
52
|
+
|
|
53
|
+
let IS_WX_HARMONY = false;
|
|
54
|
+
if (IN_WX_MINI_APP) {
|
|
55
|
+
IS_WX_HARMONY = (wx.getSystemInfoSync()?.system || '').includes('Harmony');
|
|
56
|
+
}
|
|
57
|
+
export { IS_WX_HARMONY };
|