diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index b6f1869..0f4d10b 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -673,6 +673,16 @@ export default class RoomClient stateActions.setWebcamInProgress(false)); } + setSelectedPeer(peerName) + { + logger.debug('setSelectedPeer() [peerName:"%s"]', peerName); + + this._spotlights.setPeerSpotlight(peerName); + + this._dispatch( + stateActions.setSelectedPeer(peerName)); + } + async mutePeerAudio(peerName) { logger.debug('mutePeerAudio() [peerName:"%s"]', peerName); diff --git a/app/lib/Spotlights.js b/app/lib/Spotlights.js index 33f8015..dd90895 100644 --- a/app/lib/Spotlights.js +++ b/app/lib/Spotlights.js @@ -12,6 +12,7 @@ export default class Spotlights extends EventEmitter this._room = room; this._maxSpotlights = maxSpotlights; this._peerList = []; + this._selectedSpotlights = []; this._currentSpotlights = []; this._started = false; } @@ -43,6 +44,25 @@ export default class Spotlights extends EventEmitter } } + setPeerSpotlight(peerName) + { + logger.debug('setPeerSpotlight() [peerName:"%s"]', peerName); + + const index = this._selectedSpotlights.indexOf(peerName); + + if (index === -1) // We don't have this peer in the list, adding + { + this._selectedSpotlights.push(peerName); + } + else // We have this peer, remove + { + this._selectedSpotlights.splice(index, 1); + } + + if (this._started) + this._spotlightsUpdated(); + } + _handleRoom() { this._room.on('newpeer', (peer) => @@ -69,14 +89,21 @@ export default class Spotlights extends EventEmitter { peer.on('close', () => { - const index = this._peerList.indexOf(peer.name); + let index = this._peerList.indexOf(peer.name); - if (index > -1) // We have this peer in the list, remove + if (index !== -1) // We have this peer in the list, remove { this._peerList.splice(index, 1); - - this._spotlightsUpdated(); } + + index = this._selectedSpotlights.indexOf(peer.name); + + if (index !== -1) // We have this peer in the list, remove + { + this._selectedSpotlights.splice(index, 1); + } + + this._spotlightsUpdated(); }); logger.debug('_handlePeer() | adding peer [peerName:"%s"]', peer.name); @@ -104,15 +131,26 @@ export default class Spotlights extends EventEmitter _spotlightsUpdated() { + let spotlights; + + if (this._selectedSpotlights.length > 0) + { + spotlights = [ ...new Set([ ...this._selectedSpotlights, ...this._peerList ]) ]; + } + else + { + spotlights = this._peerList; + } + if ( !this._arraysEqual( - this._currentSpotlights, this._peerList.slice(0, this._maxSpotlights) + this._currentSpotlights, spotlights.slice(0, this._maxSpotlights) ) ) { logger.debug('_spotlightsUpdated() | spotlights updated, emitting'); - this._currentSpotlights = this._peerList.slice(0, this._maxSpotlights); + this._currentSpotlights = spotlights.slice(0, this._maxSpotlights); this.emit('spotlights-updated', this._currentSpotlights); } else diff --git a/app/lib/components/Filmstrip.jsx b/app/lib/components/Filmstrip.jsx index ba5bf6a..c9b7c0c 100644 --- a/app/lib/components/Filmstrip.jsx +++ b/app/lib/components/Filmstrip.jsx @@ -4,7 +4,7 @@ import ResizeObserver from 'resize-observer-polyfill'; import { connect } from 'react-redux'; import debounce from 'lodash/debounce'; import classnames from 'classnames'; -import * as stateActions from '../redux/stateActions'; +import * as requestActions from '../redux/requestActions'; import Peer from './Peer'; import HiddenPeers from './HiddenPeers'; @@ -206,7 +206,7 @@ const mapStateToProps = (state) => }; const mapDispatchToProps = { - setSelectedPeer : stateActions.setSelectedPeer + setSelectedPeer : requestActions.setSelectedPeer }; export default connect( diff --git a/app/lib/components/ParticipantList/ParticipantList.jsx b/app/lib/components/ParticipantList/ParticipantList.jsx index 5f56983..97da94a 100644 --- a/app/lib/components/ParticipantList/ParticipantList.jsx +++ b/app/lib/components/ParticipantList/ParticipantList.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import classNames from 'classnames'; import * as appPropTypes from '../appPropTypes'; -import * as stateActions from '../../redux/stateActions'; +import * as requestActions from '../../redux/requestActions'; import PropTypes from 'prop-types'; import ListPeer from './ListPeer'; import ListMe from './ListMe'; @@ -46,7 +46,7 @@ const mapStateToProps = (state) => }; const mapDispatchToProps = { - setSelectedPeer : stateActions.setSelectedPeer + setSelectedPeer : requestActions.setSelectedPeer }; const ParticipantListContainer = connect( diff --git a/app/lib/redux/requestActions.js b/app/lib/redux/requestActions.js index 6ad7fbc..d9ba059 100644 --- a/app/lib/redux/requestActions.js +++ b/app/lib/redux/requestActions.js @@ -221,6 +221,14 @@ export const sendFile = (file, name, picture) => }; }; +export const setSelectedPeer = (selectedPeerName) => +{ + return { + type : 'REQUEST_SELECTED_PEER', + payload : { selectedPeerName } + }; +}; + // This returns a redux-thunk action (a function). export const notify = ({ type = 'info', text, timeout }) => { diff --git a/app/lib/redux/roomClientMiddleware.js b/app/lib/redux/roomClientMiddleware.js index b4e266c..265c8cb 100644 --- a/app/lib/redux/roomClientMiddleware.js +++ b/app/lib/redux/roomClientMiddleware.js @@ -237,6 +237,15 @@ export default ({ dispatch, getState }) => (next) => client.sendFile(action.payload); break; } + + case 'REQUEST_SELECTED_PEER': + { + const { selectedPeerName } = action.payload; + + client.setSelectedPeer(selectedPeerName); + + break; + } } return next(action);