Major cleanup

This commit is contained in:
Håvar Aambø Fosstveit
2018-12-12 22:28:33 +01:00
parent fa91d9b9e2
commit 60fb9c735e
32 changed files with 506 additions and 16543 deletions
+31 -27
View File
@@ -1,17 +1,28 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import * as stateActions from '../../redux/stateActions';
import * as requestActions from '../../redux/requestActions';
import { withRoomContext } from '../../RoomContext';
import MessageList from './MessageList';
class Chat extends Component
{
createNewMessage(text, sender, name, picture)
{
return {
type : 'message',
text,
time : Date.now(),
name,
sender,
picture
};
}
render()
{
const {
roomClient,
senderPlaceHolder,
onSendMessage,
disabledInput,
autofocus,
displayName,
@@ -23,7 +34,19 @@ class Chat extends Component
<MessageList />
<form
data-component='Sender'
onSubmit={(e) => { onSendMessage(e, displayName, picture); }}
onSubmit={(e) =>
{
e.preventDefault();
const userInput = e.target.message.value;
if (userInput)
{
const message = this.createNewMessage(userInput, 'response', displayName, picture);
roomClient.sendChatMessage(message);
}
e.target.message.value = '';
}}
>
<input
type='text'
@@ -47,8 +70,8 @@ class Chat extends Component
Chat.propTypes =
{
roomClient : PropTypes.any.isRequired,
senderPlaceHolder : PropTypes.string,
onSendMessage : PropTypes.func,
disabledInput : PropTypes.bool,
autofocus : PropTypes.bool,
displayName : PropTypes.string,
@@ -71,27 +94,8 @@ const mapStateToProps = (state) =>
};
};
const mapDispatchToProps = (dispatch) =>
{
return {
onSendMessage : (event, displayName, picture) =>
{
event.preventDefault();
const userInput = event.target.message.value;
if (userInput)
{
dispatch(stateActions.addUserMessage(userInput));
dispatch(requestActions.sendChatMessage(userInput, displayName, picture));
}
event.target.message.value = '';
}
};
};
const ChatContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Chat);
const ChatContainer = withRoomContext(connect(
mapStateToProps
)(Chat));
export default ChatContainer;
+36 -30
View File
@@ -30,41 +30,47 @@ class MessageList extends Component
return (
<div data-component='MessageList' id='messages'>
{ chatmessages.length > 0 ?
chatmessages.map((message, i) =>
{
const messageTime = new Date(message.time);
<Choose>
<When condition={chatmessages.length > 0}>
{
chatmessages.map((message, i) =>
{
const messageTime = new Date(message.time);
const picture = (message.sender === 'response' ?
message.picture : this.props.myPicture) || 'resources/images/avatar-empty.jpeg';
const picture = (message.sender === 'response' ?
message.picture : this.props.myPicture) || 'resources/images/avatar-empty.jpeg';
return (
<div className='message' key={i}>
<div className={message.sender}>
<img className='message-avatar' src={picture} />
return (
<div className='message' key={i}>
<div className={message.sender}>
<img className='message-avatar' src={picture} />
<div className='message-content'>
<div
className='message-text'
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html : marked.parse(
message.text,
{ sanitize: true, renderer: linkRenderer }
) }}
/>
<div className='message-content'>
<div
className='message-text'
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html : marked.parse(
message.text,
{ sanitize: true, renderer: linkRenderer }
) }}
/>
<span className='message-time'>
{message.name} - {this.getTimeString(messageTime)}
</span>
<span className='message-time'>
{message.name} - {this.getTimeString(messageTime)}
</span>
</div>
</div>
</div>
</div>
</div>
);
})
:<div className='empty'>
<p>No one has said anything yet...</p>
</div>
}
);
})
}
</When>
<Otherwise>
<div className='empty'>
<p>No one has said anything yet...</p>
</div>
</Otherwise>
</Choose>
</div>
);
}
+28 -23
View File
@@ -110,29 +110,34 @@ class FileEntry extends Component
<img className='file-avatar' src={this.props.data.picture || DEFAULT_PICTURE} />
<div className='file-content'>
{this.props.data.me ? (
<p>You shared a file.</p>
) : (
<p>{this.props.data.name} shared a file.</p>
)}
<Choose>
<When condition={this.props.data.me}>
<p>You shared a file.</p>
</When>
<Otherwise>
<p>{this.props.data.name} shared a file.</p>
</Otherwise>
</Choose>
{!this.state.active && !this.state.files && (
<If condition={!this.state.active && !this.state.files}>
<div className='file-info'>
{WebTorrent.WEBRTC_SUPPORT ? (
<span className='button' onClick={this.handleDownload}>
<img src='resources/images/download-icon.svg' />
</span>
) : (
<p>
Your browser does not support downloading files using WebTorrent.
</p>
)}
<Choose>
<When condition={WebTorrent.WEBRTC_SUPPORT}>
<span className='button' onClick={this.handleDownload}>
<img src='resources/images/download-icon.svg' />
</span>
</When>
<Otherwise>
<p>
Your browser does not support downloading files using WebTorrent.
</p>
</Otherwise>
</Choose>
<p>{magnet.decode(this.props.data.file.magnet).dn}</p>
</div>
)}
</If>
{this.state.active && this.state.numPeers === 0 && (
<If condition={this.state.active && this.state.numPeers === 0}>
<Fragment>
<p>
Locating peers
@@ -145,13 +150,13 @@ class FileEntry extends Component
</p>
)}
</Fragment>
)}
</If>
{this.state.active && this.state.numPeers > 0 && (
<If condition={this.state.active && this.state.numPeers > 0}>
<progress value={this.state.progress} />
)}
</If>
{this.state.files && (
<If condition={this.state.files}>
<Fragment>
<p>Torrent finished downloading.</p>
@@ -165,7 +170,7 @@ class FileEntry extends Component
</div>
))}
</Fragment>
)}
</If>
</div>
</div>
);
@@ -17,17 +17,23 @@ class SharedFilesList extends Component
return (
<div className='shared-files'>
{ sharing.length > 0 ?
sharing.map((entry, i) => (
<FileEntry
data={entry}
key={i}
/>
))
:<div className='empty'>
<p>No one has shared files yet...</p>
</div>
}
<Choose>
<When condition={sharing.length > 0}>
{
sharing.map((entry, i) => (
<FileEntry
data={entry}
key={i}
/>
))
}
</When>
<Otherwise>
<div className='empty'>
<p>No one has shared files yet...</p>
</div>
</Otherwise>
</Choose>
</div>
);
}
+37 -33
View File
@@ -4,7 +4,7 @@ import ResizeObserver from 'resize-observer-polyfill';
import { connect } from 'react-redux';
import debounce from 'lodash/debounce';
import classnames from 'classnames';
import * as requestActions from '../redux/requestActions';
import { withRoomContext } from '../RoomContext';
import Peer from './Peer';
import HiddenPeers from './HiddenPeers';
@@ -114,14 +114,20 @@ class Filmstrip extends Component
render()
{
const { peers, advancedMode, spotlights, spotlightsLength } = this.props;
const {
roomClient,
peers,
advancedMode,
spotlights,
spotlightsLength
} = this.props;
const activePeerName = this.getActivePeerName();
return (
<div data-component='Filmstrip'>
<div className='active-peer-container' ref={this.activePeerContainer}>
{peers[activePeerName] && (
<If condition={peers[activePeerName]}>
<div
className='active-peer'
style={{
@@ -134,7 +140,7 @@ class Filmstrip extends Component
name={activePeerName}
/>
</div>
)}
</If>
</div>
<div className='filmstrip'>
@@ -142,35 +148,37 @@ class Filmstrip extends Component
{
Object.keys(peers).map((peerName) =>
{
return (
spotlights.find((spotlightsElement) => spotlightsElement === peerName)?
<div
key={peerName}
onClick={() => this.props.setSelectedPeer(peerName)}
className={classnames('film', {
selected : this.props.selectedPeerName === peerName,
active : this.state.lastSpeaker === peerName
})}
>
<div className='film-content'>
<Peer
advancedMode={advancedMode}
name={peerName}
/>
</div>
<If
condition={
spotlights.find((spotlightsElement) => spotlightsElement === peerName)
}
>
<div
key={peerName}
onClick={() => roomClient.setSelectedPeer(peerName)}
className={classnames('film', {
selected : this.props.selectedPeerName === peerName,
active : this.state.lastSpeaker === peerName
})}
>
<div className='film-content'>
<Peer
advancedMode={advancedMode}
name={peerName}
/>
</div>
:null
);
</div>
</If>;
})
}
</div>
</div>
<div className='hidden-peer-container'>
{ (spotlightsLength<Object.keys(peers).length)?
<If condition={(spotlightsLength<Object.keys(peers).length)}>
<HiddenPeers
hiddenPeersCount={Object.keys(peers).length-spotlightsLength}
/>:null
}
/>
</If>
</div>
</div>
@@ -179,13 +187,13 @@ class Filmstrip extends Component
}
Filmstrip.propTypes = {
roomClient : PropTypes.any.isRequired,
activeSpeakerName : PropTypes.string,
advancedMode : PropTypes.bool,
peers : PropTypes.object.isRequired,
consumers : PropTypes.object.isRequired,
myName : PropTypes.string.isRequired,
selectedPeerName : PropTypes.string,
setSelectedPeer : PropTypes.func.isRequired,
spotlightsLength : PropTypes.number,
spotlights : PropTypes.array.isRequired
};
@@ -205,11 +213,7 @@ const mapStateToProps = (state) =>
};
};
const mapDispatchToProps = {
setSelectedPeer : requestActions.setSelectedPeer
};
export default connect(
export default withRoomContext(connect(
mapStateToProps,
mapDispatchToProps
)(Filmstrip);
undefined
)(Filmstrip));
+2 -3
View File
@@ -31,12 +31,11 @@ const FullScreenView = (props) =>
return (
<div data-component='FullScreenView'>
{consumerVisible && !consumer.supported ?
<If condition={consumerVisible && !consumer.supported}>
<div className='incompatible-video'>
<p>incompatible video</p>
</div>
:null
}
</If>
<div className='controls'>
<div
+2 -3
View File
@@ -35,12 +35,11 @@ export default class FullView extends React.Component
muted={Boolean(true)}
/>
{videoProfile === 'none' ?
<If condition={videoProfile === 'none'}>
<div className='spinner-container'>
<Spinner />
</div>
:null
}
</If>
</div>
);
}
+27 -45
View File
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
import classnames from 'classnames';
import { getDeviceInfo } from 'mediasoup-client';
import * as appPropTypes from './appPropTypes';
import * as requestActions from '../redux/requestActions';
import { withRoomContext } from '../RoomContext';
import PeerView from './PeerView';
import ScreenView from './ScreenView';
@@ -46,17 +46,13 @@ class Me extends React.Component
render()
{
const {
roomClient,
connected,
me,
advancedMode,
micProducer,
webcamProducer,
screenProducer,
onChangeDisplayName,
onMuteMic,
onUnmuteMic,
onEnableWebcam,
onDisableWebcam
screenProducer
} = this.props;
let micState;
@@ -107,7 +103,7 @@ class Me extends React.Component
onMouseOut={this.handleMouseOut}
>
<div className={classnames('view-container', 'webcam')}>
{connected ?
<If condition={connected}>
<div className={classnames('controls', 'visible')}>
<div
data-tip='keyboard shortcut: &lsquo;m&lsquo;'
@@ -120,7 +116,9 @@ class Me extends React.Component
})}
onClick={() =>
{
micState === 'on' ? onMuteMic() : onUnmuteMic();
micState === 'on' ?
roomClient.muteMic() :
roomClient.unmuteMic();
}}
/>
<ReactTooltip
@@ -134,12 +132,13 @@ class Me extends React.Component
})}
onClick={() =>
{
webcamState === 'on' ? onDisableWebcam() : onEnableWebcam();
webcamState === 'on' ?
roomClient.disableWebcam() :
roomClient.enableWebcam();
}}
/>
</div>
:null
}
</If>
<PeerView
isMe
@@ -151,11 +150,14 @@ class Me extends React.Component
videoVisible={videoVisible}
audioCodec={micProducer ? micProducer.codec : null}
videoCodec={webcamProducer ? webcamProducer.codec : null}
onChangeDisplayName={(displayName) => onChangeDisplayName(displayName)}
onChangeDisplayName={(displayName) =>
{
roomClient.changeDisplayName(displayName);
}}
/>
</div>
{screenProducer ?
<If condition={screenProducer}>
<div className={classnames('view-container', 'screen')}>
<ScreenView
isMe
@@ -165,8 +167,7 @@ class Me extends React.Component
screenCodec={screenProducer ? screenProducer.codec : null}
/>
</div>
:null
}
</If>
</div>
);
}
@@ -204,17 +205,13 @@ class Me extends React.Component
Me.propTypes =
{
connected : PropTypes.bool.isRequired,
advancedMode : PropTypes.bool,
me : appPropTypes.Me.isRequired,
micProducer : appPropTypes.Producer,
webcamProducer : appPropTypes.Producer,
screenProducer : appPropTypes.Producer,
onChangeDisplayName : PropTypes.func.isRequired,
onMuteMic : PropTypes.func.isRequired,
onUnmuteMic : PropTypes.func.isRequired,
onEnableWebcam : PropTypes.func.isRequired,
onDisableWebcam : PropTypes.func.isRequired
roomClient : PropTypes.any.isRequired,
connected : PropTypes.bool.isRequired,
advancedMode : PropTypes.bool,
me : appPropTypes.Me.isRequired,
micProducer : appPropTypes.Producer,
webcamProducer : appPropTypes.Producer,
screenProducer : appPropTypes.Producer
};
const mapStateToProps = (state) =>
@@ -236,23 +233,8 @@ const mapStateToProps = (state) =>
};
};
const mapDispatchToProps = (dispatch) =>
{
return {
onChangeDisplayName : (displayName) =>
{
dispatch(requestActions.changeDisplayName(displayName));
},
onMuteMic : () => dispatch(requestActions.muteMic()),
onUnmuteMic : () => dispatch(requestActions.unmuteMic()),
onEnableWebcam : () => dispatch(requestActions.enableWebcam()),
onDisableWebcam : () => dispatch(requestActions.disableWebcam())
};
};
const MeContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Me);
const MeContainer = withRoomContext(connect(
mapStateToProps
)(Me));
export default MeContainer;
+21 -60
View File
@@ -3,18 +3,15 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import * as appPropTypes from '../appPropTypes';
import * as requestActions from '../../redux/requestActions';
import { withRoomContext } from '../../RoomContext';
const ListPeer = (props) =>
{
const {
roomClient,
peer,
micConsumer,
screenConsumer,
onMuteMic,
onUnmuteMic,
onDisableScreen,
onEnableScreen
screenConsumer
} = props;
const micEnabled = (
@@ -39,7 +36,7 @@ const ListPeer = (props) =>
{peer.displayName}
</div>
<div className='indicators'>
{peer.raiseHandState ?
<If condition={peer.raiseHandState}>
<div className={
classnames(
'icon', 'raise-hand', {
@@ -49,14 +46,13 @@ const ListPeer = (props) =>
)
}
/>
:null
}
</If>
</div>
<div className='volume-container'>
<div className={classnames('bar', `level${micEnabled && micConsumer ? micConsumer.volume:0}`)} />
</div>
<div className='controls'>
{ screenConsumer ?
<If condition={screenConsumer}>
<div
className={classnames('button', 'screen', {
on : screenVisible,
@@ -67,11 +63,11 @@ const ListPeer = (props) =>
{
e.stopPropagation();
screenVisible ?
onDisableScreen(peer.name) : onEnableScreen(peer.name);
roomClient.pausePeerScreen(peer.name) :
roomClient.resumePeerScreen(peer.name);
}}
/>
:null
}
</If>
<div
className={classnames('button', 'mic', {
on : micEnabled,
@@ -81,7 +77,9 @@ const ListPeer = (props) =>
onClick={(e) =>
{
e.stopPropagation();
micEnabled ? onMuteMic(peer.name) : onUnmuteMic(peer.name);
micEnabled ?
roomClient.mutePeerAudio(peer.name) :
roomClient.unmutePeerAudio(peer.name);
}}
/>
</div>
@@ -91,17 +89,12 @@ const ListPeer = (props) =>
ListPeer.propTypes =
{
advancedMode : PropTypes.bool,
peer : appPropTypes.Peer.isRequired,
micConsumer : appPropTypes.Consumer,
webcamConsumer : appPropTypes.Consumer,
screenConsumer : appPropTypes.Consumer,
onMuteMic : PropTypes.func.isRequired,
onUnmuteMic : PropTypes.func.isRequired,
onEnableWebcam : PropTypes.func.isRequired,
onDisableWebcam : PropTypes.func.isRequired,
onEnableScreen : PropTypes.func.isRequired,
onDisableScreen : PropTypes.func.isRequired
roomClient : PropTypes.any.isRequired,
advancedMode : PropTypes.bool,
peer : appPropTypes.Peer.isRequired,
micConsumer : appPropTypes.Consumer,
webcamConsumer : appPropTypes.Consumer,
screenConsumer : appPropTypes.Consumer
};
const mapStateToProps = (state, { name }) =>
@@ -124,40 +117,8 @@ const mapStateToProps = (state, { name }) =>
};
};
const mapDispatchToProps = (dispatch) =>
{
return {
onMuteMic : (peerName) =>
{
dispatch(requestActions.mutePeerAudio(peerName));
},
onUnmuteMic : (peerName) =>
{
dispatch(requestActions.unmutePeerAudio(peerName));
},
onEnableWebcam : (peerName) =>
{
dispatch(requestActions.resumePeerVideo(peerName));
},
onDisableWebcam : (peerName) =>
{
dispatch(requestActions.pausePeerVideo(peerName));
},
onEnableScreen : (peerName) =>
{
dispatch(requestActions.resumePeerScreen(peerName));
},
onDisableScreen : (peerName) =>
{
dispatch(requestActions.pausePeerScreen(peerName));
}
};
};
const ListPeerContainer = connect(
mapStateToProps,
mapDispatchToProps
)(ListPeer);
const ListPeerContainer = withRoomContext(connect(
mapStateToProps
)(ListPeer));
export default ListPeerContainer;
@@ -2,16 +2,16 @@ import React from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';
import * as appPropTypes from '../appPropTypes';
import * as requestActions from '../../redux/requestActions';
import { withRoomContext } from '../../RoomContext';
import PropTypes from 'prop-types';
import ListPeer from './ListPeer';
import ListMe from './ListMe';
const ParticipantList =
({
roomClient,
advancedMode,
peers,
setSelectedPeer,
selectedPeerName,
spotlights
}) => (
@@ -33,7 +33,7 @@ const ParticipantList =
className={classNames('list-item', {
selected : peer.name === selectedPeerName
})}
onClick={() => setSelectedPeer(peer.name)}
onClick={() => roomClient.setSelectedPeer(peer.name)}
>
<ListPeer name={peer.name} advancedMode={advancedMode} />
</li>
@@ -52,7 +52,7 @@ const ParticipantList =
className={classNames('list-item', {
selected : peer.name === selectedPeerName
})}
onClick={() => setSelectedPeer(peer.name)}
onClick={() => roomClient.setSelectedPeer(peer.name)}
>
<ListPeer name={peer.name} advancedMode={advancedMode} />
</li>
@@ -64,9 +64,9 @@ const ParticipantList =
ParticipantList.propTypes =
{
roomClient : PropTypes.any.isRequired,
advancedMode : PropTypes.bool,
peers : PropTypes.arrayOf(appPropTypes.Peer).isRequired,
setSelectedPeer : PropTypes.func.isRequired,
selectedPeerName : PropTypes.string,
spotlights : PropTypes.array.isRequired
};
@@ -82,13 +82,8 @@ const mapStateToProps = (state) =>
};
};
const mapDispatchToProps = {
setSelectedPeer : requestActions.setSelectedPeer
};
const ParticipantListContainer = connect(
mapStateToProps,
mapDispatchToProps
)(ParticipantList);
const ParticipantListContainer = withRoomContext(connect(
mapStateToProps
)(ParticipantList));
export default ParticipantListContainer;
+16 -28
View File
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import * as appPropTypes from './appPropTypes';
import * as requestActions from '../redux/requestActions';
import { withRoomContext } from '../RoomContext';
import * as stateActions from '../redux/stateActions';
import PeerView from './PeerView';
import ScreenView from './ScreenView';
@@ -31,13 +31,12 @@ class Peer extends Component
render()
{
const {
roomClient,
advancedMode,
peer,
micConsumer,
webcamConsumer,
screenConsumer,
onMuteMic,
onUnmuteMic,
toggleConsumerFullscreen,
toggleConsumerWindow,
style,
@@ -81,23 +80,21 @@ class Peer extends Component
onMouseOver={this.handleMouseOver}
onMouseOut={this.handleMouseOut}
>
{videoVisible && !webcamConsumer.supported ?
<If condition={videoVisible && !webcamConsumer.supported}>
<div className='incompatible-video'>
<p>incompatible video</p>
</div>
:null
}
</If>
{!videoVisible ?
<If condition={!videoVisible}>
<div className='paused-video'>
<p>this video is paused</p>
</div>
:null
}
</If>
<div className={classnames('view-container', 'webcam')} style={style}>
<div className='indicators'>
{peer.raiseHandState ?
<If condition={peer.raiseHandState}>
<div className={
classnames(
'icon', 'raise-hand', {
@@ -107,8 +104,7 @@ class Peer extends Component
)
}
/>
:null
}
</If>
</div>
<div
className={classnames('controls', {
@@ -124,7 +120,9 @@ class Peer extends Component
onClick={(e) =>
{
e.stopPropagation();
micEnabled ? onMuteMic(peer.name) : onUnmuteMic(peer.name);
micEnabled ?
roomClient.mutePeerAudio(peer.name) :
roomClient.unmutePeerAudio(peer.name);
}}
/>
@@ -162,7 +160,7 @@ class Peer extends Component
/>
</div>
{screenConsumer ?
<If condition={screenConsumer}>
<div className={classnames('view-container', 'screen')} style={style}>
<div
className={classnames('controls', {
@@ -195,8 +193,7 @@ class Peer extends Component
screenCodec={screenConsumer ? screenConsumer.codec : null}
/>
</div>
:null
}
</If>
</div>
);
}
@@ -204,14 +201,13 @@ class Peer extends Component
Peer.propTypes =
{
roomClient : PropTypes.any.isRequired,
advancedMode : PropTypes.bool,
peer : appPropTypes.Peer.isRequired,
micConsumer : appPropTypes.Consumer,
webcamConsumer : appPropTypes.Consumer,
screenConsumer : appPropTypes.Consumer,
windowConsumer : PropTypes.number,
onMuteMic : PropTypes.func.isRequired,
onUnmuteMic : PropTypes.func.isRequired,
streamDimensions : PropTypes.object,
style : PropTypes.object,
toggleConsumerFullscreen : PropTypes.func.isRequired,
@@ -242,14 +238,6 @@ const mapStateToProps = (state, { name }) =>
const mapDispatchToProps = (dispatch) =>
{
return {
onMuteMic : (peerName) =>
{
dispatch(requestActions.mutePeerAudio(peerName));
},
onUnmuteMic : (peerName) =>
{
dispatch(requestActions.unmutePeerAudio(peerName));
},
toggleConsumerFullscreen : (consumer) =>
{
if (consumer)
@@ -263,9 +251,9 @@ const mapDispatchToProps = (dispatch) =>
};
};
const PeerContainer = connect(
const PeerContainer = withRoomContext(connect(
mapStateToProps,
mapDispatchToProps
)(Peer);
)(Peer));
export default PeerContainer;
+35 -38
View File
@@ -52,51 +52,50 @@ export default class PeerView extends React.Component
return (
<div data-component='PeerView'>
<div className='info'>
{advancedMode ?
<If condition={advancedMode}>
<div className={classnames('media', { 'is-me': isMe })}>
<div className='box'>
{audioCodec ?
<If condition={audioCodec}>
<p className='codec'>{audioCodec}</p>
:null
}
</If>
{videoCodec ?
<If condition={videoCodec}>
<p className='codec'>{videoCodec} {videoProfile}</p>
:null
}
</If>
{(videoVisible && videoWidth !== null) ?
<If condition={(videoVisible && videoWidth !== null)}>
<p className='resolution'>{videoWidth}x{videoHeight}</p>
:null
}
</If>
</div>
</div>
:null
}
</If>
<div className={classnames('peer', { 'is-me': isMe })}>
{isMe ?
<EditableInput
value={peer.displayName}
propName='displayName'
className='display-name editable'
classLoading='loading'
classInvalid='invalid'
shouldBlockWhileLoading
editProps={{
maxLength : 20,
autoCorrect : false,
spellCheck : false
}}
onChange={({ displayName }) => onChangeDisplayName(displayName)}
/>
:
<span className='display-name'>
{peer.displayName}
</span>
}
<Choose>
<When condition={isMe}>
<EditableInput
value={peer.displayName}
propName='displayName'
className='display-name editable'
classLoading='loading'
classInvalid='invalid'
shouldBlockWhileLoading
editProps={{
maxLength : 20,
autoCorrect : false,
spellCheck : false
}}
onChange={({ displayName }) => onChangeDisplayName(displayName)}
/>
</When>
<Otherwise>
<span className='display-name'>
{peer.displayName}
</span>
</Otherwise>
</Choose>
{advancedMode ?
<If condition={advancedMode}>
<div className='row'>
<span
className={classnames('device-icon', peer.device.flag)}
@@ -105,8 +104,7 @@ export default class PeerView extends React.Component
{peer.device.name} {Math.floor(peer.device.version) || null}
</span>
</div>
:null
}
</If>
</div>
</div>
@@ -125,12 +123,11 @@ export default class PeerView extends React.Component
<div className={classnames('bar', `level${volume}`)} />
</div>
{videoProfile === 'none' ?
<If condition={videoProfile === 'none'}>
<div className='spinner-container'>
<Spinner />
</div>
:null
}
</If>
</div>
);
}
+24 -23
View File
@@ -108,35 +108,36 @@ class Peers extends React.Component
{
peers.map((peer) =>
{
return (
(spotlights.find(function(spotlightsElement)
{ return spotlightsElement == peer.name; }))?
<Appear key={peer.name} duration={1000}>
<div
className={classnames('peer-container', {
'selected' : this.props.selectedPeerName === peer.name,
'active-speaker' : peer.name === activeSpeakerName
})}
>
<div className='peer-content'>
<Peer
advancedMode={advancedMode}
name={peer.name}
style={style}
/>
</div>
<If
condition={
spotlights.find((spotlightsElement) => spotlightsElement === peer.name)
}
>
<Appear key={peer.name} duration={1000}>
<div
className={classnames('peer-container', {
'selected' : this.props.selectedPeerName === peer.name,
'active-speaker' : peer.name === activeSpeakerName
})}
>
<div className='peer-content'>
<Peer
advancedMode={advancedMode}
name={peer.name}
style={style}
/>
</div>
</Appear>
:null
);
</div>
</Appear>
</If>;
})
}
<div className='hidden-peer-container'>
{ (spotlightsLength<peers.length)?
<If condition={spotlightsLength < peers.length}>
<HiddenPeers
hiddenPeersCount={peers.length-spotlightsLength}
/>:null
}
/>
</If>
</div>
</div>
);
+2 -4
View File
@@ -13,7 +13,6 @@ import Me from './Me';
import Peers from './Peers';
import AudioPeers from './PeerAudio/AudioPeers';
import Notifications from './Notifications';
// import ToolAreaButton from './ToolArea/ToolAreaButton';
import ToolArea from './ToolArea/ToolArea';
import FullScreenView from './FullScreenView';
import VideoWindow from './VideoWindow/VideoWindow';
@@ -97,13 +96,12 @@ class Room extends React.Component
<Notifications />
{room.advancedMode ?
<If condition={room.advancedMode}>
<div className='state' data-tip='Server status'>
<div className={classnames('icon', room.state)} />
<p className={classnames('text', room.state)}>{room.state}</p>
</div>
:null
}
</If>
<div
className={classnames('room-link-wrapper room-controls', {
+10 -15
View File
@@ -41,25 +41,21 @@ export default class ScreenView extends React.Component
return (
<div data-component='ScreenView'>
<div className='info'>
{advancedMode ?
<If condition={advancedMode}>
<div className={classnames('media', { 'is-me': isMe })}>
{screenVisible ?
<If condition={screenVisible}>
<div className='box'>
{screenCodec ?
<If condition={screenCodec}>
<p className='codec'>{screenCodec} {screenProfile}</p>
:null
}
</If>
{(screenVisible && screenWidth !== null) ?
<If condition={(screenVisible && screenWidth !== null)}>
<p className='resolution'>{screenWidth}x{screenHeight}</p>
:null
}
</If>
</div>
:null
}
</If>
</div>
:null
}
</If>
</div>
<video
@@ -73,12 +69,11 @@ export default class ScreenView extends React.Component
muted={Boolean(true)}
/>
{screenProfile === 'none' ?
<If condition={screenProfile === 'none'}>
<div className='spinner-container'>
<Spinner />
</div>
:null
}
</If>
</div>
);
}
+17 -17
View File
@@ -1,7 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import * as appPropTypes from './appPropTypes';
import * as requestActions from '../redux/requestActions';
import { withRoomContext } from '../RoomContext';
import * as stateActions from '../redux/stateActions';
import PropTypes from 'prop-types';
import Dropdown from 'react-dropdown';
@@ -18,8 +18,11 @@ const modes = [ {
const findOption = (options, value) => options.find((option) => option.value === value);
const Settings = ({
room, me, onToggleAdvancedMode, handleChangeWebcam,
handleChangeAudioDevice, handleChangeMode
roomClient,
room,
me,
onToggleAdvancedMode,
handleChangeMode
}) =>
{
let webcams;
@@ -48,7 +51,7 @@ const Settings = ({
<Dropdown
options={webcams}
value={findOption(webcams, me.selectedWebcam)}
onChange={(webcam) => handleChangeWebcam(webcam.value)}
onChange={(webcam) => roomClient.changeWebcam(webcam.value)}
placeholder={'Select camera'}
/>
@@ -56,7 +59,7 @@ const Settings = ({
disabled={!me.canChangeAudioDevice}
options={audioDevices}
value={findOption(audioDevices, me.selectedAudioDevice)}
onChange={(device) => handleChangeAudioDevice(device.value)}
onChange={(device) => roomClient.changeAudioDevice(device.value)}
placeholder={audioDevicesText}
/>
<ReactTooltip
@@ -94,12 +97,11 @@ const Settings = ({
Settings.propTypes =
{
me : appPropTypes.Me.isRequired,
room : appPropTypes.Room.isRequired,
handleChangeWebcam : PropTypes.func.isRequired,
handleChangeAudioDevice : PropTypes.func.isRequired,
onToggleAdvancedMode : PropTypes.func.isRequired,
handleChangeMode : PropTypes.func.isRequired
roomClient : PropTypes.any.isRequired,
me : appPropTypes.Me.isRequired,
room : appPropTypes.Room.isRequired,
onToggleAdvancedMode : PropTypes.func.isRequired,
handleChangeMode : PropTypes.func.isRequired
};
const mapStateToProps = (state) =>
@@ -111,15 +113,13 @@ const mapStateToProps = (state) =>
};
const mapDispatchToProps = {
handleChangeWebcam : requestActions.changeWebcam,
handleChangeAudioDevice : requestActions.changeAudioDevice,
onToggleAdvancedMode : stateActions.toggleAdvancedMode,
handleChangeMode : stateActions.setDisplayMode
onToggleAdvancedMode : stateActions.toggleAdvancedMode,
handleChangeMode : stateActions.setDisplayMode
};
const SettingsContainer = connect(
const SettingsContainer = withRoomContext(connect(
mapStateToProps,
mapDispatchToProps
)(Settings);
)(Settings));
export default SettingsContainer;
+40 -50
View File
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import classnames from 'classnames';
import * as appPropTypes from './appPropTypes';
import * as requestActions from '../redux/requestActions';
import { withRoomContext } from '../RoomContext';
import FullScreen from './FullScreen';
class Sidebar extends Component
@@ -56,8 +56,10 @@ class Sidebar extends Component
render()
{
const {
toolbarsVisible, me, screenProducer, onLogin, onShareScreen,
onUnShareScreen, onNeedExtension, onLeaveMeeting, onLogout, onToggleHand
roomClient,
toolbarsVisible,
me,
screenProducer
} = this.props;
let screenState;
@@ -91,7 +93,7 @@ class Sidebar extends Component
})}
data-component='Sidebar'
>
{this.fullscreen.fullscreenEnabled && (
<If condition={this.fullscreen.fullscreenEnabled}>
<div
className={classnames('button', 'fullscreen', {
on : this.state.fullscreen
@@ -101,7 +103,7 @@ class Sidebar extends Component
data-place='right'
data-type='dark'
/>
)}
</If>
<div
className={classnames('button', 'screen', screenState)}
@@ -114,17 +116,17 @@ class Sidebar extends Component
{
case 'on':
{
onUnShareScreen();
roomClient.disableScreenSharing();
break;
}
case 'off':
{
onShareScreen();
roomClient.enableScreenSharing();
break;
}
case 'need-extension':
{
onNeedExtension();
roomClient.installExtension();
break;
}
default:
@@ -135,25 +137,30 @@ class Sidebar extends Component
}}
/>
{me.loginEnabled && (me.loggedIn ? (
<div
className='button logout'
data-tip='Logout'
data-place='right'
data-type='dark'
onClick={onLogout}
>
<img src={me.picture || 'resources/images/avatar-empty.jpeg'} />
</div>
) : (
<div
className='button login off'
data-tip='Login'
data-place='right'
data-type='dark'
onClick={onLogin}
/>
))}
<If condition={me.loginEnabled}>
<Choose>
<When condition={me.loggedIn}>
<div
className='button logout'
data-tip='Logout'
data-place='right'
data-type='dark'
onClick={() => roomClient.logout()}
>
<img src={me.picture || 'resources/images/avatar-empty.jpeg'} />
</div>
</When>
<Otherwise>
<div
className='button login off'
data-tip='Login'
data-place='right'
data-type='dark'
onClick={() => roomClient.login()}
/>
</Otherwise>
</Choose>
</If>
<div
className={classnames('button', 'raise-hand', {
on : me.raiseHand,
@@ -162,7 +169,7 @@ class Sidebar extends Component
data-tip='Raise hand'
data-place='right'
data-type='dark'
onClick={() => onToggleHand(!me.raiseHand)}
onClick={() => roomClient.sendRaiseHandState(!me.raiseHand)}
/>
<div
@@ -170,7 +177,7 @@ class Sidebar extends Component
data-tip='Leave meeting'
data-place='right'
data-type='dark'
onClick={() => onLeaveMeeting()}
onClick={() => roomClient.close()}
/>
</div>
);
@@ -178,15 +185,9 @@ class Sidebar extends Component
}
Sidebar.propTypes = {
roomClient : PropTypes.any.isRequired,
toolbarsVisible : PropTypes.bool.isRequired,
me : appPropTypes.Me.isRequired,
onShareScreen : PropTypes.func.isRequired,
onUnShareScreen : PropTypes.func.isRequired,
onNeedExtension : PropTypes.func.isRequired,
onToggleHand : PropTypes.func.isRequired,
onLeaveMeeting : PropTypes.func.isRequired,
onLogin : PropTypes.func.isRequired,
onLogout : PropTypes.func.isRequired,
screenProducer : appPropTypes.Producer
};
@@ -198,17 +199,6 @@ const mapStateToProps = (state) =>
me : state.me
});
const mapDispatchToProps = {
onLeaveMeeting : requestActions.leaveRoom,
onShareScreen : requestActions.enableScreenSharing,
onUnShareScreen : requestActions.disableScreenSharing,
onNeedExtension : requestActions.installExtension,
onToggleHand : requestActions.toggleHand,
onLogin : requestActions.userLogin,
onLogout : requestActions.userLogout
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Sidebar);
export default withRoomContext(connect(
mapStateToProps
)(Sidebar));