Only show Peer controls when hovering
parent
79376b3a50
commit
55c1506281
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
@ -8,130 +8,118 @@ import * as stateActions from '../redux/stateActions';
|
||||||
import PeerView from './PeerView';
|
import PeerView from './PeerView';
|
||||||
import ScreenView from './ScreenView';
|
import ScreenView from './ScreenView';
|
||||||
|
|
||||||
const Peer = (props) =>
|
class Peer extends Component
|
||||||
{
|
{
|
||||||
const {
|
state = {
|
||||||
advancedMode,
|
controlsVisible : false
|
||||||
peer,
|
};
|
||||||
micConsumer,
|
|
||||||
webcamConsumer,
|
|
||||||
screenConsumer,
|
|
||||||
onMuteMic,
|
|
||||||
onUnmuteMic,
|
|
||||||
onDisableWebcam,
|
|
||||||
onEnableWebcam,
|
|
||||||
onDisableScreen,
|
|
||||||
onEnableScreen,
|
|
||||||
toggleConsumerFullscreen,
|
|
||||||
style
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const micEnabled = (
|
handleMouseOver = () =>
|
||||||
Boolean(micConsumer) &&
|
{
|
||||||
!micConsumer.locallyPaused &&
|
this.setState({
|
||||||
!micConsumer.remotelyPaused
|
controlsVisible : true
|
||||||
);
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const videoVisible = (
|
handleMouseOut = () =>
|
||||||
Boolean(webcamConsumer) &&
|
{
|
||||||
!webcamConsumer.locallyPaused &&
|
this.setState({
|
||||||
!webcamConsumer.remotelyPaused
|
controlsVisible : false
|
||||||
);
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const screenVisible = (
|
render()
|
||||||
Boolean(screenConsumer) &&
|
{
|
||||||
!screenConsumer.locallyPaused &&
|
const {
|
||||||
!screenConsumer.remotelyPaused
|
advancedMode,
|
||||||
);
|
peer,
|
||||||
|
micConsumer,
|
||||||
|
webcamConsumer,
|
||||||
|
screenConsumer,
|
||||||
|
onMuteMic,
|
||||||
|
onUnmuteMic,
|
||||||
|
onDisableWebcam,
|
||||||
|
onEnableWebcam,
|
||||||
|
onDisableScreen,
|
||||||
|
onEnableScreen,
|
||||||
|
toggleConsumerFullscreen,
|
||||||
|
style
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
let videoProfile;
|
const micEnabled = (
|
||||||
|
Boolean(micConsumer) &&
|
||||||
|
!micConsumer.locallyPaused &&
|
||||||
|
!micConsumer.remotelyPaused
|
||||||
|
);
|
||||||
|
|
||||||
if (webcamConsumer)
|
const videoVisible = (
|
||||||
videoProfile = webcamConsumer.profile;
|
Boolean(webcamConsumer) &&
|
||||||
|
!webcamConsumer.locallyPaused &&
|
||||||
|
!webcamConsumer.remotelyPaused
|
||||||
|
);
|
||||||
|
|
||||||
let screenProfile;
|
const screenVisible = (
|
||||||
|
Boolean(screenConsumer) &&
|
||||||
|
!screenConsumer.locallyPaused &&
|
||||||
|
!screenConsumer.remotelyPaused
|
||||||
|
);
|
||||||
|
|
||||||
if (screenConsumer)
|
let videoProfile;
|
||||||
screenProfile = screenConsumer.profile;
|
|
||||||
|
|
||||||
return (
|
if (webcamConsumer)
|
||||||
<div
|
videoProfile = webcamConsumer.profile;
|
||||||
data-component='Peer'
|
|
||||||
className={classnames({
|
|
||||||
screen : screenConsumer
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{videoVisible && !webcamConsumer.supported ?
|
|
||||||
<div className='incompatible-video'>
|
|
||||||
<p>incompatible video</p>
|
|
||||||
</div>
|
|
||||||
:null
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className={classnames('view-container', 'webcam')} style={style}>
|
let screenProfile;
|
||||||
<div className='controls'>
|
|
||||||
|
if (screenConsumer)
|
||||||
|
screenProfile = screenConsumer.profile;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-component='Peer'
|
||||||
|
className={classnames({
|
||||||
|
screen : screenConsumer
|
||||||
|
})}
|
||||||
|
onMouseOver={this.handleMouseOver}
|
||||||
|
onMouseOut={this.handleMouseOut}
|
||||||
|
>
|
||||||
|
{videoVisible && !webcamConsumer.supported ?
|
||||||
|
<div className='incompatible-video'>
|
||||||
|
<p>incompatible video</p>
|
||||||
|
</div>
|
||||||
|
:null
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={classnames('view-container', 'webcam')} style={style}>
|
||||||
<div
|
<div
|
||||||
className={classnames('button', 'mic', {
|
className={classnames('controls', {
|
||||||
on : micEnabled,
|
visible : this.state.controlsVisible
|
||||||
off : !micEnabled,
|
|
||||||
disabled : peer.peerAudioInProgress
|
|
||||||
})}
|
})}
|
||||||
onClick={(e) =>
|
>
|
||||||
{
|
|
||||||
e.stopPropagation();
|
|
||||||
micEnabled ? onMuteMic(peer.name) : onUnmuteMic(peer.name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={classnames('button', 'webcam', {
|
|
||||||
on : videoVisible,
|
|
||||||
off : !videoVisible,
|
|
||||||
disabled : peer.peerVideoInProgress
|
|
||||||
})}
|
|
||||||
onClick={(e) =>
|
|
||||||
{
|
|
||||||
e.stopPropagation();
|
|
||||||
videoVisible ?
|
|
||||||
onDisableWebcam(peer.name) : onEnableWebcam(peer.name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={classnames('button', 'fullscreen')}
|
|
||||||
onClick={(e) =>
|
|
||||||
{
|
|
||||||
e.stopPropagation();
|
|
||||||
toggleConsumerFullscreen(webcamConsumer);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<PeerView
|
|
||||||
advancedMode={advancedMode}
|
|
||||||
peer={peer}
|
|
||||||
audioTrack={micConsumer ? micConsumer.track : null}
|
|
||||||
videoTrack={webcamConsumer ? webcamConsumer.track : null}
|
|
||||||
videoVisible={videoVisible}
|
|
||||||
videoProfile={videoProfile}
|
|
||||||
audioCodec={micConsumer ? micConsumer.codec : null}
|
|
||||||
videoCodec={webcamConsumer ? webcamConsumer.codec : null}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{screenConsumer ?
|
|
||||||
<div className={classnames('view-container', 'screen')} style={style}>
|
|
||||||
<div className='controls'>
|
|
||||||
<div
|
<div
|
||||||
className={classnames('button', 'screen', {
|
className={classnames('button', 'mic', {
|
||||||
on : screenVisible,
|
on : micEnabled,
|
||||||
off : !screenVisible,
|
off : !micEnabled,
|
||||||
disabled : peer.peerScreenInProgress
|
disabled : peer.peerAudioInProgress
|
||||||
})}
|
})}
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
{
|
{
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
screenVisible ?
|
micEnabled ? onMuteMic(peer.name) : onUnmuteMic(peer.name);
|
||||||
onDisableScreen(peer.name) : onEnableScreen(peer.name);
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={classnames('button', 'webcam', {
|
||||||
|
on : videoVisible,
|
||||||
|
off : !videoVisible,
|
||||||
|
disabled : peer.peerVideoInProgress
|
||||||
|
})}
|
||||||
|
onClick={(e) =>
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
videoVisible ?
|
||||||
|
onDisableWebcam(peer.name) : onEnableWebcam(peer.name);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -140,23 +128,62 @@ const Peer = (props) =>
|
||||||
onClick={(e) =>
|
onClick={(e) =>
|
||||||
{
|
{
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleConsumerFullscreen(screenConsumer);
|
toggleConsumerFullscreen(webcamConsumer);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ScreenView
|
<PeerView
|
||||||
advancedMode={advancedMode}
|
advancedMode={advancedMode}
|
||||||
screenTrack={screenConsumer ? screenConsumer.track : null}
|
peer={peer}
|
||||||
screenVisible={screenVisible}
|
audioTrack={micConsumer ? micConsumer.track : null}
|
||||||
screenProfile={screenProfile}
|
videoTrack={webcamConsumer ? webcamConsumer.track : null}
|
||||||
screenCodec={screenConsumer ? screenConsumer.codec : null}
|
videoVisible={videoVisible}
|
||||||
|
videoProfile={videoProfile}
|
||||||
|
audioCodec={micConsumer ? micConsumer.codec : null}
|
||||||
|
videoCodec={webcamConsumer ? webcamConsumer.codec : null}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
:null
|
|
||||||
}
|
{screenConsumer ?
|
||||||
</div>
|
<div className={classnames('view-container', 'screen')} style={style}>
|
||||||
);
|
<div className='controls'>
|
||||||
};
|
<div
|
||||||
|
className={classnames('button', 'screen', {
|
||||||
|
on : screenVisible,
|
||||||
|
off : !screenVisible,
|
||||||
|
disabled : peer.peerScreenInProgress
|
||||||
|
})}
|
||||||
|
onClick={(e) =>
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
screenVisible ?
|
||||||
|
onDisableScreen(peer.name) : onEnableScreen(peer.name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={classnames('button', 'fullscreen')}
|
||||||
|
onClick={(e) =>
|
||||||
|
{
|
||||||
|
e.stopPropagation();
|
||||||
|
toggleConsumerFullscreen(screenConsumer);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ScreenView
|
||||||
|
advancedMode={advancedMode}
|
||||||
|
screenTrack={screenConsumer ? screenConsumer.track : null}
|
||||||
|
screenVisible={screenVisible}
|
||||||
|
screenProfile={screenProfile}
|
||||||
|
screenCodec={screenConsumer ? screenConsumer.codec : null}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
:null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Peer.propTypes =
|
Peer.propTypes =
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,30 +15,11 @@ import ToolAreaButton from './ToolArea/ToolAreaButton';
|
||||||
import ToolArea from './ToolArea/ToolArea';
|
import ToolArea from './ToolArea/ToolArea';
|
||||||
import FullScreenView from './FullScreenView';
|
import FullScreenView from './FullScreenView';
|
||||||
import Draggable from 'react-draggable';
|
import Draggable from 'react-draggable';
|
||||||
|
import { idle } from '../utils';
|
||||||
|
|
||||||
// Hide toolbars after 10 seconds of inactivity.
|
// Hide toolbars after 10 seconds of inactivity.
|
||||||
const TIMEOUT = 10 * 1000;
|
const TIMEOUT = 10 * 1000;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a function which will call the callback function
|
|
||||||
* after the given amount of milliseconds has passed since
|
|
||||||
* the last time the callback function was called.
|
|
||||||
*/
|
|
||||||
const idle = (callback, delay) =>
|
|
||||||
{
|
|
||||||
let handle;
|
|
||||||
|
|
||||||
return () =>
|
|
||||||
{
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
clearTimeout(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = setTimeout(callback, delay);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class Room extends React.Component
|
class Room extends React.Component
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,23 @@ export function getBrowserType()
|
||||||
|
|
||||||
return 'N/A';
|
return 'N/A';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a function which will call the callback function
|
||||||
|
* after the given amount of milliseconds has passed since
|
||||||
|
* the last time the callback function was called.
|
||||||
|
*/
|
||||||
|
export const idle = (callback, delay) =>
|
||||||
|
{
|
||||||
|
let handle;
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
if (handle)
|
||||||
|
{
|
||||||
|
clearTimeout(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = setTimeout(callback, delay);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -41,6 +41,15 @@
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0.4vmin;
|
padding: 0.4vmin;
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
animation: fade-out 0.3s;
|
||||||
|
|
||||||
|
&.visible {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
animation: fade-in 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
> .button {
|
> .button {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
|
||||||
|
|
@ -440,27 +440,3 @@
|
||||||
@keyframes Room-info-state-connecting {
|
@keyframes Room-info-state-connecting {
|
||||||
50% { background-color: rgba(orange, 0.75); }
|
50% { background-color: rgba(orange, 0.75); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fade-in {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-out {
|
|
||||||
from {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,7 @@ global-reset();
|
||||||
@import './mixins';
|
@import './mixins';
|
||||||
@import './fonts';
|
@import './fonts';
|
||||||
@import './reset';
|
@import './reset';
|
||||||
|
@import './keyframes';
|
||||||
|
|
||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-out {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue