@100mslive/roomkit-react 0.2.8-alpha.4 → 0.2.8-alpha.6

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 (49) hide show
  1. package/dist/{HLSView-UIPDGADR.js → HLSView-53PDKIS2.js} +239 -144
  2. package/dist/HLSView-53PDKIS2.js.map +7 -0
  3. package/dist/Prebuilt/components/Chat/MwebChatOption.d.ts +1 -1
  4. package/dist/Prebuilt/components/HMSVideo/PlayPauseButton.d.ts +6 -0
  5. package/dist/Prebuilt/components/HMSVideo/SeekControls.d.ts +7 -0
  6. package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +3 -1
  7. package/dist/Prebuilt/components/HMSVideo/index.d.ts +10 -2
  8. package/dist/Prebuilt/layouts/SidePane.d.ts +1 -1
  9. package/dist/{chunk-J4NOQ2YL.js → chunk-2ZFAT7KY.js} +339 -218
  10. package/dist/chunk-2ZFAT7KY.js.map +7 -0
  11. package/dist/index.cjs.js +932 -708
  12. package/dist/index.cjs.js.map +4 -4
  13. package/dist/index.js +1 -1
  14. package/dist/meta.cjs.json +217 -78
  15. package/dist/meta.esbuild.json +227 -87
  16. package/package.json +7 -6
  17. package/src/Prebuilt/components/AppData/useSidepane.js +17 -2
  18. package/src/Prebuilt/components/AuthToken.jsx +1 -1
  19. package/src/Prebuilt/components/Chat/ChatFooter.tsx +1 -1
  20. package/src/Prebuilt/components/Chat/MwebChatOption.tsx +1 -1
  21. package/src/Prebuilt/components/ConferenceScreen.tsx +11 -14
  22. package/src/Prebuilt/components/Footer/RoleOptions.tsx +32 -15
  23. package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.tsx +31 -1
  24. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +7 -1
  25. package/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx +27 -0
  26. package/src/Prebuilt/components/HMSVideo/SeekControls.tsx +22 -0
  27. package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +4 -3
  28. package/src/Prebuilt/components/HMSVideo/VolumeControl.tsx +1 -1
  29. package/src/Prebuilt/components/HMSVideo/index.ts +4 -2
  30. package/src/Prebuilt/components/Header/StreamActions.tsx +1 -1
  31. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +37 -31
  32. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +5 -5
  33. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +2 -2
  34. package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -1
  35. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +19 -8
  36. package/src/Prebuilt/components/SidePaneTabs.tsx +27 -35
  37. package/src/Prebuilt/components/StatsForNerds.jsx +14 -6
  38. package/src/Prebuilt/components/Streaming/Common.jsx +1 -1
  39. package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +2 -2
  40. package/src/Prebuilt/components/Toast/ToastBatcher.js +8 -1
  41. package/src/Prebuilt/components/Toast/ToastConfig.jsx +17 -0
  42. package/src/Prebuilt/layouts/HLSView.jsx +109 -69
  43. package/src/Prebuilt/layouts/SidePane.tsx +125 -67
  44. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +2 -1
  45. package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +1 -1
  46. package/src/Sheet/Sheet.tsx +4 -0
  47. package/dist/HLSView-UIPDGADR.js.map +0 -7
  48. package/dist/chunk-J4NOQ2YL.js.map +0 -7
  49. package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +0 -13
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.2.8-alpha.4",
13
+ "version": "0.2.8-alpha.6",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -82,11 +82,11 @@
82
82
  "react": ">=17.0.2 <19.0.0"
83
83
  },
84
84
  "dependencies": {
85
- "@100mslive/hls-player": "0.2.8-alpha.4",
85
+ "@100mslive/hls-player": "0.2.8-alpha.6",
86
86
  "@100mslive/hms-noise-cancellation": "0.0.0-alpha.1",
87
- "@100mslive/hms-virtual-background": "1.12.8-alpha.4",
88
- "@100mslive/react-icons": "0.9.8-alpha.4",
89
- "@100mslive/react-sdk": "0.9.8-alpha.4",
87
+ "@100mslive/hms-virtual-background": "1.12.8-alpha.6",
88
+ "@100mslive/react-icons": "0.9.8-alpha.6",
89
+ "@100mslive/react-sdk": "0.9.8-alpha.6",
90
90
  "@100mslive/types-prebuilt": "0.12.7",
91
91
  "@emoji-mart/data": "^1.0.6",
92
92
  "@emoji-mart/react": "^1.0.1",
@@ -118,8 +118,9 @@
118
118
  "react-window": "^1.8.7",
119
119
  "recordrtc": "^5.6.2",
120
120
  "screenfull": "^5.1.0",
121
+ "ts-pattern": "4.3.0",
121
122
  "uuid": "^8.3.2",
122
123
  "worker-timers": "^7.0.40"
123
124
  },
124
- "gitHead": "ec046697fe2d6a12f4be23b04f217cf38e63af34"
125
+ "gitHead": "666634daeed360298e28b87d08d82b96639e0f70"
125
126
  }
@@ -1,4 +1,5 @@
1
1
  import { useCallback } from 'react';
2
+ import { match, P } from 'ts-pattern';
2
3
  import { selectAppData, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
3
4
  import { usePollViewState } from './useUISettings';
4
5
  import { APP_DATA, POLL_STATE, POLL_VIEWS, SIDE_PANE_OPTIONS } from '../../common/constants';
@@ -45,8 +46,22 @@ export const usePollViewToggle = () => {
45
46
 
46
47
  const togglePollView = useCallback(
47
48
  id => {
48
- id = typeof id === 'string' ? id : undefined;
49
- const newView = id ? POLL_VIEWS.VOTE : isOpen && view ? null : POLL_VIEWS.CREATE_POLL_QUIZ;
49
+ const newView = match({ id, isOpen, view })
50
+ .with(
51
+ {
52
+ id: P.string,
53
+ },
54
+ () => POLL_VIEWS.VOTE,
55
+ )
56
+ .with(
57
+ {
58
+ isOpen: true,
59
+ view: P.when(view => !!view),
60
+ },
61
+ () => null,
62
+ )
63
+ .otherwise(() => POLL_VIEWS.CREATE_POLL_QUIZ);
64
+
50
65
  setPollState({
51
66
  [POLL_STATE.pollInView]: id,
52
67
  [POLL_STATE.view]: newView,
@@ -70,7 +70,7 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken })
70
70
  alignItems: 'center',
71
71
  }}
72
72
  >
73
- <img src={errorImage} height={80} width={80} />
73
+ <img src={errorImage} height={80} width={80} alt="Token Error" />
74
74
  <Text variant="h4" css={{ textAlign: 'center', mb: '$4', mt: '$10' }}>
75
75
  {error.title}
76
76
  </Text>
@@ -99,7 +99,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
99
99
  setRoleSelector(defaultSelection);
100
100
  } else {
101
101
  // @ts-ignore
102
- if (!(isMobile || isLandscapeHLSStream) || !elements?.chat?.disable_autofocus) {
102
+ if (!(isMobile || isLandscapeHLSStream) && !elements?.chat?.disable_autofocus) {
103
103
  inputRef.current?.focus();
104
104
  }
105
105
  }
@@ -8,7 +8,7 @@ export const MwebChatOption = ({
8
8
  onClick,
9
9
  color = '$on_surface_high',
10
10
  }: {
11
- icon: any;
11
+ icon: React.ReactNode;
12
12
  text: string;
13
13
  onClick: () => void | Promise<void>;
14
14
  color?: string;
@@ -11,7 +11,6 @@ import {
11
11
  useHMSStore,
12
12
  } from '@100mslive/react-sdk';
13
13
  import { Footer } from './Footer/Footer';
14
- import { LeaveRoom } from './Leave/LeaveRoom';
15
14
  import { MoreSettings } from './MoreSettings/MoreSettings';
16
15
  import { HLSFailureModal } from './Notifications/HLSFailureModal';
17
16
  // @ts-ignore: No implicit Any
@@ -57,16 +56,17 @@ export const ConferenceScreen = () => {
57
56
  const noAVPermissions = !(toggleAudio || toggleVideo);
58
57
  // using it in hls stream to show action button when chat is disabled
59
58
  const showChat = !!screenProps.elements?.chat;
60
- const toggleControls = () => {
61
- if (dropdownListRef.current?.length === 0 && isMobileDevice) {
62
- setHideControls(value => !value);
63
- }
64
- };
65
59
  const autoRoomJoined = useRef(isPreviewScreenEnabled);
66
60
  const isMobileHLSStream = useMobileHLSStream();
67
61
  const isLandscapeHLSStream = useLandscapeHLSStream();
68
62
  const isMwebHLSStream = isMobileHLSStream || isLandscapeHLSStream;
69
63
 
64
+ const toggleControls = () => {
65
+ if (dropdownListRef.current?.length === 0 && isMobileDevice && !isMwebHLSStream) {
66
+ setHideControls(value => !value);
67
+ }
68
+ };
69
+
70
70
  useEffect(() => {
71
71
  let timeout: undefined | ReturnType<typeof setTimeout>;
72
72
  dropdownListRef.current = dropdownList || [];
@@ -118,6 +118,8 @@ export const ConferenceScreen = () => {
118
118
  return <FullPageProgress text={roomState === HMSRoomState.Connecting ? 'Joining...' : ''} />;
119
119
  }
120
120
 
121
+ const hideControlsForStreaming = isMwebHLSStream ? true : hideControls;
122
+
121
123
  return (
122
124
  <>
123
125
  {isHLSStarted ? (
@@ -132,7 +134,7 @@ export const ConferenceScreen = () => {
132
134
  css={{
133
135
  h: '$18',
134
136
  transition: 'margin 0.3s ease-in-out',
135
- marginTop: hideControls ? `-${headerRef.current?.clientHeight}px` : 'none',
137
+ marginTop: hideControlsForStreaming ? `-${headerRef.current?.clientHeight}px` : 'none',
136
138
  '@md': {
137
139
  h: '$17',
138
140
  },
@@ -142,11 +144,6 @@ export const ConferenceScreen = () => {
142
144
  <Header />
143
145
  </Box>
144
146
  )}
145
- {isMwebHLSStream && (
146
- <Flex align="center" gap="2" css={{ position: 'absolute', left: '$4', top: '$4', zIndex: 1 }}>
147
- <LeaveRoom screenType={screenProps.screenType} />
148
- </Flex>
149
- )}
150
147
  <Box
151
148
  css={{
152
149
  w: '100%',
@@ -169,7 +166,7 @@ export const ConferenceScreen = () => {
169
166
  <VideoStreamingSection
170
167
  screenType={screenProps.screenType}
171
168
  elements={screenProps.elements}
172
- hideControls={hideControls}
169
+ hideControls={hideControlsForStreaming}
173
170
  />
174
171
  ) : null}
175
172
  </Box>
@@ -181,7 +178,7 @@ export const ConferenceScreen = () => {
181
178
  maxHeight: '$24',
182
179
  transition: 'margin 0.3s ease-in-out',
183
180
  bg: '$background_dim',
184
- marginBottom: hideControls ? `-${footerRef.current?.clientHeight}px` : undefined,
181
+ marginBottom: hideControlsForStreaming ? `-${footerRef.current?.clientHeight}px` : undefined,
185
182
  '@md': {
186
183
  maxHeight: 'unset',
187
184
  bg: screenProps.screenType === 'hls_live_streaming' ? 'transparent' : '$background_dim',
@@ -25,7 +25,12 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
25
25
  import { getMetadata } from '../../common/utils';
26
26
 
27
27
  const dropdownItemCSS = { backgroundColor: '$surface_default', gap: '$4', p: '$8' };
28
- const optionTextCSS = { fontWeight: '$semiBold', color: '$on_surface_high', textTransform: 'none' };
28
+ const optionTextCSS = {
29
+ fontWeight: '$semiBold',
30
+ color: '$on_surface_high',
31
+ textTransform: 'none',
32
+ whiteSpace: 'nowrap',
33
+ };
29
34
 
30
35
  const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleName: string }) => {
31
36
  const vanillaStore = useHMSVanillaStore();
@@ -34,8 +39,8 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
34
39
  const permissions = useHMSStore(selectPermissions);
35
40
  const role = useHMSStore(selectRoleByRoleName(roleName));
36
41
 
37
- let allPeersHaveVideoOn = true;
38
- let allPeersHaveAudioOn = true;
42
+ let isVideoOnForSomePeers = false;
43
+ let isAudioOnForSomePeers = false;
39
44
 
40
45
  peerList.forEach(peer => {
41
46
  if (peer.isLocal) {
@@ -43,8 +48,8 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
43
48
  }
44
49
  const isAudioOn = !!peer.audioTrack && store.tracks[peer.audioTrack]?.enabled;
45
50
  const isVideoOn = !!peer.videoTrack && store.tracks[peer.videoTrack]?.enabled;
46
- allPeersHaveAudioOn = allPeersHaveAudioOn && isAudioOn;
47
- allPeersHaveVideoOn = allPeersHaveVideoOn && isVideoOn;
51
+ isAudioOnForSomePeers = isAudioOnForSomePeers || isAudioOn;
52
+ isVideoOnForSomePeers = isVideoOnForSomePeers || isVideoOn;
48
53
  });
49
54
 
50
55
  const setTrackEnabled = async (type: 'audio' | 'video', enabled = false) => {
@@ -55,11 +60,15 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
55
60
  }
56
61
  };
57
62
 
63
+ if (!role) {
64
+ return null;
65
+ }
66
+
58
67
  return (
59
68
  <>
60
- {role.publishParams.allowed?.includes('audio') && (
69
+ {role.publishParams.allowed.includes('audio') && (
61
70
  <>
62
- {allPeersHaveAudioOn && permissions?.mute ? (
71
+ {isAudioOnForSomePeers && permissions?.mute ? (
63
72
  <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', false)}>
64
73
  <MicOffIcon />
65
74
  <Text variant="sm" css={optionTextCSS}>
@@ -68,20 +77,20 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
68
77
  </Dropdown.Item>
69
78
  ) : null}
70
79
 
71
- {!allPeersHaveAudioOn && permissions?.unmute ? (
80
+ {!isAudioOnForSomePeers && permissions?.unmute ? (
72
81
  <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', true)}>
73
82
  <MicOnIcon />
74
83
  <Text variant="sm" css={optionTextCSS}>
75
- Unmute Audio for All
84
+ Request to Unmute Audio for All
76
85
  </Text>
77
86
  </Dropdown.Item>
78
87
  ) : null}
79
88
  </>
80
89
  )}
81
90
 
82
- {role.publishParams.allowed?.includes('audio') && (
91
+ {role.publishParams.allowed.includes('video') && (
83
92
  <>
84
- {allPeersHaveVideoOn && permissions?.mute ? (
93
+ {isVideoOnForSomePeers && permissions?.mute ? (
85
94
  <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', false)}>
86
95
  <VideoOffIcon />
87
96
  <Text variant="sm" css={optionTextCSS}>
@@ -90,11 +99,11 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam
90
99
  </Dropdown.Item>
91
100
  ) : null}
92
101
 
93
- {!allPeersHaveVideoOn && permissions?.unmute ? (
102
+ {!isVideoOnForSomePeers && permissions?.unmute ? (
94
103
  <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', true)}>
95
104
  <VideoOnIcon />
96
105
  <Text variant="sm" css={optionTextCSS}>
97
- Unmute Video for All
106
+ Request to Unmute Video for All
98
107
  </Text>
99
108
  </Dropdown.Item>
100
109
  ) : null}
@@ -112,11 +121,19 @@ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList
112
121
  const { on_stage_role, off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
113
122
  const canMuteOrUnmute = permissions?.mute || permissions?.unmute;
114
123
  const canRemoveRoleFromStage = permissions?.changeRole && roleName === on_stage_role;
124
+ const role = useHMSStore(selectRoleByRoleName(roleName));
125
+
115
126
  // on stage and off stage roles
116
127
  const canRemoveRoleFromRoom =
117
128
  permissions?.removeOthers && (on_stage_role === roleName || off_stage_roles?.includes(roleName));
118
129
 
119
- if (!(canMuteOrUnmute || canRemoveRoleFromStage || canRemoveRoleFromRoom) || peerList.length === 0) {
130
+ if (
131
+ !(canMuteOrUnmute || canRemoveRoleFromStage || canRemoveRoleFromRoom) ||
132
+ peerList.length === 0 ||
133
+ // if only local peer is present no need to show any options
134
+ (peerList.length === 1 && peerList[0].isLocal) ||
135
+ !role
136
+ ) {
120
137
  return null;
121
138
  }
122
139
 
@@ -165,7 +182,7 @@ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList
165
182
  </Dropdown.Trigger>
166
183
  <Dropdown.Content
167
184
  onClick={e => e.stopPropagation()}
168
- css={{ w: 'max-content', maxWidth: '$64', bg: '$surface_default', py: 0 }}
185
+ css={{ w: 'max-content', bg: '$surface_default', py: 0 }}
169
186
  align="end"
170
187
  >
171
188
  {canRemoveRoleFromStage && (
@@ -1,7 +1,10 @@
1
1
  import React from 'react';
2
- import { Button, Dialog, Text } from '../../..';
2
+ import { useMedia } from 'react-use';
3
+ import { VolumeTwoIcon } from '@100mslive/react-icons';
4
+ import { Button, config, Dialog, IconButton, Text } from '../../..';
3
5
  // @ts-ignore
4
6
  import { DialogContent, DialogRow } from '../../primitives/DialogContent';
7
+ import { useIsLandscape } from '../../common/hooks';
5
8
 
6
9
  export function HLSAutoplayBlockedPrompt({
7
10
  open,
@@ -10,6 +13,33 @@ export function HLSAutoplayBlockedPrompt({
10
13
  open: boolean;
11
14
  unblockAutoPlay: () => Promise<void>;
12
15
  }) {
16
+ const isLandscape = useIsLandscape();
17
+ const isMobile = useMedia(config.media.md);
18
+ if ((isMobile || isLandscape) && open) {
19
+ return (
20
+ <IconButton
21
+ css={{
22
+ border: '1px solid white',
23
+ bg: 'white',
24
+ color: '#000',
25
+ r: '$2',
26
+ }}
27
+ onClick={async () => await unblockAutoPlay()}
28
+ >
29
+ <VolumeTwoIcon width="32" height="32" />
30
+ <Text
31
+ variant="body1"
32
+ css={{
33
+ fontWeight: '$semiBold',
34
+ px: '$2',
35
+ color: '#000',
36
+ }}
37
+ >
38
+ Tap To Unmute
39
+ </Text>
40
+ </IconButton>
41
+ );
42
+ }
13
43
  return (
14
44
  <Dialog.Root
15
45
  open={open}
@@ -1,7 +1,11 @@
1
1
  import React, { forwardRef } from 'react';
2
- import { Flex } from '../../../';
2
+ import { useMedia } from 'react-use';
3
+ import { config, Flex } from '../../../';
4
+ import { useIsLandscape } from '../../common/hooks';
3
5
 
4
6
  export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
7
+ const isLandscape = useIsLandscape();
8
+ const isMobile = useMedia(config.media.md);
5
9
  return (
6
10
  <Flex
7
11
  data-testid="hms-video"
@@ -36,6 +40,8 @@ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
36
40
  minHeight: '0',
37
41
  objectFit: 'contain',
38
42
  width: 'inherit',
43
+ height: isLandscape || isMobile ? '100%' : '',
44
+ position: isLandscape || isMobile ? 'absolute' : '',
39
45
  }}
40
46
  ref={videoRef}
41
47
  playsInline
@@ -0,0 +1,27 @@
1
+ import React, { MouseEvent } from 'react';
2
+ import { PauseIcon, PlayIcon } from '@100mslive/react-icons';
3
+ import { IconButton, Tooltip } from '../../..';
4
+ import { useHMSPlayerContext } from './PlayerContext';
5
+
6
+ export const PlayPauseButton = ({
7
+ isPaused,
8
+ width = 20,
9
+ height = 20,
10
+ }: {
11
+ isPaused: boolean;
12
+ width: number;
13
+ height: number;
14
+ }) => {
15
+ const { hlsPlayer } = useHMSPlayerContext();
16
+ const onClick = async (event: MouseEvent) => {
17
+ event?.stopPropagation();
18
+ isPaused ? await hlsPlayer?.play() : hlsPlayer?.pause();
19
+ };
20
+ return (
21
+ <Tooltip title={isPaused ? 'Play' : 'Pause'} side="top">
22
+ <IconButton onClick={onClick} data-testid="play_pause_btn">
23
+ {isPaused ? <PlayIcon width={width} height={height} /> : <PauseIcon width={width} height={height} />}
24
+ </IconButton>
25
+ </Tooltip>
26
+ );
27
+ };
@@ -0,0 +1,22 @@
1
+ import React, { MouseEventHandler } from 'react';
2
+ import { IconButton, Tooltip } from '../../..';
3
+
4
+ export const SeekControls = ({
5
+ title,
6
+ onClick,
7
+ children,
8
+ css,
9
+ }: {
10
+ title: string;
11
+ onClick?: MouseEventHandler<HTMLButtonElement>;
12
+ css: any;
13
+ children: React.ReactNode;
14
+ }) => {
15
+ return (
16
+ <Tooltip title={title} side="top">
17
+ <IconButton onClick={onClick} data-testid="backward_forward_arrow_btn" css={css}>
18
+ {children}
19
+ </IconButton>
20
+ </Tooltip>
21
+ );
22
+ };
@@ -3,7 +3,7 @@ import { Box, Flex, Slider } from '../../..';
3
3
  import { useHMSPlayerContext } from './PlayerContext';
4
4
  import { getPercentage } from './utils';
5
5
 
6
- export const VideoProgress = () => {
6
+ export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
7
7
  const { hlsPlayer } = useHMSPlayerContext();
8
8
  const [videoProgress, setVideoProgress] = useState<number>(0);
9
9
  const [bufferProgress, setBufferProgress] = useState(0);
@@ -48,7 +48,7 @@ export const VideoProgress = () => {
48
48
  return null;
49
49
  }
50
50
  return (
51
- <Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch' }}>
51
+ <Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch', pointerEvents: isDvr ? '' : 'none' }}>
52
52
  <Slider
53
53
  id="video-actual-rest"
54
54
  css={{
@@ -56,6 +56,7 @@ export const VideoProgress = () => {
56
56
  h: '$2',
57
57
  zIndex: 1,
58
58
  transition: `all .2s ease .5s`,
59
+ pointerEvents: isDvr ? '' : 'none',
59
60
  }}
60
61
  min={0}
61
62
  max={100}
@@ -63,7 +64,7 @@ export const VideoProgress = () => {
63
64
  value={[videoProgress]}
64
65
  showTooltip={false}
65
66
  onValueChange={onProgress}
66
- thumbStyles={{ w: '$6', h: '$6' }}
67
+ thumbStyles={{ w: '$6', h: '$6', display: isDvr ? '' : 'none' }}
67
68
  />
68
69
  <Box
69
70
  id="video-buffer"
@@ -5,7 +5,7 @@ import { useHMSPlayerContext } from './PlayerContext';
5
5
 
6
6
  export const VolumeControl = () => {
7
7
  const { hlsPlayer } = useHMSPlayerContext();
8
- const [volume, setVolume] = useState(hlsPlayer?.volume || 0);
8
+ const [volume, setVolume] = useState(hlsPlayer?.volume ?? 100);
9
9
  const [showSlider, setShowSlider] = useState(false);
10
10
 
11
11
  return (
@@ -2,14 +2,15 @@
2
2
  import { LeftControls, RightControls, VideoControls } from './Controls';
3
3
  // @ts-ignore
4
4
  import { HMSVideo } from './HMSVideo';
5
- import { PlayButton } from './PlayButton';
5
+ import { PlayPauseButton } from './PlayPauseButton';
6
+ import { SeekControls } from './SeekControls';
6
7
  import { VideoProgress } from './VideoProgress';
7
8
  import { VideoTime } from './VideoTime';
8
9
  import { VolumeControl } from './VolumeControl';
9
10
 
10
11
  export const HMSVideoPlayer = {
11
12
  Root: HMSVideo,
12
- PlayButton: PlayButton,
13
+ PlayPauseButton: PlayPauseButton,
13
14
  Progress: VideoProgress,
14
15
  Duration: VideoTime,
15
16
  Volume: VolumeControl,
@@ -18,4 +19,5 @@ export const HMSVideoPlayer = {
18
19
  Left: LeftControls,
19
20
  Right: RightControls,
20
21
  },
22
+ Seeker: SeekControls,
21
23
  };
@@ -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) {
@@ -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,
@@ -287,11 +288,10 @@ export const MwebOptions = ({
287
288
  >
288
289
  {isRecordingLoading ? <Loading /> : <RecordIcon />}
289
290
  <ActionTile.Title>
290
- {isBrowserRecordingOn
291
- ? 'Recording On'
292
- : isRecordingLoading
293
- ? 'Starting Recording'
294
- : 'Start Recording'}
291
+ {match({ isBrowserRecordingOn, isRecordingLoading })
292
+ .with({ isBrowserRecordingOn: true, isRecordingLoading: false }, () => 'Recording On')
293
+ .with({ isRecordingLoading: true }, () => 'Starting Recording')
294
+ .with({ isRecordingLoading: false }, () => 'Start Recording')}
295
295
  </ActionTile.Title>
296
296
  </ActionTile.Root>
297
297
  ) : null}
@@ -28,12 +28,12 @@ export const HandRaisedNotifications = () => {
28
28
  }
29
29
 
30
30
  // Don't show toast message in case of local peer.
31
- if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !on_stage_exp || !isSubscribing) {
31
+ if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
32
32
  return;
33
33
  }
34
34
  const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
35
35
  if (hasPeerHandRaised) {
36
- ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
36
+ ToastBatcher.showToast({ notification, type: on_stage_exp ? 'RAISE_HAND_HLS' : 'RAISE_HAND' });
37
37
  console.debug('Metadata updated', notification.data);
38
38
  }
39
39
  }, [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
  };