Started work on settings dialog. Possible to switch camera.

This commit is contained in:
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
+29 -23
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));
});
}
+3 -20
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())
};
};
+34 -12
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}
@@ -189,18 +206,19 @@ class Room extends React.Component
Room.propTypes =
{
room : appPropTypes.Room.isRequired,
me : appPropTypes.Me.isRequired,
amActiveSpeaker : PropTypes.bool.isRequired,
screenProducer : appPropTypes.Producer,
onRoomLinkCopy : PropTypes.func.isRequired,
onSetAudioMode : PropTypes.func.isRequired,
onRestartIce : PropTypes.func.isRequired,
onShareScreen : PropTypes.func.isRequired,
onUnShareScreen : PropTypes.func.isRequired,
onNeedExtension : PropTypes.func.isRequired,
onToggleHand : PropTypes.func.isRequired,
onLeaveMeeting : PropTypes.func.isRequired
room : appPropTypes.Room.isRequired,
me : appPropTypes.Me.isRequired,
amActiveSpeaker : PropTypes.bool.isRequired,
screenProducer : appPropTypes.Producer,
onRoomLinkCopy : PropTypes.func.isRequired,
onSetAudioMode : PropTypes.func.isRequired,
onRestartIce : PropTypes.func.isRequired,
onShareScreen : PropTypes.func.isRequired,
onUnShareScreen : PropTypes.func.isRequired,
onNeedExtension : PropTypes.func.isRequired,
onToggleSettings : PropTypes.func.isRequired,
onToggleHand : PropTypes.func.isRequired,
onLeaveMeeting : PropTypes.func.isRequired
};
const mapStateToProps = (state) =>
@@ -238,6 +256,10 @@ const mapDispatchToProps = (dispatch) =>
{
dispatch(requestActions.restartIce());
},
onToggleSettings : () =>
{
dispatch(stateActions.toggleSettings());
},
onToggleHand : (enable) =>
{
if (enable)
+89
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;
+8
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;
+9 -1
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;
}
+3 -2
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 }
};
};
+3 -1
View File
@@ -83,7 +83,9 @@ export default ({ dispatch, getState }) => (next) =>
case 'CHANGE_WEBCAM':
{
client.changeWebcam();
const { deviceId } = action.payload;
client.changeWebcam(deviceId);
break;
}
+15
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 {