@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.
- package/dist/{HLSView-UIPDGADR.js → HLSView-53PDKIS2.js} +239 -144
- package/dist/HLSView-53PDKIS2.js.map +7 -0
- package/dist/Prebuilt/components/Chat/MwebChatOption.d.ts +1 -1
- package/dist/Prebuilt/components/HMSVideo/PlayPauseButton.d.ts +6 -0
- package/dist/Prebuilt/components/HMSVideo/SeekControls.d.ts +7 -0
- package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +3 -1
- package/dist/Prebuilt/components/HMSVideo/index.d.ts +10 -2
- package/dist/Prebuilt/layouts/SidePane.d.ts +1 -1
- package/dist/{chunk-J4NOQ2YL.js → chunk-2ZFAT7KY.js} +339 -218
- package/dist/chunk-2ZFAT7KY.js.map +7 -0
- package/dist/index.cjs.js +932 -708
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +217 -78
- package/dist/meta.esbuild.json +227 -87
- package/package.json +7 -6
- package/src/Prebuilt/components/AppData/useSidepane.js +17 -2
- package/src/Prebuilt/components/AuthToken.jsx +1 -1
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +1 -1
- package/src/Prebuilt/components/Chat/MwebChatOption.tsx +1 -1
- package/src/Prebuilt/components/ConferenceScreen.tsx +11 -14
- package/src/Prebuilt/components/Footer/RoleOptions.tsx +32 -15
- package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.tsx +31 -1
- package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +7 -1
- package/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx +27 -0
- package/src/Prebuilt/components/HMSVideo/SeekControls.tsx +22 -0
- package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +4 -3
- package/src/Prebuilt/components/HMSVideo/VolumeControl.tsx +1 -1
- package/src/Prebuilt/components/HMSVideo/index.ts +4 -2
- package/src/Prebuilt/components/Header/StreamActions.tsx +1 -1
- package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +37 -31
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +5 -5
- package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +2 -2
- package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -1
- package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +19 -8
- package/src/Prebuilt/components/SidePaneTabs.tsx +27 -35
- package/src/Prebuilt/components/StatsForNerds.jsx +14 -6
- package/src/Prebuilt/components/Streaming/Common.jsx +1 -1
- package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +2 -2
- package/src/Prebuilt/components/Toast/ToastBatcher.js +8 -1
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +17 -0
- package/src/Prebuilt/layouts/HLSView.jsx +109 -69
- package/src/Prebuilt/layouts/SidePane.tsx +125 -67
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +2 -1
- package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +1 -1
- package/src/Sheet/Sheet.tsx +4 -0
- package/dist/HLSView-UIPDGADR.js.map +0 -7
- package/dist/chunk-J4NOQ2YL.js.map +0 -7
- 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.
|
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.
|
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.
|
88
|
-
"@100mslive/react-icons": "0.9.8-alpha.
|
89
|
-
"@100mslive/react-sdk": "0.9.8-alpha.
|
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": "
|
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
|
-
|
49
|
-
|
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)
|
102
|
+
if (!(isMobile || isLandscapeHLSStream) && !elements?.chat?.disable_autofocus) {
|
103
103
|
inputRef.current?.focus();
|
104
104
|
}
|
105
105
|
}
|
@@ -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:
|
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={
|
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:
|
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 = {
|
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
|
38
|
-
let
|
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
|
-
|
47
|
-
|
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
|
69
|
+
{role.publishParams.allowed.includes('audio') && (
|
61
70
|
<>
|
62
|
-
{
|
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
|
-
{!
|
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
|
91
|
+
{role.publishParams.allowed.includes('video') && (
|
83
92
|
<>
|
84
|
-
{
|
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
|
-
{!
|
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 (
|
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',
|
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 {
|
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 {
|
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
|
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 {
|
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
|
-
|
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
|
-
|
148
|
-
|
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={() =>
|
151
|
-
data-testid="
|
178
|
+
onClick={() => updateState(MODALS.STATS_FOR_NERDS, true)}
|
179
|
+
data-testid="stats_for_nerds_btn"
|
152
180
|
>
|
153
|
-
<
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
-
)
|
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
|
-
|
292
|
-
:
|
293
|
-
|
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 || !
|
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
|
};
|