@100mslive/roomkit-react 0.1.5 → 0.1.6-alpha.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 (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
+ };