@100mslive/roomkit-react 0.2.8-alpha.8 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. package/dist/{HLSView-6KPQ2KD6.js → HLSView-LZOTIUWE.js} +152 -96
  2. package/dist/HLSView-LZOTIUWE.js.map +7 -0
  3. package/dist/Prebuilt/components/Chat/Chat.d.ts +1 -1
  4. package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +3 -2
  5. package/dist/Prebuilt/components/HMSVideo/index.d.ts +3 -2
  6. package/dist/Prebuilt/components/SidePaneTabs.d.ts +0 -1
  7. package/dist/Prebuilt/layouts/SidePane.d.ts +1 -1
  8. package/dist/{chunk-JQCSGJIR.js → chunk-LCECN6XD.js} +297 -238
  9. package/dist/chunk-LCECN6XD.js.map +7 -0
  10. package/dist/index.cjs.js +446 -332
  11. package/dist/index.cjs.js.map +3 -3
  12. package/dist/index.js +1 -1
  13. package/dist/meta.cjs.json +96 -61
  14. package/dist/meta.esbuild.json +109 -73
  15. package/package.json +6 -6
  16. package/src/Prebuilt/components/Chat/Chat.tsx +23 -4
  17. package/src/Prebuilt/components/Chat/ChatFooter.tsx +2 -2
  18. package/src/Prebuilt/components/Chat/EmptyChat.tsx +5 -1
  19. package/src/Prebuilt/components/ConferenceScreen.tsx +13 -1
  20. package/src/Prebuilt/components/EmojiReaction.jsx +2 -2
  21. package/src/Prebuilt/components/Footer/RoleOptions.tsx +125 -126
  22. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +13 -10
  23. package/src/Prebuilt/components/HMSVideo/MwebHLSViewTitle.tsx +6 -4
  24. package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +38 -25
  25. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +1 -1
  26. package/src/Prebuilt/components/MwebLandscapePrompt.tsx +9 -3
  27. package/src/Prebuilt/components/Polls/common/utils.ts +1 -1
  28. package/src/Prebuilt/components/SidePaneTabs.tsx +1 -4
  29. package/src/Prebuilt/layouts/HLSView.jsx +293 -239
  30. package/src/Prebuilt/layouts/SidePane.tsx +73 -49
  31. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +10 -2
  32. package/dist/HLSView-6KPQ2KD6.js.map +0 -7
  33. package/dist/chunk-JQCSGJIR.js.map +0 -7
@@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  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
+ import { match, P } from 'ts-pattern';
5
6
  import {
6
7
  HLSPlaylistType,
7
8
  HMSNotificationTypes,
@@ -33,20 +34,41 @@ import { Loading } from '../../Loading';
33
34
  import { Text } from '../../Text';
34
35
  import { config, theme, useTheme } from '../../Theme';
35
36
  import { Tooltip } from '../../Tooltip';
36
- import { usePollViewToggle, useSidepaneToggle } from '../components/AppData/useSidepane';
37
+ import { useSidepaneToggle } from '../components/AppData/useSidepane';
37
38
  import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
38
39
  import { useIsLandscape } from '../common/hooks';
39
- import { APP_DATA, EMOJI_REACTION_TYPE, SIDE_PANE_OPTIONS } from '../common/constants';
40
+ import { APP_DATA, EMOJI_REACTION_TYPE, POLL_STATE, POLL_VIEWS, SIDE_PANE_OPTIONS } from '../common/constants';
40
41
 
41
42
  let hlsPlayer;
42
43
  const toastMap = {};
43
44
 
45
+ const ToggleChat = () => {
46
+ const { elements } = useRoomLayoutConferencingScreen();
47
+ const sidepane = useHMSStore(selectAppData(APP_DATA.sidePane));
48
+ const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
49
+ const showChat = !!elements?.chat;
50
+ const isMobile = useMedia(config.media.md);
51
+ const hmsActions = useHMSActions();
52
+
53
+ useEffect(() => {
54
+ match({ sidepane, isMobile, showChat })
55
+ .with({ isMobile: true, showChat: true, sidepane: P.when(value => !value) }, () => {
56
+ toggleChat();
57
+ })
58
+ .with({ showChat: false, isMobile: true, sidepane: SIDE_PANE_OPTIONS.CHAT }, () => {
59
+ hmsActions.setAppData(APP_DATA.sidePane, '');
60
+ })
61
+ .otherwise(() => {
62
+ //do nothing
63
+ });
64
+ }, [sidepane, isMobile, toggleChat, showChat, hmsActions]);
65
+ return null;
66
+ };
44
67
  const HLSView = () => {
45
68
  const videoRef = useRef(null);
46
69
  const hlsViewRef = useRef();
47
70
  const hlsState = useHMSStore(selectHLSState);
48
71
  const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats));
49
- const { elements, screenType } = useRoomLayoutConferencingScreen();
50
72
  const notification = useHMSNotifications(HMSNotificationTypes.POLL_STOPPED);
51
73
  const hmsActions = useHMSActions();
52
74
  const { themeType } = useTheme();
@@ -63,16 +85,13 @@ const HLSView = () => {
63
85
  const [isPaused, setIsPaused] = useState(false);
64
86
  const [show, toggle] = useToggle(false);
65
87
  const lastHlsUrl = usePrevious(hlsUrl);
66
- const togglePollView = usePollViewToggle();
67
88
  const vanillaStore = useHMSVanillaStore();
68
89
  const [controlsVisible, setControlsVisible] = useState(true);
69
90
  const [isUserSelectedAuto, setIsUserSelectedAuto] = useState(true);
70
91
  const [qualityDropDownOpen, setQualityDropDownOpen] = useState(false);
71
92
  const controlsRef = useRef(null);
72
93
  const controlsTimerRef = useRef();
73
- const sidepane = useHMSStore(selectAppData(APP_DATA.sidePane));
74
- const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
75
- const showChat = !!elements?.chat;
94
+ const [seekProgress, setSeekProgress] = useState(false);
76
95
  const isFullScreenSupported = screenfull.isEnabled;
77
96
 
78
97
  const isMobile = useMedia(config.media.md);
@@ -83,13 +102,6 @@ const HLSView = () => {
83
102
  });
84
103
  const [showLoader, setShowLoader] = useState(false);
85
104
 
86
- const isMwebHLSStream = screenType === 'hls_live_streaming' && isMobile;
87
-
88
- useEffect(() => {
89
- if (sidepane === '' && isMwebHLSStream && showChat) {
90
- toggleChat();
91
- }
92
- }, [sidepane, isMwebHLSStream, toggleChat, showChat]);
93
105
  // FIXME: move this logic to player controller in next release
94
106
  useEffect(() => {
95
107
  /**
@@ -175,7 +187,13 @@ const HLSView = () => {
175
187
  title: `${pollStartedBy} started a ${poll.type}: ${poll.title}`,
176
188
  action: (
177
189
  <Button
178
- onClick={() => togglePollView(pollId)}
190
+ onClick={() => {
191
+ hmsActions.setAppData(APP_DATA.pollState, {
192
+ [POLL_STATE.pollInView]: pollId,
193
+ [POLL_STATE.view]: POLL_VIEWS.VOTE,
194
+ });
195
+ hmsActions.setAppData(APP_DATA.sidePane, SIDE_PANE_OPTIONS.POLLS);
196
+ }}
179
197
  variant="standard"
180
198
  css={{
181
199
  backgroundColor: '$surface_bright',
@@ -245,7 +263,7 @@ const HLSView = () => {
245
263
  hlsPlayer.reset();
246
264
  };
247
265
  }
248
- }, [hlsUrl, togglePollView, vanillaStore]);
266
+ }, [hlsUrl, vanillaStore, hmsActions]);
249
267
 
250
268
  /**
251
269
  * initialize and subscribe to hlsState
@@ -285,21 +303,23 @@ const HLSView = () => {
285
303
  clearTimeout(controlsTimerRef.current);
286
304
  }
287
305
  controlsTimerRef.current = setTimeout(() => {
288
- setControlsVisible(false);
306
+ if (!seekProgress) {
307
+ setControlsVisible(false);
308
+ }
289
309
  }, 5000);
290
310
  return () => {
291
311
  if (controlsTimerRef.current) {
292
312
  clearTimeout(controlsTimerRef.current);
293
313
  }
294
314
  };
295
- }, [controlsVisible, isFullScreen, qualityDropDownOpen]);
315
+ }, [controlsVisible, isFullScreen, seekProgress, qualityDropDownOpen]);
296
316
 
297
317
  const onSeekTo = useCallback(seek => {
298
318
  hlsPlayer?.seekTo(videoRef.current?.currentTime + seek);
299
319
  }, []);
300
320
  const onDoubleClickHandler = useCallback(
301
321
  event => {
302
- if (!(isMobile || isLandscape)) {
322
+ if (!(isMobile || isLandscape) || hlsState?.variants[0]?.playlist_type !== HLSPlaylistType.DVR) {
303
323
  return;
304
324
  }
305
325
  const sidePercentage = (event.screenX * 100) / event.target.clientWidth;
@@ -314,7 +334,7 @@ const HLSView = () => {
314
334
  setIsSeekEnabled(false);
315
335
  }, 200);
316
336
  },
317
- [isLandscape, isMobile, onSeekTo],
337
+ [hlsState?.variants, isLandscape, isMobile, onSeekTo],
318
338
  );
319
339
  const onClickHandler = useCallback(() => {
320
340
  if (!(isMobile || isLandscape)) {
@@ -335,251 +355,187 @@ const HLSView = () => {
335
355
  setControlsVisible(true);
336
356
  return;
337
357
  }
338
- if (event.type === 'mouseleave') {
358
+ if (event.type === 'mouseleave' && !seekProgress) {
339
359
  setControlsVisible(false);
340
- } else if (isFullScreen && !controlsVisible && event.type === 'mousemove') {
360
+ } else if (!controlsVisible && event.type === 'mousemove') {
341
361
  setControlsVisible(true);
342
362
  if (controlsTimerRef.current) {
343
363
  clearTimeout(controlsTimerRef.current);
344
364
  }
345
365
  }
346
366
  },
347
- [controlsVisible, isFullScreen, isLandscape, isMobile, qualityDropDownOpen],
367
+ [controlsVisible, isLandscape, isMobile, qualityDropDownOpen, seekProgress],
348
368
  );
349
369
 
370
+ if (!hlsUrl || streamEnded) {
371
+ return (
372
+ <>
373
+ <ToggleChat />
374
+ {hlsViewRef.current && (isMobile || isLandscape) && (
375
+ <Box css={{ position: 'fixed', left: '$4', top: '$4', zIndex: 11 }}>
376
+ <LeaveRoom screenType="hls_live_streaming" container={hlsViewRef.current} />
377
+ </Box>
378
+ )}
379
+ <Flex
380
+ key="hls-viewer"
381
+ id={`hls-viewer-${themeType}`}
382
+ ref={hlsViewRef}
383
+ direction={isMobile || isLandscape ? 'column' : 'row'}
384
+ justify="center"
385
+ css={{
386
+ flex: isLandscape ? '2 1 0' : '1 1 0',
387
+ }}
388
+ >
389
+ <Flex align="center" justify="center" direction="column" css={{ size: '100%', px: '$10' }}>
390
+ <Flex css={{ c: '$on_surface_high', r: '$round', bg: '$surface_default', p: '$2' }}>
391
+ {streamEnded ? <ColoredHandIcon height={56} width={56} /> : <GoLiveIcon height={56} width={56} />}
392
+ </Flex>
393
+ <Text variant="h5" css={{ c: '$on_surface_high', mt: '$10', mb: 0, textAlign: 'center' }}>
394
+ {streamEnded ? 'Stream has ended' : 'Stream yet to start'}
395
+ </Text>
396
+ <Text variant="md" css={{ textAlign: 'center', mt: '$4', c: '$on_surface_medium' }}>
397
+ {streamEnded ? 'Have a nice day!' : 'Sit back and relax'}
398
+ </Text>
399
+ </Flex>
400
+ </Flex>
401
+ </>
402
+ );
403
+ }
350
404
  return (
351
405
  <Flex
352
406
  key="hls-viewer"
353
407
  id={`hls-viewer-${themeType}`}
354
408
  ref={hlsViewRef}
355
409
  direction={isMobile || isLandscape ? 'column' : 'row'}
410
+ justify="center"
356
411
  css={{
357
- w: sidepane !== '' && isLandscape ? '' : '100%',
358
- h: sidepane !== '' && isMobile ? '36%' : '100%',
359
- flex: '1 1 0',
412
+ flex: isLandscape ? '2 1 0' : '1 1 0',
413
+ '&:fullscreen': {
414
+ '& video': {
415
+ height: 'unset !important',
416
+ },
417
+ },
360
418
  }}
361
419
  >
362
- {hlsUrl && !streamEnded ? (
363
- <>
364
- <HMSPlayerContext.Provider value={{ hlsPlayer }}>
365
- {hlsStatsState?.url && enablHlsStats && !(isMobile || isLandscape) ? (
366
- <HlsStatsOverlay hlsStatsState={hlsStatsState} onClose={sfnOverlayClose} />
367
- ) : null}
420
+ {hlsViewRef.current && (isMobile || isLandscape) && (
421
+ <Box css={{ position: 'fixed', left: '$4', top: '$4', zIndex: 11 }}>
422
+ <LeaveRoom screenType="hls_live_streaming" container={hlsViewRef.current} />
423
+ </Box>
424
+ )}
425
+
426
+ <HMSPlayerContext.Provider value={{ hlsPlayer }}>
427
+ {hlsStatsState?.url && enablHlsStats && !(isMobile || isLandscape) ? (
428
+ <HlsStatsOverlay hlsStatsState={hlsStatsState} onClose={sfnOverlayClose} />
429
+ ) : null}
430
+ <Flex
431
+ id="hls-player-container"
432
+ align="center"
433
+ justify="center"
434
+ css={{
435
+ size: '100%',
436
+ margin: '0 auto',
437
+ '@md': {
438
+ height: 'auto',
439
+ },
440
+ }}
441
+ >
442
+ {!(isMobile || isLandscape) && (
443
+ <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
444
+ )}
445
+ {showLoader && (
368
446
  <Flex
369
- id="hls-player-container"
370
447
  align="center"
371
448
  justify="center"
372
449
  css={{
373
- size: '100%',
374
- margin: '0 auto',
450
+ position: 'absolute',
375
451
  }}
376
452
  >
377
- {!(isMobile || isLandscape) && (
378
- <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
379
- )}
380
- {showLoader && (
381
- <Flex
382
- align="center"
383
- justify="center"
384
- css={{
385
- position: 'absolute',
386
- }}
387
- >
388
- <Loading width={72} height={72} />
389
- </Flex>
390
- )}
391
- <HMSVideoPlayer.Root
392
- ref={videoRef}
393
- onMouseEnter={onHoverHandler}
394
- onMouseMove={onHoverHandler}
395
- onMouseLeave={onHoverHandler}
396
- onClick={onClickHandler}
397
- onDoubleClick={e => {
398
- onDoubleClickHandler(e);
399
- }}
400
- >
453
+ <Loading width={72} height={72} />
454
+ </Flex>
455
+ )}
456
+ <HMSVideoPlayer.Root
457
+ ref={videoRef}
458
+ onMouseEnter={onHoverHandler}
459
+ onMouseMove={onHoverHandler}
460
+ onMouseLeave={onHoverHandler}
461
+ onClick={onClickHandler}
462
+ onDoubleClick={e => {
463
+ onDoubleClickHandler(e);
464
+ }}
465
+ >
466
+ <>
467
+ {isMobile || isLandscape ? (
401
468
  <>
402
- {isMobile || isLandscape ? (
403
- <>
404
- {!showLoader && (
405
- <Flex
406
- align="center"
407
- justify="center"
469
+ <Flex
470
+ align="center"
471
+ justify="center"
472
+ css={{
473
+ position: 'absolute',
474
+ bg: '#00000066',
475
+ display: 'inline-flex',
476
+ gap: '$2',
477
+ zIndex: 1,
478
+ size: '100%',
479
+ visibility: controlsVisible ? `` : `hidden`,
480
+ opacity: controlsVisible ? `1` : '0',
481
+ }}
482
+ >
483
+ {!showLoader && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR && (
484
+ <>
485
+ <HMSVideoPlayer.Seeker
486
+ title="backward"
408
487
  css={{
409
- bg: '#00000066',
410
- display: 'inline-flex',
411
- gap: '$2',
412
- zIndex: 1,
413
- size: '100%',
414
- visibility: controlsVisible ? `` : `hidden`,
415
- opacity: controlsVisible ? `1` : '0',
488
+ visibility: isSeekEnabled ? `` : `hidden`,
489
+ opacity: isSeekEnabled ? `1` : '0',
416
490
  }}
417
491
  >
418
- <HMSVideoPlayer.Seeker
419
- title="backward"
420
- css={{
421
- visibility: isSeekEnabled ? `` : `hidden`,
422
- opacity: isSeekEnabled ? `1` : '0',
423
- }}
424
- >
425
- <BackwardArrowIcon width={32} height={32} />
426
- </HMSVideoPlayer.Seeker>
427
- <Box
428
- css={{
429
- bg: 'rgba(0, 0, 0, 0.6)',
430
- r: '$round',
431
- }}
432
- >
433
- <HMSVideoPlayer.PlayPauseButton isPaused={isPaused} width={48} height={48} />
434
- </Box>
435
- <HMSVideoPlayer.Seeker
436
- title="forward"
437
- css={{
438
- visibility: isSeekEnabled ? `` : `hidden`,
439
- opacity: isSeekEnabled ? `1` : '0',
440
- }}
441
- >
442
- <ForwardArrowIcon width={32} height={32} />
443
- </HMSVideoPlayer.Seeker>
444
- </Flex>
445
- )}
446
- <Flex
447
- ref={controlsRef}
448
- direction="column"
449
- justify="start"
450
- align="start"
451
- css={{
452
- position: 'absolute',
453
- top: '0',
454
- left: '0',
455
- width: '100%',
456
- flexShrink: 0,
457
- zIndex: 1,
458
- visibility: controlsVisible ? `` : `hidden`,
459
- opacity: controlsVisible ? `1` : '0',
460
- }}
461
- >
462
- <HMSVideoPlayer.Controls.Root
492
+ <BackwardArrowIcon width={32} height={32} />
493
+ </HMSVideoPlayer.Seeker>
494
+ <Box
463
495
  css={{
464
- p: '$4 $8',
496
+ bg: 'rgba(0, 0, 0, 0.6)',
497
+ r: '$round',
465
498
  }}
466
499
  >
467
- <HMSVideoPlayer.Controls.Left>
468
- {hlsViewRef.current && <LeaveRoom screenType={screenType} container={hlsViewRef.current} />}
469
- </HMSVideoPlayer.Controls.Left>
470
- <HMSVideoPlayer.Controls.Right>
471
- {isLandscape && <ChatToggle />}
472
- {hasCaptions && !isHlsAutoplayBlocked && (
473
- <HLSCaptionSelector isEnabled={isCaptionEnabled} />
474
- )}
475
- {hlsViewRef.current && availableLayers.length > 0 && !isHlsAutoplayBlocked ? (
476
- <HLSQualitySelector
477
- layers={availableLayers}
478
- onOpenChange={setQualityDropDownOpen}
479
- open={qualityDropDownOpen}
480
- selection={currentSelectedQuality}
481
- onQualityChange={handleQuality}
482
- isAuto={isUserSelectedAuto}
483
- containerRef={hlsViewRef.current}
484
- />
485
- ) : null}
486
- <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
487
- </HMSVideoPlayer.Controls.Right>
488
- </HMSVideoPlayer.Controls.Root>
489
- </Flex>
490
- </>
491
- ) : null}
500
+ <HMSVideoPlayer.PlayPauseButton isPaused={isPaused} width={48} height={48} />
501
+ </Box>
502
+ <HMSVideoPlayer.Seeker
503
+ title="forward"
504
+ css={{
505
+ visibility: isSeekEnabled ? `` : `hidden`,
506
+ opacity: isSeekEnabled ? `1` : '0',
507
+ }}
508
+ >
509
+ <ForwardArrowIcon width={32} height={32} />
510
+ </HMSVideoPlayer.Seeker>
511
+ </>
512
+ )}
513
+ </Flex>
492
514
  <Flex
493
515
  ref={controlsRef}
494
- direction={isMobile ? 'columnReverse' : 'column'}
495
- justify="end"
516
+ direction="column"
517
+ justify="start"
496
518
  align="start"
497
519
  css={{
498
520
  position: 'absolute',
499
- bottom: isFullScreen && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? '$8' : '0',
521
+ top: '0',
500
522
  left: '0',
501
- zIndex: 1,
502
- background:
503
- isMobile || isLandscape
504
- ? ''
505
- : `linear-gradient(180deg, ${theme.colors.background_dim.value}00 29.46%, ${theme.colors.background_dim.value}A3 100%);`,
506
523
  width: '100%',
507
- pt: '$8',
508
524
  flexShrink: 0,
509
- transition: 'visibility 0s 0.5s, opacity 0.5s linear',
525
+ zIndex: 1,
510
526
  visibility: controlsVisible ? `` : `hidden`,
511
527
  opacity: controlsVisible ? `1` : '0',
512
528
  }}
513
529
  >
514
- <HMSVideoPlayer.Progress isDvr={hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR} />
515
530
  <HMSVideoPlayer.Controls.Root
516
531
  css={{
517
532
  p: '$4 $8',
518
533
  }}
519
534
  >
520
- <HMSVideoPlayer.Controls.Left>
521
- {!(isMobile || isLandscape) && (
522
- <>
523
- <HMSVideoPlayer.Seeker
524
- onClick={() => {
525
- onSeekTo(-10);
526
- }}
527
- title="backward"
528
- >
529
- <BackwardArrowIcon width={20} height={20} />
530
- </HMSVideoPlayer.Seeker>
531
- <HMSVideoPlayer.PlayPauseButton isPaused={isPaused} />
532
- <HMSVideoPlayer.Seeker
533
- onClick={() => {
534
- onSeekTo(10);
535
- }}
536
- title="forward"
537
- >
538
- <ForwardArrowIcon width={20} height={20} />
539
- </HMSVideoPlayer.Seeker>
540
- {!isVideoLive ? <HMSVideoPlayer.Duration /> : null}
541
- <HMSVideoPlayer.Volume />
542
- </>
543
- )}
544
- <IconButton
545
- css={{ px: '$2' }}
546
- onClick={async () => {
547
- await hlsPlayer?.seekToLivePosition();
548
- setIsVideoLive(true);
549
- }}
550
- key="jump-to-live_btn"
551
- data-testid="jump-to-live_btn"
552
- >
553
- <Tooltip title={isVideoLive ? 'Live' : 'Go to Live'} side="top">
554
- <Flex justify="center" gap={2} align="center">
555
- <Box
556
- css={{
557
- height: '$4',
558
- width: '$4',
559
- background: isVideoLive ? '$alert_error_default' : '$on_primary_medium',
560
- r: '$1',
561
- }}
562
- />
563
- <Text
564
- variant="$body1"
565
- css={{
566
- c: isVideoLive ? '$on_surface_high' : '$on_surface_medium',
567
- fontWeight: '$semiBold',
568
- }}
569
- >
570
- {isVideoLive ? 'LIVE' : 'GO LIVE'}
571
- </Text>
572
- </Flex>
573
- </Tooltip>
574
- </IconButton>
575
- {(isMobile || isLandscape) && !isVideoLive ? <HMSVideoPlayer.Duration /> : null}
576
- </HMSVideoPlayer.Controls.Left>
577
-
578
535
  <HMSVideoPlayer.Controls.Right>
579
- {hasCaptions && !(isMobile || isLandscape) && (
580
- <HLSCaptionSelector isEnabled={isCaptionEnabled} />
581
- )}
582
- {availableLayers.length > 0 && !(isMobile || isLandscape) ? (
536
+ {isLandscape && <ChatToggle />}
537
+ {hasCaptions && !isHlsAutoplayBlocked && <HLSCaptionSelector isEnabled={isCaptionEnabled} />}
538
+ {hlsViewRef.current && availableLayers.length > 0 && !isHlsAutoplayBlocked ? (
583
539
  <HLSQualitySelector
584
540
  layers={availableLayers}
585
541
  onOpenChange={setQualityDropDownOpen}
@@ -587,37 +543,135 @@ const HLSView = () => {
587
543
  selection={currentSelectedQuality}
588
544
  onQualityChange={handleQuality}
589
545
  isAuto={isUserSelectedAuto}
546
+ containerRef={hlsViewRef.current}
590
547
  />
591
548
  ) : null}
592
- {isFullScreenSupported ? (
593
- <FullScreenButton isFullScreen={isFullScreen} onToggle={toggle} />
594
- ) : null}
549
+ <HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
595
550
  </HMSVideoPlayer.Controls.Right>
596
551
  </HMSVideoPlayer.Controls.Root>
597
552
  </Flex>
598
553
  </>
599
- </HMSVideoPlayer.Root>
600
- </Flex>
601
- </HMSPlayerContext.Provider>
554
+ ) : null}
555
+ {controlsVisible && (
556
+ <Flex
557
+ ref={controlsRef}
558
+ direction={isMobile ? 'columnReverse' : 'column'}
559
+ justify="end"
560
+ align="start"
561
+ css={{
562
+ position: 'absolute',
563
+ bottom: isFullScreen && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? '$8' : '0',
564
+ left: '0',
565
+ zIndex: 1,
566
+ background:
567
+ isMobile || isLandscape
568
+ ? ''
569
+ : `linear-gradient(180deg, ${theme.colors.background_dim.value}00 29.46%, ${theme.colors.background_dim.value}A3 100%);`,
570
+ width: '100%',
571
+ pt: '$8',
572
+ flexShrink: 0,
573
+ transition: 'visibility 0s 0.5s, opacity 0.5s linear',
574
+ }}
575
+ >
576
+ {hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
577
+ <HMSVideoPlayer.Progress seekProgress={seekProgress} setSeekProgress={setSeekProgress} />
578
+ ) : null}
579
+ <HMSVideoPlayer.Controls.Root
580
+ css={{
581
+ p: '$4 $8',
582
+ }}
583
+ >
584
+ <HMSVideoPlayer.Controls.Left>
585
+ {!(isMobile || isLandscape) && (
586
+ <>
587
+ {hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
588
+ <>
589
+ <HMSVideoPlayer.Seeker
590
+ onClick={() => {
591
+ onSeekTo(-10);
592
+ }}
593
+ title="backward"
594
+ >
595
+ <BackwardArrowIcon width={20} height={20} />
596
+ </HMSVideoPlayer.Seeker>
597
+ <HMSVideoPlayer.PlayPauseButton isPaused={isPaused} />
598
+ <HMSVideoPlayer.Seeker
599
+ onClick={() => {
600
+ onSeekTo(10);
601
+ }}
602
+ title="forward"
603
+ >
604
+ <ForwardArrowIcon width={20} height={20} />
605
+ </HMSVideoPlayer.Seeker>
606
+ {!isVideoLive ? <HMSVideoPlayer.Duration /> : null}
607
+ </>
608
+ ) : null}
609
+ <HMSVideoPlayer.Volume />
610
+ </>
611
+ )}
612
+ <IconButton
613
+ css={{ px: '$2' }}
614
+ onClick={async () => {
615
+ await hlsPlayer?.seekToLivePosition();
616
+ setIsVideoLive(true);
617
+ }}
618
+ key="jump-to-live_btn"
619
+ data-testid="jump-to-live_btn"
620
+ >
621
+ <Tooltip title={isVideoLive ? 'Live' : 'Go to Live'} side="top">
622
+ <Flex justify="center" gap={2} align="center">
623
+ <Box
624
+ css={{
625
+ height: '$4',
626
+ width: '$4',
627
+ background: isVideoLive ? '$alert_error_default' : '$on_primary_medium',
628
+ r: '$1',
629
+ }}
630
+ />
631
+ <Text
632
+ variant="$body1"
633
+ css={{
634
+ c: isVideoLive ? '$on_surface_high' : '$on_surface_medium',
635
+ fontWeight: '$semiBold',
636
+ }}
637
+ >
638
+ {isVideoLive ? 'LIVE' : 'GO LIVE'}
639
+ </Text>
640
+ </Flex>
641
+ </Tooltip>
642
+ </IconButton>
643
+ {(isMobile || isLandscape) &&
644
+ !isVideoLive &&
645
+ hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
646
+ <HMSVideoPlayer.Duration />
647
+ ) : null}
648
+ </HMSVideoPlayer.Controls.Left>
602
649
 
603
- {isMobile && !isFullScreen && <HLSViewTitle />}
604
- </>
605
- ) : (
606
- <Flex align="center" justify="center" direction="column" css={{ size: '100%', px: '$10' }}>
607
- <Flex align="center" gap="2" css={{ position: 'absolute', left: '$4', top: '$4', zIndex: 1 }}>
608
- {isMobile || isLandscape ? <LeaveRoom screenType={screenType} /> : null}
609
- </Flex>
610
- <Flex css={{ c: '$on_surface_high', r: '$round', bg: '$surface_default', p: '$2' }}>
611
- {streamEnded ? <ColoredHandIcon height={56} width={56} /> : <GoLiveIcon height={56} width={56} />}
612
- </Flex>
613
- <Text variant="h5" css={{ c: '$on_surface_high', mt: '$10', mb: 0, textAlign: 'center' }}>
614
- {streamEnded ? 'Stream has ended' : 'Stream yet to start'}
615
- </Text>
616
- <Text variant="md" css={{ textAlign: 'center', mt: '$4', c: '$on_surface_medium' }}>
617
- {streamEnded ? 'Have a nice day!' : 'Sit back and relax'}
618
- </Text>
650
+ <HMSVideoPlayer.Controls.Right>
651
+ {hasCaptions && !(isMobile || isLandscape) && <HLSCaptionSelector isEnabled={isCaptionEnabled} />}
652
+ {availableLayers.length > 0 && !(isMobile || isLandscape) ? (
653
+ <HLSQualitySelector
654
+ layers={availableLayers}
655
+ onOpenChange={setQualityDropDownOpen}
656
+ open={qualityDropDownOpen}
657
+ selection={currentSelectedQuality}
658
+ onQualityChange={handleQuality}
659
+ isAuto={isUserSelectedAuto}
660
+ />
661
+ ) : null}
662
+ {isFullScreenSupported ? (
663
+ <FullScreenButton isFullScreen={isFullScreen} onToggle={toggle} />
664
+ ) : null}
665
+ </HMSVideoPlayer.Controls.Right>
666
+ </HMSVideoPlayer.Controls.Root>
667
+ </Flex>
668
+ )}
669
+ </>
670
+ </HMSVideoPlayer.Root>
619
671
  </Flex>
620
- )}
672
+ </HMSPlayerContext.Provider>
673
+ <ToggleChat />
674
+ {isMobile && !isFullScreen && <HLSViewTitle />}
621
675
  </Flex>
622
676
  );
623
677
  };