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,4 +1,5 @@
1
1
  import React, {createContext, useContext, useState, useRef} from 'react';
2
+ import {StyleSheet} from 'react-native';
2
3
  import ChatContext, {controlMessageEnum} from '../ChatContext';
3
4
  import Toast from '../../../react-native-toast-message';
4
5
  import {
@@ -16,7 +17,10 @@ import {useMeetingInfo} from '../meeting-info/useMeetingInfo';
16
17
  import {useScreenshare} from '../../subComponents/screenshare/useScreenshare';
17
18
  import events, {EventPersistLevel} from '../../rtm-events-api';
18
19
  import {EventNames} from '../../rtm-events';
19
- import {useRender} from 'customization-api';
20
+ import {SidePanelType, useRender, useSidePanel} from 'customization-api';
21
+ import TertiaryButton from '../../atoms/TertiaryButton';
22
+ import PrimaryButton from '../../atoms/PrimaryButton';
23
+ import {trimText} from '../../utils/common';
20
24
 
21
25
  const LiveStreamContext = createContext(null as unknown as liveStreamContext);
22
26
 
@@ -39,6 +43,18 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
39
43
  const raiseHandListRef = useRef<any>();
40
44
  raiseHandListRef.current = raiseHandList;
41
45
 
46
+ const [coHostUids, setCoHostUids] = useState<UidType[]>([]);
47
+ const coHostUidsRef = useRef<any>();
48
+ coHostUidsRef.current = coHostUids;
49
+
50
+ const {sidePanel} = useSidePanel();
51
+ const sidePanelRef = useRef<any>();
52
+ sidePanelRef.current = sidePanel;
53
+
54
+ React.useEffect(() => {
55
+ sidePanelRef.current = sidePanel;
56
+ }, [sidePanel]);
57
+
42
58
  React.useEffect(() => {
43
59
  renderListRef.current = renderList;
44
60
  }, [renderList]);
@@ -47,11 +63,41 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
47
63
  raiseHandListRef.current = raiseHandList;
48
64
  }, [raiseHandList]);
49
65
 
66
+ React.useEffect(() => {
67
+ coHostUidsRef.current = coHostUids;
68
+ }, [coHostUids]);
69
+
70
+ React.useEffect(() => {
71
+ /**
72
+ * when user rejoin the meeting. its showing previosly raised livesteaming request.
73
+ * so deleting raise hand data once the user is offline
74
+ * */
75
+ let newRaiseHandList = raiseHandList;
76
+ const data = Object.keys(
77
+ filterObject(
78
+ renderList,
79
+ ([k, v]) => v?.type === 'rtc' && v.offline === true,
80
+ ),
81
+ );
82
+ let isRaiseHandListChanged = false;
83
+ data &&
84
+ data.length &&
85
+ data.forEach((uid, index) => {
86
+ if (newRaiseHandList[uid]) {
87
+ isRaiseHandListChanged = true;
88
+ delete newRaiseHandList[uid];
89
+ }
90
+ if (data.length - 1 === index && isRaiseHandListChanged) {
91
+ setRaiseHandList(newRaiseHandList);
92
+ }
93
+ });
94
+ }, [renderList]);
95
+
50
96
  const localUid = useLocalUid();
51
97
  const localUidRef = useRef<any>();
52
98
  localUidRef.current = localUid;
53
99
 
54
- const {hasUserJoinedRTM} = useContext(ChatContext);
100
+ const {hasUserJoinedRTM, rtmInitTimstamp} = useContext(ChatContext);
55
101
 
56
102
  const {setRtcProps, rtcProps, callActive} = props?.value;
57
103
  const {
@@ -66,11 +112,48 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
66
112
 
67
113
  const [isPendingRequestToReview, setPendingRequestToReview] = useState(false);
68
114
 
69
- const showToast = (text: string) => {
115
+ const showToast = (
116
+ text: string,
117
+ text2: string,
118
+ uid?: UidType,
119
+ toastId?: number,
120
+ ) => {
121
+ let btns: any = {};
122
+ if (uid) {
123
+ //toastId used to hide this particular notification
124
+ btns.toastId = toastId;
125
+ btns.primaryBtn = (
126
+ <PrimaryButton
127
+ containerStyle={style.primaryBtn}
128
+ textStyle={style.primaryBtnText}
129
+ text="ALLOW TO BE A PRESENTER"
130
+ onPress={() => {
131
+ hostApprovesRequestOfUID(uid);
132
+ Toast.hide();
133
+ }}
134
+ />
135
+ );
136
+ btns.secondaryBtn = (
137
+ <TertiaryButton
138
+ containerStyle={style.secondaryBtn}
139
+ text="DENY"
140
+ onPress={() => {
141
+ hostRejectsRequestOfUID(uid);
142
+ Toast.hide();
143
+ }}
144
+ />
145
+ );
146
+ } else {
147
+ btns.primaryBtn = null;
148
+ btns.secondaryBtn = null;
149
+ }
150
+
70
151
  Toast.show({
71
- type: 'success',
152
+ type: 'info',
72
153
  text1: text,
73
- visibilityTime: 1000,
154
+ text2: text2 ? text2 : null,
155
+ visibilityTime: 3000,
156
+ ...btns,
74
157
  });
75
158
  };
76
159
 
@@ -101,6 +184,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
101
184
  [userId]: {
102
185
  raised: payload?.raised || RaiseHandValue.FALSE,
103
186
  ts: payload?.ts || Date.now(),
187
+ isProcessed: payload?.isProcessed || false,
104
188
  role:
105
189
  payload?.role ||
106
190
  oldRaisedHandList[userId]?.role ||
@@ -128,9 +212,23 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
128
212
  JSON.stringify({
129
213
  action: LiveStreamControlMessageEnum.notifyHostsInChannel,
130
214
  value: RaiseHandValue.FALSE,
215
+ ts: new Date().getTime(),
216
+ isProcessed: true,
131
217
  }),
132
218
  EventPersistLevel.LEVEL2,
133
219
  );
220
+ //update local cohost state
221
+ setCoHostUids((prevState) => {
222
+ return [
223
+ ...prevState.filter((i) => i !== parseInt(localUidRef.current)),
224
+ ];
225
+ });
226
+ // Audience notfies all users that co-host permission removed
227
+ events.send(
228
+ LiveStreamControlMessageEnum.coHostRemoved,
229
+ JSON.stringify({uid: localUidRef.current}),
230
+ EventPersistLevel.LEVEL2,
231
+ );
134
232
  break;
135
233
  case ClientRole.Broadcaster:
136
234
  // Update local state
@@ -145,9 +243,21 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
145
243
  JSON.stringify({
146
244
  action: LiveStreamControlMessageEnum.notifyHostsInChannel,
147
245
  value: RaiseHandValue.TRUE,
246
+ ts: new Date().getTime(),
247
+ isProcessed: true,
148
248
  }),
149
249
  EventPersistLevel.LEVEL2,
150
250
  );
251
+ //update local cohost state
252
+ setCoHostUids((prevState) => {
253
+ return [...prevState, localUidRef.current];
254
+ });
255
+ // Audience notfies all users that co-host has joined
256
+ events.send(
257
+ LiveStreamControlMessageEnum.coHostJoined,
258
+ JSON.stringify({uid: localUidRef.current}),
259
+ EventPersistLevel.LEVEL2,
260
+ );
151
261
  default:
152
262
  break;
153
263
  }
@@ -237,6 +347,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
237
347
  const payload = JSON.parse(data.payload);
238
348
  const action = payload.action;
239
349
  const value = payload.value;
350
+ const isProcessed = payload?.isProcessed || false;
240
351
 
241
352
  switch (action) {
242
353
  // 1. Host can receive raise hand request with true or false value
@@ -244,30 +355,46 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
244
355
  switch (value) {
245
356
  case RaiseHandValue.TRUE:
246
357
  // Step 1: Show notifications
247
- showToast(
248
- `${getAttendeeName(data.sender)} ${
249
- LSNotificationObject.RAISE_HAND_RECEIVED
250
- }`,
251
- );
358
+ if (
359
+ payload.ts > rtmInitTimstamp &&
360
+ sidePanelRef.current !== SidePanelType.Participants
361
+ ) {
362
+ showToast(
363
+ `${trimText(getAttendeeName(data.sender))} ${
364
+ LSNotificationObject.RAISE_HAND_RECEIVED.text1
365
+ }`,
366
+ LSNotificationObject.RAISE_HAND_RECEIVED.text2,
367
+ data.sender,
368
+ data.ts,
369
+ );
370
+ }
252
371
  // 2. All Hosts in channel update their raised state to "true" when attendee raise their hand
253
372
  addOrUpdateLiveStreamRequest(data.sender, {
254
373
  ts: data.ts,
255
374
  raised: RaiseHandValue.TRUE,
256
375
  role: ClientRole.Audience,
376
+ isProcessed: isProcessed,
257
377
  });
258
378
  break;
259
379
  case RaiseHandValue.FALSE:
260
380
  // Step 1: Show notifications
261
- showToast(
262
- `${getAttendeeName(data.sender)} ${
263
- LSNotificationObject.RAISE_HAND_REQUEST_RECALL
264
- }`,
265
- );
381
+ if (
382
+ payload.ts > rtmInitTimstamp &&
383
+ sidePanelRef.current !== SidePanelType.Participants
384
+ ) {
385
+ showToast(
386
+ `${trimText(getAttendeeName(data.sender))} ${
387
+ LSNotificationObject.RAISE_HAND_REQUEST_RECALL.text1
388
+ }`,
389
+ LSNotificationObject.RAISE_HAND_REQUEST_RECALL.text2,
390
+ );
391
+ }
266
392
  // 2. All Hosts in channel update raised state to "false" when attendee recalls their request
267
393
  addOrUpdateLiveStreamRequest(data.sender, {
268
394
  ts: data.ts,
269
395
  raised: RaiseHandValue.FALSE,
270
396
  role: ClientRole.Audience,
397
+ isProcessed: isProcessed,
271
398
  });
272
399
  default:
273
400
  break;
@@ -282,6 +409,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
282
409
  ts: data.ts,
283
410
  raised: RaiseHandValue.TRUE,
284
411
  role: ClientRole.Broadcaster,
412
+ isProcessed: isProcessed,
285
413
  });
286
414
  break;
287
415
  case RaiseHandValue.FALSE:
@@ -289,6 +417,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
289
417
  ts: data.ts,
290
418
  raised: RaiseHandValue.FALSE,
291
419
  role: ClientRole.Audience,
420
+ isProcessed: isProcessed,
292
421
  });
293
422
  break;
294
423
  default:
@@ -306,7 +435,10 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
306
435
  events.on(LiveStreamControlMessageEnum.raiseHandRequestAccepted, (data) => {
307
436
  if (raiseHandList[localUidRef.current]?.raised === RaiseHandValue.FALSE)
308
437
  return;
309
- showToast(LSNotificationObject.RAISE_HAND_ACCEPTED);
438
+ showToast(
439
+ LSNotificationObject.RAISE_HAND_ACCEPTED.text1,
440
+ LSNotificationObject.RAISE_HAND_ACCEPTED.text2,
441
+ );
310
442
  // Promote user's privileges to host
311
443
  changeClientRoleTo(ClientRole.Broadcaster);
312
444
  // Audience updates its local attributes and notfies all host when request is approved
@@ -322,13 +454,19 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
322
454
  raiseHandListRef.current[localUidRef.current].role ==
323
455
  ClientRole.Audience
324
456
  ) {
325
- showToast(LSNotificationObject.RAISE_HAND_REJECTED);
457
+ showToast(
458
+ LSNotificationObject.RAISE_HAND_REJECTED.text1,
459
+ LSNotificationObject.RAISE_HAND_REJECTED.text2,
460
+ );
326
461
  } else if (
327
462
  raiseHandListRef.current[localUidRef.current].role ==
328
463
  ClientRole.Broadcaster
329
464
  ) {
330
465
  /** 2.b */
331
- showToast(LSNotificationObject.RAISE_HAND_APPROVED_REQUEST_RECALL);
466
+ showToast(
467
+ LSNotificationObject.RAISE_HAND_APPROVED_REQUEST_RECALL.text1,
468
+ LSNotificationObject.RAISE_HAND_APPROVED_REQUEST_RECALL.text2,
469
+ );
332
470
  screenshareContextInstanceRef?.current?.stopUserScreenShare(); // This will not exist on ios
333
471
 
334
472
  // Demote user's privileges to audience
@@ -342,6 +480,39 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
342
480
  // Audience updates its local attributes and notfies all host when they(audience) are kicked out
343
481
  UpdtLocStateAndBCastAttr(ClientRole.Audience, data.ts);
344
482
  });
483
+ // 4. Host promote audience as co-host
484
+ events.on(LiveStreamControlMessageEnum.promoteAsCoHost, (data) => {
485
+ showToast(
486
+ LSNotificationObject.PROMOTE_AS_CO_HOST.text1,
487
+ LSNotificationObject.PROMOTE_AS_CO_HOST.text2,
488
+ );
489
+ // Promote user's privileges to host
490
+ changeClientRoleTo(ClientRole.Broadcaster);
491
+ // Audience updates its local attributes and notfies all host when request is approved
492
+ UpdtLocStateAndBCastAttr(ClientRole.Broadcaster, data.ts);
493
+ });
494
+ // 4. New co-host has joined
495
+ events.on(LiveStreamControlMessageEnum.coHostJoined, ({payload}) => {
496
+ try {
497
+ const data = JSON.parse(payload);
498
+ if (data?.uid) {
499
+ setCoHostUids((prevState) => {
500
+ return [...prevState, parseInt(data.uid)];
501
+ });
502
+ }
503
+ } catch (error) {}
504
+ });
505
+ // 5. Co-host removed
506
+ events.on(LiveStreamControlMessageEnum.coHostRemoved, ({payload}) => {
507
+ try {
508
+ const data = JSON.parse(payload);
509
+ if (data?.uid) {
510
+ setCoHostUids((prevState) => {
511
+ return [...prevState.filter((i) => i !== parseInt(data.uid))];
512
+ });
513
+ }
514
+ } catch (error) {}
515
+ });
345
516
  /** ********************** AUDIENCE EVENTS SECTION ENDS ********************** */
346
517
  }, []);
347
518
 
@@ -354,25 +525,51 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
354
525
  */
355
526
 
356
527
  const hostApprovesRequestOfUID = (uid: UidType) => {
357
- addOrUpdateLiveStreamRequest(uid, {
358
- raised: RaiseHandValue.TRUE,
359
- ts: new Date().getTime(),
360
- });
361
- events.send(
362
- LiveStreamControlMessageEnum.raiseHandRequestAccepted,
363
- '',
364
- EventPersistLevel.LEVEL1,
365
- uid,
366
- );
528
+ if (!raiseHandListRef.current[uid]?.isProcessed) {
529
+ addOrUpdateLiveStreamRequest(uid, {
530
+ raised: RaiseHandValue.TRUE,
531
+ ts: new Date().getTime(),
532
+ isProcessed: true,
533
+ });
534
+ events.send(
535
+ LiveStreamControlMessageEnum.raiseHandRequestAccepted,
536
+ '',
537
+ EventPersistLevel.LEVEL1,
538
+ uid,
539
+ );
540
+ } else {
541
+ Toast.hide();
542
+ setTimeout(() => {
543
+ showToast('Request already processed.', null);
544
+ });
545
+ }
367
546
  };
368
547
 
369
548
  const hostRejectsRequestOfUID = (uid: UidType) => {
370
- addOrUpdateLiveStreamRequest(uid, {
371
- raised: RaiseHandValue.FALSE,
372
- ts: new Date().getTime(),
373
- });
549
+ if (!raiseHandListRef.current[uid]?.isProcessed) {
550
+ addOrUpdateLiveStreamRequest(uid, {
551
+ raised: RaiseHandValue.FALSE,
552
+ ts: new Date().getTime(),
553
+ isProcessed: true,
554
+ });
555
+ events.send(
556
+ LiveStreamControlMessageEnum.raiseHandRequestRejected,
557
+ '',
558
+ EventPersistLevel.LEVEL1,
559
+ uid,
560
+ );
561
+ } else {
562
+ Toast.hide();
563
+ setTimeout(() => {
564
+ showToast('Request already processed.', null);
565
+ });
566
+ }
567
+ };
568
+
569
+ // promote audience as co-host
570
+ const promoteAudienceAsCoHost = async (uid: UidType): Promise<void> => {
374
571
  events.send(
375
- LiveStreamControlMessageEnum.raiseHandRequestRejected,
572
+ LiveStreamControlMessageEnum.promoteAsCoHost,
376
573
  '',
377
574
  EventPersistLevel.LEVEL1,
378
575
  uid,
@@ -392,14 +589,19 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
392
589
  // If hand is already raised, skip the call
393
590
  if (raiseHandList[localUidRef.current]?.raised === RaiseHandValue.TRUE)
394
591
  return;
395
- showToast(LSNotificationObject.RAISE_HAND_REQUEST);
592
+ showToast(
593
+ LSNotificationObject.RAISE_HAND_REQUEST.text1,
594
+ LSNotificationObject.RAISE_HAND_REQUEST.text2,
595
+ );
396
596
  events.send(
397
597
  EventNames.RAISED_ATTRIBUTE,
398
598
  JSON.stringify({
399
599
  action: LiveStreamControlMessageEnum.raiseHandRequest,
400
600
  value: RaiseHandValue.TRUE,
601
+ ts: new Date().getTime(),
602
+ isProcessed: false,
401
603
  }),
402
- EventPersistLevel.LEVEL1,
604
+ EventPersistLevel.LEVEL2,
403
605
  );
404
606
  // Update local state
405
607
  addOrUpdateLiveStreamRequest(localUidRef.current, {
@@ -424,8 +626,22 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
424
626
  // Change role
425
627
  changeClientRoleTo(ClientRole.Audience);
426
628
  }
629
+ //notify host users
630
+ events.send(
631
+ EventNames.RAISED_ATTRIBUTE,
632
+ JSON.stringify({
633
+ action: LiveStreamControlMessageEnum.raiseHandRequest,
634
+ value: RaiseHandValue.FALSE,
635
+ ts: new Date().getTime(),
636
+ isProcessed: true,
637
+ }),
638
+ EventPersistLevel.LEVEL2,
639
+ );
427
640
  UpdtLocStateAndBCastAttr(ClientRole.Audience, new Date().getTime());
428
- showToast(LSNotificationObject.RAISE_HAND_REQUEST_RECALL_LOCAL);
641
+ showToast(
642
+ LSNotificationObject.RAISE_HAND_REQUEST_RECALL_LOCAL.text1,
643
+ LSNotificationObject.RAISE_HAND_REQUEST_RECALL_LOCAL.text2,
644
+ );
429
645
  };
430
646
 
431
647
  /** ******* AUDIENCE CONTROLS SECTION ENDS ******* */
@@ -433,6 +649,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
433
649
  return (
434
650
  <LiveStreamContext.Provider
435
651
  value={{
652
+ coHostUids: coHostUids,
436
653
  setLastCheckedRequestTimestamp,
437
654
  isPendingRequestToReview,
438
655
  raiseHandList,
@@ -440,6 +657,7 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
440
657
  hostRejectsRequestOfUID,
441
658
  audienceSendsRequest,
442
659
  audienceRecallsRequest,
660
+ promoteAudienceAsCoHost,
443
661
  }}>
444
662
  {props.children}
445
663
  </LiveStreamContext.Provider>
@@ -447,3 +665,19 @@ export const LiveStreamContextProvider: React.FC<liveStreamPropsInterface> = (
447
665
  };
448
666
 
449
667
  export default LiveStreamContext;
668
+
669
+ const style = StyleSheet.create({
670
+ secondaryBtn: {marginLeft: 16, height: 40, paddingVertical: 5},
671
+ primaryBtn: {
672
+ minWidth: 'auto',
673
+ paddingHorizontal: 12,
674
+ height: 40,
675
+ borderRadius: 4,
676
+ paddingVertical: 5,
677
+ },
678
+ primaryBtnText: {
679
+ fontWeight: '600',
680
+ fontSize: 16,
681
+ paddingLeft: 0,
682
+ },
683
+ });
@@ -16,6 +16,7 @@ export interface raiseHandItemInterface {
16
16
  role: ClientRole;
17
17
  raised: RaiseHandValue;
18
18
  ts: number;
19
+ isProcessed: boolean;
19
20
  }
20
21
 
21
22
  import {UidType} from '../../../agora-rn-uikit';
@@ -42,23 +43,45 @@ export enum LiveStreamControlMessageEnum {
42
43
  notifyAllRequestApproved = 'NOTIFY_REQUEST_APPROVED',
43
44
  notifyAllRequestRejected = 'NOTIFY_REQUEST_REJECTED',
44
45
  notifyHostsInChannel = 'NOTIFY_HOSTS_IN_CHANNEL',
46
+ promoteAsCoHost = 'PROMOTE_AS_CO_HOST',
47
+ coHostJoined = 'CO_HOST_JOINED',
48
+ coHostRemoved = 'CO_HOST_REMOVED',
45
49
  }
46
50
 
47
51
  export const LSNotificationObject = {
48
- [LiveStreamControlMessageEnum.raiseHandRequest]:
49
- 'You have raised your hand. Request sent to host for approval',
50
- [LiveStreamControlMessageEnum.raiseHandRequestReceived]:
51
- 'has raised their hand',
52
- [LiveStreamControlMessageEnum.raiseHandRequestAccepted]:
53
- 'Your request was approved, unmute to start talking',
54
- [LiveStreamControlMessageEnum.raiseHandRequestRejected]:
55
- 'Your request was rejected by the host',
56
- [LiveStreamControlMessageEnum.raiseHandRequestRecall]:
57
- 'has lowered their hand',
58
- [LiveStreamControlMessageEnum.raiseHandRequestRecallLocal]:
59
- 'You have lowered your hand',
60
- [LiveStreamControlMessageEnum.raiseHandApprovedRequestRecall]:
61
- 'The host has revoked streaming permissions',
52
+ [LiveStreamControlMessageEnum.raiseHandRequest]: {
53
+ text1: 'You’ve raised your hand.',
54
+ text2: 'Waiting for host to approve the request',
55
+ },
56
+ [LiveStreamControlMessageEnum.raiseHandRequestReceived]: {
57
+ text1: 'has raised their hand to be a Presenter',
58
+ text2:
59
+ 'Once approved they will be able to speak, share their video and present during this call.',
60
+ },
61
+ [LiveStreamControlMessageEnum.raiseHandRequestAccepted]: {
62
+ text1: 'Host has approved your request.',
63
+ text2: 'You are now a Presenter',
64
+ },
65
+ [LiveStreamControlMessageEnum.raiseHandRequestRejected]: {
66
+ text1: 'Your request was rejected by the host',
67
+ text2: null,
68
+ },
69
+ [LiveStreamControlMessageEnum.raiseHandRequestRecall]: {
70
+ text1: 'has lowered their hand',
71
+ text2: null,
72
+ },
73
+ [LiveStreamControlMessageEnum.raiseHandRequestRecallLocal]: {
74
+ text1: 'You’ve lowered your hand.',
75
+ text2: null,
76
+ },
77
+ [LiveStreamControlMessageEnum.raiseHandApprovedRequestRecall]: {
78
+ text1: 'Host has revoked streaming permissions.',
79
+ text2: null,
80
+ },
81
+ [LiveStreamControlMessageEnum.promoteAsCoHost]: {
82
+ text1: 'Host promoted you as a Presenter',
83
+ text2: null,
84
+ },
62
85
  };
63
86
 
64
87
  export interface liveStreamPropsInterface {
@@ -74,6 +97,8 @@ export interface liveStreamContext {
74
97
  hostRejectsRequestOfUID: (uid: number) => void;
75
98
  audienceSendsRequest: () => void;
76
99
  audienceRecallsRequest: () => void;
100
+ promoteAudienceAsCoHost: (uid: UidType) => void;
101
+ coHostUids: UidType[];
77
102
  }
78
103
 
79
104
  export interface requestInterface {
@@ -10,6 +10,7 @@ import LiveStreamContext, {
10
10
  } from './LiveStreamContext';
11
11
 
12
12
  export {
13
+ LiveStreamContext,
13
14
  LiveStreamContextProvider,
14
15
  LiveStreamControlMessageEnum,
15
16
  requestStatus,
@@ -15,16 +15,24 @@ import {LocalRaiseHand} from '../../../subComponents/livestream';
15
15
 
16
16
  export interface LiveStreamControlsProps {
17
17
  showControls: boolean;
18
+ isDesktop: boolean;
19
+ showLabel?: boolean;
18
20
  }
19
21
 
20
22
  const LiveStreamControls = (props: LiveStreamControlsProps) => {
21
- const {showControls} = props;
23
+ const {showControls, isDesktop, showLabel = $config.ICON_TEXT} = props;
22
24
  if (!$config.RAISE_HAND) return <></>;
23
25
  if (!showControls) return <></>;
24
26
  return (
25
- <View style={{alignSelf: 'center'}}>
26
- <LocalRaiseHand />
27
- </View>
27
+ <>
28
+ <View
29
+ style={{
30
+ alignSelf: 'center',
31
+ marginHorizontal: 10,
32
+ }}>
33
+ <LocalRaiseHand showLabel={showLabel} />
34
+ </View>
35
+ </>
28
36
  );
29
37
  };
30
38