agora-appbuilder-core 2.3.0-beta.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/Readme.md +11 -6
  2. package/package.json +1 -1
  3. package/template/Gulpfile.js +121 -83
  4. package/template/_gitignore +2 -2
  5. package/template/_package-lock.json +12959 -13248
  6. package/template/agora-rn-uikit/src/AgoraUIKit.tsx +2 -2
  7. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +2 -0
  8. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +3 -3
  9. package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +4 -5
  10. package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +3 -1
  11. package/template/agora-rn-uikit/src/Controls/LocalControls.tsx +2 -2
  12. package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +1 -1
  13. package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +1 -1
  14. package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +1 -1
  15. package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +1 -1
  16. package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +4 -4
  17. package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +7 -5
  18. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +1 -1
  19. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +1 -1
  20. package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +2 -2
  21. package/template/agora-rn-uikit/src/Rtc/Create.tsx +88 -43
  22. package/template/agora-rn-uikit/src/Rtc/Join.tsx +13 -4
  23. package/template/agora-rn-uikit/src/RtcConfigure.tsx +36 -19
  24. package/template/agora-rn-uikit/src/Utils/permission.ts +17 -6
  25. package/template/babel.config.js +9 -9
  26. package/template/bridge/rtc/webNg/RtcEngine.ts +51 -26
  27. package/template/customization-api/action-library.ts +22 -0
  28. package/template/{fpe-api/context.ts → customization-api/app-state.ts} +16 -14
  29. package/template/customization-api/customEvents.ts +9 -0
  30. package/template/{fpe-api/install.ts → customization-api/customize.ts} +27 -26
  31. package/template/{fpe-api → customization-api}/index.ts +11 -6
  32. package/template/{fpe-api/components.ts → customization-api/sub-components.ts} +22 -3
  33. package/template/{fpe-api → customization-api}/typeDefinition.ts +13 -14
  34. package/template/customization-api/utils.ts +30 -0
  35. package/template/{fpe-implementation → customization-implementation}/createHook.ts +0 -0
  36. package/template/{fpe-implementation/dummyFpe.ts → customization-implementation/dummyConfig.ts} +4 -4
  37. package/template/customization-implementation/index.ts +4 -0
  38. package/template/{fpe-api/useFpe.tsx → customization-implementation/useCustomization.tsx} +12 -12
  39. package/template/{fpe.config.js → customization.config.js} +11 -11
  40. package/template/electron/main/index.js +42 -35
  41. package/template/esbuild.rsdk.go +8 -17
  42. package/template/global.d.ts +4 -3
  43. package/template/index.rsdk.tsx +13 -5
  44. package/template/index.wsdk.tsx +21 -5
  45. package/template/package.json +3 -0
  46. package/template/react-native-toast-message/src/index.js +3 -7
  47. package/template/react-native-toast-message/src/{index.wsdk.js → index.sdk.tsx} +1 -1
  48. package/template/react-native-toast-message/src/styles.sdk.ts +17 -0
  49. package/template/src/App.tsx +8 -4
  50. package/template/src/AppWrapper.tsx +8 -6
  51. package/template/src/SDKAppWrapper.tsx +28 -21
  52. package/template/src/app-state/useLocalUserInfo.ts +8 -0
  53. package/template/src/app-state/useMessages.ts +52 -0
  54. package/template/src/atoms/PrimaryButton.tsx +2 -2
  55. package/template/src/atoms/SecondaryButton.tsx +12 -4
  56. package/template/src/atoms/TextInput.tsx +2 -2
  57. package/template/src/components/Chat.tsx +22 -11
  58. package/template/src/components/ChatContext.ts +10 -27
  59. package/template/src/components/Controls.native.tsx +13 -7
  60. package/template/src/components/Controls.tsx +15 -24
  61. package/template/src/components/DeviceConfigure.tsx +4 -3
  62. package/template/src/components/EventsConfigure.tsx +54 -0
  63. package/template/src/components/GridVideo.tsx +5 -6
  64. package/template/src/components/HostControlView.tsx +13 -19
  65. package/template/src/components/Navbar.tsx +54 -41
  66. package/template/src/components/NetworkQualityContext.tsx +4 -3
  67. package/template/src/components/ParticipantsView.tsx +7 -7
  68. package/template/src/components/PinnedVideo.tsx +3 -4
  69. package/template/src/components/Precall.native.tsx +3 -3
  70. package/template/src/components/Precall.tsx +14 -10
  71. package/template/src/components/RTMConfigure.tsx +61 -219
  72. package/template/src/components/SettingsView.tsx +6 -3
  73. package/template/src/components/Share.tsx +24 -18
  74. package/template/src/components/chat-messages/useChatMessages.tsx +397 -80
  75. package/template/src/components/chat-notification/useChatNotification.tsx +2 -2
  76. package/template/src/components/chat-ui/useChatUIControl.tsx +1 -1
  77. package/template/src/components/common/Logo.tsx +3 -2
  78. package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
  79. package/template/src/components/contexts/ScreenShareContext.tsx +3 -1
  80. package/template/src/components/contexts/VideoMeetingDataContext.tsx +85 -0
  81. package/template/src/components/contexts/WhiteboardContext.tsx +8 -8
  82. package/template/src/components/livestream/LiveStreamContext.tsx +88 -74
  83. package/template/src/components/meeting-info/useMeetingInfo.tsx +23 -19
  84. package/template/src/components/meeting-info/useSetMeetingInfo.tsx +1 -1
  85. package/template/src/components/participants/AllAudienceParticipants.tsx +2 -2
  86. package/template/src/components/participants/AllHostParticipants.tsx +4 -4
  87. package/template/src/components/participants/MeParticipant.tsx +5 -3
  88. package/template/src/components/participants/ParticipantName.tsx +2 -2
  89. package/template/src/components/participants/RemoteParticipants.tsx +9 -7
  90. package/template/src/components/precall/LocalMute.native.tsx +14 -10
  91. package/template/src/components/precall/LocalMute.tsx +7 -5
  92. package/template/src/components/precall/VideoPreview.native.tsx +6 -6
  93. package/template/src/components/precall/VideoPreview.tsx +3 -3
  94. package/template/src/components/precall/joinCallBtn.tsx +3 -3
  95. package/template/src/components/precall/meetingTitle.tsx +3 -1
  96. package/template/src/components/precall/selectDevice.tsx +2 -2
  97. package/template/src/components/precall/usePreCall.tsx +1 -1
  98. package/template/src/components/styles.ts +3 -3
  99. package/template/src/components/useShareLink.tsx +69 -29
  100. package/template/src/components/useUserPreference.tsx +16 -15
  101. package/template/src/components/useWakeLock.tsx +3 -3
  102. package/template/src/language/i18nTypes.ts +1 -1
  103. package/template/src/language/index.ts +2 -2
  104. package/template/src/language/useLanguage.tsx +2 -3
  105. package/template/src/pages/Authenticate.tsx +3 -2
  106. package/template/src/pages/Create.tsx +18 -20
  107. package/template/src/pages/Join.tsx +6 -7
  108. package/template/src/pages/VideoCall.tsx +74 -66
  109. package/template/src/pages/create/useCreate.tsx +1 -1
  110. package/template/src/pages/video-call/CustomUserContextHolder.tsx +14 -6
  111. package/template/src/pages/video-call/DefaultLayouts.ts +8 -8
  112. package/template/src/pages/video-call/{NameWithMicStatus.tsx → NameWithMicIcon.tsx} +8 -1
  113. package/template/src/pages/video-call/RenderComponent.tsx +7 -10
  114. package/template/src/pages/video-call/VideoCallScreen.tsx +31 -22
  115. package/template/src/pages/video-call/VideoComponent.tsx +13 -15
  116. package/template/src/pages/video-call/VideoRenderer.tsx +6 -6
  117. package/template/src/pages/video-call/useLayoutsData.ts +23 -0
  118. package/template/src/rtm/RTMEngine.ts +13 -0
  119. package/template/src/rtm-events/EventUtils.ts +20 -20
  120. package/template/src/rtm-events/EventsQueue.ts +9 -3
  121. package/template/src/rtm-events/constants.ts +5 -0
  122. package/template/src/rtm-events/index.tsx +1 -3
  123. package/template/src/{custom-events/CustomEvents.ts → rtm-events-api/Events.ts} +67 -61
  124. package/template/src/rtm-events-api/index.tsx +6 -0
  125. package/template/src/rtm-events-api/types.ts +22 -0
  126. package/template/src/subComponents/ChatBubble.tsx +24 -8
  127. package/template/src/subComponents/ChatContainer.tsx +24 -15
  128. package/template/src/subComponents/ChatInput.tsx +56 -42
  129. package/template/src/subComponents/LanguageSelector.tsx +2 -2
  130. package/template/src/subComponents/LayoutIconDropdown.native.tsx +5 -5
  131. package/template/src/subComponents/LayoutIconDropdown.tsx +7 -7
  132. package/template/src/subComponents/LocalAudioMute.tsx +3 -4
  133. package/template/src/subComponents/LocalEndCall.tsx +3 -6
  134. package/template/src/subComponents/LocalSwitchCamera.tsx +3 -4
  135. package/template/src/subComponents/LocalVideoMute.tsx +3 -3
  136. package/template/src/subComponents/NetworkQualityPill.tsx +8 -9
  137. package/template/src/subComponents/OpenInNativeButton.tsx +2 -3
  138. package/template/src/subComponents/RemoteAudioMute.tsx +5 -11
  139. package/template/src/subComponents/RemoteEndCall.tsx +3 -10
  140. package/template/src/subComponents/RemoteVideoMute.tsx +3 -10
  141. package/template/src/subComponents/SelectDevice.tsx +1 -1
  142. package/template/src/subComponents/SelectOAuth.tsx +3 -2
  143. package/template/src/subComponents/SidePanelButtons.ts +6 -5
  144. package/template/src/subComponents/TextWithTooltip.tsx +6 -2
  145. package/template/src/subComponents/{toastConfig.tsx → ToastConfig.tsx} +2 -2
  146. package/template/src/subComponents/chat/ChatParticipants.tsx +6 -5
  147. package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +2 -2
  148. package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +4 -3
  149. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +2 -2
  150. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +2 -4
  151. package/template/src/subComponents/livestream/index.ts +2 -2
  152. package/template/src/subComponents/recording/useRecording.tsx +44 -23
  153. package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +11 -5
  154. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +46 -34
  155. package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +97 -38
  156. package/template/src/subComponents/screenshare/useScreenshare.tsx +1 -1
  157. package/template/src/utils/SdkEvents.ts +9 -46
  158. package/template/src/utils/common.tsx +25 -9
  159. package/template/src/utils/getUniqueID.ts +5 -0
  160. package/template/src/utils/isMobileOrTablet.native.ts +2 -2
  161. package/template/src/utils/isMobileOrTablet.ts +21 -8
  162. package/template/src/utils/useButtonTemplate.tsx +1 -1
  163. package/template/src/utils/useCreateMeeting.ts +21 -10
  164. package/template/src/utils/useGetMeetingPhrase.ts +11 -8
  165. package/template/src/utils/{IsAttendeeUser.ts → useIsAttendee.ts} +3 -1
  166. package/template/src/utils/{isAudioEnabled.ts → useIsAudioEnabled.ts} +4 -4
  167. package/template/src/utils/{isHostUser.ts → useIsHost.ts} +13 -16
  168. package/template/src/utils/{isPSTNUser.ts → useIsPSTN.ts} +2 -2
  169. package/template/src/utils/{isScreenShareUser.ts → useIsScreenShare.ts} +0 -0
  170. package/template/src/utils/{isVideoEnabled.ts → useIsVideoEnabled.ts} +5 -6
  171. package/template/src/utils/useJoinMeeting.ts +8 -6
  172. package/template/src/utils/useLayout.tsx +5 -5
  173. package/template/src/utils/useMutePSTN.ts +5 -3
  174. package/template/src/utils/useMuteToggleLocal.ts +3 -4
  175. package/template/src/utils/useRemoteEndCall.ts +11 -10
  176. package/template/src/utils/useRemoteMute.ts +42 -20
  177. package/template/src/utils/useSidePanel.tsx +1 -1
  178. package/template/src/utils/useString.ts +2 -2
  179. package/template/src/utils/useUserName.ts +11 -0
  180. package/template/tsconfig_fpeApi.json +8 -9
  181. package/template/tsconfig_rsdk_index.json +8 -9
  182. package/template/tsconfig_wsdk_index.json +8 -9
  183. package/template/webpack.commons.js +9 -9
  184. package/template/webpack.rsdk.config.js +4 -2
  185. package/template/webpack.ts.config.js +6 -6
  186. package/template/webpack.wsdk.config.js +2 -1
  187. package/template/fpe-api/fpeEvents.ts +0 -9
  188. package/template/fpe-api/utils.ts +0 -61
  189. package/template/fpe-implementation/index.ts +0 -1
  190. package/template/fpe-todo.txt +0 -14
  191. package/template/src/components/RTMEvents.tsx +0 -84
  192. package/template/src/custom-events/index.tsx +0 -4
  193. package/template/src/custom-events/types.ts +0 -51
  194. package/template/src/pages/video-call/CustomLayout.ts +0 -17
  195. package/template/src/rtm-events/types.ts +0 -7
  196. package/template/src/utils/getMeetingInvite.ts +0 -53
  197. package/template/src/utils/useGroupMessages.ts +0 -24
  198. package/template/src/utils/useNavParams.ts +0 -6
  199. package/template/src/utils/useNavigateTo.ts +0 -8
  200. package/template/src/utils/usePrivateMessages.ts +0 -33
  201. package/template/src/utils/useSendControlMessage.ts +0 -51
  202. package/template/src/utils/useSendMessage.ts +0 -40
  203. package/template/src/utils/useSetUnreadMessageCount.ts +0 -43
  204. package/template/src/utils/useUnreadMessageCount.ts +0 -50
  205. package/template/src/utils/useUserList.ts +0 -26
@@ -7,8 +7,8 @@ import LiveStreamContext, {RaiseHandValue} from '../../components/livestream';
7
7
  import {filterObject} from '../../utils/index';
8
8
  import ParticipantSectionTitle from '../../components/participants/ParticipantSectionTitle';
9
9
  import {useString} from '../../utils/useString';
10
- import useUserList from '../../utils/useUserList';
11
10
  import {ClientRole} from '../../../agora-rn-uikit';
11
+ import {useRender} from 'customization-api';
12
12
 
13
13
  const CurrentLiveStreamRequestsView = (props: any) => {
14
14
  //commented for v1 release
@@ -23,7 +23,7 @@ const CurrentLiveStreamRequestsView = (props: any) => {
23
23
  const noUserFoundLabel = 'User not found';
24
24
  const raisedHandsListTitleLabel = 'Streaming Request';
25
25
  const {p_style} = props;
26
- const {renderList} = useUserList();
26
+ const {renderList} = useRender();
27
27
  const {raiseHandList, setLastCheckedRequestTimestamp} =
28
28
  useContext(LiveStreamContext);
29
29
  const [activeLiveStreamRequests, setActiveLiveStreamRequests] =
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import {BtnTemplate, UidType} from '../../../../agora-rn-uikit';
3
3
  import {LiveStreamControlMessageEnum} from '../../../components/livestream';
4
4
  import icons from '../../../assets/icons';
5
- import CustomEvents from '../../../custom-events';
5
+ import events, {EventPersistLevel} from '../../../rtm-events-api';
6
6
 
7
7
  export interface RemoteLiveStreamApprovedRequestRecallProps {
8
8
  uid: UidType;
@@ -14,9 +14,10 @@ const RemoteLiveStreamApprovedRequestRecall = (
14
14
  <BtnTemplate
15
15
  style={{width: 24, height: 22}}
16
16
  onPress={() => {
17
- CustomEvents.send(
17
+ events.send(
18
18
  LiveStreamControlMessageEnum.raiseHandRequestRejected,
19
- {},
19
+ '',
20
+ EventPersistLevel.LEVEL1,
20
21
  props.uid,
21
22
  );
22
23
  }}
@@ -4,12 +4,12 @@ import {BtnTemplate, PropsContext, UidType} from '../../../../agora-rn-uikit';
4
4
  import LiveStreamContext from '../../../components/livestream';
5
5
  import icons from '../../../assets/icons';
6
6
 
7
- export interface RemoteLiveStreamControlInterface {
7
+ export interface RemoteLiveStreamControlProps {
8
8
  uid: UidType;
9
9
  }
10
10
 
11
11
  const RemoteLiveStreamRequestApprove = (
12
- props: RemoteLiveStreamControlInterface,
12
+ props: RemoteLiveStreamControlProps,
13
13
  ) => {
14
14
  const {uid} = props;
15
15
  const {hostApprovesRequestOfUID} = useContext(LiveStreamContext);
@@ -4,13 +4,11 @@ import {BtnTemplate, PropsContext, UidType} from '../../../../agora-rn-uikit';
4
4
  import LiveStreamContext from '../../../components/livestream';
5
5
  import icons from '../../../assets/icons';
6
6
 
7
- interface RemoteLiveStreamControlInterface {
7
+ interface RemoteLiveStreamControlProps {
8
8
  uid: UidType;
9
9
  }
10
10
 
11
- const RemoteLiveStreamRequestReject = (
12
- props: RemoteLiveStreamControlInterface,
13
- ) => {
11
+ const RemoteLiveStreamRequestReject = (props: RemoteLiveStreamControlProps) => {
14
12
  const {uid} = props;
15
13
  const {hostRejectsRequestOfUID} = useContext(LiveStreamContext);
16
14
  const {styleProps} = useContext(PropsContext);
@@ -3,7 +3,7 @@ import RemoteLiveStreamApprovedRequestRecall, {
3
3
  RemoteLiveStreamApprovedRequestRecallProps,
4
4
  } from './controls/RemoteLiveStreamApprovedRequestRecall';
5
5
  import RemoteLiveStreamRequestApprove, {
6
- RemoteLiveStreamControlInterface,
6
+ RemoteLiveStreamControlProps,
7
7
  } from './controls/RemoteLiveStreamRequestApprove';
8
8
  import RemoteLiveStreamRequestReject from './controls/RemoteLiveStreamRequestReject';
9
9
  // Local controls
@@ -14,7 +14,7 @@ import ApprovedLiveStreamControlsView from './ApprovedLiveStreamControlsView';
14
14
 
15
15
  export type {
16
16
  RemoteLiveStreamApprovedRequestRecallProps,
17
- RemoteLiveStreamControlInterface,
17
+ RemoteLiveStreamControlProps,
18
18
  };
19
19
  export {
20
20
  RemoteLiveStreamApprovedRequestRecall,
@@ -20,10 +20,10 @@ import {gql, useMutation} from '@apollo/client';
20
20
  import {useParams} from '../../components/Router';
21
21
  import {PropsContext} from '../../../agora-rn-uikit';
22
22
  import Toast from '../../../react-native-toast-message';
23
- import {createHook} from 'fpe-implementation';
23
+ import {createHook} from 'customization-implementation';
24
24
  import {useString} from '../../utils/useString';
25
25
  import ChatContext from '../../components/ChatContext';
26
- import CustomEvents, {EventLevel} from '../../custom-events';
26
+ import events, {EventPersistLevel} from '../../rtm-events-api';
27
27
  import {EventActions, EventNames} from '../../rtm-events';
28
28
  import useRecordingLayoutQuery from './useRecordingLayoutQuery';
29
29
  import {useScreenContext} from '../../components/contexts/ScreenShareContext';
@@ -31,14 +31,12 @@ import {useScreenContext} from '../../components/contexts/ScreenShareContext';
31
31
  export interface RecordingContextInterface {
32
32
  startRecording: () => void;
33
33
  stopRecording: () => void;
34
- setRecordingActive: React.Dispatch<SetStateAction<boolean>>;
35
34
  isRecordingActive: boolean;
36
35
  }
37
36
 
38
37
  const RecordingContext = createContext<RecordingContextInterface>({
39
38
  startRecording: () => {},
40
39
  stopRecording: () => {},
41
- setRecordingActive: () => {},
42
40
  isRecordingActive: false,
43
41
  });
44
42
 
@@ -69,7 +67,10 @@ function usePrevious<T = any>(value: any) {
69
67
 
70
68
  interface RecordingProviderProps {
71
69
  children: React.ReactNode;
72
- value: Omit<RecordingContextInterface, 'startRecording' | 'stopRecording'>;
70
+ value: {
71
+ setRecordingActive: React.Dispatch<SetStateAction<boolean>>;
72
+ isRecordingActive: boolean;
73
+ };
73
74
  }
74
75
 
75
76
  /**
@@ -91,13 +92,17 @@ const RecordingProvider = (props: RecordingProviderProps) => {
91
92
  //const recordingStartedText = useString<boolean>('recordingNotificationLabel');
92
93
  const recordingStartedText = (active: boolean) =>
93
94
  active ? 'Recording Started' : 'Recording Stopped';
94
- const {executePresenterQuery} = useRecordingLayoutQuery();
95
+ const {executePresenterQuery, executeNormalQuery} = useRecordingLayoutQuery();
95
96
  const {localUid} = useContext(ChatContext);
96
97
  const {screenShareData} = useScreenContext();
97
98
 
98
99
  React.useEffect(() => {
99
- CustomEvents.on(EventNames.RECORDING_ATTRIBUTE, (data) => {
100
- switch (data?.payload?.action) {
100
+ events.on(EventNames.RECORDING_ATTRIBUTE, (data) => {
101
+ const payload = JSON.parse(data.payload);
102
+ const action = payload.action;
103
+ const value = payload.value;
104
+
105
+ switch (action) {
101
106
  case EventActions.RECORDING_STARTED:
102
107
  setRecordingActive(true);
103
108
  break;
@@ -109,7 +114,7 @@ const RecordingProvider = (props: RecordingProviderProps) => {
109
114
  }
110
115
  });
111
116
  () => {
112
- CustomEvents.off(EventNames.RECORDING_ATTRIBUTE);
117
+ events.off(EventNames.RECORDING_ATTRIBUTE);
113
118
  };
114
119
  }, []);
115
120
 
@@ -148,17 +153,31 @@ const RecordingProvider = (props: RecordingProviderProps) => {
148
153
  * 1. Once the backend sucessfuly starts recording, send message
149
154
  * in the channel indicating that cloud recording is now active.
150
155
  */
151
- CustomEvents.send(EventNames.RECORDING_ATTRIBUTE, {
152
- action: EventActions.RECORDING_STARTED,
153
- value: `${localUid}`,
154
- level: EventLevel.LEVEL3,
155
- });
156
+ events.send(
157
+ EventNames.RECORDING_ATTRIBUTE,
158
+ JSON.stringify({
159
+ action: EventActions.RECORDING_STARTED,
160
+ value: `${localUid}`,
161
+ }),
162
+ EventPersistLevel.LEVEL3,
163
+ );
156
164
  // 2. set the local recording state to true to update the UI
157
165
  setRecordingActive(true);
158
166
  // 3. set the presenter mode if screen share is active
159
- if (Object.values(screenShareData).some((item) => item.isActive)) {
160
- console.log('Executing presenter query');
161
- executePresenterQuery();
167
+ // 3.a Get the most recent screenshare uid
168
+ const sorted = Object.entries(screenShareData)
169
+ .filter((el) => el[1]?.ts && el[1].ts > 0 && el[1]?.isActive)
170
+ .sort((a, b) => b[1].ts - a[1].ts);
171
+
172
+ const activeScreenshareUid = sorted.length > 0 ? sorted[0][0] : 0;
173
+ if (activeScreenshareUid) {
174
+ console.log(
175
+ 'screenshare: Executing presenter query for screenuid',
176
+ activeScreenshareUid,
177
+ );
178
+ executePresenterQuery(parseInt(activeScreenshareUid));
179
+ } else {
180
+ executeNormalQuery();
162
181
  }
163
182
  }
164
183
  })
@@ -177,11 +196,14 @@ const RecordingProvider = (props: RecordingProviderProps) => {
177
196
  * 1. Once the backend sucessfuly starts recording, send message
178
197
  * in the channel indicating that cloud recording is now inactive.
179
198
  */
180
- CustomEvents.send(EventNames.RECORDING_ATTRIBUTE, {
181
- action: EventActions.RECORDING_STOPPED,
182
- value: '',
183
- level: EventLevel.LEVEL3,
184
- });
199
+ events.send(
200
+ EventNames.RECORDING_ATTRIBUTE,
201
+ JSON.stringify({
202
+ action: EventActions.RECORDING_STOPPED,
203
+ value: '',
204
+ }),
205
+ EventPersistLevel.LEVEL3,
206
+ );
185
207
  // 2. set the local recording state to false to update the UI
186
208
  setRecordingActive(false);
187
209
  }
@@ -197,7 +219,6 @@ const RecordingProvider = (props: RecordingProviderProps) => {
197
219
  startRecording,
198
220
  stopRecording,
199
221
  isRecordingActive,
200
- setRecordingActive,
201
222
  }}>
202
223
  {props.children}
203
224
  </RecordingContext.Provider>
@@ -1,8 +1,8 @@
1
- import React, {useContext} from 'react';
1
+ import React from 'react';
2
2
  import {useParams} from '../../components/Router';
3
3
 
4
4
  import {gql, useMutation} from '@apollo/client';
5
- import {PropsContext} from '../../../agora-rn-uikit';
5
+ import {UidType} from '../../../agora-rn-uikit';
6
6
 
7
7
  const SET_PRESENTER = gql`
8
8
  mutation setPresenter($uid: Int!, $passphrase: String!) {
@@ -19,10 +19,16 @@ const SET_NORMAL = gql`
19
19
  function useRecordingLayoutQuery() {
20
20
  const [setPresenterQuery] = useMutation(SET_PRESENTER);
21
21
  const [setNormalQuery] = useMutation(SET_NORMAL);
22
- const {screenShareUid} = useContext(PropsContext).rtcProps;
23
22
  const {phrase} = useParams<any>();
24
-
25
- const executePresenterQuery = () => {
23
+ /**
24
+ * @param screenShareUid
25
+ * Default : Grid
26
+ * Below query changes the layout to vertical and passed UID is maxed view
27
+ * This should be called only when screenshare is actively going on
28
+ * and we want that as the main view
29
+ * https://docs.agora.io/en/cloud-recording/cloud_recording_layout?platform=RESTful
30
+ */
31
+ const executePresenterQuery = (screenShareUid: UidType) => {
26
32
  setPresenterQuery({
27
33
  variables: {
28
34
  uid: screenShareUid,
@@ -9,38 +9,28 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import React, {useEffect, useContext, useRef} from 'react';
12
+ import React, {useEffect, useRef} from 'react';
13
13
  import KeepAwake from 'react-native-keep-awake';
14
- import {RtcContext, UidType} from '../../../agora-rn-uikit';
14
+ import {UidType} from '../../../agora-rn-uikit';
15
15
  import {
16
16
  useChangeDefaultLayout,
17
17
  useSetPinnedLayout,
18
18
  } from '../../pages/video-call/DefaultLayouts';
19
- import useUserList from '../../utils/useUserList';
20
19
  import {useScreenContext} from '../../components/contexts/ScreenShareContext';
21
20
  import {useString} from '../../utils/useString';
22
- import CustomEvents from '../../custom-events';
23
- import {EventNames} from '../../rtm-events';
24
-
25
- function usePrevious(value: any) {
26
- const ref = useRef();
27
- useEffect(() => {
28
- ref.current = value;
29
- });
30
- return ref.current;
31
- }
21
+ import events from '../../rtm-events-api';
22
+ import {EventNames, EventActions} from '../../rtm-events';
23
+ import {useRender, useRtc} from 'customization-api';
32
24
 
33
25
  export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
34
- const rtc = useContext(RtcContext);
35
- const {dispatch} = rtc;
36
- const {renderList, renderPosition} = useUserList();
26
+ const {dispatch} = useRtc();
27
+ const {renderList, activeUids} = useRender();
37
28
  const {setScreenShareData, screenShareData} = useScreenContext();
38
29
  // commented for v1 release
39
30
  // const getScreenShareName = useString('screenshareUserName');
40
31
  // const userText = useString('remoteUserDefaultLabel')();
41
32
  const getScreenShareName = (name: string) => `${name}'s screenshare`;
42
33
  const userText = 'User';
43
- const prevRenderPosition = usePrevious({renderPosition});
44
34
  const setPinnedLayout = useSetPinnedLayout();
45
35
  const changeLayout = useChangeDefaultLayout();
46
36
 
@@ -58,30 +48,52 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
58
48
  value: [screenShareUid],
59
49
  });
60
50
  setPinnedLayout();
61
- }
62
- //screenshare is stopped set the layout Grid View
63
- else {
51
+ } else {
52
+ //screenshare is stopped set the layout Grid View
64
53
  changeLayout();
65
54
  }
66
55
  };
67
56
 
68
57
  useEffect(() => {
69
- CustomEvents.on(EventNames.SCREENSHARE_ATTRIBUTE, (data) => {
58
+ events.on(EventNames.SCREENSHARE_ATTRIBUTE, (data) => {
59
+ const payload = JSON.parse(data.payload);
60
+ const action = payload.action;
61
+ const value = payload.value;
62
+
70
63
  const screenUidOfUser =
71
64
  renderListRef.current.renderList[data.sender].screenUid;
72
- setScreenShareData((prevState) => {
73
- return {
74
- ...prevState,
75
- [screenUidOfUser]: {
76
- name: renderListRef.current.renderList[screenUidOfUser]?.name,
77
- isActive: data.payload.value === 'true' ? true : false,
78
- },
79
- };
80
- });
81
- //if remote user started/stopped the screenshare then change the layout to pinned/grid
82
- data.payload.value === 'true'
83
- ? triggerChangeLayout(true, screenUidOfUser)
84
- : triggerChangeLayout(false);
65
+ switch (action) {
66
+ case EventActions.SCREENSHARE_STARTED:
67
+ setScreenShareData((prevState) => {
68
+ return {
69
+ ...prevState,
70
+ [screenUidOfUser]: {
71
+ name: renderListRef.current.renderList[screenUidOfUser]?.name,
72
+ isActive: true,
73
+ ts: value || 0,
74
+ },
75
+ };
76
+ });
77
+ //if remote user started/stopped the screenshare then change the layout to pinned/grid
78
+ triggerChangeLayout(true, screenUidOfUser);
79
+ break;
80
+ case EventActions.SCREENSHARE_STOPPED:
81
+ setScreenShareData((prevState) => {
82
+ return {
83
+ ...prevState,
84
+ [screenUidOfUser]: {
85
+ name: renderListRef.current.renderList[screenUidOfUser]?.name,
86
+ isActive: false,
87
+ ts: value || 0,
88
+ },
89
+ };
90
+ });
91
+ //if remote user started/stopped the screenshare then change the layout to pinned/grid
92
+ triggerChangeLayout(false);
93
+ break;
94
+ default:
95
+ break;
96
+ }
85
97
  });
86
98
  }, []);
87
99
 
@@ -1,5 +1,16 @@
1
+ /*
2
+ ********************************************
3
+ Copyright © 2022 Agora Lab, Inc., all rights reserved.
4
+ AppBuilder and all associated components, source code, APIs, services, and documentation
5
+ (the “Materials”) are owned by Agora Lab, Inc. and its licensors. The Materials may not be
6
+ accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
7
+ Use without a license or in violation of any license terms and conditions (including use for
8
+ any purpose competitive to Agora Lab, Inc.’s business) is strictly prohibited. For more
9
+ information visit https://appbuilder.agora.io.
10
+ *********************************************
11
+ */
1
12
  import React, {useContext, useEffect, useRef, useState} from 'react';
2
- import {RtcContext, PropsContext, UidType} from '../../../agora-rn-uikit';
13
+ import {PropsContext, UidType} from '../../../agora-rn-uikit';
3
14
  import {ScreenshareContext} from './useScreenshare';
4
15
  import {
5
16
  useChangeDefaultLayout,
@@ -7,28 +18,21 @@ import {
7
18
  } from '../../pages/video-call/DefaultLayouts';
8
19
  import {useRecording} from '../recording/useRecording';
9
20
  import {useScreenContext} from '../../components/contexts/ScreenShareContext';
10
- import useUserList from '../../utils/useUserList';
11
- import CustomEvents, {EventLevel} from '../../custom-events';
12
- import {EventNames} from '../../rtm-events';
21
+ import events, {EventPersistLevel} from '../../rtm-events-api';
22
+ import {EventActions, EventNames} from '../../rtm-events';
13
23
  import {IAgoraRTC} from 'agora-rtc-sdk-ng';
14
24
  import useRecordingLayoutQuery from '../recording/useRecordingLayoutQuery';
15
25
  import {useString} from '../../utils/useString';
16
-
17
- function usePrevious<T = any>(value: any) {
18
- const ref = useRef<T>();
19
- useEffect(() => {
20
- ref.current = value;
21
- });
22
- return ref.current;
23
- }
26
+ import {timeNow} from '../../rtm/utils';
27
+ import {useRender, useRtc} from 'customization-api';
24
28
 
25
29
  export const ScreenshareContextConsumer = ScreenshareContext.Consumer;
26
30
 
27
31
  export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
28
32
  const [isScreenshareActive, setScreenshareActive] = useState(false);
29
- const rtc = useContext(RtcContext);
33
+ const rtc = useRtc();
30
34
  const {dispatch} = rtc;
31
- const {renderList, renderPosition} = useUserList();
35
+ const {renderList, activeUids} = useRender();
32
36
  const {isRecordingActive} = useRecording();
33
37
  const {executeNormalQuery, executePresenterQuery} = useRecordingLayoutQuery();
34
38
  const {setScreenShareData, screenShareData} = useScreenContext();
@@ -64,22 +68,45 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
64
68
  };
65
69
 
66
70
  useEffect(() => {
67
- CustomEvents.on(EventNames.SCREENSHARE_ATTRIBUTE, (data) => {
71
+ events.on(EventNames.SCREENSHARE_ATTRIBUTE, (data) => {
72
+ const payload = JSON.parse(data.payload);
73
+ const action = payload.action;
74
+ const value = payload.value;
75
+
68
76
  const screenUidOfUser =
69
77
  renderListRef.current.renderList[data.sender].screenUid;
70
- setScreenShareData((prevState) => {
71
- return {
72
- ...prevState,
73
- [screenUidOfUser]: {
74
- name: renderListRef.current.renderList[screenUidOfUser]?.name,
75
- isActive: data.payload.value === 'true' ? true : false,
76
- },
77
- };
78
- });
79
- //if remote user started/stopped the screenshare then change the layout to pinned/grid
80
- data.payload.value === 'true'
81
- ? triggerChangeLayout(true, screenUidOfUser)
82
- : triggerChangeLayout(false);
78
+ switch (action) {
79
+ case EventActions.SCREENSHARE_STARTED:
80
+ setScreenShareData((prevState) => {
81
+ return {
82
+ ...prevState,
83
+ [screenUidOfUser]: {
84
+ name: renderListRef.current.renderList[screenUidOfUser]?.name,
85
+ isActive: true,
86
+ ts: value || 0,
87
+ },
88
+ };
89
+ });
90
+ //if remote user started/stopped the screenshare then change the layout to pinned/grid
91
+ triggerChangeLayout(true, screenUidOfUser);
92
+ break;
93
+ case EventActions.SCREENSHARE_STOPPED:
94
+ setScreenShareData((prevState) => {
95
+ return {
96
+ ...prevState,
97
+ [screenUidOfUser]: {
98
+ name: renderListRef.current.renderList[screenUidOfUser]?.name,
99
+ isActive: false,
100
+ ts: value || 0,
101
+ },
102
+ };
103
+ });
104
+ //if remote user started/stopped the screenshare then change the layout to pinned/grid
105
+ triggerChangeLayout(false);
106
+ break;
107
+ default:
108
+ break;
109
+ }
83
110
  });
84
111
  }, []);
85
112
 
@@ -89,9 +116,23 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
89
116
  setScreenshareActive(false);
90
117
  console.log('STOPPED SHARING');
91
118
  executeNormalQuery();
92
- CustomEvents.send(EventNames.SCREENSHARE_ATTRIBUTE, {
93
- value: `${false}`,
94
- level: EventLevel.LEVEL2,
119
+ events.send(
120
+ EventNames.SCREENSHARE_ATTRIBUTE,
121
+ JSON.stringify({
122
+ action: EventActions.SCREENSHARE_STOPPED,
123
+ value: 0,
124
+ }),
125
+ EventPersistLevel.LEVEL2,
126
+ );
127
+ setScreenShareData((prevState) => {
128
+ return {
129
+ ...prevState,
130
+ [screenShareUid]: {
131
+ ...prevState[screenShareUid],
132
+ isActive: false,
133
+ ts: 0,
134
+ },
135
+ };
95
136
  });
96
137
  //if local user stopped the screenshare then change layout to grid
97
138
  triggerChangeLayout(false);
@@ -99,9 +140,10 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
99
140
  }, []);
100
141
 
101
142
  const executeRecordingQuery = (isScreenActive: boolean) => {
102
- if (!isScreenActive) {
143
+ if (isScreenActive) {
144
+ console.log('screenshare: Executing presenter query');
103
145
  // If screen share is not going on, start the screen share by executing the graphql query
104
- executePresenterQuery();
146
+ executePresenterQuery(screenShareUid);
105
147
  } else {
106
148
  // If recording is already going on, stop the recording by executing the graphql query.
107
149
  executeNormalQuery();
@@ -134,16 +176,33 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
134
176
  encryption as unknown as any,
135
177
  );
136
178
  isActive && setScreenshareActive(true);
179
+
137
180
  if (isActive) {
138
- CustomEvents.send(EventNames.SCREENSHARE_ATTRIBUTE, {
139
- value: `${true}`,
140
- level: EventLevel.LEVEL2,
181
+ // 1. Set local state
182
+ setScreenShareData((prevState) => {
183
+ return {
184
+ ...prevState,
185
+ [screenShareUid]: {
186
+ name: renderListRef.current.renderList[screenShareUid]?.name,
187
+ isActive: true,
188
+ ts: timeNow(),
189
+ },
190
+ };
141
191
  });
142
- //if local user started the screenshare then change layout to pinned
192
+ // 2. Inform everyone in the channel screenshare is actice
193
+ events.send(
194
+ EventNames.SCREENSHARE_ATTRIBUTE,
195
+ JSON.stringify({
196
+ action: EventActions.SCREENSHARE_STARTED,
197
+ value: timeNow(),
198
+ }),
199
+ EventPersistLevel.LEVEL2,
200
+ );
201
+ //3 . if local user started the screenshare then change layout to pinned
143
202
  triggerChangeLayout(true, screenShareUid);
144
203
  }
145
204
  } catch (e) {
146
- console.error("supriya an't start the screen share", e);
205
+ console.error("can't start the screen share", e);
147
206
  executeNormalQuery();
148
207
  }
149
208
  };
@@ -10,7 +10,7 @@
10
10
  *********************************************
11
11
  */
12
12
  import {createContext} from 'react';
13
- import {createHook} from 'fpe-implementation';
13
+ import {createHook} from 'customization-implementation';
14
14
 
15
15
  export interface ScreenshareContextInterface {
16
16
  isScreenshareActive: boolean;
@@ -14,55 +14,18 @@
14
14
  */
15
15
  type callBackType = (...args: any[]) => void;
16
16
  import {userEventsMapInterface} from '../SDKAppWrapper';
17
+ import {createNanoEvents} from 'nanoevents';
17
18
 
18
19
  interface eventsMapInterface extends userEventsMapInterface {
19
- addFpe: callBackType;
20
- joinMeetingWithPhrase: (phrase: string) => void;
21
- }
22
- interface SDKEventsInterface {
23
- eventsMap: eventsMapInterface;
24
- eventSubs: {[key in keyof eventsMapInterface]: any};
25
- emit: (eventName: keyof eventsMapInterface, ...args: any) => void;
26
- on: (eventName: keyof eventsMapInterface, cb: callBackType) => void;
27
- off: (eventName: keyof eventsMapInterface) => void;
20
+ addFpe?: callBackType;
21
+ addFpeInit?: () => void;
22
+ joinMeetingWithPhrase?: (
23
+ phrase: string,
24
+ resolve: () => void,
25
+ reject: (e: Error) => void,
26
+ ) => void;
28
27
  }
29
28
 
30
- const SDKEvents: SDKEventsInterface = {
31
- eventsMap: {
32
- addFpe: () => {},
33
- joinMeetingWithPhrase: (p) => {},
34
- leave: () => {},
35
- create: () => {},
36
- preJoin: () => {},
37
- join: () => {},
38
- },
39
- eventSubs: {
40
- addFpe: null,
41
- joinMeetingWithPhrase: null,
42
- leave: null,
43
- create: null,
44
- preJoin: null,
45
- join: null,
46
- },
47
- on: function (eventName, cb) {
48
- console.log(
49
- 'DEBUG(aditya)-SDKEvents: event registered:',
50
- eventName,
51
- );
52
- this.eventsMap[eventName] = cb;
53
- if (this.eventSubs[eventName]) {
54
- cb(...this.eventSubs[eventName]);
55
- }
56
- },
57
- emit: function (eventName, ...args) {
58
- console.log('DEBUG(aditya)-SDKEvents: emit called:', eventName, ...args);
59
- this.eventsMap[eventName](...args);
60
- this.eventSubs[eventName] = args;
61
- },
62
- off: function (eventName) {
63
- console.log('DEBUG(aditya)-SDKEvents: event deregistered:', eventName);
64
- this.eventSubs[eventName] = null;
65
- },
66
- };
29
+ const SDKEvents = createNanoEvents<eventsMapInterface>();
67
30
 
68
31
  export default SDKEvents;