@100mslive/roomkit-react 0.2.8-alpha.1 → 0.2.8-alpha.11

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 (105) hide show
  1. package/dist/HLSView-EDROW5VZ.js +1411 -0
  2. package/dist/HLSView-EDROW5VZ.js.map +7 -0
  3. package/dist/Prebuilt/common/hooks.d.ts +3 -0
  4. package/dist/Prebuilt/components/Chat/MwebChatOption.d.ts +1 -1
  5. package/dist/Prebuilt/components/HMSVideo/FullscreenButton.d.ts +5 -0
  6. package/dist/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.d.ts +5 -0
  7. package/dist/Prebuilt/components/HMSVideo/HLSCaptionSelector.d.ts +1 -2
  8. package/dist/Prebuilt/components/HMSVideo/HLSQualitySelector.d.ts +13 -0
  9. package/dist/Prebuilt/components/HMSVideo/MwebHLSViewTitle.d.ts +2 -0
  10. package/dist/Prebuilt/components/HMSVideo/PlayButton.d.ts +6 -0
  11. package/dist/Prebuilt/components/HMSVideo/PlayPauseButton.d.ts +6 -0
  12. package/dist/Prebuilt/components/HMSVideo/PlayerContext.d.ts +8 -0
  13. package/dist/Prebuilt/components/HMSVideo/SeekControls.d.ts +7 -0
  14. package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +5 -0
  15. package/dist/Prebuilt/components/HMSVideo/VideoTime.d.ts +2 -0
  16. package/dist/Prebuilt/components/HMSVideo/VolumeControl.d.ts +2 -0
  17. package/dist/Prebuilt/components/HMSVideo/index.d.ts +26 -0
  18. package/dist/Prebuilt/components/HMSVideo/utils.d.ts +8 -0
  19. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +2 -1
  20. package/dist/Prebuilt/components/Leave/LeaveRoom.d.ts +2 -1
  21. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +2 -3
  22. package/dist/Prebuilt/components/MwebLandscapePrompt.d.ts +1 -1
  23. package/dist/Prebuilt/components/RaiseHand.d.ts +5 -0
  24. package/dist/Prebuilt/components/SidePaneTabs.d.ts +1 -1
  25. package/dist/Sheet/Sheet.d.ts +1 -0
  26. package/dist/{chunk-ERIM35YN.js → chunk-YFJQ4B6X.js} +1544 -1174
  27. package/dist/chunk-YFJQ4B6X.js.map +7 -0
  28. package/dist/index.cjs.js +2727 -1899
  29. package/dist/index.cjs.js.map +4 -4
  30. package/dist/index.js +1 -1
  31. package/dist/meta.cjs.json +777 -290
  32. package/dist/meta.esbuild.json +798 -299
  33. package/package.json +7 -6
  34. package/src/Button/Button.tsx +4 -4
  35. package/src/Fieldset/Fieldset.tsx +1 -1
  36. package/src/Input/PasswordInput.stories.tsx +1 -1
  37. package/src/Pagination/StyledPagination.stories.tsx +2 -2
  38. package/src/Prebuilt/IconButton.tsx +1 -1
  39. package/src/Prebuilt/common/hooks.ts +21 -0
  40. package/src/Prebuilt/components/AppData/useSidepane.js +34 -7
  41. package/src/Prebuilt/components/AuthToken.jsx +1 -1
  42. package/src/Prebuilt/components/Chat/Chat.tsx +41 -1
  43. package/src/Prebuilt/components/Chat/ChatFooter.tsx +33 -13
  44. package/src/Prebuilt/components/Chat/MwebChatOption.tsx +1 -1
  45. package/src/Prebuilt/components/ConferenceScreen.tsx +48 -7
  46. package/src/Prebuilt/components/EmojiReaction.jsx +33 -23
  47. package/src/Prebuilt/components/Footer/Footer.tsx +0 -1
  48. package/src/Prebuilt/components/Footer/RoleOptions.tsx +141 -125
  49. package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -1
  50. package/src/Prebuilt/components/HMSVideo/FullscreenButton.tsx +13 -0
  51. package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.tsx +72 -0
  52. package/src/Prebuilt/components/HMSVideo/HLSCaptionSelector.tsx +4 -2
  53. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.tsx +248 -0
  54. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +18 -7
  55. package/src/Prebuilt/components/HMSVideo/MwebHLSViewTitle.tsx +84 -0
  56. package/src/Prebuilt/components/HMSVideo/PlayButton.tsx +27 -0
  57. package/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx +27 -0
  58. package/src/Prebuilt/components/HMSVideo/PlayerContext.tsx +15 -0
  59. package/src/Prebuilt/components/HMSVideo/SeekControls.tsx +22 -0
  60. package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +95 -0
  61. package/src/Prebuilt/components/HMSVideo/VideoTime.tsx +43 -0
  62. package/src/Prebuilt/components/HMSVideo/{VolumeControl.jsx → VolumeControl.tsx} +6 -4
  63. package/src/Prebuilt/components/HMSVideo/{index.js → index.ts} +6 -2
  64. package/src/Prebuilt/components/HMSVideo/{HMSVIdeoUtils.js → utils.ts} +5 -5
  65. package/src/Prebuilt/components/Header/StreamActions.tsx +1 -1
  66. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +1 -1
  67. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +50 -46
  68. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +15 -4
  69. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +46 -27
  70. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +3 -1
  71. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +37 -31
  72. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +12 -8
  73. package/src/Prebuilt/components/MwebLandscapePrompt.tsx +14 -3
  74. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +5 -2
  75. package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -1
  76. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +19 -8
  77. package/src/Prebuilt/components/Polls/Voting/Voting.tsx +3 -2
  78. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.tsx +1 -1
  79. package/src/Prebuilt/components/Polls/common/utils.ts +2 -2
  80. package/src/Prebuilt/components/RaiseHand.tsx +24 -0
  81. package/src/Prebuilt/components/RoomDetails/RoomDetailsPane.tsx +41 -14
  82. package/src/Prebuilt/components/SidePaneTabs.tsx +56 -48
  83. package/src/Prebuilt/components/StatsForNerds.jsx +14 -6
  84. package/src/Prebuilt/components/Streaming/Common.jsx +1 -1
  85. package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +2 -2
  86. package/src/Prebuilt/components/Toast/ToastBatcher.js +8 -1
  87. package/src/Prebuilt/components/Toast/ToastConfig.jsx +17 -0
  88. package/src/Prebuilt/components/pdfAnnotator/shareScreenOptions.jsx +2 -2
  89. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +1 -1
  90. package/src/Prebuilt/layouts/HLSView.jsx +379 -179
  91. package/src/Prebuilt/layouts/SidePane.tsx +145 -59
  92. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +22 -2
  93. package/src/Prebuilt/primitives/DialogContent.jsx +1 -1
  94. package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +1 -1
  95. package/src/Sheet/Sheet.tsx +7 -3
  96. package/dist/HLSView-SJCF34GE.js +0 -987
  97. package/dist/HLSView-SJCF34GE.js.map +0 -7
  98. package/dist/chunk-ERIM35YN.js.map +0 -7
  99. package/src/Prebuilt/components/HMSVideo/FullscreenButton.jsx +0 -18
  100. package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.jsx +0 -35
  101. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +0 -127
  102. package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +0 -13
  103. package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +0 -76
  104. package/src/Prebuilt/components/HMSVideo/VideoTime.jsx +0 -33
  105. package/src/Prebuilt/components/RaiseHand.jsx +0 -17
@@ -3,6 +3,7 @@ import { useFullscreen, useMedia, usePrevious, useToggle } from 'react-use';
3
3
  import { HLSPlaybackState, HMSHLSPlayer, HMSHLSPlayerEvents } from '@100mslive/hls-player';
4
4
  import screenfull from 'screenfull';
5
5
  import {
6
+ HLSPlaylistType,
6
7
  HMSNotificationTypes,
7
8
  selectAppData,
8
9
  selectHLSState,
@@ -13,61 +14,84 @@ import {
13
14
  useHMSStore,
14
15
  useHMSVanillaStore,
15
16
  } from '@100mslive/react-sdk';
16
- import { ColoredHandIcon, ExpandIcon, GoLiveIcon, PlayIcon, ShrinkIcon } from '@100mslive/react-icons';
17
+ import { BackwardArrowIcon, ColoredHandIcon, ForwardArrowIcon, GoLiveIcon } from '@100mslive/react-icons';
18
+ import { ChatToggle } from '../components/Footer/ChatToggle';
17
19
  import { HlsStatsOverlay } from '../components/HlsStatsOverlay';
18
20
  import { HMSVideoPlayer } from '../components/HMSVideo';
19
21
  import { FullScreenButton } from '../components/HMSVideo/FullscreenButton';
20
22
  import { HLSAutoplayBlockedPrompt } from '../components/HMSVideo/HLSAutoplayBlockedPrompt';
21
23
  import { HLSCaptionSelector } from '../components/HMSVideo/HLSCaptionSelector';
22
24
  import { HLSQualitySelector } from '../components/HMSVideo/HLSQualitySelector';
25
+ import { HLSViewTitle } from '../components/HMSVideo/MwebHLSViewTitle';
26
+ import { HMSPlayerContext } from '../components/HMSVideo/PlayerContext';
27
+ import { LeaveRoom } from '../components/Leave/LeaveRoom';
23
28
  import { ToastManager } from '../components/Toast/ToastManager';
24
29
  import { Button } from '../../Button';
25
30
  import { IconButton } from '../../IconButton';
26
31
  import { Box, Flex } from '../../Layout';
27
32
  import { Loading } from '../../Loading';
28
33
  import { Text } from '../../Text';
29
- import { config, useTheme } from '../../Theme';
34
+ import { config, theme, useTheme } from '../../Theme';
30
35
  import { Tooltip } from '../../Tooltip';
31
- import { usePollViewToggle } from '../components/AppData/useSidepane';
32
- import { APP_DATA, EMOJI_REACTION_TYPE } from '../common/constants';
36
+ import { useSidepaneToggle } from '../components/AppData/useSidepane';
37
+ import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
38
+ import { useIsLandscape } from '../common/hooks';
39
+ import { APP_DATA, EMOJI_REACTION_TYPE, POLL_STATE, POLL_VIEWS, SIDE_PANE_OPTIONS } from '../common/constants';
33
40
 
34
41
  let hlsPlayer;
35
42
  const toastMap = {};
36
43
 
44
+ const ToggleChat = () => {
45
+ const { elements } = useRoomLayoutConferencingScreen();
46
+ const sidepane = useHMSStore(selectAppData(APP_DATA.sidePane));
47
+ const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
48
+ const showChat = !!elements?.chat;
49
+ const isMobile = useMedia(config.media.md);
50
+ useEffect(() => {
51
+ if (!sidepane && isMobile && showChat) {
52
+ toggleChat();
53
+ }
54
+ }, [sidepane, isMobile, toggleChat, showChat]);
55
+ return null;
56
+ };
37
57
  const HLSView = () => {
38
58
  const videoRef = useRef(null);
39
- const hlsViewRef = useRef(null);
59
+ const hlsViewRef = useRef();
40
60
  const hlsState = useHMSStore(selectHLSState);
41
61
  const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats));
42
62
  const notification = useHMSNotifications(HMSNotificationTypes.POLL_STOPPED);
43
63
  const hmsActions = useHMSActions();
44
- const { themeType, theme } = useTheme();
64
+ const { themeType } = useTheme();
45
65
  const [streamEnded, setStreamEnded] = useState(false);
46
66
  let [hlsStatsState, setHlsStatsState] = useState(null);
47
67
  const hlsUrl = hlsState.variants[0]?.url;
48
68
  const [availableLayers, setAvailableLayers] = useState([]);
49
69
  const [isVideoLive, setIsVideoLive] = useState(true);
50
- const [isUserSelectedAuto, setIsUserSelectedAuto] = useState(true);
51
70
  const [isCaptionEnabled, setIsCaptionEnabled] = useState(true);
52
71
  const [hasCaptions, setHasCaptions] = useState(false);
53
72
  const [currentSelectedQuality, setCurrentSelectedQuality] = useState(null);
54
73
  const [isHlsAutoplayBlocked, setIsHlsAutoplayBlocked] = useState(false);
74
+ const [isSeekEnabled, setIsSeekEnabled] = useState(false);
55
75
  const [isPaused, setIsPaused] = useState(false);
56
- const isFullScreenSupported = screenfull.isEnabled;
57
76
  const [show, toggle] = useToggle(false);
58
- const [controlsVisible, setControlsVisible] = useState(true);
59
- const controlsRef = useRef();
60
- const controlsTimerRef = useRef();
61
- const [qualityDropDownOpen, setQualityDropDownOpen] = useState(false);
62
77
  const lastHlsUrl = usePrevious(hlsUrl);
63
- const togglePollView = usePollViewToggle();
64
78
  const vanillaStore = useHMSVanillaStore();
79
+ const [controlsVisible, setControlsVisible] = useState(true);
80
+ const [isUserSelectedAuto, setIsUserSelectedAuto] = useState(true);
81
+ const [qualityDropDownOpen, setQualityDropDownOpen] = useState(false);
82
+ const controlsRef = useRef(null);
83
+ const controlsTimerRef = useRef();
84
+ const [seekProgress, setSeekProgress] = useState(false);
85
+ const isFullScreenSupported = screenfull.isEnabled;
65
86
 
66
87
  const isMobile = useMedia(config.media.md);
88
+ const isLandscape = useIsLandscape();
89
+
67
90
  const isFullScreen = useFullscreen(hlsViewRef, show, {
68
91
  onClose: () => toggle(false),
69
92
  });
70
93
  const [showLoader, setShowLoader] = useState(false);
94
+
71
95
  // FIXME: move this logic to player controller in next release
72
96
  useEffect(() => {
73
97
  /**
@@ -111,6 +135,15 @@ const HLSView = () => {
111
135
  };
112
136
  }, [hlsUrl]);
113
137
 
138
+ const handleQuality = useCallback(
139
+ quality => {
140
+ if (hlsPlayer) {
141
+ setIsUserSelectedAuto(quality.height?.toString().toLowerCase() === 'auto');
142
+ hlsPlayer?.setLayer(quality);
143
+ }
144
+ },
145
+ [availableLayers], //eslint-disable-line
146
+ );
114
147
  /**
115
148
  * initialize HMSHLSPlayer and add event listeners.
116
149
  */
@@ -139,25 +172,32 @@ const HLSView = () => {
139
172
  const poll = vanillaStore.getState(selectPollByID(pollId));
140
173
  const pollStartedBy = vanillaStore.getState(selectPeerNameByID(poll.startedBy)) || 'Participant';
141
174
  // launch poll
142
- const toastID = ToastManager.addToast({
143
- title: `${pollStartedBy} started a ${poll.type}: ${poll.title}`,
144
- action: (
145
- <Button
146
- onClick={() => togglePollView(pollId)}
147
- variant="standard"
148
- css={{
149
- backgroundColor: '$surface_bright',
150
- fontWeight: '$semiBold',
151
- color: '$on_surface_high',
152
- p: '$xs $md',
153
- }}
154
- >
155
- {poll.type === 'quiz' ? 'Answer' : 'Vote'}
156
- </Button>
157
- ),
158
- duration: Infinity,
159
- });
160
- toastMap[pollId] = toastID;
175
+ if (!toastMap[pollId]) {
176
+ const toastID = ToastManager.addToast({
177
+ title: `${pollStartedBy} started a ${poll.type}: ${poll.title}`,
178
+ action: (
179
+ <Button
180
+ onClick={() => {
181
+ hmsActions.setAppData({
182
+ [POLL_STATE.pollInView]: pollId,
183
+ [POLL_STATE.view]: POLL_VIEWS.VOTE,
184
+ });
185
+ }}
186
+ variant="standard"
187
+ css={{
188
+ backgroundColor: '$surface_bright',
189
+ fontWeight: '$semiBold',
190
+ color: '$on_surface_high',
191
+ p: '$xs $md',
192
+ }}
193
+ >
194
+ {poll.type === 'quiz' ? 'Answer' : 'Vote'}
195
+ </Button>
196
+ ),
197
+ duration: Infinity,
198
+ });
199
+ toastMap[pollId] = toastID;
200
+ }
161
201
  return;
162
202
  }
163
203
  switch (parsedPayload.type) {
@@ -210,10 +250,9 @@ const HLSView = () => {
210
250
  hlsPlayer.off(HMSHLSPlayerEvents.MANIFEST_LOADED, manifestLoadedHandler);
211
251
  hlsPlayer.off(HMSHLSPlayerEvents.LAYER_UPDATED, layerUpdatedHandler);
212
252
  hlsPlayer.reset();
213
- hlsPlayer = null;
214
253
  };
215
254
  }
216
- }, [hlsUrl]);
255
+ }, [hlsUrl, vanillaStore, hmsActions]);
217
256
 
218
257
  /**
219
258
  * initialize and subscribe to hlsState
@@ -239,16 +278,6 @@ const HLSView = () => {
239
278
  }
240
279
  };
241
280
 
242
- const handleQuality = useCallback(
243
- quality => {
244
- if (hlsPlayer) {
245
- setIsUserSelectedAuto(quality.height.toString().toLowerCase() === 'auto');
246
- hlsPlayer.setLayer(quality);
247
- }
248
- },
249
- [availableLayers], //eslint-disable-line
250
- );
251
-
252
281
  const sfnOverlayClose = () => {
253
282
  hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats);
254
283
  };
@@ -258,62 +287,150 @@ const HLSView = () => {
258
287
  if (controlsTimerRef.current) {
259
288
  clearTimeout(controlsTimerRef.current);
260
289
  }
261
- controlsTimerRef.current = setTimeout(() => {
262
- setControlsVisible(false);
263
- }, 5000);
264
290
  }
265
291
  if (!isFullScreen && controlsTimerRef.current) {
266
292
  clearTimeout(controlsTimerRef.current);
267
293
  }
294
+ controlsTimerRef.current = setTimeout(() => {
295
+ if (!seekProgress) {
296
+ setControlsVisible(false);
297
+ }
298
+ }, 5000);
268
299
  return () => {
269
300
  if (controlsTimerRef.current) {
270
301
  clearTimeout(controlsTimerRef.current);
271
302
  }
272
303
  };
273
- }, [controlsVisible, isFullScreen, qualityDropDownOpen]);
304
+ }, [controlsVisible, isFullScreen, seekProgress, qualityDropDownOpen]);
274
305
 
306
+ const onSeekTo = useCallback(seek => {
307
+ hlsPlayer?.seekTo(videoRef.current?.currentTime + seek);
308
+ }, []);
309
+ const onDoubleClickHandler = useCallback(
310
+ event => {
311
+ if (!(isMobile || isLandscape) || hlsState?.variants[0]?.playlist_type !== HLSPlaylistType.DVR) {
312
+ return;
313
+ }
314
+ const sidePercentage = (event.screenX * 100) / event.target.clientWidth;
315
+ setIsSeekEnabled(true);
316
+ // there is space for pause/unpause button
317
+ if (sidePercentage < 45) {
318
+ onSeekTo(-10);
319
+ } else {
320
+ onSeekTo(10);
321
+ }
322
+ setTimeout(() => {
323
+ setIsSeekEnabled(false);
324
+ }, 200);
325
+ },
326
+ [hlsState?.variants, isLandscape, isMobile, onSeekTo],
327
+ );
328
+ const onClickHandler = useCallback(() => {
329
+ if (!(isMobile || isLandscape)) {
330
+ return;
331
+ }
332
+ setControlsVisible(value => !value);
333
+ if (controlsTimerRef.current) {
334
+ clearTimeout(controlsTimerRef.current);
335
+ }
336
+ }, [isLandscape, isMobile]);
275
337
  const onHoverHandler = useCallback(
276
338
  event => {
339
+ event.preventDefault();
340
+ if (isMobile || isLandscape) {
341
+ return;
342
+ }
277
343
  if (event.type === 'mouseenter' || qualityDropDownOpen) {
278
344
  setControlsVisible(true);
279
345
  return;
280
346
  }
281
- if (event.type === 'mouseleave') {
347
+ if (event.type === 'mouseleave' && !seekProgress) {
282
348
  setControlsVisible(false);
283
- } else if (isFullScreen && !controlsVisible && event.type === 'mousemove') {
349
+ } else if (!controlsVisible && event.type === 'mousemove') {
284
350
  setControlsVisible(true);
285
351
  if (controlsTimerRef.current) {
286
352
  clearTimeout(controlsTimerRef.current);
287
353
  }
288
354
  }
289
355
  },
290
- [controlsVisible, isFullScreen, qualityDropDownOpen],
356
+ [controlsVisible, isLandscape, isMobile, qualityDropDownOpen, seekProgress],
291
357
  );
292
358
 
359
+ if (!hlsUrl || streamEnded) {
360
+ return (
361
+ <>
362
+ <ToggleChat />
363
+ {hlsViewRef.current && (isMobile || isLandscape) && (
364
+ <Box css={{ position: 'fixed', left: '$4', top: '$4', zIndex: 11 }}>
365
+ <LeaveRoom screenType="hls_live_streaming" container={hlsViewRef.current} />
366
+ </Box>
367
+ )}
368
+ <Flex
369
+ key="hls-viewer"
370
+ id={`hls-viewer-${themeType}`}
371
+ ref={hlsViewRef}
372
+ direction={isMobile || isLandscape ? 'column' : 'row'}
373
+ justify="center"
374
+ css={{
375
+ flex: isLandscape ? '2 1 0' : '1 1 0',
376
+ }}
377
+ >
378
+ <Flex align="center" justify="center" direction="column" css={{ size: '100%', px: '$10' }}>
379
+ <Flex css={{ c: '$on_surface_high', r: '$round', bg: '$surface_default', p: '$2' }}>
380
+ {streamEnded ? <ColoredHandIcon height={56} width={56} /> : <GoLiveIcon height={56} width={56} />}
381
+ </Flex>
382
+ <Text variant="h5" css={{ c: '$on_surface_high', mt: '$10', mb: 0, textAlign: 'center' }}>
383
+ {streamEnded ? 'Stream has ended' : 'Stream yet to start'}
384
+ </Text>
385
+ <Text variant="md" css={{ textAlign: 'center', mt: '$4', c: '$on_surface_medium' }}>
386
+ {streamEnded ? 'Have a nice day!' : 'Sit back and relax'}
387
+ </Text>
388
+ </Flex>
389
+ </Flex>
390
+ </>
391
+ );
392
+ }
293
393
  return (
294
394
  <Flex
295
395
  key="hls-viewer"
296
396
  id={`hls-viewer-${themeType}`}
297
397
  ref={hlsViewRef}
398
+ direction={isMobile || isLandscape ? 'column' : 'row'}
399
+ justify="center"
298
400
  css={{
299
- size: '100%',
401
+ flex: isLandscape ? '2 1 0' : '1 1 0',
402
+ '&:fullscreen': {
403
+ '& video': {
404
+ height: 'unset !important',
405
+ },
406
+ },
300
407
  }}
301
408
  >
302
- {hlsStatsState?.url && enablHlsStats ? (
303
- <HlsStatsOverlay hlsStatsState={hlsStatsState} onClose={sfnOverlayClose} />
304
- ) : null}
305
- {hlsUrl && !streamEnded ? (
409
+ {hlsViewRef.current && (isMobile || isLandscape) && (
410
+ <Box css={{ position: 'fixed', left: '$4', top: '$4', zIndex: 11 }}>
411
+ <LeaveRoom screenType="hls_live_streaming" container={hlsViewRef.current} />
412
+ </Box>
413
+ )}
414
+
415
+ <HMSPlayerContext.Provider value={{ hlsPlayer }}>
416
+ {hlsStatsState?.url && enablHlsStats && !(isMobile || isLandscape) ? (
417
+ <HlsStatsOverlay hlsStatsState={hlsStatsState} onClose={sfnOverlayClose} />
418
+ ) : null}
306
419
  <Flex
307
420
  id="hls-player-container"
308
421
  align="center"
309
422
  justify="center"
310
423
  css={{
311
- width: '100%',
424
+ size: '100%',
312
425
  margin: '0 auto',
313
- height: '100%',
426
+ '@md': {
427
+ height: 'auto',
428
+ },
314
429
  }}
315
430
  >
316
- <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
431
+ {!(isMobile || isLandscape) && (
432
+ <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
433
+ )}
317
434
  {showLoader && (
318
435
  <Flex
319
436
  align="center"
@@ -330,135 +447,218 @@ const HLSView = () => {
330
447
  onMouseEnter={onHoverHandler}
331
448
  onMouseMove={onHoverHandler}
332
449
  onMouseLeave={onHoverHandler}
450
+ onClick={onClickHandler}
451
+ onDoubleClick={e => {
452
+ onDoubleClickHandler(e);
453
+ }}
333
454
  >
334
- {isMobile && isPaused && (
335
- <Box
336
- css={{
337
- position: 'absolute',
338
- top: '40%',
339
- left: '50%',
340
- transform: 'translateY(-40%) translateX(-50%)',
341
- padding: '$8 14px $8 18px',
342
- display: 'inline-flex',
343
- r: '50%',
344
- gap: '$1',
345
- bg: '$primary_default',
346
- zIndex: 21,
347
- }}
348
- >
349
- <IconButton onClick={async () => await hlsPlayer?.play()} data-testid="play_btn">
350
- <PlayIcon width="60px" height="60px" />
351
- </IconButton>
352
- </Box>
353
- )}
354
- <Flex
355
- ref={controlsRef}
356
- direction="column"
357
- justify="flex-end"
358
- align="flex-start"
359
- css={{
360
- position: 'absolute',
361
- bottom: '0',
362
- left: '0',
363
- background: `linear-gradient(180deg, ${theme.colors.background_dim.value}00 29.46%, ${theme.colors.background_dim.value}A3 100%);`,
364
- width: '100%',
365
- pt: '$8',
366
- flexShrink: 0,
367
- transition: 'visibility 0s 0.5s, opacity 0.5s linear',
368
- visibility: controlsVisible ? `` : `hidden`,
369
- opacity: controlsVisible ? `1` : '0',
370
- }}
371
- >
372
- {!isMobile && (
373
- <HMSVideoPlayer.Controls.Root
374
- css={{
375
- p: '$4 $8',
376
- }}
377
- >
378
- <HMSVideoPlayer.Controls.Left>
379
- <HMSVideoPlayer.PlayButton
380
- onClick={async () => {
381
- isPaused ? await hlsPlayer?.play() : hlsPlayer?.pause();
455
+ <>
456
+ {isMobile || isLandscape ? (
457
+ <>
458
+ {!showLoader && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR && (
459
+ <Flex
460
+ align="center"
461
+ justify="center"
462
+ css={{
463
+ position: 'absolute',
464
+ bg: '#00000066',
465
+ display: 'inline-flex',
466
+ gap: '$2',
467
+ zIndex: 1,
468
+ size: '100%',
469
+ visibility: controlsVisible ? `` : `hidden`,
470
+ opacity: controlsVisible ? `1` : '0',
382
471
  }}
383
- isPaused={isPaused}
384
- />
385
- <HMSVideoPlayer.Duration hlsPlayer={hlsPlayer} />
386
- <HMSVideoPlayer.Volume hlsPlayer={hlsPlayer} />
387
- <IconButton
388
- variant="standard"
389
- css={{ px: '$2' }}
390
- onClick={async () => {
391
- await hlsPlayer.seekToLivePosition();
392
- setIsVideoLive(true);
472
+ >
473
+ <HMSVideoPlayer.Seeker
474
+ title="backward"
475
+ css={{
476
+ visibility: isSeekEnabled ? `` : `hidden`,
477
+ opacity: isSeekEnabled ? `1` : '0',
478
+ }}
479
+ >
480
+ <BackwardArrowIcon width={32} height={32} />
481
+ </HMSVideoPlayer.Seeker>
482
+ <Box
483
+ css={{
484
+ bg: 'rgba(0, 0, 0, 0.6)',
485
+ r: '$round',
486
+ }}
487
+ >
488
+ <HMSVideoPlayer.PlayPauseButton isPaused={isPaused} width={48} height={48} />
489
+ </Box>
490
+ <HMSVideoPlayer.Seeker
491
+ title="forward"
492
+ css={{
493
+ visibility: isSeekEnabled ? `` : `hidden`,
494
+ opacity: isSeekEnabled ? `1` : '0',
495
+ }}
496
+ >
497
+ <ForwardArrowIcon width={32} height={32} />
498
+ </HMSVideoPlayer.Seeker>
499
+ </Flex>
500
+ )}
501
+ <Flex
502
+ ref={controlsRef}
503
+ direction="column"
504
+ justify="start"
505
+ align="start"
506
+ css={{
507
+ position: 'absolute',
508
+ top: '0',
509
+ left: '0',
510
+ width: '100%',
511
+ flexShrink: 0,
512
+ zIndex: 1,
513
+ visibility: controlsVisible ? `` : `hidden`,
514
+ opacity: controlsVisible ? `1` : '0',
515
+ }}
516
+ >
517
+ <HMSVideoPlayer.Controls.Root
518
+ css={{
519
+ p: '$4 $8',
393
520
  }}
394
- key="jump-to-live_btn"
395
- data-testid="jump-to-live_btn"
396
521
  >
397
- <Tooltip title="Go to Live" side="top">
398
- <Flex justify="center" gap={2} align="center">
399
- <Box
400
- css={{
401
- height: '$4',
402
- width: '$4',
403
- background: isVideoLive ? '$alert_error_default' : '$on_primary_medium',
404
- r: '$1',
405
- }}
522
+ <HMSVideoPlayer.Controls.Right>
523
+ {isLandscape && <ChatToggle />}
524
+ {hasCaptions && !isHlsAutoplayBlocked && <HLSCaptionSelector isEnabled={isCaptionEnabled} />}
525
+ {hlsViewRef.current && availableLayers.length > 0 && !isHlsAutoplayBlocked ? (
526
+ <HLSQualitySelector
527
+ layers={availableLayers}
528
+ onOpenChange={setQualityDropDownOpen}
529
+ open={qualityDropDownOpen}
530
+ selection={currentSelectedQuality}
531
+ onQualityChange={handleQuality}
532
+ isAuto={isUserSelectedAuto}
533
+ containerRef={hlsViewRef.current}
406
534
  />
407
- <Text
408
- variant={{
409
- '@sm': 'xs',
410
- }}
411
- css={{
412
- c: isVideoLive ? '$on_surface_high' : '$on_surface_medium',
413
- }}
414
- >
415
- {isVideoLive ? 'LIVE' : 'GO LIVE'}
416
- </Text>
417
- </Flex>
418
- </Tooltip>
419
- </IconButton>
420
- </HMSVideoPlayer.Controls.Left>
535
+ ) : null}
536
+ <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
537
+ </HMSVideoPlayer.Controls.Right>
538
+ </HMSVideoPlayer.Controls.Root>
539
+ </Flex>
540
+ </>
541
+ ) : null}
542
+ {controlsVisible && (
543
+ <Flex
544
+ ref={controlsRef}
545
+ direction={isMobile ? 'columnReverse' : 'column'}
546
+ justify="end"
547
+ align="start"
548
+ css={{
549
+ position: 'absolute',
550
+ bottom: isFullScreen && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? '$8' : '0',
551
+ left: '0',
552
+ zIndex: 1,
553
+ background:
554
+ isMobile || isLandscape
555
+ ? ''
556
+ : `linear-gradient(180deg, ${theme.colors.background_dim.value}00 29.46%, ${theme.colors.background_dim.value}A3 100%);`,
557
+ width: '100%',
558
+ pt: '$8',
559
+ flexShrink: 0,
560
+ transition: 'visibility 0s 0.5s, opacity 0.5s linear',
561
+ }}
562
+ >
563
+ {hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
564
+ <HMSVideoPlayer.Progress seekProgress={seekProgress} setSeekProgress={setSeekProgress} />
565
+ ) : null}
566
+ <HMSVideoPlayer.Controls.Root
567
+ css={{
568
+ p: '$4 $8',
569
+ }}
570
+ >
571
+ <HMSVideoPlayer.Controls.Left>
572
+ {!(isMobile || isLandscape) && (
573
+ <>
574
+ {hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
575
+ <>
576
+ <HMSVideoPlayer.Seeker
577
+ onClick={() => {
578
+ onSeekTo(-10);
579
+ }}
580
+ title="backward"
581
+ >
582
+ <BackwardArrowIcon width={20} height={20} />
583
+ </HMSVideoPlayer.Seeker>
584
+ <HMSVideoPlayer.PlayPauseButton isPaused={isPaused} />
585
+ <HMSVideoPlayer.Seeker
586
+ onClick={() => {
587
+ onSeekTo(10);
588
+ }}
589
+ title="forward"
590
+ >
591
+ <ForwardArrowIcon width={20} height={20} />
592
+ </HMSVideoPlayer.Seeker>
593
+ {!isVideoLive ? <HMSVideoPlayer.Duration /> : null}
594
+ </>
595
+ ) : null}
596
+ <HMSVideoPlayer.Volume />
597
+ </>
598
+ )}
599
+ <IconButton
600
+ css={{ px: '$2' }}
601
+ onClick={async () => {
602
+ await hlsPlayer?.seekToLivePosition();
603
+ setIsVideoLive(true);
604
+ }}
605
+ key="jump-to-live_btn"
606
+ data-testid="jump-to-live_btn"
607
+ >
608
+ <Tooltip title={isVideoLive ? 'Live' : 'Go to Live'} side="top">
609
+ <Flex justify="center" gap={2} align="center">
610
+ <Box
611
+ css={{
612
+ height: '$4',
613
+ width: '$4',
614
+ background: isVideoLive ? '$alert_error_default' : '$on_primary_medium',
615
+ r: '$1',
616
+ }}
617
+ />
618
+ <Text
619
+ variant="$body1"
620
+ css={{
621
+ c: isVideoLive ? '$on_surface_high' : '$on_surface_medium',
622
+ fontWeight: '$semiBold',
623
+ }}
624
+ >
625
+ {isVideoLive ? 'LIVE' : 'GO LIVE'}
626
+ </Text>
627
+ </Flex>
628
+ </Tooltip>
629
+ </IconButton>
630
+ {(isMobile || isLandscape) &&
631
+ !isVideoLive &&
632
+ hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
633
+ <HMSVideoPlayer.Duration />
634
+ ) : null}
635
+ </HMSVideoPlayer.Controls.Left>
421
636
 
422
- <HMSVideoPlayer.Controls.Right>
423
- {hasCaptions && (
424
- <HLSCaptionSelector onClick={() => hlsPlayer?.toggleCaption()} isEnabled={isCaptionEnabled} />
425
- )}
426
- {availableLayers.length > 0 ? (
427
- <HLSQualitySelector
428
- layers={availableLayers}
429
- onOpen={setQualityDropDownOpen}
430
- open={qualityDropDownOpen}
431
- selection={currentSelectedQuality}
432
- onQualityChange={handleQuality}
433
- isAuto={isUserSelectedAuto}
434
- />
435
- ) : null}
436
- {isFullScreenSupported ? (
437
- <FullScreenButton
438
- isFullScreen={isFullScreen}
439
- onToggle={toggle}
440
- icon={isFullScreen ? <ShrinkIcon /> : <ExpandIcon />}
441
- />
442
- ) : null}
443
- </HMSVideoPlayer.Controls.Right>
444
- </HMSVideoPlayer.Controls.Root>
637
+ <HMSVideoPlayer.Controls.Right>
638
+ {hasCaptions && !(isMobile || isLandscape) && <HLSCaptionSelector isEnabled={isCaptionEnabled} />}
639
+ {availableLayers.length > 0 && !(isMobile || isLandscape) ? (
640
+ <HLSQualitySelector
641
+ layers={availableLayers}
642
+ onOpenChange={setQualityDropDownOpen}
643
+ open={qualityDropDownOpen}
644
+ selection={currentSelectedQuality}
645
+ onQualityChange={handleQuality}
646
+ isAuto={isUserSelectedAuto}
647
+ />
648
+ ) : null}
649
+ {isFullScreenSupported ? (
650
+ <FullScreenButton isFullScreen={isFullScreen} onToggle={toggle} />
651
+ ) : null}
652
+ </HMSVideoPlayer.Controls.Right>
653
+ </HMSVideoPlayer.Controls.Root>
654
+ </Flex>
445
655
  )}
446
- </Flex>
656
+ </>
447
657
  </HMSVideoPlayer.Root>
448
658
  </Flex>
449
- ) : (
450
- <Flex align="center" justify="center" direction="column" css={{ size: '100%', px: '$10' }}>
451
- <Flex css={{ c: '$on_surface_high', r: '$round', bg: '$surface_default', p: '$2' }}>
452
- {streamEnded ? <ColoredHandIcon height={56} width={56} /> : <GoLiveIcon height={56} width={56} />}
453
- </Flex>
454
- <Text variant="h5" css={{ c: '$on_surface_high', mt: '$10', mb: 0, textAlign: 'center' }}>
455
- {streamEnded ? 'Stream has ended' : 'Stream yet to start'}
456
- </Text>
457
- <Text variant="md" css={{ textAlign: 'center', mt: '$4', c: '$on_surface_medium' }}>
458
- {streamEnded ? 'Have a nice day!' : 'Sit back and relax'}
459
- </Text>
460
- </Flex>
461
- )}
659
+ </HMSPlayerContext.Provider>
660
+ <ToggleChat />
661
+ {isMobile && !isFullScreen && <HLSViewTitle />}
462
662
  </Flex>
463
663
  );
464
664
  };