agora-appbuilder-core 3.0.9 → 3.0.10

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 (248) hide show
  1. package/Readme.md +6 -0
  2. package/package.json +2 -2
  3. package/template/_package-lock.json +5871 -4728
  4. package/template/agora-rn-uikit/src/Contexts/LocalUserContext.tsx +4 -0
  5. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +18 -0
  6. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +2 -0
  7. package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +30 -26
  8. package/template/agora-rn-uikit/src/Controls/Icons.ts +30 -83
  9. package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +6 -6
  10. package/template/agora-rn-uikit/src/Reducer/ActiveSpeakerDetected.ts +11 -0
  11. package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +1 -0
  12. package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +1 -0
  13. package/template/agora-rn-uikit/src/Reducer/LocalPermissionState.ts +24 -0
  14. package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +1 -0
  15. package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +1 -0
  16. package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +1 -0
  17. package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +2 -0
  18. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +1 -0
  19. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +1 -0
  20. package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +1 -0
  21. package/template/agora-rn-uikit/src/Reducer/UserPin.ts +11 -0
  22. package/template/agora-rn-uikit/src/Reducer/index.ts +3 -0
  23. package/template/agora-rn-uikit/src/Rtc/Create.tsx +89 -1
  24. package/template/agora-rn-uikit/src/RtcConfigure.tsx +39 -2
  25. package/template/agora-rn-uikit/src/Views/MaxVideoView.native.tsx +15 -5
  26. package/template/agora-rn-uikit/src/Views/MaxVideoView.tsx +15 -9
  27. package/template/agora-rn-uikit/src/index.ts +3 -1
  28. package/template/android/app/build.gradle +1 -0
  29. package/template/android/app/src/main/AndroidManifest.xml +22 -15
  30. package/template/android/app/src/main/assets/fonts/SourceSansPro-Regular.ttf +0 -0
  31. package/template/android/app/src/main/assets/fonts/icomoon.ttf +0 -0
  32. package/template/android/app/src/main/java/com/helloworld/MainActivity.java +50 -0
  33. package/template/android/app/src/main/res/values/colors.xml +7 -0
  34. package/template/android/build.gradle +3 -3
  35. package/template/babel.config.js +1 -0
  36. package/template/bridge/rtc/webNg/RtcEngine.ts +110 -17
  37. package/template/customization-api/sub-components.ts +1 -1
  38. package/template/customization-api/typeDefinition.ts +2 -1
  39. package/template/electron/index.html +27 -27
  40. package/template/electron/renderer/index.js +1 -0
  41. package/template/global.d.ts +25 -4
  42. package/template/index.rsdk.tsx +1 -0
  43. package/template/index.web.js +2 -1
  44. package/template/index.wsdk.tsx +1 -1
  45. package/template/ios/HelloWorld/Info.plist +14 -1
  46. package/template/ios/HelloWorld.xcodeproj/project.pbxproj +17 -0
  47. package/template/metro.config.js +1 -1
  48. package/template/package.json +18 -7
  49. package/template/react-native-toast-message/index.d.ts +43 -43
  50. package/template/react-native-toast-message/src/colors/index.js +3 -2
  51. package/template/react-native-toast-message/src/components/base/index.js +46 -59
  52. package/template/react-native-toast-message/src/components/base/styles.js +16 -32
  53. package/template/react-native-toast-message/src/components/checkbox.js +178 -0
  54. package/template/react-native-toast-message/src/components/error.js +3 -2
  55. package/template/react-native-toast-message/src/components/info.js +3 -2
  56. package/template/react-native-toast-message/src/components/success.js +3 -2
  57. package/template/react-native-toast-message/src/index.js +122 -31
  58. package/template/react-native-toast-message/src/index.sdk.tsx +125 -35
  59. package/template/react-native-toast-message/src/styles.js +3 -4
  60. package/template/react-native-toast-message/src/styles.sdk.ts +3 -4
  61. package/template/react-native.config.js +7 -0
  62. package/template/src/App.tsx +6 -0
  63. package/template/src/AppWrapper.tsx +63 -28
  64. package/template/src/assets/font-styles.css +329 -0
  65. package/template/src/assets/fonts/SourceSansPro-Regular.ttf +0 -0
  66. package/template/src/assets/fonts/icomoon.ttf +0 -0
  67. package/template/src/assets/permission.png +0 -0
  68. package/template/src/assets/selection.json +1 -0
  69. package/template/src/atoms/ActionMenu.tsx +236 -0
  70. package/template/src/atoms/AnimatedActiveSpeaker.native.tsx +71 -0
  71. package/template/src/atoms/AnimatedActiveSpeaker.tsx +84 -0
  72. package/template/src/atoms/AnimatedRings.native.tsx +68 -0
  73. package/template/src/atoms/AnimatedRings.tsx +70 -0
  74. package/template/src/atoms/Card.tsx +61 -0
  75. package/template/src/atoms/CircularProgress.native.tsx +121 -0
  76. package/template/src/atoms/CircularProgress.tsx +102 -0
  77. package/template/src/atoms/CustomIcon.tsx +88 -0
  78. package/template/src/atoms/CustomSwitch.tsx +287 -0
  79. package/template/src/atoms/Dropdown.tsx +306 -0
  80. package/template/src/atoms/HorizontalRule.tsx +3 -1
  81. package/template/src/atoms/IconButton.tsx +162 -0
  82. package/template/src/atoms/ImageIcon.tsx +98 -0
  83. package/template/src/atoms/InfoBubble.tsx +291 -0
  84. package/template/src/atoms/Input.tsx +87 -0
  85. package/template/src/atoms/InviteInfo.tsx +166 -0
  86. package/template/src/atoms/LinkButton.tsx +28 -0
  87. package/template/src/atoms/OutlineButton.tsx +61 -0
  88. package/template/src/atoms/ParticipantsCount.tsx +73 -0
  89. package/template/src/atoms/Popup.tsx +147 -0
  90. package/template/src/atoms/PrimaryButton.tsx +51 -26
  91. package/template/src/atoms/RecordingInfo.tsx +49 -0
  92. package/template/src/atoms/SecondaryButton.tsx +8 -5
  93. package/template/src/atoms/Spacer.tsx +22 -0
  94. package/template/src/atoms/TertiaryButton.tsx +78 -0
  95. package/template/src/atoms/TextInput.tsx +12 -14
  96. package/template/src/atoms/Toggle.tsx +47 -0
  97. package/template/src/atoms/Tooltip.native.tsx +65 -0
  98. package/template/src/atoms/Tooltip.tsx +94 -0
  99. package/template/src/atoms/UserAvatar.tsx +60 -0
  100. package/template/src/components/Chat.tsx +86 -214
  101. package/template/src/components/ChatContext.ts +8 -1
  102. package/template/src/components/ColorConfigure.tsx +1 -1
  103. package/template/src/components/ColorContext.ts +1 -1
  104. package/template/src/components/CommonStyles.ts +44 -0
  105. package/template/src/components/Controls.tsx +342 -42
  106. package/template/src/components/{Controls.native.tsx → Controls1.native.tsx} +6 -4
  107. package/template/src/components/DeviceConfigure.tsx +461 -101
  108. package/template/src/components/DeviceContext.tsx +8 -4
  109. package/template/src/components/EventsConfigure.tsx +144 -7
  110. package/template/src/components/GraphQLProvider.tsx +1 -1
  111. package/template/src/components/GridVideo.tsx +59 -44
  112. package/template/src/components/HostControlView.tsx +114 -35
  113. package/template/src/components/Navbar.tsx +216 -398
  114. package/template/src/components/NetworkQualityContext.tsx +20 -20
  115. package/template/src/components/ParticipantsView.tsx +177 -154
  116. package/template/src/components/PinnedVideo.tsx +207 -120
  117. package/template/src/components/Precall.native.tsx +358 -119
  118. package/template/src/components/Precall.tsx +269 -135
  119. package/template/src/components/RTMConfigure.tsx +27 -4
  120. package/template/src/components/Router.electron.ts +1 -0
  121. package/template/src/components/Router.native.ts +1 -0
  122. package/template/src/components/Router.sdk.ts +1 -0
  123. package/template/src/components/Router.ts +1 -0
  124. package/template/src/components/Settings.tsx +26 -95
  125. package/template/src/components/SettingsView.tsx +251 -56
  126. package/template/src/components/Share.tsx +302 -273
  127. package/template/src/components/StorageContext.tsx +30 -3
  128. package/template/src/components/ToastComponent.tsx +8 -0
  129. package/template/src/components/chat-messages/useChatMessages.tsx +69 -23
  130. package/template/src/components/chat-ui/useChatUIControl.tsx +7 -0
  131. package/template/src/components/common/Error.tsx +20 -6
  132. package/template/src/components/common/Logo.tsx +16 -15
  133. package/template/src/components/contexts/LiveStreamDataContext.tsx +10 -5
  134. package/template/src/components/contexts/VideoMeetingDataContext.tsx +37 -7
  135. package/template/src/components/livestream/LiveStreamContext.tsx +270 -36
  136. package/template/src/components/livestream/Types.ts +39 -14
  137. package/template/src/components/livestream/index.ts +1 -0
  138. package/template/src/components/livestream/views/LiveStreamControls.tsx +12 -4
  139. package/template/src/components/participants/AllAudienceParticipants.tsx +101 -30
  140. package/template/src/components/participants/AllHostParticipants.tsx +103 -34
  141. package/template/src/components/participants/Participant.tsx +302 -0
  142. package/template/src/components/participants/ParticipantName.tsx +13 -7
  143. package/template/src/components/participants/ParticipantSectionTitle.tsx +35 -10
  144. package/template/src/components/participants/ScreenshareParticipants.tsx +144 -12
  145. package/template/src/components/participants/UserActionMenuOptions.tsx +398 -0
  146. package/template/src/components/popups/InvitePopup.tsx +115 -0
  147. package/template/src/components/popups/StopRecordingPopup.tsx +114 -0
  148. package/template/src/components/precall/LocalMute.tsx +84 -14
  149. package/template/src/components/precall/{LocalMute.native.tsx → LocalMute1.native.tsx} +21 -5
  150. package/template/src/components/precall/PermissionHelper.native.tsx +5 -0
  151. package/template/src/components/precall/PermissionHelper.tsx +126 -0
  152. package/template/src/components/precall/PreCallSettings.tsx +52 -0
  153. package/template/src/components/precall/VideoPreview.native.tsx +48 -3
  154. package/template/src/components/precall/VideoPreview.tsx +163 -7
  155. package/template/src/components/precall/joinCallBtn.tsx +15 -2
  156. package/template/src/components/precall/meetingTitle.tsx +15 -12
  157. package/template/src/components/precall/selectDevice.tsx +1 -21
  158. package/template/src/components/precall/textInput.tsx +32 -4
  159. package/template/src/components/precall/usePreCall.tsx +16 -0
  160. package/template/src/components/styles.ts +42 -21
  161. package/template/src/components/useShareLink.tsx +12 -14
  162. package/template/src/components/useToast.tsx +41 -0
  163. package/template/src/components/useVideoCall.tsx +65 -0
  164. package/template/src/language/default-labels/precallScreenLabels.ts +3 -3
  165. package/template/src/pages/Authenticate.tsx +5 -15
  166. package/template/src/pages/Create.tsx +293 -165
  167. package/template/src/pages/Endcall.tsx +148 -0
  168. package/template/src/pages/Join.tsx +93 -67
  169. package/template/src/pages/VideoCall.tsx +89 -64
  170. package/template/src/pages/video-call/ActionSheet.native.tsx +215 -0
  171. package/template/src/pages/video-call/ActionSheet.tsx +226 -0
  172. package/template/src/pages/video-call/ActionSheetContent.tsx +479 -0
  173. package/template/src/pages/video-call/ActionSheetHandle.tsx +38 -0
  174. package/template/src/pages/video-call/ActionSheetStyles.css +138 -0
  175. package/template/src/pages/video-call/DefaultLayouts.ts +4 -4
  176. package/template/src/pages/video-call/NameWithMicIcon.tsx +120 -44
  177. package/template/src/pages/video-call/RenderComponent.tsx +3 -2
  178. package/template/src/pages/video-call/SidePanelHeader.tsx +190 -0
  179. package/template/src/pages/video-call/VideoCallMobileView.tsx +139 -0
  180. package/template/src/pages/video-call/VideoCallScreen.native.tsx +37 -0
  181. package/template/src/pages/video-call/VideoCallScreen.tsx +45 -9
  182. package/template/src/pages/video-call/VideoComponent.tsx +18 -3
  183. package/template/src/pages/video-call/VideoRenderer.tsx +218 -60
  184. package/template/src/rtm-events/constants.ts +2 -0
  185. package/template/src/subComponents/ChatBubble.tsx +123 -83
  186. package/template/src/subComponents/ChatContainer.tsx +257 -84
  187. package/template/src/subComponents/ChatInput.ios.tsx +237 -0
  188. package/template/src/subComponents/ChatInput.tsx +61 -46
  189. package/template/src/subComponents/Checkbox.native.tsx +16 -5
  190. package/template/src/subComponents/Checkbox.tsx +2 -2
  191. package/template/src/subComponents/CopyJoinInfo.tsx +36 -58
  192. package/template/src/subComponents/EndcallPopup.tsx +107 -0
  193. package/template/src/subComponents/FallbackLogo.tsx +122 -40
  194. package/template/src/subComponents/LanguageSelector.tsx +1 -1
  195. package/template/src/subComponents/LayoutIconButton.tsx +201 -0
  196. package/template/src/subComponents/LayoutIconDropdown.tsx +131 -134
  197. package/template/src/subComponents/{LayoutIconDropdown.native.tsx → LayoutIconDropdown1.native.tsx} +4 -18
  198. package/template/src/subComponents/LocalAudioMute.tsx +119 -27
  199. package/template/src/subComponents/LocalEndCall.tsx +71 -33
  200. package/template/src/subComponents/LocalSwitchCamera.tsx +17 -30
  201. package/template/src/subComponents/LocalVideoMute.tsx +117 -27
  202. package/template/src/subComponents/Logo.tsx +3 -4
  203. package/template/src/subComponents/LogoutButton.tsx +1 -1
  204. package/template/src/subComponents/NetworkQualityPill.tsx +60 -63
  205. package/template/src/subComponents/OpenInNativeButton.tsx +3 -3
  206. package/template/src/subComponents/Recording.tsx +28 -29
  207. package/template/src/subComponents/RemoteAudioMute.tsx +83 -29
  208. package/template/src/subComponents/RemoteEndCall.tsx +8 -5
  209. package/template/src/subComponents/RemoteMutePopup.tsx +193 -0
  210. package/template/src/subComponents/RemoteVideoMute.tsx +74 -21
  211. package/template/src/subComponents/RemoveMeetingPopup.tsx +109 -0
  212. package/template/src/subComponents/RemoveScreensharePopup.tsx +109 -0
  213. package/template/src/subComponents/ScreenShareNotice.tsx +83 -8
  214. package/template/src/subComponents/SelectDevice.tsx +404 -61
  215. package/template/src/subComponents/SelectDeviceSettings.backup.tsx +207 -0
  216. package/template/src/subComponents/SelectOAuth.tsx +9 -8
  217. package/template/src/subComponents/SidePanelHeader.tsx +112 -0
  218. package/template/src/subComponents/ToastConfig.tsx +150 -10
  219. package/template/src/subComponents/chat/ChatParticipants.tsx +187 -78
  220. package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +95 -32
  221. package/template/src/subComponents/livestream/controls/LocalRaiseHand.tsx +29 -33
  222. package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +6 -6
  223. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +24 -11
  224. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +17 -10
  225. package/template/src/subComponents/recording/useRecording.tsx +79 -27
  226. package/template/src/subComponents/screenshare/ScreenshareButton.tsx +52 -70
  227. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +11 -2
  228. package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +26 -4
  229. package/template/src/theme/index.ts +46 -0
  230. package/template/src/utils/PlatformWrapper.tsx +21 -0
  231. package/template/src/utils/common.tsx +155 -1
  232. package/template/src/utils/hexadecimalTransparency.ts +108 -0
  233. package/template/src/utils/index.tsx +19 -0
  234. package/template/src/utils/isMobileOrTablet.ts +7 -2
  235. package/template/src/utils/pendingStateUpdateHelper.ts +19 -0
  236. package/template/src/utils/useButtonTemplate.tsx +1 -0
  237. package/template/src/utils/useFocus.tsx +46 -0
  238. package/template/src/utils/useIsActiveSpeaker.ts +27 -0
  239. package/template/src/utils/useIsHandRaised.ts +13 -0
  240. package/template/src/utils/useMuteToggleLocal.ts +54 -3
  241. package/template/src/utils/useRemoteEndScreenshare.ts +26 -0
  242. package/template/src/utils/useRemoteRequest.ts +84 -0
  243. package/template/web/index.html +5 -0
  244. package/template/webpack.commons.js +13 -8
  245. package/template/webpack.web.config.js +1 -0
  246. package/template/src/assets/icons.ts +0 -102
  247. package/template/src/components/participants/MeParticipant.tsx +0 -38
  248. package/template/src/components/participants/RemoteParticipants.tsx +0 -71
@@ -9,13 +9,40 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import React, {useContext} from 'react';
13
- import {Picker, StyleSheet, View, Text} from 'react-native';
14
- import {PropsContext, ClientRole} from '../../agora-rn-uikit';
12
+ import React, {useContext, useEffect, useState, useMemo} from 'react';
13
+ import {StyleSheet, View, Text} from 'react-native';
14
+ import {
15
+ PropsContext,
16
+ ClientRole,
17
+ LocalContext,
18
+ PermissionState,
19
+ LocalUserContext,
20
+ } from '../../agora-rn-uikit';
15
21
  import DeviceContext from '../components/DeviceContext';
16
22
  import ColorContext from '../components/ColorContext';
17
23
  import {useString} from '../utils/useString';
24
+ import Spacer from '../atoms/Spacer';
25
+ import Dropdown from '../atoms/Dropdown';
26
+ import {usePreCall} from '../components/precall/usePreCall';
27
+ import ThemeConfig from '../theme';
28
+ import {randomNameGenerator} from '../utils';
29
+ import pendingStateUpdateHelper from '../utils/pendingStateUpdateHelper';
18
30
  // import {dropdown} from '../../theme.json';
31
+
32
+ /*
33
+ * Chrome sometimes doesn't apply the "Default" prefix hence
34
+ * Checks if the deviceId is default and adds "Default - " to label
35
+ * string if not already present to differentiate from actual
36
+ * device entry.
37
+ */
38
+ const applyDefaultPrefixConditionally = (device: MediaDeviceInfo) => {
39
+ const {label, deviceId} = device;
40
+ if (deviceId === 'default') {
41
+ return label.includes('Default') ? label : 'Default - ' + label;
42
+ }
43
+ return label;
44
+ };
45
+
19
46
  /**
20
47
  * A component to diplay a dropdown and select a device.
21
48
  * It will add the selected device to the device context.
@@ -25,6 +52,7 @@ const useSelectDevice = (): [boolean, string] => {
25
52
  const {primaryColor} = useContext(ColorContext);
26
53
  const [btnTheme, setBtnTheme] = React.useState<string>(primaryColor);
27
54
  const [isPickerDisabled, setPickerDisabled] = React.useState<boolean>(false);
55
+
28
56
  React.useEffect(() => {
29
57
  if ($config.EVENT_MODE && rtcProps.role === ClientRole.Audience) {
30
58
  setPickerDisabled(true);
@@ -34,6 +62,7 @@ const useSelectDevice = (): [boolean, string] => {
34
62
  setBtnTheme(primaryColor);
35
63
  }
36
64
  }, [rtcProps?.role]);
65
+
37
66
  return [isPickerDisabled, btnTheme];
38
67
  };
39
68
 
@@ -44,31 +73,83 @@ interface SelectVideoDeviceProps {
44
73
  deviceList: MediaDeviceInfo[],
45
74
  isDisabled: boolean,
46
75
  ) => JSX.Element;
76
+ isIconDropdown?: boolean;
47
77
  }
48
78
 
49
79
  const SelectVideoDevice = (props: SelectVideoDeviceProps) => {
50
80
  const {selectedCam, setSelectedCam, deviceList} = useContext(DeviceContext);
51
81
  const [isPickerDisabled, btnTheme] = useSelectDevice();
82
+ const [isFocussed, setIsFocussed] = React.useState(false);
83
+ const [isPendingUpdate, setIsPendingUpdate] = useState(isPickerDisabled);
84
+ const local = useContext(LocalContext);
85
+
86
+ const data = useMemo(() => {
87
+ return deviceList
88
+ .filter((device) => {
89
+ if (device.kind === 'videoinput') {
90
+ return true;
91
+ }
92
+ })
93
+ ?.map((device: any) => {
94
+ if (device.kind === 'videoinput') {
95
+ return {
96
+ label: device.label,
97
+ value: device.deviceId,
98
+ };
99
+ }
100
+ });
101
+ }, [deviceList]);
102
+
103
+ useEffect(() => {
104
+ const selectedDeviceExists = Boolean(
105
+ data.find((device) => device.value === selectedCam),
106
+ );
107
+ if (isPendingUpdate) {
108
+ selectedDeviceExists && setIsPendingUpdate(false);
109
+ } else {
110
+ !selectedDeviceExists && data?.length && setIsPendingUpdate(true);
111
+ }
112
+ }, [selectedCam, data]);
113
+
114
+ const isPermissionGranted =
115
+ local.permissionStatus === PermissionState.GRANTED_FOR_CAM_AND_MIC ||
116
+ local.permissionStatus === PermissionState.GRANTED_FOR_CAM_ONLY;
52
117
  return props?.render ? (
53
118
  props.render(selectedCam, setSelectedCam, deviceList, isPickerDisabled)
54
119
  ) : (
55
- <Picker
56
- enabled={!isPickerDisabled}
57
- selectedValue={selectedCam}
58
- style={[{borderColor: btnTheme}, style.popupPicker]}
59
- onValueChange={(itemValue) => setSelectedCam(itemValue)}>
60
- {deviceList.map((device: any) => {
61
- if (device.kind === 'videoinput') {
62
- return (
63
- <Picker.Item
64
- label={device.label}
65
- value={device.deviceId}
66
- key={device.deviceId}
67
- />
68
- );
120
+ <>
121
+ <Text style={style.label}>Camera</Text>
122
+ <Dropdown
123
+ icon={
124
+ isPendingUpdate && isPermissionGranted
125
+ ? 'connection-loading'
126
+ : props?.isIconDropdown
127
+ ? 'video-on'
128
+ : undefined
129
+ }
130
+ enabled={!isPickerDisabled}
131
+ label={
132
+ !isPermissionGranted || !data || !data.length
133
+ ? 'No Camera Detected'
134
+ : isPendingUpdate
135
+ ? 'Updating'
136
+ : 'No Camera Selected'
69
137
  }
70
- })}
71
- </Picker>
138
+ data={isPermissionGranted ? data : []}
139
+ onSelect={({label, value}) => {
140
+ setIsFocussed(true);
141
+ try {
142
+ pendingStateUpdateHelper(
143
+ async () => await setSelectedCam(value),
144
+ setIsPendingUpdate,
145
+ );
146
+ } catch (e) {
147
+ setIsPendingUpdate(false);
148
+ }
149
+ }}
150
+ selectedValue={selectedCam}
151
+ />
152
+ </>
72
153
  );
73
154
  };
74
155
 
@@ -79,75 +160,337 @@ interface SelectAudioDeviceProps {
79
160
  deviceList: MediaDeviceInfo[],
80
161
  isDisabled: boolean,
81
162
  ) => JSX.Element;
163
+ isIconDropdown?: boolean;
82
164
  }
83
165
 
84
166
  const SelectAudioDevice = (props: SelectAudioDeviceProps) => {
85
167
  const {selectedMic, setSelectedMic, deviceList} = useContext(DeviceContext);
86
168
  const [isPickerDisabled, btnTheme] = useSelectDevice();
169
+ const [isFocussed, setIsFocussed] = useState(false);
170
+ const local = useContext(LocalContext);
171
+ const [isPendingUpdate, setIsPendingUpdate] = useState(isPickerDisabled);
172
+
173
+ const data = useMemo(() => {
174
+ return deviceList
175
+ .filter((device) => {
176
+ if (device.kind === 'audioinput') {
177
+ return true;
178
+ }
179
+ })
180
+ ?.map((device: any) => {
181
+ if (device.kind === 'audioinput') {
182
+ return {
183
+ label: applyDefaultPrefixConditionally(device),
184
+ value: device.deviceId,
185
+ };
186
+ }
187
+ });
188
+ }, [deviceList]);
189
+
190
+ useEffect(() => {
191
+ const selectedDeviceExists = Boolean(
192
+ data.find((device) => device.value === selectedMic),
193
+ );
194
+ if (isPendingUpdate) {
195
+ selectedDeviceExists && setIsPendingUpdate(false);
196
+ } else {
197
+ !selectedDeviceExists && data?.length && setIsPendingUpdate(true);
198
+ }
199
+ }, [selectedMic, data]);
200
+
201
+ const isPermissionGranted =
202
+ local.permissionStatus === PermissionState.GRANTED_FOR_CAM_AND_MIC ||
203
+ local.permissionStatus === PermissionState.GRANTED_FOR_MIC_ONLY;
87
204
  return props?.render ? (
88
205
  props.render(selectedMic, setSelectedMic, deviceList, isPickerDisabled)
89
206
  ) : (
90
- <Picker
91
- enabled={!isPickerDisabled}
92
- selectedValue={selectedMic}
93
- style={[{borderColor: btnTheme}, style.popupPicker]}
94
- onValueChange={(itemValue) => setSelectedMic(itemValue)}>
95
- {deviceList.map((device: any) => {
96
- if (device.kind === 'audioinput') {
97
- return (
98
- <Picker.Item
99
- label={device.label}
100
- value={device.deviceId}
101
- key={device.deviceId}
102
- />
103
- );
207
+ <View>
208
+ <Text style={style.label}>Microphone</Text>
209
+ <Dropdown
210
+ icon={
211
+ isPendingUpdate && isPermissionGranted
212
+ ? 'connection-loading'
213
+ : props?.isIconDropdown
214
+ ? 'mic-on'
215
+ : undefined
216
+ }
217
+ enabled={!isPickerDisabled && !isPendingUpdate}
218
+ selectedValue={selectedMic}
219
+ label={
220
+ !isPermissionGranted || !data || !data.length
221
+ ? 'No Microphone Detected'
222
+ : isPendingUpdate
223
+ ? 'Updating'
224
+ : 'No Microphone Selected'
225
+ }
226
+ data={isPermissionGranted ? data : []}
227
+ onSelect={({label, value}) => {
228
+ setIsFocussed(true);
229
+ try {
230
+ pendingStateUpdateHelper(
231
+ async () => await setSelectedMic(value),
232
+ setIsPendingUpdate,
233
+ );
234
+ } catch (e) {
235
+ setIsPendingUpdate(false);
236
+ }
237
+ }}
238
+ />
239
+ </View>
240
+ );
241
+ };
242
+
243
+ interface SelectSpeakerDeviceProps {
244
+ render?: (
245
+ selectedSpeaker: string,
246
+ setSelectedSpeaker: (speaker: string) => void,
247
+ deviceList: MediaDeviceInfo[],
248
+ isDisabled: boolean,
249
+ ) => JSX.Element;
250
+ isIconDropdown?: boolean;
251
+ }
252
+
253
+ const SelectSpeakerDevice = (props: SelectSpeakerDeviceProps) => {
254
+ const {selectedSpeaker, setSelectedSpeaker, deviceList} =
255
+ useContext(DeviceContext);
256
+ const local = useContext(LocalContext);
257
+ const [isPickerDisabled, btnTheme] = useSelectDevice();
258
+ const [isFocussed, setIsFocussed] = React.useState(false);
259
+ const [isPendingUpdate, setIsPendingUpdate] = useState(isPickerDisabled);
260
+ const newRandomDeviceId = randomNameGenerator(64).toUpperCase();
261
+
262
+ const data = useMemo(() => {
263
+ return deviceList
264
+ .filter((device) => {
265
+ if (device.kind === 'audiooutput') {
266
+ return true;
104
267
  }
105
- })}
106
- </Picker>
268
+ })
269
+ ?.map((device) => {
270
+ if (device.kind === 'audiooutput') {
271
+ return {
272
+ label: applyDefaultPrefixConditionally(device),
273
+ value: device.deviceId,
274
+ };
275
+ }
276
+ });
277
+ }, [deviceList]);
278
+
279
+ useEffect(() => {
280
+ const selectedDeviceExists = Boolean(
281
+ data.find((device) => device.value === selectedSpeaker),
282
+ );
283
+ if (isPendingUpdate) {
284
+ selectedDeviceExists && setIsPendingUpdate(false);
285
+ } else {
286
+ !selectedDeviceExists && data?.length && setIsPendingUpdate(true);
287
+ }
288
+ }, [selectedSpeaker, data]);
289
+
290
+ return props?.render ? (
291
+ props.render(
292
+ selectedSpeaker,
293
+ setSelectedSpeaker,
294
+ deviceList,
295
+ isPickerDisabled,
296
+ )
297
+ ) : (
298
+ <View>
299
+ <Text style={style.label}>Speaker</Text>
300
+ {(local.permissionStatus === PermissionState.GRANTED_FOR_CAM_AND_MIC ||
301
+ local.permissionStatus === PermissionState.GRANTED_FOR_MIC_ONLY) &&
302
+ (!data || data.length === 0) ? (
303
+ <Dropdown
304
+ icon={props?.isIconDropdown ? 'speaker' : undefined}
305
+ enabled={!isPickerDisabled}
306
+ selectedValue={newRandomDeviceId}
307
+ label={''}
308
+ data={[
309
+ {
310
+ value: newRandomDeviceId,
311
+ label: 'System Default Speaker Device',
312
+ },
313
+ ]}
314
+ onSelect={({label, value}) => {
315
+ setIsFocussed(true);
316
+ try {
317
+ pendingStateUpdateHelper(
318
+ async () => await setSelectedSpeaker(value),
319
+ setIsPendingUpdate,
320
+ );
321
+ } catch (e) {
322
+ setIsPendingUpdate(false);
323
+ }
324
+ }}
325
+ />
326
+ ) : (
327
+ <Dropdown
328
+ icon={
329
+ isPendingUpdate
330
+ ? 'connection-loading'
331
+ : props?.isIconDropdown
332
+ ? 'speaker'
333
+ : undefined
334
+ }
335
+ enabled={data && data.length && !isPendingUpdate}
336
+ selectedValue={selectedSpeaker}
337
+ label={
338
+ !data || !data.length
339
+ ? 'No Speaker Detected'
340
+ : isPendingUpdate
341
+ ? 'Updating'
342
+ : ''
343
+ }
344
+ data={data}
345
+ onSelect={({label, value}) => {
346
+ setIsFocussed(true);
347
+ setSelectedSpeaker(value);
348
+ }}
349
+ />
350
+ )}
351
+ </View>
107
352
  );
108
353
  };
109
354
 
110
- const SelectDevice = () => {
355
+ interface SelectDeviceProps {
356
+ isIconDropdown?: boolean;
357
+ }
358
+
359
+ const SelectDevice = (props: SelectDeviceProps) => {
111
360
  const [isPickerDisabled] = useSelectDevice();
361
+ const {deviceList} = useContext(DeviceContext);
362
+ const {setCameraAvailable, setMicAvailable, setSpeakerAvailable} =
363
+ usePreCall();
364
+
365
+ const [audioDevices, videoDevices, speakerDevices] = useMemo(
366
+ () =>
367
+ deviceList.reduce(
368
+ (prev, device) => {
369
+ const [audioDevices, videoDevices, speakerDevices] = prev;
370
+ if (device.kind === 'audioinput') {
371
+ audioDevices.push(device);
372
+ } else if (device.kind === 'videoinput') {
373
+ videoDevices.push(device);
374
+ } else if (device.kind === 'audiooutput') {
375
+ speakerDevices.push(device);
376
+ }
377
+
378
+ return [audioDevices, videoDevices, speakerDevices];
379
+ },
380
+ [[], [], []] as any,
381
+ ),
382
+ [deviceList],
383
+ );
384
+
385
+ // const audioDevices =
386
+ // deviceList.filter((device) => {
387
+ // if (device.kind === 'audioinput') {
388
+ // return true;
389
+ // }
390
+ // });
391
+ //
392
+ // const videoDevices = deviceList.filter((device) => {
393
+ // if (device.kind === 'videoinput') {
394
+ // return true;
395
+ // }
396
+ // });
397
+ // const speakerDevices = deviceList.filter((device) => {
398
+ // if (device.kind === 'audiooutput') {
399
+ // return true;
400
+ // }
401
+ // });
402
+
403
+ useEffect(() => {
404
+ if (audioDevices && audioDevices.length) {
405
+ setMicAvailable(true);
406
+ }
407
+ }, [audioDevices]);
408
+
409
+ useEffect(() => {
410
+ if (videoDevices && videoDevices.length) {
411
+ setCameraAvailable(true);
412
+ }
413
+ }, [videoDevices]);
414
+
415
+ useEffect(() => {
416
+ if (speakerDevices && speakerDevices.length) {
417
+ setSpeakerAvailable(true);
418
+ }
419
+ }, [speakerDevices]);
420
+
112
421
  //commented for v1 release
113
422
  // const settingScreenInfoMessage = useString('settingScreenInfoMessage')();
114
- const settingScreenInfoMessage = $config.AUDIO_ROOM
115
- ? 'Audio sharing is disabled for attendees. Raise hand to request permission to share.'
116
- : 'Video and Audio sharing is disabled for attendees. Raise hand to request permission to share.';
423
+ // const settingScreenInfoMessage = $config.AUDIO_ROOM
424
+ // ? 'Audio sharing is disabled for attendees. Raise hand to request permission to share.'
425
+ // : 'Video and Audio sharing is disabled for attendees. Raise hand to request permission to share.';
426
+ const settingScreenInfoMessage =
427
+ 'Attendees need to raise their hand to access the devices.';
117
428
  return (
118
- <View>
119
- <View style={{marginTop: 15}}></View>
120
- <View>
121
- {!$config.AUDIO_ROOM && <SelectVideoDevice />}
122
- <SelectAudioDevice />
123
- </View>
124
- <View style={{marginTop: 15}}></View>
125
- {$config.EVENT_MODE && isPickerDisabled && (
126
- <View>
127
- <Text style={style.infoTxt}>{settingScreenInfoMessage}</Text>
128
- </View>
129
- )}
130
- </View>
429
+ <>
430
+ <>
431
+ {$config.EVENT_MODE && isPickerDisabled && (
432
+ <>
433
+ <Spacer size={24} />
434
+ <View style={style.infoTxtContainer}>
435
+ <Text style={style.infoTxt}>{settingScreenInfoMessage}</Text>
436
+ </View>
437
+ </>
438
+ )}
439
+ <Spacer size={24} />
440
+ {!$config.AUDIO_ROOM && (
441
+ <>
442
+ <SelectVideoDevice {...props} />
443
+ <Spacer size={24} />
444
+ </>
445
+ )}
446
+ <SelectAudioDevice {...props} />
447
+ <Spacer size={24} />
448
+ <SelectSpeakerDevice {...props} />
449
+ <Spacer size={24} />
450
+ </>
451
+ </>
131
452
  );
132
453
  };
133
454
  export const SelectDeviceComponentsArray: [
134
455
  (props: SelectVideoDeviceProps) => JSX.Element,
135
456
  (props: SelectAudioDeviceProps) => JSX.Element,
136
- ] = [SelectVideoDevice, SelectAudioDevice];
457
+ (props: SelectSpeakerDeviceProps) => JSX.Element,
458
+ ] = [SelectVideoDevice, SelectAudioDevice, SelectSpeakerDevice];
137
459
 
138
460
  const style = StyleSheet.create({
139
461
  popupPicker: {
140
- height: 30,
141
- marginBottom: 10,
142
- borderRadius: 50,
462
+ // height: 30,
463
+ borderRadius: 12,
143
464
  paddingHorizontal: 15,
144
- fontSize: 15,
145
- minHeight: 35,
465
+ paddingVertical: 20,
466
+ fontSize: 14,
467
+ fontFamily: 'Source Sans Pro',
468
+ },
469
+ pickerItem: {
470
+ paddingLeft: 12,
471
+ paddingVertical: 24,
472
+ marginHorizontal: 8,
473
+ marginVertical: 20,
474
+ backgroundColor: '#FFFFFF',
475
+ },
476
+ infoTxtContainer: {
477
+ backgroundColor: $config.CARD_LAYER_4_COLOR,
478
+ borderRadius: 4,
146
479
  },
147
480
  infoTxt: {
148
- textAlign: 'center',
149
- fontSize: 12,
150
- color: '#FF0000',
481
+ textAlign: 'left',
482
+ fontSize: 16,
483
+ color: $config.FONT_COLOR,
484
+ fontFamily: 'Source Sans Pro',
485
+ fontWeight: '400',
486
+ padding: 12,
487
+ },
488
+ label: {
489
+ fontWeight: '400',
490
+ fontSize: ThemeConfig.FontSize.small,
491
+ color: $config.FONT_COLOR,
492
+ fontFamily: ThemeConfig.FontFamily.sansPro,
493
+ marginBottom: 12,
151
494
  },
152
495
  });
153
496