@100mslive/roomkit-react 0.2.8-alpha.5 → 0.2.8-alpha.7
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-CVNJNDUQ.js → HLSView-MYKM5AXS.js} +239 -144
- package/dist/HLSView-MYKM5AXS.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-25HZFDG5.js → chunk-DRBTAFKN.js} +356 -222
- package/dist/chunk-DRBTAFKN.js.map +7 -0
- package/dist/index.cjs.js +949 -712
- 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 +34 -7
- 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 +6 -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-CVNJNDUQ.js.map +0 -7
- package/dist/chunk-25HZFDG5.js.map +0 -7
- package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +0 -13
@@ -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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
108
|
-
|
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>
|
@@ -1,16 +1,15 @@
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
2
2
|
import { useMedia } from 'react-use';
|
3
3
|
import { DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
|
4
|
+
import { match } from 'ts-pattern';
|
4
5
|
import { selectPeerCount, useHMSStore } from '@100mslive/react-sdk';
|
5
6
|
import { CrossIcon } from '@100mslive/react-icons';
|
6
|
-
// @ts-ignore: No implicit Any
|
7
7
|
import { Chat } from './Chat/Chat';
|
8
8
|
import { PaginatedParticipants } from './Footer/PaginatedParticipants';
|
9
9
|
import { ParticipantList } from './Footer/ParticipantList';
|
10
10
|
import { Box, config as cssConfig, Flex, IconButton, Tabs, Text } from '../..';
|
11
11
|
import { Tooltip } from '../../Tooltip';
|
12
12
|
import { ChatSettings } from './ChatSettings';
|
13
|
-
// @ts-ignore: No implicit Any
|
14
13
|
import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
15
14
|
// @ts-ignore: No implicit Any
|
16
15
|
import { useIsSidepaneTypeOpen, useSidepaneReset, useSidepaneToggle } from './AppData/useSidepane';
|
@@ -19,12 +18,15 @@ import { getFormattedCount } from '../common/utils';
|
|
19
18
|
import { SIDE_PANE_OPTIONS } from '../common/constants';
|
20
19
|
|
21
20
|
const tabTriggerCSS = {
|
22
|
-
color: '$
|
21
|
+
color: '$on_surface_low',
|
23
22
|
p: '$4',
|
24
23
|
fontWeight: '$semiBold',
|
25
24
|
fontSize: '$sm',
|
26
25
|
w: '100%',
|
27
26
|
justifyContent: 'center',
|
27
|
+
'&[data-state="active"]': {
|
28
|
+
color: '$on_surface_high',
|
29
|
+
},
|
28
30
|
};
|
29
31
|
|
30
32
|
const ParticipantCount = ({ count }: { count: number }) => {
|
@@ -60,13 +62,16 @@ export const SidePaneTabs = React.memo<{
|
|
60
62
|
const showChatSettings = showChat && isChatOpen && (!isMobile || !isOverlayChat);
|
61
63
|
|
62
64
|
useEffect(() => {
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
match({ activeTab, showChat, showParticipants })
|
66
|
+
.with({ activeTab: SIDE_PANE_OPTIONS.CHAT, showChat: false, showParticipants: true }, () => {
|
67
|
+
setActiveTab(SIDE_PANE_OPTIONS.PARTICIPANTS);
|
68
|
+
})
|
69
|
+
.with({ activeTab: SIDE_PANE_OPTIONS.PARTICIPANTS, showChat: true, showParticipants: false }, () => {
|
70
|
+
setActiveTab(SIDE_PANE_OPTIONS.CHAT);
|
71
|
+
})
|
72
|
+
.with({ showChat: false, showParticipants: false }, () => {
|
73
|
+
resetSidePane();
|
74
|
+
});
|
70
75
|
}, [showChat, activeTab, showParticipants, resetSidePane]);
|
71
76
|
|
72
77
|
useEffect(() => {
|
@@ -102,11 +107,10 @@ export const SidePaneTabs = React.memo<{
|
|
102
107
|
transition: 'margin 0.3s ease-in-out',
|
103
108
|
}}
|
104
109
|
>
|
105
|
-
{isOverlayChat
|
106
|
-
<Chat />
|
107
|
-
|
108
|
-
|
109
|
-
{hideTabs ? (
|
110
|
+
{match({ isOverlayChat, isChatOpen, showChat, hideTabs })
|
111
|
+
.with({ isOverlayChat: true, isChatOpen: true, showChat: true }, () => <Chat />)
|
112
|
+
.with({ hideTabs: true }, () => {
|
113
|
+
return (
|
110
114
|
<>
|
111
115
|
<Flex justify="between" css={{ w: '100%', '&:empty': { display: 'none' } }}>
|
112
116
|
<Text
|
@@ -159,7 +163,10 @@ export const SidePaneTabs = React.memo<{
|
|
159
163
|
<ParticipantList offStageRoles={off_stage_roles} onActive={setActiveRole} />
|
160
164
|
)}
|
161
165
|
</>
|
162
|
-
)
|
166
|
+
);
|
167
|
+
})
|
168
|
+
.otherwise(() => {
|
169
|
+
return (
|
163
170
|
<Tabs.Root
|
164
171
|
value={activeTab}
|
165
172
|
onValueChange={setActiveTab}
|
@@ -170,24 +177,10 @@ export const SidePaneTabs = React.memo<{
|
|
170
177
|
>
|
171
178
|
<Flex css={{ w: '100%' }}>
|
172
179
|
<Tabs.List css={{ flexGrow: 1, borderRadius: '$2', bg: '$surface_default' }}>
|
173
|
-
<Tabs.Trigger
|
174
|
-
value={SIDE_PANE_OPTIONS.CHAT}
|
175
|
-
onClick={toggleChat}
|
176
|
-
css={{
|
177
|
-
...tabTriggerCSS,
|
178
|
-
color: activeTab !== SIDE_PANE_OPTIONS.CHAT ? '$on_surface_low' : '$on_surface_high',
|
179
|
-
}}
|
180
|
-
>
|
180
|
+
<Tabs.Trigger value={SIDE_PANE_OPTIONS.CHAT} onClick={toggleChat} css={tabTriggerCSS}>
|
181
181
|
{chat_title}
|
182
182
|
</Tabs.Trigger>
|
183
|
-
<Tabs.Trigger
|
184
|
-
value={SIDE_PANE_OPTIONS.PARTICIPANTS}
|
185
|
-
onClick={toggleParticipants}
|
186
|
-
css={{
|
187
|
-
...tabTriggerCSS,
|
188
|
-
color: activeTab !== SIDE_PANE_OPTIONS.PARTICIPANTS ? '$on_surface_low' : '$on_surface_high',
|
189
|
-
}}
|
190
|
-
>
|
183
|
+
<Tabs.Trigger value={SIDE_PANE_OPTIONS.PARTICIPANTS} onClick={toggleParticipants} css={tabTriggerCSS}>
|
191
184
|
Participants
|
192
185
|
<ParticipantCount count={peerCount} />
|
193
186
|
</Tabs.Trigger>
|
@@ -217,9 +210,8 @@ export const SidePaneTabs = React.memo<{
|
|
217
210
|
<Chat />
|
218
211
|
</Tabs.Content>
|
219
212
|
</Tabs.Root>
|
220
|
-
)
|
221
|
-
|
222
|
-
)}
|
213
|
+
);
|
214
|
+
})}
|
223
215
|
</Flex>
|
224
216
|
);
|
225
217
|
});
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
2
|
+
import { match, P } from 'ts-pattern';
|
2
3
|
import {
|
3
4
|
selectHMSStats,
|
4
5
|
selectLocalPeerID,
|
@@ -188,11 +189,15 @@ const LocalPeerStats = () => {
|
|
188
189
|
};
|
189
190
|
|
190
191
|
const TrackStats = ({ trackID, layer, local }) => {
|
191
|
-
const selector = layer
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
192
|
+
const selector = match({ trackID, layer, local })
|
193
|
+
.with(
|
194
|
+
{
|
195
|
+
layer: P.when(layer => !!layer),
|
196
|
+
},
|
197
|
+
() => selectHMSStats.localVideoTrackStatsByLayer(layer)(trackID),
|
198
|
+
)
|
199
|
+
.with({ local: P.when(local => !!local) }, () => selectHMSStats.localAudioTrackStatsByID(trackID))
|
200
|
+
.otherwise(() => selectHMSStats.trackStatsByID(trackID));
|
196
201
|
const stats = useHMSStatsStore(selector);
|
197
202
|
if (!stats) {
|
198
203
|
return null;
|
@@ -215,7 +220,10 @@ const TrackStats = ({ trackID, layer, local }) => {
|
|
215
220
|
{!inbound && <StatsRow label="Quality Limitation Reason" value={stats.qualityLimitationReason} />}
|
216
221
|
</>
|
217
222
|
)}
|
218
|
-
<StatsRow
|
223
|
+
<StatsRow
|
224
|
+
label="Round Trip Time"
|
225
|
+
value={stats.roundTripTime ? `${(stats.roundTripTime * 1000).toFixed(3)} ms` : '-'}
|
226
|
+
/>
|
219
227
|
</Flex>
|
220
228
|
);
|
221
229
|
};
|
@@ -20,7 +20,7 @@ export const StreamCard = ({ title, subtitle, Icon, imgSrc = '', css = {}, onCli
|
|
20
20
|
onClick={onClick}
|
21
21
|
>
|
22
22
|
<Text css={{ alignSelf: 'center', p: '$4' }}>
|
23
|
-
{imgSrc ? <img src={imgSrc} height={40} width={40} /> : <Icon width={40} height={40} />}
|
23
|
+
{imgSrc ? <img src={imgSrc} height={40} width={40} alt="Streaming" /> : <Icon width={40} height={40} />}
|
24
24
|
</Text>
|
25
25
|
<Box css={{ flex: '1 1 0', mx: '$8' }}>
|
26
26
|
<Text variant="h6" css={{ mb: '$4' }}>
|
@@ -289,7 +289,7 @@ export const TileMenuContent = ({
|
|
289
289
|
data-testid={isVideoEnabled ? 'mute_video_participant_btn' : 'unmute_video_participant_btn'}
|
290
290
|
>
|
291
291
|
{isVideoEnabled ? <VideoOnIcon height={20} width={20} /> : <VideoOffIcon height={20} width={20} />}
|
292
|
-
<span>{isVideoEnabled ? 'Mute' : 'Request Unmute'}</span>
|
292
|
+
<span>{isVideoEnabled ? 'Mute Video' : 'Request to Unmute Video'}</span>
|
293
293
|
</StyledMenuTile.ItemButton>
|
294
294
|
) : null}
|
295
295
|
|
@@ -304,7 +304,7 @@ export const TileMenuContent = ({
|
|
304
304
|
data-testid={isAudioEnabled ? 'mute_audio_participant_btn' : 'unmute_audio_participant_btn'}
|
305
305
|
>
|
306
306
|
{isAudioEnabled ? <MicOnIcon height={20} width={20} /> : <MicOffIcon height={20} width={20} />}
|
307
|
-
<span>{isAudioEnabled ? 'Mute' : 'Request Unmute'}</span>
|
307
|
+
<span>{isAudioEnabled ? 'Mute Audio' : 'Request to Unmute Audio'}</span>
|
308
308
|
</StyledMenuTile.ItemButton>
|
309
309
|
) : null}
|
310
310
|
|
@@ -3,6 +3,7 @@ import { ToastManager } from './ToastManager';
|
|
3
3
|
|
4
4
|
export const ToastBatcher = {
|
5
5
|
toastsType: new Map(),
|
6
|
+
toastCache: {},
|
6
7
|
showToastInternal({ notification, duration, type }) {
|
7
8
|
let notificationType = type;
|
8
9
|
if (!type) {
|
@@ -40,7 +41,13 @@ export const ToastBatcher = {
|
|
40
41
|
},
|
41
42
|
showToast({ notification, duration = 3000, type }) {
|
42
43
|
try {
|
43
|
-
this.
|
44
|
+
if (!this.toastCache[notification.id]) {
|
45
|
+
this.showToastInternal({ notification, duration, type });
|
46
|
+
}
|
47
|
+
this.toastCache[notification.id] = true;
|
48
|
+
if (Object.keys(this.toastCache).length > 100) {
|
49
|
+
this.toastCache = {};
|
50
|
+
}
|
44
51
|
} catch (err) {
|
45
52
|
console.debug('Notifications', err);
|
46
53
|
}
|
@@ -123,6 +123,23 @@ export const ToastConfig = {
|
|
123
123
|
},
|
124
124
|
},
|
125
125
|
RAISE_HAND: {
|
126
|
+
single: notification => {
|
127
|
+
return {
|
128
|
+
title: `${notification.data?.name} raised hand`,
|
129
|
+
icon: <HandIcon />,
|
130
|
+
};
|
131
|
+
},
|
132
|
+
multiple: notifications => {
|
133
|
+
const count = new Set(notifications.map(notification => notification.data?.id)).size;
|
134
|
+
return {
|
135
|
+
title: `${notifications[notifications.length - 1].data?.name} ${
|
136
|
+
count > 1 ? `${count} and others` : ''
|
137
|
+
} raised hand`,
|
138
|
+
icon: <HandIcon />,
|
139
|
+
};
|
140
|
+
},
|
141
|
+
},
|
142
|
+
RAISE_HAND_HLS: {
|
126
143
|
single: notification => {
|
127
144
|
return {
|
128
145
|
title: `${notification.data?.name} raised hand`,
|
@@ -14,7 +14,7 @@ import {
|
|
14
14
|
useHMSStore,
|
15
15
|
useHMSVanillaStore,
|
16
16
|
} from '@100mslive/react-sdk';
|
17
|
-
import {
|
17
|
+
import { BackwardArrowIcon, ColoredHandIcon, ForwardArrowIcon, GoLiveIcon } from '@100mslive/react-icons';
|
18
18
|
import { ChatToggle } from '../components/Footer/ChatToggle';
|
19
19
|
import { HlsStatsOverlay } from '../components/HlsStatsOverlay';
|
20
20
|
import { HMSVideoPlayer } from '../components/HMSVideo';
|
@@ -24,6 +24,7 @@ import { HLSCaptionSelector } from '../components/HMSVideo/HLSCaptionSelector';
|
|
24
24
|
import { HLSQualitySelector } from '../components/HMSVideo/HLSQualitySelector';
|
25
25
|
import { HLSViewTitle } from '../components/HMSVideo/MwebHLSViewTitle';
|
26
26
|
import { HMSPlayerContext } from '../components/HMSVideo/PlayerContext';
|
27
|
+
import { LeaveRoom } from '../components/Leave/LeaveRoom';
|
27
28
|
import { ToastManager } from '../components/Toast/ToastManager';
|
28
29
|
import { Button } from '../../Button';
|
29
30
|
import { IconButton } from '../../IconButton';
|
@@ -58,6 +59,7 @@ const HLSView = () => {
|
|
58
59
|
const [hasCaptions, setHasCaptions] = useState(false);
|
59
60
|
const [currentSelectedQuality, setCurrentSelectedQuality] = useState(null);
|
60
61
|
const [isHlsAutoplayBlocked, setIsHlsAutoplayBlocked] = useState(false);
|
62
|
+
const [isSeekEnabled, setIsSeekEnabled] = useState(false);
|
61
63
|
const [isPaused, setIsPaused] = useState(false);
|
62
64
|
const [show, toggle] = useToggle(false);
|
63
65
|
const lastHlsUrl = usePrevious(hlsUrl);
|
@@ -276,13 +278,13 @@ const HLSView = () => {
|
|
276
278
|
if (controlsTimerRef.current) {
|
277
279
|
clearTimeout(controlsTimerRef.current);
|
278
280
|
}
|
279
|
-
controlsTimerRef.current = setTimeout(() => {
|
280
|
-
setControlsVisible(false);
|
281
|
-
}, 5000);
|
282
281
|
}
|
283
282
|
if (!isFullScreen && controlsTimerRef.current) {
|
284
283
|
clearTimeout(controlsTimerRef.current);
|
285
284
|
}
|
285
|
+
controlsTimerRef.current = setTimeout(() => {
|
286
|
+
setControlsVisible(false);
|
287
|
+
}, 5000);
|
286
288
|
return () => {
|
287
289
|
if (controlsTimerRef.current) {
|
288
290
|
clearTimeout(controlsTimerRef.current);
|
@@ -290,31 +292,43 @@ const HLSView = () => {
|
|
290
292
|
};
|
291
293
|
}, [controlsVisible, isFullScreen, qualityDropDownOpen]);
|
292
294
|
|
293
|
-
const
|
295
|
+
const onSeekTo = useCallback(seek => {
|
296
|
+
hlsPlayer?.seekTo(videoRef.current?.currentTime + seek);
|
297
|
+
}, []);
|
298
|
+
const onDoubleClickHandler = useCallback(
|
294
299
|
event => {
|
295
|
-
|
296
|
-
// logic for invisible when tapping
|
297
|
-
if (event.type === 'ontouchstart' && controlsVisible) {
|
298
|
-
setControlsVisible(false);
|
300
|
+
if (!(isMobile || isLandscape)) {
|
299
301
|
return;
|
300
302
|
}
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
if (controlsTimerRef.current) {
|
309
|
-
clearTimeout(controlsTimerRef.current);
|
310
|
-
}
|
303
|
+
const sidePercentage = (event.screenX * 100) / event.target.clientWidth;
|
304
|
+
setIsSeekEnabled(true);
|
305
|
+
// there is space for pause/unpause button
|
306
|
+
if (sidePercentage < 45) {
|
307
|
+
onSeekTo(-10);
|
308
|
+
} else {
|
309
|
+
onSeekTo(10);
|
311
310
|
}
|
311
|
+
setTimeout(() => {
|
312
|
+
setIsSeekEnabled(false);
|
313
|
+
}, 200);
|
312
314
|
},
|
313
|
-
[
|
315
|
+
[isLandscape, isMobile, onSeekTo],
|
314
316
|
);
|
317
|
+
const onClickHandler = useCallback(() => {
|
318
|
+
if (!(isMobile || isLandscape)) {
|
319
|
+
return;
|
320
|
+
}
|
321
|
+
setControlsVisible(value => !value);
|
322
|
+
if (controlsTimerRef.current) {
|
323
|
+
clearTimeout(controlsTimerRef.current);
|
324
|
+
}
|
325
|
+
}, [isLandscape, isMobile]);
|
315
326
|
const onHoverHandler = useCallback(
|
316
327
|
event => {
|
317
|
-
|
328
|
+
event.preventDefault();
|
329
|
+
if (isMobile || isLandscape) {
|
330
|
+
return;
|
331
|
+
}
|
318
332
|
if (event.type === 'mouseenter' || qualityDropDownOpen) {
|
319
333
|
setControlsVisible(true);
|
320
334
|
return;
|
@@ -328,7 +342,7 @@ const HLSView = () => {
|
|
328
342
|
}
|
329
343
|
}
|
330
344
|
},
|
331
|
-
[controlsVisible, isFullScreen, qualityDropDownOpen],
|
345
|
+
[controlsVisible, isFullScreen, isLandscape, isMobile, qualityDropDownOpen],
|
332
346
|
);
|
333
347
|
|
334
348
|
return (
|
@@ -338,8 +352,9 @@ const HLSView = () => {
|
|
338
352
|
ref={hlsViewRef}
|
339
353
|
direction={isMobile || isLandscape ? 'column' : 'row'}
|
340
354
|
css={{
|
341
|
-
w: sidepane !== '' && isLandscape ? '
|
355
|
+
w: sidepane !== '' && isLandscape ? '' : '100%',
|
342
356
|
h: sidepane !== '' && isMobile ? '36%' : '100%',
|
357
|
+
flex: '1 1 0',
|
343
358
|
}}
|
344
359
|
>
|
345
360
|
{hlsUrl && !streamEnded ? (
|
@@ -357,7 +372,9 @@ const HLSView = () => {
|
|
357
372
|
margin: '0 auto',
|
358
373
|
}}
|
359
374
|
>
|
360
|
-
|
375
|
+
{!(isMobile || isLandscape) && (
|
376
|
+
<HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
|
377
|
+
)}
|
361
378
|
{showLoader && (
|
362
379
|
<Flex
|
363
380
|
align="center"
|
@@ -374,49 +391,55 @@ const HLSView = () => {
|
|
374
391
|
onMouseEnter={onHoverHandler}
|
375
392
|
onMouseMove={onHoverHandler}
|
376
393
|
onMouseLeave={onHoverHandler}
|
377
|
-
|
378
|
-
|
394
|
+
onClick={onClickHandler}
|
395
|
+
onDoubleClick={e => {
|
396
|
+
onDoubleClickHandler(e);
|
397
|
+
}}
|
379
398
|
>
|
380
399
|
<>
|
381
400
|
{isMobile || isLandscape ? (
|
382
401
|
<>
|
383
402
|
{!showLoader && (
|
384
|
-
<
|
403
|
+
<Flex
|
404
|
+
align="center"
|
405
|
+
justify="center"
|
385
406
|
css={{
|
386
|
-
|
387
|
-
top: '40%',
|
388
|
-
left: '50%',
|
389
|
-
transform: 'translateY(-40%) translateX(-50%)',
|
390
|
-
padding: '$4',
|
407
|
+
bg: '#00000066',
|
391
408
|
display: 'inline-flex',
|
392
|
-
|
393
|
-
gap: '$1',
|
394
|
-
bg: 'rgba(0, 0, 0, 0.6)',
|
409
|
+
gap: '$2',
|
395
410
|
zIndex: 1,
|
411
|
+
size: '100%',
|
396
412
|
visibility: controlsVisible ? `` : `hidden`,
|
397
413
|
opacity: controlsVisible ? `1` : '0',
|
398
414
|
}}
|
399
415
|
>
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
416
|
+
<HMSVideoPlayer.Seeker
|
417
|
+
title="backward"
|
418
|
+
css={{
|
419
|
+
visibility: isSeekEnabled ? `` : `hidden`,
|
420
|
+
opacity: isSeekEnabled ? `1` : '0',
|
421
|
+
}}
|
422
|
+
>
|
423
|
+
<BackwardArrowIcon width={32} height={32} />
|
424
|
+
</HMSVideoPlayer.Seeker>
|
425
|
+
<Box
|
426
|
+
css={{
|
427
|
+
bg: 'rgba(0, 0, 0, 0.6)',
|
428
|
+
r: '$round',
|
429
|
+
}}
|
430
|
+
>
|
431
|
+
<HMSVideoPlayer.PlayPauseButton isPaused={isPaused} width={48} height={48} />
|
432
|
+
</Box>
|
433
|
+
<HMSVideoPlayer.Seeker
|
434
|
+
title="forward"
|
435
|
+
css={{
|
436
|
+
visibility: isSeekEnabled ? `` : `hidden`,
|
437
|
+
opacity: isSeekEnabled ? `1` : '0',
|
438
|
+
}}
|
439
|
+
>
|
440
|
+
<ForwardArrowIcon width={32} height={32} />
|
441
|
+
</HMSVideoPlayer.Seeker>
|
442
|
+
</Flex>
|
420
443
|
)}
|
421
444
|
<Flex
|
422
445
|
ref={controlsRef}
|
@@ -429,6 +452,7 @@ const HLSView = () => {
|
|
429
452
|
left: '0',
|
430
453
|
width: '100%',
|
431
454
|
flexShrink: 0,
|
455
|
+
zIndex: 1,
|
432
456
|
visibility: controlsVisible ? `` : `hidden`,
|
433
457
|
opacity: controlsVisible ? `1` : '0',
|
434
458
|
}}
|
@@ -438,10 +462,15 @@ const HLSView = () => {
|
|
438
462
|
p: '$4 $8',
|
439
463
|
}}
|
440
464
|
>
|
465
|
+
<HMSVideoPlayer.Controls.Left>
|
466
|
+
<LeaveRoom screenType={screenType} />
|
467
|
+
</HMSVideoPlayer.Controls.Left>
|
441
468
|
<HMSVideoPlayer.Controls.Right>
|
442
469
|
{isLandscape && <ChatToggle />}
|
443
|
-
{hasCaptions &&
|
444
|
-
|
470
|
+
{hasCaptions && !isHlsAutoplayBlocked && (
|
471
|
+
<HLSCaptionSelector isEnabled={isCaptionEnabled} />
|
472
|
+
)}
|
473
|
+
{availableLayers.length > 0 && !isHlsAutoplayBlocked ? (
|
445
474
|
<HLSQualitySelector
|
446
475
|
layers={availableLayers}
|
447
476
|
onOpenChange={setQualityDropDownOpen}
|
@@ -451,6 +480,7 @@ const HLSView = () => {
|
|
451
480
|
isAuto={isUserSelectedAuto}
|
452
481
|
/>
|
453
482
|
) : null}
|
483
|
+
<HLSAutoplayBlockedPrompt open={isHlsAutoplayBlocked} unblockAutoPlay={unblockAutoPlay} />
|
454
484
|
</HMSVideoPlayer.Controls.Right>
|
455
485
|
</HMSVideoPlayer.Controls.Root>
|
456
486
|
</Flex>
|
@@ -458,13 +488,14 @@ const HLSView = () => {
|
|
458
488
|
) : null}
|
459
489
|
<Flex
|
460
490
|
ref={controlsRef}
|
461
|
-
direction=
|
491
|
+
direction={isMobile ? 'columnReverse' : 'column'}
|
462
492
|
justify="end"
|
463
493
|
align="start"
|
464
494
|
css={{
|
465
495
|
position: 'absolute',
|
466
496
|
bottom: '0',
|
467
497
|
left: '0',
|
498
|
+
zIndex: 1,
|
468
499
|
background:
|
469
500
|
isMobile || isLandscape
|
470
501
|
? ''
|
@@ -477,9 +508,7 @@ const HLSView = () => {
|
|
477
508
|
opacity: controlsVisible ? `1` : '0',
|
478
509
|
}}
|
479
510
|
>
|
480
|
-
{
|
481
|
-
<HMSVideoPlayer.Progress />
|
482
|
-
)}
|
511
|
+
<HMSVideoPlayer.Progress isDvr={hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR} />
|
483
512
|
<HMSVideoPlayer.Controls.Root
|
484
513
|
css={{
|
485
514
|
p: '$4 $8',
|
@@ -488,12 +517,23 @@ const HLSView = () => {
|
|
488
517
|
<HMSVideoPlayer.Controls.Left>
|
489
518
|
{!(isMobile || isLandscape) && (
|
490
519
|
<>
|
491
|
-
<HMSVideoPlayer.
|
492
|
-
onClick={
|
493
|
-
|
520
|
+
<HMSVideoPlayer.Seeker
|
521
|
+
onClick={() => {
|
522
|
+
onSeekTo(-10);
|
523
|
+
}}
|
524
|
+
title="backward"
|
525
|
+
>
|
526
|
+
<BackwardArrowIcon width={20} height={20} />
|
527
|
+
</HMSVideoPlayer.Seeker>
|
528
|
+
<HMSVideoPlayer.PlayPauseButton isPaused={isPaused} />
|
529
|
+
<HMSVideoPlayer.Seeker
|
530
|
+
onClick={() => {
|
531
|
+
onSeekTo(10);
|
494
532
|
}}
|
495
|
-
|
496
|
-
|
533
|
+
title="forward"
|
534
|
+
>
|
535
|
+
<ForwardArrowIcon width={20} height={20} />
|
536
|
+
</HMSVideoPlayer.Seeker>
|
497
537
|
{!isVideoLive ? <HMSVideoPlayer.Duration /> : null}
|
498
538
|
<HMSVideoPlayer.Volume />
|
499
539
|
</>
|
@@ -551,9 +591,6 @@ const HLSView = () => {
|
|
551
591
|
) : null}
|
552
592
|
</HMSVideoPlayer.Controls.Right>
|
553
593
|
</HMSVideoPlayer.Controls.Root>
|
554
|
-
{(isMobile || isLandscape) && hlsState?.variants[0]?.playlist_type === HLSPlaylistType.DVR ? (
|
555
|
-
<HMSVideoPlayer.Progress />
|
556
|
-
) : null}
|
557
594
|
</Flex>
|
558
595
|
</>
|
559
596
|
</HMSVideoPlayer.Root>
|
@@ -564,6 +601,9 @@ const HLSView = () => {
|
|
564
601
|
</>
|
565
602
|
) : (
|
566
603
|
<Flex align="center" justify="center" direction="column" css={{ size: '100%', px: '$10' }}>
|
604
|
+
<Flex align="center" gap="2" css={{ position: 'absolute', left: '$4', top: '$4', zIndex: 1 }}>
|
605
|
+
<LeaveRoom screenType={screenType} />
|
606
|
+
</Flex>
|
567
607
|
<Flex css={{ c: '$on_surface_high', r: '$round', bg: '$surface_default', p: '$2' }}>
|
568
608
|
{streamEnded ? <ColoredHandIcon height={56} width={56} /> : <GoLiveIcon height={56} width={56} />}
|
569
609
|
</Flex>
|