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

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 (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
  };