agora-appbuilder-core 4.0.29-beta-15 → 4.0.29-beta-16

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": "4.0.29-beta-15",
3
+ "version": "4.0.29-beta-16",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -61,3 +61,5 @@ export type {ChatUIControlsInterface} from '../src/components/chat-ui/useChatUIC
61
61
  export {useVirtualBackground} from '../src/app-state/useVirtualBackground';
62
62
  export {useBeautyEffects} from '../src/app-state/useBeautyEffects';
63
63
  export {useLiveStreamDataContext} from '../src/components/contexts/LiveStreamDataContext';
64
+ export {useRtm} from '../src/components/ChatContext';
65
+ export {useGetHostIds} from '../src/utils/useGetHostUids';
@@ -35,6 +35,7 @@ export interface PreCallInterface extends BeforeAndAfterInterface {
35
35
  joinButton?: React.ComponentType;
36
36
  textBox?: React.ComponentType;
37
37
  virtualBackgroundPanel?: React.ComponentType<VBPanelProps>;
38
+ wrapper?: React.ComponentType;
38
39
  }
39
40
  export interface ChatCmpInterface {
40
41
  //commented for v1 release
@@ -47,3 +47,4 @@ export {getSessionId} from '../src/utils/common';
47
47
  export {default as ThemeConfig} from '../src/theme';
48
48
  export {default as hexadecimalTransparency} from '../src/utils/hexadecimalTransparency';
49
49
  export {useFullScreen} from '../src/utils/useFullScreen';
50
+ export {useHideShareTitle} from '../src/utils/useHideShareTile';
@@ -510,8 +510,15 @@ const AuthProvider = (props: AuthProviderProps) => {
510
510
  'API unauth_login Trying to authenticate user',
511
511
  {requestId: requestId, startReqTs},
512
512
  );
513
+ let user_id_unauth = null;
514
+ try {
515
+ if (isWeb()) {
516
+ const urlParams = new URLSearchParams(window?.location?.search);
517
+ user_id_unauth = urlParams.get('user_id');
518
+ }
519
+ } catch (error) {}
513
520
 
514
- fetch(GET_UNAUTH_FLOW_API_ENDPOINT(), {
521
+ fetch(GET_UNAUTH_FLOW_API_ENDPOINT(user_id_unauth), {
515
522
  credentials: 'include',
516
523
  headers: {
517
524
  'X-Request-Id': requestId,
@@ -46,7 +46,12 @@ export const getOriginURL = () => {
46
46
  return isWeb() ? `${window.location.origin}` : `${$config.FRONTEND_ENDPOINT}`;
47
47
  };
48
48
 
49
- export const GET_UNAUTH_FLOW_API_ENDPOINT = () => {
49
+ export const GET_UNAUTH_FLOW_API_ENDPOINT = (user_id?: string) => {
50
+ if (user_id) {
51
+ return `${$config.BACKEND_ENDPOINT}/v1/login?project_id=${
52
+ $config.PROJECT_ID
53
+ }&platform_id=${getPlatformId()}&user_id=${user_id}`;
54
+ }
50
55
  return `${$config.BACKEND_ENDPOINT}/v1/login?project_id=${
51
56
  $config.PROJECT_ID
52
57
  }&platform_id=${getPlatformId()}`;
@@ -13,6 +13,7 @@ import RtmEngine from 'agora-react-native-rtm';
13
13
  import {UidType} from '../../agora-rn-uikit';
14
14
  import {createContext, SetStateAction} from 'react';
15
15
  import {ChatMessageType} from './chat-messages/useChatMessages';
16
+ import {createHook} from 'customization-implementation';
16
17
 
17
18
  export interface ChatBubbleProps {
18
19
  isLocal: boolean;
@@ -60,7 +61,7 @@ export enum messageActionType {
60
61
  Normal = '1',
61
62
  }
62
63
 
63
- export interface chatContext {
64
+ export interface RtmContextInterface {
64
65
  hasUserJoinedRTM: boolean;
65
66
  rtmInitTimstamp: number;
66
67
  engine: RtmEngine;
@@ -80,6 +81,9 @@ export enum controlMessageEnum {
80
81
  kickScreenshare = '9',
81
82
  }
82
83
 
83
- const ChatContext = createContext(null as unknown as chatContext);
84
+ const RtmContext = createContext(null as unknown as RtmContextInterface);
84
85
 
85
- export default ChatContext;
86
+ const useRtm = createHook(RtmContext);
87
+
88
+ export {useRtm};
89
+ export default RtmContext;
@@ -227,6 +227,7 @@ const Precall = (props: any) => {
227
227
  VirtualBackgroundComponent,
228
228
  PrecallAfterView,
229
229
  PrecallBeforeView,
230
+ wrapper: PrecallWrapper,
230
231
  } = useCustomization(data => {
231
232
  const components: {
232
233
  PrecallAfterView: React.ComponentType;
@@ -235,6 +236,7 @@ const Precall = (props: any) => {
235
236
  VideoPreview: React.ComponentType;
236
237
  VirtualBackgroundComponent: React.ComponentType<VBPanelProps>;
237
238
  MeetingName: React.ComponentType<MeetingTitleProps>;
239
+ wrapper: React.ComponentType;
238
240
  } = {
239
241
  PrecallAfterView: React.Fragment,
240
242
  PrecallBeforeView: React.Fragment,
@@ -242,6 +244,7 @@ const Precall = (props: any) => {
242
244
  VideoPreview: PreCallVideoPreview,
243
245
  DeviceSelect: PreCallSelectDevice,
244
246
  VirtualBackgroundComponent: VBPanel,
247
+ wrapper: React.Fragment,
245
248
  };
246
249
  // commented for v1 release
247
250
  // if (
@@ -288,6 +291,14 @@ const Precall = (props: any) => {
288
291
  // }
289
292
  // }
290
293
  // }
294
+ if (
295
+ data?.components?.precall?.wrapper &&
296
+ typeof data?.components?.precall?.wrapper !== 'object'
297
+ ) {
298
+ if (isValidReactComponent(data?.components?.precall?.wrapper)) {
299
+ components.wrapper = data?.components?.precall?.wrapper;
300
+ }
301
+ }
291
302
  if (
292
303
  data?.components?.precall?.virtualBackgroundPanel &&
293
304
  typeof data?.components?.precall.virtualBackgroundPanel !== 'object' &&
@@ -357,7 +368,7 @@ const Precall = (props: any) => {
357
368
  return FpePrecallComponent ? (
358
369
  <FpePrecallComponent />
359
370
  ) : (
360
- <>
371
+ <PrecallWrapper>
361
372
  <PrecallBeforeView />
362
373
  <View style={{flex: 1}}>
363
374
  <ScrollView
@@ -454,7 +465,7 @@ const Precall = (props: any) => {
454
465
  </ScrollView>
455
466
  </View>
456
467
  <PrecallAfterView />
457
- </>
468
+ </PrecallWrapper>
458
469
  );
459
470
  };
460
471
 
@@ -248,6 +248,7 @@ const Precall = () => {
248
248
  VirtualBackgroundComponent,
249
249
  PrecallAfterView,
250
250
  PrecallBeforeView,
251
+ wrapper: PrecallWrapper,
251
252
  } = useCustomization(data => {
252
253
  const components: {
253
254
  PrecallAfterView: React.ComponentType;
@@ -256,6 +257,7 @@ const Precall = () => {
256
257
  VirtualBackgroundComponent: React.ComponentType<VBPanelProps>;
257
258
  VideoPreview: React.ComponentType;
258
259
  MeetingName: React.ComponentType<MeetingTitleProps>;
260
+ wrapper: React.ComponentType;
259
261
  } = {
260
262
  PrecallAfterView: React.Fragment,
261
263
  PrecallBeforeView: React.Fragment,
@@ -263,6 +265,7 @@ const Precall = () => {
263
265
  VideoPreview: PreCallVideoPreview,
264
266
  DeviceSelect: PreCallSelectDevice,
265
267
  VirtualBackgroundComponent: VBPanel,
268
+ wrapper: React.Fragment,
266
269
  };
267
270
  // commented for v1 release
268
271
  // if (
@@ -310,6 +313,15 @@ const Precall = () => {
310
313
  // }
311
314
  // }
312
315
 
316
+ if (
317
+ data?.components?.precall?.wrapper &&
318
+ typeof data?.components?.precall?.wrapper !== 'object'
319
+ ) {
320
+ if (isValidReactComponent(data?.components?.precall?.wrapper)) {
321
+ components.wrapper = data?.components?.precall?.wrapper;
322
+ }
323
+ }
324
+
313
325
  if (
314
326
  data?.components?.precall?.virtualBackgroundPanel &&
315
327
  typeof data?.components?.precall.virtualBackgroundPanel !== 'object' &&
@@ -388,7 +400,7 @@ const Precall = () => {
388
400
  return FpePrecallComponent ? (
389
401
  <FpePrecallComponent />
390
402
  ) : (
391
- <>
403
+ <PrecallWrapper>
392
404
  <PrecallBeforeView />
393
405
  {$config.EVENT_MODE &&
394
406
  rtcProps.role == ClientRoleType.ClientRoleAudience ? (
@@ -529,7 +541,7 @@ const Precall = () => {
529
541
  </View>
530
542
  )}
531
543
  <PrecallAfterView />
532
- </>
544
+ </PrecallWrapper>
533
545
  );
534
546
  };
535
547
 
@@ -97,7 +97,13 @@ function RTableBody({status, recordings}) {
97
97
  </Text>
98
98
  </View>
99
99
  <View style={style.td}>
100
- {item?.download_url?.length > 0 ? (
100
+ {!item.download_url ? (
101
+ <View style={(style.tactions, {marginTop: 0})}>
102
+ <Text style={style.placeHolder}>
103
+ {item?.error || 'No recording found'}
104
+ </Text>
105
+ </View>
106
+ ) : item?.download_url?.length > 0 ? (
101
107
  item?.download_url?.map((link: string, i: number) => (
102
108
  <View style={style.tactions} key={i}>
103
109
  <View>
@@ -184,87 +184,100 @@ const VideoCallMobileView = props => {
184
184
 
185
185
  const VideoCallView = React.memo(() => {
186
186
  //toolbar changes
187
- const {BottombarComponent, BottombarProps, TopbarComponent, TopbarProps} =
188
- useCustomization(data => {
189
- let components: {
190
- BottombarComponent: React.ComponentType<any>;
191
- BottombarProps?: ToolbarPresetProps['items'];
192
- TopbarComponent: React.ComponentType<NavbarProps>;
193
- TopbarProps?: ToolbarPresetProps['items'];
194
- } = {
195
- BottombarComponent: ActionSheet,
196
- BottombarProps: {},
197
- TopbarComponent: NavbarMobile,
198
- TopbarProps: {},
199
- };
187
+ const {
188
+ BottombarComponent,
189
+ BottombarProps,
190
+ TopbarComponent,
191
+ TopbarProps,
192
+ VideocallWrapper,
193
+ } = useCustomization(data => {
194
+ let components: {
195
+ BottombarComponent: React.ComponentType<any>;
196
+ BottombarProps?: ToolbarPresetProps['items'];
197
+ TopbarComponent: React.ComponentType<NavbarProps>;
198
+ TopbarProps?: ToolbarPresetProps['items'];
199
+ VideocallWrapper?: React.ComponentType;
200
+ } = {
201
+ BottombarComponent: ActionSheet,
202
+ BottombarProps: {},
203
+ TopbarComponent: NavbarMobile,
204
+ TopbarProps: {},
205
+ VideocallWrapper: ContainerView,
206
+ };
207
+ if (
208
+ data?.components?.videoCall &&
209
+ typeof data?.components?.videoCall === 'object'
210
+ ) {
200
211
  if (
201
- data?.components?.videoCall &&
202
- typeof data?.components?.videoCall === 'object'
212
+ data?.components?.videoCall?.bottomToolBar &&
213
+ typeof data?.components?.videoCall.bottomToolBar !== 'object' &&
214
+ isValidReactComponent(data?.components?.videoCall.bottomToolBar)
203
215
  ) {
204
- if (
205
- data?.components?.videoCall?.bottomToolBar &&
206
- typeof data?.components?.videoCall.bottomToolBar !== 'object' &&
207
- isValidReactComponent(data?.components?.videoCall.bottomToolBar)
208
- ) {
209
- components.BottombarComponent =
210
- data?.components?.videoCall.bottomToolBar;
211
- }
212
- if (
213
- data?.components?.videoCall?.bottomToolBar &&
214
- typeof data?.components?.videoCall?.bottomToolBar === 'object' &&
215
- Object.keys(data?.components?.videoCall.bottomToolBar)?.length
216
- ) {
217
- components.BottombarProps = data?.components?.videoCall.bottomToolBar;
218
- }
216
+ components.BottombarComponent =
217
+ data?.components?.videoCall.bottomToolBar;
218
+ }
219
+ if (
220
+ data?.components?.videoCall?.bottomToolBar &&
221
+ typeof data?.components?.videoCall?.bottomToolBar === 'object' &&
222
+ Object.keys(data?.components?.videoCall.bottomToolBar)?.length
223
+ ) {
224
+ components.BottombarProps = data?.components?.videoCall.bottomToolBar;
225
+ }
219
226
 
220
- if (
221
- data?.components?.videoCall?.topToolBar &&
222
- typeof data?.components?.videoCall?.topToolBar !== 'object' &&
223
- isValidReactComponent(data?.components?.videoCall.topToolBar)
224
- ) {
225
- components.TopbarComponent = data?.components?.videoCall.topToolBar;
226
- }
227
+ if (
228
+ data?.components?.videoCall?.topToolBar &&
229
+ typeof data?.components?.videoCall?.topToolBar !== 'object' &&
230
+ isValidReactComponent(data?.components?.videoCall.topToolBar)
231
+ ) {
232
+ components.TopbarComponent = data?.components?.videoCall.topToolBar;
233
+ }
227
234
 
228
- if (
229
- data?.components?.videoCall?.topToolBar &&
230
- typeof data?.components?.videoCall?.topToolBar === 'object' &&
231
- Object.keys(data?.components?.videoCall.topToolBar).length
232
- ) {
233
- components.TopbarProps = data?.components?.videoCall.topToolBar;
234
- }
235
+ if (
236
+ data?.components?.videoCall?.topToolBar &&
237
+ typeof data?.components?.videoCall?.topToolBar === 'object' &&
238
+ Object.keys(data?.components?.videoCall.topToolBar).length
239
+ ) {
240
+ components.TopbarProps = data?.components?.videoCall.topToolBar;
241
+ }
242
+
243
+ if (
244
+ data?.components?.videoCall?.wrapper &&
245
+ typeof data?.components?.videoCall?.wrapper !== 'object' &&
246
+ isValidReactComponent(data?.components?.videoCall.wrapper)
247
+ ) {
248
+ components.VideocallWrapper = data?.components?.videoCall.wrapper;
235
249
  }
250
+ }
236
251
 
237
- return components;
238
- });
252
+ return components;
253
+ });
239
254
 
240
255
  return (
241
- <View style={styles.container}>
242
- <>
243
- <ToolbarProvider value={{position: ToolbarPosition.top}}>
244
- {Object.keys(TopbarProps)?.length ? (
245
- <TopbarComponent items={TopbarProps} includeDefaultItems={false} />
256
+ <VideocallWrapper>
257
+ <ToolbarProvider value={{position: ToolbarPosition.top}}>
258
+ {Object.keys(TopbarProps)?.length ? (
259
+ <TopbarComponent items={TopbarProps} includeDefaultItems={false} />
260
+ ) : (
261
+ <TopbarComponent />
262
+ )}
263
+ </ToolbarProvider>
264
+ <View style={styles.videoView}>
265
+ <VideoComponent />
266
+ <CaptionContainer />
267
+ </View>
268
+ <ToolbarProvider value={{position: ToolbarPosition.bottom}}>
269
+ <ActionSheetProvider>
270
+ {Object.keys(BottombarProps)?.length ? (
271
+ <BottombarComponent
272
+ items={BottombarProps}
273
+ includeDefaultItems={false}
274
+ />
246
275
  ) : (
247
- <TopbarComponent />
276
+ <BottombarComponent />
248
277
  )}
249
- </ToolbarProvider>
250
- <View style={styles.videoView}>
251
- <VideoComponent />
252
- <CaptionContainer />
253
- </View>
254
- <ToolbarProvider value={{position: ToolbarPosition.bottom}}>
255
- <ActionSheetProvider>
256
- {Object.keys(BottombarProps)?.length ? (
257
- <BottombarComponent
258
- items={BottombarProps}
259
- includeDefaultItems={false}
260
- />
261
- ) : (
262
- <BottombarComponent />
263
- )}
264
- </ActionSheetProvider>
265
- </ToolbarProvider>
266
- </>
267
- </View>
278
+ </ActionSheetProvider>
279
+ </ToolbarProvider>
280
+ </VideocallWrapper>
268
281
  );
269
282
  });
270
283
 
@@ -297,3 +310,7 @@ const styles = StyleSheet.create({
297
310
  flexDirection: 'row',
298
311
  },
299
312
  });
313
+
314
+ const ContainerView = props => {
315
+ return <View style={styles.container}>{props.children}</View>;
316
+ };
@@ -10,6 +10,8 @@ import {DispatchContext} from '../../../agora-rn-uikit';
10
10
  import MeetingInfoGridTile from '../../components/meeting-info-invite/MeetingInfoGridTile';
11
11
  import Spacer from '../../atoms/Spacer';
12
12
  import {useLiveStreamDataContext} from '../../components/contexts/LiveStreamDataContext';
13
+ import {useCustomization} from 'customization-implementation';
14
+ import useMount from '../../components/useMount';
13
15
 
14
16
  const VideoComponent = () => {
15
17
  const {dispatch} = useContext(DispatchContext);
@@ -21,23 +23,42 @@ const VideoComponent = () => {
21
23
  const isDesktop = useIsDesktop();
22
24
  const {audienceUids, hostUids} = useLiveStreamDataContext();
23
25
  const [showNoUserInfo, setShowNoUserInfo] = useState(false);
26
+ const isCustomLayoutUsed = useCustomization(config => {
27
+ if (
28
+ typeof config?.components?.videoCall === 'object' &&
29
+ config?.components?.videoCall?.customLayout
30
+ ) {
31
+ return true;
32
+ }
33
+ return false;
34
+ });
24
35
 
25
36
  const {roomPreference} = useRoomInfo();
26
37
 
27
38
  const disableShareTile = roomPreference?.disableShareTile;
39
+ const disableShareTileRef = useRef(disableShareTile);
28
40
 
29
- useEffect(() => {
30
- if (!disableShareTile) {
31
- setTimeout(() => {
41
+ useMount(() => {
42
+ //show share tile after 2.5 seconds because RTC user join take few seconds.
43
+ //meanwhile we don't want to show the share tile
44
+ setTimeout(() => {
45
+ if (!disableShareTileRef.current) {
32
46
  setShowNoUserInfo(true);
33
- }, 2500);
47
+ }
48
+ }, 2500);
49
+ });
50
+
51
+ useEffect(() => {
52
+ disableShareTileRef.current = disableShareTile;
53
+ if (disableShareTile) {
54
+ setShowNoUserInfo(false);
34
55
  }
35
56
  }, [disableShareTile]);
36
57
 
37
58
  const currentLayoutRef = useRef(currentLayout);
38
59
  const gridLayoutName = getGridLayoutName();
39
60
  useEffect(() => {
40
- if (activeUids && activeUids.length === 1) {
61
+ if (activeUids && activeUids.length === 1 && !isCustomLayoutUsed) {
41
62
  if (pinnedUid) {
42
63
  dispatch({type: 'UserPin', value: [0]});
43
64
  dispatch({type: 'UserSecondaryPin', value: [0]});
@@ -46,7 +67,7 @@ const VideoComponent = () => {
46
67
  setLayout(gridLayoutName);
47
68
  }
48
69
  }
49
- }, [activeUids]);
70
+ }, [activeUids, isCustomLayoutUsed]);
50
71
 
51
72
  useEffect(() => {
52
73
  currentLayoutRef.current = currentLayout;
@@ -0,0 +1,6 @@
1
+ import {useVideoMeetingData} from '../components/contexts/VideoMeetingDataContext';
2
+
3
+ export const useGetHostIds = () => {
4
+ const {hostUids} = useVideoMeetingData();
5
+ return hostUids;
6
+ };
@@ -0,0 +1,16 @@
1
+ import {useSetRoomInfo} from '../components/room-info/useSetRoomInfo';
2
+
3
+ export const useHideShareTitle = () => {
4
+ const {setRoomInfo} = useSetRoomInfo();
5
+ return (disableShareTile: boolean) => {
6
+ setRoomInfo(prevState => {
7
+ return {
8
+ ...prevState,
9
+ roomPreference: {
10
+ ...prevState?.roomPreference,
11
+ disableShareTile: disableShareTile,
12
+ },
13
+ };
14
+ });
15
+ };
16
+ };