agora-appbuilder-core 3.0.3 → 3.0.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import {RenderInterface} from './PropsContext';
3
+
4
+ const LastJoinedUserContext = React.createContext<{
5
+ lastUserJoined?: RenderInterface;
6
+ }>({});
7
+
8
+ export const LastJoinedUserProvider = LastJoinedUserContext.Provider;
9
+ export const LastJoinedUserConsumer = LastJoinedUserContext.Consumer;
10
+ export default LastJoinedUserContext;
@@ -46,12 +46,28 @@ export default function UserJoined(
46
46
  stateUpdate = {
47
47
  renderList: renderList,
48
48
  activeUids: activeUids.reverse(),
49
+ lastJoinedUser: {
50
+ ...state.renderList[newUid],
51
+ uid: newUid,
52
+ audio: ToggleState.disabled,
53
+ video: ToggleState.disabled,
54
+ streamType: dualStreamMode === DualStreamMode.HIGH ? 'high' : 'low', // Low if DualStreamMode is LOW or DYNAMIC by default,
55
+ ...typeData,
56
+ },
49
57
  };
50
58
  } else {
51
59
  //More than one remote
52
60
  stateUpdate = {
53
61
  renderList: renderList,
54
62
  activeUids: activeUids,
63
+ lastJoinedUser: {
64
+ ...state.renderList[newUid],
65
+ uid: newUid,
66
+ audio: ToggleState.disabled,
67
+ video: ToggleState.disabled,
68
+ streamType: dualStreamMode === DualStreamMode.HIGH ? 'high' : 'low', // Low if DualStreamMode is LOW or DYNAMIC by default,
69
+ ...typeData,
70
+ },
55
71
  };
56
72
  }
57
73
 
@@ -13,6 +13,7 @@ import PropsContext, {
13
13
  DualStreamMode,
14
14
  } from './Contexts/PropsContext';
15
15
  import {RenderProvider} from './Contexts/RenderContext';
16
+ import {LastJoinedUserProvider} from './Contexts/LastJoinedUserContext';
16
17
  import {actionTypeGuard} from './Utils/actionTypeGuard';
17
18
 
18
19
  import {
@@ -322,7 +323,10 @@ const RtcConfigure = (props: {children: React.ReactNode}) => {
322
323
  renderList: uidState.renderList,
323
324
  activeUids: uidState.activeUids,
324
325
  }}>
325
- {props.children}
326
+ <LastJoinedUserProvider
327
+ value={{lastUserJoined: uidState.lastJoinedUser}}>
328
+ {props.children}
329
+ </LastJoinedUserProvider>
326
330
  </RenderProvider>
327
331
  </RtcProvider>
328
332
  </Join>
@@ -10,6 +10,11 @@ export {
10
10
  LocalProvider,
11
11
  LocalContext,
12
12
  } from './Contexts/LocalUserContext';
13
+ export {
14
+ default as LastJoinedUserContext,
15
+ LastJoinedUserConsumer,
16
+ LastJoinedUserProvider,
17
+ } from './Contexts/LastJoinedUserContext';
13
18
  export {
14
19
  default as RenderContext,
15
20
  RenderConsumer,
@@ -2,7 +2,11 @@
2
2
  * Core contexts
3
3
  */
4
4
  import {createHook} from 'customization-implementation';
5
- import {RtcContext, RenderContext} from '../agora-rn-uikit';
5
+ import {
6
+ RtcContext,
7
+ RenderContext,
8
+ LastJoinedUserContext,
9
+ } from '../agora-rn-uikit';
6
10
 
7
11
  // commented for v1 release
8
12
  //import {default as DeviceContext} from '../src/components/DeviceContext';
@@ -15,6 +19,8 @@ export const useRtc = createHook(RtcContext);
15
19
  * The Render app state governs the information necessary to render each user content view displayed in the videocall screen.
16
20
  */
17
21
  export const useRender = createHook(RenderContext);
22
+
23
+ export const useLastJoinedUser = createHook(LastJoinedUserContext);
18
24
  export {useLocalUserInfo} from '../src/app-state/useLocalUserInfo';
19
25
 
20
26
  // commented for v1 release
@@ -205,24 +205,24 @@ const VideoCall: React.FC = () => {
205
205
  <DeviceConfigure>
206
206
  <ChatUIControlProvider>
207
207
  <ChatNotificationProvider>
208
- <SidePanelProvider
208
+ <LayoutProvider
209
209
  value={{
210
- sidePanel,
211
- setSidePanel,
210
+ currentLayout,
211
+ setLayout,
212
212
  }}>
213
- <ChatMessagesProvider>
214
- <ScreenShareProvider>
215
- <RtmConfigure
216
- setRecordingActive={setRecordingActive}
217
- callActive={callActive}>
218
- <UserPreferenceProvider>
219
- <EventsConfigure>
220
- <WhiteboardProvider>
221
- <LayoutProvider
222
- value={{
223
- currentLayout,
224
- setLayout,
225
- }}>
213
+ <SidePanelProvider
214
+ value={{
215
+ sidePanel,
216
+ setSidePanel,
217
+ }}>
218
+ <ChatMessagesProvider>
219
+ <ScreenShareProvider>
220
+ <RtmConfigure
221
+ setRecordingActive={setRecordingActive}
222
+ callActive={callActive}>
223
+ <UserPreferenceProvider>
224
+ <EventsConfigure>
225
+ <WhiteboardProvider>
226
226
  <RecordingProvider
227
227
  value={{
228
228
  setRecordingActive,
@@ -262,14 +262,14 @@ const VideoCall: React.FC = () => {
262
262
  </LiveStreamContextProvider>
263
263
  </ScreenshareConfigure>
264
264
  </RecordingProvider>
265
- </LayoutProvider>
266
- </WhiteboardProvider>
267
- </EventsConfigure>
268
- </UserPreferenceProvider>
269
- </RtmConfigure>
270
- </ScreenShareProvider>
271
- </ChatMessagesProvider>
272
- </SidePanelProvider>
265
+ </WhiteboardProvider>
266
+ </EventsConfigure>
267
+ </UserPreferenceProvider>
268
+ </RtmConfigure>
269
+ </ScreenShareProvider>
270
+ </ChatMessagesProvider>
271
+ </SidePanelProvider>
272
+ </LayoutProvider>
273
273
  </ChatNotificationProvider>
274
274
  </ChatUIControlProvider>
275
275
  </DeviceConfigure>
@@ -13,6 +13,8 @@ import React, {useEffect, useRef} from 'react';
13
13
  import KeepAwake from 'react-native-keep-awake';
14
14
  import {UidType} from '../../../agora-rn-uikit';
15
15
  import {
16
+ getGridLayoutName,
17
+ getPinnedLayoutName,
16
18
  useChangeDefaultLayout,
17
19
  useSetPinnedLayout,
18
20
  } from '../../pages/video-call/DefaultLayouts';
@@ -20,11 +22,17 @@ import {useScreenContext} from '../../components/contexts/ScreenShareContext';
20
22
  import {useString} from '../../utils/useString';
21
23
  import events from '../../rtm-events-api';
22
24
  import {EventNames, EventActions} from '../../rtm-events';
23
- import {useRender, useRtc} from 'customization-api';
25
+ import {
26
+ useLastJoinedUser,
27
+ useLayout,
28
+ useRender,
29
+ useRtc,
30
+ } from 'customization-api';
24
31
 
25
32
  export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
26
33
  const {dispatch} = useRtc();
27
34
  const {renderList, activeUids} = useRender();
35
+ const {lastUserJoined: lastJoinedUser} = useLastJoinedUser();
28
36
  const {setScreenShareData, screenShareData} = useScreenContext();
29
37
  // commented for v1 release
30
38
  // const getScreenShareName = useString('screenshareUserName');
@@ -33,24 +41,43 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
33
41
  const userText = 'User';
34
42
  const setPinnedLayout = useSetPinnedLayout();
35
43
  const changeLayout = useChangeDefaultLayout();
36
-
44
+ const {currentLayout} = useLayout();
37
45
  const renderListRef = useRef({renderList: renderList});
46
+ const currentLayoutRef = useRef({currentLayout: currentLayout});
38
47
 
39
48
  useEffect(() => {
40
49
  renderListRef.current.renderList = renderList;
41
50
  }, [renderList]);
42
51
 
52
+ useEffect(() => {
53
+ currentLayoutRef.current.currentLayout = currentLayout;
54
+ }, [currentLayout]);
55
+
56
+ useEffect(() => {
57
+ if (
58
+ lastJoinedUser &&
59
+ lastJoinedUser?.uid &&
60
+ lastJoinedUser?.type === 'screenshare' &&
61
+ activeUids &&
62
+ activeUids.indexOf(lastJoinedUser.uid) !== -1
63
+ ) {
64
+ //set to pinned layout
65
+ triggerChangeLayout(true, lastJoinedUser.uid);
66
+ }
67
+ }, [lastJoinedUser, activeUids]);
68
+
43
69
  const triggerChangeLayout = (pinned: boolean, screenShareUid?: UidType) => {
70
+ let layout = currentLayoutRef.current.currentLayout;
44
71
  //screenshare is started set the layout to Pinned View
45
72
  if (pinned && screenShareUid) {
46
73
  dispatch({
47
74
  type: 'SwapVideo',
48
75
  value: [screenShareUid],
49
76
  });
50
- setPinnedLayout();
77
+ layout !== getPinnedLayoutName() && setPinnedLayout();
51
78
  } else {
52
79
  //screenshare is stopped set the layout Grid View
53
- changeLayout();
80
+ layout !== getGridLayoutName() && changeLayout();
54
81
  }
55
82
  };
56
83
 
@@ -74,8 +101,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
74
101
  },
75
102
  };
76
103
  });
77
- //if remote user started/stopped the screenshare then change the layout to pinned/grid
78
- triggerChangeLayout(true, screenUidOfUser);
79
104
  break;
80
105
  case EventActions.SCREENSHARE_STOPPED:
81
106
  setScreenShareData((prevState) => {
@@ -13,6 +13,8 @@ import React, {useContext, useEffect, useRef, useState} from 'react';
13
13
  import {PropsContext, UidType} from '../../../agora-rn-uikit';
14
14
  import {ScreenshareContext} from './useScreenshare';
15
15
  import {
16
+ getGridLayoutName,
17
+ getPinnedLayoutName,
16
18
  useChangeDefaultLayout,
17
19
  useSetPinnedLayout,
18
20
  } from '../../pages/video-call/DefaultLayouts';
@@ -24,7 +26,12 @@ import {IAgoraRTC} from 'agora-rtc-sdk-ng';
24
26
  import useRecordingLayoutQuery from '../recording/useRecordingLayoutQuery';
25
27
  import {useString} from '../../utils/useString';
26
28
  import {timeNow} from '../../rtm/utils';
27
- import {useRender, useRtc} from 'customization-api';
29
+ import {
30
+ useLastJoinedUser,
31
+ useLayout,
32
+ useRender,
33
+ useRtc,
34
+ } from 'customization-api';
28
35
 
29
36
  export const ScreenshareContextConsumer = ScreenshareContext.Consumer;
30
37
 
@@ -33,6 +40,8 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
33
40
  const rtc = useRtc();
34
41
  const {dispatch} = rtc;
35
42
  const {renderList, activeUids} = useRender();
43
+ const {lastUserJoined: lastJoinedUser} = useLastJoinedUser();
44
+
36
45
  const {isRecordingActive} = useRecording();
37
46
  const {executeNormalQuery, executePresenterQuery} = useRecordingLayoutQuery();
38
47
  const {setScreenShareData, screenShareData} = useScreenContext();
@@ -43,6 +52,8 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
43
52
  const userText = 'User';
44
53
  const setPinnedLayout = useSetPinnedLayout();
45
54
  const changeLayout = useChangeDefaultLayout();
55
+ const {currentLayout} = useLayout();
56
+ const currentLayoutRef = useRef({currentLayout: currentLayout});
46
57
 
47
58
  const {channel, appId, screenShareUid, screenShareToken, encryption} =
48
59
  useContext(PropsContext).rtcProps;
@@ -53,17 +64,40 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
53
64
  renderListRef.current.renderList = renderList;
54
65
  }, [renderList]);
55
66
 
67
+ useEffect(() => {
68
+ currentLayoutRef.current.currentLayout = currentLayout;
69
+ }, [currentLayout]);
70
+
71
+ /**
72
+ * Event api callback trigger even before screenshare data available in the RTC layer.
73
+ * so instead of calling triggerChangeLayout from the event api call back
74
+ * listening for rtc layout lastJoinedUser data and if its screenshare then call triggerChangeLayout
75
+ */
76
+ useEffect(() => {
77
+ if (
78
+ lastJoinedUser &&
79
+ lastJoinedUser?.uid &&
80
+ lastJoinedUser?.type === 'screenshare' &&
81
+ activeUids &&
82
+ activeUids.indexOf(lastJoinedUser.uid) !== -1
83
+ ) {
84
+ //set to pinned layout
85
+ triggerChangeLayout(true, lastJoinedUser.uid);
86
+ }
87
+ }, [lastJoinedUser, activeUids]);
88
+
56
89
  const triggerChangeLayout = (pinned: boolean, screenShareUid?: UidType) => {
90
+ let layout = currentLayoutRef.current.currentLayout;
57
91
  //screenshare is started set the layout to Pinned View
58
92
  if (pinned && screenShareUid) {
59
93
  dispatch({
60
94
  type: 'SwapVideo',
61
95
  value: [screenShareUid],
62
96
  });
63
- setPinnedLayout();
97
+ layout !== getPinnedLayoutName() && setPinnedLayout();
64
98
  } else {
65
99
  //screenshare is stopped set the layout Grid View
66
- changeLayout();
100
+ layout !== getGridLayoutName() && changeLayout();
67
101
  }
68
102
  };
69
103
 
@@ -87,8 +121,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
87
121
  },
88
122
  };
89
123
  });
90
- //if remote user started/stopped the screenshare then change the layout to pinned/grid
91
- triggerChangeLayout(true, screenUidOfUser);
92
124
  break;
93
125
  case EventActions.SCREENSHARE_STOPPED:
94
126
  setScreenShareData((prevState) => {
@@ -198,8 +230,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
198
230
  }),
199
231
  EventPersistLevel.LEVEL2,
200
232
  );
201
- //3 . if local user started the screenshare then change layout to pinned
202
- triggerChangeLayout(true, screenShareUid);
203
233
  }
204
234
  } catch (e) {
205
235
  console.error("can't start the screen share", e);