@100mslive/roomkit-react 0.2.8-alpha.3 → 0.2.8-alpha.4
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-PACDZWJN.js → HLSView-UIPDGADR.js} +509 -234
- package/dist/HLSView-UIPDGADR.js.map +7 -0
- package/dist/Prebuilt/common/hooks.d.ts +3 -0
- package/dist/Prebuilt/components/HMSVideo/FullscreenButton.d.ts +5 -0
- package/dist/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.d.ts +5 -0
- package/dist/Prebuilt/components/HMSVideo/HLSCaptionSelector.d.ts +1 -2
- package/dist/Prebuilt/components/HMSVideo/HLSQualitySelector.d.ts +12 -0
- package/dist/Prebuilt/components/HMSVideo/MwebHLSViewTitle.d.ts +2 -0
- package/dist/Prebuilt/components/HMSVideo/PlayButton.d.ts +6 -0
- package/dist/Prebuilt/components/HMSVideo/PlayerContext.d.ts +8 -0
- package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +2 -0
- package/dist/Prebuilt/components/HMSVideo/VideoTime.d.ts +2 -0
- package/dist/Prebuilt/components/HMSVideo/VolumeControl.d.ts +2 -0
- package/dist/Prebuilt/components/HMSVideo/index.d.ts +17 -0
- package/dist/Prebuilt/components/HMSVideo/utils.d.ts +9 -0
- package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +1 -3
- package/dist/Prebuilt/components/MwebLandscapePrompt.d.ts +1 -1
- package/dist/Prebuilt/components/RaiseHand.d.ts +2 -0
- package/dist/Prebuilt/components/SidePaneTabs.d.ts +1 -0
- package/dist/{chunk-2QHBD2VO.js → chunk-J4NOQ2YL.js} +562 -450
- package/dist/chunk-J4NOQ2YL.js.map +7 -0
- package/dist/index.cjs.js +1556 -1145
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +429 -156
- package/dist/meta.esbuild.json +445 -164
- package/package.json +6 -6
- package/src/Prebuilt/common/hooks.ts +21 -0
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +26 -10
- package/src/Prebuilt/components/ConferenceScreen.tsx +34 -2
- package/src/Prebuilt/components/Footer/Footer.tsx +0 -1
- package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -1
- package/src/Prebuilt/components/HMSVideo/FullscreenButton.tsx +13 -0
- package/src/Prebuilt/components/HMSVideo/{HLSAutoplayBlockedPrompt.jsx → HLSAutoplayBlockedPrompt.tsx} +13 -6
- package/src/Prebuilt/components/HMSVideo/HLSCaptionSelector.tsx +4 -2
- package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.tsx +241 -0
- package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +3 -0
- package/src/Prebuilt/components/HMSVideo/MwebHLSViewTitle.tsx +91 -0
- package/src/Prebuilt/components/HMSVideo/PlayButton.tsx +27 -0
- package/src/Prebuilt/components/HMSVideo/PlayerContext.tsx +15 -0
- package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +81 -0
- package/src/Prebuilt/components/HMSVideo/VideoTime.tsx +42 -0
- package/src/Prebuilt/components/HMSVideo/{VolumeControl.jsx → VolumeControl.tsx} +7 -5
- package/src/Prebuilt/components/HMSVideo/{index.js → index.ts} +2 -0
- package/src/Prebuilt/components/HMSVideo/utils.ts +35 -0
- package/src/Prebuilt/components/Leave/LeaveRoom.tsx +7 -1
- package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +38 -25
- package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +3 -1
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +1 -1
- package/src/Prebuilt/components/MwebLandscapePrompt.tsx +5 -0
- package/src/Prebuilt/components/{RaiseHand.jsx → RaiseHand.tsx} +3 -2
- package/src/Prebuilt/components/SidePaneTabs.tsx +29 -10
- package/src/Prebuilt/layouts/HLSView.jsx +272 -156
- package/src/Prebuilt/layouts/SidePane.tsx +21 -10
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +11 -1
- package/dist/HLSView-PACDZWJN.js.map +0 -7
- package/dist/chunk-2QHBD2VO.js.map +0 -7
- package/src/Prebuilt/components/HMSVideo/FullscreenButton.jsx +0 -18
- package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +0 -127
- package/src/Prebuilt/components/HMSVideo/HMSVIdeoUtils.js +0 -27
- package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +0 -76
- package/src/Prebuilt/components/HMSVideo/VideoTime.jsx +0 -33
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { selectHLSState, selectPeerCount, useHMSStore } from '@100mslive/react-sdk';
|
|
3
|
+
import { Flex } from '../../../Layout';
|
|
4
|
+
import { Text } from '../../../Text';
|
|
5
|
+
// @ts-ignore: No implicit any
|
|
6
|
+
import { Logo } from '../Header/HeaderComponents';
|
|
7
|
+
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
|
8
|
+
// @ts-ignore: No implicit Any
|
|
9
|
+
import { getFormattedCount } from '../../common/utils';
|
|
10
|
+
import { getTime } from './utils';
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
player handler --> left -> go live with timer or live, right -> expand icon
|
|
14
|
+
inbetween -> play pause icon, double tap to go back/forward
|
|
15
|
+
seekbar
|
|
16
|
+
half page will have chat or participant view
|
|
17
|
+
*/
|
|
18
|
+
export const HLSViewTitle = () => {
|
|
19
|
+
const peerCount = useHMSStore(selectPeerCount);
|
|
20
|
+
const hlsState = useHMSStore(selectHLSState);
|
|
21
|
+
const intervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
22
|
+
const { screenType } = useRoomLayoutConferencingScreen();
|
|
23
|
+
const [liveTime, setLiveTime] = useState(0);
|
|
24
|
+
|
|
25
|
+
const startTimer = useCallback(() => {
|
|
26
|
+
intervalRef.current = setInterval(() => {
|
|
27
|
+
const timeStamp = hlsState?.variants[0]?.[screenType === 'hls_live_streaming' ? 'startedAt' : 'initialisedAt'];
|
|
28
|
+
if (hlsState?.running && timeStamp) {
|
|
29
|
+
setLiveTime(Date.now() - timeStamp.getTime());
|
|
30
|
+
}
|
|
31
|
+
}, 60000);
|
|
32
|
+
}, [hlsState?.running, hlsState?.variants, screenType]);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (hlsState?.running) {
|
|
36
|
+
startTimer();
|
|
37
|
+
const timeStamp = hlsState?.variants[0]?.[screenType === 'hls_live_streaming' ? 'startedAt' : 'initialisedAt'];
|
|
38
|
+
if (hlsState?.running && timeStamp) {
|
|
39
|
+
setLiveTime(Date.now() - timeStamp.getTime());
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!hlsState?.running && intervalRef.current) {
|
|
43
|
+
clearInterval(intervalRef.current);
|
|
44
|
+
}
|
|
45
|
+
return () => {
|
|
46
|
+
if (intervalRef.current) {
|
|
47
|
+
clearInterval(intervalRef.current);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}, [hlsState?.running, hlsState?.variants, screenType, startTimer]);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Flex
|
|
54
|
+
gap="4"
|
|
55
|
+
align="center"
|
|
56
|
+
css={{
|
|
57
|
+
position: 'relative',
|
|
58
|
+
h: 'fit-content',
|
|
59
|
+
w: '100%',
|
|
60
|
+
borderBottom: '1px solid $border_bright',
|
|
61
|
+
p: '$8',
|
|
62
|
+
backgroundColor: '$surface_dim',
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
<Logo />
|
|
66
|
+
<Flex direction="column">
|
|
67
|
+
<Text variant="sub2" css={{ fontWeight: '$semiBold' }}>
|
|
68
|
+
Tech Talk
|
|
69
|
+
</Text>
|
|
70
|
+
<Flex gap="1">
|
|
71
|
+
<Text variant="caption" css={{ color: '$on_surface_medium' }}>
|
|
72
|
+
{getFormattedCount(peerCount) + ' watching'}
|
|
73
|
+
</Text>
|
|
74
|
+
<Flex
|
|
75
|
+
direction="column"
|
|
76
|
+
css={{
|
|
77
|
+
w: '$3',
|
|
78
|
+
h: '$3',
|
|
79
|
+
backgroundColor: '$on_surface_medium',
|
|
80
|
+
borderRadius: '50%',
|
|
81
|
+
alignSelf: 'center',
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
84
|
+
<Text variant="caption" css={{ color: '$on_surface_medium' }}>
|
|
85
|
+
{'Started ' + getTime(liveTime) + ' ago'}
|
|
86
|
+
</Text>
|
|
87
|
+
</Flex>
|
|
88
|
+
</Flex>
|
|
89
|
+
</Flex>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
@@ -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 PlayButton = ({
|
|
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,15 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { HMSHLSPlayer } from '@100mslive/hls-player';
|
|
3
|
+
|
|
4
|
+
type IHMSPlayerContext = {
|
|
5
|
+
hlsPlayer?: HMSHLSPlayer;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const HMSPlayerContext = React.createContext<IHMSPlayerContext>({
|
|
9
|
+
hlsPlayer: undefined,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const useHMSPlayerContext = () => {
|
|
13
|
+
const context = useContext(HMSPlayerContext);
|
|
14
|
+
return context;
|
|
15
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Box, Flex, Slider } from '../../..';
|
|
3
|
+
import { useHMSPlayerContext } from './PlayerContext';
|
|
4
|
+
import { getPercentage } from './utils';
|
|
5
|
+
|
|
6
|
+
export const VideoProgress = () => {
|
|
7
|
+
const { hlsPlayer } = useHMSPlayerContext();
|
|
8
|
+
const [videoProgress, setVideoProgress] = useState<number>(0);
|
|
9
|
+
const [bufferProgress, setBufferProgress] = useState(0);
|
|
10
|
+
const videoEl = hlsPlayer?.getVideoElement();
|
|
11
|
+
|
|
12
|
+
const onValueChange = (time: number) => {
|
|
13
|
+
hlsPlayer?.seekTo(time);
|
|
14
|
+
};
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (!videoEl) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const timeupdateHandler = () => {
|
|
20
|
+
if (!videoEl) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const videoProgress = Math.floor(getPercentage(videoEl.currentTime, videoEl.duration));
|
|
24
|
+
let bufferProgress = 0;
|
|
25
|
+
if (videoEl.buffered.length > 0) {
|
|
26
|
+
bufferProgress = Math.floor(getPercentage(videoEl.buffered?.end(0), videoEl.duration));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setVideoProgress(isNaN(videoProgress) ? 0 : videoProgress);
|
|
30
|
+
setBufferProgress(isNaN(bufferProgress) ? 0 : bufferProgress);
|
|
31
|
+
};
|
|
32
|
+
videoEl.addEventListener('timeupdate', timeupdateHandler);
|
|
33
|
+
return function cleanup() {
|
|
34
|
+
videoEl?.removeEventListener('timeupdate', timeupdateHandler);
|
|
35
|
+
};
|
|
36
|
+
}, [videoEl]);
|
|
37
|
+
|
|
38
|
+
const onProgress = (progress: number[]) => {
|
|
39
|
+
const progress1 = Math.floor(getPercentage(progress[0], 100));
|
|
40
|
+
const videoEl = hlsPlayer?.getVideoElement();
|
|
41
|
+
const currentTime = (progress1 * (videoEl?.duration || 0)) / 100;
|
|
42
|
+
if (onValueChange) {
|
|
43
|
+
onValueChange(currentTime);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (!videoEl) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return (
|
|
51
|
+
<Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch' }}>
|
|
52
|
+
<Slider
|
|
53
|
+
id="video-actual-rest"
|
|
54
|
+
css={{
|
|
55
|
+
cursor: 'pointer',
|
|
56
|
+
h: '$2',
|
|
57
|
+
zIndex: 1,
|
|
58
|
+
transition: `all .2s ease .5s`,
|
|
59
|
+
}}
|
|
60
|
+
min={0}
|
|
61
|
+
max={100}
|
|
62
|
+
step={1}
|
|
63
|
+
value={[videoProgress]}
|
|
64
|
+
showTooltip={false}
|
|
65
|
+
onValueChange={onProgress}
|
|
66
|
+
thumbStyles={{ w: '$6', h: '$6' }}
|
|
67
|
+
/>
|
|
68
|
+
<Box
|
|
69
|
+
id="video-buffer"
|
|
70
|
+
css={{
|
|
71
|
+
h: '$2',
|
|
72
|
+
width: `${bufferProgress - videoProgress}%`,
|
|
73
|
+
background: '$on_surface_high',
|
|
74
|
+
position: 'absolute',
|
|
75
|
+
left: `${videoProgress}%`,
|
|
76
|
+
opacity: '25%',
|
|
77
|
+
}}
|
|
78
|
+
/>
|
|
79
|
+
</Flex>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { HMSHLSPlayerEvents } from '@100mslive/hls-player';
|
|
3
|
+
import { Text } from '../../../Text';
|
|
4
|
+
import { useHMSPlayerContext } from './PlayerContext';
|
|
5
|
+
import { getDurationFromSeconds } from './utils';
|
|
6
|
+
|
|
7
|
+
export const VideoTime = () => {
|
|
8
|
+
const { hlsPlayer } = useHMSPlayerContext();
|
|
9
|
+
const [videoTime, setVideoTime] = useState('');
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const timeupdateHandler = (currentTime: number) => {
|
|
13
|
+
const videoEl = hlsPlayer?.getVideoElement();
|
|
14
|
+
if (videoEl) {
|
|
15
|
+
setVideoTime(getDurationFromSeconds(videoEl.duration - currentTime));
|
|
16
|
+
} else {
|
|
17
|
+
setVideoTime(getDurationFromSeconds(currentTime));
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
if (hlsPlayer) {
|
|
21
|
+
hlsPlayer.on(HMSHLSPlayerEvents.CURRENT_TIME, timeupdateHandler);
|
|
22
|
+
}
|
|
23
|
+
return function cleanup() {
|
|
24
|
+
hlsPlayer?.off(HMSHLSPlayerEvents.CURRENT_TIME, timeupdateHandler);
|
|
25
|
+
};
|
|
26
|
+
}, [hlsPlayer]);
|
|
27
|
+
|
|
28
|
+
return hlsPlayer ? (
|
|
29
|
+
<Text
|
|
30
|
+
variant="body1"
|
|
31
|
+
css={{
|
|
32
|
+
minWidth: '$16',
|
|
33
|
+
c: '$on_surface_medium',
|
|
34
|
+
display: 'flex',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
fontWeight: '$regular',
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
-{videoTime}
|
|
40
|
+
</Text>
|
|
41
|
+
) : null;
|
|
42
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { VolumeOneIcon, VolumeTwoIcon, VolumeZeroIcon } from '@100mslive/react-icons';
|
|
3
|
-
import { Flex, Slider } from '
|
|
3
|
+
import { Flex, Slider } from '../../..';
|
|
4
|
+
import { useHMSPlayerContext } from './PlayerContext';
|
|
4
5
|
|
|
5
|
-
export const VolumeControl = (
|
|
6
|
-
const
|
|
6
|
+
export const VolumeControl = () => {
|
|
7
|
+
const { hlsPlayer } = useHMSPlayerContext();
|
|
8
|
+
const [volume, setVolume] = useState(hlsPlayer?.volume || 0);
|
|
7
9
|
const [showSlider, setShowSlider] = useState(false);
|
|
8
10
|
|
|
9
11
|
return (
|
|
@@ -47,7 +49,7 @@ export const VolumeControl = ({ hlsPlayer }) => {
|
|
|
47
49
|
step={1}
|
|
48
50
|
value={[volume]}
|
|
49
51
|
onValueChange={volume => {
|
|
50
|
-
hlsPlayer
|
|
52
|
+
hlsPlayer?.setVolume(volume[0]);
|
|
51
53
|
setVolume(volume[0]);
|
|
52
54
|
}}
|
|
53
55
|
thumbStyles={{ w: '$6', h: '$6' }}
|
|
@@ -56,7 +58,7 @@ export const VolumeControl = ({ hlsPlayer }) => {
|
|
|
56
58
|
);
|
|
57
59
|
};
|
|
58
60
|
|
|
59
|
-
const VolumeIcon = ({ volume, onClick }) => {
|
|
61
|
+
const VolumeIcon = ({ volume, onClick }: { volume: number; onClick: () => void }) => {
|
|
60
62
|
if (volume === 0) {
|
|
61
63
|
return <VolumeZeroIcon style={{ cursor: 'pointer', transition: 'color 0.3s' }} onClick={onClick} />;
|
|
62
64
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function getPercentage(a: number, b: number) {
|
|
2
|
+
return (a / b) * 100;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Take a time in seconds and return its equivalent time in hh:mm:ss format
|
|
7
|
+
* @param {number} timeInSeconds if given as floating point value, it is floored.
|
|
8
|
+
*
|
|
9
|
+
* @returns a string representing timeInSeconds in HH:MM:SS format.
|
|
10
|
+
*/
|
|
11
|
+
export function getDurationFromSeconds(timeInSeconds: number) {
|
|
12
|
+
let time = Math.floor(timeInSeconds);
|
|
13
|
+
const hours = Math.floor(time / 3600);
|
|
14
|
+
time = time - hours * 3600;
|
|
15
|
+
const minutes = Math.floor(time / 60);
|
|
16
|
+
const seconds = Math.floor(time - minutes * 60);
|
|
17
|
+
|
|
18
|
+
const prefixedMinutes = `${minutes < 10 ? `0${minutes}` : minutes}`;
|
|
19
|
+
const prefixedSeconds = `${seconds < 10 ? `0${seconds}` : seconds}`;
|
|
20
|
+
|
|
21
|
+
let videoTimeStr = `${prefixedMinutes}:${prefixedSeconds}`;
|
|
22
|
+
if (hours) {
|
|
23
|
+
const prefixedHours = `${hours < 10 ? `0${hours}` : hours}`;
|
|
24
|
+
videoTimeStr = `${prefixedHours}:${prefixedMinutes}:${prefixedSeconds}`;
|
|
25
|
+
}
|
|
26
|
+
return videoTimeStr;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getTime(timeInMilles: number) {
|
|
30
|
+
const timeInSeconds = Math.floor(timeInMilles / 1000);
|
|
31
|
+
const hours = Math.floor(timeInSeconds / 3600);
|
|
32
|
+
const minutes = Math.floor((timeInSeconds % 3600) / 60);
|
|
33
|
+
const hour = hours !== 0 ? `${hours < 10 ? '0' : ''}${hours}` : '';
|
|
34
|
+
return hour + `${hour ? 'h:' : ''}` + minutes + 'm';
|
|
35
|
+
}
|
|
@@ -18,6 +18,7 @@ import { config as cssConfig } from '../../../Theme';
|
|
|
18
18
|
import { ToastManager } from '../Toast/ToastManager';
|
|
19
19
|
import { DesktopLeaveRoom } from './DesktopLeaveRoom';
|
|
20
20
|
import { MwebLeaveRoom } from './MwebLeaveRoom';
|
|
21
|
+
import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
|
|
21
22
|
|
|
22
23
|
export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen }) => {
|
|
23
24
|
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
@@ -33,6 +34,8 @@ export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen
|
|
|
33
34
|
);
|
|
34
35
|
const hlsState = useHMSStore(selectHLSState);
|
|
35
36
|
const hmsActions = useHMSActions();
|
|
37
|
+
const isMobileHLSStream = useMobileHLSStream();
|
|
38
|
+
const isLandscapeHLSStream = useLandscapeHLSStream();
|
|
36
39
|
|
|
37
40
|
const stopStream = async () => {
|
|
38
41
|
try {
|
|
@@ -61,8 +64,11 @@ export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen
|
|
|
61
64
|
if (!permissions || !isConnected) {
|
|
62
65
|
return null;
|
|
63
66
|
}
|
|
67
|
+
if (isMobileHLSStream || isLandscapeHLSStream) {
|
|
68
|
+
return <MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} />;
|
|
69
|
+
}
|
|
64
70
|
return isMobile ? (
|
|
65
|
-
<MwebLeaveRoom leaveRoom={leaveRoom}
|
|
71
|
+
<MwebLeaveRoom leaveRoom={leaveRoom} endRoom={endRoom} />
|
|
66
72
|
) : (
|
|
67
73
|
<DesktopLeaveRoom leaveRoom={leaveRoom} screenType={screenType} endRoom={endRoom} />
|
|
68
74
|
);
|
|
@@ -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,20 @@ 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,
|
|
21
22
|
}: {
|
|
22
23
|
leaveRoom: (options?: { endStream?: boolean }) => Promise<void>;
|
|
23
|
-
screenType: keyof ConferencingScreen;
|
|
24
24
|
endRoom: () => Promise<void>;
|
|
25
25
|
}) => {
|
|
26
26
|
const [open, setOpen] = useState(false);
|
|
27
|
+
const { screenType } = useRoomLayoutConferencingScreen();
|
|
27
28
|
const [showLeaveRoomAlert, setShowLeaveRoomAlert] = useState(false);
|
|
28
29
|
const [showEndStreamAlert, setShowEndStreamAlert] = useState(false);
|
|
29
30
|
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
|
@@ -43,20 +44,7 @@ export const MwebLeaveRoom = ({
|
|
|
43
44
|
{showLeaveOptions ? (
|
|
44
45
|
<Sheet.Root open={open} onOpenChange={setOpen}>
|
|
45
46
|
<Sheet.Trigger asChild>
|
|
46
|
-
<
|
|
47
|
-
key="LeaveRoom"
|
|
48
|
-
data-testid="leave_room_btn"
|
|
49
|
-
css={{
|
|
50
|
-
borderTopRightRadius: '$1',
|
|
51
|
-
borderBottomRightRadius: '$1',
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
<Tooltip title="Leave Room">
|
|
55
|
-
<Box>
|
|
56
|
-
<ExitIcon style={{ transform: 'rotate(180deg)' }} />
|
|
57
|
-
</Box>
|
|
58
|
-
</Tooltip>
|
|
59
|
-
</LeaveIconButton>
|
|
47
|
+
<LeaveButton onClick={() => setOpen(!open)} />
|
|
60
48
|
</Sheet.Trigger>
|
|
61
49
|
<Sheet.Content>
|
|
62
50
|
<LeaveCard
|
|
@@ -88,13 +76,7 @@ export const MwebLeaveRoom = ({
|
|
|
88
76
|
</Sheet.Content>
|
|
89
77
|
</Sheet.Root>
|
|
90
78
|
) : (
|
|
91
|
-
<
|
|
92
|
-
<Tooltip title="Leave Room">
|
|
93
|
-
<Box>
|
|
94
|
-
<ExitIcon style={{ transform: 'rotate(180deg)' }} />
|
|
95
|
-
</Box>
|
|
96
|
-
</Tooltip>
|
|
97
|
-
</LeaveIconButton>
|
|
79
|
+
<LeaveButton onClick={() => setShowLeaveRoomAlert(true)} />
|
|
98
80
|
)}
|
|
99
81
|
<Sheet.Root open={showEndStreamAlert} onOpenChange={setShowEndStreamAlert}>
|
|
100
82
|
<Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }}>
|
|
@@ -114,3 +96,34 @@ export const MwebLeaveRoom = ({
|
|
|
114
96
|
</Fragment>
|
|
115
97
|
);
|
|
116
98
|
};
|
|
99
|
+
|
|
100
|
+
const LeaveButton = ({ onClick }: { onClick: () => void }) => {
|
|
101
|
+
const isMobileHLSStream = useMobileHLSStream();
|
|
102
|
+
const isLandscapeHLSStream = useLandscapeHLSStream();
|
|
103
|
+
|
|
104
|
+
return isMobileHLSStream || isLandscapeHLSStream ? (
|
|
105
|
+
<IconButton key="LeaveRoom" data-testid="leave_room_btn" onClick={() => onClick()}>
|
|
106
|
+
<Tooltip title="Leave Room">
|
|
107
|
+
<Box>
|
|
108
|
+
<CrossIcon />
|
|
109
|
+
</Box>
|
|
110
|
+
</Tooltip>
|
|
111
|
+
</IconButton>
|
|
112
|
+
) : (
|
|
113
|
+
<LeaveIconButton
|
|
114
|
+
key="LeaveRoom"
|
|
115
|
+
data-testid="leave_room_btn"
|
|
116
|
+
css={{
|
|
117
|
+
borderTopRightRadius: '$1',
|
|
118
|
+
borderBottomRightRadius: '$1',
|
|
119
|
+
}}
|
|
120
|
+
onClick={() => onClick()}
|
|
121
|
+
>
|
|
122
|
+
<Tooltip title="Leave Room">
|
|
123
|
+
<Box>
|
|
124
|
+
<ExitIcon style={{ transform: 'rotate(180deg)' }} />
|
|
125
|
+
</Box>
|
|
126
|
+
</Tooltip>
|
|
127
|
+
</LeaveIconButton>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
@@ -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
|
-
|
|
23
|
+
const isLandscapeHLSStream = useLandscapeHLSStream();
|
|
24
|
+
return isMobile || isLandscapeHLSStream ? (
|
|
23
25
|
<MwebOptions elements={elements} screenType={screenType} />
|
|
24
26
|
) : (
|
|
25
27
|
<DesktopOptions elements={elements} screenType={screenType} />
|
|
@@ -120,7 +120,7 @@ export const MwebOptions = ({
|
|
|
120
120
|
<Sheet.Root open={openOptionsSheet} onOpenChange={setOpenOptionsSheet}>
|
|
121
121
|
<Tooltip title="More options">
|
|
122
122
|
<Sheet.Trigger asChild data-testid="more_settings_btn">
|
|
123
|
-
<IconButton>
|
|
123
|
+
<IconButton css={{ '@md': { bg: screenType === 'hls_live_streaming' ? '$surface_default' : '' } }}>
|
|
124
124
|
<HamburgerMenuIcon />
|
|
125
125
|
</IconButton>
|
|
126
126
|
</Sheet.Trigger>
|
|
@@ -6,12 +6,14 @@ import { Box, Flex } from '../../Layout';
|
|
|
6
6
|
import { Dialog } from '../../Modal';
|
|
7
7
|
import { Text } from '../../Text';
|
|
8
8
|
import { config as cssConfig } from '../../Theme';
|
|
9
|
+
import { useLandscapeHLSStream } from '../common/hooks';
|
|
9
10
|
// @ts-ignore
|
|
10
11
|
import { isMobileUserAgent } from '../common/utils';
|
|
11
12
|
|
|
12
13
|
export const MwebLandscapePrompt = () => {
|
|
13
14
|
const [showMwebLandscapePrompt, setShowMwebLandscapePrompt] = useState(false);
|
|
14
15
|
const isLandscape = useMedia(cssConfig.media.ls);
|
|
16
|
+
const isLandscapeHLSStream = useLandscapeHLSStream();
|
|
15
17
|
|
|
16
18
|
useEffect(() => {
|
|
17
19
|
if (!isMobileUserAgent) {
|
|
@@ -36,6 +38,9 @@ export const MwebLandscapePrompt = () => {
|
|
|
36
38
|
};
|
|
37
39
|
}, [isLandscape]);
|
|
38
40
|
|
|
41
|
+
if (isLandscapeHLSStream) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
39
44
|
return (
|
|
40
45
|
<Dialog.Root open={showMwebLandscapePrompt} onOpenChange={setShowMwebLandscapePrompt}>
|
|
41
46
|
<Dialog.Portal>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { HandIcon } from '@100mslive/react-icons';
|
|
2
|
+
import { HandIcon, HandRaiseSlashedIcon } from '@100mslive/react-icons';
|
|
3
3
|
import { Tooltip } from '../../Tooltip';
|
|
4
|
+
// @ts-ignore: No implicit Any
|
|
4
5
|
import IconButton from '../IconButton';
|
|
5
6
|
// @ts-ignore: No implicit Any
|
|
6
7
|
import { useMyMetadata } from './hooks/useMetadata';
|
|
@@ -10,7 +11,7 @@ export const RaiseHand = () => {
|
|
|
10
11
|
return (
|
|
11
12
|
<Tooltip title={isHandRaised ? 'Lower hand' : 'Raise hand'}>
|
|
12
13
|
<IconButton data-testid="hand_raise_btn" active={!isHandRaised} onClick={async () => await toggleHandRaise()}>
|
|
13
|
-
<HandIcon />
|
|
14
|
+
{isHandRaised ? <HandRaiseSlashedIcon /> : <HandIcon />}
|
|
14
15
|
</IconButton>
|
|
15
16
|
</Tooltip>
|
|
16
17
|
);
|
|
@@ -40,18 +40,19 @@ const ParticipantCount = ({ count }: { count: number }) => {
|
|
|
40
40
|
export const SidePaneTabs = React.memo<{
|
|
41
41
|
active: 'Participants | Chat';
|
|
42
42
|
hideControls?: boolean;
|
|
43
|
-
|
|
43
|
+
hideTab?: boolean;
|
|
44
|
+
}>(({ active = SIDE_PANE_OPTIONS.CHAT, hideControls, hideTab = false }) => {
|
|
44
45
|
const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
|
|
45
46
|
const toggleParticipants = useSidepaneToggle(SIDE_PANE_OPTIONS.PARTICIPANTS);
|
|
46
47
|
const resetSidePane = useSidepaneReset();
|
|
47
48
|
const [activeTab, setActiveTab] = useState(active);
|
|
48
49
|
const [activeRole, setActiveRole] = useState('');
|
|
49
50
|
const peerCount = useHMSStore(selectPeerCount);
|
|
50
|
-
const { elements } = useRoomLayoutConferencingScreen();
|
|
51
|
+
const { elements, screenType } = useRoomLayoutConferencingScreen();
|
|
51
52
|
const chat_title = elements?.chat?.chat_title || 'Chat';
|
|
52
53
|
const showChat = !!elements?.chat;
|
|
53
54
|
const showParticipants = !!elements?.participant_list;
|
|
54
|
-
const hideTabs = !(showChat && showParticipants);
|
|
55
|
+
const hideTabs = !(showChat && showParticipants) || hideTab;
|
|
55
56
|
const isMobile = useMedia(cssConfig.media.md);
|
|
56
57
|
const isOverlayChat = !!elements?.chat?.is_overlay && isMobile;
|
|
57
58
|
const { off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
|
|
@@ -107,10 +108,19 @@ export const SidePaneTabs = React.memo<{
|
|
|
107
108
|
<>
|
|
108
109
|
{hideTabs ? (
|
|
109
110
|
<>
|
|
110
|
-
<Flex justify="between" css={{ w: '100%' }}>
|
|
111
|
-
<Text
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
<Flex justify="between" css={{ w: '100%', '&:empty': { display: 'none' } }}>
|
|
112
|
+
<Text
|
|
113
|
+
variant="sm"
|
|
114
|
+
css={{
|
|
115
|
+
fontWeight: '$semiBold',
|
|
116
|
+
p: '$4',
|
|
117
|
+
c: '$on_surface_high',
|
|
118
|
+
pr: '$12',
|
|
119
|
+
'&:empty': { display: 'none' },
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
{activeTab === SIDE_PANE_OPTIONS.CHAT ? (
|
|
123
|
+
screenType !== 'hls_live_streaming' && chat_title
|
|
114
124
|
) : (
|
|
115
125
|
<span>
|
|
116
126
|
Participants
|
|
@@ -122,7 +132,12 @@ export const SidePaneTabs = React.memo<{
|
|
|
122
132
|
{showChatSettings ? <ChatSettings /> : null}
|
|
123
133
|
{isOverlayChat && isChatOpen ? null : (
|
|
124
134
|
<IconButton
|
|
125
|
-
css={{
|
|
135
|
+
css={{
|
|
136
|
+
my: '$1',
|
|
137
|
+
color: '$on_surface_medium',
|
|
138
|
+
'&:hover': { color: '$on_surface_high' },
|
|
139
|
+
'&:empty': { display: 'none' },
|
|
140
|
+
}}
|
|
126
141
|
onClick={e => {
|
|
127
142
|
e.stopPropagation();
|
|
128
143
|
if (activeTab === SIDE_PANE_OPTIONS.CHAT) {
|
|
@@ -133,12 +148,16 @@ export const SidePaneTabs = React.memo<{
|
|
|
133
148
|
}}
|
|
134
149
|
data-testid="close_chat"
|
|
135
150
|
>
|
|
136
|
-
<CrossIcon />
|
|
151
|
+
{screenType === 'hls_live_streaming' && isChatOpen ? null : <CrossIcon />}
|
|
137
152
|
</IconButton>
|
|
138
153
|
)}
|
|
139
154
|
</Flex>
|
|
140
155
|
</Flex>
|
|
141
|
-
{
|
|
156
|
+
{activeTab === SIDE_PANE_OPTIONS.CHAT ? (
|
|
157
|
+
<Chat />
|
|
158
|
+
) : (
|
|
159
|
+
<ParticipantList offStageRoles={off_stage_roles} onActive={setActiveRole} />
|
|
160
|
+
)}
|
|
142
161
|
</>
|
|
143
162
|
) : (
|
|
144
163
|
<Tabs.Root
|