agora-appbuilder-core 4.0.0-spl.3 → 4.0.0-spl.5
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 +1 -1
- package/template/Gulpfile.js +7 -7
- package/template/customization-api/typeDefinition.ts +2 -1
- package/template/index.wsdk.tsx +1 -19
- package/template/src/SDKAppWrapper.tsx +40 -57
- package/template/src/components/Chat.tsx +9 -8
- package/template/src/components/DeviceConfigure.tsx +7 -10
- package/template/src/components/ParticipantsView.tsx +1 -1
- package/template/src/components/Precall.tsx +12 -11
- package/template/src/components/SdkApiContext.tsx +53 -77
- package/template/src/components/SdkMuteToggleListener.tsx +92 -0
- package/template/src/pages/VideoCall.tsx +32 -29
- package/template/src/utils/SdkEvents.ts +0 -3
- package/template/src/utils/SdkMethodEvents.ts +18 -1
- package/template/src/utils/useMuteToggleLocal.ts +96 -52
- package/template/tsconfig_rsdk_index.json +3 -3
- package/template/tsconfig_wsdk_index.json +1 -1
package/package.json
CHANGED
package/template/Gulpfile.js
CHANGED
|
@@ -460,11 +460,11 @@ module.exports.androidWin = series(
|
|
|
460
460
|
);
|
|
461
461
|
|
|
462
462
|
module.exports.test = series(
|
|
463
|
-
general.
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
463
|
+
general.createBuildDirectory,
|
|
464
|
+
general.generateApiTypedefs,
|
|
465
|
+
general.bundleApiTypedefs,
|
|
466
|
+
webSdk.generateSdkTypedefs,
|
|
467
|
+
webSdk.bundleSdkTypedefs,
|
|
468
|
+
general.cleanTempFiles,
|
|
469
|
+
general.genTsDefs,
|
|
470
470
|
);
|
|
@@ -101,7 +101,8 @@ export type ComponentsInterface = {
|
|
|
101
101
|
*/
|
|
102
102
|
appRoot?: React.ComponentType;
|
|
103
103
|
// commented for v1 release
|
|
104
|
-
//precall?: PreCallInterface | React.ComponentType;
|
|
104
|
+
// precall?: PreCallInterface | React.ComponentType;
|
|
105
|
+
precall?: React.ComponentType;
|
|
105
106
|
//create?: React.ComponentType;
|
|
106
107
|
//share?: React.ComponentType;
|
|
107
108
|
//join?: React.ComponentType;
|
package/template/index.wsdk.tsx
CHANGED
|
@@ -3,31 +3,13 @@ import SDKAppWrapper, {
|
|
|
3
3
|
AppBuilderSdkApi,
|
|
4
4
|
AppBuilderSdkApiInterface,
|
|
5
5
|
} from './src/SDKAppWrapper';
|
|
6
|
-
import SDKEvents from './src/utils/SdkEvents';
|
|
7
6
|
import React from 'react';
|
|
8
7
|
import * as RN from 'react-native-web';
|
|
9
8
|
import './src/assets/font-styles.css';
|
|
10
9
|
export * from 'customization-api';
|
|
11
10
|
export * from 'customization-implementation';
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const clearEvent = {
|
|
16
|
-
clear: () => {},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const AppBuilderWebSdkApi: AppBuilderWebSdkInterface = {
|
|
20
|
-
...AppBuilderSdkApi,
|
|
21
|
-
// Override customize function for web-sdk
|
|
22
|
-
customize: (customization) => {
|
|
23
|
-
SDKEvents.emit('addFpe', customization);
|
|
24
|
-
clearEvent.clear = SDKEvents.on('addFpeInit', () => {
|
|
25
|
-
console.log('addFpeInit called');
|
|
26
|
-
SDKEvents.emit('addFpe', customization);
|
|
27
|
-
clearEvent.clear();
|
|
28
|
-
});
|
|
29
|
-
},
|
|
30
|
-
};
|
|
12
|
+
const AppBuilderWebSdkApi: AppBuilderSdkApiInterface = AppBuilderSdkApi;
|
|
31
13
|
|
|
32
14
|
// init code
|
|
33
15
|
class AppBuilder extends HTMLElement {
|
|
@@ -11,82 +11,65 @@ import SDKMethodEventsManager from './utils/SdkMethodEvents';
|
|
|
11
11
|
import App from './App';
|
|
12
12
|
import SdkApiContextProvider from './components/SdkApiContext';
|
|
13
13
|
import {Unsubscribe} from 'nanoevents';
|
|
14
|
+
import {deviceId} from './components/DeviceConfigure';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
// ...p: Parameters<T>
|
|
17
|
-
// ) => PromiseLike<ReturnType<T>>;
|
|
18
|
-
//
|
|
19
|
-
// type takeOnlyFirstParam<T extends (...p: any) => void> = (
|
|
20
|
-
// p: Parameters<T>[0],
|
|
21
|
-
// ) => ReturnType<T>;
|
|
16
|
+
type meetingData = Partial<MeetingInfoContextInterface['data']>;
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
// Hard defined since its an api.
|
|
19
|
+
export interface AppBuilderSdkApiInterface {
|
|
20
|
+
customize: (customization: CustomizationApiInterface) => Promise<void>;
|
|
21
|
+
joinRoom: (roomDetails: string | meetingData) => Promise<meetingData>;
|
|
22
|
+
joinPrecall: (
|
|
23
|
+
roomDetails: string | meetingData,
|
|
24
|
+
) => Promise<[meetingData, () => void]>;
|
|
25
|
+
setMicrophone: (deviceId: deviceId) => Promise<void>;
|
|
26
|
+
setCamera: (deviceId: deviceId) => Promise<void>;
|
|
27
|
+
setSpeaker: (deviceId: deviceId) => Promise<void>;
|
|
28
|
+
muteAudio: (
|
|
29
|
+
mute: boolean | ((currentMute: boolean) => boolean),
|
|
30
|
+
) => Promise<void>;
|
|
31
|
+
muteVideo: (
|
|
32
|
+
mute: boolean | ((currentMute: boolean) => boolean),
|
|
33
|
+
) => Promise<void>;
|
|
34
|
+
createCustomization: (
|
|
35
|
+
customization: CustomizationApiInterface,
|
|
36
|
+
) => CustomizationApiInterface;
|
|
37
|
+
customEvents: typeof customEvents;
|
|
38
|
+
on: <T extends keyof userEventsMapInterface>(
|
|
39
|
+
userEventName: T,
|
|
40
|
+
cb: userEventsMapInterface[T],
|
|
41
|
+
) => Unsubscribe;
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// joinRoom: makeAsync<takeOnlyFirstParam<SdkMethodEvents['join']>>;
|
|
40
|
-
// joinPrecall: makeAsync<takeOnlyFirstParam<SdkMethodEvents['join']>>;
|
|
41
|
-
// createCustomization: (
|
|
42
|
-
// customization: CustomizationApiInterface,
|
|
43
|
-
// ) => CustomizationApiInterface;
|
|
44
|
-
// on: <T extends keyof userEventsMapInterface>(
|
|
45
|
-
// userEventName: T,
|
|
46
|
-
// callBack: userEventsMapInterface[T],
|
|
47
|
-
// ) => Unsubscribe;
|
|
48
|
-
// }
|
|
49
|
-
|
|
50
|
-
export const AppBuilderSdkApi = {
|
|
51
|
-
customize: async (customization: CustomizationApiInterface) => {
|
|
44
|
+
export const AppBuilderSdkApi: AppBuilderSdkApiInterface = {
|
|
45
|
+
customize: async (customization) => {
|
|
52
46
|
return await SDKMethodEventsManager.emit('customize', customization);
|
|
53
47
|
},
|
|
54
48
|
customEvents: customEvents,
|
|
55
|
-
|
|
56
|
-
await SDKMethodEventsManager.emit('join', roomDetails, false);
|
|
57
|
-
},
|
|
58
|
-
joinRoom: async (
|
|
59
|
-
roomDetails: string | Partial<MeetingInfoContextInterface['data']>,
|
|
60
|
-
) => {
|
|
49
|
+
joinRoom: async (roomDetails) => {
|
|
61
50
|
return await SDKMethodEventsManager.emit('join', roomDetails, true);
|
|
62
51
|
},
|
|
63
|
-
joinPrecall: async (
|
|
64
|
-
roomDetails: string | Partial<MeetingInfoContextInterface['data']>,
|
|
65
|
-
) => {
|
|
52
|
+
joinPrecall: async (roomDetails) => {
|
|
66
53
|
const t = await SDKMethodEventsManager.emit('join', roomDetails);
|
|
67
54
|
return t as unknown as [MeetingInfoContextInterface['data'], () => {}];
|
|
68
55
|
},
|
|
69
|
-
|
|
70
|
-
// return await SDKMethodEventsManager.emit(
|
|
71
|
-
// 'mediaDevice',
|
|
72
|
-
// device.deviceId,
|
|
73
|
-
// device.kind,
|
|
74
|
-
// );
|
|
75
|
-
// },
|
|
76
|
-
setMicrophone: async (deviceId: MediaDeviceInfo['deviceId']) => {
|
|
56
|
+
setMicrophone: async (deviceId) => {
|
|
77
57
|
return await SDKMethodEventsManager.emit('microphoneDevice', deviceId);
|
|
78
58
|
},
|
|
79
|
-
setSpeaker: async (deviceId
|
|
59
|
+
setSpeaker: async (deviceId) => {
|
|
80
60
|
return await SDKMethodEventsManager.emit('speakerDevice', deviceId);
|
|
81
61
|
},
|
|
82
|
-
setCamera: async (deviceId
|
|
62
|
+
setCamera: async (deviceId) => {
|
|
83
63
|
return await SDKMethodEventsManager.emit('cameraDevice', deviceId);
|
|
84
64
|
},
|
|
65
|
+
muteAudio: async (state) => {
|
|
66
|
+
return await SDKMethodEventsManager.emit('muteAudio', state);
|
|
67
|
+
},
|
|
68
|
+
muteVideo: async (state) => {
|
|
69
|
+
return await SDKMethodEventsManager.emit('muteVideo', state);
|
|
70
|
+
},
|
|
85
71
|
createCustomization: customize,
|
|
86
|
-
on:
|
|
87
|
-
userEventName: T,
|
|
88
|
-
cb: userEventsMapInterface[T],
|
|
89
|
-
): Unsubscribe => {
|
|
72
|
+
on: (userEventName, cb) => {
|
|
90
73
|
console.log('SDKEvents: Event Registered', userEventName);
|
|
91
74
|
return SDKEvents.on(userEventName, cb);
|
|
92
75
|
},
|
|
@@ -81,14 +81,15 @@ const Chat = (props?: ChatProps) => {
|
|
|
81
81
|
|
|
82
82
|
const {primaryColor} = useContext(ColorContext);
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
84
|
+
//not need since state are controlled by chatUIControl
|
|
85
|
+
// React.useEffect(() => {
|
|
86
|
+
// return () => {
|
|
87
|
+
// // reset both the active tabs
|
|
88
|
+
// setGroupActive(false);
|
|
89
|
+
// setPrivateActive(false);
|
|
90
|
+
// setSelectedUser(0);
|
|
91
|
+
// };
|
|
92
|
+
// }, []);
|
|
92
93
|
|
|
93
94
|
const selectUser = (userUID: UidType) => {
|
|
94
95
|
setSelectedUser(userUID);
|
|
@@ -20,20 +20,17 @@ import React, {
|
|
|
20
20
|
import {ClientRole} from '../../agora-rn-uikit';
|
|
21
21
|
import DeviceContext from './DeviceContext';
|
|
22
22
|
import AgoraRTC, {DeviceInfo} from 'agora-rtc-sdk-ng';
|
|
23
|
-
import {useRtc
|
|
23
|
+
import {useRtc} from 'customization-api';
|
|
24
24
|
import Toast from '../../react-native-toast-message';
|
|
25
|
-
import
|
|
26
|
-
import {StyleSheet, Text} from 'react-native';
|
|
27
|
-
import CustomIcon from '../atoms/CustomIcon';
|
|
25
|
+
import {Text} from 'react-native';
|
|
28
26
|
import StorageContext from './StorageContext';
|
|
29
27
|
|
|
30
28
|
import type RtcEngine from '../../bridge/rtc/webNg/';
|
|
31
29
|
import ColorContext from './ColorContext';
|
|
32
30
|
import {SdkApiContext} from './SdkApiContext';
|
|
33
|
-
import SDKMethodEventsManager from '../utils/SdkMethodEvents';
|
|
34
31
|
import SDKEvents from '../utils/SdkEvents';
|
|
35
32
|
|
|
36
|
-
const log = (...args) => {
|
|
33
|
+
const log = (...args: any[]) => {
|
|
37
34
|
console.log('[DeviceConfigure] ', ...args);
|
|
38
35
|
};
|
|
39
36
|
|
|
@@ -42,9 +39,9 @@ type WebRtcEngineInstance = InstanceType<typeof RtcEngine>;
|
|
|
42
39
|
interface Props {
|
|
43
40
|
userRole: ClientRole;
|
|
44
41
|
}
|
|
45
|
-
type deviceInfo = MediaDeviceInfo;
|
|
46
|
-
type deviceId = deviceInfo['deviceId'];
|
|
47
|
-
type deviceKind = deviceInfo['kind'];
|
|
42
|
+
export type deviceInfo = MediaDeviceInfo;
|
|
43
|
+
export type deviceId = deviceInfo['deviceId'];
|
|
44
|
+
export type deviceKind = deviceInfo['kind'];
|
|
48
45
|
|
|
49
46
|
const DeviceConfigure: React.FC<Props> = (props: any) => {
|
|
50
47
|
const rtc = useRtc();
|
|
@@ -213,7 +210,7 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
|
|
|
213
210
|
break;
|
|
214
211
|
case 'audiooutput':
|
|
215
212
|
//@ts-ignore
|
|
216
|
-
|
|
213
|
+
let speakerId = RtcEngine.speakerDeviceId;
|
|
217
214
|
speakerId &&
|
|
218
215
|
SDKEvents.emit('devices-selected-speaker-changed', speakerId);
|
|
219
216
|
setUiSelectedSpeaker(speakerId);
|
|
@@ -163,7 +163,7 @@ const ParticipantView = (props) => {
|
|
|
163
163
|
onPress={() => setShowHostSection(!showHostSection)}
|
|
164
164
|
/>
|
|
165
165
|
{showHostSection ? (
|
|
166
|
-
<
|
|
166
|
+
<AllHostParticipants
|
|
167
167
|
emptyMessage={'No Host has joined yet.'}
|
|
168
168
|
uids={hostUids}
|
|
169
169
|
isMobile={isSmall()}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
trimText,
|
|
20
20
|
useIsDesktop,
|
|
21
21
|
useResponsive,
|
|
22
|
+
isValidReactComponent,
|
|
22
23
|
} from '../utils/common';
|
|
23
24
|
import {useMeetingInfo} from './meeting-info/useMeetingInfo';
|
|
24
25
|
import {useCustomization} from 'customization-implementation';
|
|
@@ -276,23 +277,23 @@ const Precall = () => {
|
|
|
276
277
|
res(devices);
|
|
277
278
|
}),
|
|
278
279
|
).then((devices: MediaDeviceInfo[]) => {
|
|
279
|
-
SDKEvents.emit('
|
|
280
|
+
SDKEvents.emit('ready-to-join', meetingTitle, devices);
|
|
280
281
|
});
|
|
281
282
|
}
|
|
282
283
|
}, [isJoinDataFetched]);
|
|
283
284
|
|
|
284
285
|
const FpePrecallComponent = useCustomization((data) => {
|
|
285
286
|
// commented for v1 release
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
return undefined;
|
|
287
|
+
if (
|
|
288
|
+
data?.components?.precall &&
|
|
289
|
+
typeof data?.components?.precall !== 'object'
|
|
290
|
+
) {
|
|
291
|
+
if (isValidReactComponent(data?.components?.precall)) {
|
|
292
|
+
return data?.components?.precall;
|
|
293
|
+
}
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
// return undefined;
|
|
296
297
|
});
|
|
297
298
|
|
|
298
299
|
const isDesktop = useIsDesktop();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {createContext, useState, useEffect} from 'react';
|
|
1
|
+
import React, {createContext, useState, useEffect, useRef} from 'react';
|
|
2
2
|
import SDKMethodEventsManager, {
|
|
3
3
|
_InternalSDKMethodEventsMap,
|
|
4
4
|
} from '../utils/SdkMethodEvents';
|
|
@@ -31,12 +31,6 @@ type SdkApiContextInterface = {
|
|
|
31
31
|
customization?: CustomizationApiInterface;
|
|
32
32
|
promise?: extractPromises<_InternalSDKMethodEventsMap['customize']>;
|
|
33
33
|
};
|
|
34
|
-
// mediaDevice: {
|
|
35
|
-
// [k in MediaDeviceInfo['kind']]?: {
|
|
36
|
-
// deviceId: string;
|
|
37
|
-
// promise?: extractPromises<_InternalSDKMethodEventsMap['mediaDevice']>;
|
|
38
|
-
// };
|
|
39
|
-
// };
|
|
40
34
|
microphoneDevice: {
|
|
41
35
|
deviceId?: string;
|
|
42
36
|
promise?: extractPromises<_InternalSDKMethodEventsMap['microphoneDevice']>;
|
|
@@ -49,9 +43,19 @@ type SdkApiContextInterface = {
|
|
|
49
43
|
deviceId?: string;
|
|
50
44
|
promise?: extractPromises<_InternalSDKMethodEventsMap['cameraDevice']>;
|
|
51
45
|
};
|
|
46
|
+
onMuteAudio: (callback: _InternalSDKMethodEventsMap['muteAudio']) => void;
|
|
47
|
+
onMuteVideo: (callback: _InternalSDKMethodEventsMap['muteVideo']) => void;
|
|
52
48
|
clearState: (key: keyof _InternalSDKMethodEventsMap, param?: any) => void;
|
|
53
49
|
};
|
|
54
50
|
|
|
51
|
+
const defaultMuteListener = ((_, rej) => {
|
|
52
|
+
rej(
|
|
53
|
+
new Error(
|
|
54
|
+
"Video call not initialized, call this method on 'join' or 'ready-to-join' event listener callback",
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
}) as _InternalSDKMethodEventsMap['muteVideo'];
|
|
58
|
+
|
|
55
59
|
const SdkApiInitState: SdkApiContextInterface = {
|
|
56
60
|
join: {
|
|
57
61
|
initialized: false,
|
|
@@ -61,17 +65,20 @@ const SdkApiInitState: SdkApiContextInterface = {
|
|
|
61
65
|
microphoneDevice: {},
|
|
62
66
|
speakerDevice: {},
|
|
63
67
|
cameraDevice: {},
|
|
68
|
+
onMuteVideo: (_) => {},
|
|
69
|
+
onMuteAudio: (_) => {},
|
|
64
70
|
clearState: () => {},
|
|
65
71
|
};
|
|
66
72
|
|
|
67
73
|
export const SDK_MEETING_TAG = 'sdk-initiated-meeting';
|
|
68
74
|
|
|
69
|
-
export const SdkApiContext =
|
|
75
|
+
export const SdkApiContext =
|
|
76
|
+
createContext<SdkApiContextInterface>(SdkApiInitState);
|
|
70
77
|
|
|
71
78
|
let moduleEventsUnsub: any[] = [];
|
|
72
79
|
|
|
73
80
|
type commonEventHandlers = {
|
|
74
|
-
[K in keyof _InternalSDKMethodEventsMap]?: (
|
|
81
|
+
[K in keyof Omit<_InternalSDKMethodEventsMap, 'muteVideo' | 'muteAudio'>]?: (
|
|
75
82
|
setter: (p: SdkApiContextInterface[K]) => void,
|
|
76
83
|
) => Unsubscribe;
|
|
77
84
|
};
|
|
@@ -117,19 +124,6 @@ const commonEventHandlers: commonEventHandlers = {
|
|
|
117
124
|
res();
|
|
118
125
|
});
|
|
119
126
|
},
|
|
120
|
-
// mediaDevice: (setter) => {
|
|
121
|
-
// return SDKMethodEventsManager.on(
|
|
122
|
-
// 'mediaDevice',
|
|
123
|
-
// (res, rej, deviceId, kind) => {
|
|
124
|
-
// setter({
|
|
125
|
-
// [kind]: {
|
|
126
|
-
// deviceId,
|
|
127
|
-
// promise: {res, rej},
|
|
128
|
-
// },
|
|
129
|
-
// });
|
|
130
|
-
// },
|
|
131
|
-
// );
|
|
132
|
-
// },
|
|
133
127
|
microphoneDevice: (setter) => {
|
|
134
128
|
return SDKMethodEventsManager.on(
|
|
135
129
|
'microphoneDevice',
|
|
@@ -167,12 +161,6 @@ const registerListener = () => {
|
|
|
167
161
|
commonEventHandlers.join((state) => {
|
|
168
162
|
SdkApiInitState.join = state;
|
|
169
163
|
}),
|
|
170
|
-
// commonEventHandlers.mediaDevice((state) => {
|
|
171
|
-
// SdkApiInitState.mediaDevice = {
|
|
172
|
-
// ...SdkApiInitState.mediaDevice,
|
|
173
|
-
// ...state,
|
|
174
|
-
// };
|
|
175
|
-
// }),
|
|
176
164
|
commonEventHandlers.microphoneDevice((state) => {
|
|
177
165
|
SdkApiInitState.microphoneDevice = state;
|
|
178
166
|
}),
|
|
@@ -182,6 +170,8 @@ const registerListener = () => {
|
|
|
182
170
|
commonEventHandlers.cameraDevice((state) => {
|
|
183
171
|
SdkApiInitState.cameraDevice = state;
|
|
184
172
|
}),
|
|
173
|
+
SDKMethodEventsManager.on('muteVideo', defaultMuteListener),
|
|
174
|
+
SDKMethodEventsManager.on('muteAudio', defaultMuteListener),
|
|
185
175
|
];
|
|
186
176
|
};
|
|
187
177
|
|
|
@@ -194,9 +184,6 @@ const SdkApiContextProvider: React.FC = (props) => {
|
|
|
194
184
|
const [userCustomization, setUserCustomization] = useState(
|
|
195
185
|
SdkApiInitState.customize,
|
|
196
186
|
);
|
|
197
|
-
// const [mediaDeviceState, setMediaDeviceState] = useState(
|
|
198
|
-
// SdkApiInitState.setCamera,
|
|
199
|
-
// );
|
|
200
187
|
const [microphoneDeviceState, setMicrophoneDeviceState] = useState(
|
|
201
188
|
SdkApiInitState.microphoneDevice,
|
|
202
189
|
);
|
|
@@ -207,57 +194,50 @@ const SdkApiContextProvider: React.FC = (props) => {
|
|
|
207
194
|
SdkApiInitState.cameraDevice,
|
|
208
195
|
);
|
|
209
196
|
|
|
210
|
-
const
|
|
197
|
+
const muteVideoListener = useRef(defaultMuteListener);
|
|
198
|
+
const muteAudioListener = useRef(defaultMuteListener);
|
|
199
|
+
|
|
200
|
+
const setMuteVideoListener = (
|
|
201
|
+
value: _InternalSDKMethodEventsMap['muteVideo'],
|
|
202
|
+
) => {
|
|
203
|
+
muteVideoListener.current = value;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const setMuteAudioListener = (
|
|
207
|
+
value: _InternalSDKMethodEventsMap['muteAudio'],
|
|
208
|
+
) => {
|
|
209
|
+
muteAudioListener.current = value;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const clearState: SdkApiContextInterface['clearState'] = (key) => {
|
|
211
213
|
switch (key) {
|
|
212
214
|
case 'join':
|
|
213
215
|
setJoinState(SdkApiInitState.join);
|
|
214
|
-
|
|
216
|
+
break;
|
|
215
217
|
case 'customize':
|
|
216
218
|
setUserCustomization(SdkApiInitState.customize);
|
|
217
|
-
|
|
219
|
+
break;
|
|
218
220
|
case 'microphoneDevice':
|
|
219
221
|
setMicrophoneDeviceState({});
|
|
222
|
+
break;
|
|
220
223
|
case 'speakerDevice':
|
|
221
224
|
setSpeakerDeviceState({});
|
|
225
|
+
break;
|
|
222
226
|
case 'cameraDevice':
|
|
223
227
|
setCameraDeviceState({});
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
break;
|
|
229
|
+
case 'muteVideo':
|
|
230
|
+
setMuteVideoListener(defaultMuteListener);
|
|
231
|
+
break;
|
|
232
|
+
case 'muteAudio':
|
|
233
|
+
setMuteVideoListener(defaultMuteListener);
|
|
234
|
+
break;
|
|
229
235
|
}
|
|
230
236
|
};
|
|
231
237
|
|
|
232
238
|
useEffect(() => {
|
|
233
239
|
deRegisterListener();
|
|
234
240
|
|
|
235
|
-
// const applyPromiseWrapper = (
|
|
236
|
-
// state: SdkApiContextInterface['mediaDevice'],
|
|
237
|
-
// kind: MediaDeviceInfo['kind'],
|
|
238
|
-
// ) => {
|
|
239
|
-
// if (state[kind]) {
|
|
240
|
-
// state[kind].promise.res = () => {
|
|
241
|
-
// const resolve = state[kind].promise.res;
|
|
242
|
-
// clearState('mediaDevice', kind);
|
|
243
|
-
// resolve();
|
|
244
|
-
// };
|
|
245
|
-
// state[kind].promise.rej = (reason?: any) => {
|
|
246
|
-
// const reject = state[kind].promise.rej;
|
|
247
|
-
// clearState('mediaDevice', kind);
|
|
248
|
-
// reject(reason);
|
|
249
|
-
// };
|
|
250
|
-
// }
|
|
251
|
-
// };
|
|
252
|
-
|
|
253
|
-
// setMediaDeviceState((currentState) => {
|
|
254
|
-
// // applyPromiseWrapper(currentState, 'audiooutput');
|
|
255
|
-
// // applyPromiseWrapper(currentState, 'audioinput');
|
|
256
|
-
// // applyPromiseWrapper(currentState, 'videoinput');
|
|
257
|
-
//
|
|
258
|
-
// return currentState;
|
|
259
|
-
// });
|
|
260
|
-
|
|
261
241
|
const unsub = [
|
|
262
242
|
commonEventHandlers.customize((state) => {
|
|
263
243
|
setUserCustomization(state);
|
|
@@ -274,18 +254,12 @@ const SdkApiContextProvider: React.FC = (props) => {
|
|
|
274
254
|
commonEventHandlers.cameraDevice((state) => {
|
|
275
255
|
setCameraDeviceState(state);
|
|
276
256
|
}),
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
// return {
|
|
284
|
-
// ...currentState,
|
|
285
|
-
// ...state,
|
|
286
|
-
// };
|
|
287
|
-
// });
|
|
288
|
-
// }),
|
|
257
|
+
SDKMethodEventsManager.on('muteVideo', (...args) => {
|
|
258
|
+
muteVideoListener.current(...args);
|
|
259
|
+
}),
|
|
260
|
+
SDKMethodEventsManager.on('muteAudio', (...args) => {
|
|
261
|
+
muteAudioListener.current(...args);
|
|
262
|
+
}),
|
|
289
263
|
];
|
|
290
264
|
|
|
291
265
|
return () => {
|
|
@@ -302,6 +276,8 @@ const SdkApiContextProvider: React.FC = (props) => {
|
|
|
302
276
|
microphoneDevice: microphoneDeviceState,
|
|
303
277
|
speakerDevice: speakerDeviceState,
|
|
304
278
|
cameraDevice: cameraDeviceState,
|
|
279
|
+
onMuteAudio: setMuteAudioListener,
|
|
280
|
+
onMuteVideo: setMuteVideoListener,
|
|
305
281
|
clearState,
|
|
306
282
|
}}>
|
|
307
283
|
{props.children}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { useContext, useEffect, createContext, useRef } from 'react';
|
|
2
|
+
import { SdkApiContext } from './SdkApiContext';
|
|
3
|
+
import {
|
|
4
|
+
useMuteToggleLocal,
|
|
5
|
+
useLocalUserInfo,
|
|
6
|
+
ToggleState,
|
|
7
|
+
MUTE_LOCAL_TYPE,
|
|
8
|
+
} from 'customization-api';
|
|
9
|
+
|
|
10
|
+
export const SdkMuteQueueContext = createContext({
|
|
11
|
+
videoMuteQueue: { current: [] },
|
|
12
|
+
audioMuteQueue: { current: [] },
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const SdkMuteToggleListener = (props) => {
|
|
16
|
+
const videoMuteQueue = useRef([]);
|
|
17
|
+
const audioMuteQueue = useRef([]);
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
onMuteVideo: onSdkMuteVideo,
|
|
21
|
+
onMuteAudio: onSdkMuteAudio,
|
|
22
|
+
clearState,
|
|
23
|
+
} = useContext(SdkApiContext);
|
|
24
|
+
const local = useLocalUserInfo();
|
|
25
|
+
const toggleMute = useMuteToggleLocal();
|
|
26
|
+
|
|
27
|
+
const queuedToggleMute = (type, status) => {
|
|
28
|
+
const localstatus =
|
|
29
|
+
local[type === MUTE_LOCAL_TYPE.video ? 'video' : 'audio'];
|
|
30
|
+
|
|
31
|
+
// if ([ToggleState.enabling, ToggleState.disabling].includes(localstatus)) {
|
|
32
|
+
// if ({[ToggleState.enabling]: true, [ToggleState.disabling]: true}[localstatus]) {
|
|
33
|
+
if (
|
|
34
|
+
ToggleState.enabling === localstatus ||
|
|
35
|
+
ToggleState.disabling === localstatus
|
|
36
|
+
) {
|
|
37
|
+
return new Promise((res, rej) => {
|
|
38
|
+
if (type === MUTE_LOCAL_TYPE.video) {
|
|
39
|
+
videoMuteQueue.current.push({
|
|
40
|
+
resolveQueued: res,
|
|
41
|
+
rejectQueued: rej,
|
|
42
|
+
action: status ? ToggleState.disabled : ToggleState.enabled,
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
audioMuteQueue.current.push({
|
|
46
|
+
resolveQueued: res,
|
|
47
|
+
rejectQueued: rej,
|
|
48
|
+
action: status ? ToggleState.disabled : ToggleState.enabled,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
} else
|
|
53
|
+
return toggleMute(
|
|
54
|
+
type,
|
|
55
|
+
status ? ToggleState.disabled : ToggleState.enabled,
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
onSdkMuteVideo(async (res, rej, mute) => {
|
|
61
|
+
const status = typeof mute === 'function' ? mute(!local.video) : mute;
|
|
62
|
+
try {
|
|
63
|
+
await queuedToggleMute(MUTE_LOCAL_TYPE.video, status);
|
|
64
|
+
res();
|
|
65
|
+
} catch (e) {
|
|
66
|
+
rej(e);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
onSdkMuteAudio(async (res, rej, mute) => {
|
|
70
|
+
const status = typeof mute === 'function' ? mute(!local.audio) : mute;
|
|
71
|
+
try {
|
|
72
|
+
await queuedToggleMute(MUTE_LOCAL_TYPE.audio, status);
|
|
73
|
+
res();
|
|
74
|
+
} catch (e) {
|
|
75
|
+
rej(e);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return () => {
|
|
80
|
+
clearState('muteVideo');
|
|
81
|
+
clearState('muteAudio');
|
|
82
|
+
};
|
|
83
|
+
}, [local]);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<SdkMuteQueueContext.Provider value={{ videoMuteQueue, audioMuteQueue }}>
|
|
87
|
+
{props.children}
|
|
88
|
+
</SdkMuteQueueContext.Provider>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default SdkMuteToggleListener;
|
|
@@ -67,6 +67,7 @@ import {VideoCallProvider} from '../components/useVideoCall';
|
|
|
67
67
|
import {SdkApiContext, SDK_MEETING_TAG} from '../components/SdkApiContext';
|
|
68
68
|
import isSDK from '../utils/isSDK';
|
|
69
69
|
import {useSetMeetingInfo} from '../components/meeting-info/useSetMeetingInfo';
|
|
70
|
+
import SdkMuteToggleListener from '../components/SdkMuteToggleListener';
|
|
70
71
|
|
|
71
72
|
enum RnEncryptionEnum {
|
|
72
73
|
/**
|
|
@@ -252,15 +253,15 @@ const VideoCall: React.FC = () => {
|
|
|
252
253
|
}, 0);
|
|
253
254
|
},
|
|
254
255
|
UserJoined: (uid: UidType) => {
|
|
255
|
-
console.log(
|
|
256
|
+
console.log('UIKIT Callback: UserJoined', uid);
|
|
256
257
|
SDKEvents.emit('rtc-user-joined', uid);
|
|
257
258
|
},
|
|
258
259
|
UserOffline: (uid: UidType) => {
|
|
259
|
-
console.log(
|
|
260
|
+
console.log('UIKIT Callback: UserOffline', uid);
|
|
260
261
|
SDKEvents.emit('rtc-user-joined', uid);
|
|
261
262
|
},
|
|
262
263
|
RemoteAudioStateChanged: (uid: UidType, status: 0 | 2) => {
|
|
263
|
-
console.log(
|
|
264
|
+
console.log('UIKIT Callback: RemoteAudioStateChanged', uid, status);
|
|
264
265
|
if (status === 0) {
|
|
265
266
|
SDKEvents.emit('rtc-user-unpublished', uid, 'audio');
|
|
266
267
|
} else {
|
|
@@ -268,7 +269,7 @@ const VideoCall: React.FC = () => {
|
|
|
268
269
|
}
|
|
269
270
|
},
|
|
270
271
|
RemoteVideoStateChanged: (uid: UidType, status: 0 | 2) => {
|
|
271
|
-
console.log(
|
|
272
|
+
console.log('UIKIT Callback: RemoteVideoStateChanged', uid, status);
|
|
272
273
|
if (status === 0) {
|
|
273
274
|
SDKEvents.emit('rtc-user-unpublished', uid, 'video');
|
|
274
275
|
} else {
|
|
@@ -342,31 +343,33 @@ const VideoCall: React.FC = () => {
|
|
|
342
343
|
{!isMobileUA() && (
|
|
343
344
|
<PermissionHelper />
|
|
344
345
|
)}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
<
|
|
348
|
-
<
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
346
|
+
<SdkMuteToggleListener>
|
|
347
|
+
{callActive ? (
|
|
348
|
+
<VideoMeetingDataProvider>
|
|
349
|
+
<VideoCallProvider>
|
|
350
|
+
<VideoCallScreen />
|
|
351
|
+
</VideoCallProvider>
|
|
352
|
+
</VideoMeetingDataProvider>
|
|
353
|
+
) : $config.PRECALL ? (
|
|
354
|
+
<PreCallProvider
|
|
355
|
+
value={{
|
|
356
|
+
callActive,
|
|
357
|
+
setCallActive,
|
|
358
|
+
isCameraAvailable,
|
|
359
|
+
isMicAvailable,
|
|
360
|
+
setCameraAvailable,
|
|
361
|
+
setMicAvailable,
|
|
362
|
+
isPermissionRequested,
|
|
363
|
+
setIsPermissionRequested,
|
|
364
|
+
isSpeakerAvailable,
|
|
365
|
+
setSpeakerAvailable,
|
|
366
|
+
}}>
|
|
367
|
+
<Precall />
|
|
368
|
+
</PreCallProvider>
|
|
369
|
+
) : (
|
|
370
|
+
<></>
|
|
371
|
+
)}
|
|
372
|
+
</SdkMuteToggleListener>
|
|
370
373
|
</NetworkQualityProvider>
|
|
371
374
|
</CustomUserContextHolder>
|
|
372
375
|
</LocalUserContext>
|
|
@@ -44,9 +44,6 @@ export interface userEventsMapInterface {
|
|
|
44
44
|
'devices-selected-speaker-changed': (
|
|
45
45
|
deviceId: MediaDeviceInfo['deviceId'],
|
|
46
46
|
) => void;
|
|
47
|
-
'devices-device-list-updated': (
|
|
48
|
-
deviceId: MediaDeviceInfo['deviceId'],
|
|
49
|
-
) => void;
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
const SDKEvents = createNanoEvents<userEventsMapInterface>();
|
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
import {SdkMethodEvents} from '../SDKAppWrapper';
|
|
2
1
|
import {createNanoEvents, Emitter} from 'nanoevents';
|
|
2
|
+
import {
|
|
3
|
+
CustomizationApiInterface,
|
|
4
|
+
MeetingInfoContextInterface,
|
|
5
|
+
} from 'customization-api';
|
|
6
|
+
import {deviceId} from '../components/DeviceConfigure';
|
|
7
|
+
|
|
8
|
+
export interface SdkMethodEvents {
|
|
9
|
+
customize: (customization: CustomizationApiInterface) => void;
|
|
10
|
+
join(
|
|
11
|
+
roomid: string | Partial<MeetingInfoContextInterface['data']>,
|
|
12
|
+
skipPrecall?: boolean,
|
|
13
|
+
): MeetingInfoContextInterface['data'];
|
|
14
|
+
microphoneDevice: (deviceId: deviceId) => void;
|
|
15
|
+
speakerDevice: (deviceId: deviceId) => void;
|
|
16
|
+
cameraDevice: (deviceId: deviceId) => void;
|
|
17
|
+
muteAudio: (mute: boolean | ((currentMute: boolean) => boolean)) => void;
|
|
18
|
+
muteVideo: (mute: boolean | ((currentMute: boolean) => boolean)) => void;
|
|
19
|
+
}
|
|
3
20
|
|
|
4
21
|
type EventParameterHelper<T extends keyof SdkMethodEvents> = Parameters<
|
|
5
22
|
SdkMethodEvents[T]
|
|
@@ -15,6 +15,7 @@ import {useContext, useEffect, useRef, useState} from 'react';
|
|
|
15
15
|
import {ToggleState} from '../../agora-rn-uikit/src/Contexts/PropsContext';
|
|
16
16
|
import {isMobileUA, isWebInternal} from './common';
|
|
17
17
|
import {AppState} from 'react-native';
|
|
18
|
+
import {SdkMuteQueueContext} from '../components/SdkMuteToggleListener';
|
|
18
19
|
|
|
19
20
|
export enum MUTE_LOCAL_TYPE {
|
|
20
21
|
audio,
|
|
@@ -27,6 +28,8 @@ function useMuteToggleLocal() {
|
|
|
27
28
|
const {RtcEngine, dispatch} = useRtc();
|
|
28
29
|
const local = useLocalUserInfo();
|
|
29
30
|
|
|
31
|
+
const {videoMuteQueue, audioMuteQueue} = useContext(SdkMuteQueueContext);
|
|
32
|
+
|
|
30
33
|
const appState = useRef(AppState.currentState);
|
|
31
34
|
const [appStateVisible, setAppStateVisible] = useState(appState.current);
|
|
32
35
|
const isCamON = useRef(local.video);
|
|
@@ -69,7 +72,26 @@ function useMuteToggleLocal() {
|
|
|
69
72
|
}
|
|
70
73
|
}, [appStateVisible]);
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
const toggleMute = async (
|
|
76
|
+
type: MUTE_LOCAL_TYPE,
|
|
77
|
+
_action?: ToggleState,
|
|
78
|
+
_fromSdk?: boolean,
|
|
79
|
+
) => {
|
|
80
|
+
const queueRef =
|
|
81
|
+
type === MUTE_LOCAL_TYPE.video ? videoMuteQueue : audioMuteQueue;
|
|
82
|
+
|
|
83
|
+
const handleQueue = async () => {
|
|
84
|
+
if (queueRef.current.length > 0) {
|
|
85
|
+
const queueItem = queueRef.current.shift();
|
|
86
|
+
try {
|
|
87
|
+
await toggleMute(type, queueItem.action, true);
|
|
88
|
+
queueItem.resolveQueued();
|
|
89
|
+
} catch (e) {
|
|
90
|
+
queueItem.rejectQueued(e);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
73
95
|
switch (type) {
|
|
74
96
|
case MUTE_LOCAL_TYPE.audio:
|
|
75
97
|
let localAudioState = local.audio;
|
|
@@ -78,35 +100,45 @@ function useMuteToggleLocal() {
|
|
|
78
100
|
localAudioState === ToggleState.enabled ||
|
|
79
101
|
localAudioState === ToggleState.disabled
|
|
80
102
|
) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type: 'LocalMuteAudio',
|
|
84
|
-
value: [
|
|
85
|
-
localAudioState === ToggleState.enabled
|
|
86
|
-
? ToggleState.disabling
|
|
87
|
-
: ToggleState.enabling,
|
|
88
|
-
],
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
await RtcEngine.muteLocalAudioStream(
|
|
93
|
-
localAudioState === ToggleState.enabled,
|
|
94
|
-
);
|
|
95
|
-
// Enable UI
|
|
103
|
+
if (localAudioState !== _action) {
|
|
104
|
+
// Disable UI
|
|
96
105
|
dispatch({
|
|
97
106
|
type: 'LocalMuteAudio',
|
|
98
107
|
value: [
|
|
99
108
|
localAudioState === ToggleState.enabled
|
|
100
|
-
? ToggleState.
|
|
101
|
-
: ToggleState.
|
|
109
|
+
? ToggleState.disabling
|
|
110
|
+
: ToggleState.enabling,
|
|
102
111
|
],
|
|
103
112
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
await RtcEngine.muteLocalAudioStream(
|
|
116
|
+
localAudioState === ToggleState.enabled,
|
|
117
|
+
);
|
|
118
|
+
// Enable UI
|
|
119
|
+
dispatch({
|
|
120
|
+
type: 'LocalMuteAudio',
|
|
121
|
+
value: [
|
|
122
|
+
localAudioState === ToggleState.enabled
|
|
123
|
+
? ToggleState.disabled
|
|
124
|
+
: ToggleState.enabled,
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
handleQueue();
|
|
128
|
+
} catch (e) {
|
|
129
|
+
dispatch({
|
|
130
|
+
type: 'LocalMuteAudio',
|
|
131
|
+
value: [localAudioState],
|
|
132
|
+
});
|
|
133
|
+
handleQueue();
|
|
134
|
+
if (_fromSdk) {
|
|
135
|
+
throw e;
|
|
136
|
+
} else {
|
|
137
|
+
console.error('Error toggling audio', e);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
handleQueue();
|
|
110
142
|
}
|
|
111
143
|
}
|
|
112
144
|
break;
|
|
@@ -118,45 +150,57 @@ function useMuteToggleLocal() {
|
|
|
118
150
|
localVideoState === ToggleState.disabled
|
|
119
151
|
) {
|
|
120
152
|
// Disable UI
|
|
121
|
-
|
|
122
|
-
type: 'LocalMuteVideo',
|
|
123
|
-
value: [
|
|
124
|
-
localVideoState === ToggleState.enabled
|
|
125
|
-
? ToggleState.disabling
|
|
126
|
-
: ToggleState.enabling,
|
|
127
|
-
],
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
//enableLocalVideo not available on web
|
|
132
|
-
isWebInternal()
|
|
133
|
-
? await RtcEngine.muteLocalVideoStream(
|
|
134
|
-
localVideoState === ToggleState.enabled ? true : false,
|
|
135
|
-
)
|
|
136
|
-
: await RtcEngine.enableLocalVideo(
|
|
137
|
-
localVideoState === ToggleState.enabled ? false : true,
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
// Enable UI
|
|
153
|
+
if (localVideoState !== _action) {
|
|
141
154
|
dispatch({
|
|
142
155
|
type: 'LocalMuteVideo',
|
|
143
156
|
value: [
|
|
144
157
|
localVideoState === ToggleState.enabled
|
|
145
|
-
? ToggleState.
|
|
146
|
-
: ToggleState.
|
|
158
|
+
? ToggleState.disabling
|
|
159
|
+
: ToggleState.enabling,
|
|
147
160
|
],
|
|
148
161
|
});
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
//enableLocalVideo not available on web
|
|
165
|
+
isWebInternal()
|
|
166
|
+
? await RtcEngine.muteLocalVideoStream(
|
|
167
|
+
localVideoState === ToggleState.enabled ? true : false,
|
|
168
|
+
)
|
|
169
|
+
: await RtcEngine.enableLocalVideo(
|
|
170
|
+
localVideoState === ToggleState.enabled ? false : true,
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// Enable UI
|
|
174
|
+
dispatch({
|
|
175
|
+
type: 'LocalMuteVideo',
|
|
176
|
+
value: [
|
|
177
|
+
localVideoState === ToggleState.enabled
|
|
178
|
+
? ToggleState.disabled
|
|
179
|
+
: ToggleState.enabled,
|
|
180
|
+
],
|
|
181
|
+
});
|
|
182
|
+
handleQueue();
|
|
183
|
+
} catch (e) {
|
|
184
|
+
dispatch({
|
|
185
|
+
type: 'LocalMuteVideo',
|
|
186
|
+
value: [localVideoState],
|
|
187
|
+
});
|
|
188
|
+
handleQueue();
|
|
189
|
+
if (_fromSdk) {
|
|
190
|
+
throw e;
|
|
191
|
+
} else {
|
|
192
|
+
console.error('Error toggling video', e);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
handleQueue();
|
|
155
197
|
}
|
|
156
198
|
}
|
|
157
199
|
break;
|
|
158
200
|
}
|
|
159
201
|
};
|
|
202
|
+
|
|
203
|
+
return toggleMute;
|
|
160
204
|
}
|
|
161
205
|
|
|
162
206
|
export default useMuteToggleLocal;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// "files":["./customization-api/index.ts","./global.d.ts","./bridge/rtm/web/index.ts","./bridge/rtc/webNg/index.ts"],
|
|
5
5
|
// --------------------------------------------------------
|
|
6
6
|
// Use with typescript tsc command
|
|
7
|
-
"files": ["./
|
|
7
|
+
"files": ["./index.rsdk.tsx", "./global.d.ts"],
|
|
8
8
|
// --------------------------------------------------------
|
|
9
9
|
"compilerOptions": {
|
|
10
10
|
/* Basic Options */
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
48
48
|
|
|
49
49
|
/* Module Resolution Options */
|
|
50
|
-
|
|
51
|
-
"noResolve":
|
|
50
|
+
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
|
51
|
+
"noResolve": false /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
|
|
52
52
|
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
|
53
53
|
"resolveJsonModule": true,
|
|
54
54
|
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// "files":["./customization-api/index.ts","./global.d.ts","./bridge/rtm/web/index.ts","./bridge/rtc/webNg/index.ts"],
|
|
5
5
|
// --------------------------------------------------------
|
|
6
6
|
// Use with typescript tsc command
|
|
7
|
-
"files": ["./
|
|
7
|
+
"files": ["./index.wsdk.tsx", "./global.d.ts"],
|
|
8
8
|
// --------------------------------------------------------
|
|
9
9
|
"compilerOptions": {
|
|
10
10
|
/* Basic Options */
|