import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ResizeObserver from 'resize-observer-polyfill'; import { connect } from 'react-redux'; import debounce from 'lodash/debounce'; import classnames from 'classnames'; import { withRoomContext } from '../RoomContext'; import Peer from './Peer'; import HiddenPeers from './HiddenPeers'; class Filmstrip extends Component { constructor(props) { super(props); this.activePeerContainer = React.createRef(); } state = { lastSpeaker : null, width : 400 }; // Find the name of the peer which is currently speaking. This is either // the latest active speaker, or the manually selected peer, or, if no // person has spoken yet, the first peer in the list of peers. getActivePeerName = () => { if (this.props.selectedPeerName) { return this.props.selectedPeerName; } if (this.state.lastSpeaker) { return this.state.lastSpeaker; } const peerNames = Object.keys(this.props.peers); if (peerNames.length > 0) { return peerNames[0]; } }; isSharingCamera = (peerName) => this.props.peers[peerName] && this.props.peers[peerName].consumers.some((consumer) => this.props.consumers[consumer].source === 'screen'); getRatio = () => { let ratio = 4 / 3; if (this.isSharingCamera(this.getActivePeerName())) { ratio *= 2; } return ratio; }; updateDimensions = debounce(() => { const container = this.activePeerContainer.current; if (container) { const ratio = this.getRatio(); let width = container.clientWidth; if (width / ratio > container.clientHeight) { width = container.clientHeight * ratio; } this.setState({ width }); } }, 200); componentDidMount() { window.addEventListener('resize', this.updateDimensions); const observer = new ResizeObserver(this.updateDimensions); observer.observe(this.activePeerContainer.current); this.updateDimensions(); } componentWillUnmount() { window.removeEventListener('resize', this.updateDimensions); } componentDidUpdate(prevProps) { if (prevProps !== this.props) { this.updateDimensions(); if (this.props.activeSpeakerName !== this.props.myName) { // eslint-disable-next-line react/no-did-update-set-state this.setState({ lastSpeaker : this.props.activeSpeakerName }); } } } render() { const { roomClient, peers, advancedMode, spotlights, spotlightsLength } = this.props; const activePeerName = this.getActivePeerName(); return (
{ Object.keys(peers).map((peerName) => { if (spotlights.find((spotlightsElement) => spotlightsElement === peerName)) { return (
roomClient.setSelectedPeer(peerName)} className={classnames('film', { selected : this.props.selectedPeerName === peerName, active : this.state.lastSpeaker === peerName })} >
); } })}
); } } Filmstrip.propTypes = { roomClient : PropTypes.any.isRequired, activeSpeakerName : PropTypes.string, advancedMode : PropTypes.bool, peers : PropTypes.object.isRequired, consumers : PropTypes.object.isRequired, myName : PropTypes.string.isRequired, selectedPeerName : PropTypes.string, spotlightsLength : PropTypes.number, spotlights : PropTypes.array.isRequired }; const mapStateToProps = (state) => { const spotlightsLength = state.room.spotlights ? state.room.spotlights.length : 0; return { activeSpeakerName : state.room.activeSpeakerName, selectedPeerName : state.room.selectedPeerName, peers : state.peers, consumers : state.consumers, myName : state.me.name, spotlights : state.room.spotlights, spotlightsLength }; }; export default withRoomContext(connect( mapStateToProps, undefined )(Filmstrip));