diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index f6f4764..aea8f94 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -65,10 +65,6 @@ const VIDEO_ENCODINGS = let store; -const AudioContext = window.AudioContext // Default - || window.webkitAudioContext // Safari and old versions of Chrome - || false; - export default class RoomClient { /** @@ -119,11 +115,6 @@ export default class RoomClient // Alert sound this._soundAlert = new Audio('/sounds/notify.mp3'); - if (AudioContext) - { - this._audioContext = new AudioContext(); - } - // Socket.io peer connection this._signalingSocket = null; @@ -661,9 +652,15 @@ export default class RoomClient { logger.debug('muteMic()'); + this._micProducer.pause(); + try { - this._micProducer.pause(); + await this.sendRequest( + 'pauseProducer', { producerId: this._micProducer.id }); + + store.dispatch( + stateActions.setProducerPaused(this._micProducer.id)); } catch (error) { @@ -681,24 +678,32 @@ export default class RoomClient { logger.debug('unmuteMic()'); - try + if (!this._micProducer) { - if (this._micProducer) - this._micProducer.resume(); - else if (this._room.canSend('audio')) - await this.enableMic(); - else - throw new Error('cannot send audio'); + this.enableMic(); } - catch (error) + else { - logger.error('unmuteMic() | failed: %o', error); + this._micProducer.resume(); - store.dispatch(requestActions.notify( - { - type : 'error', - text : 'An error occured while accessing your microphone.' - })); + try + { + await this.sendRequest( + 'resumeProducer', { producerId: this._micProducer.id }); + + store.dispatch( + stateActions.setProducerResumed(this._micProducer.id)); + } + catch (error) + { + logger.error('unmuteMic() | failed: %o', error); + + store.dispatch(requestActions.notify( + { + type : 'error', + text : 'An error occured while accessing your microphone.' + })); + } } } @@ -1056,31 +1061,13 @@ export default class RoomClient stateActions.setMyRaiseHandStateInProgress(false)); } - async resumeAudio() - { - logger.debug('resumeAudio()'); - try - { - await this._audioContext.resume(); - - store.dispatch( - stateActions.setAudioSuspended({ audioSuspended: false })); - - } - catch (error) - { - store.dispatch( - stateActions.setAudioSuspended({ audioSuspended: true })); - logger.error('resumeAudioJoin() failed: %o', error); - } - } - - async join() + async join({ joinVideo }) { this._signalingSocket = io(this._signalingUrl); this._spotlights = new Spotlights(this._maxSpotlights, this._signalingSocket); + store.dispatch(stateActions.toggleJoined()); store.dispatch(stateActions.setRoomState('connecting')); this._signalingSocket.on('connect', () => @@ -1258,7 +1245,7 @@ export default class RoomClient { case 'roomReady': { - await this._joinRoom(); + await this._joinRoom({ joinVideo }); break; } @@ -1514,7 +1501,7 @@ export default class RoomClient }); } - async _joinRoom() + async _joinRoom({ joinVideo }) { logger.debug('_joinRoom()'); @@ -1664,10 +1651,10 @@ export default class RoomClient if (this._produce) { if (this._mediasoupDevice.canProduce('audio')) - await this.enableMic(); + this.enableMic(); - if (this._mediasoupDevice.canProduce('video')) - await this.enableWebcam(); + if (joinVideo && this._mediasoupDevice.canProduce('video')) + this.enableWebcam(); } store.dispatch(stateActions.setRoomState('connected')); @@ -1875,15 +1862,6 @@ export default class RoomClient store.dispatch(stateActions.setPeerVolume(this._peerId, volume)); } }); - - if (this._audioContext) - { - // We need to provoke user interaction to get permission from browser to start audio - if (this._audioContext.state === 'suspended') - { - this.resumeAudio(); - } - } } catch (error) { diff --git a/app/src/actions/stateActions.js b/app/src/actions/stateActions.js index 52ba00d..fda3ceb 100644 --- a/app/src/actions/stateActions.js +++ b/app/src/actions/stateActions.js @@ -43,14 +43,6 @@ export const setRoomLockedOut = () => }; }; -export const setAudioSuspended = ({ audioSuspended }) => -{ - return { - type : 'SET_AUDIO_SUSPENDED', - payload : { audioSuspended } - }; -}; - export const setSettingsOpen = ({ settingsOpen }) => ({ type : 'SET_SETTINGS_OPEN', @@ -568,6 +560,11 @@ export const loggedIn = () => type : 'LOGGED_IN' }); +export const toggleJoined = () => + ({ + type : 'TOGGLE_JOINED' + }); + export const setSelectedPeer = (selectedPeerId) => ({ type : 'SET_SELECTED_PEER', diff --git a/app/src/components/Controls/Sidebar.js b/app/src/components/Controls/Sidebar.js index 79024ea..9ef0583 100644 --- a/app/src/components/Controls/Sidebar.js +++ b/app/src/components/Controls/Sidebar.js @@ -78,11 +78,16 @@ const Sidebar = (props) => let micTip; - if (!me.canSendMic || !micProducer) + if (!me.canSendMic) { micState = 'unsupported'; micTip = 'Audio unsupported'; } + else if (!micProducer) + { + micState = 'off'; + micTip = 'Activate audio'; + } else if (!micProducer.locallyPaused && !micProducer.remotelyPaused) { micState = 'on'; @@ -90,7 +95,7 @@ const Sidebar = (props) => } else { - micState = 'off'; + micState = 'muted'; micTip = 'Unmute audio'; } @@ -152,9 +157,12 @@ const Sidebar = (props) => size={smallScreen ? 'large' : 'medium'} onClick={() => { - micState === 'on' ? - roomClient.disableMic() : + if (micState === 'off') roomClient.enableMic(); + else if (micState === 'on') + roomClient.muteMic(); + else + roomClient.unmuteMic(); }} > { micState === 'on' ? diff --git a/app/src/components/JoinDialog.js b/app/src/components/JoinDialog.js new file mode 100644 index 0000000..5a99b3f --- /dev/null +++ b/app/src/components/JoinDialog.js @@ -0,0 +1,90 @@ +import React from 'react'; +import { withStyles } from '@material-ui/core/styles'; +import { withRoomContext } from '../RoomContext'; +import PropTypes from 'prop-types'; +import Dialog from '@material-ui/core/Dialog'; +import Typography from '@material-ui/core/Typography'; +import DialogActions from '@material-ui/core/DialogActions'; +import Button from '@material-ui/core/Button'; + +const styles = (theme) => + ({ + root : + { + }, + dialogPaper : + { + width : '20vw', + padding : theme.spacing.unit * 2, + [theme.breakpoints.down('lg')] : + { + width : '30vw' + }, + [theme.breakpoints.down('md')] : + { + width : '40vw' + }, + [theme.breakpoints.down('sm')] : + { + width : '60vw' + }, + [theme.breakpoints.down('xs')] : + { + width : '80vw' + } + }, + logo : + { + display : 'block' + } + }); + +const JoinDialog = ({ + roomClient, + classes +}) => +{ + return ( + + { window.config.logo ? + Logo + :null + } + You are about to join a meeting, how would you like to join? + + + + + + ); +}; + +JoinDialog.propTypes = +{ + roomClient : PropTypes.any.isRequired, + classes : PropTypes.object.isRequired +}; + +export default withRoomContext(withStyles(styles)(JoinDialog)); \ No newline at end of file diff --git a/app/src/components/Room.js b/app/src/components/Room.js index 8a503b7..afcc75d 100644 --- a/app/src/components/Room.js +++ b/app/src/components/Room.js @@ -15,7 +15,6 @@ import SwipeableDrawer from '@material-ui/core/SwipeableDrawer'; import Hidden from '@material-ui/core/Hidden'; import Paper from '@material-ui/core/Paper'; import Typography from '@material-ui/core/Typography'; -import Button from '@material-ui/core/Button'; import IconButton from '@material-ui/core/IconButton'; import MenuIcon from '@material-ui/icons/Menu'; import Avatar from '@material-ui/core/Avatar'; @@ -33,6 +32,7 @@ import FullScreenIcon from '@material-ui/icons/Fullscreen'; import FullScreenExitIcon from '@material-ui/icons/FullscreenExit'; import SettingsIcon from '@material-ui/icons/Settings'; import Settings from './Settings/Settings'; +import JoinDialog from './JoinDialog'; const TIMEOUT = 10 * 1000; @@ -176,10 +176,6 @@ class Room extends React.PureComponent componentDidMount() { - const { roomClient } = this.props; - - roomClient.join(); - if (this.fullscreen.fullscreenEnabled) { this.fullscreen.addEventListener('fullscreenchange', this.handleFullscreenChange); @@ -242,29 +238,7 @@ class Room extends React.PureComponent democratic : Democratic }[room.mode]; - if (room.audioSuspended) - { - return ( -
- - - This webpage required sound and video to play, please click to allow. - - - -
- ); - } - else if (room.lockedOut) + if (room.lockedOut) { return (
@@ -274,6 +248,14 @@ class Room extends React.PureComponent
); } + else if (!room.joined) + { + return ( +
+ +
+ ); + } else { return ( diff --git a/app/src/reducers/room.js b/app/src/reducers/room.js index 446b350..e1444c3 100644 --- a/app/src/reducers/room.js +++ b/app/src/reducers/room.js @@ -4,7 +4,6 @@ const initialState = state : 'new', // new/connecting/connected/disconnected/closed, locked : false, lockedOut : false, - audioSuspended : false, activeSpeakerId : null, torrentSupport : false, showSettings : false, @@ -14,7 +13,8 @@ const initialState = mode : 'democratic', selectedPeerId : null, spotlights : [], - settingsOpen : false + settingsOpen : false, + joined : false }; const room = (state = initialState, action) => @@ -53,13 +53,6 @@ const room = (state = initialState, action) => return { ...state, lockedOut: true }; } - case 'SET_AUDIO_SUSPENDED': - { - const { audioSuspended } = action.payload; - - return { ...state, audioSuspended }; - } - case 'SET_SETTINGS_OPEN': { const { settingsOpen } = action.payload; @@ -88,6 +81,13 @@ const room = (state = initialState, action) => return { ...state, showSettings }; } + case 'TOGGLE_JOINED': + { + const joined = !state.joined; + + return { ...state, joined }; + } + case 'TOGGLE_FULLSCREEN_CONSUMER': { const { consumerId } = action.payload;