@100mslive/roomkit-react 0.2.8-alpha.0 → 0.2.8-alpha.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. package/dist/HLSView-FBEGJ3L7.js +1396 -0
  2. package/dist/HLSView-FBEGJ3L7.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-72B32WVR.js → chunk-R2JJJQR3.js} +1684 -1316
  27. package/dist/chunk-R2JJJQR3.js.map +7 -0
  28. package/dist/index.cjs.js +2866 -2053
  29. package/dist/index.cjs.js.map +4 -4
  30. package/dist/index.js +1 -1
  31. package/dist/meta.cjs.json +786 -299
  32. package/dist/meta.esbuild.json +805 -307
  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/AudioVideoToggle.tsx +2 -1
  42. package/src/Prebuilt/components/AuthToken.jsx +1 -1
  43. package/src/Prebuilt/components/Chat/Chat.tsx +41 -1
  44. package/src/Prebuilt/components/Chat/ChatFooter.tsx +33 -13
  45. package/src/Prebuilt/components/Chat/MwebChatOption.tsx +1 -1
  46. package/src/Prebuilt/components/ConferenceScreen.tsx +48 -7
  47. package/src/Prebuilt/components/EmojiReaction.jsx +33 -23
  48. package/src/Prebuilt/components/Footer/Footer.tsx +0 -1
  49. package/src/Prebuilt/components/Footer/RoleOptions.tsx +138 -125
  50. package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -1
  51. package/src/Prebuilt/components/HMSVideo/FullscreenButton.tsx +13 -0
  52. package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.tsx +72 -0
  53. package/src/Prebuilt/components/HMSVideo/HLSCaptionSelector.tsx +4 -2
  54. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.tsx +248 -0
  55. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +17 -7
  56. package/src/Prebuilt/components/HMSVideo/MwebHLSViewTitle.tsx +84 -0
  57. package/src/Prebuilt/components/HMSVideo/PlayButton.tsx +27 -0
  58. package/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx +27 -0
  59. package/src/Prebuilt/components/HMSVideo/PlayerContext.tsx +15 -0
  60. package/src/Prebuilt/components/HMSVideo/SeekControls.tsx +22 -0
  61. package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +95 -0
  62. package/src/Prebuilt/components/HMSVideo/VideoTime.tsx +43 -0
  63. package/src/Prebuilt/components/HMSVideo/{VolumeControl.jsx → VolumeControl.tsx} +6 -4
  64. package/src/Prebuilt/components/HMSVideo/{index.js → index.ts} +6 -2
  65. package/src/Prebuilt/components/HMSVideo/{HMSVIdeoUtils.js → utils.ts} +5 -5
  66. package/src/Prebuilt/components/Header/StreamActions.tsx +1 -1
  67. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +1 -1
  68. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +50 -46
  69. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +15 -4
  70. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +46 -27
  71. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +3 -1
  72. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +37 -31
  73. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +12 -8
  74. package/src/Prebuilt/components/MwebLandscapePrompt.tsx +14 -3
  75. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +5 -2
  76. package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -1
  77. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +19 -8
  78. package/src/Prebuilt/components/Polls/Voting/Voting.tsx +3 -2
  79. package/src/Prebuilt/components/Polls/common/OptionInputWithDelete.tsx +1 -1
  80. package/src/Prebuilt/components/Polls/common/utils.ts +2 -2
  81. package/src/Prebuilt/components/RaiseHand.tsx +24 -0
  82. package/src/Prebuilt/components/RoomDetails/RoomDetailsPane.tsx +41 -14
  83. package/src/Prebuilt/components/SidePaneTabs.tsx +56 -48
  84. package/src/Prebuilt/components/StatsForNerds.jsx +14 -6
  85. package/src/Prebuilt/components/Streaming/Common.jsx +1 -1
  86. package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +2 -2
  87. package/src/Prebuilt/components/Toast/ToastBatcher.js +8 -1
  88. package/src/Prebuilt/components/Toast/ToastConfig.jsx +17 -0
  89. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +1 -1
  90. package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +2 -1
  91. package/src/Prebuilt/components/pdfAnnotator/shareScreenOptions.jsx +2 -2
  92. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +1 -1
  93. package/src/Prebuilt/layouts/HLSView.jsx +359 -178
  94. package/src/Prebuilt/layouts/SidePane.tsx +145 -59
  95. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +22 -2
  96. package/src/Prebuilt/primitives/DialogContent.jsx +1 -1
  97. package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +1 -1
  98. package/src/Sheet/Sheet.tsx +7 -3
  99. package/dist/HLSView-37B2YVTC.js +0 -987
  100. package/dist/HLSView-37B2YVTC.js.map +0 -7
  101. package/dist/chunk-72B32WVR.js.map +0 -7
  102. package/src/Prebuilt/components/HMSVideo/FullscreenButton.jsx +0 -18
  103. package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.jsx +0 -35
  104. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +0 -127
  105. package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +0 -13
  106. package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +0 -76
  107. package/src/Prebuilt/components/HMSVideo/VideoTime.jsx +0 -33
  108. package/src/Prebuilt/components/RaiseHand.jsx +0 -17
@@ -1,14 +1,14 @@
1
- export function getPercentage(a, b) {
1
+ export function getPercentage(a: number, b: number) {
2
2
  return (a / b) * 100;
3
3
  }
4
4
 
5
5
  /**
6
+ * Take a time in seconds and return its equivalent time in hh:mm:ss format
7
+ * @param {number} timeInSeconds if given as floating point value, it is floored.
6
8
  *
7
- * @param {number} timeInSeconds - if given as floating point value, it is floored.
8
- * @returns a string representing timeInSeconds in HH:MM:SS format.
9
- * (e.g) getDurationFromSeconds(3910) returns "1:05:10"
9
+ * @returns a string representing timeInSeconds in HH:MM:SS format.
10
10
  */
11
- export function getDurationFromSeconds(timeInSeconds) {
11
+ export function getDurationFromSeconds(timeInSeconds: number) {
12
12
  let time = Math.floor(timeInSeconds);
13
13
  const hours = Math.floor(time / 3600);
14
14
  time = time - hours * 3600;
@@ -42,7 +42,7 @@ export const LiveStatus = () => {
42
42
  setLiveTime(Date.now() - timeStamp.getTime());
43
43
  }
44
44
  }, 1000);
45
- }, [hlsState?.running, hlsState?.variants]);
45
+ }, [hlsState?.running, hlsState?.variants, screenType]);
46
46
 
47
47
  useEffect(() => {
48
48
  if (hlsState?.running) {
@@ -24,7 +24,7 @@ const IconSection = styled(IconButton, {
24
24
  h: '$14',
25
25
  p: '$4',
26
26
  r: '$1',
27
- bg: '$transparent',
27
+ bg: 'transparent',
28
28
  borderTopRightRadius: 0,
29
29
  borderColor: '$border_bright',
30
30
  borderBottomRightRadius: 0,
@@ -17,10 +17,12 @@ export const DesktopLeaveRoom = ({
17
17
  leaveRoom,
18
18
  screenType,
19
19
  endRoom,
20
+ container,
20
21
  }: {
21
22
  leaveRoom: (options?: { endStream?: boolean }) => Promise<void>;
22
23
  screenType: keyof ConferencingScreen;
23
24
  endRoom: () => Promise<void>;
25
+ container?: HTMLElement;
24
26
  }) => {
25
27
  const [open, setOpen] = useState(false);
26
28
  const [showLeaveRoomAlert, setShowLeaveRoomAlert] = useState(false);
@@ -69,54 +71,56 @@ export const DesktopLeaveRoom = ({
69
71
  <VerticalMenuIcon />
70
72
  </MenuTriggerButton>
71
73
  </Dropdown.Trigger>
72
- <Dropdown.Content css={{ p: 0, w: '$100' }} alignOffset={-50} sideOffset={10}>
73
- <Dropdown.Item
74
- css={{
75
- bg: '$surface_dim',
76
- color: '$on_surface_medium',
77
- '&:hover': { bg: '$surface_default', color: '$on_surface_high' },
78
- p: '0',
79
- }}
80
- data-testid="just_leave_btn"
81
- >
82
- <LeaveCard
83
- title={showStream ? 'Leave Stream' : 'Leave Session'}
84
- subtitle={`Others will continue after you leave. You can join the ${
85
- showStream ? 'stream' : 'session'
86
- } again.`}
87
- bg=""
88
- titleColor="$on_surface_high"
89
- icon={<ExitIcon height={24} width={24} style={{ transform: 'rotate(180deg)' }} />}
90
- onClick={async () => await leaveRoom()}
91
- css={{ p: '$8 $4' }}
92
- />
93
- </Dropdown.Item>
74
+ <Dropdown.Portal container={container}>
75
+ <Dropdown.Content css={{ p: 0, w: '$100' }} alignOffset={-50} sideOffset={10}>
76
+ <Dropdown.Item
77
+ css={{
78
+ bg: '$surface_dim',
79
+ color: '$on_surface_medium',
80
+ '&:hover': { bg: '$surface_default', color: '$on_surface_high' },
81
+ p: '0',
82
+ }}
83
+ data-testid="just_leave_btn"
84
+ >
85
+ <LeaveCard
86
+ title={showStream ? 'Leave Stream' : 'Leave Session'}
87
+ subtitle={`Others will continue after you leave. You can join the ${
88
+ showStream ? 'stream' : 'session'
89
+ } again.`}
90
+ bg=""
91
+ titleColor="$on_surface_high"
92
+ icon={<ExitIcon height={24} width={24} style={{ transform: 'rotate(180deg)' }} />}
93
+ onClick={async () => await leaveRoom()}
94
+ css={{ p: '$8 $4' }}
95
+ />
96
+ </Dropdown.Item>
94
97
 
95
- <Dropdown.Item
96
- css={{
97
- bg: '$alert_error_dim',
98
- color: '$alert_error_bright',
99
- '&:hover': { bg: '$alert_error_dim', color: '$alert_error_brighter' },
100
- p: '0',
101
- }}
102
- data-testid="end_room_btn"
103
- >
104
- <LeaveCard
105
- title={showStream ? 'End Stream' : 'End Session'}
106
- subtitle={`The ${
107
- showStream ? 'stream' : 'session'
108
- } will end for everyone. You can't undo this action.`}
109
- bg=""
110
- titleColor="$alert_error_brighter"
111
- icon={<StopIcon height={24} width={24} />}
112
- onClick={() => {
113
- setOpen(false);
114
- setShowEndStreamAlert(true);
98
+ <Dropdown.Item
99
+ css={{
100
+ bg: '$alert_error_dim',
101
+ color: '$alert_error_bright',
102
+ '&:hover': { bg: '$alert_error_dim', color: '$alert_error_brighter' },
103
+ p: '0',
115
104
  }}
116
- css={{ p: '$8 $4' }}
117
- />
118
- </Dropdown.Item>
119
- </Dropdown.Content>
105
+ data-testid="end_room_btn"
106
+ >
107
+ <LeaveCard
108
+ title={showStream ? 'End Stream' : 'End Session'}
109
+ subtitle={`The ${
110
+ showStream ? 'stream' : 'session'
111
+ } will end for everyone. You can't undo this action.`}
112
+ bg=""
113
+ titleColor="$alert_error_brighter"
114
+ icon={<StopIcon height={24} width={24} />}
115
+ onClick={() => {
116
+ setOpen(false);
117
+ setShowEndStreamAlert(true);
118
+ }}
119
+ css={{ p: '$8 $4' }}
120
+ />
121
+ </Dropdown.Item>
122
+ </Dropdown.Content>
123
+ </Dropdown.Portal>
120
124
  </Dropdown.Root>
121
125
  </Flex>
122
126
  ) : (
@@ -14,12 +14,18 @@ import {
14
14
  } from '@100mslive/react-sdk';
15
15
  import { config as cssConfig } from '../../../Theme';
16
16
  // @ts-ignore: No implicit Any
17
- // @ts-ignore: No implicit Any
18
17
  import { ToastManager } from '../Toast/ToastManager';
19
18
  import { DesktopLeaveRoom } from './DesktopLeaveRoom';
20
19
  import { MwebLeaveRoom } from './MwebLeaveRoom';
20
+ import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
21
21
 
22
- export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen }) => {
22
+ export const LeaveRoom = ({
23
+ screenType,
24
+ container,
25
+ }: {
26
+ screenType: keyof ConferencingScreen;
27
+ container?: HTMLElement;
28
+ }) => {
23
29
  const isConnected = useHMSStore(selectIsConnectedToRoom);
24
30
  const permissions = useHMSStore(selectPermissions);
25
31
  const isMobile = useMedia(cssConfig.media.md);
@@ -33,6 +39,8 @@ export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen
33
39
  );
34
40
  const hlsState = useHMSStore(selectHLSState);
35
41
  const hmsActions = useHMSActions();
42
+ const isMobileHLSStream = useMobileHLSStream();
43
+ const isLandscapeHLSStream = useLandscapeHLSStream();
36
44
 
37
45
  const stopStream = async () => {
38
46
  try {
@@ -61,9 +69,12 @@ export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen
61
69
  if (!permissions || !isConnected) {
62
70
  return null;
63
71
  }
72
+ if (isMobileHLSStream || isLandscapeHLSStream) {
73
+ return <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} container={container} />;
74
+ }
64
75
  return isMobile ? (
65
- <MwebLeaveRoom leaveRoom={leaveRoom} screenType={screenType} endRoom={endRoom} />
76
+ <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} container={container} />
66
77
  ) : (
67
- <DesktopLeaveRoom leaveRoom={leaveRoom} screenType={screenType} endRoom={endRoom} />
78
+ <DesktopLeaveRoom leaveRoom={leaveRoom} screenType={screenType} endRoom={endRoom} container={container} />
68
79
  );
69
80
  };
@@ -1,9 +1,9 @@
1
1
  import React, { Fragment, useState } from 'react';
2
- import { ConferencingScreen } from '@100mslive/types-prebuilt';
3
2
  // @ts-ignore: No implicit Any
4
3
  import { selectIsConnectedToRoom, selectPermissions, useHMSStore, useRecordingStreaming } from '@100mslive/react-sdk';
5
4
  // @ts-ignore: No implicit Any
6
- import { ExitIcon, StopIcon } from '@100mslive/react-icons';
5
+ import { CrossIcon, ExitIcon, StopIcon } from '@100mslive/react-icons';
6
+ import { IconButton } from '../../../IconButton';
7
7
  import { Box } from '../../../Layout';
8
8
  import { Sheet } from '../../../Sheet';
9
9
  import { Tooltip } from '../../../Tooltip';
@@ -11,19 +11,22 @@ import { EndSessionContent } from './EndSessionContent';
11
11
  import { LeaveIconButton } from './LeaveAtoms';
12
12
  import { LeaveCard } from './LeaveCard';
13
13
  import { LeaveSessionContent } from './LeaveSessionContent';
14
+ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
14
15
  // @ts-ignore: No implicit Any
15
16
  import { useDropdownList } from '../hooks/useDropdownList';
17
+ import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
16
18
 
17
19
  export const MwebLeaveRoom = ({
18
20
  leaveRoom,
19
- screenType,
20
21
  endRoom,
22
+ container,
21
23
  }: {
22
24
  leaveRoom: (options?: { endStream?: boolean }) => Promise<void>;
23
- screenType: keyof ConferencingScreen;
24
25
  endRoom: () => Promise<void>;
26
+ container?: HTMLElement;
25
27
  }) => {
26
28
  const [open, setOpen] = useState(false);
29
+ const { screenType } = useRoomLayoutConferencingScreen();
27
30
  const [showLeaveRoomAlert, setShowLeaveRoomAlert] = useState(false);
28
31
  const [showEndStreamAlert, setShowEndStreamAlert] = useState(false);
29
32
  const isConnected = useHMSStore(selectIsConnectedToRoom);
@@ -43,22 +46,13 @@ export const MwebLeaveRoom = ({
43
46
  {showLeaveOptions ? (
44
47
  <Sheet.Root open={open} onOpenChange={setOpen}>
45
48
  <Sheet.Trigger asChild>
46
- <LeaveIconButton
47
- key="LeaveRoom"
48
- data-testid="leave_room_btn"
49
- css={{
50
- borderTopRightRadius: '$1',
51
- borderBottomRightRadius: '$1',
49
+ <LeaveButton
50
+ onClick={() => {
51
+ setOpen(open => !open);
52
52
  }}
53
- >
54
- <Tooltip title="Leave Room">
55
- <Box>
56
- <ExitIcon style={{ transform: 'rotate(180deg)' }} />
57
- </Box>
58
- </Tooltip>
59
- </LeaveIconButton>
53
+ />
60
54
  </Sheet.Trigger>
61
- <Sheet.Content>
55
+ <Sheet.Content container={container}>
62
56
  <LeaveCard
63
57
  title={showStream ? 'Leave Stream' : 'Leave Session'}
64
58
  subtitle={`Others will continue after you leave. You can join the ${
@@ -88,16 +82,10 @@ export const MwebLeaveRoom = ({
88
82
  </Sheet.Content>
89
83
  </Sheet.Root>
90
84
  ) : (
91
- <LeaveIconButton key="LeaveRoom" data-testid="leave_room_btn" onClick={() => setShowLeaveRoomAlert(true)}>
92
- <Tooltip title="Leave Room">
93
- <Box>
94
- <ExitIcon style={{ transform: 'rotate(180deg)' }} />
95
- </Box>
96
- </Tooltip>
97
- </LeaveIconButton>
85
+ <LeaveButton onClick={() => setShowLeaveRoomAlert(true)} />
98
86
  )}
99
87
  <Sheet.Root open={showEndStreamAlert} onOpenChange={setShowEndStreamAlert}>
100
- <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }}>
88
+ <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }} container={container}>
101
89
  <EndSessionContent
102
90
  setShowEndStreamAlert={setShowEndStreamAlert}
103
91
  leaveRoom={isStreamingOn ? leaveRoom : endRoom}
@@ -107,10 +95,41 @@ export const MwebLeaveRoom = ({
107
95
  </Sheet.Root>
108
96
 
109
97
  <Sheet.Root open={showLeaveRoomAlert} onOpenChange={setShowLeaveRoomAlert}>
110
- <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }}>
98
+ <Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }} container={container}>
111
99
  <LeaveSessionContent setShowLeaveRoomAlert={setShowLeaveRoomAlert} leaveRoom={leaveRoom} />
112
100
  </Sheet.Content>
113
101
  </Sheet.Root>
114
102
  </Fragment>
115
103
  );
116
104
  };
105
+
106
+ const LeaveButton = ({ onClick }: { onClick: () => void }) => {
107
+ const isMobileHLSStream = useMobileHLSStream();
108
+ const isLandscapeHLSStream = useLandscapeHLSStream();
109
+
110
+ return isMobileHLSStream || isLandscapeHLSStream ? (
111
+ <IconButton key="LeaveRoom" data-testid="leave_room_btn" onClick={onClick}>
112
+ <Tooltip title="Leave Room">
113
+ <Box>
114
+ <CrossIcon />
115
+ </Box>
116
+ </Tooltip>
117
+ </IconButton>
118
+ ) : (
119
+ <LeaveIconButton
120
+ key="LeaveRoom"
121
+ data-testid="leave_room_btn"
122
+ css={{
123
+ borderTopRightRadius: '$1',
124
+ borderBottomRightRadius: '$1',
125
+ }}
126
+ onClick={onClick}
127
+ >
128
+ <Tooltip title="Leave Room">
129
+ <Box>
130
+ <ExitIcon style={{ transform: 'rotate(180deg)' }} />
131
+ </Box>
132
+ </Tooltip>
133
+ </LeaveIconButton>
134
+ );
135
+ };
@@ -10,6 +10,7 @@ import { DesktopOptions } from './SplitComponents/DesktopOptions';
10
10
  // @ts-ignore: No implicit Any
11
11
  import { MwebOptions } from './SplitComponents/MwebOptions';
12
12
  import { config as cssConfig } from '../../..';
13
+ import { useLandscapeHLSStream } from '../../common/hooks';
13
14
 
14
15
  export const MoreSettings = ({
15
16
  elements,
@@ -19,7 +20,8 @@ export const MoreSettings = ({
19
20
  screenType: keyof ConferencingScreen;
20
21
  }) => {
21
22
  const isMobile = useMedia(cssConfig.media.md);
22
- return isMobile ? (
23
+ const isLandscapeHLSStream = useLandscapeHLSStream();
24
+ return isMobile || isLandscapeHLSStream ? (
23
25
  <MwebOptions elements={elements} screenType={screenType} />
24
26
  ) : (
25
27
  <DesktopOptions elements={elements} screenType={screenType} />
@@ -5,6 +5,7 @@ import {
5
5
  DefaultConferencingScreen_Elements,
6
6
  HLSLiveStreamingScreen_Elements,
7
7
  } from '@100mslive/types-prebuilt';
8
+ import { match } from 'ts-pattern';
8
9
  import { selectAppData, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
9
10
  import { BrbIcon, CheckIcon, HamburgerMenuIcon, InfoIcon, PipIcon, SettingsIcon } from '@100mslive/react-icons';
10
11
  import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../..';
@@ -143,41 +144,46 @@ export const DesktopOptions = ({
143
144
  Settings
144
145
  </Text>
145
146
  </Dropdown.Item>
147
+ {match({ screenType, isSupported: HMSHLSPlayer.isSupported() })
148
+ .with({ screenType: 'hls_live_streaming', isSupported: false }, () => null)
149
+ .with({ screenType: 'hls_live_streaming', isSupported: true }, () => {
150
+ return (
151
+ <Dropdown.Item
152
+ onClick={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)}
153
+ data-testid="hls_stats"
154
+ >
155
+ <Checkbox.Root
156
+ css={{ margin: '$2' }}
157
+ checked={enablHlsStats}
158
+ onCheckedChange={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)}
159
+ >
160
+ <Checkbox.Indicator>
161
+ <CheckIcon width={16} height={16} />
162
+ </Checkbox.Indicator>
163
+ </Checkbox.Root>
164
+ <Flex justify="between" css={{ width: '100%' }}>
165
+ <Text variant="sm" css={{ ml: '$4' }}>
166
+ Show HLS Stats
167
+ </Text>
146
168
 
147
- {screenType === 'hls_live_streaming' ? (
148
- HMSHLSPlayer.isSupported() ? (
169
+ <Text variant="sm" css={{ ml: '$4' }}>
170
+ {`${isMacOS ? '⌘' : 'ctrl'} + ]`}
171
+ </Text>
172
+ </Flex>
173
+ </Dropdown.Item>
174
+ );
175
+ })
176
+ .otherwise(() => (
149
177
  <Dropdown.Item
150
- onClick={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)}
151
- data-testid="hls_stats"
178
+ onClick={() => updateState(MODALS.STATS_FOR_NERDS, true)}
179
+ data-testid="stats_for_nerds_btn"
152
180
  >
153
- <Checkbox.Root
154
- css={{ margin: '$2' }}
155
- checked={enablHlsStats}
156
- onCheckedChange={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)}
157
- >
158
- <Checkbox.Indicator>
159
- <CheckIcon width={16} height={16} />
160
- </Checkbox.Indicator>
161
- </Checkbox.Root>
162
- <Flex justify="between" css={{ width: '100%' }}>
163
- <Text variant="sm" css={{ ml: '$4' }}>
164
- Show HLS Stats
165
- </Text>
166
-
167
- <Text variant="sm" css={{ ml: '$4' }}>
168
- {`${isMacOS ? '⌘' : 'ctrl'} + ]`}
169
- </Text>
170
- </Flex>
181
+ <InfoIcon />
182
+ <Text variant="sm" css={{ ml: '$4' }}>
183
+ Stats for Nerds
184
+ </Text>
171
185
  </Dropdown.Item>
172
- ) : null
173
- ) : (
174
- <Dropdown.Item onClick={() => updateState(MODALS.STATS_FOR_NERDS, true)} data-testid="stats_for_nreds_btn">
175
- <InfoIcon />
176
- <Text variant="sm" css={{ ml: '$4' }}>
177
- Stats for Nerds
178
- </Text>
179
- </Dropdown.Item>
180
- )}
186
+ ))}
181
187
  </Dropdown.Content>
182
188
  </Dropdown.Root>
183
189
  {openModals.has(MODALS.BULK_ROLE_CHANGE) && (
@@ -1,6 +1,7 @@
1
1
  import React, { useRef, useState } from 'react';
2
2
  import { useClickAway } from 'react-use';
3
3
  import { ConferencingScreen, DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
4
+ import { match } from 'ts-pattern';
4
5
  import {
5
6
  selectIsConnectedToRoom,
6
7
  selectPeerCount,
@@ -53,6 +54,7 @@ import { useDropdownList } from '../../hooks/useDropdownList';
53
54
  // @ts-ignore: No implicit any
54
55
  import { useMyMetadata } from '../../hooks/useMetadata';
55
56
  import { useUnreadPollQuizPresent } from '../../hooks/useUnreadPollQuizPresent';
57
+ import { useLandscapeHLSStream, useMobileHLSStream } from '../../../common/hooks';
56
58
  // @ts-ignore: No implicit any
57
59
  import { getFormattedCount } from '../../../common/utils';
58
60
  // @ts-ignore: No implicit any
@@ -98,6 +100,8 @@ export const MwebOptions = ({
98
100
  const { unreadPollQuiz, setUnreadPollQuiz } = useUnreadPollQuizPresent();
99
101
  const { title, description } = useRoomLayoutHeader();
100
102
  const toggleDetailsSheet = useSheetToggle(SHEET_OPTIONS.ROOM_DETAILS);
103
+ const isMobileHLSStream = useMobileHLSStream();
104
+ const isLandscapeHLSStream = useLandscapeHLSStream();
101
105
 
102
106
  useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' });
103
107
 
@@ -120,7 +124,7 @@ export const MwebOptions = ({
120
124
  <Sheet.Root open={openOptionsSheet} onOpenChange={setOpenOptionsSheet}>
121
125
  <Tooltip title="More options">
122
126
  <Sheet.Trigger asChild data-testid="more_settings_btn">
123
- <IconButton>
127
+ <IconButton css={{ bg: isMobileHLSStream || isLandscapeHLSStream ? '$surface_default' : '' }}>
124
128
  <HamburgerMenuIcon />
125
129
  </IconButton>
126
130
  </Sheet.Trigger>
@@ -196,7 +200,7 @@ export const MwebOptions = ({
196
200
  </ActionTile.Root>
197
201
  ) : null} */}
198
202
 
199
- {elements?.emoji_reactions && (
203
+ {elements?.emoji_reactions && !(isLandscapeHLSStream || isMobileHLSStream) && (
200
204
  <ActionTile.Root
201
205
  onClick={() => {
202
206
  setShowEmojiCard(true);
@@ -287,11 +291,11 @@ export const MwebOptions = ({
287
291
  >
288
292
  {isRecordingLoading ? <Loading /> : <RecordIcon />}
289
293
  <ActionTile.Title>
290
- {isBrowserRecordingOn
291
- ? 'Recording On'
292
- : isRecordingLoading
293
- ? 'Starting Recording'
294
- : 'Start Recording'}
294
+ {match({ isBrowserRecordingOn, isRecordingLoading })
295
+ .with({ isBrowserRecordingOn: true, isRecordingLoading: false }, () => 'Recording On')
296
+ .with({ isRecordingLoading: true }, () => 'Starting Recording')
297
+ .with({ isRecordingLoading: false }, () => 'Start Recording')
298
+ .otherwise(() => null)}
295
299
  </ActionTile.Title>
296
300
  </ActionTile.Root>
297
301
  ) : null}
@@ -339,7 +343,7 @@ export const MwebOptions = ({
339
343
  mx: '$4',
340
344
  }}
341
345
  >
342
- <EmojiReaction />
346
+ <EmojiReaction showCard />
343
347
  </Box>
344
348
  )}
345
349
  {showRecordingOn && (
@@ -1,17 +1,20 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
+ import { match, P } from 'ts-pattern';
3
4
  import { RefreshIcon } from '@100mslive/react-icons';
4
5
  import { Button } from '../../Button';
5
6
  import { Box, Flex } from '../../Layout';
6
7
  import { Dialog } from '../../Modal';
7
8
  import { Text } from '../../Text';
8
9
  import { config as cssConfig } from '../../Theme';
10
+ import { useLandscapeHLSStream } from '../common/hooks';
9
11
  // @ts-ignore
10
12
  import { isMobileUserAgent } from '../common/utils';
11
13
 
12
14
  export const MwebLandscapePrompt = () => {
13
15
  const [showMwebLandscapePrompt, setShowMwebLandscapePrompt] = useState(false);
14
16
  const isLandscape = useMedia(cssConfig.media.ls);
17
+ const isLandscapeHLSStream = useLandscapeHLSStream();
15
18
 
16
19
  useEffect(() => {
17
20
  if (!isMobileUserAgent) {
@@ -20,22 +23,30 @@ export const MwebLandscapePrompt = () => {
20
23
  }
21
24
 
22
25
  if (!window.screen?.orientation) {
23
- setShowMwebLandscapePrompt(isLandscape);
26
+ setShowMwebLandscapePrompt(isLandscape && !isLandscapeHLSStream);
24
27
  return;
25
28
  }
26
29
  const handleRotation = () => {
27
30
  const angle = window.screen.orientation.angle;
28
31
  const type = window.screen.orientation.type || '';
29
32
  // Angle check needed to diff bw mobile and desktop
30
- setShowMwebLandscapePrompt(angle ? angle >= 90 && type.includes('landscape') : isLandscape);
33
+ setShowMwebLandscapePrompt(
34
+ match({ angle, isLandscapeHLSStream, isLandscape, type })
35
+ .with({ isLandscapeHLSStream }, () => false)
36
+ .with({ angle: P.when(angle => angle && angle >= 90) }, ({ type }) => type.includes('landscape'))
37
+ .otherwise(() => isLandscape),
38
+ );
31
39
  };
32
40
  handleRotation();
33
41
  window.screen.orientation.addEventListener('change', handleRotation);
34
42
  return () => {
35
43
  window.screen.orientation.removeEventListener('change', handleRotation);
36
44
  };
37
- }, [isLandscape]);
45
+ }, [isLandscape, isLandscapeHLSStream]);
38
46
 
47
+ if (isLandscapeHLSStream) {
48
+ return null;
49
+ }
39
50
  return (
40
51
  <Dialog.Root open={showMwebLandscapePrompt} onOpenChange={setShowMwebLandscapePrompt}>
41
52
  <Dialog.Portal>
@@ -3,6 +3,7 @@ import {
3
3
  HMSNotificationTypes,
4
4
  HMSRoomState,
5
5
  selectHasPeerHandRaised,
6
+ selectPeerByID,
6
7
  selectRoomState,
7
8
  useHMSNotifications,
8
9
  useHMSStore,
@@ -28,12 +29,14 @@ export const HandRaisedNotifications = () => {
28
29
  }
29
30
 
30
31
  // Don't show toast message in case of local peer.
31
- if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !on_stage_exp || !isSubscribing) {
32
+ if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
32
33
  return;
33
34
  }
34
35
  const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
36
+ const peer = vanillaStore.getState(selectPeerByID(notification.data.id));
35
37
  if (hasPeerHandRaised) {
36
- ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
38
+ const showCTA = peer?.roleName && (on_stage_exp?.off_stage_roles || [])?.includes(peer.roleName);
39
+ ToastBatcher.showToast({ notification, type: showCTA ? 'RAISE_HAND_HLS' : 'RAISE_HAND' });
37
40
  console.debug('Metadata updated', notification.data);
38
41
  }
39
42
  }, [isSubscribing, notification, on_stage_exp, roomState, vanillaStore]);
@@ -49,7 +49,7 @@ export const PeerNotifications = () => {
49
49
  }
50
50
 
51
51
  ToastBatcher.showToast({ notification });
52
- }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed]);
52
+ }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed, selectedPeer.id, setPeerSelector]);
53
53
 
54
54
  return null;
55
55
  };
@@ -1,5 +1,6 @@
1
1
  // @ts-check
2
2
  import React, { useCallback, useMemo, useRef, useState } from 'react';
3
+ import { match } from 'ts-pattern';
3
4
  import { selectLocalPeer, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
4
5
  import { CheckCircleIcon, ChevronDownIcon, CrossCircleIcon } from '@100mslive/react-icons';
5
6
  import { Box, Button, Flex, Text } from '../../../../';
@@ -92,20 +93,30 @@ export const QuestionCard = ({
92
93
  <Text
93
94
  variant="caption"
94
95
  css={{
95
- color:
96
- respondedToQuiz && !isLive
97
- ? isCorrectAnswer
98
- ? '$alert_success'
99
- : '$alert_error_default'
100
- : '$on_surface_low',
96
+ color: match({ respondedToQuiz, isLive, isCorrectAnswer })
97
+ .when(
98
+ ({ respondedToQuiz, isLive }) => respondedToQuiz && !isLive,
99
+ ({ isCorrectAnswer }) => (isCorrectAnswer ? '$alert_success' : '$alert_error_default'),
100
+ )
101
+ .otherwise(() => '$on_surface_low'),
101
102
  fontWeight: '$semiBold',
102
103
  display: 'flex',
103
104
  alignItems: 'center',
104
105
  gap: '$4',
105
106
  }}
106
107
  >
107
- {respondedToQuiz && isCorrectAnswer && pollEnded ? <CheckCircleIcon height={16} width={16} /> : null}
108
- {respondedToQuiz && !isCorrectAnswer && pollEnded ? <CrossCircleIcon height={16} width={16} /> : null}
108
+ {match({ respondedToQuiz, pollEnded, isCorrectAnswer })
109
+ .when(
110
+ ({ respondedToQuiz, pollEnded }) => respondedToQuiz && pollEnded,
111
+ ({ isCorrectAnswer }) => {
112
+ return isCorrectAnswer ? (
113
+ <CheckCircleIcon height={16} width={16} />
114
+ ) : (
115
+ <CrossCircleIcon height={16} width={16} />
116
+ );
117
+ },
118
+ )
119
+ .otherwise(() => null)}
109
120
  QUESTION {index} OF {totalQuestions}: {type.toUpperCase()}
110
121
  </Text>
111
122
  </Flex>