import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { withStyles } from '@material-ui/core/styles'; import classnames from 'classnames'; import { videoBoxesSelector } from '../Selectors'; import { withRoomContext } from '../../RoomContext'; import Me from '../Containers/Me'; import Peer from '../Containers/Peer'; import SpeakerPeer from '../Containers/SpeakerPeer'; import Grid from '@material-ui/core/Grid'; const RATIO = 1.334; const PADDING_V = 40; const PADDING_H = 0; const FILMSTRING_PADDING_V = 10; const FILMSTRING_PADDING_H = 0; const styles = () => ({ root : { height : '100%', width : '100%', display : 'grid', gridTemplateColumns : '1fr', gridTemplateRows : '1fr 0.25fr' }, speaker : { gridArea : '1 / 1 / 1 / 1', display : 'flex', justifyContent : 'center', alignItems : 'center' }, filmStrip : { gridArea : '2 / 1 / 2 / 1' }, filmItem : { display : 'flex', border : 'var(--peer-border)', '&.selected' : { borderColor : 'var(--selected-peer-border-color)' }, '&.active' : { opacity : '0.6' } }, hiddenToolBar : { paddingTop : 0, transition : 'padding .5s' }, showingToolBar : { paddingTop : 60, transition : 'padding .5s' } }); class Filmstrip extends React.PureComponent { constructor(props) { super(props); this.resizeTimeout = null; this.rootContainer = React.createRef(); this.activePeerContainer = React.createRef(); this.filmStripContainer = React.createRef(); } state = { lastSpeaker : null }; // 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. getActivePeerId = () => { const { selectedPeerId, peers } = this.props; const { lastSpeaker } = this.state; if (selectedPeerId && peers[selectedPeerId]) { return this.props.selectedPeerId; } if (lastSpeaker && peers[lastSpeaker]) { return this.state.lastSpeaker; } const peerIds = Object.keys(peers); if (peerIds.length > 0) { return peerIds[0]; } }; isSharingCamera = (peerId) => this.props.peers[peerId] && this.props.peers[peerId].consumers.some((consumer) => this.props.consumers[consumer].source === 'screen'); updateDimensions = () => { const newState = {}; const root = this.rootContainer.current; const availableWidth = root.clientWidth; // Grid is: // 4/5 speaker // 1/5 filmstrip const availableSpeakerHeight = (root.clientHeight * 0.8) - (this.props.toolbarsVisible || this.props.permanentTopBar ? PADDING_V : PADDING_H); const availableFilmstripHeight = root.clientHeight * 0.2; const speaker = this.activePeerContainer.current; if (speaker) { let speakerWidth = (availableWidth - PADDING_H); let speakerHeight = speakerWidth / RATIO; if (this.isSharingCamera(this.getActivePeerId())) { speakerWidth /= 2; speakerHeight = speakerWidth / RATIO; } if (speakerHeight > (availableSpeakerHeight - PADDING_V)) { speakerHeight = (availableSpeakerHeight - PADDING_V); speakerWidth = speakerHeight * RATIO; } newState.speakerWidth = speakerWidth; newState.speakerHeight = speakerHeight; } const filmStrip = this.filmStripContainer.current; if (filmStrip) { let filmStripHeight = availableFilmstripHeight - FILMSTRING_PADDING_V; let filmStripWidth = filmStripHeight * RATIO; if ( (filmStripWidth * this.props.boxes) > (availableWidth - FILMSTRING_PADDING_H) ) { filmStripWidth = (availableWidth - FILMSTRING_PADDING_H) / this.props.boxes; filmStripHeight = filmStripWidth / RATIO; } newState.filmStripWidth = filmStripWidth; newState.filmStripHeight = filmStripHeight; } this.setState({ ...newState }); }; componentDidMount() { // window.resize event listener window.addEventListener('resize', () => { // clear the timeout clearTimeout(this.resizeTimeout); // start timing for event "completion" this.resizeTimeout = setTimeout(() => this.updateDimensions(), 250); }); this.updateDimensions(); } componentWillUnmount() { window.removeEventListener('resize', this.updateDimensions); } componentDidUpdate(prevProps) { if (prevProps !== this.props) { if ( this.props.activeSpeakerId != null && this.props.activeSpeakerId !== this.props.myId ) { // eslint-disable-next-line react/no-did-update-set-state this.setState({ lastSpeaker : this.props.activeSpeakerId }); } this.updateDimensions(); } } render() { const { roomClient, peers, myId, advancedMode, spotlights, toolbarsVisible, permanentTopBar, classes } = this.props; const activePeerId = this.getActivePeerId(); const speakerStyle = { width : this.state.speakerWidth, height : this.state.speakerHeight }; const peerStyle = { width : this.state.filmStripWidth, height : this.state.filmStripHeight }; return (