@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
@@ -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>
@@ -38,9 +38,9 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
38
38
  <Flex
39
39
  align="center"
40
40
  css={{
41
- gap: '$6',
41
+ gap: '$4',
42
42
  py: '$6',
43
- px: '$10',
43
+ px: '$8',
44
44
  my: '$4',
45
45
  w: '100%',
46
46
  color: '$on_surface_high',
@@ -60,6 +60,7 @@ export const Voting = ({ id, toggleVoting }: { id: string; toggleVoting: () => v
60
60
  marginLeft: 'auto',
61
61
  cursor: 'pointer',
62
62
  '&:hover': { opacity: '0.8' },
63
+ height: 'fit-content',
63
64
  }}
64
65
  >
65
66
  <CrossIcon onClick={toggleVoting} />
@@ -29,7 +29,7 @@ export const OptionInputWithDelete = ({
29
29
  key={index}
30
30
  onChange={event => handleOptionTextChange(index, event.target.value)}
31
31
  />
32
- <IconButton onClick={() => removeOption(index)} css={{ bg: '$transparent', border: 'none' }}>
32
+ <IconButton onClick={() => removeOption(index)} css={{ bg: 'transparent', border: 'none' }}>
33
33
  <TrashIcon />
34
34
  </IconButton>
35
35
  </>
@@ -4,7 +4,7 @@ export const getFormattedTime = (milliseconds: number | undefined, precise = tru
4
4
  const totalSeconds = milliseconds / 1000;
5
5
  const hours = Math.floor(totalSeconds / 3600);
6
6
  const minutes = Math.floor((totalSeconds % 3600) / 60);
7
- const seconds = precise ? totalSeconds % 60 : Math.floor(totalSeconds % 60);
7
+ const seconds = totalSeconds % 60;
8
8
 
9
9
  let formattedTime = '';
10
10
  if (hours) {
@@ -16,7 +16,7 @@ export const getFormattedTime = (milliseconds: number | undefined, precise = tru
16
16
  if (!precise && (hours || minutes)) {
17
17
  return formattedTime;
18
18
  }
19
- formattedTime += `${seconds}s`;
19
+ formattedTime += `${precise ? seconds.toFixed(3) : Math.floor(seconds)}s`;
20
20
 
21
21
  return formattedTime;
22
22
  };
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { HandIcon, HandRaiseSlashedIcon } from '@100mslive/react-icons';
3
+ import { CSS } from '../../Theme';
4
+ import { Tooltip } from '../../Tooltip';
5
+ // @ts-ignore: No implicit Any
6
+ import IconButton from '../IconButton';
7
+ // @ts-ignore: No implicit Any
8
+ import { useMyMetadata } from './hooks/useMetadata';
9
+
10
+ export const RaiseHand = ({ css }: { css?: CSS }) => {
11
+ const { isHandRaised, toggleHandRaise } = useMyMetadata();
12
+ return (
13
+ <Tooltip title={isHandRaised ? 'Lower hand' : 'Raise hand'}>
14
+ <IconButton
15
+ data-testid="hand_raise_btn"
16
+ css={css}
17
+ active={!isHandRaised}
18
+ onClick={async () => await toggleHandRaise()}
19
+ >
20
+ {isHandRaised ? <HandRaiseSlashedIcon /> : <HandIcon />}
21
+ </IconButton>
22
+ </Tooltip>
23
+ );
24
+ };
@@ -2,31 +2,32 @@ import React from 'react';
2
2
  import { CrossIcon } from '@100mslive/react-icons';
3
3
  import { Box, Flex } from '../../../Layout';
4
4
  import { Text } from '../../../Text';
5
+ // @ts-ignore: No implicit any
6
+ import { Logo } from '../Header/HeaderComponents';
5
7
  import { RoomDetailsRow } from './RoomDetailsRow';
6
8
  import { useRoomLayoutHeader } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
7
9
  // @ts-ignore
8
10
  import { useSidepaneToggle } from '../AppData/useSidepane';
11
+ import { useMobileHLSStream } from '../../common/hooks';
9
12
  import { SIDE_PANE_OPTIONS } from '../../common/constants';
10
13
 
11
14
  export const RoomDetailsPane = () => {
12
- const { title, description, details } = useRoomLayoutHeader();
13
- const toggleDetailsPane = useSidepaneToggle(SIDE_PANE_OPTIONS.ROOM_DETAILS);
15
+ const { description } = useRoomLayoutHeader();
16
+ const isMwebHLSStream = useMobileHLSStream();
14
17
  return (
15
18
  <Box css={{ flex: '1 1 0' }}>
16
- <Flex justify="between" align="center" css={{ w: '100%' }}>
17
- <Text variant="h6">{title}</Text>
18
- <Flex
19
- onClick={toggleDetailsPane}
20
- css={{ color: '$on_surface_high', cursor: 'pointer', '&:hover': { opacity: '0.8' } }}
21
- >
22
- <CrossIcon />
19
+ {isMwebHLSStream ? (
20
+ <Flex direction="row" align="center" gap="2">
21
+ <Logo />
22
+ <ShowRoomDetailHeader />
23
23
  </Flex>
24
- </Flex>
25
-
26
- <RoomDetailsRow details={details} />
27
-
24
+ ) : (
25
+ <ShowRoomDetailHeader />
26
+ )}
28
27
  <Box css={{ mt: '$10' }}>
29
- <Text css={{ color: '$on_surface_high', fontWeight: '$semiBold' }}>Description</Text>
28
+ <Text css={{ color: '$on_surface_high', fontWeight: '$semiBold', display: isMwebHLSStream ? 'none' : '' }}>
29
+ Description
30
+ </Text>
30
31
  <Text variant="sm" css={{ c: '$on_surface_medium' }}>
31
32
  {description}
32
33
  </Text>
@@ -34,3 +35,29 @@ export const RoomDetailsPane = () => {
34
35
  </Box>
35
36
  );
36
37
  };
38
+
39
+ const ShowRoomDetailHeader = () => {
40
+ const { title, details } = useRoomLayoutHeader();
41
+ const toggleDetailsPane = useSidepaneToggle(SIDE_PANE_OPTIONS.ROOM_DETAILS);
42
+ const isMwebHLSStream = useMobileHLSStream();
43
+ return (
44
+ <Flex direction="column">
45
+ <Flex justify="between" align="center" css={{ w: '100%' }}>
46
+ <Text variant="h6">{title}</Text>
47
+ {!isMwebHLSStream && (
48
+ <Flex
49
+ onClick={toggleDetailsPane}
50
+ css={{
51
+ color: '$on_surface_high',
52
+ cursor: 'pointer',
53
+ '&:hover': { opacity: '0.8' },
54
+ }}
55
+ >
56
+ <CrossIcon />
57
+ </Flex>
58
+ )}
59
+ </Flex>
60
+ <RoomDetailsRow details={details} />
61
+ </Flex>
62
+ );
63
+ };