Fixes to performance. Moved volume out to new component to optimize rerenders.
parent
e84af94544
commit
abca6645a9
|
|
@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import * as appPropTypes from '../appPropTypes';
|
import * as appPropTypes from '../appPropTypes';
|
||||||
import VideoView from '../VideoContainers/VideoView';
|
import VideoView from '../VideoContainers/VideoView';
|
||||||
|
import Volume from './Volume';
|
||||||
|
|
||||||
const styles = () =>
|
const styles = () =>
|
||||||
({
|
({
|
||||||
|
|
@ -55,7 +56,6 @@ const Me = (props) =>
|
||||||
micProducer,
|
micProducer,
|
||||||
webcamProducer,
|
webcamProducer,
|
||||||
screenProducer,
|
screenProducer,
|
||||||
volume,
|
|
||||||
classes
|
classes
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
|
@ -87,8 +87,6 @@ const Me = (props) =>
|
||||||
advancedMode={advancedMode}
|
advancedMode={advancedMode}
|
||||||
peer={me}
|
peer={me}
|
||||||
showPeerInfo
|
showPeerInfo
|
||||||
audioTrack={micProducer ? micProducer.track : null}
|
|
||||||
volume={volume}
|
|
||||||
videoTrack={webcamProducer ? webcamProducer.track : null}
|
videoTrack={webcamProducer ? webcamProducer.track : null}
|
||||||
videoVisible={videoVisible}
|
videoVisible={videoVisible}
|
||||||
audioCodec={micProducer ? micProducer.codec : null}
|
audioCodec={micProducer ? micProducer.codec : null}
|
||||||
|
|
@ -97,7 +95,9 @@ const Me = (props) =>
|
||||||
{
|
{
|
||||||
roomClient.changeDisplayName(displayName);
|
roomClient.changeDisplayName(displayName);
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
<Volume name={me.name} />
|
||||||
|
</VideoView>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{ screenProducer ?
|
{ screenProducer ?
|
||||||
|
|
@ -128,7 +128,6 @@ Me.propTypes =
|
||||||
micProducer : appPropTypes.Producer,
|
micProducer : appPropTypes.Producer,
|
||||||
webcamProducer : appPropTypes.Producer,
|
webcamProducer : appPropTypes.Producer,
|
||||||
screenProducer : appPropTypes.Producer,
|
screenProducer : appPropTypes.Producer,
|
||||||
volume : PropTypes.number,
|
|
||||||
style : PropTypes.object,
|
style : PropTypes.object,
|
||||||
classes : PropTypes.object.isRequired
|
classes : PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
@ -138,12 +137,22 @@ const mapStateToProps = (state) =>
|
||||||
return {
|
return {
|
||||||
me : state.me,
|
me : state.me,
|
||||||
...meProducersSelector(state),
|
...meProducersSelector(state),
|
||||||
volume : state.peerVolumes[state.me.name],
|
|
||||||
activeSpeaker : state.me.name === state.room.activeSpeakerName
|
activeSpeaker : state.me.name === state.room.activeSpeakerName
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRoomContext(connect(
|
export default withRoomContext(connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
null
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.me === next.me &&
|
||||||
|
prev.producers === next.producers &&
|
||||||
|
prev.room.activeSpeakerName === next.room.activeSpeakerName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles)(Me)));
|
)(withStyles(styles)(Me)));
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import MicIcon from '@material-ui/icons/Mic';
|
||||||
import MicOffIcon from '@material-ui/icons/MicOff';
|
import MicOffIcon from '@material-ui/icons/MicOff';
|
||||||
import NewWindowIcon from '@material-ui/icons/OpenInNew';
|
import NewWindowIcon from '@material-ui/icons/OpenInNew';
|
||||||
import FullScreenIcon from '@material-ui/icons/Fullscreen';
|
import FullScreenIcon from '@material-ui/icons/Fullscreen';
|
||||||
|
import Volume from './Volume';
|
||||||
|
|
||||||
const styles = (theme) =>
|
const styles = (theme) =>
|
||||||
({
|
({
|
||||||
|
|
@ -125,7 +126,6 @@ const Peer = (props) =>
|
||||||
micConsumer,
|
micConsumer,
|
||||||
webcamConsumer,
|
webcamConsumer,
|
||||||
screenConsumer,
|
screenConsumer,
|
||||||
volume,
|
|
||||||
toggleConsumerFullscreen,
|
toggleConsumerFullscreen,
|
||||||
toggleConsumerWindow,
|
toggleConsumerWindow,
|
||||||
style,
|
style,
|
||||||
|
|
@ -134,9 +134,6 @@ const Peer = (props) =>
|
||||||
theme
|
theme
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (!peer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const micEnabled = (
|
const micEnabled = (
|
||||||
Boolean(micConsumer) &&
|
Boolean(micConsumer) &&
|
||||||
!micConsumer.locallyPaused &&
|
!micConsumer.locallyPaused &&
|
||||||
|
|
@ -289,13 +286,14 @@ const Peer = (props) =>
|
||||||
advancedMode={advancedMode}
|
advancedMode={advancedMode}
|
||||||
peer={peer}
|
peer={peer}
|
||||||
showPeerInfo
|
showPeerInfo
|
||||||
volume={volume}
|
|
||||||
videoTrack={webcamConsumer ? webcamConsumer.track : null}
|
videoTrack={webcamConsumer ? webcamConsumer.track : null}
|
||||||
videoVisible={videoVisible}
|
videoVisible={videoVisible}
|
||||||
videoProfile={videoProfile}
|
videoProfile={videoProfile}
|
||||||
audioCodec={micConsumer ? micConsumer.codec : null}
|
audioCodec={micConsumer ? micConsumer.codec : null}
|
||||||
videoCodec={webcamConsumer ? webcamConsumer.codec : null}
|
videoCodec={webcamConsumer ? webcamConsumer.codec : null}
|
||||||
/>
|
>
|
||||||
|
<Volume name={peer.name} />
|
||||||
|
</VideoView>
|
||||||
</div>
|
</div>
|
||||||
:null
|
:null
|
||||||
}
|
}
|
||||||
|
|
@ -419,7 +417,6 @@ Peer.propTypes =
|
||||||
micConsumer : appPropTypes.Consumer,
|
micConsumer : appPropTypes.Consumer,
|
||||||
webcamConsumer : appPropTypes.Consumer,
|
webcamConsumer : appPropTypes.Consumer,
|
||||||
screenConsumer : appPropTypes.Consumer,
|
screenConsumer : appPropTypes.Consumer,
|
||||||
volume : PropTypes.number,
|
|
||||||
windowConsumer : PropTypes.number,
|
windowConsumer : PropTypes.number,
|
||||||
activeSpeaker : PropTypes.bool,
|
activeSpeaker : PropTypes.bool,
|
||||||
style : PropTypes.object,
|
style : PropTypes.object,
|
||||||
|
|
@ -438,7 +435,6 @@ const makeMapStateToProps = (initialState, props) =>
|
||||||
return {
|
return {
|
||||||
peer : state.peers[props.name],
|
peer : state.peers[props.name],
|
||||||
...getPeerConsumers(state, props),
|
...getPeerConsumers(state, props),
|
||||||
volume : state.peerVolumes[props.name],
|
|
||||||
windowConsumer : state.room.windowConsumer,
|
windowConsumer : state.room.windowConsumer,
|
||||||
activeSpeaker : props.name === state.room.activeSpeakerName
|
activeSpeaker : props.name === state.room.activeSpeakerName
|
||||||
};
|
};
|
||||||
|
|
@ -465,5 +461,17 @@ const mapDispatchToProps = (dispatch) =>
|
||||||
|
|
||||||
export default withRoomContext(connect(
|
export default withRoomContext(connect(
|
||||||
makeMapStateToProps,
|
makeMapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.peers === next.peers &&
|
||||||
|
prev.consumers === next.consumers &&
|
||||||
|
prev.room.activeSpeakerName === next.room.activeSpeakerName &&
|
||||||
|
prev.room.windowConsumer === next.room.windowConsumer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles, { withTheme: true })(Peer)));
|
)(withStyles(styles, { withTheme: true })(Peer)));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
const styles = () =>
|
||||||
|
({
|
||||||
|
volumeLarge :
|
||||||
|
{
|
||||||
|
position : 'absolute',
|
||||||
|
top : 0,
|
||||||
|
bottom : 0,
|
||||||
|
right : 2,
|
||||||
|
width : 10,
|
||||||
|
display : 'flex',
|
||||||
|
flexDirection : 'column',
|
||||||
|
justifyContent : 'center',
|
||||||
|
alignItems : 'center'
|
||||||
|
},
|
||||||
|
largeBar :
|
||||||
|
{
|
||||||
|
width : 6,
|
||||||
|
borderRadius : 6,
|
||||||
|
background : 'rgba(yellow, 0.65)',
|
||||||
|
transitionProperty : 'height background-color',
|
||||||
|
transitionDuration : '0.25s',
|
||||||
|
'&.level0' :
|
||||||
|
{
|
||||||
|
height : 0,
|
||||||
|
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level1' :
|
||||||
|
{
|
||||||
|
height : '10%',
|
||||||
|
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level2' :
|
||||||
|
{
|
||||||
|
height : '20%',
|
||||||
|
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level3' :
|
||||||
|
{
|
||||||
|
height : '30%',
|
||||||
|
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level4' :
|
||||||
|
{
|
||||||
|
height : '40%',
|
||||||
|
backgroundColor : 'rgba(255, 165, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level5' :
|
||||||
|
{
|
||||||
|
height : '50%',
|
||||||
|
backgroundColor : 'rgba(255, 165, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level6' :
|
||||||
|
{
|
||||||
|
height : '60%',
|
||||||
|
backgroundColor : 'rgba(255, 0, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level7' :
|
||||||
|
{
|
||||||
|
height : '70%',
|
||||||
|
backgroundColor : 'rgba(255, 0, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level8' :
|
||||||
|
{
|
||||||
|
height : '80%',
|
||||||
|
backgroundColor : 'rgba(0, 0, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level9' :
|
||||||
|
{
|
||||||
|
height : '90%',
|
||||||
|
backgroundColor : 'rgba(0, 0, 0, 0.65)'
|
||||||
|
},
|
||||||
|
'&.level10' :
|
||||||
|
{
|
||||||
|
height : '100%',
|
||||||
|
backgroundColor : 'rgba(0, 0, 0, 0.65)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
volumeSmall :
|
||||||
|
{
|
||||||
|
float : 'right',
|
||||||
|
display : 'flex',
|
||||||
|
flexDirection : 'row',
|
||||||
|
justifyContent : 'flex-start',
|
||||||
|
width : '1vmin',
|
||||||
|
position : 'relative',
|
||||||
|
backgroundSize : '75%'
|
||||||
|
},
|
||||||
|
smallBar :
|
||||||
|
{
|
||||||
|
flex : '0 0 auto',
|
||||||
|
margin : '0.3rem',
|
||||||
|
backgroundSize : '75%',
|
||||||
|
backgroundRepeat : 'no-repeat',
|
||||||
|
backgroundColor : 'rgba(0, 0, 0, 1)',
|
||||||
|
cursor : 'pointer',
|
||||||
|
transitionProperty : 'opacity, background-color',
|
||||||
|
width : 3,
|
||||||
|
borderRadius : 6,
|
||||||
|
transitionDuration : '0.25s',
|
||||||
|
position : 'absolute',
|
||||||
|
bottom : 0,
|
||||||
|
'&.level0' : { height: 0 },
|
||||||
|
'&.level1' : { height: '0.2vh' },
|
||||||
|
'&.level2' : { height: '0.4vh' },
|
||||||
|
'&.level3' : { height: '0.6vh' },
|
||||||
|
'&.level4' : { height: '0.8vh' },
|
||||||
|
'&.level5' : { height: '1.0vh' },
|
||||||
|
'&.level6' : { height: '1.2vh' },
|
||||||
|
'&.level7' : { height: '1.4vh' },
|
||||||
|
'&.level8' : { height: '1.6vh' },
|
||||||
|
'&.level9' : { height: '1.8vh' },
|
||||||
|
'&.level10' : { height: '2.0vh' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Volume = (props) =>
|
||||||
|
{
|
||||||
|
const {
|
||||||
|
small,
|
||||||
|
volume,
|
||||||
|
classes
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={small ? classes.volumeSmall : classes.volumeLarge}>
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
small ? classes.smallBar : classes.largeBar, `level${volume}`
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Volume.propTypes =
|
||||||
|
{
|
||||||
|
small : PropTypes.bool,
|
||||||
|
volume : PropTypes.number,
|
||||||
|
classes : PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeMapStateToProps = (initialState, props) =>
|
||||||
|
{
|
||||||
|
const mapStateToProps = (state) =>
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
volume : state.peerVolumes[props.name]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return mapStateToProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
makeMapStateToProps
|
||||||
|
)(withStyles(styles)(Volume));
|
||||||
|
|
@ -127,5 +127,18 @@ const mapStateToProps = (state) =>
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withRoomContext(
|
export default withRoomContext(
|
||||||
connect(mapStateToProps)(withStyles(styles)(ChatInput))
|
connect(
|
||||||
|
mapStateToProps,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.me.displayName === next.me.displayName &&
|
||||||
|
prev.me.picture === next.me.picture
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)(withStyles(styles)(ChatInput))
|
||||||
);
|
);
|
||||||
|
|
@ -119,5 +119,16 @@ const mapDispatchToProps = {
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.toolarea.currentToolTab === next.toolarea.currentToolTab &&
|
||||||
|
prev.toolarea.unreadMessages === next.toolarea.unreadMessages &&
|
||||||
|
prev.toolarea.unreadFiles === next.toolarea.unreadFiles
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles, { withTheme: true })(MeetingDrawer));
|
)(withStyles(styles, { withTheme: true })(MeetingDrawer));
|
||||||
|
|
|
||||||
|
|
@ -111,5 +111,15 @@ const mapStateToProps = (state) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps
|
mapStateToProps,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.me === next.me
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles)(ListMe));
|
)(withStyles(styles)(ListMe));
|
||||||
|
|
|
||||||
|
|
@ -82,42 +82,6 @@ const styles = () =>
|
||||||
backgroundImage : `url(${HandIcon})`
|
backgroundImage : `url(${HandIcon})`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
volumeContainer :
|
|
||||||
{
|
|
||||||
float : 'right',
|
|
||||||
display : 'flex',
|
|
||||||
flexDirection : 'row',
|
|
||||||
justifyContent : 'flex-start',
|
|
||||||
width : '1vmin',
|
|
||||||
position : 'relative',
|
|
||||||
backgroundSize : '75%'
|
|
||||||
},
|
|
||||||
bar :
|
|
||||||
{
|
|
||||||
flex : '0 0 auto',
|
|
||||||
margin : '0.3rem',
|
|
||||||
backgroundSize : '75%',
|
|
||||||
backgroundRepeat : 'no-repeat',
|
|
||||||
backgroundColor : 'rgba(0, 0, 0, 1)',
|
|
||||||
cursor : 'pointer',
|
|
||||||
transitionProperty : 'opacity, background-color',
|
|
||||||
width : 3,
|
|
||||||
borderRadius : 6,
|
|
||||||
transitionDuration : '0.25s',
|
|
||||||
position : 'absolute',
|
|
||||||
bottom : 0,
|
|
||||||
'&.level0' : { height: 0 },
|
|
||||||
'&.level1' : { height: '0.2vh' },
|
|
||||||
'&.level2' : { height: '0.4vh' },
|
|
||||||
'&.level3' : { height: '0.6vh' },
|
|
||||||
'&.level4' : { height: '0.8vh' },
|
|
||||||
'&.level5' : { height: '1.0vh' },
|
|
||||||
'&.level6' : { height: '1.2vh' },
|
|
||||||
'&.level7' : { height: '1.4vh' },
|
|
||||||
'&.level8' : { height: '1.6vh' },
|
|
||||||
'&.level9' : { height: '1.8vh' },
|
|
||||||
'&.level10' : { height: '2.0vh' }
|
|
||||||
},
|
|
||||||
controls :
|
controls :
|
||||||
{
|
{
|
||||||
float : 'right',
|
float : 'right',
|
||||||
|
|
@ -169,13 +133,10 @@ const ListPeer = (props) =>
|
||||||
peer,
|
peer,
|
||||||
micConsumer,
|
micConsumer,
|
||||||
screenConsumer,
|
screenConsumer,
|
||||||
volume,
|
children,
|
||||||
classes
|
classes
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (!peer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const micEnabled = (
|
const micEnabled = (
|
||||||
Boolean(micConsumer) &&
|
Boolean(micConsumer) &&
|
||||||
!micConsumer.locallyPaused &&
|
!micConsumer.locallyPaused &&
|
||||||
|
|
@ -211,9 +172,7 @@ const ListPeer = (props) =>
|
||||||
:null
|
:null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.volumeContainer}>
|
{children}
|
||||||
<div className={classnames(classes.bar, `level${volume}`)} />
|
|
||||||
</div>
|
|
||||||
<div className={classes.controls}>
|
<div className={classes.controls}>
|
||||||
{ screenConsumer ?
|
{ screenConsumer ?
|
||||||
<div
|
<div
|
||||||
|
|
@ -271,7 +230,7 @@ ListPeer.propTypes =
|
||||||
micConsumer : appPropTypes.Consumer,
|
micConsumer : appPropTypes.Consumer,
|
||||||
webcamConsumer : appPropTypes.Consumer,
|
webcamConsumer : appPropTypes.Consumer,
|
||||||
screenConsumer : appPropTypes.Consumer,
|
screenConsumer : appPropTypes.Consumer,
|
||||||
volume : PropTypes.number,
|
children : PropTypes.object,
|
||||||
classes : PropTypes.object.isRequired
|
classes : PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -282,9 +241,8 @@ const makeMapStateToProps = (initialState, props) =>
|
||||||
const mapStateToProps = (state) =>
|
const mapStateToProps = (state) =>
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
peer : state.peers[props.name],
|
peer : state.peers[props.name],
|
||||||
...getPeerConsumers(state, props),
|
...getPeerConsumers(state, props)
|
||||||
volume : state.peerVolumes[props.name]
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -292,5 +250,16 @@ const makeMapStateToProps = (initialState, props) =>
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRoomContext(connect(
|
export default withRoomContext(connect(
|
||||||
makeMapStateToProps
|
makeMapStateToProps,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.peers === next.peers &&
|
||||||
|
prev.consumers === next.consumers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles)(ListPeer)));
|
)(withStyles(styles)(ListPeer)));
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
passivePeersSelector
|
passivePeersSelector,
|
||||||
|
spotlightPeersSelector
|
||||||
} from '../../Selectors';
|
} from '../../Selectors';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { withStyles } from '@material-ui/core/styles';
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
|
@ -9,6 +10,7 @@ import { withRoomContext } from '../../../RoomContext';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ListPeer from './ListPeer';
|
import ListPeer from './ListPeer';
|
||||||
import ListMe from './ListMe';
|
import ListMe from './ListMe';
|
||||||
|
import Volume from '../../Containers/Volume';
|
||||||
|
|
||||||
const styles = (theme) =>
|
const styles = (theme) =>
|
||||||
({
|
({
|
||||||
|
|
@ -75,7 +77,7 @@ class ParticipantList extends React.PureComponent
|
||||||
advancedMode,
|
advancedMode,
|
||||||
passivePeers,
|
passivePeers,
|
||||||
selectedPeerName,
|
selectedPeerName,
|
||||||
spotlights,
|
spotlightPeers,
|
||||||
classes
|
classes
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
|
@ -88,15 +90,17 @@ class ParticipantList extends React.PureComponent
|
||||||
<br />
|
<br />
|
||||||
<ul className={classes.list}>
|
<ul className={classes.list}>
|
||||||
<li className={classes.listheader}>Participants in Spotlight:</li>
|
<li className={classes.listheader}>Participants in Spotlight:</li>
|
||||||
{ spotlights.map((peerName) => (
|
{ spotlightPeers.map((peer) => (
|
||||||
<li
|
<li
|
||||||
key={peerName}
|
key={peer.name}
|
||||||
className={classNames(classes.listItem, {
|
className={classNames(classes.listItem, {
|
||||||
selected : peerName === selectedPeerName
|
selected : peer.name === selectedPeerName
|
||||||
})}
|
})}
|
||||||
onClick={() => roomClient.setSelectedPeer(peerName)}
|
onClick={() => roomClient.setSelectedPeer(peer.name)}
|
||||||
>
|
>
|
||||||
<ListPeer name={peerName} advancedMode={advancedMode} />
|
<ListPeer name={peer.name} advancedMode={advancedMode}>
|
||||||
|
<Volume small name={peer.name} />
|
||||||
|
</ListPeer>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -126,16 +130,18 @@ ParticipantList.propTypes =
|
||||||
advancedMode : PropTypes.bool,
|
advancedMode : PropTypes.bool,
|
||||||
passivePeers : PropTypes.array,
|
passivePeers : PropTypes.array,
|
||||||
selectedPeerName : PropTypes.string,
|
selectedPeerName : PropTypes.string,
|
||||||
spotlights : PropTypes.array.isRequired,
|
spotlightPeers : PropTypes.array,
|
||||||
classes : PropTypes.object.isRequired
|
classes : PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) =>
|
const mapStateToProps = (state) =>
|
||||||
({
|
{
|
||||||
|
return {
|
||||||
passivePeers : passivePeersSelector(state),
|
passivePeers : passivePeersSelector(state),
|
||||||
selectedPeerName : state.room.selectedPeerName,
|
selectedPeerName : state.room.selectedPeerName,
|
||||||
spotlights : state.room.spotlights
|
spotlightPeers : spotlightPeersSelector(state)
|
||||||
});
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const ParticipantListContainer = withRoomContext(connect(
|
const ParticipantListContainer = withRoomContext(connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
|
spotlightPeersSelector,
|
||||||
peersLengthSelector,
|
peersLengthSelector,
|
||||||
videoBoxesSelector,
|
videoBoxesSelector,
|
||||||
spotlightsLengthSelector
|
spotlightsLengthSelector
|
||||||
|
|
@ -117,7 +118,7 @@ class Democratic extends React.PureComponent
|
||||||
const {
|
const {
|
||||||
advancedMode,
|
advancedMode,
|
||||||
peersLength,
|
peersLength,
|
||||||
spotlights,
|
spotlightsPeers,
|
||||||
spotlightsLength,
|
spotlightsLength,
|
||||||
classes
|
classes
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
@ -134,13 +135,13 @@ class Democratic extends React.PureComponent
|
||||||
advancedMode={advancedMode}
|
advancedMode={advancedMode}
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
{ spotlights.map((peerName) =>
|
{ spotlightsPeers.map((peer) =>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
<Peer
|
<Peer
|
||||||
key={peerName}
|
key={peer.name}
|
||||||
advancedMode={advancedMode}
|
advancedMode={advancedMode}
|
||||||
name={peerName}
|
name={peer.name}
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
@ -162,7 +163,7 @@ Democratic.propTypes =
|
||||||
peersLength : PropTypes.number,
|
peersLength : PropTypes.number,
|
||||||
boxes : PropTypes.number,
|
boxes : PropTypes.number,
|
||||||
spotlightsLength : PropTypes.number,
|
spotlightsLength : PropTypes.number,
|
||||||
spotlights : PropTypes.array.isRequired,
|
spotlightsPeers : PropTypes.array.isRequired,
|
||||||
classes : PropTypes.object.isRequired
|
classes : PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -171,7 +172,7 @@ const mapStateToProps = (state) =>
|
||||||
return {
|
return {
|
||||||
peersLength : peersLengthSelector(state),
|
peersLength : peersLengthSelector(state),
|
||||||
boxes : videoBoxesSelector(state),
|
boxes : videoBoxesSelector(state),
|
||||||
spotlights : state.room.spotlights,
|
spotlightsPeers : spotlightPeersSelector(state),
|
||||||
spotlightsLength : spotlightsLengthSelector(state)
|
spotlightsLength : spotlightsLengthSelector(state)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -184,6 +185,7 @@ export default connect(
|
||||||
areStatesEqual : (next, prev) =>
|
areStatesEqual : (next, prev) =>
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
|
prev.peers === next.peers &&
|
||||||
prev.producers === next.producers &&
|
prev.producers === next.producers &&
|
||||||
prev.consumers === next.consumers &&
|
prev.consumers === next.consumers &&
|
||||||
prev.spotlights === next.spotlights
|
prev.spotlights === next.spotlights
|
||||||
|
|
|
||||||
|
|
@ -81,5 +81,17 @@ const mapDispatchToProps = (dispatch) =>
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withSnackbar(
|
export default withSnackbar(
|
||||||
connect(mapStateToProps, mapDispatchToProps)(Notifications)
|
connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.notifications === next.notifications
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)(Notifications)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,17 @@ const mapStateToProps = (state) =>
|
||||||
});
|
});
|
||||||
|
|
||||||
const AudioPeersContainer = connect(
|
const AudioPeersContainer = connect(
|
||||||
mapStateToProps
|
mapStateToProps,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.consumers === next.consumers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(AudioPeers);
|
)(AudioPeers);
|
||||||
|
|
||||||
export default AudioPeersContainer;
|
export default AudioPeersContainer;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,15 @@ import { createSelector } from 'reselect';
|
||||||
|
|
||||||
const producersSelect = (state) => state.producers;
|
const producersSelect = (state) => state.producers;
|
||||||
const consumersSelect = (state) => state.consumers;
|
const consumersSelect = (state) => state.consumers;
|
||||||
|
const spotlightsSelector = (state) => state.room.spotlights;
|
||||||
export const spotlightsSelector = (state) => state.room.spotlights;
|
|
||||||
|
|
||||||
const peersSelector = (state) => state.peers;
|
const peersSelector = (state) => state.peers;
|
||||||
|
const getPeerConsumers = (state, props) =>
|
||||||
|
(state.peers[props.name] ? state.peers[props.name].consumers : null);
|
||||||
|
const getAllConsumers = (state) => state.consumers;
|
||||||
|
const peersKeySelector = createSelector(
|
||||||
|
peersSelector,
|
||||||
|
(peers) => Object.keys(peers)
|
||||||
|
);
|
||||||
|
|
||||||
export const micProducersSelector = createSelector(
|
export const micProducersSelector = createSelector(
|
||||||
producersSelect,
|
producersSelect,
|
||||||
|
|
@ -54,13 +59,20 @@ export const screenConsumerSelector = createSelector(
|
||||||
|
|
||||||
export const spotlightsLengthSelector = createSelector(
|
export const spotlightsLengthSelector = createSelector(
|
||||||
spotlightsSelector,
|
spotlightsSelector,
|
||||||
(spotlights) => (spotlights ? spotlights.length : 0)
|
(spotlights) => spotlights.length
|
||||||
);
|
);
|
||||||
|
|
||||||
export const spotlightPeersSelector = createSelector(
|
export const spotlightPeersSelector = createSelector(
|
||||||
spotlightsSelector,
|
spotlightsSelector,
|
||||||
peersSelector,
|
peersSelector,
|
||||||
(spotlights, peers) => spotlights.map((peerName) => peers[peerName])
|
(spotlights, peers) =>
|
||||||
|
spotlights.reduce((result, peerName) =>
|
||||||
|
{
|
||||||
|
if (peers[peerName])
|
||||||
|
result.push(peers[peerName]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, [])
|
||||||
);
|
);
|
||||||
|
|
||||||
export const peersLengthSelector = createSelector(
|
export const peersLengthSelector = createSelector(
|
||||||
|
|
@ -68,11 +80,6 @@ export const peersLengthSelector = createSelector(
|
||||||
(peers) => Object.values(peers).length
|
(peers) => Object.values(peers).length
|
||||||
);
|
);
|
||||||
|
|
||||||
const peersKeySelector = createSelector(
|
|
||||||
peersSelector,
|
|
||||||
(peers) => Object.keys(peers)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const passivePeersSelector = createSelector(
|
export const passivePeersSelector = createSelector(
|
||||||
peersKeySelector,
|
peersKeySelector,
|
||||||
spotlightsSelector,
|
spotlightsSelector,
|
||||||
|
|
@ -101,10 +108,6 @@ export const meProducersSelector = createSelector(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const getPeerConsumers = (state, props) =>
|
|
||||||
(state.peers[props.name] ? state.peers[props.name].consumers : null);
|
|
||||||
const getAllConsumers = (state) => state.consumers;
|
|
||||||
|
|
||||||
export const makePeerConsumerSelector = () =>
|
export const makePeerConsumerSelector = () =>
|
||||||
{
|
{
|
||||||
return createSelector(
|
return createSelector(
|
||||||
|
|
|
||||||
|
|
@ -215,5 +215,15 @@ const mapDispatchToProps = {
|
||||||
|
|
||||||
export default withRoomContext(connect(
|
export default withRoomContext(connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.me === next.me &&
|
||||||
|
prev.room === next.room
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles)(Settings)));
|
)(withStyles(styles)(Settings)));
|
||||||
|
|
@ -161,5 +161,16 @@ const mapDispatchToProps = (dispatch) =>
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.consumers[prev.room.fullScreenConsumer] ===
|
||||||
|
next.consumers[next.room.fullScreenConsumer] &&
|
||||||
|
prev.room.toolbarsVisible === next.room.toolbarsVisible
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(withStyles(styles)(FullScreenView));
|
)(withStyles(styles)(FullScreenView));
|
||||||
|
|
|
||||||
|
|
@ -132,81 +132,6 @@ const styles = () =>
|
||||||
fontSize : 11,
|
fontSize : 11,
|
||||||
color : 'rgba(255, 255, 255, 0.55)'
|
color : 'rgba(255, 255, 255, 0.55)'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
volume :
|
|
||||||
{
|
|
||||||
position : 'absolute',
|
|
||||||
top : 0,
|
|
||||||
bottom : 0,
|
|
||||||
right : 2,
|
|
||||||
width : 10,
|
|
||||||
display : 'flex',
|
|
||||||
flexDirection : 'column',
|
|
||||||
justifyContent : 'center',
|
|
||||||
alignItems : 'center'
|
|
||||||
},
|
|
||||||
volumeBar :
|
|
||||||
{
|
|
||||||
width : 6,
|
|
||||||
borderRadius : 6,
|
|
||||||
background : 'rgba(yellow, 0.65)',
|
|
||||||
transitionProperty : 'height background-color',
|
|
||||||
transitionDuration : '0.25s',
|
|
||||||
'&.level0' :
|
|
||||||
{
|
|
||||||
height : 0,
|
|
||||||
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level1' :
|
|
||||||
{
|
|
||||||
height : '10%',
|
|
||||||
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level2' :
|
|
||||||
{
|
|
||||||
height : '20%',
|
|
||||||
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level3' :
|
|
||||||
{
|
|
||||||
height : '30%',
|
|
||||||
backgroundColor : 'rgba(255, 255, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level4' :
|
|
||||||
{
|
|
||||||
height : '40%',
|
|
||||||
backgroundColor : 'rgba(255, 165, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level5' :
|
|
||||||
{
|
|
||||||
height : '50%',
|
|
||||||
backgroundColor : 'rgba(255, 165, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level6' :
|
|
||||||
{
|
|
||||||
height : '60%',
|
|
||||||
backgroundColor : 'rgba(255, 0, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level7' :
|
|
||||||
{
|
|
||||||
height : '70%',
|
|
||||||
backgroundColor : 'rgba(255, 0, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level8' :
|
|
||||||
{
|
|
||||||
height : '80%',
|
|
||||||
backgroundColor : 'rgba(0, 0, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level9' :
|
|
||||||
{
|
|
||||||
height : '90%',
|
|
||||||
backgroundColor : 'rgba(0, 0, 0, 0.65)'
|
|
||||||
},
|
|
||||||
'&.level10' :
|
|
||||||
{
|
|
||||||
height : '100%',
|
|
||||||
backgroundColor : 'rgba(0, 0, 0, 0.65)'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -218,15 +143,10 @@ class VideoView extends React.PureComponent
|
||||||
|
|
||||||
this.state =
|
this.state =
|
||||||
{
|
{
|
||||||
volume : 0, // Integer from 0 to 10.,
|
|
||||||
videoWidth : null,
|
videoWidth : null,
|
||||||
videoHeight : null
|
videoHeight : null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Latest received video track.
|
|
||||||
// @type {MediaStreamTrack}
|
|
||||||
this._audioTrack = null;
|
|
||||||
|
|
||||||
// Latest received video track.
|
// Latest received video track.
|
||||||
// @type {MediaStreamTrack}
|
// @type {MediaStreamTrack}
|
||||||
this._videoTrack = null;
|
this._videoTrack = null;
|
||||||
|
|
@ -240,7 +160,6 @@ class VideoView extends React.PureComponent
|
||||||
const {
|
const {
|
||||||
isMe,
|
isMe,
|
||||||
peer,
|
peer,
|
||||||
volume,
|
|
||||||
showPeerInfo,
|
showPeerInfo,
|
||||||
videoContain,
|
videoContain,
|
||||||
advancedMode,
|
advancedMode,
|
||||||
|
|
@ -249,6 +168,7 @@ class VideoView extends React.PureComponent
|
||||||
audioCodec,
|
audioCodec,
|
||||||
videoCodec,
|
videoCodec,
|
||||||
onChangeDisplayName,
|
onChangeDisplayName,
|
||||||
|
children,
|
||||||
classes
|
classes
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
|
@ -331,18 +251,16 @@ class VideoView extends React.PureComponent
|
||||||
muted={isMe}
|
muted={isMe}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={classes.volume}>
|
{children}
|
||||||
<div className={classnames(classes.volumeBar, `level${volume}`)} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount()
|
componentDidMount()
|
||||||
{
|
{
|
||||||
const { audioTrack, videoTrack } = this.props;
|
const { videoTrack } = this.props;
|
||||||
|
|
||||||
this._setTracks(audioTrack, videoTrack);
|
this._setTracks(videoTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount()
|
componentWillUnmount()
|
||||||
|
|
@ -352,18 +270,17 @@ class VideoView extends React.PureComponent
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps)
|
componentWillReceiveProps(nextProps)
|
||||||
{
|
{
|
||||||
const { audioTrack, videoTrack } = nextProps;
|
const { videoTrack } = nextProps;
|
||||||
|
|
||||||
this._setTracks(audioTrack, videoTrack);
|
this._setTracks(videoTrack);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setTracks(audioTrack, videoTrack)
|
_setTracks(videoTrack)
|
||||||
{
|
{
|
||||||
if (this._audioTrack === audioTrack && this._videoTrack === videoTrack)
|
if (this._videoTrack === videoTrack)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._audioTrack = audioTrack;
|
|
||||||
this._videoTrack = videoTrack;
|
this._videoTrack = videoTrack;
|
||||||
|
|
||||||
clearInterval(this._videoResolutionTimer);
|
clearInterval(this._videoResolutionTimer);
|
||||||
|
|
@ -371,13 +288,10 @@ class VideoView extends React.PureComponent
|
||||||
|
|
||||||
const { video } = this.refs;
|
const { video } = this.refs;
|
||||||
|
|
||||||
if (audioTrack || videoTrack)
|
if (videoTrack)
|
||||||
{
|
{
|
||||||
const stream = new MediaStream();
|
const stream = new MediaStream();
|
||||||
|
|
||||||
if (audioTrack)
|
|
||||||
stream.addTrack(audioTrack);
|
|
||||||
|
|
||||||
if (videoTrack)
|
if (videoTrack)
|
||||||
stream.addTrack(videoTrack);
|
stream.addTrack(videoTrack);
|
||||||
|
|
||||||
|
|
@ -425,14 +339,13 @@ VideoView.propTypes =
|
||||||
showPeerInfo : PropTypes.bool,
|
showPeerInfo : PropTypes.bool,
|
||||||
videoContain : PropTypes.bool,
|
videoContain : PropTypes.bool,
|
||||||
advancedMode : PropTypes.bool,
|
advancedMode : PropTypes.bool,
|
||||||
audioTrack : PropTypes.any,
|
|
||||||
volume : PropTypes.number,
|
|
||||||
videoTrack : PropTypes.any,
|
videoTrack : PropTypes.any,
|
||||||
videoVisible : PropTypes.bool.isRequired,
|
videoVisible : PropTypes.bool.isRequired,
|
||||||
videoProfile : PropTypes.string,
|
videoProfile : PropTypes.string,
|
||||||
audioCodec : PropTypes.string,
|
audioCodec : PropTypes.string,
|
||||||
videoCodec : PropTypes.string,
|
videoCodec : PropTypes.string,
|
||||||
onChangeDisplayName : PropTypes.func,
|
onChangeDisplayName : PropTypes.func,
|
||||||
|
children : PropTypes.object,
|
||||||
classes : PropTypes.object.isRequired
|
classes : PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,17 @@ const mapDispatchToProps = (dispatch) =>
|
||||||
|
|
||||||
const VideoWindowContainer = connect(
|
const VideoWindowContainer = connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
mapDispatchToProps
|
mapDispatchToProps,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
areStatesEqual : (next, prev) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
prev.consumers[prev.room.windowConsumer] ===
|
||||||
|
next.consumers[next.room.windowConsumer]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
)(VideoWindow);
|
)(VideoWindow);
|
||||||
|
|
||||||
export default VideoWindowContainer;
|
export default VideoWindowContainer;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue