@100mslive/roomkit-react 0.1.5 → 0.1.6-alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. package/dist/{HLSView-P57IRMAR.js → HLSView-HNVYG5VE.js} +309 -151
  2. package/dist/HLSView-HNVYG5VE.js.map +7 -0
  3. package/dist/Prebuilt/App.d.ts +3 -0
  4. package/dist/Prebuilt/AppContext.d.ts +13 -0
  5. package/dist/Prebuilt/common/PeersSorter.d.ts +21 -0
  6. package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +7 -0
  7. package/dist/Prebuilt/components/Connection/ConnectionIndicator.d.ts +6 -0
  8. package/dist/Prebuilt/components/Connection/TileConnection.d.ts +10 -0
  9. package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +4 -0
  10. package/dist/Prebuilt/components/Footer/Footer.d.ts +6 -0
  11. package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +14 -0
  12. package/dist/Prebuilt/components/Footer/RoleOptions.d.ts +6 -0
  13. package/dist/Prebuilt/components/Header/Header.d.ts +2 -0
  14. package/dist/Prebuilt/components/Header/StreamActions.d.ts +11 -0
  15. package/dist/Prebuilt/components/InsetTile.d.ts +2 -0
  16. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +8 -0
  17. package/dist/Prebuilt/components/Leave/EndSessionContent.d.ts +9 -0
  18. package/dist/Prebuilt/components/Leave/LeaveAtoms.d.ts +2196 -0
  19. package/dist/Prebuilt/components/Leave/LeaveCard.d.ts +11 -0
  20. package/dist/Prebuilt/components/Leave/LeaveRoom.d.ts +5 -0
  21. package/dist/Prebuilt/components/Leave/LeaveSessionContent.d.ts +8 -0
  22. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +8 -0
  23. package/dist/Prebuilt/components/MoreSettings/MoreSettings.d.ts +6 -0
  24. package/dist/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.d.ts +6 -0
  25. package/dist/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.d.ts +6 -0
  26. package/dist/Prebuilt/components/Pagination.d.ts +6 -0
  27. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +3 -0
  28. package/dist/Prebuilt/components/Preview/PreviewForm.d.ts +10 -0
  29. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +16 -0
  30. package/dist/Prebuilt/components/RoleChangeRequestModal.d.ts +2 -0
  31. package/dist/Prebuilt/components/SecondaryTiles.d.ts +3 -0
  32. package/dist/Prebuilt/components/VideoLayouts/EqualProminence.d.ts +3 -0
  33. package/dist/Prebuilt/components/VideoLayouts/Grid.d.ts +6 -0
  34. package/dist/Prebuilt/components/VideoLayouts/GridLayout.d.ts +12 -0
  35. package/dist/Prebuilt/components/VideoLayouts/ProminenceLayout.d.ts +15 -0
  36. package/dist/Prebuilt/components/VideoLayouts/RoleProminence.d.ts +3 -0
  37. package/dist/Prebuilt/components/VideoLayouts/ScreenshareLayout.d.ts +3 -0
  38. package/dist/Prebuilt/components/VideoLayouts/interface.d.ts +9 -0
  39. package/dist/Prebuilt/components/hooks/useAutoStartStreaming.d.ts +1 -0
  40. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +3 -0
  41. package/dist/Prebuilt/components/hooks/useRoleProminencePeers.d.ts +5 -0
  42. package/dist/Prebuilt/components/hooks/useTileLayout.d.ts +13 -0
  43. package/dist/Prebuilt/components/hooks/useVideoTileLayout.d.ts +13 -0
  44. package/dist/Prebuilt/layouts/SidePane.d.ts +9 -0
  45. package/dist/Prebuilt/layouts/VideoStreamingSection.d.ts +7 -0
  46. package/dist/Prebuilt/plugins/whiteboard/ToggleWhiteboard.d.ts +5 -0
  47. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.d.ts +1 -0
  48. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useInsetEnabled.d.ts +1 -0
  49. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.d.ts +17 -0
  50. package/dist/Prebuilt/provider/roomLayoutProvider/index.d.ts +6 -1
  51. package/dist/{VirtualBackground-GGCQJ5JM.js → VirtualBackground-UM2FOUHQ.js} +5 -11
  52. package/dist/VirtualBackground-UM2FOUHQ.js.map +7 -0
  53. package/dist/{chunk-P5X32KOD.js → chunk-364HP22I.js} +8 -5
  54. package/dist/chunk-364HP22I.js.map +7 -0
  55. package/dist/{chunk-OSM4QEQG.js → chunk-LYSAET4G.js} +3742 -5462
  56. package/dist/chunk-LYSAET4G.js.map +7 -0
  57. package/dist/chunk-POE7H4IE.js +898 -0
  58. package/dist/chunk-POE7H4IE.js.map +7 -0
  59. package/dist/conference-UWLJHMB2.js +5727 -0
  60. package/dist/conference-UWLJHMB2.js.map +7 -0
  61. package/dist/index.cjs.js +9655 -15326
  62. package/dist/index.cjs.js.map +4 -4
  63. package/dist/index.js +2 -2
  64. package/dist/meta.cjs.json +2513 -3456
  65. package/dist/meta.esbuild.json +2807 -3838
  66. package/package.json +8 -7
  67. package/src/Button/Button.tsx +2 -2
  68. package/src/Prebuilt/App.tsx +58 -53
  69. package/src/Prebuilt/{AppContext.jsx → AppContext.tsx} +11 -3
  70. package/src/Prebuilt/IconButton.jsx +11 -0
  71. package/src/Prebuilt/Prebuilt.stories.tsx +1 -0
  72. package/src/Prebuilt/common/{PeersSorter.js → PeersSorter.ts} +16 -11
  73. package/src/Prebuilt/common/constants.js +4 -114
  74. package/src/Prebuilt/common/hooks.js +34 -1
  75. package/src/Prebuilt/common/utils.js +1 -9
  76. package/src/Prebuilt/components/AppData/AppData.jsx +11 -15
  77. package/src/Prebuilt/components/AppData/useUISettings.js +6 -10
  78. package/src/Prebuilt/components/AudioVideoToggle.jsx +10 -2
  79. package/src/Prebuilt/components/AuthToken.jsx +11 -42
  80. package/src/Prebuilt/components/Chat/Chat.jsx +75 -27
  81. package/src/Prebuilt/components/Chat/ChatBody.jsx +95 -36
  82. package/src/Prebuilt/components/Chat/ChatFooter.tsx +199 -0
  83. package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +84 -0
  84. package/src/Prebuilt/components/Chat/ChatSelector.jsx +16 -17
  85. package/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx +81 -0
  86. package/src/Prebuilt/components/Chat/useEmojiPickerStyles.js +5 -4
  87. package/src/Prebuilt/components/Connection/{ConnectionIndicator.jsx → ConnectionIndicator.tsx} +12 -4
  88. package/src/Prebuilt/components/Connection/TileConnection.tsx +71 -0
  89. package/src/Prebuilt/components/EmojiReaction.jsx +19 -22
  90. package/src/Prebuilt/components/Footer/{ChatToggle.jsx → ChatToggle.tsx} +13 -9
  91. package/src/Prebuilt/components/Footer/Footer.tsx +98 -0
  92. package/src/Prebuilt/components/Footer/ParticipantList.jsx +187 -179
  93. package/src/Prebuilt/components/Footer/RoleAccordion.tsx +94 -0
  94. package/src/Prebuilt/components/Footer/RoleOptions.tsx +155 -0
  95. package/src/Prebuilt/components/FullPageProgress.jsx +3 -3
  96. package/src/Prebuilt/components/HMSVideo/Controls.jsx +3 -2
  97. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +63 -18
  98. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +2 -2
  99. package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +1 -1
  100. package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +5 -6
  101. package/src/Prebuilt/components/HMSVideo/VideoTime.jsx +3 -3
  102. package/src/Prebuilt/components/HMSVideo/VolumeControl.jsx +38 -9
  103. package/src/Prebuilt/components/Header/{ConferencingHeader.jsx → Header.tsx} +9 -7
  104. package/src/Prebuilt/components/Header/HeaderComponents.jsx +13 -4
  105. package/src/Prebuilt/components/Header/{StreamActions.jsx → StreamActions.tsx} +54 -67
  106. package/src/Prebuilt/components/Header/common.jsx +5 -2
  107. package/src/Prebuilt/components/Header/index.tsx +1 -0
  108. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +23 -4
  109. package/src/Prebuilt/components/InsetTile.tsx +128 -0
  110. package/src/Prebuilt/components/{MoreSettings/SplitComponents/DesktopLeaveRoom.jsx → Leave/DesktopLeaveRoom.tsx} +67 -25
  111. package/src/Prebuilt/components/{EndSessionContent.jsx → Leave/EndSessionContent.tsx} +18 -11
  112. package/src/Prebuilt/components/Leave/LeaveAtoms.tsx +26 -0
  113. package/src/Prebuilt/components/Leave/LeaveCard.tsx +36 -0
  114. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +66 -0
  115. package/src/Prebuilt/components/{LeaveSessionContent.jsx → Leave/LeaveSessionContent.tsx} +20 -6
  116. package/src/Prebuilt/components/{MoreSettings/SplitComponents/MwebLeaveRoom.jsx → Leave/MwebLeaveRoom.tsx} +43 -18
  117. package/src/Prebuilt/components/MetaActions.jsx +15 -23
  118. package/src/Prebuilt/components/MoreSettings/ActionTile.jsx +5 -0
  119. package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +16 -7
  120. package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +1 -1
  121. package/src/Prebuilt/components/MoreSettings/FullScreenItem.jsx +1 -4
  122. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +27 -0
  123. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +216 -0
  124. package/src/Prebuilt/components/MoreSettings/SplitComponents/{MwebOptions.jsx → MwebOptions.tsx} +107 -45
  125. package/src/Prebuilt/components/Notifications/HLSFailureModal.jsx +3 -1
  126. package/src/Prebuilt/components/Notifications/Notifications.jsx +46 -30
  127. package/src/Prebuilt/components/Notifications/PeerNotifications.jsx +14 -2
  128. package/src/Prebuilt/components/Notifications/PermissionErrorModal.jsx +10 -4
  129. package/src/Prebuilt/components/Notifications/ReconnectNotifications.jsx +5 -11
  130. package/src/Prebuilt/components/PIP/PIPComponent.jsx +7 -16
  131. package/src/Prebuilt/components/PIP/PIPManager.js +1 -0
  132. package/src/Prebuilt/components/Pagination.tsx +60 -0
  133. package/src/Prebuilt/components/Playlist/Playlist.jsx +1 -6
  134. package/src/Prebuilt/components/PostLeave.jsx +7 -7
  135. package/src/Prebuilt/components/Preview/{PreviewContainer.jsx → PreviewContainer.tsx} +16 -15
  136. package/src/Prebuilt/components/Preview/{PreviewForm.jsx → PreviewForm.tsx} +16 -8
  137. package/src/Prebuilt/components/Preview/{PreviewJoin.jsx → PreviewJoin.tsx} +48 -22
  138. package/src/Prebuilt/components/RaiseHand.jsx +0 -7
  139. package/src/Prebuilt/components/RoleChangeRequestModal.tsx +119 -0
  140. package/src/Prebuilt/components/ScreenshareDisplay.jsx +4 -10
  141. package/src/Prebuilt/components/ScreenshareTile.jsx +43 -36
  142. package/src/Prebuilt/components/SecondaryTiles.tsx +36 -0
  143. package/src/Prebuilt/components/Settings/LayoutSettings.jsx +2 -12
  144. package/src/Prebuilt/components/Settings/NotificationSettings.jsx +3 -9
  145. package/src/Prebuilt/components/Settings/SettingsModal.jsx +3 -9
  146. package/src/Prebuilt/components/StatsForNerds.jsx +3 -1
  147. package/src/Prebuilt/components/TileMenu/TileMenu.jsx +16 -17
  148. package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +33 -27
  149. package/src/Prebuilt/components/Toast/ToastConfig.jsx +58 -15
  150. package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +65 -0
  151. package/src/Prebuilt/components/VideoLayouts/Grid.tsx +43 -0
  152. package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +110 -0
  153. package/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx +74 -0
  154. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +59 -0
  155. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +52 -0
  156. package/src/Prebuilt/components/VideoLayouts/interface.ts +10 -0
  157. package/src/Prebuilt/components/VideoTile.jsx +116 -74
  158. package/src/Prebuilt/components/conference.jsx +86 -85
  159. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +57 -0
  160. package/src/Prebuilt/components/hooks/useMetadata.jsx +19 -3
  161. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +34 -0
  162. package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +38 -0
  163. package/src/Prebuilt/components/hooks/useTileLayout.tsx +127 -0
  164. package/src/Prebuilt/components/hooks/useVideoTileLayout.ts +26 -0
  165. package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +5 -72
  166. package/src/Prebuilt/components/pdfAnnotator/submitPdf.jsx +4 -45
  167. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +2 -17
  168. package/src/Prebuilt/components/peerTileUtils.jsx +1 -1
  169. package/src/Prebuilt/images/empty-chat.svg +12 -0
  170. package/src/Prebuilt/layouts/EmbedView.jsx +17 -50
  171. package/src/Prebuilt/layouts/HLSView.jsx +138 -51
  172. package/src/Prebuilt/layouts/PDFView.jsx +1 -11
  173. package/src/Prebuilt/layouts/SidePane.tsx +108 -0
  174. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +96 -0
  175. package/src/Prebuilt/layouts/WhiteboardView.jsx +10 -34
  176. package/src/Prebuilt/plugins/FlyingEmoji.jsx +14 -2
  177. package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +1 -4
  178. package/src/Prebuilt/plugins/whiteboard/{ToggleWhiteboard.jsx → ToggleWhiteboard.tsx} +5 -9
  179. package/src/Prebuilt/primitives/DialogContent.jsx +15 -11
  180. package/src/Prebuilt/provider/roomLayoutProvider/constants/index.ts +17 -2
  181. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.ts +36 -13
  182. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useInsetEnabled.ts +10 -0
  183. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.ts +65 -0
  184. package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +17 -6
  185. package/src/Prebuilt/services/FeatureFlags.jsx +0 -1
  186. package/src/VideoTile/StyledVideoTile.tsx +1 -0
  187. package/dist/HLSView-P57IRMAR.js.map +0 -7
  188. package/dist/PinnedTrackView-4FYJEBTB.js +0 -102
  189. package/dist/PinnedTrackView-4FYJEBTB.js.map +0 -7
  190. package/dist/VirtualBackground-GGCQJ5JM.js.map +0 -7
  191. package/dist/chunk-IVTWKQI3.js +0 -827
  192. package/dist/chunk-IVTWKQI3.js.map +0 -7
  193. package/dist/chunk-OSM4QEQG.js.map +0 -7
  194. package/dist/chunk-P5X32KOD.js.map +0 -7
  195. package/dist/chunk-RVCZPPTL.js +0 -1100
  196. package/dist/chunk-RVCZPPTL.js.map +0 -7
  197. package/dist/conference-P6I6ESVF.js +0 -8995
  198. package/dist/conference-P6I6ESVF.js.map +0 -7
  199. package/src/Prebuilt/components/AudioLevel/BeamSpeakerLabelsLogging.jsx +0 -16
  200. package/src/Prebuilt/components/Chat/ChatFooter.jsx +0 -150
  201. package/src/Prebuilt/components/Chat/ChatHeader.jsx +0 -67
  202. package/src/Prebuilt/components/Connection/TileConnection.jsx +0 -39
  203. package/src/Prebuilt/components/EqualProminence.jsx +0 -180
  204. package/src/Prebuilt/components/FirstPersonDisplay.jsx +0 -50
  205. package/src/Prebuilt/components/Footer/Footer.jsx +0 -73
  206. package/src/Prebuilt/components/Header/Header.jsx +0 -8
  207. package/src/Prebuilt/components/Header/StreamingHeader.jsx +0 -54
  208. package/src/Prebuilt/components/LeaveCard.jsx +0 -19
  209. package/src/Prebuilt/components/LeaveRoom.jsx +0 -94
  210. package/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +0 -10
  211. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx +0 -219
  212. package/src/Prebuilt/components/Notifications/MessageNotifications.jsx +0 -25
  213. package/src/Prebuilt/components/Pagination.jsx +0 -29
  214. package/src/Prebuilt/components/RoleChangeRequestModal.jsx +0 -26
  215. package/src/Prebuilt/components/VideoList.jsx +0 -73
  216. package/src/Prebuilt/components/gridView.jsx +0 -85
  217. package/src/Prebuilt/components/hooks/useFeatures.js +0 -22
  218. package/src/Prebuilt/components/hooks/useNavigation.js +0 -19
  219. package/src/Prebuilt/components/hooks/useSkipPreview.jsx +0 -20
  220. package/src/Prebuilt/components/pdfAnnotator/pdfErrorView.jsx +0 -29
  221. package/src/Prebuilt/images/Logo.svg +0 -8
  222. package/src/Prebuilt/layouts/ActiveSpeakerView.jsx +0 -34
  223. package/src/Prebuilt/layouts/InsetView.jsx +0 -260
  224. package/src/Prebuilt/layouts/PinnedTrackView.jsx +0 -59
  225. package/src/Prebuilt/layouts/SidePane.jsx +0 -52
  226. package/src/Prebuilt/layouts/mainGridView.jsx +0 -98
  227. package/src/Prebuilt/layouts/mainView.jsx +0 -141
  228. package/src/Prebuilt/layouts/screenShareView.jsx +0 -183
  229. /package/{src/Prebuilt/components/Header/index.jsx → dist/Prebuilt/components/Header/index.d.ts} +0 -0
  230. /package/src/Prebuilt/components/{ScreenShare.jsx → ScreenShareToggle.jsx} +0 -0
  231. /package/src/{assets → Prebuilt/images}/android-perm-1.png +0 -0
  232. /package/src/{assets → Prebuilt/images}/ios-perm-0.png +0 -0
@@ -1,46 +1,56 @@
1
1
  import React, { Fragment, useCallback, useEffect, useState } from 'react';
2
- import { useDebounce, useMeasure } from 'react-use';
3
- import { FixedSizeList } from 'react-window';
2
+ import { useDebounce, useMedia } from 'react-use';
4
3
  import {
5
- selectAudioTrackByPeerID,
4
+ selectIsPeerAudioEnabled,
6
5
  selectLocalPeerID,
7
6
  selectPeerCount,
8
7
  selectPeerMetadata,
8
+ selectPeersByCondition,
9
9
  selectPermissions,
10
10
  useHMSActions,
11
11
  useHMSStore,
12
- useParticipants,
13
12
  } from '@100mslive/react-sdk';
14
13
  import {
15
14
  ChangeRoleIcon,
16
- CrossIcon,
17
- HandRaiseIcon,
15
+ HandIcon,
16
+ MicOffIcon,
18
17
  PeopleIcon,
19
- RemoveUserIcon,
18
+ PeopleRemoveIcon,
20
19
  SearchIcon,
21
- SpeakerIcon,
22
20
  VerticalMenuIcon,
23
21
  } from '@100mslive/react-icons';
24
- import { Avatar, Box, Dropdown, Flex, Input, Slider, Text, textEllipsis } from '../../..';
22
+ import { Box, config as cssConfig, Dropdown, Flex, Input, Text, textEllipsis } from '../../..';
25
23
  import IconButton from '../../IconButton';
24
+ import { ChatParticipantHeader } from '../Chat/ChatParticipantHeader';
26
25
  import { ConnectionIndicator } from '../Connection/ConnectionIndicator';
27
- import { ParticipantFilter } from '../Header/ParticipantFilter';
28
- import { RoleChangeModal } from '../RoleChangeModal';
26
+ import { ToastManager } from '../Toast/ToastManager';
27
+ import { RoleAccordion } from './RoleAccordion';
28
+ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
29
29
  import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
30
+ import { useParticipants } from '../../common/hooks';
30
31
  import { isInternalRole } from '../../common/utils';
31
32
  import { SIDE_PANE_OPTIONS } from '../../common/constants';
32
33
 
33
34
  export const ParticipantList = () => {
34
35
  const [filter, setFilter] = useState();
35
- const { participants, isConnected, peerCount, rolesWithParticipants } = useParticipants(filter);
36
- const [selectedPeerId, setSelectedPeerId] = useState(null);
37
- const toggleSidepane = useSidepaneToggle(SIDE_PANE_OPTIONS.PARTICIPANTS);
36
+ const { participants, isConnected, peerCount } = useParticipants(filter);
37
+ const peersOrderedByRoles = {};
38
+
39
+ const handRaisedPeers = useHMSStore(selectPeersByCondition(peer => JSON.parse(peer.metadata || '{}')?.isHandRaised));
40
+
41
+ participants.forEach(participant => {
42
+ if (peersOrderedByRoles[participant.roleName] === undefined) {
43
+ peersOrderedByRoles[participant.roleName] = [];
44
+ }
45
+ peersOrderedByRoles[participant.roleName].push(participant);
46
+ });
47
+
38
48
  const onSearch = useCallback(value => {
39
49
  setFilter(filterValue => {
40
50
  if (!filterValue) {
41
51
  filterValue = {};
42
52
  }
43
- filterValue.search = value;
53
+ filterValue.search = value.toLowerCase();
44
54
  return { ...filterValue };
45
55
  });
46
56
  }, []);
@@ -50,39 +60,21 @@ export const ParticipantList = () => {
50
60
 
51
61
  return (
52
62
  <Fragment>
53
- <Flex direction="column" css={{ size: '100%' }}>
54
- <Flex align="center" css={{ w: '100%', mb: '$10' }}>
55
- <Text css={{ fontWeight: '$semiBold', mr: '$4' }}>Participants</Text>
56
- <ParticipantFilter
57
- selection={filter}
58
- onSelection={setFilter}
59
- isConnected={isConnected}
60
- roles={rolesWithParticipants}
61
- />
62
- <IconButton onClick={toggleSidepane} css={{ w: '$11', h: '$11', ml: 'auto' }}>
63
- <CrossIcon />
64
- </IconButton>
65
- </Flex>
66
- {!filter?.search && participants.length === 0 ? null : <ParticipantSearch onSearch={onSearch} />}
67
- {participants.length === 0 && (
63
+ <Flex direction="column" css={{ size: '100%', gap: '$4' }}>
64
+ <ChatParticipantHeader activeTabValue={SIDE_PANE_OPTIONS.PARTICIPANTS} />
65
+ {!filter?.search && participants.length === 0 ? null : <ParticipantSearch onSearch={onSearch} inSidePane />}
66
+ {participants.length === 0 ? (
68
67
  <Flex align="center" justify="center" css={{ w: '100%', p: '$8 0' }}>
69
68
  <Text variant="sm">{!filter ? 'No participants' : 'No matching participants'}</Text>
70
69
  </Flex>
71
- )}
70
+ ) : null}
72
71
  <VirtualizedParticipants
73
- participants={participants}
72
+ peersOrderedByRoles={peersOrderedByRoles}
73
+ handRaisedList={handRaisedPeers}
74
74
  isConnected={isConnected}
75
- setSelectedPeerId={setSelectedPeerId}
75
+ filter={filter}
76
76
  />
77
77
  </Flex>
78
- {selectedPeerId && (
79
- <RoleChangeModal
80
- peerId={selectedPeerId}
81
- onOpenChange={value => {
82
- !value && setSelectedPeerId(null);
83
- }}
84
- />
85
- )}
86
78
  </Fragment>
87
79
  );
88
80
  };
@@ -123,142 +115,186 @@ export const ParticipantCount = () => {
123
115
  );
124
116
  };
125
117
 
126
- function itemKey(index, data) {
127
- return data.participants[index].id;
128
- }
129
-
130
- const VirtualizedParticipants = ({ participants, isConnected, setSelectedPeerId }) => {
131
- const [ref, { width, height }] = useMeasure();
118
+ const VirtualizedParticipants = ({ peersOrderedByRoles = {}, isConnected, filter, handRaisedList = [] }) => {
132
119
  return (
133
- <Box
134
- ref={ref}
120
+ <Flex
121
+ direction="column"
135
122
  css={{
136
- flex: '1 1 0',
137
- mr: '-$10',
123
+ gap: '$8',
124
+ maxHeight: '100%',
125
+ overflowY: 'auto',
126
+ overflowX: 'hidden',
127
+ pr: '$3',
138
128
  }}
139
129
  >
140
- <FixedSizeList
141
- itemSize={68}
142
- itemData={{ participants, isConnected, setSelectedPeerId }}
143
- itemKey={itemKey}
144
- itemCount={participants.length}
145
- width={width}
146
- height={height}
147
- >
148
- {VirtualisedParticipantListItem}
149
- </FixedSizeList>
150
- </Box>
151
- );
152
- };
153
-
154
- const VirtualisedParticipantListItem = React.memo(({ style, index, data }) => {
155
- return (
156
- <div style={style} key={data.participants[index].id}>
157
- <Participant
158
- peer={data.participants[index]}
159
- isConnected={data.isConnected}
160
- setSelectedPeerId={data.setSelectedPeerId}
130
+ <RoleAccordion
131
+ peerList={handRaisedList}
132
+ roleName="Hand Raised"
133
+ filter={filter}
134
+ isConnected={isConnected}
135
+ isHandRaisedAccordion
161
136
  />
162
- </div>
137
+ {Object.keys(peersOrderedByRoles).map(role => (
138
+ <RoleAccordion
139
+ key={role}
140
+ peerList={peersOrderedByRoles[role]}
141
+ roleName={role}
142
+ isConnected={isConnected}
143
+ filter={filter}
144
+ />
145
+ ))}
146
+ </Flex>
163
147
  );
164
- });
148
+ };
165
149
 
166
- const Participant = ({ peer, isConnected, setSelectedPeerId }) => {
150
+ export const Participant = ({ peer, isConnected }) => {
151
+ const localPeerId = useHMSStore(selectLocalPeerID);
167
152
  return (
168
- <Fragment>
169
- <Flex
170
- key={peer.id}
171
- css={{ w: '100%', py: '$4', pr: '$10' }}
172
- align="center"
173
- data-testid={'participant_' + peer.name}
174
- >
175
- <Avatar
176
- name={peer.name}
177
- css={{
178
- position: 'unset',
179
- transform: 'unset',
180
- mr: '$8',
181
- fontSize: '$sm',
182
- size: '$12',
183
- p: '$4',
184
- }}
185
- />
186
- <Flex direction="column" css={{ flex: '1 1 0' }}>
187
- <Text variant="md" css={{ ...textEllipsis(150), fontWeight: '$semiBold' }}>
188
- {peer.name}
189
- </Text>
190
- <Text variant="sub2">{peer.roleName}</Text>
191
- </Flex>
192
- {isConnected && (
193
- <ParticipantActions
194
- peerId={peer.id}
195
- role={peer.roleName}
196
- onSettings={() => {
197
- setSelectedPeerId(peer.id);
198
- }}
199
- />
200
- )}
201
- </Flex>
202
- </Fragment>
153
+ <Flex
154
+ key={peer.id}
155
+ css={{
156
+ w: '100%',
157
+ p: '$4 $8',
158
+ pr: '$6',
159
+ h: '$16',
160
+ '&:hover .participant_item': { display: 'flex' },
161
+ }}
162
+ align="center"
163
+ justify="between"
164
+ data-testid={'participant_' + peer.name}
165
+ >
166
+ <Text variant="sm" css={{ ...textEllipsis(150), fontWeight: '$semiBold', color: '$on_surface_high' }}>
167
+ {peer.name} {localPeerId === peer.id ? '(You)' : ''}
168
+ </Text>
169
+ {isConnected ? (
170
+ <ParticipantActions peerId={peer.id} isLocal={peer.id === localPeerId} role={peer.roleName} />
171
+ ) : null}
172
+ </Flex>
203
173
  );
204
174
  };
205
175
 
206
176
  /**
207
177
  * shows settings to change for a participant like changing their role
208
178
  */
209
- const ParticipantActions = React.memo(({ onSettings, peerId, role }) => {
179
+ const ParticipantActions = React.memo(({ peerId, role, isLocal }) => {
210
180
  const isHandRaised = useHMSStore(selectPeerMetadata(peerId))?.isHandRaised;
211
181
  const canChangeRole = useHMSStore(selectPermissions)?.changeRole;
212
- const audioTrack = useHMSStore(selectAudioTrackByPeerID(peerId));
213
- const localPeerId = useHMSStore(selectLocalPeerID);
214
- const canChangeVolume = peerId !== localPeerId && audioTrack;
215
- const shouldShowMoreActions = canChangeRole || canChangeVolume;
182
+ const shouldShowMoreActions = canChangeRole;
183
+ const isAudioMuted = !useHMSStore(selectIsPeerAudioEnabled(peerId));
216
184
 
217
185
  return (
218
- <Flex align="center" css={{ flexShrink: 0 }}>
186
+ <Flex
187
+ align="center"
188
+ css={{
189
+ flexShrink: 0,
190
+ gap: '$8',
191
+ }}
192
+ >
219
193
  <ConnectionIndicator peerId={peerId} />
220
- {isHandRaised && <HandRaiseIcon />}
221
- {shouldShowMoreActions && !isInternalRole(role) && (
222
- <ParticipantMoreActions onRoleChange={onSettings} peerId={peerId} role={role} />
194
+ {isHandRaised && (
195
+ <Flex
196
+ align="center"
197
+ justify="center"
198
+ css={{ p: '$1', c: '$on_surface_high', bg: '$surface_bright', borderRadius: '$round' }}
199
+ >
200
+ <HandIcon height={19} width={19} />
201
+ </Flex>
223
202
  )}
203
+ {isAudioMuted ? (
204
+ <Flex
205
+ align="center"
206
+ justify="center"
207
+ css={{ p: '$2', c: '$on_surface_high', bg: '$surface_bright', borderRadius: '$round' }}
208
+ >
209
+ <MicOffIcon height={19} width={19} />
210
+ </Flex>
211
+ ) : null}
212
+
213
+ {shouldShowMoreActions && !isInternalRole(role) && !isLocal ? (
214
+ <ParticipantMoreActions peerId={peerId} role={role} />
215
+ ) : null}
224
216
  </Flex>
225
217
  );
226
218
  });
227
219
 
228
- const ParticipantMoreActions = ({ onRoleChange, peerId }) => {
220
+ const ParticipantMoreActions = ({ peerId, role }) => {
221
+ const hmsActions = useHMSActions();
229
222
  const { changeRole: canChangeRole, removeOthers: canRemoveOthers } = useHMSStore(selectPermissions);
223
+ const { elements } = useRoomLayoutConferencingScreen();
224
+ const {
225
+ bring_to_stage_label,
226
+ remove_from_stage_label,
227
+ on_stage_role,
228
+ off_stage_roles = [],
229
+ } = elements.on_stage_exp || {};
230
+ const isInStage = role === on_stage_role;
231
+ const shouldShowStageRoleChange =
232
+ canChangeRole &&
233
+ ((isInStage && remove_from_stage_label) || (off_stage_roles?.includes(role) && bring_to_stage_label));
234
+ const prevRole = useHMSStore(selectPeerMetadata(peerId))?.prevRole;
230
235
  const localPeerId = useHMSStore(selectLocalPeerID);
231
236
  const isLocal = localPeerId === peerId;
232
- const actions = useHMSActions();
233
237
  const [open, setOpen] = useState(false);
238
+
239
+ const handleStageAction = async () => {
240
+ if (isInStage) {
241
+ prevRole && hmsActions.changeRoleOfPeer(peerId, prevRole, true);
242
+ } else {
243
+ await hmsActions.changeRoleOfPeer(peerId, on_stage_role);
244
+ }
245
+ setOpen(false);
246
+ };
247
+
234
248
  return (
235
249
  <Dropdown.Root open={open} onOpenChange={value => setOpen(value)} modal={false}>
236
- <Dropdown.Trigger asChild data-testid="participant_more_actions" css={{ p: '$2', r: '$0' }} tabIndex={0}>
237
- <Text>
250
+ <Dropdown.Trigger
251
+ asChild
252
+ data-testid="participant_more_actions"
253
+ className="participant_item"
254
+ css={{
255
+ p: '$1',
256
+ r: '$0',
257
+ c: '$on_surface_high',
258
+ display: open ? 'flex' : 'none',
259
+ '&:hover': {
260
+ bg: '$surface_bright',
261
+ },
262
+ '@md': {
263
+ display: 'flex',
264
+ },
265
+ }}
266
+ tabIndex={0}
267
+ >
268
+ <Box css={{ my: 'auto' }}>
238
269
  <VerticalMenuIcon />
239
- </Text>
270
+ </Box>
240
271
  </Dropdown.Trigger>
241
272
  <Dropdown.Portal>
242
- <Dropdown.Content align="end" sideOffset={8} css={{ w: '$64' }}>
243
- {canChangeRole && (
244
- <Dropdown.Item onClick={() => onRoleChange(peerId)}>
273
+ <Dropdown.Content align="end" sideOffset={8} css={{ w: '$64', bg: '$surface_default' }}>
274
+ {shouldShowStageRoleChange ? (
275
+ <Dropdown.Item css={{ bg: '$surface_default' }} onClick={() => handleStageAction()}>
245
276
  <ChangeRoleIcon />
246
- <Text css={{ ml: '$4' }}>Change Role</Text>
277
+ <Text variant="sm" css={{ ml: '$4', fontWeight: '$semiBold', c: '$on_surface_high' }}>
278
+ {isInStage ? remove_from_stage_label : bring_to_stage_label}
279
+ </Text>
247
280
  </Dropdown.Item>
248
- )}
249
- <ParticipantVolume peerId={peerId} />
281
+ ) : null}
282
+
250
283
  {!isLocal && canRemoveOthers && (
251
284
  <Dropdown.Item
285
+ css={{ color: '$alert_error_default', bg: '$surface_default' }}
252
286
  onClick={async () => {
253
287
  try {
254
- await actions.removePeer(peerId, '');
288
+ await hmsActions.removePeer(peerId, '');
255
289
  } catch (error) {
256
- // TODO: Toast here
290
+ ToastManager.addToast({ title: error.message, variant: 'error' });
257
291
  }
258
292
  }}
259
293
  >
260
- <RemoveUserIcon />
261
- <Text css={{ ml: '$4', color: '$alert_error_default' }}>Remove Participant</Text>
294
+ <PeopleRemoveIcon />
295
+ <Text variant="sm" css={{ ml: '$4', color: 'inherit', fontWeight: '$semiBold' }}>
296
+ Remove Participant
297
+ </Text>
262
298
  </Dropdown.Item>
263
299
  )}
264
300
  </Dropdown.Content>
@@ -267,37 +303,10 @@ const ParticipantMoreActions = ({ onRoleChange, peerId }) => {
267
303
  );
268
304
  };
269
305
 
270
- const ParticipantVolume = ({ peerId }) => {
271
- const audioTrack = useHMSStore(selectAudioTrackByPeerID(peerId));
272
- const localPeerId = useHMSStore(selectLocalPeerID);
273
- const hmsActions = useHMSActions();
274
- // No volume control for local peer or non audio publishing role
275
- if (peerId === localPeerId || !audioTrack) {
276
- return null;
277
- }
278
-
279
- return (
280
- <Dropdown.Item css={{ h: 'auto' }}>
281
- <Flex direction="column" css={{ w: '100%' }}>
282
- <Flex align="center">
283
- <SpeakerIcon />
284
- <Text css={{ ml: '$4' }}>Volume{audioTrack.volume ? `(${audioTrack.volume})` : ''}</Text>
285
- </Flex>
286
- <Slider
287
- css={{ my: '0.5rem' }}
288
- step={5}
289
- value={[audioTrack.volume]}
290
- onValueChange={e => {
291
- hmsActions.setVolume(e[0], audioTrack?.id);
292
- }}
293
- />
294
- </Flex>
295
- </Dropdown.Item>
296
- );
297
- };
298
-
299
- export const ParticipantSearch = ({ onSearch, placeholder }) => {
306
+ export const ParticipantSearch = ({ onSearch, placeholder, inSidePane = false }) => {
300
307
  const [value, setValue] = React.useState('');
308
+ const isMobile = useMedia(cssConfig.media.md);
309
+
301
310
  useDebounce(
302
311
  () => {
303
312
  onSearch(value);
@@ -306,22 +315,21 @@ export const ParticipantSearch = ({ onSearch, placeholder }) => {
306
315
  [value, onSearch],
307
316
  );
308
317
  return (
309
- <Box css={{ p: '$4 0', my: '$8', position: 'relative' }}>
310
- <Box
311
- css={{
312
- position: 'absolute',
313
- left: '$4',
314
- top: '$2',
315
- transform: 'translateY(50%)',
316
- color: '$on_surface_medium',
317
- }}
318
- >
319
- <SearchIcon />
320
- </Box>
318
+ <Flex
319
+ align="center"
320
+ css={{
321
+ p: isMobile ? '$0 $6' : '$2 0',
322
+ mb: '$2',
323
+ position: 'relative',
324
+ color: '$on_surface_medium',
325
+ mt: inSidePane ? '$4' : '',
326
+ }}
327
+ >
328
+ <SearchIcon style={{ position: 'absolute', left: isMobile ? '1.25rem' : '0.5rem' }} />
321
329
  <Input
322
330
  type="text"
323
- placeholder={placeholder || 'Search among participants'}
324
- css={{ w: '100%', pl: '$14', bg: '$surface_bright' }}
331
+ placeholder={placeholder || 'Search for participants'}
332
+ css={{ w: '100%', p: '$6', pl: '$14', mr: '$4', bg: inSidePane ? '$surface_default' : '$surface_dim' }}
325
333
  value={value}
326
334
  onKeyDown={event => {
327
335
  event.stopPropagation();
@@ -332,6 +340,6 @@ export const ParticipantSearch = ({ onSearch, placeholder }) => {
332
340
  autoComplete="off"
333
341
  aria-autocomplete="none"
334
342
  />
335
- </Box>
343
+ </Flex>
336
344
  );
337
345
  };
@@ -0,0 +1,94 @@
1
+ import React from 'react';
2
+ import { useMeasure } from 'react-use';
3
+ import { FixedSizeList } from 'react-window';
4
+ import { HMSPeer } from '@100mslive/react-sdk';
5
+ import { Accordion } from '../../../Accordion';
6
+ import { Box, Flex } from '../../../Layout';
7
+ import { Text } from '../../../Text';
8
+ // @ts-ignore: No implicit Any
9
+ import { Participant } from './ParticipantList';
10
+ import { RoleOptions } from './RoleOptions';
11
+ // @ts-ignore: No implicit Any
12
+ import { getFormattedCount } from '../../common/utils';
13
+
14
+ const ROW_HEIGHT = 50;
15
+
16
+ interface ItemData {
17
+ peerList: HMSPeer[];
18
+ isConnected: boolean;
19
+ }
20
+
21
+ function itemKey(index: number, data: ItemData) {
22
+ return data.peerList[index].id;
23
+ }
24
+
25
+ const VirtualizedParticipantItem = React.memo(({ index, data }: { index: number; data: ItemData }) => {
26
+ return <Participant key={data.peerList[index].id} peer={data.peerList[index]} isConnected={data.isConnected} />;
27
+ });
28
+
29
+ export const RoleAccordion = ({
30
+ peerList = [],
31
+ roleName,
32
+ isConnected,
33
+ filter,
34
+ isHandRaisedAccordion = false,
35
+ }: ItemData & {
36
+ roleName: string;
37
+ isHandRaisedAccordion?: boolean;
38
+ filter?: { search: string };
39
+ }) => {
40
+ const [ref, { width }] = useMeasure<HTMLDivElement>();
41
+ const showAcordion = filter?.search ? peerList.some(peer => peer.name.toLowerCase().includes(filter.search)) : true;
42
+
43
+ if (!showAcordion || (isHandRaisedAccordion && filter?.search) || peerList.length === 0) {
44
+ return null;
45
+ }
46
+ const height = ROW_HEIGHT * peerList.length;
47
+
48
+ return (
49
+ <Flex direction="column" css={{ flexGrow: 1, '&:hover .role_actions': { visibility: 'visible' } }} ref={ref}>
50
+ <Accordion.Root
51
+ type="single"
52
+ collapsible
53
+ defaultValue={roleName}
54
+ css={{ borderRadius: '$1', border: '1px solid $border_bright' }}
55
+ >
56
+ <Accordion.Item value={roleName}>
57
+ <Accordion.Header
58
+ iconStyles={{ c: '$on_surface_high' }}
59
+ css={{
60
+ textTransform: 'capitalize',
61
+ p: '$6 $8',
62
+ fontSize: '$sm',
63
+ fontWeight: '$semiBold',
64
+ c: '$on_surface_medium',
65
+ }}
66
+ >
67
+ <Flex justify="between" css={{ flexGrow: 1, pr: '$6' }}>
68
+ <Text
69
+ variant="sm"
70
+ css={{ fontWeight: '$semiBold', textTransform: 'capitalize', color: '$on_surface_medium' }}
71
+ >
72
+ {roleName} {`(${getFormattedCount(peerList.length)})`}
73
+ </Text>
74
+ <RoleOptions roleName={roleName} peerList={peerList} />
75
+ </Flex>
76
+ </Accordion.Header>
77
+ <Accordion.Content>
78
+ <Box css={{ borderTop: '1px solid $border_default' }} />
79
+ <FixedSizeList
80
+ itemSize={ROW_HEIGHT}
81
+ itemData={{ peerList, isConnected }}
82
+ itemKey={itemKey}
83
+ itemCount={peerList.length}
84
+ width={width}
85
+ height={height}
86
+ >
87
+ {VirtualizedParticipantItem}
88
+ </FixedSizeList>
89
+ </Accordion.Content>
90
+ </Accordion.Item>
91
+ </Accordion.Root>
92
+ </Flex>
93
+ );
94
+ };