Cleanup of Me, Peer, PeerView, ScreenView and Democratic

master
Håvar Aambø Fosstveit 2019-04-02 13:37:13 +02:00
parent 978d49f045
commit a40b843848
5 changed files with 151 additions and 396 deletions

View File

@ -7,8 +7,7 @@ import PropTypes from 'prop-types';
import classnames from 'classnames';
import { getDeviceInfo } from 'mediasoup-client';
import * as appPropTypes from '../appPropTypes';
import PeerView from '../VideoContainers/PeerView';
import ScreenView from '../VideoContainers/ScreenView';
import VideoView from '../VideoContainers/VideoView';
const styles = () =>
({
@ -16,8 +15,19 @@ const styles = () =>
{
display : 'flex',
flexDirection : 'row',
flex : '100 100 auto',
position : 'relative'
margin : 6,
flex : '0 0 auto',
boxShadow : 'var(--peer-shadow)',
border : 'var(--peer-border)',
backgroundColor : 'var(--peer-bg-color)',
backgroundImage : 'var(--peer-empty-avatar)',
backgroundPosition : 'bottom',
backgroundSize : 'auto 85%',
backgroundRepeat : 'no-repeat',
'&.active-speaker' :
{
borderColor : 'var(--active-speaker-border-color)'
}
},
viewContainer :
{
@ -74,6 +84,7 @@ class Me extends React.PureComponent
const {
roomClient,
me,
activeSpeaker,
style,
advancedMode,
micProducer,
@ -101,7 +112,12 @@ class Me extends React.PureComponent
return (
<div
className={classes.root}
className={
classnames(
classes.root,
activeSpeaker ? 'active-speaker' : null
)
}
ref={(node) => (this._rootNode = node)}
data-tip={tip}
data-tip-disable={!tip}
@ -110,10 +126,11 @@ class Me extends React.PureComponent
onMouseOut={this.handleMouseOut}
>
<div className={classnames(classes.viewContainer, 'webcam')} style={style}>
<PeerView
<VideoView
isMe
advancedMode={advancedMode}
peer={me}
showPeerInfo
audioTrack={micProducer ? micProducer.track : null}
volume={micProducer ? micProducer.volume : null}
videoTrack={webcamProducer ? webcamProducer.track : null}
@ -129,12 +146,12 @@ class Me extends React.PureComponent
{ screenProducer ?
<div className={classnames(classes.viewContainer, 'screen')} style={style}>
<ScreenView
<VideoView
isMe
advancedMode={advancedMode}
screenTrack={screenProducer ? screenProducer.track : null}
screenVisible={screenVisible}
screenCodec={screenProducer ? screenProducer.codec : null}
videoTrack={screenProducer ? screenProducer.track : null}
videoVisible={screenVisible}
videoCodec={screenProducer ? screenProducer.codec : null}
/>
</div>
:null
@ -180,6 +197,7 @@ Me.propTypes =
connected : PropTypes.bool.isRequired,
advancedMode : PropTypes.bool,
me : appPropTypes.Me.isRequired,
activeSpeaker : PropTypes.bool,
micProducer : appPropTypes.Producer,
webcamProducer : appPropTypes.Producer,
screenProducer : appPropTypes.Producer,
@ -202,7 +220,8 @@ const mapStateToProps = (state) =>
me : state.me,
micProducer : micProducer,
webcamProducer : webcamProducer,
screenProducer : screenProducer
screenProducer : screenProducer,
activeSpeaker : state.me.name === state.room.activeSpeakerName
};
};

View File

@ -7,8 +7,7 @@ import { withRoomContext } from '../../RoomContext';
import { withStyles } from '@material-ui/core/styles';
import { unstable_useMediaQuery as useMediaQuery } from '@material-ui/core/useMediaQuery';
import * as stateActions from '../../actions/stateActions';
import PeerView from '../VideoContainers/PeerView';
import ScreenView from '../VideoContainers/ScreenView';
import VideoView from '../VideoContainers/VideoView';
import Fab from '@material-ui/core/Fab';
import MicIcon from '@material-ui/icons/Mic';
import MicOffIcon from '@material-ui/icons/MicOff';
@ -19,12 +18,16 @@ const styles = (theme) =>
({
root :
{
overflow : 'hidden',
flex : '0 0 auto',
margin : 6,
boxShadow : 'var(--peer-shadow)',
border : 'var(--peer-border)',
touchAction : 'none',
backgroundColor : 'var(--peer-bg-color)',
backgroundImage : 'var(--peer-empty-avatar)',
backgroundPosition : 'bottom',
backgroundSize : 'auto 85%',
backgroundRepeat : 'no-repeat',
'&.webcam' :
{
order : 2
@ -36,17 +39,11 @@ const styles = (theme) =>
'&.hover' :
{
boxShadow : '0px 1px 3px rgba(0, 0, 0, 0.05) inset, 0px 0px 8px rgba(82, 168, 236, 0.9)'
}
},
peerContainer :
'&.active-speaker' :
{
width : '100%',
height : '100%',
display : 'flex',
flexDirection : 'row',
flex : '100 100 auto',
position : 'relative',
touchAction : 'none'
borderColor : 'var(--active-speaker-border-color)'
}
},
fab :
{
@ -86,32 +83,8 @@ const styles = (theme) =>
opacity : 1
}
},
pausedVideo :
videoInfo :
{
position : 'absolute',
zIndex : 11,
top : 0,
bottom : 0,
left : 0,
right : 0,
display : 'flex',
flexDirection : 'column',
justifyContent : 'center',
alignItems : 'center',
'& p' :
{
padding : '6px 12px',
borderRadius : 6,
userSelect : 'none',
pointerEvents : 'none',
fontSize : 20,
color : 'rgba(255, 255, 255, 0.55)'
}
},
incompatibleVideo :
{
position : 'absolute',
zIndex : 10,
top : 0,
bottom : 0,
left : 0,
@ -148,6 +121,7 @@ const Peer = (props) =>
roomClient,
advancedMode,
peer,
activeSpeaker,
micConsumer,
webcamConsumer,
screenConsumer,
@ -192,7 +166,14 @@ const Peer = (props) =>
return (
<React.Fragment>
<div
className={classnames(classes.root, 'webcam', hover ? 'hover' : null)}
className={
classnames(
classes.root,
'webcam',
hover ? 'hover' : null,
activeSpeaker ? 'active-speaker' : null
)
}
onMouseOver={() => setHover(true)}
onMouseOut={() => setHover(false)}
onTouchStart={() =>
@ -213,21 +194,21 @@ const Peer = (props) =>
}, 2000);
}}
>
<div className={classes.peerContainer}>
{ videoVisible && !webcamConsumer.supported ?
<div className={classes.incompatibleVideo}>
<div className={classes.videoInfo} style={style}>
<p>incompatible video</p>
</div>
:null
}
{ !videoVisible ?
<div className={classes.pausedVideo}>
<div className={classes.videoInfo} style={style}>
<p>this video is paused</p>
</div>
:null
}
{ videoVisible && webcamConsumer.supported ?
<div className={classnames(classes.viewContainer)} style={style}>
<div
className={classnames(classes.controls, webcamHover ? 'hover' : null)}
@ -300,9 +281,10 @@ const Peer = (props) =>
</Fab>
</div>
<PeerView
<VideoView
advancedMode={advancedMode}
peer={peer}
showPeerInfo
volume={micConsumer ? micConsumer.volume : null}
videoTrack={webcamConsumer ? webcamConsumer.track : null}
videoVisible={videoVisible}
@ -311,7 +293,8 @@ const Peer = (props) =>
videoCodec={webcamConsumer ? webcamConsumer.codec : null}
/>
</div>
</div>
:null
}
</div>
{ screenConsumer ?
@ -337,20 +320,21 @@ const Peer = (props) =>
}, 2000);
}}
>
<div className={classes.peerContainer}>
{ screenVisible && !screenConsumer.supported ?
<div className={classes.incompatibleVideo}>
<div className={classes.videoInfo} style={style}>
<p>incompatible video</p>
</div>
:null
}
{ !screenVisible ?
<div className={classes.pausedVideo}>
<div className={classes.videoInfo} style={style}>
<p>this video is paused</p>
</div>
:null
}
{ screenVisible && screenConsumer.supported ?
<div className={classnames(classes.viewContainer)} style={style}>
<div
className={classnames(classes.controls, screenHover ? 'hover' : null)}
@ -405,15 +389,16 @@ const Peer = (props) =>
<FullScreenIcon />
</Fab>
</div>
<ScreenView
<VideoView
advancedMode={advancedMode}
screenTrack={screenConsumer ? screenConsumer.track : null}
screenVisible={screenVisible}
screenProfile={screenProfile}
screenCodec={screenConsumer ? screenConsumer.codec : null}
videoTrack={screenConsumer ? screenConsumer.track : null}
videoVisible={screenVisible}
videoProfile={screenProfile}
videoCodec={screenConsumer ? screenConsumer.codec : null}
/>
</div>
</div>
:null
}
</div>
:null
}
@ -430,7 +415,7 @@ Peer.propTypes =
webcamConsumer : appPropTypes.Consumer,
screenConsumer : appPropTypes.Consumer,
windowConsumer : PropTypes.number,
streamDimensions : PropTypes.object,
activeSpeaker : PropTypes.bool,
style : PropTypes.object,
toggleConsumerFullscreen : PropTypes.func.isRequired,
toggleConsumerWindow : PropTypes.func.isRequired,
@ -455,7 +440,8 @@ const mapStateToProps = (state, { name }) =>
micConsumer,
webcamConsumer,
screenConsumer,
windowConsumer : state.room.windowConsumer
windowConsumer : state.room.windowConsumer,
activeSpeaker : name === state.room.activeSpeakerName
};
};

View File

@ -130,6 +130,8 @@ class Democratic extends React.PureComponent
const {
advancedMode,
amActiveSpeaker,
activeSpeakerName,
selectedPeerName,
peers,
spotlights,
spotlightsLength,
@ -144,16 +146,10 @@ class Democratic extends React.PureComponent
return (
<div className={classes.root} ref={this.peersRef}>
<div
className={classnames(classes.peerContainer, {
'active-speaker' : amActiveSpeaker
})}
>
<Me
advancedMode={advancedMode}
style={style}
/>
</div>
{ Object.keys(peers).map((peerName) =>
{
if (spotlights.find((spotlightsElement) => spotlightsElement === peerName))

View File

@ -1,246 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { withStyles } from '@material-ui/core/styles';
const styles = () =>
({
root :
{
position : 'relative',
flex : '100 100 auto',
height : '100%',
width : '100%',
display : 'flex',
flexDirection : 'column',
overflow : 'hidden',
backgroundColor : 'var(--peer-bg-color)',
backgroundImage : 'var(--peer-empty-avatar)',
backgroundPosition : 'bottom',
backgroundSize : 'auto 85%',
backgroundRepeat : 'no-repeat'
},
video :
{
flex : '100 100 auto',
height : '100%',
width : '100%',
objectFit : 'cover',
userSelect : 'none',
transitionProperty : 'opacity',
transitionDuration : '.15s',
backgroundColor : 'var(--peer-video-bg-color)',
'&.is-me' :
{
transform : 'scaleX(-1)'
},
'&.hidden' :
{
opacity : 0,
transitionDuration : '0s'
},
'&.loading' :
{
filter : 'blur(5px)'
}
},
info :
{
position : 'absolute',
zIndex : 10,
top : '0.6vmin',
left : '0.6vmin',
bottom : 0,
right : 0,
display : 'flex',
flexDirection : 'column',
justifyContent : 'space-between'
},
media :
{
flex : '0 0 auto',
display : 'flex',
flexDirection : 'row'
},
box :
{
padding : '0.4vmin',
borderRadius : 2,
backgroundColor : 'rgba(0, 0, 0, 0.25)',
'& p' :
{
userSelect : 'none',
pointerEvents : 'none',
margin : 0,
color : 'rgba(255, 255, 255, 0.7)',
fontSize : 10,
'&:last-child' :
{
marginBottom : 0
}
}
}
});
class ScreenView extends React.PureComponent
{
constructor(props)
{
super(props);
this.state =
{
screenWidth : null,
screenHeight : null
};
// Latest received screen track.
// @type {MediaStreamTrack}
this._screenTrack = null;
// Periodic timer for showing video resolution.
this._screenResolutionTimer = null;
}
render()
{
const {
isMe,
advancedMode,
screenVisible,
screenProfile,
screenCodec,
classes
} = this.props;
const {
screenWidth,
screenHeight
} = this.state;
return (
<div className={classes.root}>
<div className={classes.info}>
{ advancedMode ?
<div className={classnames(classes.media, { 'is-me': isMe })}>
{ screenVisible ?
<div className={classes.box}>
{ screenCodec ?
<p>{screenCodec} {screenProfile}</p>
:null
}
{ (screenVisible && screenWidth !== null) ?
<p>{screenWidth}x{screenHeight}</p>
:null
}
</div>
:null
}
</div>
:null
}
</div>
<video
ref='video'
className={classnames(classes.video, {
hidden : !screenVisible,
'is-me' : isMe,
loading : screenProfile === 'none'
})}
autoPlay
playsInline
muted={Boolean(true)}
/>
</div>
);
}
componentDidMount()
{
const { screenTrack } = this.props;
this._setTracks(screenTrack);
}
componentWillUnmount()
{
clearInterval(this._screenResolutionTimer);
}
componentWillReceiveProps(nextProps)
{
const { screenTrack } = nextProps;
this._setTracks(screenTrack);
}
_setTracks(screenTrack)
{
if (this._screenTrack === screenTrack)
return;
this._screenTrack = screenTrack;
clearInterval(this._screenResolutionTimer);
this._hideScreenResolution();
const { video } = this.refs;
if (screenTrack)
{
const stream = new MediaStream();
if (screenTrack)
stream.addTrack(screenTrack);
video.srcObject = stream;
if (screenTrack)
this._showScreenResolution();
}
else
{
video.srcObject = null;
}
}
_showScreenResolution()
{
this._screenResolutionTimer = setInterval(() =>
{
const { screenWidth, screenHeight } = this.state;
const { video } = this.refs;
// Don't re-render if nothing changed.
if (video.videoWidth === screenWidth && video.videoHeight === screenHeight)
return;
this.setState(
{
screenWidth : video.videoWidth,
screenHeight : video.videoHeight
});
}, 1000);
}
_hideScreenResolution()
{
this.setState({ screenWidth: null, screenHeight: null });
}
}
ScreenView.propTypes =
{
isMe : PropTypes.bool,
advancedMode : PropTypes.bool,
screenTrack : PropTypes.any,
screenVisible : PropTypes.bool,
screenProfile : PropTypes.string,
screenCodec : PropTypes.string,
classes : PropTypes.object.isRequired
};
export default withStyles(styles)(ScreenView);

View File

@ -15,12 +15,7 @@ const styles = () =>
width : '100%',
display : 'flex',
flexDirection : 'column',
overflow : 'hidden',
backgroundColor : 'var(--peer-bg-color)',
backgroundImage : 'var(--peer-empty-avatar)',
backgroundPosition : 'bottom',
backgroundSize : 'auto 85%',
backgroundRepeat : 'no-repeat'
overflow : 'hidden'
},
video :
{
@ -210,7 +205,7 @@ const styles = () =>
}
});
class PeerView extends React.PureComponent
class VideoView extends React.PureComponent
{
constructor(props)
{
@ -241,6 +236,7 @@ class PeerView extends React.PureComponent
isMe,
peer,
volume,
showPeerInfo,
advancedMode,
videoVisible,
videoProfile,
@ -280,6 +276,7 @@ class PeerView extends React.PureComponent
:null
}
{ showPeerInfo ?
<div className={classes.peer}>
{ isMe ?
<EditableInput
@ -311,6 +308,8 @@ class PeerView extends React.PureComponent
:null
}
</div>
:null
}
</div>
<video
@ -411,11 +410,12 @@ class PeerView extends React.PureComponent
}
}
PeerView.propTypes =
VideoView.propTypes =
{
isMe : PropTypes.bool,
peer : PropTypes.oneOfType(
[ appPropTypes.Me, appPropTypes.Peer ]).isRequired,
[ appPropTypes.Me, appPropTypes.Peer ]),
showPeerInfo : PropTypes.bool,
advancedMode : PropTypes.bool,
audioTrack : PropTypes.any,
volume : PropTypes.number,
@ -428,4 +428,4 @@ PeerView.propTypes =
classes : PropTypes.object.isRequired
};
export default withStyles(styles)(PeerView);
export default withStyles(styles)(VideoView);