From ed5ef29fba44cbe8bfcc6c460b1a11cdb9f26844 Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Mon, 29 Oct 2018 12:48:47 +0100 Subject: [PATCH] Added user interface for lastN (only peers in lastN are visible, others stay in HiddenPeers component) --- app/lib/components/Filmstrip.jsx | 87 ++++++++++++++-------- app/lib/components/HiddenPeers.jsx | 71 ++++++++++++++++++ app/lib/components/Peers.jsx | 56 +++++++++----- app/lib/redux/reducers/room.js | 2 +- app/lib/redux/reducers/toolarea.js | 18 ++++- app/lib/redux/stateActions.js | 14 ++++ app/stylus/components/HiddenPeersView.styl | 65 ++++++++++++++++ app/stylus/index.styl | 1 + 8 files changed, 262 insertions(+), 52 deletions(-) create mode 100644 app/lib/components/HiddenPeers.jsx create mode 100644 app/stylus/components/HiddenPeersView.styl diff --git a/app/lib/components/Filmstrip.jsx b/app/lib/components/Filmstrip.jsx index 56adbe0..60c5ee6 100644 --- a/app/lib/components/Filmstrip.jsx +++ b/app/lib/components/Filmstrip.jsx @@ -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
- {Object.keys(peers).map((peerName) => ( -
this.props.setSelectedPeer(peerName)} - className={classnames('film', { - selected : this.props.selectedPeerName === peerName, - active : this.state.lastSpeaker === peerName - })} - > -
- -
-
- ))} + { + Object.keys(peers).map((peerName) => + { + return ( + lastN.find((lastNElement) => lastNElement === peerName)? +
this.props.setSelectedPeer(peerName)} + className={classnames('film', { + selected : this.props.selectedPeerName === peerName, + active : this.state.lastSpeaker === peerName + })} + > +
+ +
+
+ :null + ); + }) + }
+
+ { (lastNLength:null + } +
+ ); } @@ -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 diff --git a/app/lib/components/HiddenPeers.jsx b/app/lib/components/HiddenPeers.jsx new file mode 100644 index 0000000..0dbdbb9 --- /dev/null +++ b/app/lib/components/HiddenPeers.jsx @@ -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 ( +
+
+
openUsersTab()}> +

+{lastNLength}
participant(s)

+
+
+
+ ); + } +} + +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; diff --git a/app/lib/components/Peers.jsx b/app/lib/components/Peers.jsx index 8913ec8..8230976 100644 --- a/app/lib/components/Peers.jsx +++ b/app/lib/components/Peers.jsx @@ -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 ( - -
- -
-
+ (lastN.find(function(lastNElement) + { return lastNElement == peer.name; }))? + +
+ +
+
+ :null ); }) } +
+ { (lastNLength:null + } +
); } @@ -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 }; }; diff --git a/app/lib/redux/reducers/room.js b/app/lib/redux/reducers/room.js index dd99318..ad390f0 100644 --- a/app/lib/redux/reducers/room.js +++ b/app/lib/redux/reducers/room.js @@ -9,7 +9,7 @@ const initialState = toolbarsVisible : true, mode : 'democratic', selectedPeerName : null, - lastN : null + lastN : [] }; const room = (state = initialState, action) => diff --git a/app/lib/redux/reducers/toolarea.js b/app/lib/redux/reducers/toolarea.js index 0d25eca..556c3fd 100644 --- a/app/lib/redux/reducers/toolarea.js +++ b/app/lib/redux/reducers/toolarea.js @@ -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; @@ -30,7 +46,7 @@ const toolarea = (state = initialState, action) => case 'ADD_NEW_RESPONSE_MESSAGE': { - if (state.toolAreaOpen && state.currentToolTab === 'chat') + if (state.toolAreaOpen && state.currentToolTab === 'chat') { return state; } diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index bc19deb..c4a7818 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -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 { diff --git a/app/stylus/components/HiddenPeersView.styl b/app/stylus/components/HiddenPeersView.styl new file mode 100644 index 0000000..a591b07 --- /dev/null +++ b/app/stylus/components/HiddenPeersView.styl @@ -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; + } +} diff --git a/app/stylus/index.styl b/app/stylus/index.styl index 8de11ad..f0b201a 100644 --- a/app/stylus/index.styl +++ b/app/stylus/index.styl @@ -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';