agora-appbuilder-core 4.1.9-beta.3 → 4.1.10-beta.1

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 (109) hide show
  1. package/package.json +2 -2
  2. package/template/Gulpfile.js +0 -16
  3. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -3
  4. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +1 -2
  5. package/template/agora-rn-uikit/src/Reducer/index.ts +0 -2
  6. package/template/agora-rn-uikit/src/Rtc/Join.tsx +11 -25
  7. package/template/agora-rn-uikit/src/RtcConfigure.tsx +1 -14
  8. package/template/bridge/rtc/webNg/RtcEngine.ts +2 -2
  9. package/template/bridge/rtm/web/index.ts +30 -0
  10. package/template/customization-api/typeDefinition.ts +1 -0
  11. package/template/defaultConfig.js +3 -2
  12. package/template/global.d.ts +1 -0
  13. package/template/package.json +0 -2
  14. package/template/src/AppRoutes.tsx +3 -3
  15. package/template/src/ai-agent/components/ControlButtons.tsx +1 -1
  16. package/template/src/assets/font-styles.css +36 -0
  17. package/template/src/assets/fonts/icomoon.ttf +0 -0
  18. package/template/src/assets/selection.json +1 -1
  19. package/template/src/atoms/CustomIcon.tsx +8 -0
  20. package/template/src/atoms/Dropdown.tsx +5 -0
  21. package/template/src/atoms/TertiaryButton.tsx +1 -1
  22. package/template/src/atoms/UserAvatar.tsx +1 -1
  23. package/template/src/components/ChatContext.ts +5 -3
  24. package/template/src/components/Controls.tsx +68 -22
  25. package/template/src/components/DeviceConfigure.tsx +1 -1
  26. package/template/src/components/EventsConfigure.tsx +22 -17
  27. package/template/src/components/Navbar.tsx +14 -11
  28. package/template/src/components/RTMConfigure.tsx +31 -1036
  29. package/template/src/components/UserGlobalPreferenceProvider.tsx +227 -0
  30. package/template/src/components/beauty-effect/useBeautyEffects.tsx +50 -13
  31. package/template/src/components/breakout-room/BreakoutRoomPanel.tsx +58 -0
  32. package/template/src/components/breakout-room/context/BreakoutRoomContext.tsx +2508 -0
  33. package/template/src/components/breakout-room/events/BreakoutRoomEventsConfigure.tsx +272 -0
  34. package/template/src/components/breakout-room/events/constants.ts +17 -0
  35. package/template/src/components/breakout-room/hoc/BreakoutRoomNameRenderer.tsx +68 -0
  36. package/template/src/components/breakout-room/hooks/useBreakoutRoomExit.ts +49 -0
  37. package/template/src/components/breakout-room/state/reducer.ts +522 -0
  38. package/template/src/components/breakout-room/state/types.ts +54 -0
  39. package/template/src/components/breakout-room/ui/BreakoutMeetingTitle.tsx +60 -0
  40. package/template/src/components/breakout-room/ui/BreakoutRoomActionMenu.tsx +136 -0
  41. package/template/src/components/breakout-room/ui/BreakoutRoomAnnouncementModal.tsx +135 -0
  42. package/template/src/components/breakout-room/ui/BreakoutRoomGroupSettings.tsx +588 -0
  43. package/template/src/components/breakout-room/ui/BreakoutRoomMainRoomUsers.tsx +142 -0
  44. package/template/src/components/breakout-room/ui/BreakoutRoomMemberActionMenu.tsx +122 -0
  45. package/template/src/components/breakout-room/ui/BreakoutRoomParticipants.tsx +124 -0
  46. package/template/src/components/breakout-room/ui/BreakoutRoomRaiseHand.tsx +65 -0
  47. package/template/src/components/breakout-room/ui/BreakoutRoomRenameModal.tsx +227 -0
  48. package/template/src/components/breakout-room/ui/BreakoutRoomSettings.tsx +140 -0
  49. package/template/src/components/breakout-room/ui/BreakoutRoomTransition.tsx +52 -0
  50. package/template/src/components/breakout-room/ui/BreakoutRoomView.tsx +193 -0
  51. package/template/src/components/breakout-room/ui/ExitBreakoutRoomIconButton.tsx +79 -0
  52. package/template/src/components/breakout-room/ui/ParticipantManualAssignmentModal.tsx +638 -0
  53. package/template/src/components/breakout-room/ui/SelectParticipantAssignmentStrategy.tsx +57 -0
  54. package/template/src/components/chat/chatConfigure.tsx +7 -1
  55. package/template/src/components/chat-messages/useChatMessages.tsx +43 -11
  56. package/template/src/components/common/Dividers.tsx +53 -0
  57. package/template/src/components/controls/toolbar-items/ExitBreakoutRoomToolbarItem.tsx +13 -0
  58. package/template/src/components/controls/useControlPermissionMatrix.tsx +32 -4
  59. package/template/src/components/participants/AllHostParticipants.tsx +10 -2
  60. package/template/src/components/participants/Participant.tsx +7 -1
  61. package/template/src/components/participants/UserActionMenuOptions.tsx +12 -2
  62. package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +12 -8
  63. package/template/src/components/precall/joinWaitingRoomBtn.tsx +14 -10
  64. package/template/src/components/raise-hand/RaiseHandButton.tsx +50 -0
  65. package/template/src/components/raise-hand/RaiseHandProvider.tsx +308 -0
  66. package/template/src/components/raise-hand/index.ts +14 -0
  67. package/template/src/components/recordings/RecordingsDateTable.tsx +3 -2
  68. package/template/src/components/room-info/useCurrentRoomInfo.tsx +42 -0
  69. package/template/src/components/room-info/useSetBreakoutRoomInfo.tsx +64 -0
  70. package/template/src/components/useUserPreference.tsx +39 -12
  71. package/template/src/components/virtual-background/useVB.tsx +18 -0
  72. package/template/src/components/whiteboard/WhiteboardConfigure.tsx +27 -0
  73. package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -0
  74. package/template/src/logger/AppBuilderLogger.tsx +11 -3
  75. package/template/src/pages/VideoCall.tsx +171 -518
  76. package/template/src/pages/video-call/BreakoutVideoCall.tsx +213 -0
  77. package/template/src/pages/video-call/SidePanelHeader.tsx +17 -0
  78. package/template/src/pages/video-call/VideoCallContent.tsx +211 -0
  79. package/template/src/pages/video-call/VideoCallScreen.tsx +18 -0
  80. package/template/src/pages/video-call/VideoCallScreenWrapper.tsx +0 -1
  81. package/template/src/pages/video-call/VideoCallStateWrapper.tsx +495 -0
  82. package/template/src/rtm/RTMConfigureBreakoutRoomProvider.tsx +882 -0
  83. package/template/src/rtm/RTMConfigureMainRoomProvider.tsx +757 -0
  84. package/template/src/rtm/RTMCoreProvider.tsx +419 -0
  85. package/template/src/rtm/RTMEngine.ts +188 -60
  86. package/template/src/rtm/RTMGlobalStateProvider.tsx +706 -0
  87. package/template/src/rtm/RTMStatusBanner.tsx +99 -0
  88. package/template/src/rtm/constants.ts +12 -0
  89. package/template/src/rtm/hooks/useMainRoomUserDisplayName.ts +45 -0
  90. package/template/src/rtm/rtm-presence-utils.ts +344 -0
  91. package/template/src/rtm/utils.ts +68 -1
  92. package/template/src/rtm-events/constants.ts +40 -1
  93. package/template/src/rtm-events-api/Events.ts +62 -19
  94. package/template/src/subComponents/ChatBubble.tsx +3 -3
  95. package/template/src/subComponents/ChatContainer.tsx +19 -9
  96. package/template/src/subComponents/LocalAudioMute.tsx +2 -2
  97. package/template/src/subComponents/LocalVideoMute.tsx +2 -2
  98. package/template/src/subComponents/SidePanelEnum.tsx +1 -0
  99. package/template/src/subComponents/caption/useCaption.tsx +1 -1
  100. package/template/src/subComponents/chat/ChatAnnouncementView.tsx +65 -0
  101. package/template/src/subComponents/chat/ChatSendButton.tsx +1 -0
  102. package/template/src/subComponents/screenshare/ScreenshareButton.tsx +16 -0
  103. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +1 -1
  104. package/template/src/subComponents/waiting-rooms/WaitingRoomControls.tsx +7 -4
  105. package/template/src/utils/useDebouncedCallback.tsx +20 -0
  106. package/template/src/utils/useEndCall.ts +0 -2
  107. package/template/src/utils/useMuteToggleLocal.ts +14 -10
  108. package/template/agora-rn-uikit/src/Reducer/Spotlight.ts +0 -11
  109. package/template/agora-rn-uikit/src/Reducer/UserBanned.ts +0 -11
@@ -7,6 +7,7 @@ import {useLocalUid} from '../../../agora-rn-uikit';
7
7
  import {UidType, useContent} from 'customization-api';
8
8
  import {
9
9
  ChatMessageType,
10
+ ChatNotificationType,
10
11
  ChatOption,
11
12
  SDKChatType,
12
13
  useChatMessages,
@@ -255,7 +256,7 @@ const ChatConfigure = ({children}) => {
255
256
  );
256
257
  }
257
258
  },
258
- // text message is recieved
259
+ // Text message is recieved, update receiver side ui
259
260
  onTextMessage: message => {
260
261
  if (message?.ext?.channel !== data?.channel) {
261
262
  return;
@@ -272,11 +273,14 @@ const ChatConfigure = ({children}) => {
272
273
 
273
274
  if (message.chatType === SDKChatType.GROUP_CHAT) {
274
275
  // show to notifcation- group msg received
276
+
275
277
  showMessageNotification(
276
278
  message.msg,
277
279
  fromUser,
278
280
  false,
279
281
  message.type,
282
+ false,
283
+ message.ext?.announcement,
280
284
  );
281
285
  addMessageToStore(Number(fromUser), {
282
286
  msg: message.msg.replace(/^(\n)+|(\n)+$/g, ''),
@@ -285,6 +289,7 @@ const ChatConfigure = ({children}) => {
285
289
  isDeleted: false,
286
290
  type: ChatMessageType.TXT,
287
291
  replyToMsgId: message.ext?.replyToMsgId,
292
+ announcement: message.ext?.announcement,
288
293
  });
289
294
  }
290
295
 
@@ -418,6 +423,7 @@ const ChatConfigure = ({children}) => {
418
423
  ext: option?.ext?.file_ext,
419
424
  fileName: option?.ext?.file_name,
420
425
  replyToMsgId: option?.ext?.replyToMsgId,
426
+ announcement: option?.ext?.announcement,
421
427
  };
422
428
 
423
429
  // update local user message store
@@ -46,6 +46,11 @@ interface ChatMessagesProviderProps {
46
46
  children: React.ReactNode;
47
47
  callActive: boolean;
48
48
  }
49
+
50
+ export enum ChatNotificationType {
51
+ ANNOUNCEMENT = 'ANNOUNCEMENT',
52
+ }
53
+
49
54
  export enum ChatMessageType {
50
55
  /**
51
56
  * Text message.
@@ -85,6 +90,10 @@ export enum ChatMessageType {
85
90
  COMBINE = 'combine',
86
91
  }
87
92
 
93
+ export interface AnnouncementMessage {
94
+ sender: string;
95
+ heading: string;
96
+ }
88
97
  export interface messageInterface {
89
98
  createdTimestamp: number;
90
99
  updatedTimestamp?: number;
@@ -99,6 +108,7 @@ export interface messageInterface {
99
108
  reactions?: Reaction[];
100
109
  replyToMsgId?: string;
101
110
  hide?: boolean;
111
+ announcement?: AnnouncementMessage;
102
112
  }
103
113
 
104
114
  export enum SDKChatType {
@@ -122,6 +132,7 @@ export interface ChatOption {
122
132
  channel?: string;
123
133
  msg?: string;
124
134
  replyToMsgId?: string;
135
+ announcement?: AnnouncementMessage;
125
136
  };
126
137
  url?: string;
127
138
  }
@@ -178,6 +189,8 @@ interface ChatMessagesInterface {
178
189
  uid: string,
179
190
  isPrivateMessage?: boolean,
180
191
  msgType?: ChatMessageType,
192
+ forceStop?: boolean,
193
+ notificationType?: ChatNotificationType,
181
194
  ) => void;
182
195
  openPrivateChat: (toUid: UidType) => void;
183
196
  removeMessageFromStore: (msgId: string, isMsgRecalled: boolean) => void;
@@ -277,11 +290,20 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
277
290
 
278
291
  //commented for v1 release
279
292
  //const fromText = useString('messageSenderNotificationLabel');
280
- const fromText = (name: string, msgType: ChatMessageType) => {
293
+ const fromText = (
294
+ name: string,
295
+ msgType: ChatMessageType,
296
+ announcement?: AnnouncementText,
297
+ ) => {
281
298
  let text = '';
282
299
  switch (msgType) {
283
300
  case ChatMessageType.TXT:
284
- text = txtToastHeading?.current(name);
301
+ if (announcement?.text) {
302
+ text = `${announcement.sender}: made an announcement in public chat`;
303
+ } else {
304
+ text = txtToastHeading?.current(name);
305
+ }
306
+
285
307
  break;
286
308
  case ChatMessageType.IMAGE:
287
309
  text = imgToastHeading?.current(name);
@@ -329,12 +351,15 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
329
351
 
330
352
  //TODO: check why need
331
353
 
332
- const updateRenderListState = (
333
- uid: number,
334
- data: Partial<ContentInterface>,
335
- ) => {
336
- dispatch({type: 'UpdateRenderList', value: [uid, data]});
337
- };
354
+ // If this is needed use syncUserState
355
+ //
356
+ // const updateRenderListState = (
357
+ // uid: number,
358
+ // data: Partial<ContentInterface>,
359
+ // ) => {
360
+ // dispatch({type: 'UpdateRenderList', value: [uid, data]});
361
+ // };
362
+ //
338
363
 
339
364
  const addMessageToStore = (uid: UidType, body: messageInterface) => {
340
365
  setMessageStore((m: messageStoreInterface[]) => {
@@ -353,6 +378,7 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
353
378
  fileName: body?.fileName,
354
379
  replyToMsgId: body?.replyToMsgId,
355
380
  hide: false,
381
+ announcement: body?.announcement,
356
382
  },
357
383
  ];
358
384
  });
@@ -520,6 +546,7 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
520
546
  isPrivateMessage: boolean = false,
521
547
  msgType: ChatMessageType,
522
548
  forceStop: boolean = false,
549
+ announcement: AnnouncementMessage,
523
550
  ) => {
524
551
  if (isUserBanedRef.current.isUserBaned) {
525
552
  return;
@@ -684,17 +711,22 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
684
711
  primaryBtn: null,
685
712
  secondaryBtn: null,
686
713
  type: 'info',
687
- leadingIconName: 'chat-nav',
688
- text1: isPrivateMessage
714
+ leadingIconName: announcement ? 'announcement' : 'chat-nav',
715
+ text1: announcement
716
+ ? announcement.heading
717
+ : isPrivateMessage
689
718
  ? privateMessageLabel?.current()
690
719
  : //@ts-ignore
691
- defaultContentRef.current.defaultContent[uidAsNumber]?.name
720
+ announcement?.sender
721
+ ? announcement.sender
722
+ : defaultContentRef.current.defaultContent[uidAsNumber]?.name
692
723
  ? fromText(
693
724
  trimText(
694
725
  //@ts-ignore
695
726
  defaultContentRef.current.defaultContent[uidAsNumber]?.name,
696
727
  ),
697
728
  msgType,
729
+ announcement,
698
730
  )
699
731
  : '',
700
732
  text2: isPrivateMessage
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ import {View, StyleSheet} from 'react-native';
3
+ import ThemeConfig from '../../theme';
4
+
5
+ interface DividerProps {
6
+ orientation?: 'horizontal' | 'vertical';
7
+ marginTop?: number;
8
+ marginBottom?: number;
9
+ marginLeft?: number;
10
+ marginRight?: number;
11
+ thickness?: number;
12
+ color?: string;
13
+ length?: number | string; // only for vertical dividers
14
+ }
15
+
16
+ const Divider: React.FC<DividerProps> = ({
17
+ orientation = 'horizontal',
18
+ marginTop = 8,
19
+ marginBottom = 8,
20
+ marginLeft = 0,
21
+ marginRight = 0,
22
+ thickness = 1,
23
+ color = $config.CARD_LAYER_4_COLOR,
24
+ length = '100%',
25
+ }) => {
26
+ const isHorizontal = orientation === 'horizontal';
27
+
28
+ const style = isHorizontal
29
+ ? {
30
+ height: thickness,
31
+ width: '100%',
32
+ backgroundColor: color,
33
+ marginTop,
34
+ marginBottom,
35
+ }
36
+ : {
37
+ width: thickness,
38
+ height: length,
39
+ backgroundColor: color,
40
+ marginLeft,
41
+ marginRight,
42
+ };
43
+
44
+ return <View style={[styles.base, style]} />;
45
+ };
46
+
47
+ const styles = StyleSheet.create({
48
+ base: {
49
+ backgroundColor: $config.CARD_LAYER_4_COLOR,
50
+ },
51
+ });
52
+
53
+ export default Divider;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import ToolbarItem, {ToolbarItemProps} from '../../../atoms/ToolbarItem';
3
+ import ExitBreakoutRoomIconButton from '../../breakout-room/ui/ExitBreakoutRoomIconButton';
4
+
5
+ export interface Props extends ToolbarItemProps {}
6
+
7
+ export const ExitBreakoutRoomToolbarItem = (props: Props) => {
8
+ return (
9
+ <ToolbarItem testID="exit-breakout-room-btn" toolbarProps={props}>
10
+ <ExitBreakoutRoomIconButton />
11
+ </ToolbarItem>
12
+ );
13
+ };
@@ -3,7 +3,9 @@ import {useContext} from 'react';
3
3
  import {ClientRoleType, PropsContext} from '../../../agora-rn-uikit/src';
4
4
  import {useRoomInfo} from '../room-info/useRoomInfo';
5
5
  import {joinRoomPreference} from '../../utils/useJoinRoom';
6
- import {isWeb} from '../../utils/common';
6
+ import {isWeb, isWebInternal} from '../../utils/common';
7
+ import {ENABLE_AUTH} from '../../auth/config';
8
+ import {useBreakoutRoomInfo} from '../room-info/useSetBreakoutRoomInfo';
7
9
 
8
10
  /**
9
11
  * ControlPermissionKey represents the different keys
@@ -15,7 +17,12 @@ export type ControlPermissionKey =
15
17
  | 'participantControl'
16
18
  | 'screenshareControl'
17
19
  | 'settingsControl'
18
- | 'viewAllTextTracks';
20
+ | 'viewAllTextTracksControl'
21
+ | 'breakoutRoomControl'
22
+ | 'whiteboardControl'
23
+ | 'recordingControl'
24
+ | 'captionsControl'
25
+ | 'transcriptsControl';
19
26
 
20
27
  /**
21
28
  * ControlPermissionRule defines the properties used to evaluate permission rules.
@@ -24,6 +31,7 @@ export type ControlPermissionRule = {
24
31
  isHost: boolean;
25
32
  role: ClientRoleType;
26
33
  preference: joinRoomPreference;
34
+ isInBreakoutRoom: boolean;
27
35
  };
28
36
 
29
37
  export const controlPermissionMatrix: Record<
@@ -36,12 +44,30 @@ export const controlPermissionMatrix: Record<
36
44
  settingsControl: ({preference}) => !preference.disableSettings,
37
45
  screenshareControl: ({preference}) =>
38
46
  $config.SCREEN_SHARING && !preference.disableScreenShare,
39
- viewAllTextTracks: ({isHost}) =>
47
+
48
+ viewAllTextTracksControl: ({isHost, isInBreakoutRoom}) =>
40
49
  isHost &&
41
50
  $config.ENABLE_STT &&
42
51
  $config.ENABLE_MEETING_TRANSCRIPT &&
43
52
  $config.ENABLE_TEXT_TRACKS &&
44
- isWeb(),
53
+ isWeb() &&
54
+ !isInBreakoutRoom,
55
+ whiteboardControl: ({isHost, isInBreakoutRoom}) =>
56
+ isHost && $config.ENABLE_WHITEBOARD && isWebInternal() && !isInBreakoutRoom,
57
+ recordingControl: ({isHost, isInBreakoutRoom}) =>
58
+ isHost && $config.CLOUD_RECORDING && !isInBreakoutRoom,
59
+ captionsControl: ({isInBreakoutRoom}) =>
60
+ $config.ENABLE_STT && $config.ENABLE_CAPTION && !isInBreakoutRoom,
61
+ transcriptsControl: ({isInBreakoutRoom}) =>
62
+ $config.ENABLE_MEETING_TRANSCRIPT && !isInBreakoutRoom,
63
+ breakoutRoomControl: () =>
64
+ isWeb() &&
65
+ $config.ENABLE_BREAKOUT_ROOM &&
66
+ ENABLE_AUTH &&
67
+ !$config.ENABLE_CONVERSATIONAL_AI &&
68
+ !$config.EVENT_MODE &&
69
+ !$config.RAISE_HAND &&
70
+ !$config.ENABLE_WAITING_ROOM,
45
71
  };
46
72
 
47
73
  export const useControlPermissionMatrix = (
@@ -49,12 +75,14 @@ export const useControlPermissionMatrix = (
49
75
  ): boolean => {
50
76
  const {data: roomData, roomPreference} = useRoomInfo();
51
77
  const {rtcProps} = useContext(PropsContext);
78
+ const {breakoutRoomChannelData} = useBreakoutRoomInfo();
52
79
 
53
80
  // Build the permission rule context for the current user.
54
81
  const rule: ControlPermissionRule = {
55
82
  isHost: roomData?.isHost || false,
56
83
  role: rtcProps.role,
57
84
  preference: {...roomPreference},
85
+ isInBreakoutRoom: breakoutRoomChannelData?.isBreakoutMode || false,
58
86
  };
59
87
  // Retrieve the permission function for the given key and evaluate it.
60
88
  const permissionFn = controlPermissionMatrix[key];
@@ -73,12 +73,14 @@ export default function AllHostParticipants(props: any) {
73
73
  isAudienceUser={false}
74
74
  name={getParticipantName(localUid)}
75
75
  user={defaultContent[localUid]}
76
- showControls={true}
76
+ showControls={props?.hideControls ? false : true}
77
77
  isHostUser={hostUids.indexOf(localUid) !== -1}
78
78
  key={localUid}
79
79
  isMobile={isMobile}
80
80
  handleClose={handleClose}
81
81
  updateActionSheet={updateActionSheet}
82
+ showBreakoutRoomMenu={props?.showBreakoutRoomMenu}
83
+ from={props?.from}
82
84
  />
83
85
  {renderScreenShare(defaultContent[localUid])}
84
86
  </>
@@ -104,12 +106,18 @@ export default function AllHostParticipants(props: any) {
104
106
  isAudienceUser={false}
105
107
  name={getParticipantName(uid)}
106
108
  user={defaultContent[uid]}
107
- showControls={defaultContent[uid]?.type === 'rtc' && isHost}
109
+ showControls={
110
+ defaultContent[uid]?.type === 'rtc' &&
111
+ isHost &&
112
+ (props?.hideControls ? false : true)
113
+ }
108
114
  isHostUser={hostUids.indexOf(uid) !== -1}
109
115
  key={uid}
110
116
  isMobile={isMobile}
111
117
  handleClose={handleClose}
112
118
  updateActionSheet={updateActionSheet}
119
+ showBreakoutRoomMenu={props?.showBreakoutRoomMenu}
120
+ from={props?.from}
113
121
  />
114
122
  {renderScreenShare(defaultContent[uid])}
115
123
  </>
@@ -66,6 +66,12 @@ interface ParticipantInterface {
66
66
  updateActionSheet: (screenName: 'chat' | 'participants' | 'settings') => {};
67
67
  uid?: UidType;
68
68
  screenUid?: UidType;
69
+ showBreakoutRoomMenu?: boolean;
70
+ from?:
71
+ | 'breakout-room'
72
+ | 'partcipant'
73
+ | 'screenshare-participant'
74
+ | 'video-tile';
69
75
  }
70
76
 
71
77
  const Participant = (props: ParticipantInterface) => {
@@ -106,7 +112,7 @@ const Participant = (props: ParticipantInterface) => {
106
112
  setActionMenuVisible={setActionMenuVisible}
107
113
  user={props.user}
108
114
  btnRef={moreIconRef}
109
- from={'partcipant'}
115
+ from={props?.from || 'partcipant'}
110
116
  spotlightUid={spotlightUid}
111
117
  setSpotlightUid={setSpotlightUid}
112
118
  />
@@ -77,13 +77,21 @@ import {
77
77
  DEFAULT_ACTION_KEYS,
78
78
  UserActionMenuItemsConfig,
79
79
  } from '../../atoms/UserActionMenuPreset';
80
+ import {
81
+ MemberDropdownOption,
82
+ useBreakoutRoom,
83
+ } from '../breakout-room/context/BreakoutRoomContext';
80
84
 
81
85
  interface UserActionMenuOptionsOptionsProps {
82
86
  user: ContentInterface;
83
87
  actionMenuVisible: boolean;
84
88
  setActionMenuVisible: (actionMenuVisible: boolean) => void;
85
89
  btnRef: any;
86
- from: 'partcipant' | 'screenshare-participant' | 'video-tile';
90
+ from:
91
+ | 'partcipant'
92
+ | 'screenshare-participant'
93
+ | 'video-tile'
94
+ | 'breakout-room';
87
95
  spotlightUid?: UidType;
88
96
  setSpotlightUid?: (uid: UidType) => void;
89
97
  items?: UserActionMenuItemsConfig;
@@ -102,7 +110,8 @@ export default function UserActionMenuOptionsOptions(
102
110
  useState(false);
103
111
  const [actionMenuitems, setActionMenuitems] = useState<ActionMenuItem[]>([]);
104
112
  const {setSidePanel} = useSidePanel();
105
- const {user, actionMenuVisible, setActionMenuVisible, spotlightUid} = props;
113
+ const {user, actionMenuVisible, setActionMenuVisible, spotlightUid, from} =
114
+ props;
106
115
  const {currentLayout} = useLayout();
107
116
  const {pinnedUid, activeUids, customContent, secondaryPinnedUid} =
108
117
  useContent();
@@ -729,6 +738,7 @@ export default function UserActionMenuOptionsOptions(
729
738
  secondaryPinnedUid,
730
739
  currentLayout,
731
740
  spotlightUid,
741
+ from,
732
742
  ]);
733
743
 
734
744
  const {width: globalWidth, height: globalHeight} = useWindowDimensions();
@@ -39,6 +39,7 @@ import {
39
39
  waitingRoomHostNotJoined,
40
40
  waitingRoomUsersInCall,
41
41
  } from '../../language/default-labels/videoCallScreenLabels';
42
+ import ChatContext from '../ChatContext';
42
43
 
43
44
  export interface PreCallJoinWaitingRoomBtnProps {
44
45
  render?: (
@@ -58,6 +59,7 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
58
59
  const waitingRoomUsersInCallText = useString(waitingRoomUsersInCall);
59
60
  let pollingTimeout = React.useRef(null);
60
61
  const {rtcProps} = useContext(PropsContext);
62
+ const {syncUserState} = useContext(ChatContext);
61
63
  const {setCallActive, callActive} = usePreCall();
62
64
  const username = useGetName();
63
65
  const {isJoinDataFetched, isInWaitingRoom} = useRoomInfo();
@@ -139,10 +141,11 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
139
141
  if (callActive) return;
140
142
  // on approve/reject response from host, waiting room permission is reset
141
143
  // update waitinng room status on uid
142
- dispatch({
143
- type: 'UpdateRenderList',
144
- value: [localUid, {isInWaitingRoom: false}],
145
- });
144
+ // dispatch({
145
+ // type: 'UpdateRenderList',
146
+ // value: [localUid, {isInWaitingRoom: false}],
147
+ // });
148
+ syncUserState(localUid, {isInWaitingRoom: false});
146
149
 
147
150
  if (approved) {
148
151
  setRoomInfo(prev => {
@@ -219,10 +222,11 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
219
222
  });
220
223
 
221
224
  // add the waitingRoomStatus to the uid
222
- dispatch({
223
- type: 'UpdateRenderList',
224
- value: [localUid, {isInWaitingRoom: true}],
225
- });
225
+ // dispatch({
226
+ // type: 'UpdateRenderList',
227
+ // value: [localUid, {isInWaitingRoom: true}],
228
+ // });
229
+ syncUserState(localUid, {isInWaitingRoom: true});
226
230
 
227
231
  // join request API to server, server will send RTM message to all hosts regarding request from this user,
228
232
  requestServerToJoinRoom();
@@ -45,6 +45,7 @@ import {
45
45
  waitingRoomHostNotJoined,
46
46
  waitingRoomUsersInCall,
47
47
  } from '../../language/default-labels/videoCallScreenLabels';
48
+ import ChatContext from '../ChatContext';
48
49
 
49
50
  const audio = new Audio(
50
51
  'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3',
@@ -84,7 +85,7 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
84
85
 
85
86
  const localUid = useLocalUid();
86
87
  const {dispatch} = useContext(DispatchContext);
87
-
88
+ const {syncUserState} = useContext(ChatContext);
88
89
  const [buttonText, setButtonText] = React.useState(
89
90
  waitingRoomButton({
90
91
  ready: isInWaitingRoom,
@@ -144,10 +145,11 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
144
145
  if (callActive) return;
145
146
  // on approve/reject response from host, waiting room permission is reset
146
147
  // update waitinng room status on uid
147
- dispatch({
148
- type: 'UpdateRenderList',
149
- value: [localUid, {isInWaitingRoom: false}],
150
- });
148
+ // dispatch({
149
+ // type: 'UpdateRenderList',
150
+ // value: [localUid, {isInWaitingRoom: false}],
151
+ // });
152
+ syncUserState(localUid, {isInWaitingRoom: false});
151
153
 
152
154
  if (approved) {
153
155
  setRoomInfo(prev => {
@@ -241,10 +243,12 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
241
243
  //setCallActive(true);
242
244
 
243
245
  // add the waitingRoomStatus to the uid
244
- dispatch({
245
- type: 'UpdateRenderList',
246
- value: [localUid, {isInWaitingRoom: true}],
247
- });
246
+ // dispatch({
247
+ // type: 'UpdateRenderList',
248
+ // value: [localUid, {isInWaitingRoom: true}],
249
+ // });
250
+ syncUserState(localUid, {isInWaitingRoom: true});
251
+
248
252
  // Enter waiting rooom;
249
253
  setRoomInfo(prev => {
250
254
  return {...prev, isInWaitingRoom: true};
@@ -281,7 +285,7 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => {
281
285
  const title = buttonText;
282
286
  const onPress = () => onSubmit();
283
287
  const disabled = $config.ENABLE_WAITING_ROOM_AUTO_REQUEST
284
- ? !hasHostJoined || isInWaitingRoom || username?.trim() === ''
288
+ ? !hasHostJoined || isInWaitingRoom || username?.trim() === ''
285
289
  : isInWaitingRoom || username?.trim() === '';
286
290
  return props?.render ? (
287
291
  props.render(onPress, title, disabled)
@@ -0,0 +1,50 @@
1
+ /*
2
+ ********************************************
3
+ Copyright © 2021 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
+ */
12
+
13
+ import React from 'react';
14
+ import {useRaiseHand} from './RaiseHandProvider';
15
+ import {StyleSheet} from 'react-native';
16
+ import ThemeConfig from '../../theme';
17
+ import TertiaryButton from '../../atoms/TertiaryButton';
18
+
19
+ const RaiseHandButton: React.FC = () => {
20
+ const {isHandRaised, toggleHand} = useRaiseHand();
21
+
22
+ return (
23
+ <TertiaryButton
24
+ containerStyle={style.raiseHandBtn}
25
+ textStyle={style.raiseHandBtnText}
26
+ text={isHandRaised ? 'Lower Hand' : 'Raise Hand'}
27
+ iconName={isHandRaised ? 'lower-hand' : 'raise-hand'}
28
+ iconColor={$config.SEMANTIC_WARNING}
29
+ iconSize={15}
30
+ onPress={toggleHand}
31
+ />
32
+ );
33
+ };
34
+
35
+ export default RaiseHandButton;
36
+
37
+ const style = StyleSheet.create({
38
+ raiseHandBtn: {
39
+ width: '100%',
40
+ borderRadius: 4,
41
+ borderColor: $config.SECONDARY_ACTION_COLOR,
42
+ backgroundColor: 'transparent',
43
+ },
44
+ raiseHandBtnText: {
45
+ textAlign: 'center',
46
+ color: $config.SECONDARY_ACTION_COLOR,
47
+ fontSize: ThemeConfig.FontSize.small,
48
+ lineHeight: 16,
49
+ },
50
+ });