diff --git a/app/lib/components/Filmstrip.jsx b/app/lib/components/Filmstrip.jsx index 5e2f870..01552e4 100644 --- a/app/lib/components/Filmstrip.jsx +++ b/app/lib/components/Filmstrip.jsx @@ -1,15 +1,92 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import ResizeObserver from 'resize-observer-polyfill'; import { connect } from 'react-redux'; import classnames from 'classnames'; import Peer from './Peer'; class Filmstrip extends Component { + constructor(props) + { + super(props); + + this.activePeerContainer = React.createRef(); + } + state = { - selectedPeerName : null + selectedPeerName : 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. + getActivePeerName = () => + this.state.selectedPeerName || this.props.activeSpeakerName; + + 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 = () => + { + 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 + }); + } + }; + + componentDidMount() + { + this.updateDimensions(); + } + + componentDidMount() + { + window.addEventListener('resize', this.updateDimensions); + const observer = new ResizeObserver(this.updateDimensions); + + observer.observe(this.activePeerContainer.current); + } + + componentWillUnmount() + { + window.removeEventListener('resize', this.updateDimensions); + } + + componentDidUpdate(prevProps) + { + if (prevProps !== this.props) + { + this.updateDimensions(); + } + } + handleSelectPeer = (selectedPeerName) => { this.setState((oldState) => ({ @@ -22,39 +99,44 @@ class Filmstrip extends Component { const { activeSpeakerName, peers, advancedMode } = this.props; - // Find the name of the peer which is currently speaking. This is either - // the latest active speaker, or the manually selected peer. - const activePeerName = this.state.selectedPeerName || activeSpeakerName; + const activePeerName = this.getActivePeerName(); return (
- {peers[activePeerName] && ( -
- -
- )} +
+ {peers[activePeerName] && ( +
+ +
+ )} +
- {Object.keys(peers).map((peerName) => ( -
this.handleSelectPeer(peerName)} - className={classnames('film', { - selected : this.state.selectedPeerName === peerName, - active : activeSpeakerName === peerName - })} - > -
- +
+ {Object.keys(peers).map((peerName) => ( +
this.handleSelectPeer(peerName)} + className={classnames('film', { + selected : this.state.selectedPeerName === peerName, + active : activeSpeakerName === peerName + })} + > +
+ +
-
- ))} + ))} +
); @@ -64,13 +146,15 @@ class Filmstrip extends Component Filmstrip.propTypes = { activeSpeakerName : PropTypes.string, advancedMode : PropTypes.bool, - peers : PropTypes.object.isRequired + peers : PropTypes.object.isRequired, + consumers : PropTypes.object.isRequired }; const mapStateToProps = (state) => ({ activeSpeakerName : state.room.activeSpeakerName, - peers : state.peers + peers : state.peers, + consumers : state.consumers }); export default connect( diff --git a/app/stylus/components/Filmstrip.styl b/app/stylus/components/Filmstrip.styl index d6edfc6..529f11b 100644 --- a/app/stylus/components/Filmstrip.styl +++ b/app/stylus/components/Filmstrip.styl @@ -4,13 +4,20 @@ align-items: center; height: 100%; - > .active-peer { - width: 95vmin; - padding: 10vmin 1vmin 1vmin 1vmin; + > .active-peer-container { + width: 100%; + height: 80vh; + display: flex; + justify-content: center; - > [data-component='Peer'] { - border: 5px solid rgba(255, 255, 255, 0.15); - box-shadow: 0px 5px 12px 2px rgba(17, 17, 17, 0.5); + > .active-peer { + width: 100%; + padding: 5vmin 1vmin 1vmin 1vmin; + + > [data-component='Peer'] { + border: 5px solid rgba(255, 255, 255, 0.15); + box-shadow: 0px 5px 12px 2px rgba(17, 17, 17, 0.5); + } } } @@ -19,16 +26,16 @@ background: rgba(0, 0, 0 , 0.5); width: 100%; overflow-x: auto; - padding: 1vmin 0; - margin-top: auto; + height: 20vh; + align-items: center; > .film { - height: 15vmin; - flex-shrink: 0; - padding-left: 1vmin; + height: 18vh; + flex-shrink: 0; + padding-left: 1vh; &:last-child { - padding-right: 1vmin; + padding-right: 1vh; } > .film-content { @@ -37,11 +44,11 @@ border: 1px solid rgba(255,255,255,0.15); > [data-component='Peer'] { - max-width: 15vmin * (4 / 3); + max-width: 17vh * (4 / 3); cursor: pointer; &.screen { - max-width: 15vmin * (2 * 4 / 3); + max-width: 17vh * (2 * 4 / 3); border: 0; } }