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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. package/dist/{HLSView-PY2FKWX3.js → HLSView-HNVYG5VE.js} +208 -118
  2. package/dist/HLSView-HNVYG5VE.js.map +7 -0
  3. package/dist/Prebuilt/AppContext.d.ts +1 -1
  4. package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +7 -0
  5. package/dist/Prebuilt/components/Connection/ConnectionIndicator.d.ts +6 -0
  6. package/dist/Prebuilt/components/Connection/TileConnection.d.ts +10 -0
  7. package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +4 -0
  8. package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +14 -0
  9. package/dist/Prebuilt/components/Footer/RoleOptions.d.ts +6 -0
  10. package/dist/Prebuilt/components/Header/StreamActions.d.ts +11 -0
  11. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +4 -3
  12. package/dist/Prebuilt/components/Leave/EndSessionContent.d.ts +4 -3
  13. package/dist/Prebuilt/components/Leave/LeaveCard.d.ts +1 -2
  14. package/dist/Prebuilt/components/Leave/LeaveSessionContent.d.ts +3 -1
  15. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +4 -3
  16. package/dist/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.d.ts +6 -0
  17. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +3 -0
  18. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +16 -0
  19. package/dist/Prebuilt/components/RoleChangeRequestModal.d.ts +2 -0
  20. package/dist/Prebuilt/components/SecondaryTiles.d.ts +1 -1
  21. package/dist/Prebuilt/components/VideoLayouts/EqualProminence.d.ts +1 -1
  22. package/dist/Prebuilt/components/VideoLayouts/Grid.d.ts +1 -0
  23. package/dist/Prebuilt/components/VideoLayouts/GridLayout.d.ts +5 -3
  24. package/dist/Prebuilt/components/VideoLayouts/ProminenceLayout.d.ts +6 -3
  25. package/dist/Prebuilt/components/VideoLayouts/RoleProminence.d.ts +1 -1
  26. package/dist/Prebuilt/components/VideoLayouts/ScreenshareLayout.d.ts +1 -1
  27. package/dist/Prebuilt/components/VideoLayouts/interface.d.ts +1 -0
  28. package/dist/Prebuilt/components/hooks/useAutoStartStreaming.d.ts +1 -0
  29. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +3 -0
  30. package/dist/Prebuilt/components/hooks/useTileLayout.d.ts +2 -1
  31. package/dist/Prebuilt/components/hooks/useVideoTileLayout.d.ts +2 -0
  32. package/dist/Prebuilt/layouts/SidePane.d.ts +4 -1
  33. package/dist/Prebuilt/layouts/VideoStreamingSection.d.ts +2 -1
  34. package/dist/{VirtualBackground-AYDHYLIZ.js → VirtualBackground-UM2FOUHQ.js} +3 -3
  35. package/dist/{chunk-E2M2ZSOL.js → chunk-364HP22I.js} +2 -2
  36. package/dist/{chunk-RXTHJUMZ.js → chunk-LYSAET4G.js} +946 -390
  37. package/dist/chunk-LYSAET4G.js.map +7 -0
  38. package/dist/{chunk-GQD2AGWW.js → chunk-POE7H4IE.js} +12 -2
  39. package/dist/{chunk-GQD2AGWW.js.map → chunk-POE7H4IE.js.map} +2 -2
  40. package/dist/{conference-V2XZGTKU.js → conference-UWLJHMB2.js} +1116 -1316
  41. package/dist/conference-UWLJHMB2.js.map +7 -0
  42. package/dist/index.cjs.js +6080 -5631
  43. package/dist/index.cjs.js.map +4 -4
  44. package/dist/index.js +2 -2
  45. package/dist/meta.cjs.json +741 -493
  46. package/dist/meta.esbuild.json +782 -529
  47. package/package.json +8 -7
  48. package/src/Prebuilt/App.tsx +10 -21
  49. package/src/Prebuilt/AppContext.tsx +1 -1
  50. package/src/Prebuilt/IconButton.jsx +10 -0
  51. package/src/Prebuilt/common/PeersSorter.ts +1 -1
  52. package/src/Prebuilt/common/constants.js +1 -2
  53. package/src/Prebuilt/common/utils.js +1 -1
  54. package/src/Prebuilt/components/AppData/AppData.jsx +8 -2
  55. package/src/Prebuilt/components/AppData/useUISettings.js +6 -6
  56. package/src/Prebuilt/components/AudioVideoToggle.jsx +8 -6
  57. package/src/Prebuilt/components/Chat/Chat.jsx +23 -6
  58. package/src/Prebuilt/components/Chat/ChatBody.jsx +20 -21
  59. package/src/Prebuilt/components/Chat/{ChatFooter.jsx → ChatFooter.tsx} +38 -13
  60. package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +38 -27
  61. package/src/Prebuilt/components/Chat/useEmojiPickerStyles.js +5 -4
  62. package/src/Prebuilt/components/Connection/{ConnectionIndicator.jsx → ConnectionIndicator.tsx} +12 -4
  63. package/src/Prebuilt/components/Connection/{TileConnection.jsx → TileConnection.tsx} +20 -6
  64. package/src/Prebuilt/components/EmojiReaction.jsx +2 -6
  65. package/src/Prebuilt/components/Footer/{ChatToggle.jsx → ChatToggle.tsx} +13 -3
  66. package/src/Prebuilt/components/Footer/Footer.tsx +15 -6
  67. package/src/Prebuilt/components/Footer/ParticipantList.jsx +15 -47
  68. package/src/Prebuilt/components/Footer/{RoleAccordion.jsx → RoleAccordion.tsx} +33 -17
  69. package/src/Prebuilt/components/Footer/RoleOptions.tsx +155 -0
  70. package/src/Prebuilt/components/FullPageProgress.jsx +3 -3
  71. package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -0
  72. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +39 -17
  73. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +2 -2
  74. package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +5 -6
  75. package/src/Prebuilt/components/HMSVideo/VolumeControl.jsx +1 -1
  76. package/src/Prebuilt/components/Header/{StreamActions.jsx → StreamActions.tsx} +23 -9
  77. package/src/Prebuilt/components/Header/common.jsx +5 -2
  78. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +6 -1
  79. package/src/Prebuilt/components/InsetTile.tsx +14 -8
  80. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +21 -11
  81. package/src/Prebuilt/components/Leave/EndSessionContent.tsx +2 -5
  82. package/src/Prebuilt/components/Leave/LeaveCard.tsx +1 -3
  83. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +28 -25
  84. package/src/Prebuilt/components/Leave/LeaveSessionContent.tsx +8 -2
  85. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +8 -8
  86. package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +4 -0
  87. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +1 -1
  88. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +9 -23
  89. package/src/Prebuilt/components/MoreSettings/SplitComponents/{MwebOptions.jsx → MwebOptions.tsx} +88 -27
  90. package/src/Prebuilt/components/Notifications/Notifications.jsx +30 -21
  91. package/src/Prebuilt/components/Notifications/ReconnectNotifications.jsx +5 -11
  92. package/src/Prebuilt/components/Pagination.tsx +14 -12
  93. package/src/Prebuilt/components/Preview/{PreviewContainer.jsx → PreviewContainer.tsx} +11 -2
  94. package/src/Prebuilt/components/Preview/PreviewForm.tsx +6 -8
  95. package/src/Prebuilt/components/Preview/{PreviewJoin.jsx → PreviewJoin.tsx} +43 -19
  96. package/src/Prebuilt/components/{RoleChangeRequestModal.jsx → RoleChangeRequestModal.tsx} +32 -15
  97. package/src/Prebuilt/components/ScreenshareTile.jsx +6 -7
  98. package/src/Prebuilt/components/SecondaryTiles.tsx +12 -10
  99. package/src/Prebuilt/components/TileMenu/TileMenu.jsx +1 -1
  100. package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +14 -10
  101. package/src/Prebuilt/components/Toast/ToastConfig.jsx +5 -4
  102. package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +13 -10
  103. package/src/Prebuilt/components/VideoLayouts/Grid.tsx +36 -34
  104. package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +33 -15
  105. package/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx +45 -31
  106. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +12 -9
  107. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +25 -9
  108. package/src/Prebuilt/components/VideoLayouts/interface.ts +1 -0
  109. package/src/Prebuilt/components/VideoTile.jsx +45 -53
  110. package/src/Prebuilt/components/conference.jsx +71 -74
  111. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +57 -0
  112. package/src/Prebuilt/components/hooks/useMetadata.jsx +12 -3
  113. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +34 -0
  114. package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +1 -1
  115. package/src/Prebuilt/components/hooks/useTileLayout.tsx +24 -18
  116. package/src/Prebuilt/components/hooks/useVideoTileLayout.ts +4 -0
  117. package/src/Prebuilt/layouts/EmbedView.jsx +1 -11
  118. package/src/Prebuilt/layouts/HLSView.jsx +152 -82
  119. package/src/Prebuilt/layouts/SidePane.tsx +15 -3
  120. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +11 -47
  121. package/src/Prebuilt/plugins/FlyingEmoji.jsx +14 -2
  122. package/src/Prebuilt/services/FeatureFlags.jsx +0 -1
  123. package/src/VideoTile/StyledVideoTile.tsx +1 -0
  124. package/dist/HLSView-PY2FKWX3.js.map +0 -7
  125. package/dist/chunk-RXTHJUMZ.js.map +0 -7
  126. package/dist/conference-V2XZGTKU.js.map +0 -7
  127. package/src/Prebuilt/components/AudioLevel/BeamSpeakerLabelsLogging.jsx +0 -16
  128. package/src/Prebuilt/components/VideoList.jsx +0 -73
  129. /package/dist/{VirtualBackground-AYDHYLIZ.js.map → VirtualBackground-UM2FOUHQ.js.map} +0 -0
  130. /package/dist/{chunk-E2M2ZSOL.js.map → chunk-364HP22I.js.map} +0 -0
@@ -1,4 +1,5 @@
1
1
  import React, { Fragment } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import {
3
4
  selectPermissions,
4
5
  selectSessionStore,
@@ -24,6 +25,7 @@ import {
24
25
  import { Box, Flex } from '../../../Layout';
25
26
  import { Slider } from '../../../Slider';
26
27
  import { Text } from '../../../Text';
28
+ import { config as cssConfig } from '../../../Theme';
27
29
  import { StyledMenuTile } from '../../../TileMenu';
28
30
  import { ToastManager } from '../Toast/ToastManager';
29
31
  import { useSetAppDataByKey } from '../AppData/useUISettings';
@@ -62,7 +64,7 @@ const SpotlightActions = ({
62
64
  onSpotLightClick();
63
65
  }}
64
66
  >
65
- <StarIcon />
67
+ <StarIcon height={20} width={20} />
66
68
  <span>{isTileSpotlighted ? 'Remove from Spotlight' : 'Spotlight Tile for everyone'}</span>
67
69
  </StyledMenuTile.ItemButton>
68
70
  );
@@ -83,7 +85,7 @@ const PinActions = ({ audioTrackID, videoTrackID }) => {
83
85
  css={spacingCSS}
84
86
  onClick={() => (isTilePinned ? setPinnedTrackId() : setPinnedTrackId(videoTrackID || audioTrackID))}
85
87
  >
86
- <PinIcon />
88
+ <PinIcon height={20} width={20} />
87
89
  <span>{isTilePinned ? 'Unpin' : 'Pin'} Tile for myself</span>
88
90
  </StyledMenuTile.ItemButton>
89
91
  </>
@@ -96,7 +98,7 @@ const MinimiseInset = () => {
96
98
  return (
97
99
  <>
98
100
  <StyledMenuTile.ItemButton css={spacingCSS} onClick={() => setMinimised(!minimised)}>
99
- <ShrinkIcon />
101
+ <ShrinkIcon height={20} width={20} />
100
102
  <span>{minimised ? 'Show' : 'Minimise'} your video</span>
101
103
  </StyledMenuTile.ItemButton>
102
104
  </>
@@ -210,6 +212,8 @@ export const TileMenuContent = props => {
210
212
  type: REMOTE_STOP_SCREENSHARE_TYPE,
211
213
  });
212
214
 
215
+ const isMobile = useMedia(cssConfig.media.md);
216
+
213
217
  return isLocal ? (
214
218
  (showPinAction || canMinimise) && (
215
219
  <>
@@ -222,7 +226,7 @@ export const TileMenuContent = props => {
222
226
  closeSheetOnClick();
223
227
  }}
224
228
  >
225
- <PencilIcon />
229
+ <PencilIcon height={20} width={20} />
226
230
  <Text variant="sm" css={{ '@md': { fontWeight: '$semiBold' }, c: '$on_surface_high' }}>
227
231
  Change Name
228
232
  </Text>
@@ -240,7 +244,7 @@ export const TileMenuContent = props => {
240
244
  }}
241
245
  data-testid={isVideoEnabled ? 'mute_video_participant_btn' : 'unmute_video_participant_btn'}
242
246
  >
243
- {isVideoEnabled ? <VideoOnIcon /> : <VideoOffIcon />}
247
+ {isVideoEnabled ? <VideoOnIcon height={20} width={20} /> : <VideoOffIcon height={20} width={20} />}
244
248
  <span>{isVideoEnabled ? 'Mute' : 'Request Unmute'}</span>
245
249
  </StyledMenuTile.ItemButton>
246
250
  ) : null}
@@ -254,7 +258,7 @@ export const TileMenuContent = props => {
254
258
  }}
255
259
  data-testid={isVideoEnabled ? 'mute_audio_participant_btn' : 'unmute_audio_participant_btn'}
256
260
  >
257
- {isAudioEnabled ? <MicOnIcon /> : <MicOffIcon />}
261
+ {isAudioEnabled ? <MicOnIcon height={20} width={20} /> : <MicOffIcon height={20} width={20} />}
258
262
  <span>{isAudioEnabled ? 'Mute' : 'Request Unmute'}</span>
259
263
  </StyledMenuTile.ItemButton>
260
264
  ) : null}
@@ -262,7 +266,7 @@ export const TileMenuContent = props => {
262
266
  {audioTrackID ? (
263
267
  <StyledMenuTile.VolumeItem data-testid="participant_volume_slider" css={{ ...spacingCSS, mb: '$0' }}>
264
268
  <Flex align="center" gap={1}>
265
- <SpeakerIcon />
269
+ <SpeakerIcon height={20} width={20} />
266
270
  <Box as="span" css={{ ml: '$4' }}>
267
271
  Volume ({volume})
268
272
  </Box>
@@ -278,7 +282,7 @@ export const TileMenuContent = props => {
278
282
  </>
279
283
  )}
280
284
 
281
- <SimulcastLayers trackId={videoTrackID} />
285
+ {isMobile ? null : <SimulcastLayers trackId={videoTrackID} />}
282
286
 
283
287
  {removeOthers ? (
284
288
  <StyledMenuTile.RemoveItem
@@ -293,7 +297,7 @@ export const TileMenuContent = props => {
293
297
  }}
294
298
  data-testid="remove_participant_btn"
295
299
  >
296
- <RemoveUserIcon />
300
+ <RemoveUserIcon height={20} width={20} />
297
301
  <span>Remove Participant</span>
298
302
  </StyledMenuTile.RemoveItem>
299
303
  ) : null}
@@ -306,7 +310,7 @@ export const TileMenuContent = props => {
306
310
  }}
307
311
  css={spacingCSS}
308
312
  >
309
- <ShareScreenIcon />
313
+ <ShareScreenIcon height={20} width={20} />
310
314
  <span>Stop Screenshare</span>
311
315
  </StyledMenuTile.RemoveItem>
312
316
  ) : null}
@@ -109,7 +109,7 @@ export const ToastConfig = {
109
109
  };
110
110
  },
111
111
  },
112
- METADATA_UPDATED: {
112
+ RAISE_HAND: {
113
113
  single: notification => {
114
114
  return {
115
115
  title: `${notification.data?.name} raised hand`,
@@ -118,10 +118,11 @@ export const ToastConfig = {
118
118
  };
119
119
  },
120
120
  multiple: notifications => {
121
+ const count = new Set(notifications.map(notification => notification.data?.id)).size;
121
122
  return {
122
- title: `${notifications[notifications.length - 1].data?.name} and ${
123
- notifications.length - 1
124
- } others raised hand`,
123
+ title: `${notifications[notifications.length - 1].data?.name} ${
124
+ count > 1 ? `${count} and others` : ''
125
+ } raised hand`,
125
126
  icon: <HandIcon />,
126
127
  action: <HandRaiseAction isSingleHandRaise={false} />,
127
128
  };
@@ -13,7 +13,7 @@ import { usePagesWithTiles, useTileLayout } from '../hooks/useTileLayout';
13
13
  // @ts-ignore: No implicit Any
14
14
  import { UI_SETTINGS } from '../../common/constants';
15
15
 
16
- export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, onPageSize }: LayoutProps) {
16
+ export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, onPageSize, edgeToEdge }: LayoutProps) {
17
17
  const localPeer = useHMSStore(selectLocalPeer);
18
18
  const isMobile = useMedia(cssConfig.media.md);
19
19
  let maxTileCount = useUISettings(UI_SETTINGS.maxTileCount);
@@ -35,6 +35,7 @@ export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, o
35
35
  const { ref, pagesWithTiles } = useTileLayout({
36
36
  pageList,
37
37
  maxTileCount,
38
+ edgeToEdge,
38
39
  });
39
40
  const [page, setPage] = useState(0);
40
41
  const pageSize = pagesWithTiles[0]?.length || 0;
@@ -47,15 +48,17 @@ export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, o
47
48
 
48
49
  return (
49
50
  <Flex direction="column" css={{ flex: '1 1 0', h: '100%', position: 'relative', minWidth: 0 }}>
50
- <Grid tiles={pagesWithTiles[page]} ref={ref} />
51
- <Pagination
52
- page={page}
53
- onPageChange={page => {
54
- setPage(page);
55
- onPageChange?.(page);
56
- }}
57
- numPages={pagesWithTiles.length}
58
- />
51
+ <Grid tiles={pagesWithTiles[page]} ref={ref} edgeToEdge={edgeToEdge} />
52
+ {!edgeToEdge && (
53
+ <Pagination
54
+ page={page}
55
+ onPageChange={page => {
56
+ setPage(page);
57
+ onPageChange?.(page);
58
+ }}
59
+ numPages={pagesWithTiles.length}
60
+ />
61
+ )}
59
62
  {isInsetEnabled && pageList.length > 0 && pageList[0][0].peer.id !== localPeer?.id && <InsetTile />}
60
63
  </Flex>
61
64
  );
@@ -5,37 +5,39 @@ import { Box } from '../../../Layout';
5
5
  import VideoTile from '../VideoTile';
6
6
  import { useVideoTileContext } from '../hooks/useVideoTileLayout';
7
7
 
8
- export const Grid = React.forwardRef<HTMLDivElement, { tiles: TrackWithPeerAndDimensions[] }>(({ tiles }, ref) => {
9
- const videoTileProps = useVideoTileContext();
10
- return (
11
- <Box
12
- ref={ref}
13
- css={{
14
- flex: '1 1 0',
15
- gap: '$4',
16
- py: '$4',
17
- display: 'flex',
18
- placeContent: 'center',
19
- alignItems: 'center',
20
- justifyContent: 'center',
21
- flexFlow: 'row wrap',
22
- minHeight: 0,
23
- }}
24
- >
25
- {tiles?.map(tile => {
26
- return (
27
- <VideoTile
28
- key={tile.track?.id || tile.peer?.id}
29
- width={tile.width}
30
- height={tile.height}
31
- peerId={tile.peer?.id}
32
- trackId={tile.track?.id}
33
- rootCSS={{ padding: 0 }}
34
- objectFit="contain"
35
- {...videoTileProps}
36
- />
37
- );
38
- })}
39
- </Box>
40
- );
41
- });
8
+ export const Grid = React.forwardRef<HTMLDivElement, { tiles: TrackWithPeerAndDimensions[]; edgeToEdge?: boolean }>(
9
+ ({ tiles, edgeToEdge }, ref) => {
10
+ const videoTileProps = useVideoTileContext();
11
+ return (
12
+ <Box
13
+ ref={ref}
14
+ css={{
15
+ flex: '1 1 0',
16
+ gap: '$4',
17
+ display: 'flex',
18
+ placeContent: 'center',
19
+ alignItems: 'center',
20
+ justifyContent: 'center',
21
+ flexFlow: 'row wrap',
22
+ minHeight: 0,
23
+ '@md': { gap: edgeToEdge ? 0 : '$4' },
24
+ }}
25
+ >
26
+ {tiles?.map(tile => {
27
+ return (
28
+ <VideoTile
29
+ key={tile.track?.id || tile.peer?.id}
30
+ width={tile.width}
31
+ height={tile.height}
32
+ peerId={tile.peer?.id}
33
+ trackId={tile.track?.id}
34
+ rootCSS={{ padding: 0 }}
35
+ objectFit="contain"
36
+ {...videoTileProps}
37
+ />
38
+ );
39
+ })}
40
+ </Box>
41
+ );
42
+ },
43
+ );
@@ -1,12 +1,6 @@
1
1
  import React, { useEffect, useMemo, useState } from 'react';
2
2
  import { GridVideoTileLayout } from '@100mslive/types-prebuilt/elements/video_tile_layout';
3
- import {
4
- selectPeers,
5
- selectPeerScreenSharing,
6
- selectRemotePeers,
7
- useHMSStore,
8
- useHMSVanillaStore,
9
- } from '@100mslive/react-sdk';
3
+ import { selectPeers, selectPeerScreenSharing, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
10
4
  import { EqualProminence } from './EqualProminence';
11
5
  import { RoleProminence } from './RoleProminence';
12
6
  import { ScreenshareLayout } from './ScreenshareLayout';
@@ -15,14 +9,17 @@ import { usePinnedTrack } from '../AppData/useUISettings';
15
9
  import { VideoTileContext } from '../hooks/useVideoTileLayout';
16
10
  import PeersSorter from '../../common/PeersSorter';
17
11
 
18
- export type GridLayoutProps = GridVideoTileLayout & {
12
+ export type TileCustomisationProps = {
19
13
  hide_participant_name_on_tile: boolean;
20
- hide_audio_level_on_tile: boolean;
21
14
  rounded_video_tile: boolean;
22
15
  hide_audio_mute_on_tile: boolean;
23
16
  video_object_fit: 'contain' | 'cover';
17
+ edge_to_edge: boolean;
18
+ hide_metadata_on_tile: boolean;
24
19
  };
25
20
 
21
+ export type GridLayoutProps = GridVideoTileLayout & TileCustomisationProps;
22
+
26
23
  export const GridLayout = ({
27
24
  enable_local_tile_inset: isInsetEnabled = false,
28
25
  prominent_roles: prominentRoles = [],
@@ -31,13 +28,26 @@ export const GridLayout = ({
31
28
  rounded_video_tile = true,
32
29
  hide_audio_mute_on_tile = false,
33
30
  video_object_fit = 'contain',
31
+ edge_to_edge = false,
32
+ hide_metadata_on_tile = false,
34
33
  }: GridLayoutProps) => {
35
34
  const peerSharing = useHMSStore(selectPeerScreenSharing);
36
35
  const pinnedTrack = usePinnedTrack();
37
- const isRoleProminence = prominentRoles.length > 0 || pinnedTrack;
38
- const peers = useHMSStore(isInsetEnabled && !isRoleProminence && !peerSharing ? selectRemotePeers : selectPeers);
36
+ const peers = useHMSStore(selectPeers);
37
+ const isRoleProminence =
38
+ (prominentRoles.length &&
39
+ peers.some(
40
+ peer => peer.roleName && prominentRoles.includes(peer.roleName) && (peer.videoTrack || peer.audioTrack),
41
+ )) ||
42
+ pinnedTrack;
43
+ const updatedPeers = useMemo(() => {
44
+ if (isInsetEnabled && !isRoleProminence && !peerSharing) {
45
+ return peers.filter(peer => !peer.isLocal);
46
+ }
47
+ return peers;
48
+ }, [isInsetEnabled, isRoleProminence, peerSharing, peers]);
39
49
  const vanillaStore = useHMSVanillaStore();
40
- const [sortedPeers, setSortedPeers] = useState(peers);
50
+ const [sortedPeers, setSortedPeers] = useState(updatedPeers);
41
51
  const peersSorter = useMemo(() => new PeersSorter(vanillaStore), [vanillaStore]);
42
52
  const [pageSize, setPageSize] = useState(0);
43
53
  const [mainPage, setMainPage] = useState(0);
@@ -46,6 +56,7 @@ export const GridLayout = ({
46
56
  hideParticipantNameOnTile: hide_participant_name_on_tile,
47
57
  roundedVideoTile: rounded_video_tile,
48
58
  hideAudioMuteOnTile: hide_audio_mute_on_tile,
59
+ hideMetadataOnTile: hide_metadata_on_tile,
49
60
  objectFit: video_object_fit,
50
61
  };
51
62
 
@@ -54,16 +65,21 @@ export const GridLayout = ({
54
65
  return;
55
66
  }
56
67
  peersSorter.setPeersAndTilesPerPage({
57
- peers,
68
+ peers: updatedPeers,
58
69
  tilesPerPage: pageSize,
59
70
  });
60
71
  peersSorter.onUpdate(setSortedPeers);
61
- }, [mainPage, peersSorter, peers, pageSize]);
72
+ }, [mainPage, peersSorter, updatedPeers, pageSize]);
62
73
 
63
74
  if (peerSharing) {
64
75
  return (
65
76
  <VideoTileContext.Provider value={tileLayout}>
66
- <ScreenshareLayout peers={sortedPeers} onPageSize={setPageSize} onPageChange={setMainPage} />
77
+ <ScreenshareLayout
78
+ peers={sortedPeers}
79
+ onPageSize={setPageSize}
80
+ onPageChange={setMainPage}
81
+ edgeToEdge={edge_to_edge}
82
+ />
67
83
  </VideoTileContext.Provider>
68
84
  );
69
85
  } else if (isRoleProminence) {
@@ -75,6 +91,7 @@ export const GridLayout = ({
75
91
  onPageChange={setMainPage}
76
92
  prominentRoles={prominentRoles}
77
93
  isInsetEnabled={isInsetEnabled}
94
+ edgeToEdge={edge_to_edge}
78
95
  />
79
96
  </VideoTileContext.Provider>
80
97
  );
@@ -86,6 +103,7 @@ export const GridLayout = ({
86
103
  onPageSize={setPageSize}
87
104
  onPageChange={setMainPage}
88
105
  isInsetEnabled={isInsetEnabled}
106
+ edgeToEdge={edge_to_edge}
89
107
  />
90
108
  </VideoTileContext.Provider>
91
109
  );
@@ -1,13 +1,16 @@
1
1
  import React from 'react';
2
2
  import { TrackWithPeerAndDimensions } from '@100mslive/react-sdk';
3
- import { Flex } from '../../../Layout';
3
+ import { Box, Flex } from '../../../Layout';
4
4
  import { CSS } from '../../../Theme';
5
5
  // @ts-ignore: No implicit Any
6
6
  import VideoTile from '../VideoTile';
7
7
  import { useVideoTileContext } from '../hooks/useVideoTileLayout';
8
8
 
9
- const Root = ({ children }: React.PropsWithChildren) => (
10
- <Flex direction="column" css={{ size: '100%', gap: '$6' }}>
9
+ const Root = ({ children, edgeToEdge }: React.PropsWithChildren<{ edgeToEdge?: boolean }>) => (
10
+ <Flex
11
+ direction="column"
12
+ css={{ h: '100%', flex: '1 1 0', minWidth: 0, gap: '$6', '@md': { gap: edgeToEdge ? 0 : '$6' } }}
13
+ >
11
14
  {children}
12
15
  </Flex>
13
16
  );
@@ -20,36 +23,47 @@ const ProminentSection = ({ children, css = {} }: React.PropsWithChildren<{ css?
20
23
  );
21
24
  };
22
25
 
23
- const SecondarySection = ({ tiles, children }: React.PropsWithChildren<{ tiles: TrackWithPeerAndDimensions[] }>) => {
26
+ const SecondarySection = ({
27
+ tiles,
28
+ children,
29
+ edgeToEdge,
30
+ }: React.PropsWithChildren<{ tiles: TrackWithPeerAndDimensions[]; edgeToEdge?: boolean }>) => {
24
31
  const tileLayoutProps = useVideoTileContext();
32
+ if (!tiles?.length) {
33
+ return null;
34
+ }
25
35
  return (
26
- <Flex direction="column" css={{ flexBasis: tiles?.length > 0 ? 154 : 0, minHeight: 0, gap: '$2' }}>
27
- <Flex justify="center" align="center" css={{ gap: '$4', minHeight: 0, margin: '0 auto' }}>
28
- {tiles?.map(tile => {
29
- return (
30
- <VideoTile
31
- key={tile.track?.id || tile.peer?.id}
32
- height="100%"
33
- peerId={tile.peer?.id}
34
- trackId={tile.track?.id}
35
- rootCSS={{
36
- padding: 0,
37
- flex: '1 1 0',
38
- maxWidth: 'max-content',
39
- }}
40
- containerCSS={{
41
- width: 'unset',
42
- aspectRatio: 16 / 9,
43
- '@md': { aspectRatio: 1 },
44
- }}
45
- objectFit="contain"
46
- {...tileLayoutProps}
47
- />
48
- );
49
- })}
50
- </Flex>
51
- {children}
52
- </Flex>
36
+ <Box
37
+ css={{
38
+ display: 'grid',
39
+ gridTemplateRows: React.Children.count(children) > 0 ? '136px auto' : '154px',
40
+ gridTemplateColumns: `repeat(${tiles.length}, minmax(0, 1fr))`,
41
+ margin: '0 auto',
42
+ gap: '$2 $4',
43
+ placeItems: 'center',
44
+ '@md': { gap: edgeToEdge ? 0 : '$4' },
45
+ }}
46
+ >
47
+ {tiles.map(tile => {
48
+ return (
49
+ <VideoTile
50
+ key={tile.track?.id || tile.peer?.id}
51
+ peerId={tile.peer?.id}
52
+ trackId={tile.track?.id}
53
+ rootCSS={{
54
+ padding: 0,
55
+ maxWidth: 240,
56
+ maxHeight: '100%',
57
+ aspectRatio: 16 / 9,
58
+ '@md': { aspectRatio: 1 },
59
+ }}
60
+ objectFit="contain"
61
+ {...tileLayoutProps}
62
+ />
63
+ );
64
+ })}
65
+ <Box css={{ gridColumn: `1/span ${tiles.length}` }}>{children}</Box>
66
+ </Box>
53
67
  );
54
68
  };
55
69
 
@@ -15,6 +15,7 @@ export function RoleProminence({
15
15
  peers,
16
16
  onPageChange,
17
17
  onPageSize,
18
+ edgeToEdge,
18
19
  }: LayoutProps) {
19
20
  const { prominentPeers, secondaryPeers } = useRoleProminencePeers(prominentRoles, peers, isInsetEnabled);
20
21
  const localPeer = useHMSStore(selectLocalPeer);
@@ -41,15 +42,17 @@ export function RoleProminence({
41
42
  <ProminenceLayout.ProminentSection>
42
43
  <Grid ref={ref} tiles={pagesWithTiles[page]} />
43
44
  </ProminenceLayout.ProminentSection>
44
- <Pagination
45
- page={page}
46
- onPageChange={page => {
47
- setPage(page);
48
- onPageChange?.(page);
49
- }}
50
- numPages={pagesWithTiles.length}
51
- />
52
- <SecondaryTiles peers={secondaryPeers} isInsetEnabled={isInsetEnabled} />
45
+ {!edgeToEdge && (
46
+ <Pagination
47
+ page={page}
48
+ onPageChange={page => {
49
+ setPage(page);
50
+ onPageChange?.(page);
51
+ }}
52
+ numPages={pagesWithTiles.length}
53
+ />
54
+ )}
55
+ <SecondaryTiles peers={secondaryPeers} isInsetEnabled={isInsetEnabled} edgeToEdge={edgeToEdge} />
53
56
  {isInsetEnabled && localPeer && !prominentPeers.includes(localPeer) && <InsetTile />}
54
57
  </ProminenceLayout.Root>
55
58
  );
@@ -1,5 +1,7 @@
1
1
  import React, { useEffect, useMemo, useState } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import { selectPeersScreenSharing, useHMSStore } from '@100mslive/react-sdk';
4
+ import { config as cssConfig } from '../../../Theme';
3
5
  import { Pagination } from '../Pagination';
4
6
  // @ts-ignore: No implicit Any
5
7
  import ScreenshareTile from '../ScreenshareTile';
@@ -11,26 +13,40 @@ import { useSetAppDataByKey } from '../AppData/useUISettings';
11
13
  // @ts-ignore: No implicit Any
12
14
  import { APP_DATA } from '../../common/constants';
13
15
 
14
- export const ScreenshareLayout = ({ peers, onPageChange, onPageSize }: LayoutProps) => {
16
+ export const ScreenshareLayout = ({ peers, onPageChange, onPageSize, edgeToEdge }: LayoutProps) => {
15
17
  const peersSharing = useHMSStore(selectPeersScreenSharing);
16
18
  const [, setActiveScreenSharePeer] = useSetAppDataByKey(APP_DATA.activeScreensharePeerId);
17
19
  const [page, setPage] = useState(0);
18
- const activeSharePeerId = peersSharing[page]?.id;
19
- const secondaryPeers = useMemo(() => peers.filter(p => p.id !== activeSharePeerId), [activeSharePeerId, peers]);
20
+ const activeSharePeer = peersSharing[page];
21
+ const isMobile = useMedia(cssConfig.media.md);
22
+ const secondaryPeers = useMemo(
23
+ () =>
24
+ isMobile
25
+ ? activeSharePeer
26
+ ? [activeSharePeer, ...peers.filter(p => p.id !== activeSharePeer?.id)]
27
+ : peers //keep active sharing peer as first tile
28
+ : peers.filter(p => p.id !== activeSharePeer?.id),
29
+ [activeSharePeer, peers, isMobile],
30
+ );
20
31
  useEffect(() => {
21
- setActiveScreenSharePeer(activeSharePeerId);
32
+ setActiveScreenSharePeer(isMobile ? '' : activeSharePeer?.id);
22
33
  return () => {
23
34
  setActiveScreenSharePeer('');
24
35
  };
25
- }, [activeSharePeerId, setActiveScreenSharePeer]);
36
+ }, [activeSharePeer?.id, isMobile, setActiveScreenSharePeer]);
26
37
 
27
38
  return (
28
- <ProminenceLayout.Root>
39
+ <ProminenceLayout.Root edgeToEdge={edgeToEdge}>
29
40
  <ProminenceLayout.ProminentSection>
30
- <ScreenshareTile peerId={peersSharing[page].id} />
31
- <Pagination page={page} onPageChange={setPage} numPages={peersSharing.length} />
41
+ <ScreenshareTile peerId={peersSharing[page]?.id} />
42
+ {!edgeToEdge && <Pagination page={page} onPageChange={setPage} numPages={peersSharing.length} />}
32
43
  </ProminenceLayout.ProminentSection>
33
- <SecondaryTiles peers={secondaryPeers} onPageChange={onPageChange} onPageSize={onPageSize} />
44
+ <SecondaryTiles
45
+ peers={secondaryPeers}
46
+ onPageChange={onPageChange}
47
+ onPageSize={onPageSize}
48
+ edgeToEdge={edgeToEdge}
49
+ />
34
50
  </ProminenceLayout.Root>
35
51
  );
36
52
  };
@@ -2,6 +2,7 @@ import { HMSPeer } from '@100mslive/react-sdk';
2
2
 
3
3
  export interface LayoutProps {
4
4
  isInsetEnabled?: boolean;
5
+ edgeToEdge?: boolean;
5
6
  prominentRoles?: string[];
6
7
  peers: HMSPeer[];
7
8
  onPageChange?: (page: number) => void;