mirror of
https://github.com/edumeet/edumeet.git
synced 2026-01-23 10:36:11 +00:00
356 lines
8.5 KiB
JavaScript
356 lines
8.5 KiB
JavaScript
import React, { useState, useRef, useEffect } from 'react';
|
|
import { useWindowSize } from '@react-hook/window-size';
|
|
import { connect } from 'react-redux';
|
|
import PropTypes from 'prop-types';
|
|
import classnames from 'classnames';
|
|
import { withStyles } from '@material-ui/core/styles';
|
|
import * as appPropTypes from '../appPropTypes';
|
|
import * as roomActions from '../../store/actions/roomActions';
|
|
import { withRoomContext } from '../../RoomContext';
|
|
import FullScreenExitIcon from '@material-ui/icons/FullscreenExit';
|
|
import VideoView from './VideoView';
|
|
import ButtonControlBar from '../Controls/ButtonControlBar';
|
|
import IconButton from '@material-ui/core/IconButton';
|
|
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
|
import KeyboardArrowLeftIcon from '@material-ui/icons/KeyboardArrowLeft';
|
|
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
|
|
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
|
|
import useMediaQuery from '@material-ui/core/useMediaQuery';
|
|
import Collapse from '@material-ui/core/Collapse';
|
|
|
|
const styles = (theme) =>
|
|
({
|
|
root :
|
|
{
|
|
position : 'absolute',
|
|
top : 0,
|
|
left : 0,
|
|
height : '100%',
|
|
width : '100%',
|
|
zIndex : 1499
|
|
},
|
|
controls :
|
|
{
|
|
position : 'absolute',
|
|
zIndex : 1520,
|
|
right : 0,
|
|
top : 0,
|
|
display : 'flex',
|
|
flexDirection : 'row',
|
|
justifyContent : 'flex-start',
|
|
alignItems : 'center',
|
|
padding : theme.spacing(1),
|
|
'&.hide' :
|
|
{
|
|
transition : 'opacity 0.1s ease-in-out',
|
|
opacity : 0
|
|
},
|
|
'&.hover' :
|
|
{
|
|
opacity : 1
|
|
}
|
|
},
|
|
buttonControlBarPanel :
|
|
{
|
|
'&.hide' :
|
|
{
|
|
transition : 'opacity 0.1s ease-in-out',
|
|
opacity : 0
|
|
},
|
|
'&.hover' :
|
|
{
|
|
opacity : 1
|
|
}
|
|
},
|
|
button :
|
|
{
|
|
flex : '0 0 auto',
|
|
margin : '0.2vmin',
|
|
borderRadius : 2,
|
|
backgroundColor : 'rgba(255, 255, 255, 0.7)',
|
|
cursor : 'pointer',
|
|
transitionProperty : 'opacity, background-color',
|
|
transitionDuration : '0.15s',
|
|
width : '5vmin',
|
|
height : '5vmin',
|
|
opacity : 0,
|
|
'&.visible' :
|
|
{
|
|
opacity : 1
|
|
}
|
|
},
|
|
collapseButton :
|
|
{
|
|
position : 'fixed',
|
|
display : 'flex',
|
|
zIndex : 30,
|
|
backgroundColor : 'rgba(0,0,0,.1)',
|
|
color : 'white',
|
|
transitionProperty : 'left, bottom',
|
|
transitionDuration : '0.6s',
|
|
[theme.breakpoints.up('md')] :
|
|
{
|
|
top : '50%',
|
|
flexDirection : 'column',
|
|
justifyContent : 'center',
|
|
alignItems : 'center',
|
|
transform : 'translate(0%, -50%)',
|
|
left : theme.spacing(1)
|
|
},
|
|
[theme.breakpoints.down('sm')] :
|
|
{
|
|
flexDirection : 'row',
|
|
bottom : theme.spacing(1),
|
|
left : '50%',
|
|
transform : 'translate(-50%, 0%)'
|
|
}
|
|
},
|
|
expandOpen :
|
|
{
|
|
[theme.breakpoints.up('md')] :
|
|
{
|
|
left : theme.spacing(10)
|
|
},
|
|
[theme.breakpoints.down('sm')] :
|
|
{
|
|
bottom : theme.spacing(10)
|
|
}
|
|
},
|
|
icon :
|
|
{
|
|
fontSize : '5vmin'
|
|
},
|
|
incompatibleVideo :
|
|
{
|
|
position : 'absolute',
|
|
zIndex : 1510,
|
|
top : 0,
|
|
bottom : 0,
|
|
left : 0,
|
|
right : 0,
|
|
display : 'flex',
|
|
flexDirection : 'column',
|
|
justifyContent : 'center',
|
|
alignItems : 'center',
|
|
'& p' :
|
|
{
|
|
padding : '6px 12px',
|
|
borderRadius : 6,
|
|
userSelect : 'none',
|
|
pointerEvents : 'none',
|
|
fontSize : 15,
|
|
color : 'rgba(255, 255, 255, 0.55)'
|
|
}
|
|
}
|
|
});
|
|
|
|
const FullScreenView = (props) =>
|
|
{
|
|
const [ hover, setHover ] = useState(false);
|
|
|
|
let touchTimeout = null;
|
|
|
|
const {
|
|
roomClient,
|
|
advancedMode,
|
|
consumer,
|
|
fullScreenConsumer,
|
|
toggleConsumerFullscreen,
|
|
toolbarsVisible,
|
|
permanentTopBar,
|
|
classes,
|
|
theme
|
|
} = props;
|
|
|
|
const smallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
|
|
|
const [ expanded, setExpanded ] = React.useState(false);
|
|
|
|
let timer = null;
|
|
|
|
const handleExpandClick = () =>
|
|
{
|
|
setExpanded(!expanded);
|
|
};
|
|
|
|
const handleAutoHide = (logical) =>
|
|
{
|
|
logical ?
|
|
timer = setTimeout(() => setExpanded(false), 10000)
|
|
:
|
|
clearTimeout(timer);
|
|
};
|
|
|
|
const elementRef = useRef(null);
|
|
const size = useWindowSize({
|
|
wait : 400
|
|
});
|
|
|
|
useEffect(() =>
|
|
{
|
|
if (!elementRef.current)
|
|
return;
|
|
|
|
if (consumer && consumer.type !== 'simple')
|
|
{
|
|
roomClient.adaptConsumerPreferredLayers(consumer, size[0], size[1]);
|
|
}
|
|
}, [ size, fullScreenConsumer, consumer, roomClient ]);
|
|
|
|
if (!consumer)
|
|
return null;
|
|
|
|
const consumerVisible = (
|
|
Boolean(consumer) &&
|
|
!consumer.locallyPaused &&
|
|
!consumer.remotelyPaused
|
|
);
|
|
|
|
return (
|
|
<div className={classes.root} ref={elementRef}
|
|
onMouseOver={() => setHover(true)}
|
|
onMouseOut={() => setHover(false)}
|
|
onTouchStart={() =>
|
|
{
|
|
if (touchTimeout)
|
|
clearTimeout(touchTimeout);
|
|
|
|
setHover(true);
|
|
}}
|
|
onTouchEnd={() =>
|
|
{
|
|
if (touchTimeout)
|
|
clearTimeout(touchTimeout);
|
|
|
|
touchTimeout = setTimeout(() =>
|
|
{
|
|
setHover(false);
|
|
}, 2000);
|
|
}}
|
|
>
|
|
<div className={classnames(
|
|
classes.controls,
|
|
'hide',
|
|
hover ? 'hover' : null
|
|
)}
|
|
>
|
|
<div
|
|
className={classnames(classes.button, {
|
|
visible : toolbarsVisible || permanentTopBar
|
|
})}
|
|
onClick={(e) =>
|
|
{
|
|
e.stopPropagation();
|
|
toggleConsumerFullscreen(consumer);
|
|
}}
|
|
>
|
|
<FullScreenExitIcon className={classes.icon} />
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={classnames(classes.buttonControlBarPanel,
|
|
'hide',
|
|
hover ? 'hover' : null
|
|
)}
|
|
onMouseEnter={() => handleAutoHide(false)}
|
|
onMouseLeave={() => handleAutoHide(true)}
|
|
>
|
|
<IconButton
|
|
className={classnames(classes.collapseButton, {
|
|
[classes.expandOpen] : expanded
|
|
})}
|
|
onClick={handleExpandClick}
|
|
>
|
|
{smallScreen?
|
|
expanded ?
|
|
<KeyboardArrowDownIcon />
|
|
:
|
|
<KeyboardArrowUpIcon />
|
|
:
|
|
expanded ?
|
|
<KeyboardArrowLeftIcon />
|
|
:
|
|
<KeyboardArrowRightIcon />
|
|
}
|
|
</IconButton>
|
|
|
|
<Collapse in={expanded} timeout='auto' unmountOnExit className={classes.buttonControlBar}>
|
|
<ButtonControlBar />
|
|
</Collapse>
|
|
</div>
|
|
|
|
<VideoView
|
|
advancedMode={advancedMode}
|
|
videoContain
|
|
consumerSpatialLayers={consumer ? consumer.spatialLayers : null}
|
|
consumerTemporalLayers={consumer ? consumer.temporalLayers : null}
|
|
consumerCurrentSpatialLayer={
|
|
consumer ? consumer.currentSpatialLayer : null
|
|
}
|
|
consumerCurrentTemporalLayer={
|
|
consumer ? consumer.currentTemporalLayer : null
|
|
}
|
|
consumerPreferredSpatialLayer={
|
|
consumer ? consumer.preferredSpatialLayer : null
|
|
}
|
|
consumerPreferredTemporalLayer={
|
|
consumer ? consumer.preferredTemporalLayer : null
|
|
}
|
|
videoMultiLayer={consumer && consumer.type !== 'simple'}
|
|
videoTrack={consumer && consumer.track}
|
|
videoVisible={consumerVisible}
|
|
videoCodec={consumer && consumer.codec}
|
|
videoScore={consumer ? consumer.score : null}
|
|
width={size[0]}
|
|
height={size[1]}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
FullScreenView.propTypes =
|
|
{
|
|
roomClient : PropTypes.any.isRequired,
|
|
advancedMode : PropTypes.bool,
|
|
consumer : appPropTypes.Consumer,
|
|
fullScreenConsumer : PropTypes.string,
|
|
toggleConsumerFullscreen : PropTypes.func.isRequired,
|
|
toolbarsVisible : PropTypes.bool,
|
|
permanentTopBar : PropTypes.bool,
|
|
classes : PropTypes.object.isRequired,
|
|
theme : PropTypes.object.isRequired
|
|
};
|
|
|
|
const mapStateToProps = (state) =>
|
|
({
|
|
consumer : state.consumers[state.room.fullScreenConsumer],
|
|
toolbarsVisible : state.room.toolbarsVisible,
|
|
permanentTopBar : state.settings.permanentTopBar,
|
|
fullScreenConsumer : state.room.fullScreenConsumer
|
|
});
|
|
|
|
const mapDispatchToProps = (dispatch) =>
|
|
({
|
|
toggleConsumerFullscreen : (consumer) =>
|
|
{
|
|
if (consumer)
|
|
dispatch(roomActions.toggleConsumerFullscreen(consumer.id));
|
|
}
|
|
});
|
|
|
|
export default withRoomContext(connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps,
|
|
null,
|
|
{
|
|
areStatesEqual : (next, prev) =>
|
|
{
|
|
return (
|
|
prev.consumers[prev.room.fullScreenConsumer] ===
|
|
next.consumers[next.room.fullScreenConsumer] &&
|
|
prev.room.toolbarsVisible === next.room.toolbarsVisible &&
|
|
prev.settings.permanentTopBar === next.settings.permanentTopBar
|
|
);
|
|
}
|
|
}
|
|
)(withStyles(styles, { withTheme: true })(FullScreenView)));
|