commit
51de7bb33d
|
|
@ -24,14 +24,14 @@ module.exports =
|
|||
version: '15'
|
||||
}
|
||||
},
|
||||
parser: 'babel-eslint',
|
||||
parserOptions:
|
||||
{
|
||||
ecmaVersion: 6,
|
||||
ecmaVersion: 9,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures:
|
||||
{
|
||||
impliedStrict: true,
|
||||
experimentalObjectRestSpread: true,
|
||||
jsx: true
|
||||
}
|
||||
},
|
||||
|
|
@ -121,7 +121,6 @@ module.exports =
|
|||
'no-implicit-globals': 2,
|
||||
'no-inner-declarations': 2,
|
||||
'no-invalid-regexp': 2,
|
||||
'no-invalid-this': 2,
|
||||
'no-irregular-whitespace': 2,
|
||||
'no-lonely-if': 2,
|
||||
'no-mixed-operators': 2,
|
||||
|
|
|
|||
|
|
@ -79,13 +79,7 @@ function bundle(options)
|
|||
})
|
||||
.transform('babelify',
|
||||
{
|
||||
presets : [ 'es2015', 'react' ],
|
||||
plugins :
|
||||
[
|
||||
'transform-runtime',
|
||||
'transform-object-assign',
|
||||
'transform-object-rest-spread'
|
||||
]
|
||||
presets : [ 'env', 'react-app' ]
|
||||
})
|
||||
.transform(envify(
|
||||
{
|
||||
|
|
@ -132,21 +126,29 @@ function changeHTML(content)
|
|||
|
||||
gulp.task('clean', () => del(OUTPUT_DIR, { force: true }));
|
||||
|
||||
gulp.task('lint', () =>
|
||||
{
|
||||
const src =
|
||||
[
|
||||
const LINTING_FILES = [
|
||||
'gulpfile.js',
|
||||
'lib/**/*.js',
|
||||
'lib/**/*.jsx'
|
||||
];
|
||||
|
||||
return gulp.src(src)
|
||||
gulp.task('lint', () =>
|
||||
{
|
||||
return gulp.src(LINTING_FILES)
|
||||
.pipe(plumber())
|
||||
.pipe(eslint())
|
||||
.pipe(eslint.format());
|
||||
});
|
||||
|
||||
gulp.task('lint-fix', function()
|
||||
{
|
||||
return gulp.src(LINTING_FILES)
|
||||
.pipe(plumber())
|
||||
.pipe(eslint({ fix: true }))
|
||||
.pipe(eslint.format())
|
||||
.pipe(gulp.dest((file) => file.base));
|
||||
});
|
||||
|
||||
gulp.task('css', () =>
|
||||
{
|
||||
return gulp.src('stylus/index.styl')
|
||||
|
|
|
|||
|
|
@ -11,6 +11,24 @@ import ScreenView from './ScreenView';
|
|||
|
||||
class Me extends React.Component
|
||||
{
|
||||
state = {
|
||||
controlsVisible : false
|
||||
};
|
||||
|
||||
handleMouseOver = () =>
|
||||
{
|
||||
this.setState({
|
||||
controlsVisible : true
|
||||
});
|
||||
};
|
||||
|
||||
handleMouseOut = () =>
|
||||
{
|
||||
this.setState({
|
||||
controlsVisible : false
|
||||
});
|
||||
};
|
||||
|
||||
constructor(props)
|
||||
{
|
||||
super(props);
|
||||
|
|
@ -85,10 +103,15 @@ class Me extends React.Component
|
|||
data-tip={tip}
|
||||
data-tip-disable={!tip}
|
||||
data-type='dark'
|
||||
onMouseOver={this.handleMouseOver}
|
||||
onMouseOut={this.handleMouseOut}
|
||||
>
|
||||
<div className={classnames('view-container', 'webcam')}>
|
||||
{connected ?
|
||||
<div className='controls'>
|
||||
<div className={classnames('controls', {
|
||||
visible : this.state.controlsVisible
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classnames('button', 'mic', micState, {
|
||||
disabled : me.audioInProgress
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
|
@ -8,7 +8,27 @@ import * as stateActions from '../redux/stateActions';
|
|||
import PeerView from './PeerView';
|
||||
import ScreenView from './ScreenView';
|
||||
|
||||
const Peer = (props) =>
|
||||
class Peer extends Component
|
||||
{
|
||||
state = {
|
||||
controlsVisible : false
|
||||
};
|
||||
|
||||
handleMouseOver = () =>
|
||||
{
|
||||
this.setState({
|
||||
controlsVisible : true
|
||||
});
|
||||
};
|
||||
|
||||
handleMouseOut = () =>
|
||||
{
|
||||
this.setState({
|
||||
controlsVisible : false
|
||||
});
|
||||
};
|
||||
|
||||
render()
|
||||
{
|
||||
const {
|
||||
advancedMode,
|
||||
|
|
@ -24,7 +44,7 @@ const Peer = (props) =>
|
|||
onEnableScreen,
|
||||
toggleConsumerFullscreen,
|
||||
style
|
||||
} = props;
|
||||
} = this.props;
|
||||
|
||||
const micEnabled = (
|
||||
Boolean(micConsumer) &&
|
||||
|
|
@ -60,6 +80,8 @@ const Peer = (props) =>
|
|||
className={classnames({
|
||||
screen : screenConsumer
|
||||
})}
|
||||
onMouseOver={this.handleMouseOver}
|
||||
onMouseOut={this.handleMouseOut}
|
||||
>
|
||||
{videoVisible && !webcamConsumer.supported ?
|
||||
<div className='incompatible-video'>
|
||||
|
|
@ -69,7 +91,11 @@ const Peer = (props) =>
|
|||
}
|
||||
|
||||
<div className={classnames('view-container', 'webcam')} style={style}>
|
||||
<div className='controls'>
|
||||
<div
|
||||
className={classnames('controls', {
|
||||
visible : this.state.controlsVisible
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classnames('button', 'mic', {
|
||||
on : micEnabled,
|
||||
|
|
@ -156,7 +182,8 @@ const Peer = (props) =>
|
|||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Peer.propTypes =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import classnames from 'classnames';
|
|||
import ClipboardButton from 'react-clipboard.js';
|
||||
import * as appPropTypes from './appPropTypes';
|
||||
import * as requestActions from '../redux/requestActions';
|
||||
import * as stateActions from '../redux/stateActions';
|
||||
import { Appear } from './transitions';
|
||||
import Me from './Me';
|
||||
import Peers from './Peers';
|
||||
|
|
@ -14,9 +15,45 @@ import ToolAreaButton from './ToolArea/ToolAreaButton';
|
|||
import ToolArea from './ToolArea/ToolArea';
|
||||
import FullScreenView from './FullScreenView';
|
||||
import Draggable from 'react-draggable';
|
||||
import { idle } from '../utils';
|
||||
|
||||
// Hide toolbars after 10 seconds of inactivity.
|
||||
const TIMEOUT = 10 * 1000;
|
||||
|
||||
class Room extends React.Component
|
||||
{
|
||||
/**
|
||||
* Hides the different toolbars on the page after a
|
||||
* given amount of time has passed since the
|
||||
* last time the cursor was moved.
|
||||
*/
|
||||
waitForHide = idle(() =>
|
||||
{
|
||||
this.props.setToolbarsVisible(false);
|
||||
}, TIMEOUT);
|
||||
|
||||
handleMouseMove = () =>
|
||||
{
|
||||
// If the toolbars were hidden, show them again when
|
||||
// the user moves their cursor.
|
||||
if (!this.props.room.toolbarsVisible)
|
||||
{
|
||||
this.props.setToolbarsVisible(true);
|
||||
}
|
||||
|
||||
this.waitForHide();
|
||||
}
|
||||
|
||||
componentDidMount()
|
||||
{
|
||||
window.addEventListener('mousemove', this.handleMouseMove);
|
||||
}
|
||||
|
||||
componentWillUnmount()
|
||||
{
|
||||
window.removeEventListener('mousemove', this.handleMouseMove);
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const {
|
||||
|
|
@ -78,7 +115,11 @@ class Room extends React.Component
|
|||
:null
|
||||
}
|
||||
|
||||
<div className='room-link-wrapper'>
|
||||
<div
|
||||
className={classnames('room-link-wrapper room-controls', {
|
||||
'visible' : this.props.room.toolbarsVisible
|
||||
})}
|
||||
>
|
||||
<div className='room-link'>
|
||||
<ClipboardButton
|
||||
component='a'
|
||||
|
|
@ -125,7 +166,10 @@ class Room extends React.Component
|
|||
</div>
|
||||
</Draggable>
|
||||
|
||||
<div className='sidebar'>
|
||||
<div className={classnames('sidebar room-controls', {
|
||||
'visible' : this.props.room.toolbarsVisible
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={classnames('button', 'screen', screenState)}
|
||||
data-tip={screenTip}
|
||||
|
|
@ -214,7 +258,8 @@ Room.propTypes =
|
|||
onUnShareScreen : PropTypes.func.isRequired,
|
||||
onNeedExtension : PropTypes.func.isRequired,
|
||||
onLeaveMeeting : PropTypes.func.isRequired,
|
||||
onLogin : PropTypes.func.isRequired
|
||||
onLogin : PropTypes.func.isRequired,
|
||||
setToolbarsVisible : PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) =>
|
||||
|
|
@ -261,6 +306,10 @@ const mapDispatchToProps = (dispatch) =>
|
|||
onLogin : () =>
|
||||
{
|
||||
dispatch(requestActions.userLogin());
|
||||
},
|
||||
setToolbarsVisible : (visible) =>
|
||||
{
|
||||
dispatch(stateActions.setToolbarsVisible(visible));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ class ToolAreaButton extends React.Component
|
|||
return (
|
||||
<div data-component='ToolAreaButton'>
|
||||
<div
|
||||
className={classnames('button', 'toolarea-button', {
|
||||
on : toolAreaOpen
|
||||
className={classnames('button toolarea-button room-controls', {
|
||||
on : toolAreaOpen,
|
||||
visible : this.props.visible
|
||||
})}
|
||||
data-tip='Toggle tool area'
|
||||
data-type='dark'
|
||||
|
|
@ -40,13 +41,15 @@ ToolAreaButton.propTypes =
|
|||
{
|
||||
toolAreaOpen : PropTypes.bool.isRequired,
|
||||
toggleToolArea : PropTypes.func.isRequired,
|
||||
unread : PropTypes.bool.isRequired
|
||||
unread : PropTypes.bool.isRequired,
|
||||
visible : PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) =>
|
||||
{
|
||||
return {
|
||||
toolAreaOpen : state.toolarea.toolAreaOpen,
|
||||
visible : state.room.toolbarsVisible,
|
||||
unread : state.toolarea.unread
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ const initialState =
|
|||
activeSpeakerName : null,
|
||||
showSettings : false,
|
||||
advancedMode : false,
|
||||
fullScreenConsumer : null // ConsumerID
|
||||
fullScreenConsumer : null, // ConsumerID
|
||||
toolbarsVisible : true
|
||||
};
|
||||
|
||||
const room = (state = initialState, action) =>
|
||||
|
|
@ -58,6 +59,12 @@ const room = (state = initialState, action) =>
|
|||
return { ...state, fullScreenConsumer: currentConsumer ? null : consumerId };
|
||||
}
|
||||
|
||||
case 'SET_TOOLBARS_VISIBLE':
|
||||
{
|
||||
const { toolbarsVisible } = action.payload;
|
||||
|
||||
return { ...state, toolbarsVisible };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -369,6 +369,11 @@ export const toggleConsumerFullscreen = (consumerId) =>
|
|||
};
|
||||
};
|
||||
|
||||
export const setToolbarsVisible = (toolbarsVisible) => ({
|
||||
type : 'SET_TOOLBARS_VISIBLE',
|
||||
payload : { toolbarsVisible }
|
||||
});
|
||||
|
||||
export const increaseBadge = () =>
|
||||
{
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -43,3 +43,23 @@ export function getBrowserType()
|
|||
|
||||
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);
|
||||
};
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -8,65 +8,65 @@
|
|||
"main": "lib/index.jsx",
|
||||
"dependencies": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"classnames": "^2.2.5",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "^3.1.0",
|
||||
"domready": "^1.0.8",
|
||||
"hark": "^1.1.6",
|
||||
"hark": "^1.2.0",
|
||||
"js-cookie": "^2.2.0",
|
||||
"marked": "^0.3.17",
|
||||
"marked": "^0.4.0",
|
||||
"mediasoup-client": "^2.1.1",
|
||||
"prop-types": "^15.6.0",
|
||||
"protoo-client": "^2.0.7",
|
||||
"prop-types": "^15.6.2",
|
||||
"protoo-client": "^3.0.0",
|
||||
"random-string": "^0.2.0",
|
||||
"react": "^16.2.0",
|
||||
"react-clipboard.js": "^1.1.3",
|
||||
"react-dom": "^16.2.0",
|
||||
"react": "^16.4.1",
|
||||
"react-clipboard.js": "^1.1.4",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-draggable": "^3.0.5",
|
||||
"react-dropdown": "^1.5.0",
|
||||
"react-redux": "^5.0.6",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-spinner": "^0.2.7",
|
||||
"react-tooltip": "^3.4.0",
|
||||
"react-transition-group": "^2.2.1",
|
||||
"redux": "^3.7.2",
|
||||
"react-tooltip": "^3.6.1",
|
||||
"react-transition-group": "^2.4.0",
|
||||
"redux": "^4.0.0",
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"riek": "^1.1.0",
|
||||
"url-parse": "^1.2.0"
|
||||
"url-parse": "^1.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-transform-object-assign": "^6.22.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.2.6",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-preset-react-app": "^3.1.2",
|
||||
"babel-preset-stage-0": "^6.24.1",
|
||||
"babelify": "^8.0.0",
|
||||
"browser-sync": "^2.23.6",
|
||||
"browserify": "^16.1.0",
|
||||
"browser-sync": "^2.24.5",
|
||||
"browserify": "^16.2.2",
|
||||
"del": "^3.0.0",
|
||||
"envify": "^4.1.0",
|
||||
"eslint": "^4.17.0",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eslint-plugin-react": "^7.6.1",
|
||||
"eslint": "^5.1.0",
|
||||
"eslint-plugin-import": "^2.13.0",
|
||||
"eslint-plugin-react": "^7.10.0",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-css-base64": "^1.3.4",
|
||||
"gulp-eslint": "^4.0.2",
|
||||
"gulp-change": "^1.0.0",
|
||||
"gulp-header": "^2.0.1",
|
||||
"gulp-css-base64": "^1.3.4",
|
||||
"gulp-eslint": "^5.0.0",
|
||||
"gulp-header": "^2.0.5",
|
||||
"gulp-if": "^2.0.2",
|
||||
"gulp-plumber": "^1.2.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-rename": "^1.3.0",
|
||||
"gulp-stylus": "^2.7.0",
|
||||
"gulp-touch-cmd": "0.0.1",
|
||||
"gulp-uglify": "^3.0.0",
|
||||
"gulp-util": "^3.0.8",
|
||||
"lodash": "^4.17.10",
|
||||
"mkdirp": "^0.5.1",
|
||||
"ncp": "^2.0.0",
|
||||
"nib": "^1.1.2",
|
||||
"supports-color": "^5.2.0",
|
||||
"supports-color": "^5.4.0",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vinyl-source-stream": "^2.0.0",
|
||||
"watchify": "^3.10.0"
|
||||
"watchify": "^3.11.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@
|
|||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0.4vmin;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
animation: fade-out 0.3s;
|
||||
|
||||
&.visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
animation: fade-in 0.3s;
|
||||
}
|
||||
|
||||
> .button {
|
||||
flex: 0 0 auto;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,15 @@
|
|||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0.4vmin;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
animation: fade-out 0.3s;
|
||||
|
||||
&.visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
animation: fade-in 0.3s;
|
||||
}
|
||||
|
||||
> .button {
|
||||
flex: 0 0 auto;
|
||||
|
|
|
|||
|
|
@ -276,6 +276,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
.room-controls {
|
||||
visibility: hidden;
|
||||
animation: fade-out 0.5s;
|
||||
opacity: 0;
|
||||
|
||||
&.visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
animation: fade-in 0.5s;
|
||||
}
|
||||
}
|
||||
|
||||
.Dropdown-root {
|
||||
position: relative;
|
||||
padding: 0.3vmin;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ global-reset();
|
|||
@import './mixins';
|
||||
@import './fonts';
|
||||
@import './reset';
|
||||
@import './keyframes';
|
||||
|
||||
html {
|
||||
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