From e5ddaa458aebc128ee26d3809bd20b715176c168 Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Wed, 23 Oct 2019 11:47:41 +0200 Subject: [PATCH] lock Dialog --- app/src/RoomClient.js | 109 +++++++++- app/src/actions/stateActions.js | 30 +++ .../LockDialog}/ListLobbyPeer.js | 42 ++-- .../AccessControl/LockDialog/LockDialog.js | 191 ++++++++++++++++++ .../ParticipantList/ParticipantList.js | 26 +-- app/src/components/Room.js | 38 ++-- app/src/index.js | 3 +- app/src/reducers/room.js | 24 +++ server/lib/Room.js | 48 ++++- 9 files changed, 445 insertions(+), 66 deletions(-) rename app/src/components/{MeetingDrawer/ParticipantList => AccessControl/LockDialog}/ListLobbyPeer.js (76%) create mode 100644 app/src/components/AccessControl/LockDialog/LockDialog.js diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index 243ce57..7c586ef 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -77,7 +77,7 @@ export default class RoomClient } constructor( - { roomId, peerId, device, useSimulcast, produce, consume, forceTcp }) + { roomId, peerId, accessCode, device, useSimulcast, produce, consume, forceTcp }) { logger.debug( 'constructor() [roomId: "%s", peerId: "%s", device: "%s", useSimulcast: "%s", produce: "%s", consume: "%s", forceTcp: "%s"]', @@ -112,6 +112,9 @@ export default class RoomClient // My peer name. this._peerId = peerId; + // Access code + this._accessCode = accessCode; + // Alert sound this._soundAlert = new Audio('/sounds/notify.mp3'); @@ -609,7 +612,8 @@ export default class RoomClient fileHistory, lastN, locked, - lobbyPeers + lobbyPeers, + accessCode } = await this.sendRequest('serverHistory'); if (chatHistory.length > 0) @@ -654,6 +658,13 @@ export default class RoomClient stateActions.setLobbyPeerDisplayName(peer.displayName)); }); } + + if (accessCode != null) + { + logger.debug('Got accessCode'); + + store.dispatch(stateActions.setAccessCode(accessCode)) + } } catch (error) { @@ -1385,6 +1396,46 @@ export default class RoomClient break; } + case 'setAccessCode': + { + const { accessCode } = notification.data; + + store.dispatch( + stateActions.setAccessCode(accessCode)); + + store.dispatch(requestActions.notify( + { + text : 'Access code for room updated' + })); + + break; + } + + case 'setJoinByAccessCode': + { + const { joinByAccessCode } = notification.data; + + store.dispatch( + stateActions.setJoinByAccessCode(joinByAccessCode)); + + if (joinByAccessCode) + { + store.dispatch(requestActions.notify( + { + text : 'Access code for room is now activated' + })); + } + else + { + store.dispatch(requestActions.notify( + { + text : 'Access code for room is now deactivated' + })); + } + + break; + } + case 'activeSpeaker': { const { peerId } = notification.data; @@ -1843,6 +1894,60 @@ export default class RoomClient } } + async setAccessCode(code) + { + logger.debug('setAccessCode()'); + + try + { + await this.sendRequest('setAccessCode', { accessCode: code }); + + store.dispatch( + stateActions.setAccessCode(code)); + + store.dispatch(requestActions.notify( + { + text : 'Access code saved.' + })); + } + catch (error) + { + logger.error('setAccessCode() | failed: %o', error); + store.dispatch(requestActions.notify( + { + type : 'error', + text : 'Unable to set access code.' + })); + } + } + + async setJoinByAccessCode(value) + { + logger.debug('setJoinByAccessCode()'); + + try + { + await this.sendRequest('setJoinByAccessCode', { joinByAccessCode: value }); + + store.dispatch( + stateActions.setJoinByAccessCode(value)); + + store.dispatch(requestActions.notify( + { + text : `You switched Join by access-code to ${value}` + })); + } + catch (error) + { + logger.error('setAccessCode() | failed: %o', error); + store.dispatch(requestActions.notify( + { + type : 'error', + text : 'Unable to set join by access code.' + })); + } + } + async enableMic() { if (this._micProducer) diff --git a/app/src/actions/stateActions.js b/app/src/actions/stateActions.js index 24f6870..1e72125 100644 --- a/app/src/actions/stateActions.js +++ b/app/src/actions/stateActions.js @@ -43,12 +43,35 @@ export const setRoomLockedOut = () => }; }; +export const setAccessCode = (accessCode) => +{ + return { + type : 'SET_ACCESS_CODE', + payload : { accessCode } + }; +}; + +export const setJoinByAccessCode = (joinByAccessCode) => +{ + return { + type : 'SET_JOIN_BY_ACCESS_CODE', + payload : { joinByAccessCode } + }; +}; + + export const setSettingsOpen = ({ settingsOpen }) => ({ type : 'SET_SETTINGS_OPEN', payload : { settingsOpen } }); +export const setLockDialogOpen = ({ lockDialogOpen }) => + ({ + type : 'SET_LOCK_DIALOG_OPEN', + payload : { lockDialogOpen } + }); + export const setMe = ({ peerId, device, loginEnabled }) => { return { @@ -178,6 +201,13 @@ export const toggleSettings = () => }; }; +export const toggleLockDialog = () => +{ + return { + type : 'TOGGLE_LOCK_DIALOG' + }; +}; + export const toggleToolArea = () => { return { diff --git a/app/src/components/MeetingDrawer/ParticipantList/ListLobbyPeer.js b/app/src/components/AccessControl/LockDialog/ListLobbyPeer.js similarity index 76% rename from app/src/components/MeetingDrawer/ParticipantList/ListLobbyPeer.js rename to app/src/components/AccessControl/LockDialog/ListLobbyPeer.js index 85b0136..665561d 100644 --- a/app/src/components/MeetingDrawer/ParticipantList/ListLobbyPeer.js +++ b/app/src/components/AccessControl/LockDialog/ListLobbyPeer.js @@ -4,6 +4,11 @@ import { withStyles } from '@material-ui/core/styles'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { withRoomContext } from '../../../RoomContext'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemAvatar from '@material-ui/core/ListItemAvatar'; +import Avatar from '@material-ui/core/Avatar'; import EmptyAvatar from '../../../images/avatar-empty.jpeg'; import PromoteIcon from '@material-ui/icons/OpenInBrowser'; @@ -78,27 +83,30 @@ const ListLobbyPeer = (props) => const picture = peer.picture || EmptyAvatar; return ( -
- Peer avatar - -
- {peer.displayName} -
-
-
+ + + + + + { e.stopPropagation(); roomClient.promoteLobbyPeer(peer.id); }} - > - -
-
-
+ > + + + ); }; diff --git a/app/src/components/AccessControl/LockDialog/LockDialog.js b/app/src/components/AccessControl/LockDialog/LockDialog.js new file mode 100644 index 0000000..021cf20 --- /dev/null +++ b/app/src/components/AccessControl/LockDialog/LockDialog.js @@ -0,0 +1,191 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { + lobbyPeersKeySelector +} from '../../Selectors'; +import * as appPropTypes from '../../appPropTypes'; +import { withStyles } from '@material-ui/core/styles'; +import { withRoomContext } from '../../../RoomContext'; +import * as stateActions from '../../../actions/stateActions'; +import PropTypes from 'prop-types'; +import Dialog from '@material-ui/core/Dialog'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import DialogActions from '@material-ui/core/DialogActions'; +import Button from '@material-ui/core/Button'; +import FormLabel from '@material-ui/core/FormLabel'; +import FormControl from '@material-ui/core/FormControl'; +import FormGroup from '@material-ui/core/FormGroup'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; +import Checkbox from '@material-ui/core/Checkbox'; +import InputLabel from '@material-ui/core/InputLabel'; +import OutlinedInput from '@material-ui/core/OutlinedInput'; +import Switch from '@material-ui/core/Switch'; +import List from '@material-ui/core/List'; +import ListSubheader from '@material-ui/core/ListSubheader'; +import ListLobbyPeer from './ListLobbyPeer'; + + +const styles = (theme) => + ({ + root : + { + }, + dialogPaper : + { + width : '30vw', + [theme.breakpoints.down('lg')] : + { + width : '40vw' + }, + [theme.breakpoints.down('md')] : + { + width : '50vw' + }, + [theme.breakpoints.down('sm')] : + { + width : '70vw' + }, + [theme.breakpoints.down('xs')] : + { + width : '90vw' + } + }, + lock : + { + padding : theme.spacing.unit * 2 + } + }); + +const LockDialog = ({ + roomClient, + room, + handleCloseLockDialog, + handleAccessCode, + lobbyPeers, + classes +}) => +{ + return ( + handleCloseLockDialog({ lockDialogOpen: false })} + classes={{ + paper : classes.dialogPaper + }} + > + Room access control +
+ + Room lock + + + { + if (room.locked) + { + roomClient.unlockRoom(); + } + else + { + roomClient.lockRoom(); + } + }} + />} + label='Lock' + /> + {/* TODO: access code + roomClient.setJoinByAccessCode(event.target.checked) + } + />} + label='Join by Access code' + /> + + handleAccessCode(event.target.value)} + > + + + */} + + + + { lobbyPeers.length > 0 ? + + Participants in Lobby + + }> + { + lobbyPeers.map((peerId) => { return (); }) + } + + : null + } +
+ + + + +
+ ); +}; + +LockDialog.propTypes = +{ + roomClient : PropTypes.any.isRequired, + room : appPropTypes.Room.isRequired, + handleCloseLockDialog : PropTypes.func.isRequired, + handleAccessCode : PropTypes.func.isRequired, + lobbyPeers : PropTypes.array, + classes : PropTypes.object.isRequired +}; + +const mapStateToProps = (state) => +{ + return { + room : state.room, + lobbyPeers : lobbyPeersKeySelector(state) + + }; +}; + +const mapDispatchToProps = { + handleCloseLockDialog : stateActions.setLockDialogOpen, + handleAccessCode : stateActions.setAccessCode +}; + +export default withRoomContext(connect( + mapStateToProps, + mapDispatchToProps, + null, + { + areStatesEqual : (next, prev) => + { + return ( + prev.room.locked === next.room.locked && + prev.room.joinByAccessCode === next.room.joinByAccessCode && + prev.room.accessCode === next.room.accessCode && + prev.room.code === next.room.code && + prev.room.lockDialogOpen === next.room.lockDialogOpen && + prev.room.codeHidden === next.room.codeHidden && + prev.lobbyPeers === next.lobbyPeers + ); + } + } +)(withStyles(styles)(LockDialog))); \ No newline at end of file diff --git a/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js b/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js index 85a71cb..484c7ba 100644 --- a/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js +++ b/app/src/components/MeetingDrawer/ParticipantList/ParticipantList.js @@ -2,15 +2,13 @@ import React from 'react'; import { connect } from 'react-redux'; import { passivePeersSelector, - spotlightPeersSelector, - lobbyPeersKeySelector + spotlightPeersSelector } from '../../Selectors'; import classNames from 'classnames'; import { withStyles } from '@material-ui/core/styles'; import { withRoomContext } from '../../../RoomContext'; import PropTypes from 'prop-types'; import ListPeer from './ListPeer'; -import ListLobbyPeer from './ListLobbyPeer'; import ListMe from './ListMe'; import Volume from '../../Containers/Volume'; @@ -80,7 +78,6 @@ class ParticipantList extends React.PureComponent passivePeers, selectedPeerId, spotlightPeers, - lobbyPeers, classes } = this.props; @@ -90,20 +87,6 @@ class ParticipantList extends React.PureComponent
  • Me:
  • - { lobbyPeers.length > 0 ? -
      -
    • Participants in Lobby:
    • - { lobbyPeers.map((peerId) => ( -
    • - -
    • - ))} -
    - :null - }
    • Participants in Spotlight:
    • { spotlightPeers.map((peer) => ( @@ -146,7 +129,6 @@ ParticipantList.propTypes = passivePeers : PropTypes.array, selectedPeerId : PropTypes.string, spotlightPeers : PropTypes.array, - lobbyPeers : PropTypes.array, classes : PropTypes.object.isRequired }; @@ -155,8 +137,7 @@ const mapStateToProps = (state) => return { passivePeers : passivePeersSelector(state), selectedPeerId : state.room.selectedPeerId, - spotlightPeers : spotlightPeersSelector(state), - lobbyPeers : lobbyPeersKeySelector(state) + spotlightPeers : spotlightPeersSelector(state) }; }; @@ -170,8 +151,7 @@ const ParticipantListContainer = withRoomContext(connect( return ( prev.peers === next.peers && prev.room.spotlights === next.room.spotlights && - prev.room.selectedPeerId === next.room.selectedPeerId && - prev.lobbyPeers === next.lobbyPeers + prev.room.selectedPeerId === next.room.selectedPeerId ); } } diff --git a/app/src/components/Room.js b/app/src/components/Room.js index 3ebebeb..c002a94 100644 --- a/app/src/components/Room.js +++ b/app/src/components/Room.js @@ -35,6 +35,7 @@ import LockOpenIcon from '@material-ui/icons/LockOpen'; import Button from '@material-ui/core/Button'; import Settings from './Settings/Settings'; import JoinDialog from './JoinDialog'; +import LockDialog from './AccessControl/LockDialog/LockDialog'; const TIMEOUT = 10 * 1000; @@ -264,6 +265,7 @@ class Room extends React.PureComponent loggedIn, loginEnabled, setSettingsOpen, + setLockDialogOpen, toolAreaOpen, toggleToolArea, unread, @@ -345,28 +347,6 @@ class Room extends React.PureComponent
      - - { - if (room.locked) - { - roomClient.unlockRoom(); - } - else - { - roomClient.lockRoom(); - } - }} - > - { room.locked ? - - : - - } - { this.fullscreen.fullscreenEnabled ? + setLockDialogOpen(!room.lockDialogOpen)} + > + { room.locked ? : } + { loginEnabled ? + +
      ); @@ -457,6 +446,7 @@ Room.propTypes = toolAreaOpen : PropTypes.bool.isRequired, setToolbarsVisible : PropTypes.func.isRequired, setSettingsOpen : PropTypes.func.isRequired, + setLockDialogOpen : PropTypes.func.isRequired, toggleToolArea : PropTypes.func.isRequired, unread : PropTypes.number.isRequired, classes : PropTypes.object.isRequired, @@ -485,6 +475,10 @@ const mapDispatchToProps = (dispatch) => { dispatch(stateActions.setSettingsOpen({ settingsOpen })); }, + setLockDialogOpen : (lockDialogOpen) => + { + dispatch(stateActions.setLockDialogOpen({ lockDialogOpen })); + }, toggleToolArea : () => { dispatch(stateActions.toggleToolArea()); diff --git a/app/src/index.js b/app/src/index.js index 8e30c9d..c85fa18 100644 --- a/app/src/index.js +++ b/app/src/index.js @@ -62,6 +62,7 @@ function run() window.history.pushState('', '', urlParser.toString()); } + const accessCode = parameters.get('code'); const produce = parameters.get('produce') !== 'false'; const consume = parameters.get('consume') !== 'false'; const useSimulcast = parameters.get('simulcast') === 'true'; @@ -84,7 +85,7 @@ function run() ); roomClient = new RoomClient( - { roomId, peerId, device, useSimulcast, produce, consume, forceTcp }); + { roomId, peerId, accessCode, device, useSimulcast, produce, consume, forceTcp }); global.CLIENT = roomClient; diff --git a/app/src/reducers/room.js b/app/src/reducers/room.js index e1444c3..20a6026 100644 --- a/app/src/reducers/room.js +++ b/app/src/reducers/room.js @@ -4,6 +4,8 @@ const initialState = state : 'new', // new/connecting/connected/disconnected/closed, locked : false, lockedOut : false, + accessCode : '', // access code to the room if locked and joinByAccessCode == true + joinByAccessCode : true, // if true: accessCode is a possibility to open the room activeSpeakerId : null, torrentSupport : false, showSettings : false, @@ -14,6 +16,7 @@ const initialState = selectedPeerId : null, spotlights : [], settingsOpen : false, + lockDialogOpen : false, joined : false }; @@ -53,6 +56,27 @@ const room = (state = initialState, action) => return { ...state, lockedOut: true }; } + case 'SET_ACCESS_CODE': + { + const { accessCode } = action.payload; + + return { ...state, accessCode }; + } + + case 'SET_JOIN_BY_ACCESS_CODE': + { + const { joinByAccessCode } = action.payload; + + return { ...state, joinByAccessCode }; + } + + case 'SET_LOCK_DIALOG_OPEN': + { + const { lockDialogOpen } = action.payload; + + return { ...state, lockDialogOpen }; + } + case 'SET_SETTINGS_OPEN': { const { settingsOpen } = action.payload; diff --git a/server/lib/Room.js b/server/lib/Room.js index ef9d941..f382880 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -55,6 +55,12 @@ class Room extends EventEmitter // Locked flag. this._locked = false; + // if true: accessCode is a possibility to open the room + this._joinByAccesCode = true; + + // access code to the room, applicable if ( _locked == true and _joinByAccessCode == true ) + this._accessCode = ''; + this._lobby = new Lobby(); this._lobby.on('promotePeer', (peer) => @@ -815,7 +821,8 @@ class Room extends EventEmitter fileHistory : this._fileHistory, lastN : this._lastN, locked : this._locked, - lobbyPeers : lobbyPeers + lobbyPeers : lobbyPeers, + accessCode : this._accessCode } ); @@ -852,6 +859,45 @@ class Room extends EventEmitter break; } + case 'setAccessCode': + { + const { accessCode } = request.data; + + this._accessCode = accessCode; + + // Spread to others + // if (request.public) { + this._notification(peer.socket, 'setAccessCode', { + peerId : peer.id, + accessCode : accessCode + }, true); + //} + + // Return no error + cb(); + + break; + } + + case 'setJoinByAccessCode': + { + const { joinByAccessCode } = request.data; + + this._joinByAccessCode = joinByAccessCode; + + // Spread to others + this._notification(peer.socket, 'setJoinByAccessCode', { + peerId : peer.id, + joinByAccessCode : joinByAccessCode + }, true); + + // Return no error + cb(); + + break; + } + + case 'promotePeer': { const { peerId } = request.data;