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
@@ -1,29 +1,54 @@
1
+ import ImageIcon from '../../atoms/ImageIcon';
1
2
  import React from 'react';
2
- import {StyleSheet, Text} from 'react-native';
3
+ import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
4
+ import ThemeConfig from '../../theme';
3
5
 
4
6
  interface PropsInterface {
5
7
  title: string;
6
8
  count?: number;
9
+ isOpen?: boolean;
10
+ onPress?: () => void;
7
11
  }
8
12
 
9
13
  export default function ParticipantSectionTitle(props: PropsInterface) {
10
14
  const {title, count = 0} = props;
11
15
  return (
12
- <Text style={style.subheading}>
13
- {title} {count > 0 && <Text style={style.count}>({count})</Text>}
14
- </Text>
16
+ <TouchableOpacity
17
+ style={style.container}
18
+ onPress={() => props?.onPress && props?.onPress()}>
19
+ <Text style={style.subheading}>
20
+ {title} {count > 0 ? '(' + count + ')' : ''}
21
+ </Text>
22
+ <View style={style.iconView}>
23
+ <ImageIcon
24
+ iconType="plain"
25
+ name={props?.isOpen ? 'arrow-up' : 'arrow-down'}
26
+ iconSize={20}
27
+ tintColor={$config.SECONDARY_ACTION_COLOR}
28
+ />
29
+ </View>
30
+ </TouchableOpacity>
15
31
  );
16
32
  }
17
33
 
18
34
  const style = StyleSheet.create({
35
+ container: {
36
+ flex: 1,
37
+ flexDirection: 'row',
38
+ justifyContent: 'space-between',
39
+ backgroundColor: $config.CARD_LAYER_2_COLOR,
40
+ paddingHorizontal: 20,
41
+ },
19
42
  subheading: {
20
- fontSize: 15,
21
- letterSpacing: 0.8,
43
+ fontSize: 12,
44
+ fontFamily: 'Source Sans Pro',
22
45
  fontWeight: '700',
23
- color: $config.PRIMARY_FONT_COLOR,
46
+ color: $config.FONT_COLOR + ThemeConfig.EmphasisPlus.medium,
47
+ paddingVertical: 12,
48
+ alignSelf: 'center',
24
49
  },
25
- count: {
26
- fontSize: 13,
27
- fontWeight: '500',
50
+ iconView: {
51
+ paddingVertical: 8,
52
+ alignSelf: 'center',
28
53
  },
29
54
  });
@@ -9,20 +9,152 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import React from 'react';
13
- import {View, Text} from 'react-native';
14
- import ParticipantName from './ParticipantName';
12
+ import React, {useRef, useState} from 'react';
13
+ import {View, Text, StyleSheet, TouchableOpacity} from 'react-native';
14
+ import ThemeConfig from '../../theme';
15
+ import UserAvatar from '../../atoms/UserAvatar';
16
+ import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
17
+ import {RenderInterface} from 'customization-api';
18
+ import {isWebInternal, isMobileUA} from '../../utils/common';
19
+ import IconButton from '../../atoms/IconButton';
20
+ import UserActionMenuOptionsOptions from './UserActionMenuOptions';
15
21
 
16
- const ScreenshareParticipants = (props: any) => {
17
- const {p_styles, name} = props;
22
+ const ScreenshareParticipants = (props: {user: RenderInterface}) => {
23
+ const screenshareRef = useRef();
24
+ const [isHovered, setIsHovered] = useState(false);
25
+ const [actionMenuVisible, setActionMenuVisible] = useState(false);
26
+
27
+ const showModal = () => {
28
+ setActionMenuVisible((state) => !state);
29
+ };
18
30
  return (
19
- <View style={p_styles.participantRow}>
20
- <ParticipantName value={name} />
21
- <View style={p_styles.dummyView}>
22
- {/** its just the placeholder to adjust the UI. if no icon option to be shown */}
23
- <Text>local screen sharing</Text>
24
- </View>
25
- </View>
31
+ <>
32
+ {/* {renderActionMenu()} */}
33
+ <UserActionMenuOptionsOptions
34
+ actionMenuVisible={actionMenuVisible}
35
+ setActionMenuVisible={setActionMenuVisible}
36
+ user={props.user}
37
+ btnRef={screenshareRef}
38
+ from={'screenshare-participant'}
39
+ />
40
+ <PlatformWrapper showModal={showModal} setIsHovered={setIsHovered}>
41
+ <View style={styles.container}>
42
+ <View style={styles.userInfoContainer}>
43
+ <View style={styles.bgContainerStyle}>
44
+ <UserAvatar
45
+ name={props.user.name}
46
+ containerStyle={styles.containerStyle}
47
+ textStyle={styles.textStyle}
48
+ />
49
+ </View>
50
+ <View style={{alignSelf: 'center'}}>
51
+ <Text style={styles.participantNameText}>{props.user.name}</Text>
52
+ </View>
53
+ </View>
54
+ {true ? (
55
+ <View
56
+ style={styles.iconContainer}
57
+ ref={screenshareRef}
58
+ collapsable={false}>
59
+ {isHovered || actionMenuVisible || isMobileUA() ? (
60
+ //todo mobile by default it should show
61
+ <View
62
+ style={{
63
+ width: 24,
64
+ height: 24,
65
+ alignSelf: 'center',
66
+ justifyContent: 'center',
67
+ alignItems: 'center',
68
+ borderRadius: 20,
69
+ }}>
70
+ <IconButton
71
+ hoverEffect={true}
72
+ hoverEffectStyle={{
73
+ backgroundColor:
74
+ $config.CARD_LAYER_5_COLOR +
75
+ hexadecimalTransparency['20%'],
76
+ borderRadius: 20,
77
+ padding: 5,
78
+ }}
79
+ iconProps={{
80
+ iconType: 'plain',
81
+ name: 'more-menu',
82
+ iconSize: 20,
83
+ tintColor: $config.SECONDARY_ACTION_COLOR,
84
+ }}
85
+ onPress={() => {
86
+ showModal();
87
+ }}
88
+ />
89
+ </View>
90
+ ) : (
91
+ <></>
92
+ )}
93
+ </View>
94
+ ) : (
95
+ <></>
96
+ )}
97
+ </View>
98
+ </PlatformWrapper>
99
+ </>
26
100
  );
27
101
  };
28
102
  export default ScreenshareParticipants;
103
+
104
+ const PlatformWrapper = ({children, showModal, setIsHovered}) => {
105
+ return isWebInternal() ? (
106
+ <div
107
+ onMouseEnter={() => {
108
+ setIsHovered(true);
109
+ }}
110
+ onMouseLeave={() => {
111
+ setIsHovered(false);
112
+ }}>
113
+ {children}
114
+ </div>
115
+ ) : (
116
+ <>{children}</>
117
+ );
118
+ };
119
+
120
+ const styles = StyleSheet.create({
121
+ bgContainerStyle: {
122
+ backgroundColor: $config.VIDEO_AUDIO_TILE_AVATAR_COLOR,
123
+ width: 36,
124
+ height: 36,
125
+ borderRadius: 18,
126
+ marginRight: 8,
127
+ },
128
+ containerStyle: {
129
+ width: 36,
130
+ height: 36,
131
+ borderRadius: 18,
132
+ },
133
+ textStyle: {
134
+ fontSize: ThemeConfig.FontSize.tiny,
135
+ lineHeight: 10,
136
+ fontWeight: '400',
137
+ color: $config.CARD_LAYER_1_COLOR,
138
+ },
139
+ participantNameText: {
140
+ fontWeight: '400',
141
+ fontSize: 12,
142
+ lineHeight: 15,
143
+ fontFamily: ThemeConfig.FontFamily.sansPro,
144
+ flexDirection: 'row',
145
+ color: $config.FONT_COLOR,
146
+ textAlign: 'left',
147
+ },
148
+ container: {
149
+ flexDirection: 'row',
150
+ justifyContent: 'space-between',
151
+ paddingHorizontal: 20,
152
+ paddingVertical: 8,
153
+ },
154
+ userInfoContainer: {
155
+ flexDirection: 'row',
156
+ },
157
+ iconContainer: {
158
+ flexDirection: 'row',
159
+ },
160
+ });
@@ -0,0 +1,398 @@
1
+ import React, {useContext, useEffect, useRef, useState} from 'react';
2
+ import {
3
+ MUTE_REMOTE_TYPE,
4
+ RenderInterface,
5
+ SidePanelType,
6
+ useLayout,
7
+ useLocalUid,
8
+ useMeetingInfo,
9
+ useRemoteMute,
10
+ useRender,
11
+ useRtc,
12
+ useSidePanel,
13
+ } from 'customization-api';
14
+ import {getPinnedLayoutName} from '../../pages/video-call/DefaultLayouts';
15
+ import useRemoteRequest, {
16
+ REQUEST_REMOTE_TYPE,
17
+ } from '../../utils/useRemoteRequest';
18
+ import ActionMenu, {ActionMenuItem} from '../../atoms/ActionMenu';
19
+ import {useChatMessages} from '../chat-messages/useChatMessages';
20
+ import {useLiveStreamDataContext} from '../contexts/LiveStreamDataContext';
21
+ import useRemoteEndCall from '../../utils/useRemoteEndCall';
22
+ import LiveStreamContext from '../livestream/LiveStreamContext';
23
+ import {ClientRole, UidType} from '../../../agora-rn-uikit';
24
+ import {useWindowDimensions} from 'react-native';
25
+ import {
26
+ LiveStreamControlMessageEnum,
27
+ RaiseHandValue,
28
+ } from '../livestream/Types';
29
+ import events, {EventPersistLevel} from '../../rtm-events-api';
30
+ import RemoveMeetingPopup from '../../subComponents/RemoveMeetingPopup';
31
+ import RemoveScreensharePopup from '../../subComponents/RemoveScreensharePopup';
32
+ import useRemoteEndScreenshare from '../../utils/useRemoteEndScreenshare';
33
+ import {useScreenshare} from '../../subComponents/screenshare/useScreenshare';
34
+ import {useFocus} from '../../utils/useFocus';
35
+ import Toast from '../../../react-native-toast-message';
36
+ import RemoteMutePopup from '../../subComponents/RemoteMutePopup';
37
+ import {calculatePosition, trimText} from '../../utils/common';
38
+
39
+ interface UserActionMenuOptionsOptionsProps {
40
+ user: RenderInterface;
41
+ actionMenuVisible: boolean;
42
+ setActionMenuVisible: (actionMenuVisible: boolean) => void;
43
+ btnRef: any;
44
+ from: 'partcipant' | 'screenshare-participant' | 'video-tile';
45
+ }
46
+ export default function UserActionMenuOptionsOptions(
47
+ props: UserActionMenuOptionsOptionsProps,
48
+ ) {
49
+ const [showAudioMuteModal, setShowAudioMuteModal] = useState(false);
50
+ const [showVideoMuteModal, setShowVideoMuteModal] = useState(false);
51
+ const [isPosCalculated, setIsPosCalculated] = useState(false);
52
+ const {setFocus} = useFocus();
53
+ const {stopUserScreenShare} = useScreenshare();
54
+ const remoteEndScreenshare = useRemoteEndScreenshare();
55
+ const [removeScreensharePopupVisible, setRemoveScreensharePopupVisible] =
56
+ useState(false);
57
+ const [actionMenuitems, setActionMenuitems] = useState<ActionMenuItem[]>([]);
58
+ const {setSidePanel} = useSidePanel();
59
+ const {user, actionMenuVisible, setActionMenuVisible} = props;
60
+ const {pinnedUid, activeUids} = useRender();
61
+ const {dispatch} = useRtc();
62
+ const {setLayout} = useLayout();
63
+ const localuid = useLocalUid();
64
+ const {openPrivateChat} = useChatMessages();
65
+ const {hostUids, audienceUids} = useLiveStreamDataContext();
66
+ const {
67
+ data: {isHost},
68
+ } = useMeetingInfo();
69
+ const remoteRequest = useRemoteRequest();
70
+ const remoteMute = useRemoteMute();
71
+ const endRemoteCall = useRemoteEndCall();
72
+ const {promoteAudienceAsCoHost, raiseHandList} =
73
+ useContext(LiveStreamContext);
74
+ const [removeMeetingPopupVisible, setRemoveMeetingPopupVisible] =
75
+ useState(false);
76
+
77
+ useEffect(() => {
78
+ const items: ActionMenuItem[] = [];
79
+
80
+ /**
81
+ * In VideoMeeting/VoiceChat - Show pin menu for all users
82
+ * In Livestreaming/AudioLivecast - Show only for host -> i.e who is streaming video/audio. don't show it for audience
83
+ */
84
+ if (
85
+ !$config.EVENT_MODE ||
86
+ !(
87
+ $config.EVENT_MODE &&
88
+ $config.RAISE_HAND &&
89
+ audienceUids.indexOf(user.uid) !== -1
90
+ )
91
+ ) {
92
+ items.push({
93
+ disabled: activeUids.length === 1,
94
+ icon: pinnedUid ? 'unpin-outlined' : 'pin-outlined',
95
+ onHoverIcon: pinnedUid ? 'unpin-outlined' : 'pin-filled',
96
+ iconColor: $config.SECONDARY_ACTION_COLOR,
97
+ textColor: $config.SECONDARY_ACTION_COLOR,
98
+ title: pinnedUid
99
+ ? user.uid === pinnedUid
100
+ ? 'Unpin'
101
+ : 'Replace Pin'
102
+ : 'Pin for me',
103
+ callback: () => {
104
+ setActionMenuVisible(false);
105
+ dispatch({
106
+ type: 'UserPin',
107
+ value: [pinnedUid && user.uid === pinnedUid ? 0 : user.uid],
108
+ });
109
+ setLayout(getPinnedLayoutName());
110
+ },
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Below menu items for remote user with type rtc(not for screenshare)
116
+ */
117
+ if (localuid !== user.uid && user.type === 'rtc') {
118
+ /**
119
+ * Chat menu
120
+ */
121
+ items.push({
122
+ icon: 'chat-outlined',
123
+ onHoverIcon: 'chat-filled',
124
+ iconColor: $config.SECONDARY_ACTION_COLOR,
125
+ textColor: $config.SECONDARY_ACTION_COLOR,
126
+ title: 'Message Privately',
127
+ callback: () => {
128
+ setActionMenuVisible(false);
129
+ openPrivateChat(user.uid);
130
+ },
131
+ });
132
+
133
+ /**
134
+ * Only host can see this menu item - request/mute - video/audio, promote to co host,demote to audience,remove form meeting
135
+ */
136
+ if (isHost) {
137
+ /**
138
+ * Request/Mute -> Audio/Video
139
+ * VideoMeeting/Voice chat - show this for all user
140
+ * Livestreaming/Audio livecast - show this for host user only(because audience not have permission to stream)
141
+ *
142
+ * note:
143
+ * Audio Menu applicable to all vertcials
144
+ * Video menu applicable to VideoMeeting and Livestreaming
145
+ */
146
+ if (
147
+ !$config.EVENT_MODE ||
148
+ ($config.EVENT_MODE &&
149
+ $config.RAISE_HAND &&
150
+ hostUids.indexOf(user.uid) !== -1)
151
+ ) {
152
+ items.push({
153
+ icon: user.audio ? 'mic-off-outlined' : 'mic-on-outlined',
154
+ onHoverIcon: user.audio ? 'mic-off-filled' : 'mic-on-filled',
155
+ iconColor: $config.SECONDARY_ACTION_COLOR,
156
+ textColor: $config.SECONDARY_ACTION_COLOR,
157
+ title: user.audio ? 'Mute Audio' : 'Request Audio',
158
+ callback: () => {
159
+ setActionMenuVisible(false);
160
+ user.audio
161
+ ? setShowAudioMuteModal(true)
162
+ : remoteRequest(REQUEST_REMOTE_TYPE.audio, user.uid);
163
+ },
164
+ });
165
+ if (!$config.AUDIO_ROOM) {
166
+ items.push({
167
+ icon: user.video ? 'video-off-outlined' : 'video-on-outlined',
168
+ onHoverIcon: user.video ? 'video-off-filled' : 'video-on-filled',
169
+ iconColor: $config.SECONDARY_ACTION_COLOR,
170
+ textColor: $config.SECONDARY_ACTION_COLOR,
171
+ title: user.video ? 'Mute Video' : 'Request Video',
172
+ callback: () => {
173
+ setActionMenuVisible(false);
174
+ user.video
175
+ ? setShowVideoMuteModal(true)
176
+ : remoteRequest(REQUEST_REMOTE_TYPE.video, user.uid);
177
+ },
178
+ });
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Promote co host -> show only on Livestreaming and Audio livecast
184
+ */
185
+ if (
186
+ $config.EVENT_MODE &&
187
+ $config.RAISE_HAND &&
188
+ hostUids.indexOf(user.uid) === -1
189
+ ) {
190
+ items.push({
191
+ icon: 'promote-outlined',
192
+ onHoverIcon: 'promote-filled',
193
+ iconColor: $config.SECONDARY_ACTION_COLOR,
194
+ textColor: $config.SECONDARY_ACTION_COLOR,
195
+ title: 'Add as Presenter',
196
+ callback: () => {
197
+ setActionMenuVisible(false);
198
+ promoteAudienceAsCoHost(user.uid);
199
+ },
200
+ });
201
+ }
202
+ if ($config.EVENT_MODE) {
203
+ if (
204
+ raiseHandList[user.uid]?.raised === RaiseHandValue.TRUE &&
205
+ raiseHandList[user.uid]?.role == ClientRole.Broadcaster
206
+ ) {
207
+ items.push({
208
+ isBase64Icon: true,
209
+ icon: 'demote-outlined',
210
+ onHoverIcon: 'demote-filled',
211
+ iconColor: $config.SECONDARY_ACTION_COLOR,
212
+ textColor: $config.SECONDARY_ACTION_COLOR,
213
+ title: 'Remove as Presenter',
214
+ callback: () => {
215
+ setActionMenuVisible(false);
216
+ events.send(
217
+ LiveStreamControlMessageEnum.raiseHandRequestRejected,
218
+ '',
219
+ EventPersistLevel.LEVEL1,
220
+ user.uid,
221
+ );
222
+ },
223
+ });
224
+ }
225
+ }
226
+
227
+ items.push({
228
+ icon: 'remove-meeting',
229
+ iconColor: $config.SEMANTIC_ERROR,
230
+ textColor: $config.SEMANTIC_ERROR,
231
+ title: 'Remove From Meeting',
232
+ callback: () => {
233
+ setActionMenuVisible(false);
234
+ setRemoveMeetingPopupVisible(true);
235
+ },
236
+ });
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Local User menu item - change name
242
+ */
243
+ if (localuid == user.uid && user.type === 'rtc') {
244
+ items.push({
245
+ icon: 'pencil-outlined',
246
+ onHoverIcon: 'pencil-filled',
247
+ iconColor: $config.SECONDARY_ACTION_COLOR,
248
+ textColor: $config.SECONDARY_ACTION_COLOR,
249
+ title: 'Change Name',
250
+ callback: () => {
251
+ setFocus((prevState) => {
252
+ return {
253
+ ...prevState,
254
+ editName: true,
255
+ };
256
+ });
257
+
258
+ setActionMenuVisible(false);
259
+ setSidePanel(SidePanelType.Settings);
260
+ },
261
+ });
262
+ }
263
+ //Screenshare menu item
264
+ if (
265
+ (isHost || localuid === user.parentUid) &&
266
+ user.type === 'screenshare'
267
+ ) {
268
+ items.push({
269
+ icon: 'remove-meeting',
270
+ iconColor: $config.SEMANTIC_ERROR,
271
+ textColor: $config.SEMANTIC_ERROR,
272
+ title:
273
+ localuid === user?.parentUid
274
+ ? 'Stop Screenshare'
275
+ : 'Remove Screenshare',
276
+ callback: () => {
277
+ setActionMenuVisible(false);
278
+ //for local user directly stop the screenshare
279
+ if (localuid === user.parentUid) {
280
+ stopUserScreenShare();
281
+ }
282
+ //for remote user show popup and then user will use cta to stop screenshare
283
+ else {
284
+ setRemoveScreensharePopupVisible(true);
285
+ }
286
+ },
287
+ });
288
+ }
289
+ setActionMenuitems(items);
290
+ }, [pinnedUid, isHost, raiseHandList, hostUids, user]);
291
+
292
+ const {width: globalWidth, height: globalHeight} = useWindowDimensions();
293
+ const [modalPosition, setModalPosition] = useState({});
294
+
295
+ useEffect(() => {
296
+ if (actionMenuVisible) {
297
+ //getting btnRef x,y
298
+ props.btnRef?.current?.measure(
299
+ (
300
+ _fx: number,
301
+ _fy: number,
302
+ localWidth: number,
303
+ localHeight: number,
304
+ px: number,
305
+ py: number,
306
+ ) => {
307
+ const data = calculatePosition({
308
+ px,
309
+ py,
310
+ localWidth,
311
+ localHeight,
312
+ globalHeight,
313
+ globalWidth,
314
+ });
315
+ setModalPosition(data);
316
+ setIsPosCalculated(true);
317
+ },
318
+ );
319
+ }
320
+ }, [actionMenuVisible]);
321
+
322
+ return (
323
+ <>
324
+ {isHost ? (
325
+ <RemoteMutePopup
326
+ type="audio"
327
+ actionMenuVisible={showAudioMuteModal}
328
+ setActionMenuVisible={setShowAudioMuteModal}
329
+ name={props?.user.name}
330
+ modalPosition={modalPosition}
331
+ onMutePress={() => {
332
+ remoteMute(MUTE_REMOTE_TYPE.audio, user.uid);
333
+ setShowAudioMuteModal(false);
334
+ }}
335
+ />
336
+ ) : (
337
+ <></>
338
+ )}
339
+ {isHost ? (
340
+ <RemoteMutePopup
341
+ type="video"
342
+ actionMenuVisible={showVideoMuteModal}
343
+ setActionMenuVisible={setShowVideoMuteModal}
344
+ name={props?.user.name}
345
+ modalPosition={modalPosition}
346
+ onMutePress={() => {
347
+ remoteMute(MUTE_REMOTE_TYPE.video, user.uid);
348
+ setShowVideoMuteModal(false);
349
+ }}
350
+ />
351
+ ) : (
352
+ <></>
353
+ )}
354
+ {isHost ? (
355
+ <RemoveScreensharePopup
356
+ modalVisible={removeScreensharePopupVisible}
357
+ setModalVisible={setRemoveScreensharePopupVisible}
358
+ username={user.name}
359
+ removeScreenShareFromMeeting={() => {
360
+ props.user.parentUid
361
+ ? remoteEndScreenshare(props.user.parentUid)
362
+ : console.log('Parent Uid is not available');
363
+ }}
364
+ />
365
+ ) : (
366
+ <></>
367
+ )}
368
+ {isHost ? (
369
+ <RemoveMeetingPopup
370
+ modalVisible={removeMeetingPopupVisible}
371
+ setModalVisible={setRemoveMeetingPopupVisible}
372
+ username={user.name}
373
+ removeUserFromMeeting={() => {
374
+ Toast.show({
375
+ type: 'info',
376
+ text1: `The system will remove ${trimText(
377
+ user.name,
378
+ )} from this call after 5 secs.`,
379
+ visibilityTime: 5000,
380
+ primaryBtn: null,
381
+ secondaryBtn: null,
382
+ });
383
+ endRemoteCall(user.uid);
384
+ }}
385
+ />
386
+ ) : (
387
+ <></>
388
+ )}
389
+ <ActionMenu
390
+ from={props.from}
391
+ actionMenuVisible={actionMenuVisible && isPosCalculated}
392
+ setActionMenuVisible={setActionMenuVisible}
393
+ modalPosition={modalPosition}
394
+ items={actionMenuitems}
395
+ />
396
+ </>
397
+ );
398
+ }