agora-appbuilder-core 2.3.0-beta.9 → 3.0.0
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/Readme.md +11 -6
- package/package.json +1 -1
- package/template/Gulpfile.js +121 -83
- package/template/_gitignore +2 -2
- package/template/_package-lock.json +12959 -13248
- package/template/agora-rn-uikit/src/AgoraUIKit.tsx +2 -2
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +2 -0
- package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +3 -3
- package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +4 -5
- package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +3 -1
- package/template/agora-rn-uikit/src/Controls/LocalControls.tsx +2 -2
- package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +4 -4
- package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +7 -5
- package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +2 -2
- package/template/agora-rn-uikit/src/Rtc/Create.tsx +88 -43
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +13 -4
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +36 -19
- package/template/agora-rn-uikit/src/Utils/permission.ts +17 -6
- package/template/babel.config.js +9 -9
- package/template/bridge/rtc/webNg/RtcEngine.ts +51 -26
- package/template/customization-api/action-library.ts +22 -0
- package/template/{fpe-api/context.ts → customization-api/app-state.ts} +16 -14
- package/template/customization-api/customEvents.ts +9 -0
- package/template/{fpe-api/install.ts → customization-api/customize.ts} +27 -26
- package/template/{fpe-api → customization-api}/index.ts +11 -6
- package/template/{fpe-api/components.ts → customization-api/sub-components.ts} +22 -3
- package/template/{fpe-api → customization-api}/typeDefinition.ts +13 -14
- package/template/customization-api/utils.ts +30 -0
- package/template/{fpe-implementation → customization-implementation}/createHook.ts +0 -0
- package/template/{fpe-implementation/dummyFpe.ts → customization-implementation/dummyConfig.ts} +4 -4
- package/template/customization-implementation/index.ts +4 -0
- package/template/{fpe-api/useFpe.tsx → customization-implementation/useCustomization.tsx} +12 -12
- package/template/{fpe.config.js → customization.config.js} +11 -11
- package/template/electron/main/index.js +42 -35
- package/template/esbuild.rsdk.go +8 -17
- package/template/global.d.ts +4 -3
- package/template/index.rsdk.tsx +13 -5
- package/template/index.wsdk.tsx +21 -5
- package/template/package.json +3 -0
- package/template/react-native-toast-message/src/index.js +3 -7
- package/template/react-native-toast-message/src/{index.wsdk.js → index.sdk.tsx} +1 -1
- package/template/react-native-toast-message/src/styles.sdk.ts +17 -0
- package/template/src/App.tsx +8 -4
- package/template/src/AppWrapper.tsx +8 -6
- package/template/src/SDKAppWrapper.tsx +28 -21
- package/template/src/app-state/useLocalUserInfo.ts +8 -0
- package/template/src/app-state/useMessages.ts +52 -0
- package/template/src/atoms/PrimaryButton.tsx +2 -2
- package/template/src/atoms/SecondaryButton.tsx +12 -4
- package/template/src/atoms/TextInput.tsx +2 -2
- package/template/src/components/Chat.tsx +22 -11
- package/template/src/components/ChatContext.ts +10 -27
- package/template/src/components/Controls.native.tsx +13 -7
- package/template/src/components/Controls.tsx +15 -24
- package/template/src/components/DeviceConfigure.tsx +4 -3
- package/template/src/components/EventsConfigure.tsx +54 -0
- package/template/src/components/GridVideo.tsx +5 -6
- package/template/src/components/HostControlView.tsx +13 -19
- package/template/src/components/Navbar.tsx +54 -41
- package/template/src/components/NetworkQualityContext.tsx +4 -3
- package/template/src/components/ParticipantsView.tsx +7 -7
- package/template/src/components/PinnedVideo.tsx +3 -4
- package/template/src/components/Precall.native.tsx +3 -3
- package/template/src/components/Precall.tsx +14 -10
- package/template/src/components/RTMConfigure.tsx +61 -219
- package/template/src/components/SettingsView.tsx +6 -3
- package/template/src/components/Share.tsx +24 -18
- package/template/src/components/chat-messages/useChatMessages.tsx +397 -80
- package/template/src/components/chat-notification/useChatNotification.tsx +2 -2
- package/template/src/components/chat-ui/useChatUIControl.tsx +1 -1
- package/template/src/components/common/Logo.tsx +3 -2
- package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
- package/template/src/components/contexts/ScreenShareContext.tsx +3 -1
- package/template/src/components/contexts/VideoMeetingDataContext.tsx +85 -0
- package/template/src/components/contexts/WhiteboardContext.tsx +8 -8
- package/template/src/components/livestream/LiveStreamContext.tsx +88 -74
- package/template/src/components/meeting-info/useMeetingInfo.tsx +23 -19
- package/template/src/components/meeting-info/useSetMeetingInfo.tsx +1 -1
- package/template/src/components/participants/AllAudienceParticipants.tsx +2 -2
- package/template/src/components/participants/AllHostParticipants.tsx +4 -4
- package/template/src/components/participants/MeParticipant.tsx +5 -3
- package/template/src/components/participants/ParticipantName.tsx +2 -2
- package/template/src/components/participants/RemoteParticipants.tsx +9 -7
- package/template/src/components/precall/LocalMute.native.tsx +14 -10
- package/template/src/components/precall/LocalMute.tsx +7 -5
- package/template/src/components/precall/VideoPreview.native.tsx +6 -6
- package/template/src/components/precall/VideoPreview.tsx +3 -3
- package/template/src/components/precall/joinCallBtn.tsx +3 -3
- package/template/src/components/precall/meetingTitle.tsx +3 -1
- package/template/src/components/precall/selectDevice.tsx +2 -2
- package/template/src/components/precall/usePreCall.tsx +1 -1
- package/template/src/components/styles.ts +3 -3
- package/template/src/components/useShareLink.tsx +69 -29
- package/template/src/components/useUserPreference.tsx +16 -15
- package/template/src/components/useWakeLock.tsx +3 -3
- package/template/src/language/i18nTypes.ts +1 -1
- package/template/src/language/index.ts +2 -2
- package/template/src/language/useLanguage.tsx +2 -3
- package/template/src/pages/Authenticate.tsx +3 -2
- package/template/src/pages/Create.tsx +18 -20
- package/template/src/pages/Join.tsx +6 -7
- package/template/src/pages/VideoCall.tsx +74 -66
- package/template/src/pages/create/useCreate.tsx +1 -1
- package/template/src/pages/video-call/CustomUserContextHolder.tsx +14 -6
- package/template/src/pages/video-call/DefaultLayouts.ts +8 -8
- package/template/src/pages/video-call/{NameWithMicStatus.tsx → NameWithMicIcon.tsx} +8 -1
- package/template/src/pages/video-call/RenderComponent.tsx +7 -10
- package/template/src/pages/video-call/VideoCallScreen.tsx +31 -22
- package/template/src/pages/video-call/VideoComponent.tsx +13 -15
- package/template/src/pages/video-call/VideoRenderer.tsx +6 -6
- package/template/src/pages/video-call/useLayoutsData.ts +23 -0
- package/template/src/rtm/RTMEngine.ts +13 -0
- package/template/src/rtm-events/EventUtils.ts +20 -20
- package/template/src/rtm-events/EventsQueue.ts +9 -3
- package/template/src/rtm-events/constants.ts +5 -0
- package/template/src/rtm-events/index.tsx +1 -3
- package/template/src/{custom-events/CustomEvents.ts → rtm-events-api/Events.ts} +67 -61
- package/template/src/rtm-events-api/index.tsx +6 -0
- package/template/src/rtm-events-api/types.ts +22 -0
- package/template/src/subComponents/ChatBubble.tsx +24 -8
- package/template/src/subComponents/ChatContainer.tsx +24 -15
- package/template/src/subComponents/ChatInput.tsx +56 -42
- package/template/src/subComponents/LanguageSelector.tsx +2 -2
- package/template/src/subComponents/LayoutIconDropdown.native.tsx +5 -5
- package/template/src/subComponents/LayoutIconDropdown.tsx +7 -7
- package/template/src/subComponents/LocalAudioMute.tsx +3 -4
- package/template/src/subComponents/LocalEndCall.tsx +3 -6
- package/template/src/subComponents/LocalSwitchCamera.tsx +3 -4
- package/template/src/subComponents/LocalVideoMute.tsx +3 -3
- package/template/src/subComponents/NetworkQualityPill.tsx +8 -9
- package/template/src/subComponents/OpenInNativeButton.tsx +2 -3
- package/template/src/subComponents/RemoteAudioMute.tsx +5 -11
- package/template/src/subComponents/RemoteEndCall.tsx +3 -10
- package/template/src/subComponents/RemoteVideoMute.tsx +3 -10
- package/template/src/subComponents/SelectDevice.tsx +1 -1
- package/template/src/subComponents/SelectOAuth.tsx +3 -2
- package/template/src/subComponents/SidePanelButtons.ts +6 -5
- package/template/src/subComponents/TextWithTooltip.tsx +6 -2
- package/template/src/subComponents/{toastConfig.tsx → ToastConfig.tsx} +2 -2
- package/template/src/subComponents/chat/ChatParticipants.tsx +6 -5
- package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +2 -2
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +4 -3
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +2 -2
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +2 -4
- package/template/src/subComponents/livestream/index.ts +2 -2
- package/template/src/subComponents/recording/useRecording.tsx +44 -23
- package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +11 -5
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +46 -34
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +97 -38
- package/template/src/subComponents/screenshare/useScreenshare.tsx +1 -1
- package/template/src/utils/SdkEvents.ts +9 -46
- package/template/src/utils/common.tsx +25 -9
- package/template/src/utils/getUniqueID.ts +5 -0
- package/template/src/utils/isMobileOrTablet.native.ts +2 -2
- package/template/src/utils/isMobileOrTablet.ts +21 -8
- package/template/src/utils/useButtonTemplate.tsx +1 -1
- package/template/src/utils/useCreateMeeting.ts +21 -10
- package/template/src/utils/useGetMeetingPhrase.ts +11 -8
- package/template/src/utils/{IsAttendeeUser.ts → useIsAttendee.ts} +3 -1
- package/template/src/utils/{isAudioEnabled.ts → useIsAudioEnabled.ts} +4 -4
- package/template/src/utils/{isHostUser.ts → useIsHost.ts} +13 -16
- package/template/src/utils/{isPSTNUser.ts → useIsPSTN.ts} +2 -2
- package/template/src/utils/{isScreenShareUser.ts → useIsScreenShare.ts} +0 -0
- package/template/src/utils/{isVideoEnabled.ts → useIsVideoEnabled.ts} +5 -6
- package/template/src/utils/useJoinMeeting.ts +8 -6
- package/template/src/utils/useLayout.tsx +5 -5
- package/template/src/utils/useMutePSTN.ts +5 -3
- package/template/src/utils/useMuteToggleLocal.ts +3 -4
- package/template/src/utils/useRemoteEndCall.ts +11 -10
- package/template/src/utils/useRemoteMute.ts +42 -20
- package/template/src/utils/useSidePanel.tsx +1 -1
- package/template/src/utils/useString.ts +2 -2
- package/template/src/utils/useUserName.ts +11 -0
- package/template/tsconfig_fpeApi.json +8 -9
- package/template/tsconfig_rsdk_index.json +8 -9
- package/template/tsconfig_wsdk_index.json +8 -9
- package/template/webpack.commons.js +9 -9
- package/template/webpack.rsdk.config.js +4 -2
- package/template/webpack.ts.config.js +6 -6
- package/template/webpack.wsdk.config.js +2 -1
- package/template/fpe-api/fpeEvents.ts +0 -9
- package/template/fpe-api/utils.ts +0 -61
- package/template/fpe-implementation/index.ts +0 -1
- package/template/fpe-todo.txt +0 -14
- package/template/src/components/RTMEvents.tsx +0 -84
- package/template/src/custom-events/index.tsx +0 -4
- package/template/src/custom-events/types.ts +0 -51
- package/template/src/pages/video-call/CustomLayout.ts +0 -17
- package/template/src/rtm-events/types.ts +0 -7
- package/template/src/utils/getMeetingInvite.ts +0 -53
- package/template/src/utils/useGroupMessages.ts +0 -24
- package/template/src/utils/useNavParams.ts +0 -6
- package/template/src/utils/useNavigateTo.ts +0 -8
- package/template/src/utils/usePrivateMessages.ts +0 -33
- package/template/src/utils/useSendControlMessage.ts +0 -51
- package/template/src/utils/useSendMessage.ts +0 -40
- package/template/src/utils/useSetUnreadMessageCount.ts +0 -43
- package/template/src/utils/useUnreadMessageCount.ts +0 -50
- package/template/src/utils/useUserList.ts +0 -26
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React, {createContext, useState, useEffect, useContext} from 'react';
|
|
2
|
+
import {createHook} from 'customization-implementation';
|
|
3
|
+
import {UidType, useLocalUid} from '../../../agora-rn-uikit';
|
|
4
|
+
import {useMeetingInfo} from '../meeting-info/useMeetingInfo';
|
|
5
|
+
import events, {EventPersistLevel} from '../../rtm-events-api';
|
|
6
|
+
import {EventNames} from '../../rtm-events';
|
|
7
|
+
import ChatContext from '../ChatContext';
|
|
8
|
+
|
|
9
|
+
export interface VideoMeetingDataInterface {
|
|
10
|
+
hostUids: UidType[];
|
|
11
|
+
attendeeUids: UidType[];
|
|
12
|
+
}
|
|
13
|
+
const VideoMeetingData = createContext<VideoMeetingDataInterface>({
|
|
14
|
+
hostUids: [],
|
|
15
|
+
attendeeUids: [],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
interface VideoMeetingDataProviderProps {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
const VideoMeetingDataProvider = (props: VideoMeetingDataProviderProps) => {
|
|
22
|
+
const {
|
|
23
|
+
data: {isHost},
|
|
24
|
+
} = useMeetingInfo();
|
|
25
|
+
const {hasUserJoinedRTM} = useContext(ChatContext);
|
|
26
|
+
const localUid = useLocalUid();
|
|
27
|
+
const [hostUids, setHostUids] = useState<UidType[]>([]);
|
|
28
|
+
const [attendeeUids, setAttendeeUids] = useState<UidType[]>([]);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
//set local uid
|
|
32
|
+
isHost ? setHostUids([localUid]) : setAttendeeUids([localUid]);
|
|
33
|
+
|
|
34
|
+
//listen for remote user role
|
|
35
|
+
//if remote user is host then add it in the hostUids
|
|
36
|
+
events.on(EventNames.VIDEO_MEETING_HOST, (data) => {
|
|
37
|
+
const payload = JSON.parse(data?.payload);
|
|
38
|
+
const hostUid = payload?.uid;
|
|
39
|
+
if (hostUid && hostUids.indexOf(hostUid) === -1) {
|
|
40
|
+
setHostUids((prevState) => [...prevState, hostUid]);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
//if remote user is not host then add it in the attendeeUids
|
|
45
|
+
events.on(EventNames.VIDEO_MEETING_ATTENDEE, (data) => {
|
|
46
|
+
const payload = JSON.parse(data?.payload);
|
|
47
|
+
const attendeeUid = payload?.uid;
|
|
48
|
+
if (attendeeUid && attendeeUids.indexOf(attendeeUid) === -1) {
|
|
49
|
+
setAttendeeUids((prevState) => [...prevState, attendeeUid]);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return () => {
|
|
54
|
+
events.off(EventNames.VIDEO_MEETING_HOST);
|
|
55
|
+
events.off(EventNames.VIDEO_MEETING_ATTENDEE);
|
|
56
|
+
};
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
//hasUserJoinedRTM ensure that RTM login successful and events can be sent.
|
|
61
|
+
if (hasUserJoinedRTM) {
|
|
62
|
+
//send user role event so newly joining user will get the previous user role details
|
|
63
|
+
events.send(
|
|
64
|
+
isHost
|
|
65
|
+
? EventNames.VIDEO_MEETING_HOST
|
|
66
|
+
: EventNames.VIDEO_MEETING_ATTENDEE,
|
|
67
|
+
JSON.stringify({uid: localUid}),
|
|
68
|
+
EventPersistLevel.LEVEL2,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
}, [isHost, hasUserJoinedRTM]);
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<VideoMeetingData.Provider
|
|
75
|
+
value={{
|
|
76
|
+
hostUids,
|
|
77
|
+
attendeeUids,
|
|
78
|
+
}}>
|
|
79
|
+
{props.children}
|
|
80
|
+
</VideoMeetingData.Provider>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
const useVideoMeetingData = createHook(VideoMeetingData);
|
|
84
|
+
|
|
85
|
+
export {useVideoMeetingData, VideoMeetingDataProvider};
|
|
@@ -6,9 +6,9 @@ import React, {
|
|
|
6
6
|
useEffect,
|
|
7
7
|
useState,
|
|
8
8
|
} from 'react';
|
|
9
|
-
import {createHook} from '
|
|
9
|
+
import {createHook} from 'customization-implementation';
|
|
10
10
|
import {filterObject} from '../../utils/index';
|
|
11
|
-
import {
|
|
11
|
+
import {useRtc} from 'customization-api';
|
|
12
12
|
|
|
13
13
|
export interface WhiteboardObjectInterface {
|
|
14
14
|
[key: number]: {
|
|
@@ -21,7 +21,7 @@ export interface WhiteboardContextInterface {
|
|
|
21
21
|
whiteboardData: WhiteboardObjectInterface;
|
|
22
22
|
setWhiteboardData: Dispatch<SetStateAction<WhiteboardObjectInterface>>;
|
|
23
23
|
}
|
|
24
|
-
const
|
|
24
|
+
const Whiteboard = createContext<WhiteboardContextInterface>({
|
|
25
25
|
whiteboardData: {},
|
|
26
26
|
setWhiteboardData: () => {},
|
|
27
27
|
});
|
|
@@ -32,7 +32,7 @@ interface WhiteboardProviderProps {
|
|
|
32
32
|
const WhiteboardProvider = (props: WhiteboardProviderProps) => {
|
|
33
33
|
const [whiteboardData, setWhiteboardData] =
|
|
34
34
|
useState<WhiteboardObjectInterface>({});
|
|
35
|
-
const {dispatch} =
|
|
35
|
+
const {dispatch} = useRtc();
|
|
36
36
|
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
const activeData = filterObject(
|
|
@@ -49,11 +49,11 @@ const WhiteboardProvider = (props: WhiteboardProviderProps) => {
|
|
|
49
49
|
}, [whiteboardData]);
|
|
50
50
|
|
|
51
51
|
return (
|
|
52
|
-
<
|
|
52
|
+
<Whiteboard.Provider value={{whiteboardData, setWhiteboardData}}>
|
|
53
53
|
{props.children}
|
|
54
|
-
</
|
|
54
|
+
</Whiteboard.Provider>
|
|
55
55
|
);
|
|
56
56
|
};
|
|
57
|
-
const
|
|
57
|
+
const useWhiteBoard = createHook(Whiteboard);
|
|
58
58
|
|
|
59
|
-
export {
|
|
59
|
+
export {useWhiteBoard, WhiteboardProvider};
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
import {ClientRole, useLocalUid, UidType} from '../../../agora-rn-uikit';
|
|
14
14
|
import {filterObject, isEmptyObject} from '../../utils';
|
|
15
15
|
import {useMeetingInfo} from '../meeting-info/useMeetingInfo';
|
|
16
|
-
import useUserList from '../../utils/useUserList';
|
|
17
16
|
import {useScreenshare} from '../../subComponents/screenshare/useScreenshare';
|
|
18
|
-
import
|
|
17
|
+
import events, {EventPersistLevel} from '../../rtm-events-api';
|
|
19
18
|
import {EventNames} from '../../rtm-events';
|
|
19
|
+
import {useRender} from 'customization-api';
|
|
20
20
|
|
|
21
21
|
const LiveStreamContext = createContext(null as unknown as liveStreamContext);
|
|
22
22
|
|
|
@@ -29,7 +29,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
29
29
|
const screenshareContextInstanceRef = useRef<any>();
|
|
30
30
|
screenshareContextInstanceRef.current = screenshareContextInstance;
|
|
31
31
|
|
|
32
|
-
const {renderList} =
|
|
32
|
+
const {renderList} = useRender();
|
|
33
33
|
const renderListRef = useRef<any>();
|
|
34
34
|
renderListRef.current = renderList;
|
|
35
35
|
|
|
@@ -54,7 +54,9 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
54
54
|
const {hasUserJoinedRTM} = useContext(ChatContext);
|
|
55
55
|
|
|
56
56
|
const {setRtcProps, rtcProps, callActive} = props?.value;
|
|
57
|
-
const {
|
|
57
|
+
const {
|
|
58
|
+
data: {isHost},
|
|
59
|
+
} = useMeetingInfo();
|
|
58
60
|
|
|
59
61
|
const [lastCheckedRequestTimestamp, setLastCheckedRequestTimestamp] =
|
|
60
62
|
useState(0);
|
|
@@ -89,7 +91,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
89
91
|
};
|
|
90
92
|
|
|
91
93
|
const addOrUpdateLiveStreamRequest = (
|
|
92
|
-
userUID:
|
|
94
|
+
userUID: UidType,
|
|
93
95
|
payload: Partial<raiseHandItemInterface>,
|
|
94
96
|
) => {
|
|
95
97
|
if (userUID && !isEmptyObject(payload)) {
|
|
@@ -121,11 +123,14 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
121
123
|
role: ClientRole.Audience,
|
|
122
124
|
});
|
|
123
125
|
// Audience notfies all host when request is rejected
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
events.send(
|
|
127
|
+
EventNames.RAISED_ATTRIBUTE,
|
|
128
|
+
JSON.stringify({
|
|
129
|
+
action: LiveStreamControlMessageEnum.notifyHostsInChannel,
|
|
130
|
+
value: RaiseHandValue.FALSE,
|
|
131
|
+
}),
|
|
132
|
+
EventPersistLevel.LEVEL2,
|
|
133
|
+
);
|
|
129
134
|
break;
|
|
130
135
|
case ClientRole.Broadcaster:
|
|
131
136
|
// Update local state
|
|
@@ -135,11 +140,14 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
135
140
|
role: ClientRole.Broadcaster,
|
|
136
141
|
});
|
|
137
142
|
// Audience notfies all host when request is approved
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
events.send(
|
|
144
|
+
EventNames.RAISED_ATTRIBUTE,
|
|
145
|
+
JSON.stringify({
|
|
146
|
+
action: LiveStreamControlMessageEnum.notifyHostsInChannel,
|
|
147
|
+
value: RaiseHandValue.TRUE,
|
|
148
|
+
}),
|
|
149
|
+
EventPersistLevel.LEVEL2,
|
|
150
|
+
);
|
|
143
151
|
default:
|
|
144
152
|
break;
|
|
145
153
|
}
|
|
@@ -181,15 +189,15 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
181
189
|
|
|
182
190
|
/** ******* SETTING UP ROLES BEGINS ******* */
|
|
183
191
|
React.useEffect(() => {
|
|
184
|
-
|
|
192
|
+
events.on(EventNames.ROLE_ATTRIBUTE, (data) => {
|
|
185
193
|
setRaiseHandList((prevState) => {
|
|
186
194
|
return {
|
|
187
195
|
...prevState,
|
|
188
196
|
[data.sender]: {
|
|
189
197
|
...prevState[data.sender],
|
|
190
198
|
role:
|
|
191
|
-
data.payload
|
|
192
|
-
? parseInt(data.payload
|
|
199
|
+
data.payload in ClientRole
|
|
200
|
+
? parseInt(data.payload)
|
|
193
201
|
: ClientRole.Audience,
|
|
194
202
|
},
|
|
195
203
|
};
|
|
@@ -199,10 +207,13 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
199
207
|
|
|
200
208
|
React.useEffect(() => {
|
|
201
209
|
if (!callActive || !hasUserJoinedRTM) return;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
events.send(
|
|
211
|
+
EventNames.ROLE_ATTRIBUTE,
|
|
212
|
+
JSON.stringify(
|
|
213
|
+
rtcProps.role in ClientRole ? rtcProps.role : ClientRole.Audience,
|
|
214
|
+
),
|
|
215
|
+
EventPersistLevel.LEVEL2,
|
|
216
|
+
);
|
|
206
217
|
setRaiseHandList((prevState) => {
|
|
207
218
|
return {
|
|
208
219
|
...prevState,
|
|
@@ -221,12 +232,16 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
221
232
|
|
|
222
233
|
React.useEffect(() => {
|
|
223
234
|
/** ********************** HOST EVENTS SECTION BEGINS ********************** */
|
|
224
|
-
|
|
235
|
+
events.on(EventNames.RAISED_ATTRIBUTE, (data) => {
|
|
225
236
|
if (!isHost) return;
|
|
226
|
-
|
|
237
|
+
const payload = JSON.parse(data.payload);
|
|
238
|
+
const action = payload.action;
|
|
239
|
+
const value = payload.value;
|
|
240
|
+
|
|
241
|
+
switch (action) {
|
|
227
242
|
// 1. Host can receive raise hand request with true or false value
|
|
228
243
|
case LiveStreamControlMessageEnum.raiseHandRequest:
|
|
229
|
-
switch (
|
|
244
|
+
switch (value) {
|
|
230
245
|
case RaiseHandValue.TRUE:
|
|
231
246
|
// Step 1: Show notifications
|
|
232
247
|
showToast(
|
|
@@ -261,7 +276,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
261
276
|
// 2. All Hosts in channel gets notified when an attendee's request gets approved or rejected
|
|
262
277
|
case LiveStreamControlMessageEnum.notifyHostsInChannel:
|
|
263
278
|
if (!isHost) return;
|
|
264
|
-
switch (
|
|
279
|
+
switch (value) {
|
|
265
280
|
case RaiseHandValue.TRUE:
|
|
266
281
|
addOrUpdateLiveStreamRequest(data.sender, {
|
|
267
282
|
ts: data.ts,
|
|
@@ -288,48 +303,42 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
288
303
|
|
|
289
304
|
/** ********************** AUDIENCE EVENTS SECTION BEGINS ********************** */
|
|
290
305
|
// 1. Audience receives this when the request is accepted by host
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
UpdtLocStateAndBCastAttr(ClientRole.Broadcaster, data.ts);
|
|
301
|
-
},
|
|
302
|
-
);
|
|
306
|
+
events.on(LiveStreamControlMessageEnum.raiseHandRequestAccepted, (data) => {
|
|
307
|
+
if (raiseHandList[localUidRef.current]?.raised === RaiseHandValue.FALSE)
|
|
308
|
+
return;
|
|
309
|
+
showToast(LSNotificationObject.RAISE_HAND_ACCEPTED);
|
|
310
|
+
// Promote user's privileges to host
|
|
311
|
+
changeClientRoleTo(ClientRole.Broadcaster);
|
|
312
|
+
// Audience updates its local attributes and notfies all host when request is approved
|
|
313
|
+
UpdtLocStateAndBCastAttr(ClientRole.Broadcaster, data.ts);
|
|
314
|
+
});
|
|
303
315
|
/** 2. Audience receives this when the request is rejected by host
|
|
304
316
|
* 2.a Audience receives this when the request is rejected by host which is not yet approved
|
|
305
317
|
* 2.b Audience receives this when the request when is demoted by the host
|
|
306
318
|
*/
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
UpdtLocStateAndBCastAttr(ClientRole.Audience, data.ts);
|
|
329
|
-
},
|
|
330
|
-
);
|
|
319
|
+
events.on(LiveStreamControlMessageEnum.raiseHandRequestRejected, (data) => {
|
|
320
|
+
/** 2.a */
|
|
321
|
+
if (
|
|
322
|
+
raiseHandListRef.current[localUidRef.current].role ==
|
|
323
|
+
ClientRole.Audience
|
|
324
|
+
) {
|
|
325
|
+
showToast(LSNotificationObject.RAISE_HAND_REJECTED);
|
|
326
|
+
} else if (
|
|
327
|
+
raiseHandListRef.current[localUidRef.current].role ==
|
|
328
|
+
ClientRole.Broadcaster
|
|
329
|
+
) {
|
|
330
|
+
/** 2.b */
|
|
331
|
+
showToast(LSNotificationObject.RAISE_HAND_APPROVED_REQUEST_RECALL);
|
|
332
|
+
screenshareContextInstanceRef?.current?.stopUserScreenShare(); // This will not exist on ios
|
|
333
|
+
|
|
334
|
+
// Demote user's privileges to audience
|
|
335
|
+
changeClientRoleTo(ClientRole.Audience);
|
|
336
|
+
}
|
|
337
|
+
// Audience updates its local attributes and notfies all host when demoted/request rejected
|
|
338
|
+
UpdtLocStateAndBCastAttr(ClientRole.Audience, data.ts);
|
|
339
|
+
});
|
|
331
340
|
// 3. Audience when receives kickUser notifies all host when is kicked out
|
|
332
|
-
|
|
341
|
+
events.on(controlMessageEnum.kickUser, (data) => {
|
|
333
342
|
// Audience updates its local attributes and notfies all host when they(audience) are kicked out
|
|
334
343
|
UpdtLocStateAndBCastAttr(ClientRole.Audience, data.ts);
|
|
335
344
|
});
|
|
@@ -345,25 +354,27 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
345
354
|
*/
|
|
346
355
|
|
|
347
356
|
const hostApprovesRequestOfUID = (uid: UidType) => {
|
|
348
|
-
addOrUpdateLiveStreamRequest(
|
|
357
|
+
addOrUpdateLiveStreamRequest(uid, {
|
|
349
358
|
raised: RaiseHandValue.TRUE,
|
|
350
359
|
ts: new Date().getTime(),
|
|
351
360
|
});
|
|
352
|
-
|
|
361
|
+
events.send(
|
|
353
362
|
LiveStreamControlMessageEnum.raiseHandRequestAccepted,
|
|
354
|
-
|
|
363
|
+
'',
|
|
364
|
+
EventPersistLevel.LEVEL1,
|
|
355
365
|
uid,
|
|
356
366
|
);
|
|
357
367
|
};
|
|
358
368
|
|
|
359
369
|
const hostRejectsRequestOfUID = (uid: UidType) => {
|
|
360
|
-
addOrUpdateLiveStreamRequest(
|
|
370
|
+
addOrUpdateLiveStreamRequest(uid, {
|
|
361
371
|
raised: RaiseHandValue.FALSE,
|
|
362
372
|
ts: new Date().getTime(),
|
|
363
373
|
});
|
|
364
|
-
|
|
374
|
+
events.send(
|
|
365
375
|
LiveStreamControlMessageEnum.raiseHandRequestRejected,
|
|
366
|
-
|
|
376
|
+
'',
|
|
377
|
+
EventPersistLevel.LEVEL1,
|
|
367
378
|
uid,
|
|
368
379
|
);
|
|
369
380
|
};
|
|
@@ -382,11 +393,14 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
|
|
|
382
393
|
if (raiseHandList[localUidRef.current]?.raised === RaiseHandValue.TRUE)
|
|
383
394
|
return;
|
|
384
395
|
showToast(LSNotificationObject.RAISE_HAND_REQUEST);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
396
|
+
events.send(
|
|
397
|
+
EventNames.RAISED_ATTRIBUTE,
|
|
398
|
+
JSON.stringify({
|
|
399
|
+
action: LiveStreamControlMessageEnum.raiseHandRequest,
|
|
400
|
+
value: RaiseHandValue.TRUE,
|
|
401
|
+
}),
|
|
402
|
+
EventPersistLevel.LEVEL1,
|
|
403
|
+
);
|
|
390
404
|
// Update local state
|
|
391
405
|
addOrUpdateLiveStreamRequest(localUidRef.current, {
|
|
392
406
|
raised: RaiseHandValue.TRUE,
|
|
@@ -10,38 +10,42 @@
|
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
import React, {createContext} from 'react';
|
|
13
|
-
import {createHook} from '
|
|
13
|
+
import {createHook} from 'customization-implementation';
|
|
14
14
|
import {UidType} from '../../../agora-rn-uikit';
|
|
15
15
|
export interface MeetingInfoContextInterface {
|
|
16
16
|
isJoinDataFetched?: boolean;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
data?: {
|
|
18
|
+
isHost: boolean;
|
|
19
|
+
meetingTitle: string;
|
|
20
|
+
roomId: {
|
|
21
|
+
attendee: string;
|
|
22
|
+
host?: string;
|
|
23
|
+
};
|
|
22
24
|
pstn?: {
|
|
23
25
|
number: string;
|
|
24
26
|
pin: string;
|
|
25
27
|
};
|
|
28
|
+
isSeparateHostLink: boolean;
|
|
29
|
+
channel?: string;
|
|
30
|
+
uid?: UidType;
|
|
31
|
+
token?: string;
|
|
32
|
+
rtmToken?: string;
|
|
33
|
+
encryptionSecret?: string;
|
|
34
|
+
screenShareUid?: string;
|
|
35
|
+
screenShareToken?: string;
|
|
26
36
|
};
|
|
27
|
-
isSeparateHostLink: boolean;
|
|
28
|
-
channel?: string;
|
|
29
|
-
uid?: UidType;
|
|
30
|
-
token?: string;
|
|
31
|
-
rtm?: string;
|
|
32
|
-
secret?: string;
|
|
33
|
-
screenShareUid?: string;
|
|
34
|
-
screenShareToken?: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export const MeetingInfoDefaultValue: MeetingInfoContextInterface = {
|
|
38
40
|
isJoinDataFetched: false,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
data: {
|
|
42
|
+
isHost: false,
|
|
43
|
+
meetingTitle: '',
|
|
44
|
+
roomId: {
|
|
45
|
+
attendee: '',
|
|
46
|
+
},
|
|
47
|
+
isSeparateHostLink: true,
|
|
43
48
|
},
|
|
44
|
-
isSeparateHostLink: true,
|
|
45
49
|
};
|
|
46
50
|
|
|
47
51
|
const MeetingInfoContext = createContext(MeetingInfoDefaultValue);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
import React, {createContext, SetStateAction} from 'react';
|
|
13
|
-
import {createHook} from '
|
|
13
|
+
import {createHook} from 'customization-implementation';
|
|
14
14
|
import {MeetingInfoContextInterface} from './useMeetingInfo';
|
|
15
15
|
|
|
16
16
|
export interface SetMeetingInfoContextInterface {
|
|
@@ -4,11 +4,11 @@ import RemoteEndCall from '../../subComponents/RemoteEndCall';
|
|
|
4
4
|
import ParticipantName from '../../components/participants/ParticipantName';
|
|
5
5
|
import chatContext from '../ChatContext';
|
|
6
6
|
import {useString} from '../../utils/useString';
|
|
7
|
-
import {
|
|
7
|
+
import {useRender} from 'customization-api';
|
|
8
8
|
|
|
9
9
|
const AllAudienceParticipants = (props: any) => {
|
|
10
10
|
const {p_style, isHost, uids} = props;
|
|
11
|
-
const {renderList} =
|
|
11
|
+
const {renderList} = useRender();
|
|
12
12
|
const {localUid} = useContext(chatContext);
|
|
13
13
|
//commented for v1 release
|
|
14
14
|
//const participantListPlaceholder = useString('participantListPlaceholder')();
|
|
@@ -3,8 +3,8 @@ import MeParticipant from './MeParticipant';
|
|
|
3
3
|
import ScreenshareParticipants from './ScreenshareParticipants';
|
|
4
4
|
import RemoteParticipants from './RemoteParticipants';
|
|
5
5
|
import {useString} from '../../utils/useString';
|
|
6
|
-
import useUserList from '../../utils/useUserList';
|
|
7
6
|
import {UidType, useLocalUid} from '../../../agora-rn-uikit';
|
|
7
|
+
import {useRender} from 'customization-api';
|
|
8
8
|
|
|
9
9
|
export default function AllHostParticipants(props: any) {
|
|
10
10
|
const {p_style, isHost} = props;
|
|
@@ -12,7 +12,7 @@ export default function AllHostParticipants(props: any) {
|
|
|
12
12
|
//commented for v1 release
|
|
13
13
|
//const remoteUserDefaultLabel = useString('remoteUserDefaultLabel')();
|
|
14
14
|
const remoteUserDefaultLabel = 'User';
|
|
15
|
-
const {renderList,
|
|
15
|
+
const {renderList, activeUids} = useRender();
|
|
16
16
|
const getParticipantName = (uid: UidType) => {
|
|
17
17
|
return renderList[uid]?.name || remoteUserDefaultLabel;
|
|
18
18
|
};
|
|
@@ -20,7 +20,7 @@ export default function AllHostParticipants(props: any) {
|
|
|
20
20
|
return (
|
|
21
21
|
<>
|
|
22
22
|
{/* User should see his name first */}
|
|
23
|
-
{
|
|
23
|
+
{activeUids.filter((uid) => uid === localUid).length > 0 && (
|
|
24
24
|
<MeParticipant
|
|
25
25
|
name={getParticipantName(localUid)}
|
|
26
26
|
p_style={p_style}
|
|
@@ -28,7 +28,7 @@ export default function AllHostParticipants(props: any) {
|
|
|
28
28
|
/>
|
|
29
29
|
)}
|
|
30
30
|
{/* Others Users in the call */}
|
|
31
|
-
{
|
|
31
|
+
{activeUids
|
|
32
32
|
.filter((uid) => uid !== localUid)
|
|
33
33
|
.map((uid) =>
|
|
34
34
|
renderList[uid]?.type === 'screenshare' ? (
|
|
@@ -26,9 +26,11 @@ const MeParticipant = (props: any) => {
|
|
|
26
26
|
<View style={[p_style.actionBtnIcon, {marginRight: 10}]}>
|
|
27
27
|
<LocalAudioMute buttonTemplateName={ButtonTemplateName.topBar} />
|
|
28
28
|
</View>
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
29
|
+
{!$config.AUDIO_ROOM && (
|
|
30
|
+
<View style={p_style.actionBtnIcon}>
|
|
31
|
+
<LocalVideoMute buttonTemplateName={ButtonTemplateName.topBar} />
|
|
32
|
+
</View>
|
|
33
|
+
)}
|
|
32
34
|
</View>
|
|
33
35
|
</View>
|
|
34
36
|
);
|
|
@@ -13,11 +13,11 @@ import React from 'react';
|
|
|
13
13
|
import {View, StyleSheet, useWindowDimensions, Platform} from 'react-native';
|
|
14
14
|
import TextWithToolTip from '../../subComponents/TextWithTooltip';
|
|
15
15
|
import {RFValue} from 'react-native-responsive-fontsize';
|
|
16
|
-
import {
|
|
16
|
+
import {isWebInternal} from '../../utils/common';
|
|
17
17
|
|
|
18
18
|
const ParticipantName = ({value}: {value: string}) => {
|
|
19
19
|
const {height, width} = useWindowDimensions();
|
|
20
|
-
const fontSize =
|
|
20
|
+
const fontSize = isWebInternal() ? 14 : 16;
|
|
21
21
|
return (
|
|
22
22
|
<View style={{flex: 1}}>
|
|
23
23
|
<TextWithToolTip
|
|
@@ -49,13 +49,15 @@ const RemoteParticipants = (props: remoteParticipantsInterface) => {
|
|
|
49
49
|
isHost={isHost}
|
|
50
50
|
/>
|
|
51
51
|
</View>
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
{!$config.AUDIO_ROOM && (
|
|
53
|
+
<View style={[p_styles.actionBtnIcon]}>
|
|
54
|
+
<RemoteVideoMute
|
|
55
|
+
uid={user.uid}
|
|
56
|
+
video={user.video}
|
|
57
|
+
isHost={isHost}
|
|
58
|
+
/>
|
|
59
|
+
</View>
|
|
60
|
+
)}
|
|
59
61
|
</View>
|
|
60
62
|
) : (
|
|
61
63
|
<></>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import {View, StyleSheet} from 'react-native';
|
|
14
|
-
import {
|
|
14
|
+
import {useCustomization} from 'customization-implementation';
|
|
15
15
|
import {isValidReactComponent} from '../../utils/common';
|
|
16
16
|
import LocalAudioMute, {
|
|
17
17
|
LocalAudioMuteProps,
|
|
@@ -24,7 +24,7 @@ import LocalSwitchCamera, {
|
|
|
24
24
|
} from '../../subComponents/LocalSwitchCamera';
|
|
25
25
|
|
|
26
26
|
const PreCallLocalMute: React.FC = () => {
|
|
27
|
-
const {VideoMute, AudioMute} =
|
|
27
|
+
const {VideoMute, AudioMute} = useCustomization((data) => {
|
|
28
28
|
let components: {
|
|
29
29
|
VideoMute: React.ComponentType<LocalAudioMuteProps>;
|
|
30
30
|
AudioMute: React.ComponentType<LocalVideoMuteProps>;
|
|
@@ -68,14 +68,18 @@ const PreCallLocalMute: React.FC = () => {
|
|
|
68
68
|
<View style={style.width50}>
|
|
69
69
|
<AudioMute />
|
|
70
70
|
</View>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
{!$config.AUDIO_ROOM && (
|
|
72
|
+
<>
|
|
73
|
+
<View style={style.width50} />
|
|
74
|
+
<View style={style.width50}>
|
|
75
|
+
<VideoMute />
|
|
76
|
+
</View>
|
|
77
|
+
<View style={style.width50} />
|
|
78
|
+
<View style={style.width50}>
|
|
79
|
+
<LocalSwitchCamera />
|
|
80
|
+
</View>
|
|
81
|
+
</>
|
|
82
|
+
)}
|
|
79
83
|
</>
|
|
80
84
|
);
|
|
81
85
|
};
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import {View, StyleSheet} from 'react-native';
|
|
14
|
-
import {
|
|
14
|
+
import {useCustomization} from 'customization-implementation';
|
|
15
15
|
import {isValidReactComponent} from '../../utils/common';
|
|
16
16
|
import LocalVideoMute, {
|
|
17
17
|
LocalVideoMuteProps,
|
|
@@ -21,7 +21,7 @@ import LocalAudioMute, {
|
|
|
21
21
|
} from '../../subComponents/LocalAudioMute';
|
|
22
22
|
|
|
23
23
|
const PreCallLocalMute: React.FC = () => {
|
|
24
|
-
const {VideoMute, AudioMute} =
|
|
24
|
+
const {VideoMute, AudioMute} = useCustomization((data) => {
|
|
25
25
|
let components: {
|
|
26
26
|
VideoMute: React.ComponentType<LocalAudioMuteProps>;
|
|
27
27
|
AudioMute: React.ComponentType<LocalVideoMuteProps>;
|
|
@@ -65,9 +65,11 @@ const PreCallLocalMute: React.FC = () => {
|
|
|
65
65
|
<View style={{alignSelf: 'center'}}>
|
|
66
66
|
<AudioMute />
|
|
67
67
|
</View>
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
|
|
68
|
+
{!$config.AUDIO_ROOM && (
|
|
69
|
+
<View style={{alignSelf: 'center'}}>
|
|
70
|
+
<VideoMute />
|
|
71
|
+
</View>
|
|
72
|
+
)}
|
|
71
73
|
</View>
|
|
72
74
|
);
|
|
73
75
|
};
|