Started work on settings dialog. Possible to switch camera.

master
Håvar Aambø Fosstveit 2018-06-15 14:58:01 +02:00
parent 668fa0f37f
commit 7e1b391fe1
18 changed files with 651 additions and 70 deletions

View File

@ -366,9 +366,9 @@ export default class RoomClient
});
}
changeWebcam()
changeWebcam(deviceId)
{
logger.debug('changeWebcam()');
logger.debug('changeWebcam() [deviceId: %s]', deviceId);
this._dispatch(
stateActions.setWebcamInProgress(true));
@ -376,22 +376,20 @@ export default class RoomClient
return Promise.resolve()
.then(() =>
{
return this._updateWebcams();
logger.debug('changeWebcam() | calling enumerateDevices()');
return navigator.mediaDevices.enumerateDevices();
})
.then(() =>
.then((devices) =>
{
const array = Array.from(this._webcams.keys());
const len = array.length;
const deviceId =
this._webcam.device ? this._webcam.device.deviceId : undefined;
let idx = array.indexOf(deviceId);
for (const device of devices)
{
if (device.kind !== 'videoinput')
continue;
if (idx < len - 1)
idx++;
else
idx = 0;
this._webcam.device = this._webcams.get(array[idx]);
if (device.deviceId == deviceId)
this._webcam.device = device;
}
logger.debug(
'changeWebcam() | new selected webcam [device:%o]',
@ -1487,7 +1485,7 @@ export default class RoomClient
logger.debug('_updateWebcams()');
// Reset the list.
this._webcams = new Map();
this._webcams = {};
return Promise.resolve()
.then(() =>
@ -1503,25 +1501,33 @@ export default class RoomClient
if (device.kind !== 'videoinput')
continue;
this._webcams.set(device.deviceId, device);
this._webcams[device.deviceId] = {
value : device.deviceId,
label : device.label
};
}
})
.then(() =>
{
const array = Array.from(this._webcams.values());
const len = array.length;
const currentWebcamId =
this._webcam.device ? this._webcam.device.deviceId : undefined;
logger.debug('_updateWebcams() [webcams:%o]', array);
logger.debug('_updateWebcams() [webcams:%o]', this._webcams);
const len = Object.keys(this._webcams).length;
if (len === 0)
this._webcam.device = null;
else if (!this._webcams.has(currentWebcamId))
this._webcam.device = array[0];
else if (!this._webcams[currentWebcamId])
for (this._webcam.device in this._webcams)
if (this._webcams.hasOwnProperty(this._webcam.device))
break;
this._dispatch(
stateActions.setCanChangeWebcam(this._webcams.size >= 2));
stateActions.setCanChangeWebcam(len >= 2));
if (len >= 1)
this._dispatch(
stateActions.setWebcamDevices(this._webcams));
});
}

View File

@ -35,8 +35,7 @@ class Me extends React.Component
onMuteMic,
onUnmuteMic,
onEnableWebcam,
onDisableWebcam,
onChangeWebcam
onDisableWebcam
} = this.props;
let micState;
@ -59,13 +58,6 @@ class Me extends React.Component
else
webcamState = 'off';
let changeWebcamState;
if (Boolean(webcamProducer) && me.canChangeWebcam)
changeWebcamState = 'on';
else
changeWebcamState = 'unsupported';
const videoVisible = (
Boolean(webcamProducer) &&
!webcamProducer.locallyPaused &&
@ -104,13 +96,6 @@ class Me extends React.Component
webcamState === 'on' ? onDisableWebcam() : onEnableWebcam();
}}
/>
<div
className={classnames('button', 'change-webcam', changeWebcamState, {
disabled : me.webcamInProgress
})}
onClick={() => onChangeWebcam()}
/>
</div>
:null
}
@ -179,8 +164,7 @@ Me.propTypes =
onMuteMic : PropTypes.func.isRequired,
onUnmuteMic : PropTypes.func.isRequired,
onEnableWebcam : PropTypes.func.isRequired,
onDisableWebcam : PropTypes.func.isRequired,
onChangeWebcam : PropTypes.func.isRequired
onDisableWebcam : PropTypes.func.isRequired
};
const mapStateToProps = (state) =>
@ -209,8 +193,7 @@ const mapDispatchToProps = (dispatch) =>
onMuteMic : () => dispatch(requestActions.muteMic()),
onUnmuteMic : () => dispatch(requestActions.unmuteMic()),
onEnableWebcam : () => dispatch(requestActions.enableWebcam()),
onDisableWebcam : () => dispatch(requestActions.disableWebcam()),
onChangeWebcam : () => dispatch(requestActions.changeWebcam())
onDisableWebcam : () => dispatch(requestActions.disableWebcam())
};
};

View File

@ -5,12 +5,14 @@ import PropTypes from 'prop-types';
import classnames from 'classnames';
import ClipboardButton from 'react-clipboard.js';
import * as appPropTypes from './appPropTypes';
import * as stateActions from '../redux/stateActions';
import * as requestActions from '../redux/requestActions';
import { Appear } from './transitions';
import Me from './Me';
import Peers from './Peers';
import Notifications from './Notifications';
import ChatWidget from './ChatWidget';
import Settings from './Settings';
class Room extends React.Component
{
@ -24,6 +26,7 @@ class Room extends React.Component
onRoomLinkCopy,
onSetAudioMode,
onRestartIce,
onToggleSettings,
onShareScreen,
onUnShareScreen,
onNeedExtension,
@ -158,6 +161,16 @@ class Room extends React.Component
onClick={() => onRestartIce()}
/>
<div
className={classnames('button', 'settings', {
on : room.showSettings,
off : !room.showSettings
})}
data-tip='Open settings'
data-type='dark'
onClick={() => onToggleSettings()}
/>
<div
className={classnames('button', 'raise-hand', {
on : me.raiseHand,
@ -176,6 +189,10 @@ class Room extends React.Component
/>
</div>
<Settings
onToggleSettings={onToggleSettings}
/>
<ReactTooltip
effect='solid'
delayShow={100}
@ -199,6 +216,7 @@ Room.propTypes =
onShareScreen : PropTypes.func.isRequired,
onUnShareScreen : PropTypes.func.isRequired,
onNeedExtension : PropTypes.func.isRequired,
onToggleSettings : PropTypes.func.isRequired,
onToggleHand : PropTypes.func.isRequired,
onLeaveMeeting : PropTypes.func.isRequired
};
@ -238,6 +256,10 @@ const mapDispatchToProps = (dispatch) =>
{
dispatch(requestActions.restartIce());
},
onToggleSettings : () =>
{
dispatch(stateActions.toggleSettings());
},
onToggleHand : (enable) =>
{
if (enable)

View File

@ -0,0 +1,89 @@
import React from 'react';
import { connect } from 'react-redux';
import * as appPropTypes from './appPropTypes';
import * as requestActions from '../redux/requestActions';
import PropTypes from 'prop-types';
import Dropdown from 'react-dropdown';
class Settings extends React.Component
{
constructor(props)
{
super(props);
}
render()
{
const {
room,
me,
handleChangeWebcam,
onToggleSettings
} = this.props;
if (!room.showSettings)
return null;
const webcams = Object.values(me.webcamDevices);
return (
<div data-component='Settings'>
<div className='dialog'>
<div className='header'>
<span>Settings</span>
</div>
<div className='settings'>
<Dropdown
disabled={!me.canChangeWebcam}
options={webcams}
onChange={handleChangeWebcam}
value={webcams[0]}
placeholder='No other cameras detected'
/>
</div>
<div className='footer'>
<span
className='button'
onClick={() => onToggleSettings()}
>
Close
</span>
</div>
</div>
</div>
);
}
}
Settings.propTypes =
{
me : appPropTypes.Me.isRequired,
room : appPropTypes.Room.isRequired,
onToggleSettings : PropTypes.func.isRequired,
handleChangeWebcam : PropTypes.func.isRequired
};
const mapStateToProps = (state) =>
{
return {
me : state.me,
room : state.room
};
};
const mapDispatchToProps = (dispatch) =>
{
return {
handleChangeWebcam : (device) =>
{
dispatch(requestActions.changeWebcam(device.value));
}
};
};
const SettingsContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Settings);
export default SettingsContainer;

View File

@ -9,6 +9,7 @@ const initialState =
canShareScreen : false,
needExtension : false,
canChangeWebcam : false,
webcamDevices : null,
webcamInProgress : false,
screenShareInProgress : false,
audioOnly : false,
@ -50,6 +51,13 @@ const me = (state = initialState, action) =>
return { ...state, canChangeWebcam };
}
case 'SET_WEBCAM_DEVICES':
{
const devices = action.payload;
return { ...state, webcamDevices: devices };
}
case 'SET_WEBCAM_IN_PROGRESS':
{
const { flag } = action.payload;

View File

@ -4,7 +4,8 @@ const initialState =
state : 'new', // new/connecting/connected/disconnected/closed,
activeSpeakerName : null,
peerHeight : 300,
peerWidth : 400
peerWidth : 400,
showSettings : false
};
const room = (state = initialState, action) =>
@ -42,6 +43,13 @@ const room = (state = initialState, action) =>
return { ...state, peerWidth: peerWidth, peerHeight: peerHeight };
}
case 'TOGGLE_SETTINGS':
{
const showSettings = !state.showSettings;
return { ...state, showSettings };
}
default:
return state;
}

View File

@ -57,10 +57,11 @@ export const disableWebcam = () =>
};
};
export const changeWebcam = () =>
export const changeWebcam = (deviceId) =>
{
return {
type : 'CHANGE_WEBCAM'
type : 'CHANGE_WEBCAM',
payload : { deviceId }
};
};

View File

@ -83,7 +83,9 @@ export default ({ dispatch, getState }) => (next) =>
case 'CHANGE_WEBCAM':
{
client.changeWebcam();
const { deviceId } = action.payload;
client.changeWebcam(deviceId);
break;
}

View File

@ -62,6 +62,14 @@ export const setCanChangeWebcam = (flag) =>
};
};
export const setWebcamDevices = (devices) =>
{
return {
type : 'SET_WEBCAM_DEVICES',
payload : devices
};
};
export const setDisplayName = (displayName) =>
{
return {
@ -110,6 +118,13 @@ export const setMyRaiseHandState = (flag) =>
};
};
export const toggleSettings = () =>
{
return {
type : 'TOGGLE_SETTINGS'
};
};
export const setMyRaiseHandStateInProgress = (flag) =>
{
return {

296
app/package-lock.json generated
View File

@ -591,6 +591,28 @@
}
}
},
"babel-helper-bindify-decorators": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz",
"integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=",
"dev": true,
"requires": {
"babel-runtime": "6.26.0",
"babel-traverse": "6.26.0",
"babel-types": "6.26.0"
}
},
"babel-helper-builder-binary-assignment-operator-visitor": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
"integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
"dev": true,
"requires": {
"babel-helper-explode-assignable-expression": "6.24.1",
"babel-runtime": "6.26.0",
"babel-types": "6.26.0"
}
},
"babel-helper-builder-react-jsx": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz",
@ -626,6 +648,29 @@
"lodash": "4.17.4"
}
},
"babel-helper-explode-assignable-expression": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
"integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
"dev": true,
"requires": {
"babel-runtime": "6.26.0",
"babel-traverse": "6.26.0",
"babel-types": "6.26.0"
}
},
"babel-helper-explode-class": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz",
"integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=",
"dev": true,
"requires": {
"babel-helper-bindify-decorators": "6.24.1",
"babel-runtime": "6.26.0",
"babel-traverse": "6.26.0",
"babel-types": "6.26.0"
}
},
"babel-helper-function-name": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
@ -680,6 +725,19 @@
"lodash": "4.17.4"
}
},
"babel-helper-remap-async-to-generator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
"integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
"dev": true,
"requires": {
"babel-helper-function-name": "6.24.1",
"babel-runtime": "6.26.0",
"babel-template": "6.26.0",
"babel-traverse": "6.26.0",
"babel-types": "6.26.0"
}
},
"babel-helper-replace-supers": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
@ -722,12 +780,72 @@
"babel-runtime": "6.26.0"
}
},
"babel-plugin-syntax-async-functions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
"dev": true
},
"babel-plugin-syntax-async-generators": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
"integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
"dev": true
},
"babel-plugin-syntax-class-constructor-call": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
"integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=",
"dev": true
},
"babel-plugin-syntax-class-properties": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
"dev": true
},
"babel-plugin-syntax-decorators": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
"dev": true
},
"babel-plugin-syntax-do-expressions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
"integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=",
"dev": true
},
"babel-plugin-syntax-dynamic-import": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
"integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
"dev": true
},
"babel-plugin-syntax-exponentiation-operator": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
"integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
"dev": true
},
"babel-plugin-syntax-export-extensions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
"integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=",
"dev": true
},
"babel-plugin-syntax-flow": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
"integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=",
"dev": true
},
"babel-plugin-syntax-function-bind": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
"integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=",
"dev": true
},
"babel-plugin-syntax-jsx": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
@ -740,6 +858,80 @@
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
"dev": true
},
"babel-plugin-syntax-trailing-function-commas": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
"integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=",
"dev": true
},
"babel-plugin-transform-async-generator-functions": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz",
"integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=",
"dev": true,
"requires": {
"babel-helper-remap-async-to-generator": "6.24.1",
"babel-plugin-syntax-async-generators": "6.13.0",
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-async-to-generator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
"integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
"dev": true,
"requires": {
"babel-helper-remap-async-to-generator": "6.24.1",
"babel-plugin-syntax-async-functions": "6.13.0",
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-class-constructor-call": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz",
"integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=",
"dev": true,
"requires": {
"babel-plugin-syntax-class-constructor-call": "6.18.0",
"babel-runtime": "6.26.0",
"babel-template": "6.26.0"
}
},
"babel-plugin-transform-class-properties": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
"integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
"dev": true,
"requires": {
"babel-helper-function-name": "6.24.1",
"babel-plugin-syntax-class-properties": "6.13.0",
"babel-runtime": "6.26.0",
"babel-template": "6.26.0"
}
},
"babel-plugin-transform-decorators": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz",
"integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=",
"dev": true,
"requires": {
"babel-helper-explode-class": "6.24.1",
"babel-plugin-syntax-decorators": "6.13.0",
"babel-runtime": "6.26.0",
"babel-template": "6.26.0",
"babel-types": "6.26.0"
}
},
"babel-plugin-transform-do-expressions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz",
"integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=",
"dev": true,
"requires": {
"babel-plugin-syntax-do-expressions": "6.13.0",
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-es2015-arrow-functions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
@ -974,6 +1166,27 @@
"regexpu-core": "2.0.0"
}
},
"babel-plugin-transform-exponentiation-operator": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
"integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
"dev": true,
"requires": {
"babel-helper-builder-binary-assignment-operator-visitor": "6.24.1",
"babel-plugin-syntax-exponentiation-operator": "6.13.0",
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-export-extensions": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz",
"integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=",
"dev": true,
"requires": {
"babel-plugin-syntax-export-extensions": "6.13.0",
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-flow-strip-types": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz",
@ -984,6 +1197,16 @@
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-function-bind": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz",
"integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=",
"dev": true,
"requires": {
"babel-plugin-syntax-function-bind": "6.13.0",
"babel-runtime": "6.26.0"
}
},
"babel-plugin-transform-object-assign": {
"version": "6.22.0",
"resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz",
@ -1126,6 +1349,53 @@
"babel-preset-flow": "6.23.0"
}
},
"babel-preset-stage-0": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz",
"integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=",
"dev": true,
"requires": {
"babel-plugin-transform-do-expressions": "6.22.0",
"babel-plugin-transform-function-bind": "6.22.0",
"babel-preset-stage-1": "6.24.1"
}
},
"babel-preset-stage-1": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz",
"integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=",
"dev": true,
"requires": {
"babel-plugin-transform-class-constructor-call": "6.24.1",
"babel-plugin-transform-export-extensions": "6.22.0",
"babel-preset-stage-2": "6.24.1"
}
},
"babel-preset-stage-2": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz",
"integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=",
"dev": true,
"requires": {
"babel-plugin-syntax-dynamic-import": "6.18.0",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-decorators": "6.24.1",
"babel-preset-stage-3": "6.24.1"
}
},
"babel-preset-stage-3": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz",
"integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=",
"dev": true,
"requires": {
"babel-plugin-syntax-trailing-function-commas": "6.22.0",
"babel-plugin-transform-async-generator-functions": "6.24.1",
"babel-plugin-transform-async-to-generator": "6.24.1",
"babel-plugin-transform-exponentiation-operator": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0"
}
},
"babel-register": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
@ -3850,8 +4120,8 @@
"dev": true,
"optional": true,
"requires": {
"co": "4.6.0",
"json-stable-stringify": "1.0.1"
"co": "^4.6.0",
"json-stable-stringify": "^1.0.1"
}
},
"ansi-regex": {
@ -3924,7 +4194,7 @@
"bundled": true,
"dev": true,
"requires": {
"inherits": "2.0.3"
"inherits": "~2.0.0"
}
},
"boom": {
@ -3932,7 +4202,7 @@
"bundled": true,
"dev": true,
"requires": {
"hoek": "2.16.3"
"hoek": "2.x.x"
}
},
"brace-expansion": {
@ -3994,7 +4264,7 @@
"bundled": true,
"dev": true,
"requires": {
"boom": "2.10.1"
"boom": "2.x.x"
}
},
"dashdash": {
@ -4052,7 +4322,7 @@
"dev": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
"jsbn": "~0.1.0"
}
},
"extend": {
@ -4132,7 +4402,7 @@
"dev": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
"assert-plus": "^1.0.0"
},
"dependencies": {
"assert-plus": {
@ -4261,7 +4531,7 @@
"dev": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
"jsbn": "~0.1.0"
}
},
"jsbn": {
@ -4282,7 +4552,7 @@
"dev": true,
"optional": true,
"requires": {
"jsonify": "0.0.0"
"jsonify": "~0.0.0"
}
},
"json-stringify-safe": {
@ -8579,6 +8849,14 @@
"prop-types": "15.6.0"
}
},
"react-dropdown": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/react-dropdown/-/react-dropdown-1.5.0.tgz",
"integrity": "sha512-rRv3a7NiP++yC1rzdjzkviC5ujq759i4SRa0M3C0Cr7loYT4Z3+JhSPekv1/04JiZNXX46cV3/g6A9kS7rkI4Q==",
"requires": {
"classnames": "2.2.5"
}
},
"react-redux": {
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz",

View File

@ -21,6 +21,7 @@
"react": "^16.2.0",
"react-clipboard.js": "^1.1.3",
"react-dom": "^16.2.0",
"react-dropdown": "^1.5.0",
"react-redux": "^5.0.6",
"react-spinner": "^0.2.7",
"react-tooltip": "^3.4.0",
@ -38,6 +39,7 @@
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babelify": "^8.0.0",
"browser-sync": "^2.23.6",
"browserify": "^16.1.0",

View File

@ -1,4 +1,4 @@
<svg fill="#FFFFFF" fill-opacity="0.65" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<svg fill="#FFFFFF" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>

Before

Width:  |  Height:  |  Size: 372 B

After

Width:  |  Height:  |  Size: 352 B

View File

@ -1,4 +1,4 @@
<svg fill="#FFFFFF" fill-opacity="0.65" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z"/>
</svg>

Before

Width:  |  Height:  |  Size: 352 B

After

Width:  |  Height:  |  Size: 332 B

View File

@ -0,0 +1,4 @@
<svg fill="#000000" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path fill="none" d="M0 0h20v20H0V0z"/>
<path d="M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z"/>
</svg>

After

Width:  |  Height:  |  Size: 801 B

View File

@ -0,0 +1,3 @@
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z"/>
</svg>

After

Width:  |  Height:  |  Size: 757 B

View File

@ -232,6 +232,16 @@
}
}
&.settings {
&.off {
background-image: url('/resources/images/icon_settings_white.svg');
}
&.on {
background-image: url('/resources/images/icon_settings_black.svg');
}
}
&.screen {
&.on {
background-image: url('/resources/images/no-share-screen-black.svg');

View File

@ -0,0 +1,149 @@
[data-component='Settings'] {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 19999;
background-color: rgba(000, 000, 000, 0.5);
> .dialog {
position: absolute;
height: 50vmin;
width: 60vmin;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 4px;
box-shadow: 0px 3px 12px 2px rgba(#111, 0.4);
padding: 1vmin;
> .header {
> span {
font-size: 2vmin;
font-weight: 400;
}
}
> .settings {
height: 100%;
width: 100%;
.Dropdown-root {
position: relative;
}
.Dropdown-control {
position: relative;
overflow: hidden;
background-color: white;
border: 1px solid #ccc;
border-radius: 2px;
box-sizing: border-box;
color: #333;
cursor: default;
outline: none;
padding: 8px 52px 8px 10px;
transition: all 200ms ease;
}
.Dropdown-control:hover {
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
}
.Dropdown-arrow {
border-color: #999 transparent transparent;
border-style: solid;
border-width: 5px 5px 0;
content: ' ';
display: block;
height: 0;
margin-top: -ceil(2.5);
position: absolute;
right: 10px;
top: 14px;
width: 0
}
.is-open .Dropdown-arrow {
border-color: transparent transparent #999;
border-width: 0 5px 5px;
}
.Dropdown-menu {
background-color: white;
border: 1px solid #ccc;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
box-sizing: border-box;
margin-top: -1px;
max-height: 200px;
overflow-y: auto;
position: absolute;
top: 100%;
width: 100%;
z-index: 1000;
-webkit-overflow-scrolling: touch;
}
.Dropdown-menu .Dropdown-group > .Dropdown-title {
padding: 8px 10px;
color: rgba(51, 51, 51, 1.2);
font-weight: bold;
text-transform: capitalize;
}
.Dropdown-option {
box-sizing: border-box;
color: rgba(51, 51, 51, 0.8);
cursor: pointer;
display: block;
padding: 8px 10px;
}
.Dropdown-option:last-child {
border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px;
}
.Dropdown-option:hover {
background-color: #f2f9fc;
color: #333;
}
.Dropdown-option.is-selected {
background-color: #f2f9fc;
color: #333;
}
.Dropdown-noresults {
box-sizing: border-box;
color: #ccc;
cursor: default;
display: block;
padding: 8px 10px;
}
}
> .footer {
position: absolute;
bottom: 0;
right: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
> .button {
flex: 0 0 auto;
margin: 1vmin;
background-color: rgba(#000, 0.8);
color: #fff;
cursor: pointer;
border-radius: 4px;
padding: 0.5vmin;
}
}
}
}

View File

@ -42,6 +42,7 @@ body {
@import './components/PeerView';
@import './components/Notifications';
@import './components/Chat';
@import './components/Settings';
}
// Hack to detect in JS the current media query