@100mslive/roomkit-react 0.3.14 → 0.3.15-alpha.1
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/Diagnostics/components.d.ts +2 -0
- package/dist/{HLSView-67SFNI2P.js → HLSView-33JUAQ33.js} +2 -2
- package/dist/{HLSView-TYHCIAWX.css → HLSView-KKS3ZEYM.css} +3 -3
- package/dist/{HLSView-TYHCIAWX.css.map → HLSView-KKS3ZEYM.css.map} +1 -1
- package/dist/{chunk-VCXILOW6.js → chunk-MTS2LMGT.js} +2324 -11723
- package/dist/chunk-MTS2LMGT.js.map +7 -0
- package/dist/index.cjs.css +2 -2
- package/dist/index.cjs.css.map +1 -1
- package/dist/index.cjs.js +4232 -13646
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +117 -214
- package/dist/meta.esbuild.json +126 -223
- package/package.json +8 -7
- package/src/Diagnostics/AudioTest.tsx +13 -11
- package/src/Diagnostics/BrowserTest.tsx +5 -5
- package/src/Diagnostics/ConnectivityTest.tsx +3 -4
- package/src/Diagnostics/Diagnostics.tsx +34 -18
- package/src/Diagnostics/VideoTest.tsx +7 -7
- package/src/Diagnostics/components.tsx +6 -5
- package/src/Prebuilt/components/Chat/ChatBody.tsx +23 -8
- package/src/Prebuilt/components/Header/AdditionalRoomState.jsx +4 -66
- package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +2 -2
- package/src/Prebuilt/components/VideoLayouts/WhiteboardLayout.tsx +4 -0
- package/dist/Diagnostics/hms.d.ts +0 -9
- package/dist/Prebuilt/components/HMSVideo/PlayButton.d.ts +0 -6
- package/dist/Prebuilt/components/Polls/common/VoterList.d.ts +0 -4
- package/dist/chunk-VCXILOW6.js.map +0 -7
- package/src/Diagnostics/hms.ts +0 -9
- package/src/Prebuilt/common/roles.js +0 -4
- package/src/Prebuilt/components/AppData/useAppConfig.js +0 -7
- package/src/Prebuilt/components/HMSVideo/PlayButton.tsx +0 -27
- package/src/Prebuilt/components/Header/AmbientMusic.jsx +0 -88
- package/src/Prebuilt/components/Image.jsx +0 -7
- package/src/Prebuilt/components/MetaActions.jsx +0 -37
- package/src/Prebuilt/components/Playlist/Playlist.jsx +0 -124
- package/src/Prebuilt/components/Playlist/PlaylistControls.jsx +0 -172
- package/src/Prebuilt/components/Playlist/PlaylistItem.jsx +0 -51
- package/src/Prebuilt/components/Playlist/VideoPlayer.jsx +0 -95
- package/src/Prebuilt/components/Polls/CreatePollQuiz/Timer.jsx +0 -71
- package/src/Prebuilt/components/Polls/common/VoterList.tsx +0 -22
- package/src/Prebuilt/components/ScreenshareHintModal.jsx +0 -37
- /package/dist/{HLSView-67SFNI2P.js.map → HLSView-33JUAQ33.js.map} +0 -0
package/src/Diagnostics/hms.ts
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
// @ts-check
|
2
|
-
import { HMSReactiveStore } from '@100mslive/hms-video-store';
|
3
|
-
|
4
|
-
const hms = new HMSReactiveStore();
|
5
|
-
export const hmsStore = hms.getStore();
|
6
|
-
export const hmsActions = hms.getActions();
|
7
|
-
export const hmsNotifications = hms.getNotifications();
|
8
|
-
export const hmsStats = hms.getStats();
|
9
|
-
export const hmsDiagnostics = hms.getDiagnosticsSDK();
|
@@ -1,7 +0,0 @@
|
|
1
|
-
import { selectAppDataByPath, useHMSStore } from '@100mslive/react-sdk';
|
2
|
-
import { APP_DATA } from '../../common/constants';
|
3
|
-
|
4
|
-
export const useAppConfig = (...path) => {
|
5
|
-
const appConfig = useHMSStore(selectAppDataByPath(APP_DATA.appConfig, ...path));
|
6
|
-
return appConfig;
|
7
|
-
};
|
@@ -1,27 +0,0 @@
|
|
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
|
-
};
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
2
|
-
import { MusicIcon } from '@100mslive/react-icons';
|
3
|
-
import { IconButton, Tooltip } from '../../../';
|
4
|
-
import { useSetUiSettings } from '../AppData/useUISettings';
|
5
|
-
import { useWhenAloneInRoom } from '../../common/hooks';
|
6
|
-
import { UI_SETTINGS } from '../../common/constants';
|
7
|
-
|
8
|
-
const ambientMusicURL = process.env.REACT_APP_AMBIENT_MUSIC;
|
9
|
-
/**
|
10
|
-
* @type HTMLAudioElement
|
11
|
-
*/
|
12
|
-
let ambientAudio = null;
|
13
|
-
if (ambientMusicURL) {
|
14
|
-
try {
|
15
|
-
ambientAudio = new Audio(ambientMusicURL);
|
16
|
-
} catch (err) {
|
17
|
-
console.error(err);
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
/**
|
22
|
-
*
|
23
|
-
* @param {number} threshold the threshold after which the music is played(from the starting to be alone in the room)
|
24
|
-
* @returns {Object}
|
25
|
-
* ready: boolean - the threshold has passed and the music can be played,
|
26
|
-
*
|
27
|
-
* playing: boolean - flag to denote whether music is playing,
|
28
|
-
*
|
29
|
-
* toggleAmbientMusic - function to play/pause the music
|
30
|
-
*/
|
31
|
-
const useAmbientMusic = (threshold = 5 * 1000) => {
|
32
|
-
const audioRef = useRef(ambientAudio);
|
33
|
-
const [userHasEnabled, setEnableAmbientMusic] = useSetUiSettings(UI_SETTINGS.enableAmbientMusic); // user settings
|
34
|
-
const [playing, setPlaying] = useState(false);
|
35
|
-
const { alone: aloneRightNow, aloneForLong } = useWhenAloneInRoom(threshold);
|
36
|
-
// play if user has enabled the setting and been alone for some time
|
37
|
-
const shouldMusicBePlayed = !playing && userHasEnabled && aloneForLong;
|
38
|
-
// pause immediately if user has disabled the setting or not alone anymore
|
39
|
-
const shouldMusicBePaused = playing && (!userHasEnabled || !aloneRightNow);
|
40
|
-
|
41
|
-
useEffect(() => {
|
42
|
-
if (shouldMusicBePlayed && audioRef.current) {
|
43
|
-
audioRef.current.volume = 0.2;
|
44
|
-
audioRef.current.loop = true;
|
45
|
-
audioRef.current.play().catch(err => console.error('Unable to play Ambient Music', err));
|
46
|
-
setPlaying(true);
|
47
|
-
}
|
48
|
-
}, [shouldMusicBePlayed]);
|
49
|
-
|
50
|
-
useEffect(() => {
|
51
|
-
if (shouldMusicBePaused) {
|
52
|
-
audioRef.current.pause();
|
53
|
-
setPlaying(false);
|
54
|
-
}
|
55
|
-
}, [shouldMusicBePaused]);
|
56
|
-
|
57
|
-
useEffect(() => {
|
58
|
-
const ref = audioRef.current;
|
59
|
-
// Stop on leave
|
60
|
-
return () => {
|
61
|
-
if (ref) {
|
62
|
-
ref.pause();
|
63
|
-
}
|
64
|
-
};
|
65
|
-
}, []);
|
66
|
-
|
67
|
-
const toggleAmbientMusic = useCallback(
|
68
|
-
() => setEnableAmbientMusic(!playing), // save user settings
|
69
|
-
[playing, setEnableAmbientMusic],
|
70
|
-
);
|
71
|
-
|
72
|
-
return { ready: aloneForLong, playing, toggleAmbientMusic };
|
73
|
-
};
|
74
|
-
|
75
|
-
export const AmbientMusic = () => {
|
76
|
-
const { ready, playing, toggleAmbientMusic } = useAmbientMusic();
|
77
|
-
if (!ambientAudio || !ready) {
|
78
|
-
return null;
|
79
|
-
}
|
80
|
-
|
81
|
-
return (
|
82
|
-
<Tooltip title={playing ? `Disable Ambient Music` : `Play Ambient Music`} key="ambient-music">
|
83
|
-
<IconButton css={{ mx: '$4' }} onClick={toggleAmbientMusic} active={!playing}>
|
84
|
-
<MusicIcon />
|
85
|
-
</IconButton>
|
86
|
-
</Tooltip>
|
87
|
-
);
|
88
|
-
};
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { selectIsConnectedToRoom, useHMSStore } from '@100mslive/react-sdk';
|
3
|
-
import { BrbIcon, HandIcon } from '@100mslive/react-icons';
|
4
|
-
import { Flex } from '../../Layout';
|
5
|
-
import { Tooltip } from '../../Tooltip';
|
6
|
-
import IconButton from '../IconButton';
|
7
|
-
import { useMyMetadata } from './hooks/useMetadata';
|
8
|
-
|
9
|
-
const MetaActions = ({ isMobile = false, compact = false }) => {
|
10
|
-
const isConnected = useHMSStore(selectIsConnectedToRoom);
|
11
|
-
const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata();
|
12
|
-
|
13
|
-
if (!isConnected) {
|
14
|
-
return null;
|
15
|
-
}
|
16
|
-
|
17
|
-
return (
|
18
|
-
<Flex align="center" css={{ gap: compact ? '$4' : '$8' }}>
|
19
|
-
<Tooltip title={`${!isHandRaised ? 'Raise' : 'Unraise'} hand`}>
|
20
|
-
<IconButton
|
21
|
-
onClick={toggleHandRaise}
|
22
|
-
active={!isHandRaised}
|
23
|
-
data-testid={isMobile ? 'raise_hand_btn_mobile' : 'raise_hand_btn'}
|
24
|
-
>
|
25
|
-
<HandIcon />
|
26
|
-
</IconButton>
|
27
|
-
</Tooltip>
|
28
|
-
<Tooltip title={isBRBOn ? `I'm back` : `I'll be right back`}>
|
29
|
-
<IconButton onClick={toggleBRB} active={!isBRBOn} data-testid="brb_btn">
|
30
|
-
<BrbIcon />
|
31
|
-
</IconButton>
|
32
|
-
</Tooltip>
|
33
|
-
</Flex>
|
34
|
-
);
|
35
|
-
};
|
36
|
-
|
37
|
-
export default MetaActions;
|
@@ -1,124 +0,0 @@
|
|
1
|
-
import React, { Fragment, useState } from 'react';
|
2
|
-
import { HMSPlaylistType, selectIsAllowedToPublish, useHMSStore } from '@100mslive/react-sdk';
|
3
|
-
import { AudioPlayerIcon, CrossIcon, VideoPlayerIcon } from '@100mslive/react-icons';
|
4
|
-
import { Box, Dropdown, Flex, Text, Tooltip } from '../../../';
|
5
|
-
import IconButton from '../../IconButton';
|
6
|
-
import { AudioPlaylistControls } from './PlaylistControls';
|
7
|
-
import { PlaylistItem } from './PlaylistItem';
|
8
|
-
import { usePlaylist } from '../hooks/usePlaylist';
|
9
|
-
|
10
|
-
const BrowseAndPlayFromLocal = ({ type, actions }) => {
|
11
|
-
return (
|
12
|
-
<Fragment>
|
13
|
-
<Text as="label" htmlFor={`${type}PlaylistBrowse`} variant="sm" css={{ cursor: 'pointer', mr: '$2' }}>
|
14
|
-
Browse
|
15
|
-
</Text>
|
16
|
-
<input
|
17
|
-
type="file"
|
18
|
-
id={`${type}PlaylistBrowse`}
|
19
|
-
accept={type === HMSPlaylistType.audio ? 'audio/*' : 'video/*'}
|
20
|
-
onChange={e => {
|
21
|
-
const file = e.target.files[0];
|
22
|
-
const id = file.lastModified;
|
23
|
-
actions.setList([
|
24
|
-
{
|
25
|
-
type,
|
26
|
-
id,
|
27
|
-
name: file.name,
|
28
|
-
url: URL.createObjectURL(file),
|
29
|
-
},
|
30
|
-
]);
|
31
|
-
actions.play(id);
|
32
|
-
}}
|
33
|
-
style={{ display: 'none' }}
|
34
|
-
/>
|
35
|
-
</Fragment>
|
36
|
-
);
|
37
|
-
};
|
38
|
-
|
39
|
-
export const Playlist = ({ type }) => {
|
40
|
-
const isAudioPlaylist = type === HMSPlaylistType.audio;
|
41
|
-
const { active, list: playlist, actions } = usePlaylist(type);
|
42
|
-
const [open, setOpen] = useState(false);
|
43
|
-
const [collapse, setCollapse] = useState(false);
|
44
|
-
const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish);
|
45
|
-
if (!isAllowedToPublish.screen || playlist.length === 0) {
|
46
|
-
return null;
|
47
|
-
}
|
48
|
-
|
49
|
-
return (
|
50
|
-
<Fragment>
|
51
|
-
<Dropdown.Root open={open} onOpenChange={setOpen}>
|
52
|
-
<Dropdown.Trigger asChild data-testid={type === HMSPlaylistType.audio ? 'audio_playlist' : 'video_playlist'}>
|
53
|
-
<IconButton active={!active}>
|
54
|
-
<Tooltip title={isAudioPlaylist ? 'Audio Playlist' : 'Video Playlist'}>
|
55
|
-
<Box>{isAudioPlaylist ? <AudioPlayerIcon /> : <VideoPlayerIcon />}</Box>
|
56
|
-
</Tooltip>
|
57
|
-
</IconButton>
|
58
|
-
</Dropdown.Trigger>
|
59
|
-
<Dropdown.Content
|
60
|
-
sideOffset={5}
|
61
|
-
align="center"
|
62
|
-
css={{
|
63
|
-
maxHeight: 'unset',
|
64
|
-
width: '$60',
|
65
|
-
p: '$0',
|
66
|
-
bg: '$surface_bright',
|
67
|
-
border: '1px solid $border_default',
|
68
|
-
}}
|
69
|
-
>
|
70
|
-
<Flex
|
71
|
-
align="center"
|
72
|
-
css={{
|
73
|
-
p: '$4 $8',
|
74
|
-
borderBottom: '1px solid $border_bright',
|
75
|
-
bg: '$surface_default',
|
76
|
-
}}
|
77
|
-
>
|
78
|
-
<Text variant="md" css={{ flex: '1 1 0' }}>
|
79
|
-
{isAudioPlaylist ? 'Audio Player' : 'Video Playlist'}
|
80
|
-
</Text>
|
81
|
-
<BrowseAndPlayFromLocal type={type} actions={actions} />
|
82
|
-
<IconButton
|
83
|
-
css={{ mr: '-$4' }}
|
84
|
-
onClick={async () => {
|
85
|
-
if (active) {
|
86
|
-
await actions.stop();
|
87
|
-
}
|
88
|
-
setOpen(false);
|
89
|
-
setCollapse(false);
|
90
|
-
}}
|
91
|
-
>
|
92
|
-
<CrossIcon width={24} height={24} />
|
93
|
-
</IconButton>
|
94
|
-
</Flex>
|
95
|
-
{!collapse && (
|
96
|
-
<Box css={{ maxHeight: '$96', overflowY: 'auto' }}>
|
97
|
-
{playlist.map(playlistItem => {
|
98
|
-
return (
|
99
|
-
<PlaylistItem
|
100
|
-
key={playlistItem.id}
|
101
|
-
{...playlistItem}
|
102
|
-
onClick={async e => {
|
103
|
-
e.preventDefault();
|
104
|
-
try {
|
105
|
-
await actions.play(playlistItem.id);
|
106
|
-
} catch (e) {
|
107
|
-
// error in playlist, stop or play next
|
108
|
-
}
|
109
|
-
// Close the dropdown list for videoplaylist
|
110
|
-
if (!isAudioPlaylist) {
|
111
|
-
setOpen(false);
|
112
|
-
}
|
113
|
-
}}
|
114
|
-
/>
|
115
|
-
);
|
116
|
-
})}
|
117
|
-
</Box>
|
118
|
-
)}
|
119
|
-
{isAudioPlaylist && <AudioPlaylistControls onToggle={() => setCollapse(value => !value)} />}
|
120
|
-
</Dropdown.Content>
|
121
|
-
</Dropdown.Root>
|
122
|
-
</Fragment>
|
123
|
-
);
|
124
|
-
};
|
@@ -1,172 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import {
|
3
|
-
HMSPlaylistType,
|
4
|
-
selectAudioPlaylist,
|
5
|
-
selectAudioTrackVolume,
|
6
|
-
selectPeerSharingVideoPlaylist,
|
7
|
-
selectVideoPlaylist,
|
8
|
-
selectVideoPlaylistAudioTrackByPeerID,
|
9
|
-
useHMSActions,
|
10
|
-
useHMSStore,
|
11
|
-
} from '@100mslive/react-sdk';
|
12
|
-
import { NextIcon, PauseIcon, PlayIcon, PlaylistIcon, PrevIcon, SpeakerIcon } from '@100mslive/react-icons';
|
13
|
-
import { Box, Flex, IconButton, Slider, Text } from '../../../';
|
14
|
-
import { usePlaylist } from '../hooks/usePlaylist';
|
15
|
-
|
16
|
-
const Progress = ({ type, duration }) => {
|
17
|
-
const selectPlaylist = type === HMSPlaylistType.audio ? selectAudioPlaylist : selectVideoPlaylist;
|
18
|
-
const progress = useHMSStore(selectPlaylist.progress);
|
19
|
-
const hmsActions = useHMSActions();
|
20
|
-
const playlistAction = type === HMSPlaylistType.audio ? hmsActions.audioPlaylist : hmsActions.videoPlaylist;
|
21
|
-
|
22
|
-
if (!duration) {
|
23
|
-
return null;
|
24
|
-
}
|
25
|
-
|
26
|
-
return (
|
27
|
-
<Slider
|
28
|
-
step={1}
|
29
|
-
value={[progress]}
|
30
|
-
onValueChange={e => {
|
31
|
-
playlistAction.seekTo(e[0] * 0.01 * duration);
|
32
|
-
}}
|
33
|
-
/>
|
34
|
-
);
|
35
|
-
};
|
36
|
-
|
37
|
-
export const PlaylistActive = ({ type, onToggle }) => {
|
38
|
-
const isAudioPlaylist = type === HMSPlaylistType.audio;
|
39
|
-
const selector = isAudioPlaylist ? selectAudioPlaylist : selectVideoPlaylist;
|
40
|
-
const active = useHMSStore(selector.selectedItem);
|
41
|
-
if (!active) {
|
42
|
-
return null;
|
43
|
-
}
|
44
|
-
return (
|
45
|
-
<Box css={{ mt: '$8' }}>
|
46
|
-
<Flex justify="between" css={{ w: '100%' }}>
|
47
|
-
<Box>
|
48
|
-
<Text variant="md">{active.name}</Text>
|
49
|
-
{active.metadata?.description && <Text variant="xs">{active.metadata?.description}</Text>}
|
50
|
-
</Box>
|
51
|
-
<IconButton onClick={onToggle} css={{ alignSelf: 'center' }} data-testid="playlist_collapse_btn">
|
52
|
-
<PlaylistIcon />
|
53
|
-
</IconButton>
|
54
|
-
</Flex>
|
55
|
-
</Box>
|
56
|
-
);
|
57
|
-
};
|
58
|
-
|
59
|
-
const Controls = ({ type, css = {} }) => {
|
60
|
-
const { active, hasNext, hasPrevious, actions } = usePlaylist(type);
|
61
|
-
if (!active) {
|
62
|
-
return null;
|
63
|
-
}
|
64
|
-
return (
|
65
|
-
<Flex justify="center" css={css}>
|
66
|
-
<IconButton
|
67
|
-
disabled={!hasPrevious}
|
68
|
-
onClick={() => {
|
69
|
-
actions.playPrevious();
|
70
|
-
}}
|
71
|
-
data-testid="playlist_prev_btn"
|
72
|
-
>
|
73
|
-
<PrevIcon />
|
74
|
-
</IconButton>
|
75
|
-
<IconButton
|
76
|
-
onClick={() => {
|
77
|
-
active.playing ? actions.pause() : actions.play(active.id);
|
78
|
-
}}
|
79
|
-
data-testid="playlist_play_pause_btn"
|
80
|
-
>
|
81
|
-
{active.playing ? <PauseIcon width={32} height={32} /> : <PlayIcon width={32} height={32} />}
|
82
|
-
</IconButton>
|
83
|
-
<IconButton
|
84
|
-
disabled={!hasNext}
|
85
|
-
onClick={() => {
|
86
|
-
actions.playNext();
|
87
|
-
}}
|
88
|
-
data-testid="playlist_next_btn"
|
89
|
-
>
|
90
|
-
<NextIcon />
|
91
|
-
</IconButton>
|
92
|
-
</Flex>
|
93
|
-
);
|
94
|
-
};
|
95
|
-
|
96
|
-
const VolumeControl = () => {
|
97
|
-
const hmsActions = useHMSActions();
|
98
|
-
const volume = useHMSStore(selectVideoPlaylist.volume);
|
99
|
-
const active = useHMSStore(selectVideoPlaylist.selectedItem);
|
100
|
-
const peerSharingPlaylist = useHMSStore(selectPeerSharingVideoPlaylist);
|
101
|
-
const audioTrack = useHMSStore(selectVideoPlaylistAudioTrackByPeerID(peerSharingPlaylist?.id));
|
102
|
-
const audioTrackVolume = useHMSStore(selectAudioTrackVolume(audioTrack?.id));
|
103
|
-
const sliderVolume = active ? volume : audioTrackVolume;
|
104
|
-
|
105
|
-
return (
|
106
|
-
<Flex align="center" css={{ color: '$on_primary_high' }}>
|
107
|
-
<SpeakerIcon />
|
108
|
-
<Slider
|
109
|
-
css={{ mx: '$4', w: '$20' }}
|
110
|
-
min={0}
|
111
|
-
max={100}
|
112
|
-
step={1}
|
113
|
-
value={[Math.floor(sliderVolume ?? 100)]}
|
114
|
-
onValueChange={e => {
|
115
|
-
const value = e[0];
|
116
|
-
if (active) {
|
117
|
-
hmsActions.videoPlaylist.setVolume(value);
|
118
|
-
} else if (audioTrack) {
|
119
|
-
hmsActions.setVolume(value, audioTrack.id);
|
120
|
-
}
|
121
|
-
}}
|
122
|
-
thumbStyles={{ w: '$6', h: '$6' }}
|
123
|
-
/>
|
124
|
-
</Flex>
|
125
|
-
);
|
126
|
-
};
|
127
|
-
|
128
|
-
export const AudioPlaylistControls = ({ onToggle }) => {
|
129
|
-
const { active } = usePlaylist(HMSPlaylistType.audio);
|
130
|
-
if (!active) {
|
131
|
-
return null;
|
132
|
-
}
|
133
|
-
return (
|
134
|
-
<Box
|
135
|
-
css={{
|
136
|
-
p: '$8',
|
137
|
-
borderTop: '1px solid $border_bright',
|
138
|
-
bg: '$surface_default',
|
139
|
-
}}
|
140
|
-
>
|
141
|
-
<Controls type={HMSPlaylistType.audio} />
|
142
|
-
<Progress type={HMSPlaylistType.audio} duration={active.duration} />
|
143
|
-
<PlaylistActive type={HMSPlaylistType.audio} onToggle={onToggle} />
|
144
|
-
</Box>
|
145
|
-
);
|
146
|
-
};
|
147
|
-
|
148
|
-
export const VideoPlaylistControls = ({ children }) => {
|
149
|
-
const { active } = usePlaylist(HMSPlaylistType.video);
|
150
|
-
|
151
|
-
return (
|
152
|
-
<Box
|
153
|
-
css={{
|
154
|
-
p: '$8',
|
155
|
-
mt: '-$24',
|
156
|
-
w: '100%',
|
157
|
-
zIndex: 1,
|
158
|
-
'@lg': {
|
159
|
-
mt: 0,
|
160
|
-
p: '$6',
|
161
|
-
},
|
162
|
-
}}
|
163
|
-
>
|
164
|
-
{active && <Progress type={HMSPlaylistType.video} duration={active.duration} />}
|
165
|
-
<Flex align="center" justify="between">
|
166
|
-
<VolumeControl />
|
167
|
-
{active && <Controls css={{ flex: '1 1 0' }} />}
|
168
|
-
{children}
|
169
|
-
</Flex>
|
170
|
-
</Box>
|
171
|
-
);
|
172
|
-
};
|
@@ -1,51 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { Dropdown, Flex, Text } from '../../../';
|
3
|
-
|
4
|
-
function formatDuration(duration) {
|
5
|
-
if (!duration) {
|
6
|
-
return '';
|
7
|
-
}
|
8
|
-
let mins = Math.floor(duration / 60);
|
9
|
-
if (mins < 10) {
|
10
|
-
mins = `0${String(mins)}`;
|
11
|
-
}
|
12
|
-
let secs = Math.floor(duration % 60);
|
13
|
-
if (secs < 10) {
|
14
|
-
secs = `0${String(secs)}`;
|
15
|
-
}
|
16
|
-
|
17
|
-
return `${mins}:${secs}`;
|
18
|
-
}
|
19
|
-
|
20
|
-
export const PlaylistItem = React.memo(({ name, metadata, duration, selected, onClick }) => {
|
21
|
-
return (
|
22
|
-
<Dropdown.Item
|
23
|
-
css={{
|
24
|
-
flexDirection: 'column',
|
25
|
-
alignItems: 'flex-start',
|
26
|
-
h: '$18',
|
27
|
-
p: '$8',
|
28
|
-
'&:hover': {
|
29
|
-
cursor: 'pointer',
|
30
|
-
bg: '$surface_default',
|
31
|
-
},
|
32
|
-
'&:focus-visible': {
|
33
|
-
bg: '$surface_default',
|
34
|
-
},
|
35
|
-
}}
|
36
|
-
onClick={onClick}
|
37
|
-
>
|
38
|
-
<Flex align="center" justify="between" css={{ width: '100%', minHeight: 0 }}>
|
39
|
-
<Text variant="md" css={{ color: selected ? '$primary_default' : '$on_primary_high' }}>
|
40
|
-
{name}
|
41
|
-
</Text>
|
42
|
-
<Text variant="xs">{formatDuration(duration)}</Text>
|
43
|
-
</Flex>
|
44
|
-
{metadata?.description && (
|
45
|
-
<Text variant="xs" css={{ mt: '$4' }}>
|
46
|
-
{metadata?.description}
|
47
|
-
</Text>
|
48
|
-
)}
|
49
|
-
</Dropdown.Item>
|
50
|
-
);
|
51
|
-
});
|
@@ -1,95 +0,0 @@
|
|
1
|
-
import React, { useRef } from 'react';
|
2
|
-
import { useFullscreen, useToggle } from 'react-use';
|
3
|
-
import screenfull from 'screenfull';
|
4
|
-
import {
|
5
|
-
selectVideoPlaylist,
|
6
|
-
selectVideoPlaylistAudioTrackByPeerID,
|
7
|
-
selectVideoPlaylistVideoTrackByPeerID,
|
8
|
-
useHMSActions,
|
9
|
-
useHMSStore,
|
10
|
-
} from '@100mslive/react-sdk';
|
11
|
-
import { CrossIcon, ExpandIcon, ShrinkIcon } from '@100mslive/react-icons';
|
12
|
-
import { Box, Flex, IconButton, Text, Video, VideoTileStats } from '../../../';
|
13
|
-
import { VideoPlaylistControls } from './PlaylistControls';
|
14
|
-
import { useUISettings } from '../AppData/useUISettings';
|
15
|
-
import { UI_SETTINGS } from '../../common/constants';
|
16
|
-
|
17
|
-
export const VideoPlayer = React.memo(({ peerId }) => {
|
18
|
-
const videoTrack = useHMSStore(selectVideoPlaylistVideoTrackByPeerID(peerId));
|
19
|
-
const audioTrack = useHMSStore(selectVideoPlaylistAudioTrackByPeerID(peerId));
|
20
|
-
const active = useHMSStore(selectVideoPlaylist.selectedItem);
|
21
|
-
const isAudioOnly = useUISettings(UI_SETTINGS.isAudioOnly);
|
22
|
-
const hmsActions = useHMSActions();
|
23
|
-
const ref = useRef(null);
|
24
|
-
const [show, toggle] = useToggle(false);
|
25
|
-
const isFullscreen = useFullscreen(ref, show, {
|
26
|
-
onClose: () => toggle(false),
|
27
|
-
});
|
28
|
-
const showStatsOnTiles = useUISettings(UI_SETTINGS.showStatsOnTiles);
|
29
|
-
|
30
|
-
return (
|
31
|
-
<Flex direction="column" justify="center" css={{ w: '100%', h: '100%' }} ref={ref}>
|
32
|
-
{active && (
|
33
|
-
<Flex
|
34
|
-
justify="between"
|
35
|
-
align="center"
|
36
|
-
css={{
|
37
|
-
bg: '$surface_default',
|
38
|
-
p: '$2 $2 $2 $6',
|
39
|
-
borderTopLeftRadius: '$1',
|
40
|
-
borderTopRightRadius: '$1',
|
41
|
-
}}
|
42
|
-
>
|
43
|
-
<Text css={{ color: '$on_primary_high' }}>{active.name}</Text>
|
44
|
-
<IconButton
|
45
|
-
css={{
|
46
|
-
color: '$on_primary_high',
|
47
|
-
}}
|
48
|
-
onClick={() => {
|
49
|
-
hmsActions.videoPlaylist.stop();
|
50
|
-
}}
|
51
|
-
data-testid="videoplaylist_cross_btn"
|
52
|
-
>
|
53
|
-
<CrossIcon />
|
54
|
-
</IconButton>
|
55
|
-
</Flex>
|
56
|
-
)}
|
57
|
-
{showStatsOnTiles ? (
|
58
|
-
<Box css={{ '& > div': { top: '$14', left: '$8' } }}>
|
59
|
-
<VideoTileStats
|
60
|
-
audioTrackID={audioTrack?.id}
|
61
|
-
videoTrackID={videoTrack?.id}
|
62
|
-
peerID={peerId}
|
63
|
-
isLocal={active}
|
64
|
-
/>
|
65
|
-
</Box>
|
66
|
-
) : null}
|
67
|
-
<Video
|
68
|
-
trackId={videoTrack?.id}
|
69
|
-
attach={!isAudioOnly}
|
70
|
-
css={{
|
71
|
-
objectFit: 'contain',
|
72
|
-
h: 'auto',
|
73
|
-
r: '$1',
|
74
|
-
borderTopLeftRadius: 0,
|
75
|
-
borderTopRightRadius: 0,
|
76
|
-
}}
|
77
|
-
/>
|
78
|
-
<VideoPlaylistControls>
|
79
|
-
{screenfull.enabled && (
|
80
|
-
<IconButton
|
81
|
-
onClick={toggle}
|
82
|
-
css={{
|
83
|
-
color: '$on_primary_high',
|
84
|
-
height: 'max-content',
|
85
|
-
alignSelf: 'center',
|
86
|
-
cursor: 'pointer',
|
87
|
-
}}
|
88
|
-
>
|
89
|
-
{isFullscreen ? <ShrinkIcon /> : <ExpandIcon />}
|
90
|
-
</IconButton>
|
91
|
-
)}
|
92
|
-
</VideoPlaylistControls>
|
93
|
-
</Flex>
|
94
|
-
);
|
95
|
-
});
|