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.
Files changed (205) hide show
  1. package/Readme.md +11 -6
  2. package/package.json +1 -1
  3. package/template/Gulpfile.js +121 -83
  4. package/template/_gitignore +2 -2
  5. package/template/_package-lock.json +12959 -13248
  6. package/template/agora-rn-uikit/src/AgoraUIKit.tsx +2 -2
  7. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +2 -0
  8. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +3 -3
  9. package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +4 -5
  10. package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +3 -1
  11. package/template/agora-rn-uikit/src/Controls/LocalControls.tsx +2 -2
  12. package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +1 -1
  13. package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +1 -1
  14. package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +1 -1
  15. package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +1 -1
  16. package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +4 -4
  17. package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +7 -5
  18. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +1 -1
  19. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +1 -1
  20. package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +2 -2
  21. package/template/agora-rn-uikit/src/Rtc/Create.tsx +88 -43
  22. package/template/agora-rn-uikit/src/Rtc/Join.tsx +13 -4
  23. package/template/agora-rn-uikit/src/RtcConfigure.tsx +36 -19
  24. package/template/agora-rn-uikit/src/Utils/permission.ts +17 -6
  25. package/template/babel.config.js +9 -9
  26. package/template/bridge/rtc/webNg/RtcEngine.ts +51 -26
  27. package/template/customization-api/action-library.ts +22 -0
  28. package/template/{fpe-api/context.ts → customization-api/app-state.ts} +16 -14
  29. package/template/customization-api/customEvents.ts +9 -0
  30. package/template/{fpe-api/install.ts → customization-api/customize.ts} +27 -26
  31. package/template/{fpe-api → customization-api}/index.ts +11 -6
  32. package/template/{fpe-api/components.ts → customization-api/sub-components.ts} +22 -3
  33. package/template/{fpe-api → customization-api}/typeDefinition.ts +13 -14
  34. package/template/customization-api/utils.ts +30 -0
  35. package/template/{fpe-implementation → customization-implementation}/createHook.ts +0 -0
  36. package/template/{fpe-implementation/dummyFpe.ts → customization-implementation/dummyConfig.ts} +4 -4
  37. package/template/customization-implementation/index.ts +4 -0
  38. package/template/{fpe-api/useFpe.tsx → customization-implementation/useCustomization.tsx} +12 -12
  39. package/template/{fpe.config.js → customization.config.js} +11 -11
  40. package/template/electron/main/index.js +42 -35
  41. package/template/esbuild.rsdk.go +8 -17
  42. package/template/global.d.ts +4 -3
  43. package/template/index.rsdk.tsx +13 -5
  44. package/template/index.wsdk.tsx +21 -5
  45. package/template/package.json +3 -0
  46. package/template/react-native-toast-message/src/index.js +3 -7
  47. package/template/react-native-toast-message/src/{index.wsdk.js → index.sdk.tsx} +1 -1
  48. package/template/react-native-toast-message/src/styles.sdk.ts +17 -0
  49. package/template/src/App.tsx +8 -4
  50. package/template/src/AppWrapper.tsx +8 -6
  51. package/template/src/SDKAppWrapper.tsx +28 -21
  52. package/template/src/app-state/useLocalUserInfo.ts +8 -0
  53. package/template/src/app-state/useMessages.ts +52 -0
  54. package/template/src/atoms/PrimaryButton.tsx +2 -2
  55. package/template/src/atoms/SecondaryButton.tsx +12 -4
  56. package/template/src/atoms/TextInput.tsx +2 -2
  57. package/template/src/components/Chat.tsx +22 -11
  58. package/template/src/components/ChatContext.ts +10 -27
  59. package/template/src/components/Controls.native.tsx +13 -7
  60. package/template/src/components/Controls.tsx +15 -24
  61. package/template/src/components/DeviceConfigure.tsx +4 -3
  62. package/template/src/components/EventsConfigure.tsx +54 -0
  63. package/template/src/components/GridVideo.tsx +5 -6
  64. package/template/src/components/HostControlView.tsx +13 -19
  65. package/template/src/components/Navbar.tsx +54 -41
  66. package/template/src/components/NetworkQualityContext.tsx +4 -3
  67. package/template/src/components/ParticipantsView.tsx +7 -7
  68. package/template/src/components/PinnedVideo.tsx +3 -4
  69. package/template/src/components/Precall.native.tsx +3 -3
  70. package/template/src/components/Precall.tsx +14 -10
  71. package/template/src/components/RTMConfigure.tsx +61 -219
  72. package/template/src/components/SettingsView.tsx +6 -3
  73. package/template/src/components/Share.tsx +24 -18
  74. package/template/src/components/chat-messages/useChatMessages.tsx +397 -80
  75. package/template/src/components/chat-notification/useChatNotification.tsx +2 -2
  76. package/template/src/components/chat-ui/useChatUIControl.tsx +1 -1
  77. package/template/src/components/common/Logo.tsx +3 -2
  78. package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
  79. package/template/src/components/contexts/ScreenShareContext.tsx +3 -1
  80. package/template/src/components/contexts/VideoMeetingDataContext.tsx +85 -0
  81. package/template/src/components/contexts/WhiteboardContext.tsx +8 -8
  82. package/template/src/components/livestream/LiveStreamContext.tsx +88 -74
  83. package/template/src/components/meeting-info/useMeetingInfo.tsx +23 -19
  84. package/template/src/components/meeting-info/useSetMeetingInfo.tsx +1 -1
  85. package/template/src/components/participants/AllAudienceParticipants.tsx +2 -2
  86. package/template/src/components/participants/AllHostParticipants.tsx +4 -4
  87. package/template/src/components/participants/MeParticipant.tsx +5 -3
  88. package/template/src/components/participants/ParticipantName.tsx +2 -2
  89. package/template/src/components/participants/RemoteParticipants.tsx +9 -7
  90. package/template/src/components/precall/LocalMute.native.tsx +14 -10
  91. package/template/src/components/precall/LocalMute.tsx +7 -5
  92. package/template/src/components/precall/VideoPreview.native.tsx +6 -6
  93. package/template/src/components/precall/VideoPreview.tsx +3 -3
  94. package/template/src/components/precall/joinCallBtn.tsx +3 -3
  95. package/template/src/components/precall/meetingTitle.tsx +3 -1
  96. package/template/src/components/precall/selectDevice.tsx +2 -2
  97. package/template/src/components/precall/usePreCall.tsx +1 -1
  98. package/template/src/components/styles.ts +3 -3
  99. package/template/src/components/useShareLink.tsx +69 -29
  100. package/template/src/components/useUserPreference.tsx +16 -15
  101. package/template/src/components/useWakeLock.tsx +3 -3
  102. package/template/src/language/i18nTypes.ts +1 -1
  103. package/template/src/language/index.ts +2 -2
  104. package/template/src/language/useLanguage.tsx +2 -3
  105. package/template/src/pages/Authenticate.tsx +3 -2
  106. package/template/src/pages/Create.tsx +18 -20
  107. package/template/src/pages/Join.tsx +6 -7
  108. package/template/src/pages/VideoCall.tsx +74 -66
  109. package/template/src/pages/create/useCreate.tsx +1 -1
  110. package/template/src/pages/video-call/CustomUserContextHolder.tsx +14 -6
  111. package/template/src/pages/video-call/DefaultLayouts.ts +8 -8
  112. package/template/src/pages/video-call/{NameWithMicStatus.tsx → NameWithMicIcon.tsx} +8 -1
  113. package/template/src/pages/video-call/RenderComponent.tsx +7 -10
  114. package/template/src/pages/video-call/VideoCallScreen.tsx +31 -22
  115. package/template/src/pages/video-call/VideoComponent.tsx +13 -15
  116. package/template/src/pages/video-call/VideoRenderer.tsx +6 -6
  117. package/template/src/pages/video-call/useLayoutsData.ts +23 -0
  118. package/template/src/rtm/RTMEngine.ts +13 -0
  119. package/template/src/rtm-events/EventUtils.ts +20 -20
  120. package/template/src/rtm-events/EventsQueue.ts +9 -3
  121. package/template/src/rtm-events/constants.ts +5 -0
  122. package/template/src/rtm-events/index.tsx +1 -3
  123. package/template/src/{custom-events/CustomEvents.ts → rtm-events-api/Events.ts} +67 -61
  124. package/template/src/rtm-events-api/index.tsx +6 -0
  125. package/template/src/rtm-events-api/types.ts +22 -0
  126. package/template/src/subComponents/ChatBubble.tsx +24 -8
  127. package/template/src/subComponents/ChatContainer.tsx +24 -15
  128. package/template/src/subComponents/ChatInput.tsx +56 -42
  129. package/template/src/subComponents/LanguageSelector.tsx +2 -2
  130. package/template/src/subComponents/LayoutIconDropdown.native.tsx +5 -5
  131. package/template/src/subComponents/LayoutIconDropdown.tsx +7 -7
  132. package/template/src/subComponents/LocalAudioMute.tsx +3 -4
  133. package/template/src/subComponents/LocalEndCall.tsx +3 -6
  134. package/template/src/subComponents/LocalSwitchCamera.tsx +3 -4
  135. package/template/src/subComponents/LocalVideoMute.tsx +3 -3
  136. package/template/src/subComponents/NetworkQualityPill.tsx +8 -9
  137. package/template/src/subComponents/OpenInNativeButton.tsx +2 -3
  138. package/template/src/subComponents/RemoteAudioMute.tsx +5 -11
  139. package/template/src/subComponents/RemoteEndCall.tsx +3 -10
  140. package/template/src/subComponents/RemoteVideoMute.tsx +3 -10
  141. package/template/src/subComponents/SelectDevice.tsx +1 -1
  142. package/template/src/subComponents/SelectOAuth.tsx +3 -2
  143. package/template/src/subComponents/SidePanelButtons.ts +6 -5
  144. package/template/src/subComponents/TextWithTooltip.tsx +6 -2
  145. package/template/src/subComponents/{toastConfig.tsx → ToastConfig.tsx} +2 -2
  146. package/template/src/subComponents/chat/ChatParticipants.tsx +6 -5
  147. package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +2 -2
  148. package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +4 -3
  149. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +2 -2
  150. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +2 -4
  151. package/template/src/subComponents/livestream/index.ts +2 -2
  152. package/template/src/subComponents/recording/useRecording.tsx +44 -23
  153. package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +11 -5
  154. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +46 -34
  155. package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +97 -38
  156. package/template/src/subComponents/screenshare/useScreenshare.tsx +1 -1
  157. package/template/src/utils/SdkEvents.ts +9 -46
  158. package/template/src/utils/common.tsx +25 -9
  159. package/template/src/utils/getUniqueID.ts +5 -0
  160. package/template/src/utils/isMobileOrTablet.native.ts +2 -2
  161. package/template/src/utils/isMobileOrTablet.ts +21 -8
  162. package/template/src/utils/useButtonTemplate.tsx +1 -1
  163. package/template/src/utils/useCreateMeeting.ts +21 -10
  164. package/template/src/utils/useGetMeetingPhrase.ts +11 -8
  165. package/template/src/utils/{IsAttendeeUser.ts → useIsAttendee.ts} +3 -1
  166. package/template/src/utils/{isAudioEnabled.ts → useIsAudioEnabled.ts} +4 -4
  167. package/template/src/utils/{isHostUser.ts → useIsHost.ts} +13 -16
  168. package/template/src/utils/{isPSTNUser.ts → useIsPSTN.ts} +2 -2
  169. package/template/src/utils/{isScreenShareUser.ts → useIsScreenShare.ts} +0 -0
  170. package/template/src/utils/{isVideoEnabled.ts → useIsVideoEnabled.ts} +5 -6
  171. package/template/src/utils/useJoinMeeting.ts +8 -6
  172. package/template/src/utils/useLayout.tsx +5 -5
  173. package/template/src/utils/useMutePSTN.ts +5 -3
  174. package/template/src/utils/useMuteToggleLocal.ts +3 -4
  175. package/template/src/utils/useRemoteEndCall.ts +11 -10
  176. package/template/src/utils/useRemoteMute.ts +42 -20
  177. package/template/src/utils/useSidePanel.tsx +1 -1
  178. package/template/src/utils/useString.ts +2 -2
  179. package/template/src/utils/useUserName.ts +11 -0
  180. package/template/tsconfig_fpeApi.json +8 -9
  181. package/template/tsconfig_rsdk_index.json +8 -9
  182. package/template/tsconfig_wsdk_index.json +8 -9
  183. package/template/webpack.commons.js +9 -9
  184. package/template/webpack.rsdk.config.js +4 -2
  185. package/template/webpack.ts.config.js +6 -6
  186. package/template/webpack.wsdk.config.js +2 -1
  187. package/template/fpe-api/fpeEvents.ts +0 -9
  188. package/template/fpe-api/utils.ts +0 -61
  189. package/template/fpe-implementation/index.ts +0 -1
  190. package/template/fpe-todo.txt +0 -14
  191. package/template/src/components/RTMEvents.tsx +0 -84
  192. package/template/src/custom-events/index.tsx +0 -4
  193. package/template/src/custom-events/types.ts +0 -51
  194. package/template/src/pages/video-call/CustomLayout.ts +0 -17
  195. package/template/src/rtm-events/types.ts +0 -7
  196. package/template/src/utils/getMeetingInvite.ts +0 -53
  197. package/template/src/utils/useGroupMessages.ts +0 -24
  198. package/template/src/utils/useNavParams.ts +0 -6
  199. package/template/src/utils/useNavigateTo.ts +0 -8
  200. package/template/src/utils/usePrivateMessages.ts +0 -33
  201. package/template/src/utils/useSendControlMessage.ts +0 -51
  202. package/template/src/utils/useSendMessage.ts +0 -40
  203. package/template/src/utils/useSetUnreadMessageCount.ts +0 -43
  204. package/template/src/utils/useUnreadMessageCount.ts +0 -50
  205. package/template/src/utils/useUserList.ts +0 -26
@@ -17,8 +17,8 @@ const AgoraUIKit: React.FC<PropsInterface> = (props) => {
17
17
  <View style={{backgroundColor: '#000', flex: 1}}>
18
18
  <RtcConfigure>
19
19
  <RenderConsumer>
20
- {({renderList, renderPosition}) => {
21
- const [maxUid, ...minUids] = renderPosition;
20
+ {({renderList, activeUids}) => {
21
+ const [maxUid, ...minUids] = activeUids;
22
22
  return (
23
23
  <>
24
24
  <MaxVideoView user={renderList[maxUid]} key={maxUid} />
@@ -106,6 +106,7 @@ export interface RtcPropsInterface {
106
106
  // useBeforeCreate?: () => () => Promise<void>;
107
107
  // };
108
108
  geoFencing?: boolean;
109
+ audioRoom?: boolean;
109
110
  }
110
111
 
111
112
  export interface CallbacksInterface {
@@ -142,6 +143,7 @@ const initialValue: PropsInterface = {
142
143
  appId: '',
143
144
  channel: '',
144
145
  geoFencing: true,
146
+ audioRoom: false,
145
147
  },
146
148
  };
147
149
 
@@ -5,13 +5,13 @@ import type {DualStreamMode, RenderInterface} from './PropsContext';
5
5
 
6
6
  export type UidType = number;
7
7
 
8
- export interface RenderObjectInterface {
8
+ export interface RenderObjects {
9
9
  [key: number]: RenderInterface;
10
10
  }
11
11
 
12
12
  export interface RenderStateInterface {
13
- renderList: RenderObjectInterface;
14
- renderPosition: Array<UidType>;
13
+ renderList: RenderObjects;
14
+ activeUids: Array<UidType>;
15
15
  }
16
16
 
17
17
  export interface ActionInterface<T extends keyof CallbacksInterface> {
@@ -62,11 +62,10 @@ const BtnTemplate: React.FC<BtnTemplateInterface> = (props) => {
62
62
  tintColor: disabled ? 'grey' : props.color || theme || '#fff',
63
63
  }}
64
64
  resizeMode={'contain'}
65
- source={
66
- props.name && icons[props.name]
67
- ? {uri: icons[props.name]}
68
- : props.icon
69
- }
65
+ source={{
66
+ uri:
67
+ props.name && icons[props.name] ? icons[props.name] : props.icon,
68
+ }}
70
69
  />
71
70
  </View>
72
71
  <Text
@@ -49,7 +49,9 @@ const ImageIcon: React.FC<ImageIconInterface> = (props) => {
49
49
  props.style as object,
50
50
  ]}
51
51
  resizeMode={'contain'}
52
- source={props.name && icons[props.name] ? {uri: icons[props.name] } : props.icon}
52
+ source={{
53
+ uri: props.name && icons[props.name] ? icons[props.name] : props.icon,
54
+ }}
53
55
  />
54
56
  );
55
57
  };
@@ -30,10 +30,10 @@ function Controls(props: ControlsPropsInterface) {
30
30
  </View>
31
31
  {showButton ? (
32
32
  <RenderConsumer>
33
- {({renderList, renderPosition}) => (
33
+ {({renderList, activeUids}) => (
34
34
  <View style={{...styles.Controls, top: styles.Controls.top - 100}}>
35
35
  <RemoteControls
36
- user={renderList[renderPosition[0]]}
36
+ user={renderList[activeUids[0]]}
37
37
  showRemoteSwap={false}
38
38
  />
39
39
  </View>
@@ -17,7 +17,7 @@ export default function LocalMuteAudio(
17
17
  audio: action.value[0],
18
18
  },
19
19
  },
20
- renderPosition: [...state.renderPosition],
20
+ activeUids: [...state.activeUids],
21
21
  };
22
22
  return stateUpdate;
23
23
  }
@@ -17,7 +17,7 @@ export default function LocalMuteVideo(
17
17
  video: action.value[0],
18
18
  },
19
19
  },
20
- renderPosition: [...state.renderPosition],
20
+ activeUids: [...state.activeUids],
21
21
  };
22
22
  return stateUpdate;
23
23
  }
@@ -20,7 +20,7 @@ export default function RemoteAudioStateChanged(
20
20
  audio: audioState,
21
21
  },
22
22
  },
23
- renderPosition: [...state.renderPosition],
23
+ activeUids: [...state.activeUids],
24
24
  };
25
25
  return stateUpdate;
26
26
  }
@@ -23,7 +23,7 @@ export default function RemoteVideoStateChanged(
23
23
  : state.renderList[action.value[0]].video,
24
24
  },
25
25
  },
26
- renderPosition: [...state.renderPosition],
26
+ activeUids: [...state.activeUids],
27
27
  };
28
28
  return stateUpdate;
29
29
  }
@@ -22,12 +22,12 @@ export default function UpdateDualStreamMode(
22
22
 
23
23
  if (newMode === DualStreamMode.HIGH) {
24
24
  // Update everybody to high
25
- state.renderPosition.forEach(setHighStreamType);
25
+ state.activeUids.forEach(setHighStreamType);
26
26
  } else if (newMode === DualStreamMode.LOW) {
27
27
  // Update everybody to low
28
- state.renderPosition.forEach(setLowStreamType);
28
+ state.activeUids.forEach(setLowStreamType);
29
29
  } else {
30
- const [maxUid, ...minUids] = state.renderPosition;
30
+ const [maxUid, ...minUids] = state.activeUids;
31
31
  // if (newMode === DualStreamMode.DYNAMIC)
32
32
  // Max users are high other are low
33
33
  //setting high for maxuid
@@ -37,7 +37,7 @@ export default function UpdateDualStreamMode(
37
37
  }
38
38
  stateUpdate = {
39
39
  renderList: renderList,
40
- renderPosition: [...state.renderPosition],
40
+ activeUids: [...state.activeUids],
41
41
  };
42
42
  return stateUpdate;
43
43
  }
@@ -32,9 +32,11 @@ export default function UserJoined(
32
32
  ...typeData,
33
33
  },
34
34
  };
35
- let renderPosition = [...state.renderPosition, newUid];
36
- const [maxUid] = renderPosition;
37
- if (renderPosition.length === 2 && maxUid === localUid) {
35
+ let activeUids = state.activeUids.filter((i) => i === newUid).length
36
+ ? [...state.activeUids]
37
+ : [...state.activeUids, newUid];
38
+ const [maxUid] = activeUids;
39
+ if (activeUids.length === 2 && maxUid === localUid) {
38
40
  //Only one remote and local is maximized
39
41
  //Change stream type to high if dualStreaMode is DYNAMIC
40
42
  if (dualStreamMode === DualStreamMode.DYNAMIC) {
@@ -43,13 +45,13 @@ export default function UserJoined(
43
45
  //Swap render positions
44
46
  stateUpdate = {
45
47
  renderList: renderList,
46
- renderPosition: renderPosition.reverse(),
48
+ activeUids: activeUids.reverse(),
47
49
  };
48
50
  } else {
49
51
  //More than one remote
50
52
  stateUpdate = {
51
53
  renderList: renderList,
52
- renderPosition: renderPosition,
54
+ activeUids: activeUids,
53
55
  };
54
56
  }
55
57
 
@@ -12,7 +12,7 @@ export default function UserMuteRemoteAudio(
12
12
  audio: action.value[1],
13
13
  },
14
14
  },
15
- renderPosition: [...state.renderPosition],
15
+ activeUids: [...state.activeUids],
16
16
  };
17
17
  return stateUpdate;
18
18
  }
@@ -12,7 +12,7 @@ export default function UserMuteRemoteVideo(
12
12
  video: action.value[1],
13
13
  },
14
14
  },
15
- renderPosition: [...state.renderPosition],
15
+ activeUids: [...state.activeUids],
16
16
  };
17
17
  return stateUpdate;
18
18
  }
@@ -12,12 +12,12 @@ export default function UserOffline(
12
12
  // if (updatedRenderList[action.value[0]]) {
13
13
  // delete updatedRenderList[action.value[0]];
14
14
  // }
15
- const updatedRenderPosition = [...state.renderPosition].filter(
15
+ const updatedActiveUids = [...state.activeUids].filter(
16
16
  (uid) => uid !== action.value[0],
17
17
  );
18
18
  const stateUpdate: RenderStateInterface = {
19
19
  renderList: state.renderList,
20
- renderPosition: updatedRenderPosition,
20
+ activeUids: updatedActiveUids,
21
21
  };
22
22
 
23
23
  return stateUpdate;
@@ -2,6 +2,8 @@ import React, {useState, useEffect, useContext, useRef, FC} from 'react';
2
2
  import RtcEngine, {
3
3
  VideoEncoderConfiguration,
4
4
  AreaCode,
5
+ AudioProfile,
6
+ AudioScenario,
5
7
  } from 'react-native-agora';
6
8
  import {Platform} from 'react-native';
7
9
  import requestCameraAndAudioPermission from '../Utils/permission';
@@ -22,7 +24,7 @@ const Create = ({
22
24
  }) => {
23
25
  const [ready, setReady] = useState(false);
24
26
  const {callbacks, rtcProps, mode} = useContext(PropsContext);
25
- const {geoFencing = true} = rtcProps || {};
27
+ const {geoFencing = true, audioRoom = false} = rtcProps || {};
26
28
  let engine = useRef<RtcEngine>({} as RtcEngine);
27
29
  // commented for v1 release
28
30
  // const beforeCreate = rtcProps?.lifecycle?.useBeforeCreate
@@ -33,15 +35,23 @@ const Create = ({
33
35
 
34
36
  const enableVideoAndAudioWithDisabledState = async () => {
35
37
  try {
36
- await engine.current.enableVideo();
37
- dispatch({
38
- type: 'LocalMuteAudio',
39
- value: [ToggleState.disabled],
40
- });
41
- dispatch({
42
- type: 'LocalMuteVideo',
43
- value: [ToggleState.disabled],
44
- });
38
+ if (audioRoom === true) {
39
+ await engine.current.enableAudio();
40
+ dispatch({
41
+ type: 'LocalMuteAudio',
42
+ value: [ToggleState.disabled],
43
+ });
44
+ } else {
45
+ await engine.current.enableVideo();
46
+ dispatch({
47
+ type: 'LocalMuteAudio',
48
+ value: [ToggleState.disabled],
49
+ });
50
+ dispatch({
51
+ type: 'LocalMuteVideo',
52
+ value: [ToggleState.disabled],
53
+ });
54
+ }
45
55
  } catch (error) {
46
56
  const {status} = error as any;
47
57
  // App Builder web only
@@ -57,7 +67,7 @@ const Create = ({
57
67
  console.error('No audio device', audioError);
58
68
  }
59
69
 
60
- if (!videoError) {
70
+ if (!videoError && !audioRoom) {
61
71
  dispatch({
62
72
  type: 'LocalMuteVideo',
63
73
  value: [ToggleState.disabled],
@@ -71,15 +81,23 @@ const Create = ({
71
81
  };
72
82
  const enableVideoAndAudioWithEnabledState = async () => {
73
83
  try {
74
- await engine.current.enableVideo();
75
- dispatch({
76
- type: 'LocalMuteAudio',
77
- value: [ToggleState.enabled],
78
- });
79
- dispatch({
80
- type: 'LocalMuteVideo',
81
- value: [ToggleState.enabled],
82
- });
84
+ if (audioRoom === true) {
85
+ await engine.current.enableAudio();
86
+ dispatch({
87
+ type: 'LocalMuteAudio',
88
+ value: [ToggleState.enabled],
89
+ });
90
+ } else {
91
+ await engine.current.enableVideo();
92
+ dispatch({
93
+ type: 'LocalMuteAudio',
94
+ value: [ToggleState.enabled],
95
+ });
96
+ dispatch({
97
+ type: 'LocalMuteVideo',
98
+ value: [ToggleState.enabled],
99
+ });
100
+ }
83
101
  } catch (e) {
84
102
  const {status} = e as any;
85
103
 
@@ -96,7 +114,7 @@ const Create = ({
96
114
  console.error('No audio device', audioError);
97
115
  }
98
116
 
99
- if (!videoError) {
117
+ if (!videoError && !audioRoom) {
100
118
  dispatch({
101
119
  type: 'LocalMuteVideo',
102
120
  value: [ToggleState.enabled],
@@ -123,7 +141,7 @@ const Create = ({
123
141
  async function init() {
124
142
  if (Platform.OS === 'android') {
125
143
  //Request required permissions from Android
126
- await requestCameraAndAudioPermission();
144
+ await requestCameraAndAudioPermission(audioRoom);
127
145
  }
128
146
  // commented for v1 release
129
147
  // try {
@@ -159,17 +177,36 @@ const Create = ({
159
177
  } else {
160
178
  await engine.current.setChannelProfile(ChannelProfile.Communication);
161
179
  }
162
- if (rtcProps.profile) {
163
- if (Platform.OS === 'web') {
164
- // move this to bridge?
165
- // @ts-ignore
166
- await engine.current.setVideoProfile(rtcProps.profile);
167
- } else {
168
- const config: VideoEncoderConfiguration = quality[rtcProps.profile];
169
- await engine.current.setVideoEncoderConfiguration({
170
- ...config,
171
- bitrate: 0,
172
- });
180
+ if (!audioRoom) {
181
+ if (rtcProps.profile) {
182
+ if (Platform.OS === 'web') {
183
+ // move this to bridge?
184
+ // @ts-ignore
185
+ await engine.current.setVideoProfile(rtcProps.profile);
186
+ } else {
187
+ const config: VideoEncoderConfiguration =
188
+ quality[rtcProps.profile];
189
+ await engine.current.setVideoEncoderConfiguration({
190
+ ...config,
191
+ bitrate: 0,
192
+ });
193
+ }
194
+ }
195
+ } else {
196
+ //web will work even without audio profile
197
+ //but native need to set audio profile otherwise user will experience low audio issue
198
+ if (Platform.OS === 'android' || Platform.OS === 'ios') {
199
+ await engine.current.setAudioProfile(
200
+ AudioProfile.Default,
201
+ AudioScenario.Default,
202
+ );
203
+ //also audio route for voice-chat will work through earpiece not phonespeaker
204
+ //for audiolivecast it will work through phone speaker
205
+ //ref - https://docs.agora.io/en/help/integration-issues/profile_difference/#audio-route
206
+ //so setting into phone speaker manually as requested
207
+ if (mode == ChannelProfile.Communication) {
208
+ await engine.current.setEnableSpeakerphone(true);
209
+ }
173
210
  }
174
211
  }
175
212
 
@@ -271,16 +308,20 @@ const Create = ({
271
308
  if (isVideoEnabledRef.current) {
272
309
  // This unpublishes the current track
273
310
  await engine.current?.muteLocalAudioStream(true);
274
- await engine.current?.muteLocalVideoStream(true);
311
+ if (!audioRoom) {
312
+ await engine.current?.muteLocalVideoStream(true);
313
+ }
275
314
  // This updates the uid interface
276
315
  dispatch({
277
316
  type: 'LocalMuteAudio',
278
317
  value: [ToggleState.disabled],
279
318
  });
280
- dispatch({
281
- type: 'LocalMuteVideo',
282
- value: [ToggleState.disabled],
283
- });
319
+ if (!audioRoom) {
320
+ dispatch({
321
+ type: 'LocalMuteVideo',
322
+ value: [ToggleState.disabled],
323
+ });
324
+ }
284
325
  }
285
326
  }
286
327
  if (rtcProps.role == ClientRole.Audience) {
@@ -289,15 +330,19 @@ const Create = ({
289
330
  * Otherwise the setClientRole method call fails and throws an exception.
290
331
  */
291
332
  await engine.current?.muteLocalAudioStream(true);
292
- await engine.current?.muteLocalVideoStream(true);
333
+ if (!audioRoom) {
334
+ await engine.current?.muteLocalVideoStream(true);
335
+ }
293
336
  dispatch({
294
337
  type: 'LocalMuteAudio',
295
338
  value: [ToggleState.disabled],
296
339
  });
297
- dispatch({
298
- type: 'LocalMuteVideo',
299
- value: [ToggleState.disabled],
300
- });
340
+ if (!audioRoom) {
341
+ dispatch({
342
+ type: 'LocalMuteVideo',
343
+ value: [ToggleState.disabled],
344
+ });
345
+ }
301
346
  await engine.current?.setClientRole(ClientRole.Audience);
302
347
  }
303
348
  }
@@ -13,6 +13,7 @@ const Join: React.FC<{
13
13
  }> = ({children, precall, engineRef, uidState, dispatch}) => {
14
14
  let joinState = useRef(false);
15
15
  const {rtcProps} = useContext(PropsContext);
16
+ const {audioRoom = false} = rtcProps;
16
17
  //commented for v1 release
17
18
  // const beforeJoin = rtcProps?.lifecycle?.useBeforeJoin
18
19
  // ? rtcProps.lifecycle.useBeforeJoin()
@@ -29,8 +30,8 @@ const Join: React.FC<{
29
30
  console.error('Cannot leave the channel:', err);
30
31
  }
31
32
  }
32
- const {renderList, renderPosition} = uidState;
33
- const [maxUid] = renderPosition;
33
+ const {renderList, activeUids} = uidState;
34
+ const [maxUid] = activeUids;
34
35
  const videoState = renderList[maxUid].video;
35
36
  async function join() {
36
37
  if (
@@ -44,7 +45,11 @@ const Join: React.FC<{
44
45
  encryptionMode: rtcProps.encryption.mode,
45
46
  });
46
47
  }
47
- if (videoState === ToggleState.enabled && Platform.OS === 'ios') {
48
+ if (
49
+ !audioRoom &&
50
+ videoState === ToggleState.enabled &&
51
+ Platform.OS === 'ios'
52
+ ) {
48
53
  dispatch({
49
54
  type: 'LocalMuteVideo',
50
55
  value: [ToggleState.disabling],
@@ -70,7 +75,11 @@ const Join: React.FC<{
70
75
  null,
71
76
  rtcProps.uid || 0,
72
77
  );
73
- if (videoState === ToggleState.enabled && Platform.OS === 'ios') {
78
+ if (
79
+ !audioRoom &&
80
+ videoState === ToggleState.enabled &&
81
+ Platform.OS === 'ios'
82
+ ) {
74
83
  dispatch({
75
84
  type: 'LocalMuteVideo',
76
85
  value: [ToggleState.enabling],
@@ -46,7 +46,7 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
46
46
  type: 'rtc',
47
47
  },
48
48
  },
49
- renderPosition: [localUid],
49
+ activeUids: [localUid],
50
50
  };
51
51
 
52
52
  const [initialState, setInitialState] = React.useState(
@@ -97,7 +97,7 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
97
97
  ) => {
98
98
  const newState = {
99
99
  ...state,
100
- renderPosition: [...state.renderPosition, action.value[0]],
100
+ activeUids: [...state.activeUids, action.value[0]],
101
101
  renderList: {
102
102
  ...state.renderList,
103
103
  [action.value[0]]: {
@@ -203,16 +203,28 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
203
203
 
204
204
  const swapVideo = useCallback(
205
205
  (state: RenderStateInterface, newMaxUid: UidType) => {
206
- let renderPosition: RenderStateInterface['renderPosition'] = [
207
- ...state.renderPosition,
206
+ if (state?.activeUids?.indexOf(newMaxUid) === -1) {
207
+ //skip the update if new max uid is not joined yet.
208
+ return {};
209
+ }
210
+ let activeUids: RenderStateInterface['activeUids'] = [
211
+ ...state.activeUids,
208
212
  ];
209
213
  let renderList: RenderStateInterface['renderList'] = {
210
214
  ...state.renderList,
211
215
  };
216
+
212
217
  // Element which is currently maximized
213
- const [currentMaxUid] = renderPosition;
218
+ const [currentMaxUid] = activeUids;
214
219
 
215
220
  if (currentMaxUid === newMaxUid) {
221
+ //skip the update if new max uid is already maximized
222
+ return {};
223
+ }
224
+
225
+ const newMaxUidOldPosition = activeUids.findIndex((i) => i === newMaxUid);
226
+
227
+ if (!newMaxUidOldPosition) {
216
228
  return {};
217
229
  }
218
230
 
@@ -228,15 +240,11 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
228
240
  * else push newMaxUid at last position
229
241
  */
230
242
 
231
- const newMaxUidOldPosition = renderPosition.findIndex(
232
- (i) => i === newMaxUid,
233
- );
234
-
235
- renderPosition[0] = newMaxUid;
236
- renderPosition[newMaxUidOldPosition] = currentMaxUid;
243
+ activeUids[0] = newMaxUid;
244
+ activeUids[newMaxUidOldPosition] = currentMaxUid;
237
245
 
238
246
  return {
239
- renderPosition: renderPosition,
247
+ activeUids: activeUids,
240
248
  renderList: renderList,
241
249
  };
242
250
  },
@@ -248,16 +256,25 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
248
256
  */
249
257
  const dequeVideo = useCallback(
250
258
  (state: RenderStateInterface, newMaxUid: UidType) => {
251
- let renderPosition: RenderStateInterface['renderPosition'] = [
252
- ...state.renderPosition,
259
+ if (state?.activeUids?.indexOf(newMaxUid) === -1) {
260
+ //skip the update if new max uid is not joined yet.
261
+ return {};
262
+ }
263
+ let activeUids: RenderStateInterface['activeUids'] = [
264
+ ...state.activeUids,
253
265
  ];
254
266
  let renderList: RenderStateInterface['renderList'] = {
255
267
  ...state.renderList,
256
268
  };
269
+ if (!(newMaxUid in renderList)) {
270
+ //skip the update if new max uid is not joined yet.
271
+ return {};
272
+ }
257
273
  // Element which is currently maximized
258
- const [currentMaxUid] = renderPosition;
274
+ const [currentMaxUid] = activeUids;
259
275
 
260
276
  if (currentMaxUid === newMaxUid) {
277
+ //skip the update if new max uid is already maximized
261
278
  return {};
262
279
  }
263
280
 
@@ -267,14 +284,14 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
267
284
  // No need to modify the streamType if the mode is not dynamic
268
285
  }
269
286
 
270
- const minIds = renderPosition.filter(
287
+ const minIds = activeUids.filter(
271
288
  (uid) => uid !== newMaxUid && uid !== currentMaxUid,
272
289
  );
273
290
 
274
- renderPosition = [newMaxUid, currentMaxUid, ...minIds];
291
+ activeUids = [newMaxUid, currentMaxUid, ...minIds];
275
292
 
276
293
  return {
277
- renderPosition: renderPosition,
294
+ activeUids: activeUids,
278
295
  renderList: renderList,
279
296
  };
280
297
  },
@@ -303,7 +320,7 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
303
320
  <RenderProvider
304
321
  value={{
305
322
  renderList: uidState.renderList,
306
- renderPosition: uidState.renderPosition,
323
+ activeUids: uidState.activeUids,
307
324
  }}>
308
325
  {props.children}
309
326
  </RenderProvider>
@@ -1,14 +1,20 @@
1
- import {PermissionsAndroid} from 'react-native';
1
+ import {Permission, PermissionsAndroid} from 'react-native';
2
2
  /**
3
3
  * @name requestCameraAndAudioPermission
4
4
  * @description Function to request permission for Audio and Camera
5
5
  */
6
- export default async function requestCameraAndAudioPermission() {
6
+ export default async function requestCameraAndAudioPermission(
7
+ audioRoom: boolean,
8
+ ) {
7
9
  try {
8
- const granted = await PermissionsAndroid.requestMultiple([
9
- PermissionsAndroid.PERMISSIONS.CAMERA,
10
- PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
11
- ]);
10
+ const permissionsToRequest: Permission[] = [];
11
+ permissionsToRequest.push(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO);
12
+ if (!audioRoom) {
13
+ permissionsToRequest.push(PermissionsAndroid.PERMISSIONS.CAMERA);
14
+ }
15
+ const granted = await PermissionsAndroid.requestMultiple(
16
+ permissionsToRequest,
17
+ );
12
18
  if (
13
19
  granted['android.permission.RECORD_AUDIO'] ===
14
20
  PermissionsAndroid.RESULTS.GRANTED &&
@@ -16,6 +22,11 @@ export default async function requestCameraAndAudioPermission() {
16
22
  PermissionsAndroid.RESULTS.GRANTED
17
23
  ) {
18
24
  console.log('You can use the cameras & mic');
25
+ } else if (
26
+ granted['android.permission.RECORD_AUDIO'] ===
27
+ PermissionsAndroid.RESULTS.GRANTED
28
+ ) {
29
+ console.log('You can use mic');
19
30
  } else {
20
31
  console.log('Permission denied');
21
32
  }