Files
multiparty-meeting/app/src/components/MeetingViews/Democratic.js
T

211 lines
4.3 KiB
JavaScript

import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import debounce from 'lodash/debounce';
import { withStyles } from '@material-ui/core/styles';
import Peer from '../Containers/Peer';
import HiddenPeers from '../Containers/HiddenPeers';
import ResizeObserver from 'resize-observer-polyfill';
const RATIO = 1.334;
const PADDING = 100;
const styles = (theme) =>
({
root :
{
width : '100%',
height : '100%',
display : 'flex',
flexDirection : 'row',
flexWrap : 'wrap',
justifyContent : 'center',
alignItems : 'center',
alignContent : 'center',
paddingTop : 70,
paddingBottom : 30
},
peerContainer :
{
overflow : 'hidden',
flex : '0 0 auto',
margin : 6,
boxShadow : 'var(--peer-shadow)',
border : 'var(--peer-border)',
transitionProperty : 'border-color',
'&.active-speaker' :
{
borderColor : 'var(--active-speaker-border-color)'
},
'&.selected' :
{
borderColor : 'var(--selected-peer-border-color)'
}
}
});
class Democratic extends React.Component
{
constructor(props)
{
super(props);
this.state = {
peerWidth : 400,
peerHeight : 300
};
this.peersRef = React.createRef();
}
updateDimensions = debounce(() =>
{
if (!this.peersRef.current)
{
return;
}
const n = this.props.boxes;
if (n === 0)
{
return;
}
const width = this.peersRef.current.clientWidth;
const height = this.peersRef.current.clientHeight - PADDING;
let x, y, space;
for (let rows = 1; rows < 100; rows = rows + 1)
{
x = width / Math.ceil(n / rows);
y = x / RATIO;
if (height < (y * rows))
{
y = height / rows;
x = RATIO * y;
break;
}
space = height - (y * (rows));
if (space < y)
{
break;
}
}
if (Math.ceil(this.state.peerWidth) !== Math.ceil(0.9 * x))
{
this.setState({
peerWidth : 0.9 * x,
peerHeight : 0.9 * y
});
}
}, 200);
componentDidMount()
{
window.addEventListener('resize', this.updateDimensions);
const observer = new ResizeObserver(this.updateDimensions);
observer.observe(this.peersRef.current);
}
componentWillUnmount()
{
window.removeEventListener('resize', this.updateDimensions);
}
componentDidUpdate()
{
this.updateDimensions();
}
render()
{
const {
advancedMode,
activeSpeakerName,
peers,
spotlights,
spotlightsLength,
classes
} = this.props;
const style =
{
'width' : this.state.peerWidth,
'height' : this.state.peerHeight
};
return (
<div className={classes.root} ref={this.peersRef}>
{ Object.keys(peers).map((peerName) =>
{
if (spotlights.find((spotlightsElement) => spotlightsElement === peerName))
{
return (
<div
key={peerName}
className={classnames(classes.peerContainer, {
'selected' : this.props.selectedPeerName === peerName,
'active-speaker' : peerName === activeSpeakerName
})}
>
<Peer
advancedMode={advancedMode}
name={peerName}
style={style}
/>
</div>
);
}
else
{
return('');
}
})}
{ spotlightsLength < Object.keys(peers).length ?
<HiddenPeers
hiddenPeersCount={Object.keys(peers).length - spotlightsLength}
/>
:null
}
</div>
);
}
}
Democratic.propTypes =
{
advancedMode : PropTypes.bool,
peers : PropTypes.object.isRequired,
boxes : PropTypes.number,
activeSpeakerName : PropTypes.string,
selectedPeerName : PropTypes.string,
spotlightsLength : PropTypes.number,
spotlights : PropTypes.array.isRequired,
classes : PropTypes.object.isRequired
};
const mapStateToProps = (state) =>
{
const spotlights = state.room.spotlights;
const spotlightsLength = spotlights ? state.room.spotlights.length : 0;
const boxes = spotlightsLength + Object.values(state.consumers)
.filter((consumer) => consumer.source === 'screen').length;
return {
peers : state.peers,
boxes,
activeSpeakerName : state.room.activeSpeakerName,
selectedPeerName : state.room.selectedPeerName,
spotlights,
spotlightsLength
};
};
export default connect(
mapStateToProps
)(withStyles(styles)(Democratic));