276 lines
6.0 KiB
JavaScript
276 lines
6.0 KiB
JavaScript
import React from 'react';
|
|
import { connect } from 'react-redux';
|
|
import ReactTooltip from 'react-tooltip';
|
|
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
|
|
{
|
|
render()
|
|
{
|
|
const {
|
|
room,
|
|
me,
|
|
amActiveSpeaker,
|
|
screenProducer,
|
|
onRoomLinkCopy,
|
|
onToggleSettings,
|
|
onLogin,
|
|
onShareScreen,
|
|
onUnShareScreen,
|
|
onNeedExtension,
|
|
onToggleHand,
|
|
onLeaveMeeting
|
|
} = this.props;
|
|
|
|
let screenState;
|
|
let screenTip;
|
|
|
|
if (me.needExtension)
|
|
{
|
|
screenState = 'need-extension';
|
|
screenTip = 'Install screen sharing extension';
|
|
}
|
|
else if (!me.canShareScreen)
|
|
{
|
|
screenState = 'unsupported';
|
|
screenTip = 'Screen sharing not supported';
|
|
}
|
|
else if (screenProducer)
|
|
{
|
|
screenState = 'on';
|
|
screenTip = 'Stop screen sharing';
|
|
}
|
|
else
|
|
{
|
|
screenState = 'off';
|
|
screenTip = 'Start screen sharing';
|
|
}
|
|
|
|
return (
|
|
<Appear duration={300}>
|
|
<div data-component='Room'>
|
|
<Notifications />
|
|
<ChatWidget />
|
|
|
|
<div className='state' data-tip='Server status'>
|
|
<div className={classnames('icon', room.state)} />
|
|
<p className={classnames('text', room.state)}>{room.state}</p>
|
|
</div>
|
|
|
|
<div className='room-link-wrapper'>
|
|
<div className='room-link'>
|
|
<ClipboardButton
|
|
component='a'
|
|
className='link'
|
|
button-href={room.url}
|
|
button-target='_blank'
|
|
data-tip='Click to copy room link'
|
|
data-clipboard-text={room.url}
|
|
onSuccess={onRoomLinkCopy}
|
|
onClick={(event) =>
|
|
{
|
|
// If this is a 'Open in new window/tab' don't prevent
|
|
// click default action.
|
|
if (
|
|
event.ctrlKey || event.shiftKey || event.metaKey ||
|
|
// Middle click (IE > 9 and everyone else).
|
|
(event.button && event.button === 1)
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
}}
|
|
>
|
|
invitation link
|
|
</ClipboardButton>
|
|
</div>
|
|
</div>
|
|
|
|
<Peers />
|
|
|
|
<div
|
|
className={classnames('me-container', {
|
|
'active-speaker' : amActiveSpeaker
|
|
})}
|
|
>
|
|
<Me />
|
|
</div>
|
|
|
|
<div className='sidebar'>
|
|
<div
|
|
className={classnames('button', 'screen', screenState)}
|
|
data-tip={screenTip}
|
|
data-type='dark'
|
|
onClick={() =>
|
|
{
|
|
switch (screenState)
|
|
{
|
|
case 'on':
|
|
{
|
|
onUnShareScreen();
|
|
break;
|
|
}
|
|
case 'off':
|
|
{
|
|
onShareScreen();
|
|
break;
|
|
}
|
|
case 'need-extension':
|
|
{
|
|
onNeedExtension();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}}
|
|
/>
|
|
|
|
<div
|
|
className={classnames('button', 'settings', {
|
|
on : room.showSettings,
|
|
off : !room.showSettings
|
|
})}
|
|
data-tip='Open settings'
|
|
data-type='dark'
|
|
onClick={() => onToggleSettings()}
|
|
/>
|
|
|
|
<div
|
|
className={classnames('button', 'login', 'off', {
|
|
disabled : me.loginInProgress
|
|
})}
|
|
data-tip='Login'
|
|
data-type='dark'
|
|
onClick={() => onLogin()}
|
|
/>
|
|
|
|
<div
|
|
className={classnames('button', 'raise-hand', {
|
|
on : me.raiseHand,
|
|
disabled : me.raiseHandInProgress
|
|
})}
|
|
data-tip='Raise hand'
|
|
data-type='dark'
|
|
onClick={() => onToggleHand(!me.raiseHand)}
|
|
/>
|
|
|
|
<div
|
|
className={classnames('button', 'leave-meeting')}
|
|
data-tip='Leave meeting'
|
|
data-type='dark'
|
|
onClick={() => onLeaveMeeting()}
|
|
/>
|
|
</div>
|
|
|
|
<Settings
|
|
onToggleSettings={onToggleSettings}
|
|
/>
|
|
|
|
<ReactTooltip
|
|
effect='solid'
|
|
delayShow={100}
|
|
delayHide={100}
|
|
/>
|
|
</div>
|
|
</Appear>
|
|
);
|
|
}
|
|
}
|
|
|
|
Room.propTypes =
|
|
{
|
|
room : appPropTypes.Room.isRequired,
|
|
me : appPropTypes.Me.isRequired,
|
|
amActiveSpeaker : PropTypes.bool.isRequired,
|
|
screenProducer : appPropTypes.Producer,
|
|
onRoomLinkCopy : 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,
|
|
onLogin : PropTypes.func.isRequired
|
|
};
|
|
|
|
const mapStateToProps = (state) =>
|
|
{
|
|
const producersArray = Object.values(state.producers);
|
|
const screenProducer =
|
|
producersArray.find((producer) => producer.source === 'screen');
|
|
|
|
return {
|
|
room : state.room,
|
|
me : state.me,
|
|
amActiveSpeaker : state.me.name === state.room.activeSpeakerName,
|
|
screenProducer : screenProducer
|
|
};
|
|
};
|
|
|
|
const mapDispatchToProps = (dispatch) =>
|
|
{
|
|
return {
|
|
onRoomLinkCopy : () =>
|
|
{
|
|
dispatch(requestActions.notify(
|
|
{
|
|
text : 'Room link copied to the clipboard'
|
|
}));
|
|
},
|
|
onToggleSettings : () =>
|
|
{
|
|
dispatch(stateActions.toggleSettings());
|
|
},
|
|
onToggleHand : (enable) =>
|
|
{
|
|
if (enable)
|
|
dispatch(requestActions.raiseHand());
|
|
else
|
|
dispatch(requestActions.lowerHand());
|
|
},
|
|
onLeaveMeeting : () =>
|
|
{
|
|
dispatch(requestActions.leaveRoom());
|
|
},
|
|
onShareScreen : () =>
|
|
{
|
|
dispatch(requestActions.enableScreenSharing());
|
|
},
|
|
onUnShareScreen : () =>
|
|
{
|
|
dispatch(requestActions.disableScreenSharing());
|
|
},
|
|
onNeedExtension : () =>
|
|
{
|
|
dispatch(requestActions.installExtension());
|
|
},
|
|
onLogin : () =>
|
|
{
|
|
dispatch(requestActions.userLogin());
|
|
}
|
|
};
|
|
};
|
|
|
|
const RoomContainer = connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
)(Room);
|
|
|
|
export default RoomContainer;
|