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

Sign up to get free protection for your applications and to get access to all the features.
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
  };