@100mslive/roomkit-react 0.1.6-alpha.0 → 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 (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,5 +1,4 @@
1
1
  import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
- import { useMedia } from 'react-use';
3
2
  import {
4
3
  selectAudioTrackByPeerID,
5
4
  selectIsPeerAudioEnabled,
@@ -19,7 +18,7 @@ import TileMenu, { isSameTile } from './TileMenu/TileMenu';
19
18
  import { Avatar } from '../../Avatar';
20
19
  import { Box, Flex } from '../../Layout';
21
20
  import { VideoTileStats } from '../../Stats';
22
- import { config as cssConfig, keyframes } from '../../Theme';
21
+ import { keyframes } from '../../Theme';
23
22
  import { Video } from '../../Video';
24
23
  import { StyledVideoTile } from '../../VideoTile';
25
24
  import { getVideoTileLabel } from './peerTileUtils';
@@ -40,6 +39,7 @@ const Tile = ({
40
39
  hideParticipantNameOnTile = false,
41
40
  roundedVideoTile = true,
42
41
  hideAudioMuteOnTile = false,
42
+ hideMetadataOnTile = false,
43
43
  }) => {
44
44
  const trackSelector = trackId ? selectVideoTrackByID(trackId) : selectVideoTrackByPeerID(peerId);
45
45
  const track = useHMSStore(trackSelector);
@@ -81,7 +81,6 @@ const Tile = ({
81
81
  }
82
82
  return 'large';
83
83
  }, [width, height]);
84
- const isMobile = useMedia(cssConfig.media.md);
85
84
 
86
85
  return (
87
86
  <StyledVideoTile.Root
@@ -103,44 +102,42 @@ const Tile = ({
103
102
  <VideoTileStats audioTrackID={audioTrack?.id} videoTrackID={track?.id} peerID={peerId} isLocal={isLocal} />
104
103
  ) : null}
105
104
 
106
- {track ? (
107
- <Video
108
- trackId={track?.id}
109
- attach={isLocal ? undefined : !isAudioOnly}
110
- mirror={
111
- mirrorLocalVideo &&
112
- peerId === localPeerID &&
113
- track?.source === 'regular' &&
114
- track?.facingMode !== 'environment'
115
- }
116
- noRadius={!roundedVideoTile}
117
- data-testid="participant_video_tile"
118
- css={{
119
- objectFit,
120
- filter: isVideoDegraded ? 'blur($space$2)' : undefined,
121
- bg: 'transparent',
122
- }}
123
- />
124
- ) : null}
105
+ <Video
106
+ trackId={track?.id}
107
+ attach={isLocal ? undefined : !isAudioOnly}
108
+ mirror={
109
+ mirrorLocalVideo &&
110
+ peerId === localPeerID &&
111
+ track?.source === 'regular' &&
112
+ track?.facingMode !== 'environment'
113
+ }
114
+ noRadius={!roundedVideoTile}
115
+ data-testid="participant_video_tile"
116
+ css={{
117
+ objectFit,
118
+ filter: isVideoDegraded ? 'blur($space$2)' : undefined,
119
+ bg: 'transparent',
120
+ }}
121
+ />
122
+
125
123
  {isVideoMuted || (!isLocal && isAudioOnly) ? (
126
124
  <StyledVideoTile.AvatarContainer>
127
125
  <Avatar name={peerName || ''} data-testid="participant_avatar_icon" size={avatarSize} />
128
126
  </StyledVideoTile.AvatarContainer>
129
127
  ) : null}
130
128
 
131
- {showAudioMuted({
132
- hideAudioMute: hideAudioMuteOnTile,
133
- isAudioMuted,
134
- }) ? (
135
- <StyledVideoTile.AudioIndicator
136
- data-testid="participant_audio_mute_icon"
137
- size={width && height && (width < 180 || height < 180) ? 'small' : 'medium'}
138
- >
139
- <MicOffIcon />
140
- </StyledVideoTile.AudioIndicator>
141
- ) : (
142
- <AudioLevel trackId={audioTrack?.id} />
143
- )}
129
+ {!hideAudioMuteOnTile ? (
130
+ isAudioMuted ? (
131
+ <StyledVideoTile.AudioIndicator
132
+ data-testid="participant_audio_mute_icon"
133
+ size={width && height && (width < 180 || height < 180) ? 'small' : 'medium'}
134
+ >
135
+ <MicOffIcon />
136
+ </StyledVideoTile.AudioIndicator>
137
+ ) : (
138
+ <AudioLevel trackId={audioTrack?.id} />
139
+ )
140
+ ) : null}
144
141
  {isMouseHovered || isDragabble ? (
145
142
  <TileMenu
146
143
  peerID={peerId}
@@ -150,25 +147,24 @@ const Tile = ({
150
147
  enableSpotlightingPeer={enableSpotlightingPeer}
151
148
  />
152
149
  ) : null}
153
- <PeerMetadata peerId={peerId} />
154
- {isMobile ? null : (
155
- <TileConnection
156
- hideLabel={hideParticipantNameOnTile}
157
- name={label}
158
- isTile
159
- peerId={peerId}
160
- width={width}
161
- pinned={pinned}
162
- spotlighted={spotlighted}
163
- />
164
- )}
150
+ {!hideMetadataOnTile && <PeerMetadata peerId={peerId} />}
151
+
152
+ <TileConnection
153
+ hideLabel={hideParticipantNameOnTile}
154
+ name={label}
155
+ isTile
156
+ peerId={peerId}
157
+ width={width}
158
+ pinned={pinned}
159
+ spotlighted={spotlighted}
160
+ />
165
161
  </StyledVideoTile.Container>
166
162
  ) : null}
167
163
  </StyledVideoTile.Root>
168
164
  );
169
165
  };
170
166
 
171
- const metaStyles = { top: '$4', left: '$4' };
167
+ const metaStyles = { top: '$4', left: '$4', width: '$14', height: '$14' };
172
168
 
173
169
  const heightAnimation = value =>
174
170
  keyframes({
@@ -233,7 +229,7 @@ const PeerMetadata = ({ peerId }) => {
233
229
  ) : null}
234
230
  {isBRB ? (
235
231
  <StyledVideoTile.AttributeBox css={metaStyles} data-testid="brb_icon_onTile">
236
- <BrbTileIcon width={24} height={24} />
232
+ <BrbTileIcon width={22} height={22} />
237
233
  </StyledVideoTile.AttributeBox>
238
234
  ) : null}
239
235
  </Fragment>
@@ -242,8 +238,4 @@ const PeerMetadata = ({ peerId }) => {
242
238
 
243
239
  const VideoTile = React.memo(Tile);
244
240
 
245
- const showAudioMuted = ({ hideAudioMute, isAudioMuted }) => {
246
- return isAudioMuted && !hideAudioMute;
247
- };
248
-
249
241
  export default VideoTile;
@@ -23,14 +23,13 @@ import {
23
23
  useRoomLayoutConferencingScreen,
24
24
  useRoomLayoutPreviewScreen,
25
25
  } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
26
- import { useAuthToken, useIsHeadless, useSetAppDataByKey } from './AppData/useUISettings';
27
- import { APP_DATA, EMOJI_REACTION_TYPE, isAndroid, isIOS, isIPadOS } from '../common/constants';
26
+ import { useAuthToken, useSetAppDataByKey } from './AppData/useUISettings';
27
+ import { APP_DATA, isAndroid, isIOS, isIPadOS } from '../common/constants';
28
28
 
29
29
  const Conference = () => {
30
30
  const navigate = useNavigate();
31
31
  const { roomId, role } = useParams();
32
- const isHeadless = useIsHeadless();
33
- const { userName } = useHMSPrebuiltContext();
32
+ const { userName, endpoints } = useHMSPrebuiltContext();
34
33
  const screenProps = useRoomLayoutConferencingScreen();
35
34
  const { isPreviewScreenEnabled } = useRoomLayoutPreviewScreen();
36
35
  const roomState = useHMSStore(selectRoomState);
@@ -42,11 +41,11 @@ const Conference = () => {
42
41
  const authTokenInAppData = useAuthToken();
43
42
  const headerRef = useRef();
44
43
  const footerRef = useRef();
44
+ const isMobileDevice = isAndroid || isIOS || isIPadOS;
45
45
  const dropdownListRef = useRef();
46
- const performAutoHide = hideControls && (isAndroid || isIOS || isIPadOS);
47
46
  const [isHLSStarted] = useSetAppDataByKey(APP_DATA.hlsStarted);
48
47
  const toggleControls = () => {
49
- if (dropdownListRef.current?.length === 0) {
48
+ if (dropdownListRef.current?.length === 0 && isMobileDevice) {
50
49
  setHideControls(value => !value);
51
50
  }
52
51
  };
@@ -58,14 +57,14 @@ const Conference = () => {
58
57
  clearTimeout(timeout);
59
58
  timeout = setTimeout(() => {
60
59
  if (dropdownListRef.current.length === 0) {
61
- setHideControls(true);
60
+ setHideControls(isMobileDevice);
62
61
  }
63
62
  }, 5000);
64
63
  }
65
64
  return () => {
66
65
  clearTimeout(timeout);
67
66
  };
68
- }, [dropdownList, hideControls]);
67
+ }, [dropdownList, hideControls, isMobileDevice]);
69
68
 
70
69
  useEffect(() => {
71
70
  if (!roomId) {
@@ -90,9 +89,7 @@ const Conference = () => {
90
89
  .join({
91
90
  userName,
92
91
  authToken: authTokenInAppData,
93
- initEndpoint: process.env.REACT_APP_ENV
94
- ? `https://${process.env.REACT_APP_ENV}-init.100ms.live/init`
95
- : undefined,
92
+ initEndpoint: endpoints?.init,
96
93
  initialSettings: {
97
94
  isAudioMuted: !isPreviewScreenEnabled,
98
95
  isVideoMuted: !isPreviewScreenEnabled,
@@ -101,14 +98,7 @@ const Conference = () => {
101
98
  })
102
99
  .catch(console.error);
103
100
  }
104
- }, [authTokenInAppData, hmsActions, isConnectedToRoom, isPreviewScreenEnabled, roomState, userName]);
105
-
106
- useEffect(() => {
107
- // beam doesn't need to store messages, saves on unnecessary store updates in large calls
108
- if (isHeadless) {
109
- hmsActions.ignoreMessageTypes(['chat', EMOJI_REACTION_TYPE]);
110
- }
111
- }, [isHeadless, hmsActions]);
101
+ }, [authTokenInAppData, endpoints?.init, hmsActions, isConnectedToRoom, isPreviewScreenEnabled, roomState, userName]);
112
102
 
113
103
  useEffect(() => {
114
104
  return () => {
@@ -117,71 +107,78 @@ const Conference = () => {
117
107
  }, []);
118
108
 
119
109
  if (!isConnectedToRoom) {
120
- return <FullPageProgress loadingText="Joining..." />;
121
- }
122
-
123
- if (isHLSStarted) {
124
- return <FullPageProgress loadingText="Starting live stream..." />;
110
+ return <FullPageProgress text="Joining..." />;
125
111
  }
126
112
 
127
113
  return (
128
- <Flex css={{ size: '100%', overflow: 'hidden' }} direction="column">
129
- {!screenProps.hideSections.includes('header') && (
130
- <Box
131
- ref={headerRef}
132
- css={{
133
- h: '$18',
134
- transition: 'margin 0.3s ease-in-out',
135
- marginTop: performAutoHide ? `-${headerRef.current?.clientHeight}px` : 'none',
136
- '@md': {
137
- h: '$17',
138
- },
139
- }}
140
- data-testid="header"
141
- >
142
- <Header elements={screenProps.elements} screenType={screenProps.screenType} />
114
+ <>
115
+ {isHLSStarted ? (
116
+ <Box css={{ position: 'fixed', zIndex: 100, w: '100%', h: '100%', left: 0, top: 0 }}>
117
+ <FullPageProgress text="Starting live stream..." css={{ opacity: 0.8, bg: '$background_dim' }} />
143
118
  </Box>
144
- )}
145
- <Box
146
- css={{
147
- w: '100%',
148
- flex: '1 1 0',
149
- minHeight: 0,
150
- px: '$10',
151
- paddingBottom: 'env(safe-area-inset-bottom)',
152
- '@lg': {
153
- px: '$4',
154
- },
155
- }}
156
- id="conferencing"
157
- data-testid="conferencing"
158
- onClick={toggleControls}
159
- >
160
- <VideoStreamingSection screenType={screenProps.screenType} elements={screenProps.elements} />
161
- </Box>
162
- {!screenProps.hideSections.includes('footer') && (
119
+ ) : null}
120
+ <Flex css={{ size: '100%', overflow: 'hidden' }} direction="column">
121
+ {!screenProps.hideSections.includes('header') && (
122
+ <Box
123
+ ref={headerRef}
124
+ css={{
125
+ h: '$18',
126
+ transition: 'margin 0.3s ease-in-out',
127
+ marginTop: hideControls ? `-${headerRef.current?.clientHeight}px` : 'none',
128
+ '@md': {
129
+ h: '$17',
130
+ },
131
+ }}
132
+ data-testid="header"
133
+ >
134
+ <Header elements={screenProps.elements} screenType={screenProps.screenType} />
135
+ </Box>
136
+ )}
163
137
  <Box
164
- ref={footerRef}
165
138
  css={{
166
- flexShrink: 0,
167
- maxHeight: '$24',
168
- transition: 'margin 0.3s ease-in-out',
169
- bg: '$background_dim',
170
- marginBottom: performAutoHide ? `-${footerRef.current?.clientHeight}px` : undefined,
171
- '@md': {
172
- maxHeight: 'unset',
173
- bg: screenProps.screenType === 'hls_live_streaming' ? 'transparent' : '$background_dim',
139
+ w: '100%',
140
+ flex: '1 1 0',
141
+ minHeight: 0,
142
+ px: screenProps?.elements?.video_tile_layout?.grid?.edge_to_edge ? 0 : '$10', // TODO: padding to be controlled by section/element
143
+ paddingBottom: 'env(safe-area-inset-bottom)',
144
+ '@lg': {
145
+ px: 0,
174
146
  },
175
147
  }}
176
- data-testid="footer"
148
+ id="conferencing"
149
+ data-testid="conferencing"
150
+ onClick={toggleControls}
177
151
  >
178
- <Footer elements={screenProps.elements} screenType={screenProps.screenType} />
152
+ <VideoStreamingSection
153
+ screenType={screenProps.screenType}
154
+ elements={screenProps.elements}
155
+ hideControls={hideControls}
156
+ />
179
157
  </Box>
180
- )}
181
- <RoleChangeRequestModal />
182
- <HLSFailureModal />
183
- <ActivatedPIP />
184
- </Flex>
158
+ {!screenProps.hideSections.includes('footer') && (
159
+ <Box
160
+ ref={footerRef}
161
+ css={{
162
+ flexShrink: 0,
163
+ maxHeight: '$24',
164
+ transition: 'margin 0.3s ease-in-out',
165
+ bg: '$background_dim',
166
+ marginBottom: hideControls ? `-${footerRef.current?.clientHeight}px` : undefined,
167
+ '@md': {
168
+ maxHeight: 'unset',
169
+ bg: screenProps.screenType === 'hls_live_streaming' ? 'transparent' : '$background_dim',
170
+ },
171
+ }}
172
+ data-testid="footer"
173
+ >
174
+ <Footer elements={screenProps.elements} screenType={screenProps.screenType} />
175
+ </Box>
176
+ )}
177
+ <RoleChangeRequestModal />
178
+ <HLSFailureModal />
179
+ <ActivatedPIP />
180
+ </Flex>
181
+ </>
185
182
  );
186
183
  };
187
184
 
@@ -0,0 +1,57 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ import {
3
+ HMSException,
4
+ selectIsConnectedToRoom,
5
+ selectPermissions,
6
+ useHMSActions,
7
+ useHMSStore,
8
+ useRecordingStreaming,
9
+ } from '@100mslive/react-sdk';
10
+ // @ts-ignore: No implicit Any
11
+ import { useSetAppDataByKey } from '../AppData/useUISettings';
12
+ // @ts-ignore: No implicit Any
13
+ import { useShowStreamingUI } from '../../common/hooks';
14
+ // @ts-ignore: No implicit Any
15
+ import { APP_DATA } from '../../common/constants';
16
+
17
+ export const useAutoStartStreaming = () => {
18
+ const [isHLSStarted, setHLSStarted] = useSetAppDataByKey(APP_DATA.hlsStarted);
19
+ const permissions = useHMSStore(selectPermissions);
20
+ const showStreamingUI = useShowStreamingUI();
21
+ const hmsActions = useHMSActions();
22
+ const isConnected = useHMSStore(selectIsConnectedToRoom);
23
+ const { isHLSRunning } = useRecordingStreaming();
24
+ const streamStartedRef = useRef(false);
25
+
26
+ const startHLS = useCallback(async () => {
27
+ try {
28
+ if (isHLSStarted || !showStreamingUI || isHLSRunning) {
29
+ return;
30
+ }
31
+ setHLSStarted(true);
32
+ streamStartedRef.current = true;
33
+ await hmsActions.startHLSStreaming();
34
+ } catch (error) {
35
+ if ((error as HMSException).message?.includes('beam already started')) {
36
+ return;
37
+ }
38
+ streamStartedRef.current = false;
39
+ setHLSStarted(false);
40
+ }
41
+ }, [hmsActions, isHLSRunning, isHLSStarted, setHLSStarted, showStreamingUI]);
42
+
43
+ useEffect(() => {
44
+ if (!isHLSStarted && !isHLSRunning) {
45
+ streamStartedRef.current = false;
46
+ }
47
+ }, [isHLSStarted, isHLSRunning]);
48
+
49
+ useEffect(() => {
50
+ if (!isConnected || streamStartedRef.current || !permissions?.hlsStreaming) {
51
+ return;
52
+ }
53
+ // Is a streaming kit and broadcaster joins
54
+ startHLS();
55
+ // eslint-disable-next-line react-hooks/exhaustive-deps
56
+ }, [isConnected]);
57
+ };
@@ -1,19 +1,28 @@
1
1
  import { useCallback, useState } from 'react';
2
- import { selectLocalPeerID, selectPeerMetadata, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
2
+ import {
3
+ selectLocalPeerID,
4
+ selectPeerMetadata,
5
+ useHMSActions,
6
+ useHMSStore,
7
+ useHMSVanillaStore,
8
+ } from '@100mslive/react-sdk';
3
9
 
4
10
  export const useMyMetadata = () => {
5
11
  const hmsActions = useHMSActions();
6
12
  const localPeerId = useHMSStore(selectLocalPeerID);
13
+ const vanillaStore = useHMSVanillaStore();
7
14
  const metaData = useHMSStore(selectPeerMetadata(localPeerId));
8
15
  const [isHandRaised, setHandRaised] = useState(metaData?.isHandRaised || false);
9
16
  const [isBRBOn, setBRBOn] = useState(metaData?.isBRBOn || false); // BRB = be right back
10
17
 
11
18
  const update = async updatedFields => {
12
19
  try {
13
- await hmsActions.changeMetadata(Object.assign(metaData, updatedFields));
20
+ // get current state from store and merge updated fields
21
+ const currentMetadata = vanillaStore.getState(selectPeerMetadata(localPeerId));
22
+ await hmsActions.changeMetadata(Object.assign(currentMetadata, updatedFields));
14
23
  return true;
15
24
  } catch (error) {
16
- console.error('failed to update metadata ', metaData, updatedFields);
25
+ console.error('failed to update metadata ', updatedFields);
17
26
  }
18
27
  };
19
28
 
@@ -0,0 +1,34 @@
1
+ import { useCallback } from 'react';
2
+ import { useNavigate, useParams } from 'react-router-dom';
3
+ import { useHMSPrebuiltContext } from '../../AppContext';
4
+ // @ts-ignore: No implicit Any
5
+ import { PictureInPicture } from '../PIP/PIPManager';
6
+ // @ts-ignore: No implicit Any
7
+ import { ToastManager } from '../Toast/ToastManager';
8
+ import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
9
+
10
+ export const useRedirectToLeave = () => {
11
+ const { isLeaveScreenEnabled } = useRoomLayoutLeaveScreen();
12
+ const { onLeave } = useHMSPrebuiltContext();
13
+ const params = useParams();
14
+ const navigate = useNavigate();
15
+
16
+ const redirect = useCallback(
17
+ (timeout = 0) => {
18
+ setTimeout(() => {
19
+ const prefix = isLeaveScreenEnabled ? '/leave/' : '/';
20
+ if (params.role) {
21
+ navigate(prefix + params.roomId + '/' + params.role);
22
+ } else {
23
+ navigate(prefix + params.roomId);
24
+ }
25
+ PictureInPicture.stop().catch(() => console.error('stopping pip'));
26
+ ToastManager.clearAllToast();
27
+ onLeave?.();
28
+ }, timeout);
29
+ },
30
+ [isLeaveScreenEnabled, navigate, onLeave, params.role, params.roomId],
31
+ );
32
+
33
+ return { redirectToLeave: redirect };
34
+ };
@@ -12,7 +12,7 @@ export const useRoleProminencePeers = (prominentRoles: string[], peers: HMSPeer[
12
12
  if (pinnedTrack) {
13
13
  if (pinnedTrack.peerId === peer.id) {
14
14
  acc[0].push(peer);
15
- } else {
15
+ } else if (!(isInsetEnabled && peer.isLocal)) {
16
16
  acc[1].push(peer);
17
17
  }
18
18
  return acc;
@@ -10,7 +10,6 @@ import {
10
10
  import { config as cssConfig } from '../../../Theme';
11
11
 
12
12
  const aspectRatioConfig = { default: [1 / 1, 4 / 3, 16 / 9], mobile: [1 / 1, 3 / 4, 9 / 16] };
13
- const gap = 8; // gap between flex items
14
13
 
15
14
  export const usePagesWithTiles = ({ peers, maxTileCount }: { peers: HMSPeer[]; maxTileCount: number }) => {
16
15
  const vanillaStore = useHMSVanillaStore();
@@ -39,9 +38,11 @@ export const usePagesWithTiles = ({ peers, maxTileCount }: { peers: HMSPeer[]; m
39
38
  export const useTileLayout = ({
40
39
  pageList,
41
40
  maxTileCount,
41
+ edgeToEdge = false,
42
42
  }: {
43
43
  pageList: TrackWithPeerAndDimensions[][];
44
44
  maxTileCount: number;
45
+ edgeToEdge?: boolean;
45
46
  }) => {
46
47
  const vanillaStore = useHMSVanillaStore();
47
48
  const [ref, { width, height }] = useMeasure<HTMLDivElement>();
@@ -76,6 +77,7 @@ export const useTileLayout = ({
76
77
  return rowElements;
77
78
  });
78
79
 
80
+ const gap = edgeToEdge && isMobile ? 0 : 8; // gap between flex items
79
81
  const maxHeight = height - (maxRows - 1) * gap;
80
82
  const maxRowHeight = maxHeight / matrix.length;
81
83
  const aspectRatios =
@@ -86,25 +88,29 @@ export const useTileLayout = ({
86
88
  for (const row of matrix) {
87
89
  let tileWidth = (width - (row.length - 1) * gap) / row.length;
88
90
  let tileHeight = 0;
89
- const calcHeights = aspectRatios.map(aR => tileWidth / aR);
90
- for (const h of calcHeights) {
91
- if (h < maxRowHeight) {
92
- if (tileHeight < h) {
93
- tileHeight = h;
91
+ if (edgeToEdge) {
92
+ tileHeight = maxRowHeight;
93
+ } else {
94
+ const calcHeights = aspectRatios.map(aR => tileWidth / aR);
95
+ for (const h of calcHeights) {
96
+ if (h < maxRowHeight) {
97
+ if (tileHeight < h) {
98
+ tileHeight = h;
99
+ }
94
100
  }
95
101
  }
96
- }
97
102
 
98
- // tileHeight is not calculated as it could be exceeding the max possible height
99
- // find the max possible width instead
100
- if (tileHeight === 0) {
101
- tileHeight = maxRowHeight;
102
- const calcWidths = aspectRatios.map(aR => tileHeight * aR);
103
- tileWidth = 0;
104
- for (const w of calcWidths) {
105
- if (w < width) {
106
- if (tileWidth < w) {
107
- tileWidth = w;
103
+ // tileHeight is not calculated as it could be exceeding the max possible height
104
+ // find the max possible width instead
105
+ if (tileHeight === 0) {
106
+ tileHeight = maxRowHeight;
107
+ const calcWidths = aspectRatios.map(aR => tileHeight * aR);
108
+ tileWidth = 0;
109
+ for (const w of calcWidths) {
110
+ if (w < width) {
111
+ if (tileWidth < w) {
112
+ tileWidth = w;
113
+ }
108
114
  }
109
115
  }
110
116
  }
@@ -116,6 +122,6 @@ export const useTileLayout = ({
116
122
  }
117
123
  }
118
124
  setPagesWithTiles([...pageList]);
119
- }, [width, height, maxTileCount, pageList, vanillaStore, isMobile]);
125
+ }, [width, height, maxTileCount, pageList, vanillaStore, isMobile, edgeToEdge]);
120
126
  return { pagesWithTiles, ref };
121
127
  };
@@ -5,7 +5,9 @@ type TileContextType = {
5
5
  hideParticipantNameOnTile?: boolean;
6
6
  roundedVideoTile?: boolean;
7
7
  hideAudioMuteOnTile?: boolean;
8
+ hideAudioLevelOnTile?: boolean;
8
9
  objectFit?: 'cover' | 'contain';
10
+ hideMetadataOnTile?: boolean;
9
11
  };
10
12
 
11
13
  export const VideoTileContext = React.createContext<TileContextType>({
@@ -13,7 +15,9 @@ export const VideoTileContext = React.createContext<TileContextType>({
13
15
  hideParticipantNameOnTile: false,
14
16
  roundedVideoTile: true,
15
17
  hideAudioMuteOnTile: false,
18
+ hideAudioLevelOnTile: false,
16
19
  objectFit: 'contain',
20
+ hideMetadataOnTile: false,
17
21
  });
18
22
 
19
23
  export const useVideoTileContext = () => {
@@ -1,7 +1,5 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import {
3
- selectLocalPeerID,
4
- selectLocalPeerRoleName,
5
3
  selectPeers,
6
4
  selectPeerScreenSharing,
7
5
  throwErrorHandler,
@@ -25,21 +23,13 @@ export const EmbedView = () => {
25
23
  export const EmbebScreenShareView = ({ children }) => {
26
24
  const peers = useHMSStore(selectPeers);
27
25
 
28
- const localPeerID = useHMSStore(selectLocalPeerID);
29
- const localPeerRole = useHMSStore(selectLocalPeerRoleName);
30
26
  const peerPresenting = useHMSStore(selectPeerScreenSharing);
31
- const isPresenterFromMyRole = peerPresenting?.roleName?.toLowerCase() === localPeerRole?.toLowerCase();
32
- const amIPresenting = localPeerID === peerPresenting?.id;
33
- const showPresenterInSmallTile = amIPresenting || isPresenterFromMyRole;
34
27
  const [, setActiveScreenSharePeer] = useSetAppDataByKey(APP_DATA.activeScreensharePeerId);
35
28
 
36
29
  const smallTilePeers = useMemo(() => {
37
30
  const smallTilePeers = peers.filter(peer => peer.id !== peerPresenting?.id);
38
- if (showPresenterInSmallTile && peerPresenting) {
39
- smallTilePeers.unshift(peerPresenting); // put presenter on first page
40
- }
41
31
  return smallTilePeers;
42
- }, [peers, peerPresenting, showPresenterInSmallTile]);
32
+ }, [peers, peerPresenting]);
43
33
 
44
34
  useEffect(() => {
45
35
  setActiveScreenSharePeer(peerPresenting?.id);