Added user interface for lastN (only peers in lastN are visible, others stay in HiddenPeers component)

This commit is contained in:
Stefan Otto
2018-10-29 12:48:47 +01:00
parent d7ce8253e2
commit ed5ef29fba
8 changed files with 262 additions and 52 deletions
+56 -31
View File
@@ -6,6 +6,7 @@ import debounce from 'lodash/debounce';
import classnames from 'classnames';
import * as stateActions from '../redux/stateActions';
import Peer from './Peer';
import HiddenPeers from './HiddenPeers';
class Filmstrip extends Component
{
@@ -26,11 +27,11 @@ class Filmstrip extends Component
// person has spoken yet, the first peer in the list of peers.
getActivePeerName = () =>
{
if (this.props.selectedPeerName)
if (this.props.selectedPeerName)
{
return this.props.selectedPeerName;
}
if (this.state.lastSpeaker)
{
return this.state.lastSpeaker;
@@ -52,7 +53,7 @@ class Filmstrip extends Component
{
let ratio = 4 / 3;
if (this.isSharingCamera(this.getActivePeerName()))
if (this.isSharingCamera(this.getActivePeerName()))
{
ratio *= 2;
}
@@ -70,11 +71,11 @@ class Filmstrip extends Component
let width = container.clientWidth;
if (width / ratio > container.clientHeight)
if (width / ratio > container.clientHeight)
{
width = container.clientHeight * ratio;
}
this.setState({
width
});
@@ -113,7 +114,7 @@ class Filmstrip extends Component
render()
{
const { peers, advancedMode } = this.props;
const { peers, advancedMode, lastN, lastNLength } = this.props;
const activePeerName = this.getActivePeerName();
@@ -138,25 +139,40 @@ class Filmstrip extends Component
<div className='filmstrip'>
<div className='filmstrip-content'>
{Object.keys(peers).map((peerName) => (
<div
key={peerName}
onClick={() => this.props.setSelectedPeer(peerName)}
className={classnames('film', {
selected : this.props.selectedPeerName === peerName,
active : this.state.lastSpeaker === peerName
})}
>
<div className='film-content'>
<Peer
advancedMode={advancedMode}
name={peerName}
/>
</div>
</div>
))}
{
Object.keys(peers).map((peerName) =>
{
return (
lastN.find((lastNElement) => lastNElement === peerName)?
<div
key={peerName}
onClick={() => this.props.setSelectedPeer(peerName)}
className={classnames('film', {
selected : this.props.selectedPeerName === peerName,
active : this.state.lastSpeaker === peerName
})}
>
<div className='film-content'>
<Peer
advancedMode={advancedMode}
name={peerName}
/>
</div>
</div>
:null
);
})
}
</div>
</div>
<div className='hidden-peer-container'>
{ (lastNLength<Object.keys(peers).length)?
<HiddenPeers
lastNLength={Object.keys(peers).length-lastNLength}
/>:null
}
</div>
</div>
);
}
@@ -169,16 +185,25 @@ Filmstrip.propTypes = {
consumers : PropTypes.object.isRequired,
myName : PropTypes.string.isRequired,
selectedPeerName : PropTypes.string,
setSelectedPeer : PropTypes.func.isRequired
setSelectedPeer : PropTypes.func.isRequired,
lastNLength : PropTypes.number,
lastN : PropTypes.array.isRequired
};
const mapStateToProps = (state) => ({
activeSpeakerName : state.room.activeSpeakerName,
selectedPeerName : state.room.selectedPeerName,
peers : state.peers,
consumers : state.consumers,
myName : state.me.name
});
const mapStateToProps = (state) =>
{
const lastNLength = state.room.lastN ? state.room.lastN.length : 0;
return {
activeSpeakerName : state.room.activeSpeakerName,
selectedPeerName : state.room.selectedPeerName,
peers : state.peers,
consumers : state.consumers,
myName : state.me.name,
lastN : state.room.lastN,
lastNLength
};
};
const mapDispatchToProps = {
setSelectedPeer : stateActions.setSelectedPeer
+71
View File
@@ -0,0 +1,71 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import * as stateActions from '../redux/stateActions';
class HiddenPeers extends Component
{
state = {
controlsVisible : false
};
handleMouseOver = () =>
{
this.setState({
controlsVisible : true
});
};
handleMouseOut = () =>
{
this.setState({
controlsVisible : false
});
};
render()
{
const {
lastNLength,
openUsersTab
} = this.props;
return (
<div
data-component='HiddenPeers'
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
>
<div data-component='HiddenPeersView'>
<div className='view-container' onClick={() => openUsersTab()}>
<p>+{lastNLength} <br /> participant(s)</p>
</div>
</div>
</div>
);
}
}
HiddenPeers.propTypes =
{
lastNLength : PropTypes.number,
openUsersTab : PropTypes.func.isRequired
};
const mapDispatchToProps = (dispatch) =>
{
return {
openUsersTab : () =>
{
dispatch(stateActions.openToolArea());
dispatch(stateActions.setToolTab('users'));
}
};
};
const HiddenPeersContainer = connect(
null,
mapDispatchToProps
)(HiddenPeers);
export default HiddenPeersContainer;
+37 -19
View File
@@ -6,6 +6,7 @@ import debounce from 'lodash/debounce';
import * as appPropTypes from './appPropTypes';
import { Appear } from './transitions';
import Peer from './Peer';
import HiddenPeers from './HiddenPeers';
import ResizeObserver from 'resize-observer-polyfill';
const RATIO = 1.334;
@@ -26,7 +27,7 @@ class Peers extends React.Component
updateDimensions = debounce(() =>
{
if (!this.peersRef.current)
if (!this.peersRef.current)
{
return;
}
@@ -91,7 +92,9 @@ class Peers extends React.Component
const {
advancedMode,
activeSpeakerName,
peers
peers,
lastN,
lastNLength
} = this.props;
const style =
@@ -106,22 +109,32 @@ class Peers extends React.Component
peers.map((peer) =>
{
return (
<Appear key={peer.name} duration={1000}>
<div
className={classnames('peer-container', {
'active-speaker' : peer.name === activeSpeakerName
})}
>
<Peer
advancedMode={advancedMode}
name={peer.name}
style={style}
/>
</div>
</Appear>
(lastN.find(function(lastNElement)
{ return lastNElement == peer.name; }))?
<Appear key={peer.name} duration={1000}>
<div
className={classnames('peer-container', {
'active-speaker' : peer.name === activeSpeakerName
})}
>
<Peer
advancedMode={advancedMode}
name={peer.name}
style={style}
/>
</div>
</Appear>
:null
);
})
}
<div className='hidden-peer-container'>
{ (lastNLength<peers.length)?
<HiddenPeers
lastNLength={peers.length-lastNLength}
/>:null
}
</div>
</div>
);
}
@@ -132,20 +145,25 @@ Peers.propTypes =
advancedMode : PropTypes.bool,
peers : PropTypes.arrayOf(appPropTypes.Peer).isRequired,
boxes : PropTypes.number,
activeSpeakerName : PropTypes.string
activeSpeakerName : PropTypes.string,
lastNLength : PropTypes.number,
lastN : PropTypes.array.isRequired
};
const mapStateToProps = (state) =>
{
const peers = Object.values(state.peers);
const boxes = peers.length + Object.values(state.consumers)
const lastN = state.room.lastN;
const lastNLength = lastN ? state.room.lastN.length : 0;
const boxes = lastNLength + Object.values(state.consumers)
.filter((consumer) => consumer.source === 'screen').length;
return {
peers,
boxes,
activeSpeakerName : state.room.activeSpeakerName
activeSpeakerName : state.room.activeSpeakerName,
lastN,
lastNLength
};
};