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

master
Stefan Otto 2018-10-29 12:48:47 +01:00
parent d7ce8253e2
commit ed5ef29fba
8 changed files with 262 additions and 52 deletions

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
{
@ -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

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;

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;
@ -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
};
};

View File

@ -9,7 +9,7 @@ const initialState =
toolbarsVisible : true,
mode : 'democratic',
selectedPeerName : null,
lastN : null
lastN : []
};
const room = (state = initialState, action) =>

View File

@ -19,6 +19,22 @@ const toolarea = (state = initialState, action) =>
return { ...state, toolAreaOpen, unreadMessages, unreadFiles };
}
case 'OPEN_TOOL_AREA':
{
const toolAreaOpen = true;
const unreadMessages = state.currentToolTab === 'chat' ? 0 : state.unreadMessages;
const unreadFiles = state.currentToolTab === 'files' ? 0 : state.unreadFiles;
return { ...state, toolAreaOpen, unreadMessages, unreadFiles };
}
case 'CLOSE_TOOL_AREA':
{
const toolAreaOpen = false;
return { ...state, toolAreaOpen };
}
case 'SET_TOOL_TAB':
{
const { toolTab } = action.payload;

View File

@ -161,6 +161,20 @@ export const toggleToolArea = () =>
};
};
export const openToolArea = () =>
{
return {
type : 'OPEN_TOOL_AREA'
};
};
export const closeToolArea = () =>
{
return {
type : 'CLOSE_TOOL_AREA'
};
};
export const setToolTab = (toolTab) =>
{
return {

View File

@ -0,0 +1,65 @@
[data-component='HiddenPeersView'] {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
> .info {
$backgroundTint = #000;
position: absolute;
z-index: 10;
top: 0.6vmin;
left: 0.6vmin;
bottom: 0;
right: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
}
> .view-container {
width: 12vmin;
height: 9vmin;
position: absolute;
bottom: 3%;
right: 3%;
color: #aaa;
background-image: url('/resources/images/buddy.svg');
background-color: rgba(#2a4b58, 1);
background-position: bottom;
background-size: auto 85%;
background-repeat: no-repeat;
text-align: center;
vertical-align: middle;
line-height: 1.8vmin;
font-size: 1.7vmin;
}
.view-container>p{
transform: translate(0%,50%);
}
.view-container,
.view-container::before,
.view-container::after {
/* Add shadow to distinguish sheets from one another */
box-shadow: 2px 1px 1px rgba(0,0,0,0.15);
}
.view-container::before,
.view-container::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
background-color: #2a4b58;
}
/* Second sheet of paper */
.view-container::before {
left: .7vmin;
top: .7vmin;
z-index: -1;
}
/* Third sheet of paper */
.view-container::after {
left: 1.4vmin;
top: 1.4vmin;
z-index: -2;
}
}

View File

@ -47,6 +47,7 @@ body {
@import './components/Peers';
@import './components/Peer';
@import './components/PeerView';
@import './components/HiddenPeersView';
@import './components/ScreenView';
@import './components/Notifications';
@import './components/Chat';