Merge pull request #4 from havfo/develop

sync with upstream repo
auto_join_3.3
Saša Davidović 2020-05-07 12:53:09 +02:00 committed by GitHub
commit 99a9ec7d1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1086 additions and 431 deletions

View File

@ -27,6 +27,7 @@
"react": "^16.10.2", "react": "^16.10.2",
"react-cookie-consent": "^2.5.0", "react-cookie-consent": "^2.5.0",
"react-dom": "^16.10.2", "react-dom": "^16.10.2",
"react-flip-toolkit": "^7.0.9",
"react-intl": "^3.4.0", "react-intl": "^3.4.0",
"react-redux": "^7.1.1", "react-redux": "^7.1.1",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",

View File

@ -42,6 +42,17 @@ var config =
{ {
tcp : true tcp : true
}, },
defaultAudio :
{
sampleRate : 48000,
channelCount : 1,
volume : 1.0,
autoGainControl : true,
echoCancellation : true,
noiseSuppression : true,
sampleSize : 16
},
background : 'images/background.jpg',
defaultLayout : 'democratic', // democratic, filmstrip defaultLayout : 'democratic', // democratic, filmstrip
lastN : 4, lastN : 4,
mobileLastN : 1, mobileLastN : 1,
@ -49,7 +60,6 @@ var config =
maxLastN : 5, maxLastN : 5,
// If truthy, users can NOT change number of speakers visible // If truthy, users can NOT change number of speakers visible
lockLastN : false, lockLastN : false,
background : 'images/background.jpg',
// Add file and uncomment for adding logo to appbar // Add file and uncomment for adding logo to appbar
// logo : 'images/logo.svg', // logo : 'images/logo.svg',
title : 'Multiparty meeting', title : 'Multiparty meeting',

View File

@ -475,9 +475,9 @@ export default class RoomClient
window.open(url, 'loginWindow'); window.open(url, 'loginWindow');
} }
logout() logout(roomId = this._roomId)
{ {
window.open('/auth/logout', 'logoutWindow'); window.open(`/auth/logout?peerId=${this._peerId}&roomId=${roomId}`, 'logoutWindow');
} }
receiveLoginChildWindow(data) receiveLoginChildWindow(data)
@ -953,78 +953,32 @@ export default class RoomClient
} }
} }
async getAudioTrack() disconnectLocalHark()
{ {
await navigator.mediaDevices.getUserMedia( logger.debug('disconnectLocalHark() | Stopping harkStream.');
{
audio : true, video : false
});
}
async getVideoTrack()
{
await navigator.mediaDevices.getUserMedia(
{
audio : false, video : true
});
}
async changeAudioDevice(deviceId)
{
logger.debug('changeAudioDevice() [deviceId: %s]', deviceId);
store.dispatch(
meActions.setAudioInProgress(true));
try
{
const device = this._audioDevices[deviceId];
if (!device)
throw new Error('no audio devices');
logger.debug(
'changeAudioDevice() | new selected webcam [device:%o]',
device);
if (this._hark != null)
this._hark.stop();
if (this._harkStream != null) if (this._harkStream != null)
{ {
logger.debug('Stopping hark.');
this._harkStream.getAudioTracks()[0].stop(); this._harkStream.getAudioTracks()[0].stop();
this._harkStream = null; this._harkStream = null;
} }
if (this._micProducer && this._micProducer.track) if (this._hark != null)
this._micProducer.track.stop();
logger.debug('changeAudioDevice() | calling getUserMedia()');
const stream = await navigator.mediaDevices.getUserMedia(
{ {
audio : logger.debug('disconnectLocalHark() Stopping hark.');
{ this._hark.stop();
deviceId : { exact: device.deviceId } }
} }
});
const track = stream.getAudioTracks()[0];
if (this._micProducer)
await this._micProducer.replaceTrack({ track });
if (this._micProducer)
this._micProducer.volume = 0;
connectLocalHark(track)
{
logger.debug('connectLocalHark() | Track:%o', track);
this._harkStream = new MediaStream(); this._harkStream = new MediaStream();
this._harkStream.addTrack(track.clone()); this._harkStream.addTrack(track.clone());
this._harkStream.getAudioTracks()[0].enabled = true; this._harkStream.getAudioTracks()[0].enabled = true;
if (!this._harkStream.getAudioTracks()[0]) if (!this._harkStream.getAudioTracks()[0])
throw new Error('changeAudioDevice(): given stream has no audio track'); throw new Error('getMicStream():something went wrong with hark');
this._hark = hark(this._harkStream, { play: false }); this._hark = hark(this._harkStream, { play: false });
@ -1033,7 +987,7 @@ export default class RoomClient
{ {
// The exact formula to convert from dBs (-100..0) to linear (0..1) is: // The exact formula to convert from dBs (-100..0) to linear (0..1) is:
// Math.pow(10, dBs / 20) // Math.pow(10, dBs / 20)
// However it does not produce a visually useful output, so let exaggerate // However it does not produce a visually useful output, so let exagerate
// it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to // it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to
// minimize component renderings. // minimize component renderings.
let volume = Math.round(Math.pow(10, dBs / 85) * 10); let volume = Math.round(Math.pow(10, dBs / 85) * 10);
@ -1058,6 +1012,59 @@ export default class RoomClient
{ {
store.dispatch(meActions.setIsSpeaking(false)); store.dispatch(meActions.setIsSpeaking(false));
}); });
}
async changeAudioDevice(deviceId)
{
logger.debug('changeAudioDevice() [deviceId: %s]', deviceId);
store.dispatch(
meActions.setAudioInProgress(true));
try
{
const device = this._audioDevices[deviceId];
if (!device)
throw new Error('no audio devices');
logger.debug(
'changeAudioDevice() | new selected webcam [device:%o]',
device);
this.disconnectLocalHark();
if (this._micProducer && this._micProducer.track)
this._micProducer.track.stop();
logger.debug('changeAudioDevice() | calling getUserMedia() %o', store.getState().settings);
const stream = await navigator.mediaDevices.getUserMedia(
{
audio :
{
deviceId : { ideal: device.deviceId },
sampleRate : store.getState().settings.sampleRate,
channelCount : store.getState().settings.channelCount,
volume : store.getState().settings.volume,
autoGainControl : store.getState().settings.autoGainControl,
echoCancellation : store.getState().settings.echoCancellation,
noiseSuppression : store.getState().settings.noiseSuppression,
sampleSize : store.getState().settings.sampleSize
}
}
);
logger.debug('Constraints: %o', stream.getAudioTracks()[0].getConstraints());
const track = stream.getAudioTracks()[0];
if (this._micProducer)
await this._micProducer.replaceTrack({ track });
if (this._micProducer)
this._micProducer.volume = 0;
this.connectLocalHark(track);
if (this._micProducer && this._micProducer.id) if (this._micProducer && this._micProducer.id)
store.dispatch( store.dispatch(
producerActions.setProducerTrack(this._micProducer.id, track)); producerActions.setProducerTrack(this._micProducer.id, track));
@ -1533,6 +1540,26 @@ export default class RoomClient
} }
} }
async lowerPeerHand(peerId)
{
logger.debug('lowerPeerHand() [peerId:"%s"]', peerId);
store.dispatch(
peerActions.setPeerRaisedHandInProgress(peerId, true));
try
{
await this.sendRequest('moderator:lowerHand', { peerId });
}
catch (error)
{
logger.error('lowerPeerHand() | [error:"%o"]', error);
}
store.dispatch(
peerActions.setPeerRaisedHandInProgress(peerId, false));
}
async setRaisedHand(raisedHand) async setRaisedHand(raisedHand)
{ {
logger.debug('setRaisedHand: ', raisedHand); logger.debug('setRaisedHand: ', raisedHand);
@ -2534,6 +2561,13 @@ export default class RoomClient
break; break;
} }
case 'moderator:lowerHand':
{
this.setRaisedHand(false);
break;
}
case 'gotRole': case 'gotRole':
{ {
const { peerId, role } = notification.data; const { peerId, role } = notification.data;
@ -2811,7 +2845,9 @@ export default class RoomClient
{ {
text : intl.formatMessage({ text : intl.formatMessage({
id : 'roles.gotRole', id : 'roles.gotRole',
defaultMessage : `You got the role: ${role}` defaultMessage : 'You got the role: {role}'
}, {
role
}) })
})); }));
} }
@ -3233,11 +3269,20 @@ export default class RoomClient
const stream = await navigator.mediaDevices.getUserMedia( const stream = await navigator.mediaDevices.getUserMedia(
{ {
audio : { audio : {
deviceId : { ideal: deviceId } deviceId : { ideal: device.deviceId },
sampleRate : store.getState().settings.sampleRate,
channelCount : store.getState().settings.channelCount,
volume : store.getState().settings.volume,
autoGainControl : store.getState().settings.autoGainControl,
echoCancellation : store.getState().settings.echoCancellation,
noiseSuppression : store.getState().settings.noiseSuppression,
sampleSize : store.getState().settings.sampleSize
} }
} }
); );
logger.debug('Constraints: %o', stream.getAudioTracks()[0].getConstraints());
track = stream.getAudioTracks()[0]; track = stream.getAudioTracks()[0];
this._micProducer = await this._sendTransport.produce( this._micProducer = await this._sendTransport.produce(
@ -3291,51 +3336,8 @@ export default class RoomClient
this._micProducer.volume = 0; this._micProducer.volume = 0;
if (this._hark != null) this.connectLocalHark(track);
this._hark.stop();
if (this._harkStream != null)
this._harkStream.getAudioTracks()[0].stop();
this._harkStream = new MediaStream();
this._harkStream.addTrack(track.clone());
if (!this._harkStream.getAudioTracks()[0])
throw new Error('enableMic(): given stream has no audio track');
this._hark = hark(this._harkStream, { play: false });
// eslint-disable-next-line no-unused-vars
this._hark.on('volume_change', (dBs, threshold) =>
{
// The exact formula to convert from dBs (-100..0) to linear (0..1) is:
// Math.pow(10, dBs / 20)
// However it does not produce a visually useful output, so let exaggerate
// it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to
// minimize component renderings.
let volume = Math.round(Math.pow(10, dBs / 85) * 10);
if (volume === 1)
volume = 0;
volume = Math.round(volume);
if (this._micProducer && volume !== this._micProducer.volume)
{
this._micProducer.volume = volume;
store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume));
}
});
this._hark.on('speaking', function()
{
store.dispatch(meActions.setIsSpeaking(true));
});
this._hark.on('stopped_speaking', function()
{
store.dispatch(meActions.setIsSpeaking(false));
});
} }
catch (error) catch (error)
{ {

View File

@ -40,6 +40,12 @@ export const setPeerRaisedHand = (peerId, raisedHand, raisedHandTimestamp) =>
payload : { peerId, raisedHand, raisedHandTimestamp } payload : { peerId, raisedHand, raisedHandTimestamp }
}); });
export const setPeerRaisedHandInProgress = (peerId, flag) =>
({
type : 'SET_PEER_RAISED_HAND_IN_PROGRESS',
payload : { peerId, flag }
});
export const setPeerPicture = (peerId, picture) => export const setPeerPicture = (peerId, picture) =>
({ ({
type : 'SET_PEER_PICTURE', type : 'SET_PEER_PICTURE',

View File

@ -38,6 +38,50 @@ export const togglePermanentTopBar = () =>
type : 'TOGGLE_PERMANENT_TOPBAR' type : 'TOGGLE_PERMANENT_TOPBAR'
}); });
export const toggleShowNotifications = () =>
({
type : 'TOGGLE_SHOW_NOTIFICATIONS'
});
export const setEchoCancellation = (echoCancellation) =>
({
type : 'SET_ECHO_CANCELLATION',
payload : { echoCancellation }
});
export const setAutoGainControl = (autoGainControl) =>
({
type : 'SET_AUTO_GAIN_CONTROL',
payload : { autoGainControl }
});
export const setNoiseSuppression = (noiseSuppression) =>
({
type : 'SET_NOISE_SUPPRESSION',
payload : { noiseSuppression }
});
export const setDefaultAudio = (audio) =>
({
type : 'SET_DEFAULT_AUDIO',
payload : { audio }
});
export const toggleEchoCancellation = () =>
({
type : 'TOGGLE_ECHO_CANCELLATION'
});
export const toggleAutoGainControl = () =>
({
type : 'TOGGLE_AUTO_GAIN_CONTROL'
});
export const toggleNoiseSuppression = () =>
({
type : 'TOGGLE_NOISE_SUPPRESSION'
});
export const toggleHiddenControls = () => export const toggleHiddenControls = () =>
({ ({
type : 'TOGGLE_HIDDEN_CONTROLS' type : 'TOGGLE_HIDDEN_CONTROLS'

View File

@ -16,11 +16,13 @@ import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar'; import Toolbar from '@material-ui/core/Toolbar';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import Menu from '@material-ui/core/Menu'; import Menu from '@material-ui/core/Menu';
import Popover from '@material-ui/core/Popover';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu'; import MenuIcon from '@material-ui/icons/Menu';
import Avatar from '@material-ui/core/Avatar'; import Avatar from '@material-ui/core/Avatar';
import Badge from '@material-ui/core/Badge'; import Badge from '@material-ui/core/Badge';
import Paper from '@material-ui/core/Paper';
import ExtensionIcon from '@material-ui/icons/Extension'; import ExtensionIcon from '@material-ui/icons/Extension';
import AccountCircle from '@material-ui/icons/AccountCircle'; import AccountCircle from '@material-ui/icons/AccountCircle';
import FullScreenIcon from '@material-ui/icons/Fullscreen'; import FullScreenIcon from '@material-ui/icons/Fullscreen';
@ -33,6 +35,7 @@ import LockOpenIcon from '@material-ui/icons/LockOpen';
import VideoCallIcon from '@material-ui/icons/VideoCall'; import VideoCallIcon from '@material-ui/icons/VideoCall';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip'; import Tooltip from '@material-ui/core/Tooltip';
import MoreIcon from '@material-ui/icons/MoreVert';
const styles = (theme) => const styles = (theme) =>
({ ({
@ -77,9 +80,17 @@ const styles = (theme) =>
display : 'block' display : 'block'
} }
}, },
actionButtons : sectionDesktop : {
{ display : 'none',
[theme.breakpoints.up('md')] : {
display : 'flex' display : 'flex'
}
},
sectionMobile : {
display : 'flex',
[theme.breakpoints.up('md')] : {
display : 'none'
}
}, },
actionButton : actionButton :
{ {
@ -96,7 +107,7 @@ const styles = (theme) =>
}, },
moreAction : moreAction :
{ {
margin : theme.spacing(0, 0, 0, 1) margin : theme.spacing(0.5, 0, 0.5, 1.5)
} }
}); });
@ -135,16 +146,36 @@ const TopBar = (props) =>
{ {
const intl = useIntl(); const intl = useIntl();
const [ moreActionsElement, setMoreActionsElement ] = useState(null); const [ mobileMoreAnchorEl, setMobileMoreAnchorEl ] = useState(null);
const [ anchorEl, setAnchorEl ] = useState(null);
const [ currentMenu, setCurrentMenu ] = useState(null);
const handleMoreActionsOpen = (event) => const handleExited = () =>
{ {
setMoreActionsElement(event.currentTarget); setCurrentMenu(null);
}; };
const handleMoreActionsClose = () => const handleMobileMenuOpen = (event) =>
{ {
setMoreActionsElement(null); setMobileMoreAnchorEl(event.currentTarget);
};
const handleMobileMenuClose = () =>
{
setMobileMoreAnchorEl(null);
};
const handleMenuOpen = (event, menu) =>
{
setAnchorEl(event.currentTarget);
setCurrentMenu(menu);
};
const handleMenuClose = () =>
{
setAnchorEl(null);
handleMobileMenuClose();
}; };
const { const {
@ -171,7 +202,8 @@ const TopBar = (props) =>
classes classes
} = props; } = props;
const isMoreActionsMenuOpen = Boolean(moreActionsElement); const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const lockTooltip = room.locked ? const lockTooltip = room.locked ?
intl.formatMessage({ intl.formatMessage({
@ -239,10 +271,15 @@ const TopBar = (props) =>
{ window.config.title ? window.config.title : 'Multiparty meeting' } { window.config.title ? window.config.title : 'Multiparty meeting' }
</Typography> </Typography>
<div className={classes.grow} /> <div className={classes.grow} />
<div className={classes.actionButtons}> <div className={classes.sectionDesktop}>
<IconButton <IconButton
aria-owns={
isMenuOpen &&
currentMenu === 'moreActions' ?
'material-appbar' : undefined
}
aria-haspopup='true' aria-haspopup='true'
onClick={handleMoreActionsOpen} onClick={(event) => handleMenuOpen(event, 'moreActions')}
color='inherit' color='inherit'
> >
<ExtensionIcon /> <ExtensionIcon />
@ -386,6 +423,16 @@ const TopBar = (props) =>
</IconButton> </IconButton>
</Tooltip> </Tooltip>
} }
</div>
<div className={classes.sectionMobile}>
<IconButton
aria-haspopup='true'
onClick={handleMobileMenuOpen}
color='inherit'
>
<MoreIcon />
</IconButton>
</div>
<div className={classes.divider} /> <div className={classes.divider} />
<Button <Button
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
@ -402,23 +449,24 @@ const TopBar = (props) =>
defaultMessage='Leave' defaultMessage='Leave'
/> />
</Button> </Button>
</div>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
<Menu <Popover
anchorEl={moreActionsElement} anchorEl={anchorEl}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }} anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
transformOrigin={{ vertical: 'top', horizontal: 'left' }} transformOrigin={{ vertical: 'top', horizontal: 'left' }}
open={isMoreActionsMenuOpen} open={isMenuOpen}
onClose={handleMoreActionsClose} onClose={handleMenuClose}
onExited={handleExited}
getContentAnchorEl={null} getContentAnchorEl={null}
> >
{ currentMenu === 'moreActions' &&
<Paper>
<MenuItem <MenuItem
dense
disabled={!canProduceExtraVideo} disabled={!canProduceExtraVideo}
onClick={() => onClick={() =>
{ {
handleMoreActionsClose(); handleMenuClose();
setExtraVideoOpen(!room.extraVideoOpen); setExtraVideoOpen(!room.extraVideoOpen);
}} }}
> >
@ -435,6 +483,196 @@ const TopBar = (props) =>
/> />
</p> </p>
</MenuItem> </MenuItem>
</Paper>
}
</Popover>
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
transformOrigin={{ vertical: 'bottom', horizontal: 'right' }}
open={isMobileMenuOpen}
onClose={handleMenuClose}
getContentAnchorEl={null}
>
{ loginEnabled &&
<MenuItem
aria-label={loginTooltip}
onClick={() =>
{
handleMenuClose();
loggedIn ? roomClient.logout() : roomClient.login();
}}
>
{ myPicture ?
<Avatar src={myPicture} />
:
<AccountCircle className={loggedIn ? classes.green : null} />
}
{ loggedIn ?
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.logout'
defaultMessage='Log out'
/>
</p>
:
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.login'
defaultMessage='Log in'
/>
</p>
}
</MenuItem>
}
<MenuItem
aria-label={lockTooltip}
disabled={!canLock}
onClick={() =>
{
handleMenuClose();
if (room.locked)
{
roomClient.unlockRoom();
}
else
{
roomClient.lockRoom();
}
}}
>
{ room.locked ?
<LockIcon />
:
<LockOpenIcon />
}
{ room.locked ?
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.unLockRoom'
defaultMessage='Unlock room'
/>
</p>
:
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.lockRoom'
defaultMessage='Lock room'
/>
</p>
}
</MenuItem>
<MenuItem
aria-label={intl.formatMessage({
id : 'tooltip.settings',
defaultMessage : 'Show settings'
})}
onClick={() =>
{
handleMenuClose();
setSettingsOpen(!room.settingsOpen);
}}
>
<SettingsIcon />
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.settings'
defaultMessage='Show settings'
/>
</p>
</MenuItem>
{ lobbyPeers.length > 0 &&
<MenuItem
aria-label={intl.formatMessage({
id : 'tooltip.lobby',
defaultMessage : 'Show lobby'
})}
disabled={!canPromote}
onClick={() =>
{
handleMenuClose();
setLockDialogOpen(!room.lockDialogOpen);
}}
>
<PulsingBadge
color='secondary'
badgeContent={lobbyPeers.length}
>
<SecurityIcon />
</PulsingBadge>
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.lobby'
defaultMessage='Show lobby'
/>
</p>
</MenuItem>
}
<MenuItem
aria-label={intl.formatMessage({
id : 'tooltip.participants',
defaultMessage : 'Show participants'
})}
onClick={() =>
{
handleMenuClose();
openUsersTab();
}}
>
<Badge
color='primary'
badgeContent={peersLength + 1}
>
<PeopleIcon />
</Badge>
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.participants'
defaultMessage='Show participants'
/>
</p>
</MenuItem>
{ fullscreenEnabled &&
<MenuItem
aria-label={intl.formatMessage({
id : 'tooltip.enterFullscreen',
defaultMessage : 'Enter fullscreen'
})}
onClick={() =>
{
handleMenuClose();
onFullscreen();
}}
>
{ fullscreen ?
<FullScreenExitIcon />
:
<FullScreenIcon />
}
<p className={classes.moreAction}>
<FormattedMessage
id='tooltip.enterFullscreen'
defaultMessage='Enter fullscreen'
/>
</p>
</MenuItem>
}
<MenuItem
aria-label={intl.formatMessage({
id : 'label.moreActions',
defaultMessage : 'Add video'
})}
onClick={(event) => handleMenuOpen(event, 'moreActions')}
>
<ExtensionIcon />
<p className={classes.moreAction}>
<FormattedMessage
id='label.moreActions'
defaultMessage='More actions'
/>
</p>
</MenuItem>
</Menu> </Menu>
</React.Fragment> </React.Fragment>
); );

View File

@ -224,7 +224,7 @@ const JoinDialog = ({
myPicture={myPicture} myPicture={myPicture}
onLogin={() => onLogin={() =>
{ {
loggedIn ? roomClient.logout() : roomClient.login(roomId); loggedIn ? roomClient.logout(roomId) : roomClient.login(roomId);
}} }}
loggedIn={loggedIn} loggedIn={loggedIn}
> >

View File

@ -2,10 +2,12 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import { withRoomContext } from '../../../RoomContext'; import { withRoomContext } from '../../../RoomContext';
import classnames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import * as appPropTypes from '../../appPropTypes'; import * as appPropTypes from '../../appPropTypes';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import PanIcon from '@material-ui/icons/PanTool'; import PanIcon from '@material-ui/icons/PanTool';
import EmptyAvatar from '../../../images/avatar-empty.jpeg'; import EmptyAvatar from '../../../images/avatar-empty.jpeg';
@ -22,7 +24,7 @@ const styles = (theme) =>
{ {
borderRadius : '50%', borderRadius : '50%',
height : '2rem', height : '2rem',
marginTop : theme.spacing(1) marginTop : theme.spacing(0.5)
}, },
peerInfo : peerInfo :
{ {
@ -32,6 +34,10 @@ const styles = (theme) =>
flexGrow : 1, flexGrow : 1,
alignItems : 'center' alignItems : 'center'
}, },
buttons :
{
padding : theme.spacing(1)
},
green : green :
{ {
color : 'rgba(0, 153, 0, 1)' color : 'rgba(0, 153, 0, 1)'
@ -58,12 +64,21 @@ const ListMe = (props) =>
<div className={classes.peerInfo}> <div className={classes.peerInfo}>
{settings.displayName} {settings.displayName}
</div> </div>
<Tooltip
title={intl.formatMessage({
id : 'tooltip.raisedHand',
defaultMessage : 'Raise hand'
})}
placement='bottom'
>
<IconButton <IconButton
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
id : 'tooltip.raisedHand', id : 'tooltip.raisedHand',
defaultMessage : 'Raise hand' defaultMessage : 'Raise hand'
})} })}
className={me.raisedHand ? classes.green : null} className={
classnames(me.raisedHand ? classes.green : null, classes.buttons)
}
disabled={me.raisedHandInProgress} disabled={me.raisedHandInProgress}
color='primary' color='primary'
onClick={(e) => onClick={(e) =>
@ -75,6 +90,7 @@ const ListMe = (props) =>
> >
<PanIcon /> <PanIcon />
</IconButton> </IconButton>
</Tooltip>
</div> </div>
); );
}; };

View File

@ -6,7 +6,9 @@ import PropTypes from 'prop-types';
import * as appPropTypes from '../../appPropTypes'; import * as appPropTypes from '../../appPropTypes';
import { withRoomContext } from '../../../RoomContext'; import { withRoomContext } from '../../../RoomContext';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { green } from '@material-ui/core/colors';
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import VideocamIcon from '@material-ui/icons/Videocam'; import VideocamIcon from '@material-ui/icons/Videocam';
import VideocamOffIcon from '@material-ui/icons/VideocamOff'; import VideocamOffIcon from '@material-ui/icons/VideocamOff';
import VolumeUpIcon from '@material-ui/icons/VolumeUp'; import VolumeUpIcon from '@material-ui/icons/VolumeUp';
@ -16,6 +18,7 @@ import ScreenOffIcon from '@material-ui/icons/StopScreenShare';
import ExitIcon from '@material-ui/icons/ExitToApp'; import ExitIcon from '@material-ui/icons/ExitToApp';
import EmptyAvatar from '../../../images/avatar-empty.jpeg'; import EmptyAvatar from '../../../images/avatar-empty.jpeg';
import PanIcon from '@material-ui/icons/PanTool'; import PanIcon from '@material-ui/icons/PanTool';
import RecordVoiceOverIcon from '@material-ui/icons/RecordVoiceOver';
const styles = (theme) => const styles = (theme) =>
({ ({
@ -30,7 +33,7 @@ const styles = (theme) =>
{ {
borderRadius : '50%', borderRadius : '50%',
height : '2rem', height : '2rem',
marginTop : theme.spacing(1) marginTop : theme.spacing(0.5)
}, },
peerInfo : peerInfo :
{ {
@ -43,11 +46,16 @@ const styles = (theme) =>
indicators : indicators :
{ {
display : 'flex', display : 'flex',
padding : theme.spacing(1.5) padding : theme.spacing(1)
},
buttons :
{
padding : theme.spacing(1)
}, },
green : green :
{ {
color : 'rgba(0, 153, 0, 1)' color : 'rgba(0, 153, 0, 1)',
marginLeft : theme.spacing(2)
} }
}); });
@ -58,6 +66,7 @@ const ListPeer = (props) =>
const { const {
roomClient, roomClient,
isModerator, isModerator,
spotlight,
peer, peer,
micConsumer, micConsumer,
webcamConsumer, webcamConsumer,
@ -93,12 +102,38 @@ const ListPeer = (props) =>
<div className={classes.peerInfo}> <div className={classes.peerInfo}>
{peer.displayName} {peer.displayName}
</div> </div>
<div className={classes.indicators}>
{ peer.raisedHand && { peer.raisedHand &&
<PanIcon className={classes.green} /> <IconButton
className={classes.buttons}
style={{ color: green[500] }}
disabled={!isModerator || peer.raisedHandInProgress}
onClick={(e) =>
{
e.stopPropagation();
roomClient.lowerPeerHand(peer.id);
}}
>
<PanIcon />
</IconButton>
}
{ spotlight &&
<IconButton
className={classes.buttons}
style={{ color: green[500] }}
disabled
>
<RecordVoiceOverIcon />
</IconButton>
} }
</div>
{ screenConsumer && { screenConsumer &&
<Tooltip
title={intl.formatMessage({
id : 'tooltip.muteScreenSharing',
defaultMessage : 'Mute participant share'
})}
placement='bottom'
>
<IconButton <IconButton
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
id : 'tooltip.muteScreenSharing', id : 'tooltip.muteScreenSharing',
@ -106,6 +141,7 @@ const ListPeer = (props) =>
})} })}
color={screenVisible ? 'primary' : 'secondary'} color={screenVisible ? 'primary' : 'secondary'}
disabled={peer.peerScreenInProgress} disabled={peer.peerScreenInProgress}
className={classes.buttons}
onClick={(e) => onClick={(e) =>
{ {
e.stopPropagation(); e.stopPropagation();
@ -121,7 +157,15 @@ const ListPeer = (props) =>
<ScreenOffIcon /> <ScreenOffIcon />
} }
</IconButton> </IconButton>
</Tooltip>
} }
<Tooltip
title={intl.formatMessage({
id : 'tooltip.muteParticipantVideo',
defaultMessage : 'Mute participant video'
})}
placement='bottom'
>
<IconButton <IconButton
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
id : 'tooltip.muteParticipantVideo', id : 'tooltip.muteParticipantVideo',
@ -129,6 +173,7 @@ const ListPeer = (props) =>
})} })}
color={webcamEnabled ? 'primary' : 'secondary'} color={webcamEnabled ? 'primary' : 'secondary'}
disabled={peer.peerVideoInProgress} disabled={peer.peerVideoInProgress}
className={classes.buttons}
onClick={(e) => onClick={(e) =>
{ {
e.stopPropagation(); e.stopPropagation();
@ -144,6 +189,14 @@ const ListPeer = (props) =>
<VideocamOffIcon /> <VideocamOffIcon />
} }
</IconButton> </IconButton>
</Tooltip>
<Tooltip
title={intl.formatMessage({
id : 'tooltip.muteParticipant',
defaultMessage : 'Mute participant'
})}
placement='bottom'
>
<IconButton <IconButton
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
id : 'tooltip.muteParticipant', id : 'tooltip.muteParticipant',
@ -151,6 +204,7 @@ const ListPeer = (props) =>
})} })}
color={micEnabled ? 'primary' : 'secondary'} color={micEnabled ? 'primary' : 'secondary'}
disabled={peer.peerAudioInProgress} disabled={peer.peerAudioInProgress}
className={classes.buttons}
onClick={(e) => onClick={(e) =>
{ {
e.stopPropagation(); e.stopPropagation();
@ -166,13 +220,22 @@ const ListPeer = (props) =>
<VolumeOffIcon /> <VolumeOffIcon />
} }
</IconButton> </IconButton>
</Tooltip>
{ isModerator && { isModerator &&
<Tooltip
title={intl.formatMessage({
id : 'tooltip.kickParticipant',
defaultMessage : 'Kick out participant'
})}
placement='bottom'
>
<IconButton <IconButton
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
id : 'tooltip.kickParticipant', id : 'tooltip.kickParticipant',
defaultMessage : 'Kick out participant' defaultMessage : 'Kick out participant'
})} })}
disabled={peer.peerKickInProgress} disabled={peer.peerKickInProgress}
className={classes.buttons}
color='secondary' color='secondary'
onClick={(e) => onClick={(e) =>
{ {
@ -183,6 +246,7 @@ const ListPeer = (props) =>
> >
<ExitIcon /> <ExitIcon />
</IconButton> </IconButton>
</Tooltip>
} }
{children} {children}
</div> </div>
@ -194,6 +258,7 @@ ListPeer.propTypes =
roomClient : PropTypes.any.isRequired, roomClient : PropTypes.any.isRequired,
advancedMode : PropTypes.bool, advancedMode : PropTypes.bool,
isModerator : PropTypes.bool, isModerator : PropTypes.bool,
spotlight : PropTypes.bool,
peer : appPropTypes.Peer.isRequired, peer : appPropTypes.Peer.isRequired,
micConsumer : appPropTypes.Consumer, micConsumer : appPropTypes.Consumer,
webcamConsumer : appPropTypes.Consumer, webcamConsumer : appPropTypes.Consumer,

View File

@ -1,13 +1,13 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { import {
passivePeersSelector, participantListSelector
spotlightSortedPeersSelector
} from '../../Selectors'; } from '../../Selectors';
import classNames from 'classnames'; import classnames from 'classnames';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import { withRoomContext } from '../../../RoomContext'; import { withRoomContext } from '../../../RoomContext';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Flipper, Flipped } from 'react-flip-toolkit';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import ListPeer from './ListPeer'; import ListPeer from './ListPeer';
import ListMe from './ListMe'; import ListMe from './ListMe';
@ -76,9 +76,9 @@ class ParticipantList extends React.PureComponent
roomClient, roomClient,
advancedMode, advancedMode,
isModerator, isModerator,
passivePeers, participants,
spotlights,
selectedPeerId, selectedPeerId,
spotlightPeers,
classes classes
} = this.props; } = this.props;
@ -107,50 +107,42 @@ class ParticipantList extends React.PureComponent
<ul className={classes.list}> <ul className={classes.list}>
<li className={classes.listheader}> <li className={classes.listheader}>
<FormattedMessage <FormattedMessage
id='room.spotlights' id='label.participants'
defaultMessage='Participants in Spotlight' defaultMessage='Participants'
/> />
</li> </li>
{ spotlightPeers.map((peer) => ( <Flipper
flipKey={participants}
>
{ participants.map((peer) => (
<Flipped key={peer.id} flipId={peer.id}>
<li <li
key={peer.id} key={peer.id}
className={classNames(classes.listItem, { className={classnames(classes.listItem, {
selected : peer.id === selectedPeerId selected : peer.id === selectedPeerId
})} })}
onClick={() => roomClient.setSelectedPeer(peer.id)} onClick={() => roomClient.setSelectedPeer(peer.id)}
> >
{ spotlights.includes(peer.id) ?
<ListPeer <ListPeer
id={peer.id} id={peer.id}
advancedMode={advancedMode} advancedMode={advancedMode}
isModerator={isModerator} isModerator={isModerator}
spotlight
> >
<Volume small id={peer.id} /> <Volume small id={peer.id} />
</ListPeer> </ListPeer>
</li> :
))}
</ul>
<ul className={classes.list}>
<li className={classes.listheader}>
<FormattedMessage
id='room.passive'
defaultMessage='Passive Participants'
/>
</li>
{ passivePeers.map((peer) => (
<li
key={peer.id}
className={classNames(classes.listItem, {
selected : peer.id === selectedPeerId
})}
onClick={() => roomClient.setSelectedPeer(peer.id)}
>
<ListPeer <ListPeer
id={peer.id} id={peer.id}
advancedMode={advancedMode} advancedMode={advancedMode}
isModerator={isModerator} isModerator={isModerator}
/> />
}
</li> </li>
</Flipped>
))} ))}
</Flipper>
</ul> </ul>
</div> </div>
); );
@ -162,9 +154,9 @@ ParticipantList.propTypes =
roomClient : PropTypes.any.isRequired, roomClient : PropTypes.any.isRequired,
advancedMode : PropTypes.bool, advancedMode : PropTypes.bool,
isModerator : PropTypes.bool, isModerator : PropTypes.bool,
passivePeers : PropTypes.array, participants : PropTypes.array,
spotlights : PropTypes.array,
selectedPeerId : PropTypes.string, selectedPeerId : PropTypes.string,
spotlightPeers : PropTypes.array,
classes : PropTypes.object.isRequired classes : PropTypes.object.isRequired
}; };
@ -174,9 +166,9 @@ const mapStateToProps = (state) =>
isModerator : isModerator :
state.me.roles.some((role) => state.me.roles.some((role) =>
state.room.permissionsFromRoles.MODERATE_ROOM.includes(role)), state.room.permissionsFromRoles.MODERATE_ROOM.includes(role)),
passivePeers : passivePeersSelector(state), participants : participantListSelector(state),
selectedPeerId : state.room.selectedPeerId, spotlights : state.room.spotlights,
spotlightPeers : spotlightSortedPeersSelector(state) selectedPeerId : state.room.selectedPeerId
}; };
}; };

View File

@ -142,6 +142,7 @@ class Room extends React.PureComponent
room, room,
browser, browser,
advancedMode, advancedMode,
showNotifications,
toolAreaOpen, toolAreaOpen,
toggleToolArea, toggleToolArea,
classes, classes,
@ -178,7 +179,9 @@ class Room extends React.PureComponent
<AudioPeers /> <AudioPeers />
{ showNotifications &&
<Notifications /> <Notifications />
}
<CssBaseline /> <CssBaseline />
@ -232,6 +235,7 @@ Room.propTypes =
room : appPropTypes.Room.isRequired, room : appPropTypes.Room.isRequired,
browser : PropTypes.object.isRequired, browser : PropTypes.object.isRequired,
advancedMode : PropTypes.bool.isRequired, advancedMode : PropTypes.bool.isRequired,
showNotifications : PropTypes.bool.isRequired,
toolAreaOpen : PropTypes.bool.isRequired, toolAreaOpen : PropTypes.bool.isRequired,
setToolbarsVisible : PropTypes.func.isRequired, setToolbarsVisible : PropTypes.func.isRequired,
toggleToolArea : PropTypes.func.isRequired, toggleToolArea : PropTypes.func.isRequired,
@ -244,6 +248,7 @@ const mapStateToProps = (state) =>
room : state.room, room : state.room,
browser : state.me.browser, browser : state.me.browser,
advancedMode : state.settings.advancedMode, advancedMode : state.settings.advancedMode,
showNotifications : state.settings.showNotifications,
toolAreaOpen : state.toolarea.toolAreaOpen toolAreaOpen : state.toolarea.toolAreaOpen
}); });
@ -270,6 +275,7 @@ export default connect(
prev.room === next.room && prev.room === next.room &&
prev.me.browser === next.me.browser && prev.me.browser === next.me.browser &&
prev.settings.advancedMode === next.settings.advancedMode && prev.settings.advancedMode === next.settings.advancedMode &&
prev.settings.showNotifications === next.settings.showNotifications &&
prev.toolarea.toolAreaOpen === next.toolarea.toolAreaOpen prev.toolarea.toolAreaOpen === next.toolarea.toolAreaOpen
); );
} }

View File

@ -12,7 +12,8 @@ const peersKeySelector = createSelector(
peersSelector, peersSelector,
(peers) => Object.keys(peers) (peers) => Object.keys(peers)
); );
const peersValueSelector = createSelector(
export const peersValueSelector = createSelector(
peersSelector, peersSelector,
(peers) => Object.values(peers) (peers) => Object.values(peers)
); );
@ -113,10 +114,33 @@ export const spotlightPeersSelector = createSelector(
export const spotlightSortedPeersSelector = createSelector( export const spotlightSortedPeersSelector = createSelector(
spotlightsSelector, spotlightsSelector,
peersValueSelector, peersValueSelector,
(spotlights, peers) => peers.filter((peer) => spotlights.includes(peer.id)) (spotlights, peers) =>
peers.filter((peer) => spotlights.includes(peer.id) && !peer.raisedHand)
.sort((a, b) => String(a.displayName || '').localeCompare(String(b.displayName || ''))) .sort((a, b) => String(a.displayName || '').localeCompare(String(b.displayName || '')))
); );
const raisedHandSortedPeers = createSelector(
peersValueSelector,
(peers) => peers.filter((peer) => peer.raisedHand)
.sort((a, b) => a.raisedHandTimestamp - b.raisedHandTimestamp)
);
const peersSortedSelector = createSelector(
spotlightsSelector,
peersValueSelector,
(spotlights, peers) =>
peers.filter((peer) => !spotlights.includes(peer.id) && !peer.raisedHand)
.sort((a, b) => String(a.displayName || '').localeCompare(String(b.displayName || '')))
);
export const participantListSelector = createSelector(
raisedHandSortedPeers,
spotlightSortedPeersSelector,
peersSortedSelector,
(raisedHands, spotlights, peers) =>
[ ...raisedHands, ...spotlights, ...peers ]
);
export const peersLengthSelector = createSelector( export const peersLengthSelector = createSelector(
peersSelector, peersSelector,
(peers) => Object.values(peers).length (peers) => Object.values(peers).length

View File

@ -30,6 +30,7 @@ const AppearenceSettings = ({
settings, settings,
onTogglePermanentTopBar, onTogglePermanentTopBar,
onToggleHiddenControls, onToggleHiddenControls,
onToggleShowNotifications,
handleChangeMode, handleChangeMode,
classes classes
}) => }) =>
@ -101,6 +102,14 @@ const AppearenceSettings = ({
defaultMessage : 'Hidden media controls' defaultMessage : 'Hidden media controls'
})} })}
/> />
<FormControlLabel
className={classes.setting}
control={<Checkbox checked={settings.showNotifications} onChange={onToggleShowNotifications} value='showNotifications' />}
label={intl.formatMessage({
id : 'settings.showNotifications',
defaultMessage : 'Show notifications'
})}
/>
</React.Fragment> </React.Fragment>
); );
}; };
@ -111,6 +120,7 @@ AppearenceSettings.propTypes =
settings : PropTypes.object.isRequired, settings : PropTypes.object.isRequired,
onTogglePermanentTopBar : PropTypes.func.isRequired, onTogglePermanentTopBar : PropTypes.func.isRequired,
onToggleHiddenControls : PropTypes.func.isRequired, onToggleHiddenControls : PropTypes.func.isRequired,
onToggleShowNotifications : PropTypes.func.isRequired,
handleChangeMode : PropTypes.func.isRequired, handleChangeMode : PropTypes.func.isRequired,
classes : PropTypes.object.isRequired classes : PropTypes.object.isRequired
}; };
@ -124,6 +134,7 @@ const mapStateToProps = (state) =>
const mapDispatchToProps = { const mapDispatchToProps = {
onTogglePermanentTopBar : settingsActions.togglePermanentTopBar, onTogglePermanentTopBar : settingsActions.togglePermanentTopBar,
onToggleHiddenControls : settingsActions.toggleHiddenControls, onToggleHiddenControls : settingsActions.toggleHiddenControls,
onToggleShowNotifications : settingsActions.toggleShowNotifications,
handleChangeMode : roomActions.setDisplayMode handleChangeMode : roomActions.setDisplayMode
}; };

View File

@ -3,12 +3,15 @@ import { connect } from 'react-redux';
import * as appPropTypes from '../appPropTypes'; import * as appPropTypes from '../appPropTypes';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import { withRoomContext } from '../../RoomContext'; import { withRoomContext } from '../../RoomContext';
import * as settingsActions from '../../actions/settingsActions';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useIntl, FormattedMessage } from 'react-intl'; import { useIntl, FormattedMessage } from 'react-intl';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import FormHelperText from '@material-ui/core/FormHelperText'; import FormHelperText from '@material-ui/core/FormHelperText';
import FormControl from '@material-ui/core/FormControl'; import FormControl from '@material-ui/core/FormControl';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import Checkbox from '@material-ui/core/Checkbox';
const styles = (theme) => const styles = (theme) =>
({ ({
@ -23,6 +26,9 @@ const styles = (theme) =>
}); });
const MediaSettings = ({ const MediaSettings = ({
setEchoCancellation,
setAutoGainControl,
setNoiseSuppression,
roomClient, roomClient,
me, me,
settings, settings,
@ -247,6 +253,51 @@ const MediaSettings = ({
/> />
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
<FormControlLabel
className={classes.setting}
control={
<Checkbox checked={settings.echoCancellation} onChange={
(event) =>
{
setEchoCancellation(event.target.checked);
roomClient.changeAudioDevice(settings.selectedAudioDevice);
}}
/>}
label={intl.formatMessage({
id : 'settings.echoCancellation',
defaultMessage : 'Echo Cancellation'
})}
/>
<FormControlLabel
className={classes.setting}
control={
<Checkbox checked={settings.autoGainControl} onChange={
(event) =>
{
setAutoGainControl(event.target.checked);
roomClient.changeAudioDevice(settings.selectedAudioDevice);
}}
/>}
label={intl.formatMessage({
id : 'settings.autoGainControl',
defaultMessage : 'Auto Gain Control'
})}
/>
<FormControlLabel
className={classes.setting}
control={
<Checkbox checked={settings.noiseSuppression} onChange={
(event) =>
{
setNoiseSuppression(event.target.checked);
roomClient.changeAudioDevice(settings.selectedAudioDevice);
}}
/>}
label={intl.formatMessage({
id : 'settings.noiseSuppression',
defaultMessage : 'Noise Suppression'
})}
/>
</form> </form>
</React.Fragment> </React.Fragment>
); );
@ -255,6 +306,9 @@ const MediaSettings = ({
MediaSettings.propTypes = MediaSettings.propTypes =
{ {
roomClient : PropTypes.any.isRequired, roomClient : PropTypes.any.isRequired,
setEchoCancellation : PropTypes.func.isRequired,
setAutoGainControl : PropTypes.func.isRequired,
setNoiseSuppression : PropTypes.func.isRequired,
me : appPropTypes.Me.isRequired, me : appPropTypes.Me.isRequired,
settings : PropTypes.object.isRequired, settings : PropTypes.object.isRequired,
classes : PropTypes.object.isRequired classes : PropTypes.object.isRequired
@ -268,9 +322,15 @@ const mapStateToProps = (state) =>
}; };
}; };
const mapDispatchToProps = {
setEchoCancellation : settingsActions.setEchoCancellation,
setAutoGainControl : settingsActions.toggleAutoGainControl,
setNoiseSuppression : settingsActions.toggleNoiseSuppression
};
export default withRoomContext(connect( export default withRoomContext(connect(
mapStateToProps, mapStateToProps,
null, mapDispatchToProps,
null, null,
{ {
areStatesEqual : (next, prev) => areStatesEqual : (next, prev) =>

View File

@ -4,13 +4,12 @@ import classnames from 'classnames';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import EditableInput from '../Controls/EditableInput'; import EditableInput from '../Controls/EditableInput';
import Logger from '../../Logger'; import Logger from '../../Logger';
import { green, yellow, orange, red } from '@material-ui/core/colors'; import { yellow, orange, red } from '@material-ui/core/colors';
import SignalCellularOffIcon from '@material-ui/icons/SignalCellularOff'; import SignalCellularOffIcon from '@material-ui/icons/SignalCellularOff';
import SignalCellular0BarIcon from '@material-ui/icons/SignalCellular0Bar'; import SignalCellular0BarIcon from '@material-ui/icons/SignalCellular0Bar';
import SignalCellular1BarIcon from '@material-ui/icons/SignalCellular1Bar'; import SignalCellular1BarIcon from '@material-ui/icons/SignalCellular1Bar';
import SignalCellular2BarIcon from '@material-ui/icons/SignalCellular2Bar'; import SignalCellular2BarIcon from '@material-ui/icons/SignalCellular2Bar';
import SignalCellular3BarIcon from '@material-ui/icons/SignalCellular3Bar'; import SignalCellular3BarIcon from '@material-ui/icons/SignalCellular3Bar';
import SignalCellularAltIcon from '@material-ui/icons/SignalCellularAlt';
const logger = new Logger('VideoView'); const logger = new Logger('VideoView');
@ -162,8 +161,6 @@ class VideoView extends React.PureComponent
videoMultiLayer, videoMultiLayer,
audioScore, audioScore,
videoScore, videoScore,
// consumerSpatialLayers,
// consumerTemporalLayers,
consumerCurrentSpatialLayer, consumerCurrentSpatialLayer,
consumerCurrentTemporalLayer, consumerCurrentTemporalLayer,
consumerPreferredSpatialLayer, consumerPreferredSpatialLayer,
@ -215,16 +212,16 @@ class VideoView extends React.PureComponent
case 7: case 7:
case 8: case 8:
case 9:
{ {
quality = <SignalCellular3BarIcon style={{ color: yellow[500] }}/>; quality = <SignalCellular3BarIcon style={{ color: yellow[500] }}/>;
break; break;
} }
case 9:
case 10: case 10:
{ {
quality = <SignalCellularAltIcon style={{ color: green[500] }}/>; quality = null;
break; break;
} }

View File

@ -27,6 +27,12 @@ const peer = (state = {}, action) =>
raisedHandTimestamp : action.payload.raisedHandTimestamp raisedHandTimestamp : action.payload.raisedHandTimestamp
}; };
case 'SET_PEER_RAISED_HAND_IN_PROGRESS':
return {
...state,
raisedHandInProgress : action.payload.flag
};
case 'ADD_CONSUMER': case 'ADD_CONSUMER':
{ {
const consumers = [ ...state.consumers, action.payload.consumer.id ]; const consumers = [ ...state.consumers, action.payload.consumer.id ];
@ -91,6 +97,7 @@ const peers = (state = {}, action) =>
case 'SET_PEER_AUDIO_IN_PROGRESS': case 'SET_PEER_AUDIO_IN_PROGRESS':
case 'SET_PEER_SCREEN_IN_PROGRESS': case 'SET_PEER_SCREEN_IN_PROGRESS':
case 'SET_PEER_RAISED_HAND': case 'SET_PEER_RAISED_HAND':
case 'SET_PEER_RAISED_HAND_IN_PROGRESS':
case 'SET_PEER_PICTURE': case 'SET_PEER_PICTURE':
case 'ADD_CONSUMER': case 'ADD_CONSUMER':
case 'ADD_PEER_ROLE': case 'ADD_PEER_ROLE':

View File

@ -4,12 +4,21 @@ const initialState =
selectedWebcam : null, selectedWebcam : null,
selectedAudioDevice : null, selectedAudioDevice : null,
advancedMode : false, advancedMode : false,
sampleRate : 48000,
channelCount : 1,
volume : 1.0,
autoGainControl : true,
echoCancellation : true,
noiseSuppression : true,
sampleSize : 16,
// low, medium, high, veryhigh, ultra // low, medium, high, veryhigh, ultra
resolution : window.config.defaultResolution || 'medium', resolution : window.config.defaultResolution || 'medium',
lastN : 4, lastN : 4,
permanentTopBar : true, permanentTopBar : true,
hiddenControls : false, hiddenControls : false,
notificationSounds : true showNotifications : true,
notificationSounds : true,
...window.config.defaultAudio
}; };
const settings = (state = initialState, action) => const settings = (state = initialState, action) =>
@ -45,6 +54,83 @@ const settings = (state = initialState, action) =>
return { ...state, advancedMode }; return { ...state, advancedMode };
} }
case 'SET_SAMPLE_RATE':
{
const { sampleRate } = action.payload;
return { ...state, sampleRate };
}
case 'SET_CHANNEL_COUNT':
{
const { channelCount } = action.payload;
return { ...state, channelCount };
}
case 'SET_VOLUME':
{
const { volume } = action.payload;
return { ...state, volume };
}
case 'SET_AUTO_GAIN_CONTROL':
{
const { autoGainControl } = action.payload;
return { ...state, autoGainControl };
}
case 'SET_ECHO_CANCELLATION':
{
const { echoCancellation } = action.payload;
return { ...state, echoCancellation };
}
case 'SET_NOISE_SUPPRESSION':
{
const { noiseSuppression } = action.payload;
return { ...state, noiseSuppression };
}
case 'SET_DEFAULT_AUDIO':
{
const { audio } = action.payload;
return { ...state, audio };
}
case 'TOGGLE_AUTO_GAIN_CONTROL':
{
const autoGainControl = !state.autoGainControl;
return { ...state, autoGainControl };
}
case 'TOGGLE_ECHO_CANCELLATION':
{
const echoCancellation = !state.echoCancellation;
return { ...state, echoCancellation };
}
case 'TOGGLE_NOISE_SUPPRESSION':
{
const noiseSuppression = !state.noiseSuppression;
return { ...state, noiseSuppression };
}
case 'SET_SAMPLE_SIZE':
{
const { sampleSize } = action.payload;
return { ...state, sampleSize };
}
case 'SET_LAST_N': case 'SET_LAST_N':
{ {
const { lastN } = action.payload; const { lastN } = action.payload;
@ -73,6 +159,13 @@ const settings = (state = initialState, action) =>
return { ...state, notificationSounds }; return { ...state, notificationSounds };
} }
case 'TOGGLE_SHOW_NOTIFICATIONS':
{
const showNotifications = !state.showNotifications;
return { ...state, showNotifications };
}
case 'SET_VIDEO_RESOLUTION': case 'SET_VIDEO_RESOLUTION':
{ {
const { resolution } = action.payload; const { resolution } = action.payload;

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "房间名称", "label.roomName": "房间名称",
"label.chooseRoomButton": "继续", "label.chooseRoomButton": "继续",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "设置", "settings.settings": "设置",
"settings.camera": "视频设备", "settings.camera": "视频设备",
@ -128,6 +130,7 @@
"settings.lastn": "可见视频数量", "settings.lastn": "可见视频数量",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "无法保存文件", "filesharing.saveFileError": "无法保存文件",
"filesharing.startingFileShare": "正在尝试共享文件", "filesharing.startingFileShare": "正在尝试共享文件",

View File

@ -79,6 +79,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Jméno místnosti", "label.roomName": "Jméno místnosti",
"label.chooseRoomButton": "Pokračovat", "label.chooseRoomButton": "Pokračovat",
@ -108,6 +109,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Nastavení", "settings.settings": "Nastavení",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -127,6 +129,7 @@
"settings.lastn": null, "settings.lastn": null,
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Není možné uložit soubor", "filesharing.saveFileError": "Není možné uložit soubor",
"filesharing.startingFileShare": "Pokouším se sdílet soubor", "filesharing.startingFileShare": "Pokouším se sdílet soubor",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Name des Raums", "label.roomName": "Name des Raums",
"label.chooseRoomButton": "Weiter", "label.chooseRoomButton": "Weiter",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Einstellungen", "settings.settings": "Einstellungen",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -128,6 +130,7 @@
"settings.lastn": "Anzahl der sichtbaren Videos", "settings.lastn": "Anzahl der sichtbaren Videos",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Fehler beim Speichern der Datei", "filesharing.saveFileError": "Fehler beim Speichern der Datei",
"filesharing.startingFileShare": "Starte Teilen der Datei", "filesharing.startingFileShare": "Starte Teilen der Datei",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Værelsesnavn", "label.roomName": "Værelsesnavn",
"label.chooseRoomButton": "Fortsæt", "label.chooseRoomButton": "Fortsæt",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Indstillinger", "settings.settings": "Indstillinger",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -128,6 +130,7 @@
"settings.lastn": "Antal synlige videoer", "settings.lastn": "Antal synlige videoer",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Kan ikke gemme fil", "filesharing.saveFileError": "Kan ikke gemme fil",
"filesharing.startingFileShare": "Forsøger at dele filen", "filesharing.startingFileShare": "Forsøger at dele filen",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Όνομα δωματίου", "label.roomName": "Όνομα δωματίου",
"label.chooseRoomButton": "Συνέχεια", "label.chooseRoomButton": "Συνέχεια",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Ρυθμίσεις", "settings.settings": "Ρυθμίσεις",
"settings.camera": "Κάμερα", "settings.camera": "Κάμερα",
@ -128,6 +130,7 @@
"settings.lastn": "Αριθμός ορατών βίντεο", "settings.lastn": "Αριθμός ορατών βίντεο",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Αδυναμία αποθήκευσης του αρχείου", "filesharing.saveFileError": "Αδυναμία αποθήκευσης του αρχείου",
"filesharing.startingFileShare": "Προσπάθεια διαμοιρασμού αρχείου", "filesharing.startingFileShare": "Προσπάθεια διαμοιρασμού αρχείου",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": "Mute participant", "tooltip.muteParticipant": "Mute participant",
"tooltip.muteParticipantVideo": "Mute participant video", "tooltip.muteParticipantVideo": "Mute participant video",
"tooltip.raisedHand": "Raise hand", "tooltip.raisedHand": "Raise hand",
"tooltip.muteScreenSharing": "Mute participant share",
"label.roomName": "Room name", "label.roomName": "Room name",
"label.chooseRoomButton": "Continue", "label.chooseRoomButton": "Continue",
@ -109,6 +110,7 @@
"label.advanced": "Advanced", "label.advanced": "Advanced",
"label.addVideo": "Add video", "label.addVideo": "Add video",
"label.promoteAllPeers": "Promote all", "label.promoteAllPeers": "Promote all",
"label.moreActions": "More actions",
"settings.settings": "Settings", "settings.settings": "Settings",
"settings.camera": "Camera", "settings.camera": "Camera",
@ -128,6 +130,7 @@
"settings.lastn": "Number of visible videos", "settings.lastn": "Number of visible videos",
"settings.hiddenControls": "Hidden media controls", "settings.hiddenControls": "Hidden media controls",
"settings.notificationSounds": "Notification sounds", "settings.notificationSounds": "Notification sounds",
"settings.showNotifications": "Show notifications",
"filesharing.saveFileError": "Unable to save file", "filesharing.saveFileError": "Unable to save file",
"filesharing.startingFileShare": "Attempting to share file", "filesharing.startingFileShare": "Attempting to share file",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Nombre de la sala", "label.roomName": "Nombre de la sala",
"label.chooseRoomButton": "Continuar", "label.chooseRoomButton": "Continuar",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Ajustes", "settings.settings": "Ajustes",
"settings.camera": "Cámara", "settings.camera": "Cámara",
@ -128,6 +130,7 @@
"settings.lastn": "Cantidad de videos visibles", "settings.lastn": "Cantidad de videos visibles",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "No ha sido posible guardar el fichero", "filesharing.saveFileError": "No ha sido posible guardar el fichero",
"filesharing.startingFileShare": "Intentando compartir el fichero", "filesharing.startingFileShare": "Intentando compartir el fichero",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Nom de la salle", "label.roomName": "Nom de la salle",
"label.chooseRoomButton": "Continuer", "label.chooseRoomButton": "Continuer",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Paramètres", "settings.settings": "Paramètres",
"settings.camera": "Caméra", "settings.camera": "Caméra",
@ -128,6 +130,7 @@
"settings.lastn": "Nombre de vidéos visibles", "settings.lastn": "Nombre de vidéos visibles",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Impossible d'enregistrer le fichier", "filesharing.saveFileError": "Impossible d'enregistrer le fichier",
"filesharing.startingFileShare": "Début du transfert de fichier", "filesharing.startingFileShare": "Début du transfert de fichier",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": "Utišaj sudionika", "tooltip.muteParticipant": "Utišaj sudionika",
"tooltip.muteParticipantVideo": "Ne primaj video sudionika", "tooltip.muteParticipantVideo": "Ne primaj video sudionika",
"tooltip.raisedHand": "Podigni ruku", "tooltip.raisedHand": "Podigni ruku",
"tooltip.muteScreenSharing": null,
"label.roomName": "Naziv sobe", "label.roomName": "Naziv sobe",
"label.chooseRoomButton": "Nastavi", "label.chooseRoomButton": "Nastavi",
@ -109,6 +110,7 @@
"label.advanced": "Napredno", "label.advanced": "Napredno",
"label.addVideo": "Dodaj video", "label.addVideo": "Dodaj video",
"label.promoteAllPeers": "Promoviraj sve", "label.promoteAllPeers": "Promoviraj sve",
"label.moreActions": null,
"settings.settings": "Postavke", "settings.settings": "Postavke",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -128,6 +130,7 @@
"settings.lastn": "Broj vidljivih videozapisa", "settings.lastn": "Broj vidljivih videozapisa",
"settings.hiddenControls": "Skrivene kontrole medija", "settings.hiddenControls": "Skrivene kontrole medija",
"settings.notificationSounds": "Zvuk obavijesti", "settings.notificationSounds": "Zvuk obavijesti",
"settings.showNotifications": null,
"filesharing.saveFileError": "Nije moguće spremiti datoteku", "filesharing.saveFileError": "Nije moguće spremiti datoteku",
"filesharing.startingFileShare": "Pokušaj dijeljenja datoteke", "filesharing.startingFileShare": "Pokušaj dijeljenja datoteke",

View File

@ -1,24 +1,24 @@
{ {
"socket.disconnected": "A kapcsolat lebomlott", "socket.disconnected": "A kapcsolat lebomlott",
"socket.reconnecting": "A kapcsolat lebomlott, újrapróbálkozás", "socket.reconnecting": "A kapcsolat lebomlott, újrapróbálkozás",
"socket.reconnected": "Sikeres újarkapcsolódás", "socket.reconnected": "Sikeres újrakapcsolódás",
"socket.requestError": "Sikertelen szerver lekérés", "socket.requestError": "Sikertelen szerver lekérés",
"room.chooseRoom": "Válaszd ki a konferenciaszobát", "room.chooseRoom": "Válaszd ki a konferenciaszobát",
"room.cookieConsent": "Ez a weblap a felhasználói élmény fokozása miatt sütiket használ", "room.cookieConsent": "Ez a weblap a felhasználói élmény fokozása miatt sütiket használ",
"room.consentUnderstand": "Megértettem", "room.consentUnderstand": "Megértettem",
"room.joined": "Csatlakozátál a konferenciához", "room.joined": "Csatlakoztál a konferenciához",
"room.cantJoin": "Sikertelen csatlakozás a konferenciához", "room.cantJoin": "Sikertelen csatlakozás a konferenciához",
"room.youLocked": "A konferenciába való belépés letiltva", "room.youLocked": "A konferenciába való belépés letiltva",
"room.cantLock": "Sikertelen a konferenciaba való belépés letiltása", "room.cantLock": "Sikertelen a konferenciába való belépés letiltása",
"room.youUnLocked": "A konferenciába való belépés engedélyezve", "room.youUnLocked": "A konferenciába való belépés engedélyezve",
"room.cantUnLock": "Sikertelen a konferenciába való belépés engedélyezése", "room.cantUnLock": "Sikertelen a konferenciába való belépés engedélyezése",
"room.locked": "A konferenciába való belépés letiltva", "room.locked": "A konferenciába való belépés letiltva",
"room.unlocked": "A konferenciába való belépés engedélyezve", "room.unlocked": "A konferenciába való belépés engedélyezve",
"room.newLobbyPeer": "Új részvevő lépett be a konferencia előszobájába", "room.newLobbyPeer": "Új részvevő lépett be a konferencia előszobájába",
"room.lobbyPeerLeft": "A konferencia előszobájából a részvevő távozott", "room.lobbyPeerLeft": "A konferencia előszobájából a részvevő távozott",
"room.lobbyPeerChangedDisplayName": "Az előszobai résztvevő meváltoztatta a nevét: {displayName}", "room.lobbyPeerChangedDisplayName": "Az előszobai résztvevő megváltoztatta a nevét: {displayName}",
"room.lobbyPeerChangedPicture": "Az előszobai résztvevő meváltoztatta a képét", "room.lobbyPeerChangedPicture": "Az előszobai résztvevő megváltoztatta a képét",
"room.setAccessCode": "A konferencia hozzáférési kódja megváltozott", "room.setAccessCode": "A konferencia hozzáférési kódja megváltozott",
"room.accessCodeOn": "A konferencia hozzáférési kódja aktiválva", "room.accessCodeOn": "A konferencia hozzáférési kódja aktiválva",
"room.accessCodeOff": "A konferencia hozzáférési kódka deaktiválva", "room.accessCodeOff": "A konferencia hozzáférési kódka deaktiválva",
@ -39,7 +39,7 @@
"room.audioOnly": "csak Hang", "room.audioOnly": "csak Hang",
"room.audioVideo": "Hang és Videó", "room.audioVideo": "Hang és Videó",
"room.youAreReady": "Ok, kész vagy", "room.youAreReady": "Ok, kész vagy",
"room.emptyRequireLogin": "A konferencia üres! Be kell lépned a konferecnia elkezdéséhez, vagy várnod kell amíg a házigazda becsatlakozik.", "room.emptyRequireLogin": "A konferencia üres! Be kell lépned a konferencia elkezdéséhez, vagy várnod kell amíg a házigazda becsatlakozik.",
"room.locketWait": "Az automatikus belépés tiltva van - Várj amíg valaki beenged ...", "room.locketWait": "Az automatikus belépés tiltva van - Várj amíg valaki beenged ...",
"room.lobbyAdministration": "Előszoba adminisztráció", "room.lobbyAdministration": "Előszoba adminisztráció",
"room.peersInLobby": "Résztvevők az előszobában", "room.peersInLobby": "Résztvevők az előszobában",
@ -54,7 +54,7 @@
"room.closeMeeting": "Konferencia lebontása", "room.closeMeeting": "Konferencia lebontása",
"room.clearChat": "Chat történelem kiürítése", "room.clearChat": "Chat történelem kiürítése",
"room.clearFileSharing": "File megosztás kiürítése", "room.clearFileSharing": "File megosztás kiürítése",
"room.speechUnsupported": "A böngésződ nem támogatja a hangszint", "room.speechUnsupported": "A böngésződ nem támogatja a hangfelismerést",
"room.moderatoractions": "Moderátor funkciók", "room.moderatoractions": "Moderátor funkciók",
"room.raisedHand": "{displayName} jelentkezik", "room.raisedHand": "{displayName} jelentkezik",
"room.loweredHand": "{displayName} leeresztette a kezét", "room.loweredHand": "{displayName} leeresztette a kezét",
@ -68,7 +68,7 @@
"tooltip.login": "Belépés", "tooltip.login": "Belépés",
"tooltip.logout": "Kilépés", "tooltip.logout": "Kilépés",
"tooltip.admitFromLobby": "Beenegdem az előszobából", "tooltip.admitFromLobby": "Beengedem az előszobából",
"tooltip.lockRoom": "A konferenciába való belépés letiltása", "tooltip.lockRoom": "A konferenciába való belépés letiltása",
"tooltip.unLockRoom": "konferenciába való belépés engedélyezése", "tooltip.unLockRoom": "konferenciába való belépés engedélyezése",
"tooltip.enterFullscreen": "Teljes képernyős mód", "tooltip.enterFullscreen": "Teljes képernyős mód",
@ -78,8 +78,9 @@
"tooltip.participants": "Résztvevők", "tooltip.participants": "Résztvevők",
"tooltip.kickParticipant": "Résztvevő kirúgása", "tooltip.kickParticipant": "Résztvevő kirúgása",
"tooltip.muteParticipant": "Résztvevő némítása", "tooltip.muteParticipant": "Résztvevő némítása",
"tooltip.muteParticipantVideo": "Résztvevő video némítása", "tooltip.muteParticipantVideo": "Résztvevő videóstreamének némítása",
"tooltip.raisedHand": "Jelentkezés", "tooltip.raisedHand": "Jelentkezés",
"tooltip.muteScreenSharing": "Képernyőmegosztás szüneteltetése",
"label.roomName": "Konferencia", "label.roomName": "Konferencia",
"label.chooseRoomButton": "Tovább", "label.chooseRoomButton": "Tovább",
@ -109,6 +110,7 @@
"label.advanced": "Részletek", "label.advanced": "Részletek",
"label.addVideo": "Videó hozzáadása", "label.addVideo": "Videó hozzáadása",
"label.promoteAllPeers": "Mindenkit beengedek", "label.promoteAllPeers": "Mindenkit beengedek",
"label.moreActions": "További műveletek",
"settings.settings": "Beállítások", "settings.settings": "Beállítások",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -127,12 +129,13 @@
"settings.permanentTopBar": "Állandó felső sáv", "settings.permanentTopBar": "Állandó felső sáv",
"settings.lastn": "A látható videók száma", "settings.lastn": "A látható videók száma",
"settings.hiddenControls": "Média Gombok automatikus elrejtése", "settings.hiddenControls": "Média Gombok automatikus elrejtése",
"settings.notificationSounds": "Értesítések hangjelzjéssel", "settings.notificationSounds": "Értesítések hangjelzéssel",
"settings.showNotifications": null,
"filesharing.saveFileError": "A file-t nem sikerült elmenteni", "filesharing.saveFileError": "A file-t nem sikerült elmenteni",
"filesharing.startingFileShare": "Fájl megosztása", "filesharing.startingFileShare": "Fájl megosztása",
"filesharing.successfulFileShare": "A fájl sikeresen megosztva", "filesharing.successfulFileShare": "A fájl sikeresen megosztva",
"filesharing.unableToShare": "Sikereteln fájl megosztás", "filesharing.unableToShare": "Sikertelen fájl megosztás",
"filesharing.error": "Hiba a fájlmegosztás során", "filesharing.error": "Hiba a fájlmegosztás során",
"filesharing.finished": "A fájl letöltés befejeződött", "filesharing.finished": "A fájl letöltés befejeződött",
"filesharing.save": "Mentés", "filesharing.save": "Mentés",
@ -142,7 +145,7 @@
"devices.devicesChanged": "Az eszközei megváltoztak, konfiguráld őket be a beállítások menüben", "devices.devicesChanged": "Az eszközei megváltoztak, konfiguráld őket be a beállítások menüben",
"device.audioUnsupported": "A hnag nem támogatott", "device.audioUnsupported": "A hang nem támogatott",
"device.activateAudio": "Hang aktiválása", "device.activateAudio": "Hang aktiválása",
"device.muteAudio": "Hang némítása", "device.muteAudio": "Hang némítása",
"device.unMuteAudio": "Hang némítás kikapcsolása", "device.unMuteAudio": "Hang némítás kikapcsolása",
@ -153,9 +156,9 @@
"device.screenSharingUnsupported": "A képernyő megosztás nem támogatott", "device.screenSharingUnsupported": "A képernyő megosztás nem támogatott",
"device.startScreenSharing": "Képernyőmegosztás indítása", "device.startScreenSharing": "Képernyőmegosztás indítása",
"device.stopScreenSharing": "Képernyőmegosztás leáłłítása", "device.stopScreenSharing": "Képernyőmegosztás leállítása",
"devices.microphoneDisconnected": "Microphone kapcsolat bontva", "devices.microphoneDisconnected": "Mikrofon kapcsolat bontva",
"devices.microphoneError": "Hiba történt a mikrofon hangeszköz elérése közben", "devices.microphoneError": "Hiba történt a mikrofon hangeszköz elérése közben",
"devices.microphoneMute": "A mikrofon némítva lett", "devices.microphoneMute": "A mikrofon némítva lett",
"devices.microphoneUnMute": "A mikrofon némítása ki lett kapocsolva", "devices.microphoneUnMute": "A mikrofon némítása ki lett kapocsolva",

View File

@ -49,22 +49,22 @@
"room.spotlights": "Partecipanti in Evidenza", "room.spotlights": "Partecipanti in Evidenza",
"room.passive": "Participanti Passivi", "room.passive": "Participanti Passivi",
"room.videoPaused": "Il video è in pausa", "room.videoPaused": "Il video è in pausa",
"room.muteAll": null, "room.muteAll": "Muta tutti",
"room.stopAllVideo": null, "room.stopAllVideo": "Ferma tutti i video",
"room.closeMeeting": null, "room.closeMeeting": "Termina meeting",
"room.clearChat": null, "room.clearChat": "Pulisci chat",
"room.clearFileSharing": null, "room.clearFileSharing": "Pulisci file sharing",
"room.speechUnsupported": null, "room.speechUnsupported": "Il tuo browser non supporta il riconoscimento vocale",
"room.moderatoractions": null, "room.moderatoractions": "Azioni moderatore",
"room.raisedHand": null, "room.raisedHand": "{displayName} ha alzato la mano",
"room.loweredHand": null, "room.loweredHand": "{displayName} ha abbassato la mano",
"room.extraVideo": null, "room.extraVideo": "Video extra",
"room.overRoomLimit": null, "room.overRoomLimit": null,
"me.mutedPTT": null, "me.mutedPTT": "Sei mutato, tieni premuto SPAZIO per parlare",
"roles.gotRole": null, "roles.gotRole": "Hai ottenuto il ruolo: {role}",
"roles.lostRole": null, "roles.lostRole": "Hai perso il ruolo: {role}",
"tooltip.login": "Log in", "tooltip.login": "Log in",
"tooltip.logout": "Log out", "tooltip.logout": "Log out",
@ -76,9 +76,10 @@
"tooltip.lobby": "Mostra lobby", "tooltip.lobby": "Mostra lobby",
"tooltip.settings": "Mostra impostazioni", "tooltip.settings": "Mostra impostazioni",
"tooltip.participants": "Mostra partecipanti", "tooltip.participants": "Mostra partecipanti",
"tooltip.muteParticipant": null, "tooltip.muteParticipant": "Muta partecipante",
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": "Ferma video partecipante",
"tooltip.raisedHand": null, "tooltip.raisedHand": "Mano alzata",
"tooltip.muteScreenSharing": null,
"label.roomName": "Nome della stanza", "label.roomName": "Nome della stanza",
"label.chooseRoomButton": "Continua", "label.chooseRoomButton": "Continua",
@ -103,11 +104,12 @@
"label.veryHigh": "Molto alta (FHD)", "label.veryHigh": "Molto alta (FHD)",
"label.ultra": "Ultra (UHD)", "label.ultra": "Ultra (UHD)",
"label.close": "Chiudi", "label.close": "Chiudi",
"label.media": null, "label.media": "Media",
"label.appearence": null, "label.appearence": "Aspetto",
"label.advanced": null, "label.advanced": "Avanzate",
"label.addVideo": null, "label.addVideo": "Aggiungi video",
"label.promoteAllPeers": null, "label.promoteAllPeers": "Promuovi tutti",
"label.moreActions": null,
"settings.settings": "Impostazioni", "settings.settings": "Impostazioni",
"settings.camera": "Videocamera", "settings.camera": "Videocamera",
@ -125,8 +127,9 @@
"settings.advancedMode": "Modalità avanzata", "settings.advancedMode": "Modalità avanzata",
"settings.permanentTopBar": "Barra superiore permanente", "settings.permanentTopBar": "Barra superiore permanente",
"settings.lastn": "Numero di video visibili", "settings.lastn": "Numero di video visibili",
"settings.hiddenControls": null, "settings.hiddenControls": "Controlli media nascosti",
"settings.notificationSounds": null, "settings.notificationSounds": "Suoni di notifica",
"settings.showNotifications": null,
"filesharing.saveFileError": "Impossibile salvare file", "filesharing.saveFileError": "Impossibile salvare file",
"filesharing.startingFileShare": "Tentativo di condivisione file", "filesharing.startingFileShare": "Tentativo di condivisione file",
@ -168,8 +171,8 @@
"devices.cameraDisconnected": "Videocamera scollegata", "devices.cameraDisconnected": "Videocamera scollegata",
"devices.cameraError": "Errore con l'accesso alla videocamera", "devices.cameraError": "Errore con l'accesso alla videocamera",
"moderator.clearChat": null, "moderator.clearChat": "Il moderatore ha pulito la chat",
"moderator.clearFiles": null, "moderator.clearFiles": "Il moderatore ha pulito i file",
"moderator.muteAudio": null, "moderator.muteAudio": "Il moderatore ha mutato il tuo audio",
"moderator.muteVideo": null "moderator.muteVideo": "Il moderatore ha fermato il tuo video"
} }

View File

@ -79,6 +79,7 @@
"tooltip.muteParticipant": "Noklusināt dalībnieku", "tooltip.muteParticipant": "Noklusināt dalībnieku",
"tooltip.muteParticipantVideo": "Atslēgt dalībnieka video", "tooltip.muteParticipantVideo": "Atslēgt dalībnieka video",
"tooltip.raisedHand": "Pacelt roku", "tooltip.raisedHand": "Pacelt roku",
"tooltip.muteScreenSharing": null,
"label.roomName": "Sapulces telpas nosaukums (ID)", "label.roomName": "Sapulces telpas nosaukums (ID)",
"label.chooseRoomButton": "Turpināt", "label.chooseRoomButton": "Turpināt",
@ -106,6 +107,7 @@
"label.appearence": "Izskats", "label.appearence": "Izskats",
"label.advanced": "Advancēts", "label.advanced": "Advancēts",
"label.addVideo": "Pievienot video", "label.addVideo": "Pievienot video",
"label.moreActions": null,
"settings.settings": "Iestatījumi", "settings.settings": "Iestatījumi",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -122,6 +124,7 @@
"settings.lastn": "Jums redzamo video/kameru skaits", "settings.lastn": "Jums redzamo video/kameru skaits",
"settings.hiddenControls": "Slēpto mediju vadība", "settings.hiddenControls": "Slēpto mediju vadība",
"settings.notificationSounds": "Paziņojumu skaņas", "settings.notificationSounds": "Paziņojumu skaņas",
"settings.showNotifications": null,
"filesharing.saveFileError": "Nav iespējams saglabāt failu", "filesharing.saveFileError": "Nav iespējams saglabāt failu",
"filesharing.startingFileShare": "Tiek mēģināts kopīgot failu", "filesharing.startingFileShare": "Tiek mēģināts kopīgot failu",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": "Demp deltaker", "tooltip.muteParticipant": "Demp deltaker",
"tooltip.muteParticipantVideo": "Demp deltakervideo", "tooltip.muteParticipantVideo": "Demp deltakervideo",
"tooltip.raisedHand": "Rekk opp hånden", "tooltip.raisedHand": "Rekk opp hånden",
"tooltip.muteScreenSharing": "Demp deltaker skjermdeling",
"label.roomName": "Møtenavn", "label.roomName": "Møtenavn",
"label.chooseRoomButton": "Fortsett", "label.chooseRoomButton": "Fortsett",
@ -109,6 +110,7 @@
"label.advanced": "Avansert", "label.advanced": "Avansert",
"label.addVideo": "Legg til video", "label.addVideo": "Legg til video",
"label.promoteAllPeers": "Slipp inn alle", "label.promoteAllPeers": "Slipp inn alle",
"label.moreActions": "Flere handlinger",
"settings.settings": "Innstillinger", "settings.settings": "Innstillinger",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -128,6 +130,7 @@
"settings.lastn": "Antall videoer synlig", "settings.lastn": "Antall videoer synlig",
"settings.hiddenControls": "Skjul media knapper", "settings.hiddenControls": "Skjul media knapper",
"settings.notificationSounds": "Varslingslyder", "settings.notificationSounds": "Varslingslyder",
"settings.showNotifications": "Vis varslinger",
"filesharing.saveFileError": "Klarte ikke å lagre fil", "filesharing.saveFileError": "Klarte ikke å lagre fil",
"filesharing.startingFileShare": "Starter fildeling", "filesharing.startingFileShare": "Starter fildeling",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Nazwa konferencji", "label.roomName": "Nazwa konferencji",
"label.chooseRoomButton": "Kontynuuj", "label.chooseRoomButton": "Kontynuuj",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Ustawienia", "settings.settings": "Ustawienia",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -128,6 +130,7 @@
"settings.lastn": "Liczba widocznych uczestników (zdalnych)", "settings.lastn": "Liczba widocznych uczestników (zdalnych)",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Nie można zapisać pliku", "filesharing.saveFileError": "Nie można zapisać pliku",
"filesharing.startingFileShare": "Próba udostępnienia pliku", "filesharing.startingFileShare": "Próba udostępnienia pliku",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Nome da sala", "label.roomName": "Nome da sala",
"label.chooseRoomButton": "Continuar", "label.chooseRoomButton": "Continuar",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Definições", "settings.settings": "Definições",
"settings.camera": "Camera", "settings.camera": "Camera",
@ -128,6 +130,7 @@
"settings.lastn": "Número de vídeos visíveis", "settings.lastn": "Número de vídeos visíveis",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Impossível de gravar o ficheiro", "filesharing.saveFileError": "Impossível de gravar o ficheiro",
"filesharing.startingFileShare": "Tentando partilha de ficheiro", "filesharing.startingFileShare": "Tentando partilha de ficheiro",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Numele camerei", "label.roomName": "Numele camerei",
"label.chooseRoomButton": "Continuare", "label.chooseRoomButton": "Continuare",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Setări", "settings.settings": "Setări",
"settings.camera": "Cameră video", "settings.camera": "Cameră video",
@ -128,6 +130,7 @@
"settings.lastn": "Numărul de videoclipuri vizibile", "settings.lastn": "Numărul de videoclipuri vizibile",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Încercarea de a salva fișierul a eșuat", "filesharing.saveFileError": "Încercarea de a salva fișierul a eșuat",
"filesharing.startingFileShare": "Partajarea fișierului", "filesharing.startingFileShare": "Partajarea fișierului",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Oda adı", "label.roomName": "Oda adı",
"label.chooseRoomButton": "Devam", "label.chooseRoomButton": "Devam",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Ayarlar", "settings.settings": "Ayarlar",
"settings.camera": "Kamera", "settings.camera": "Kamera",
@ -125,6 +127,7 @@
"settings.lastn": "İzlenebilir video sayısı", "settings.lastn": "İzlenebilir video sayısı",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Dosya kaydedilemiyor", "filesharing.saveFileError": "Dosya kaydedilemiyor",
"filesharing.startingFileShare": "Paylaşılan dosyaya erişiliyor", "filesharing.startingFileShare": "Paylaşılan dosyaya erişiliyor",

View File

@ -80,6 +80,7 @@
"tooltip.muteParticipant": null, "tooltip.muteParticipant": null,
"tooltip.muteParticipantVideo": null, "tooltip.muteParticipantVideo": null,
"tooltip.raisedHand": null, "tooltip.raisedHand": null,
"tooltip.muteScreenSharing": null,
"label.roomName": "Назва кімнати", "label.roomName": "Назва кімнати",
"label.chooseRoomButton": "Продовжити", "label.chooseRoomButton": "Продовжити",
@ -109,6 +110,7 @@
"label.advanced": null, "label.advanced": null,
"label.addVideo": null, "label.addVideo": null,
"label.promoteAllPeers": null, "label.promoteAllPeers": null,
"label.moreActions": null,
"settings.settings": "Налаштування", "settings.settings": "Налаштування",
"settings.camera": "Камера", "settings.camera": "Камера",
@ -128,6 +130,7 @@
"settings.lastn": "Кількість видимих ​​відео", "settings.lastn": "Кількість видимих ​​відео",
"settings.hiddenControls": null, "settings.hiddenControls": null,
"settings.notificationSounds": null, "settings.notificationSounds": null,
"settings.showNotifications": null,
"filesharing.saveFileError": "Неможливо зберегти файл", "filesharing.saveFileError": "Неможливо зберегти файл",
"filesharing.startingFileShare": "Спроба поділитися файлом", "filesharing.startingFileShare": "Спроба поділитися файлом",

View File

@ -96,8 +96,8 @@ module.exports =
this._queue = new AwaitQueue(); this._queue = new AwaitQueue();
} }
// rooms: number of rooms // rooms: rooms object
// peers: number of peers // peers: peers object
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
async log({ rooms, peers }) async log({ rooms, peers })
{ {
@ -106,9 +106,9 @@ module.exports =
// Do your logging in here, use queue to keep correct order // Do your logging in here, use queue to keep correct order
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log('Number of rooms: ', rooms); console.log('Number of rooms: ', rooms.size);
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log('Number of peers: ', peers); console.log('Number of peers: ', peers.size);
}) })
.catch((error) => .catch((error) =>
{ {

View File

@ -117,6 +117,8 @@ class Room extends EventEmitter
this._peers = {}; this._peers = {};
this._selfDestructTimeout = null;
// Array of mediasoup Router instances. // Array of mediasoup Router instances.
this._mediasoupRouters = mediasoupRouters; this._mediasoupRouters = mediasoupRouters;
@ -146,6 +148,11 @@ class Room extends EventEmitter
this._closed = true; this._closed = true;
if (this._selfDestructTimeout)
clearTimeout(this._selfDestructTimeout);
this._selfDestructTimeout = null;
this._chatHistory = null; this._chatHistory = null;
this._fileHistory = null; this._fileHistory = null;
@ -411,7 +418,10 @@ class Room extends EventEmitter
{ {
logger.debug('selfDestructCountdown() started'); logger.debug('selfDestructCountdown() started');
setTimeout(() => if (this._selfDestructTimeout)
clearTimeout(this._selfDestructTimeout);
this._selfDestructTimeout = setTimeout(() =>
{ {
if (this._closed) if (this._closed)
return; return;
@ -659,7 +669,14 @@ class Room extends EventEmitter
.filter((joinedPeer) => joinedPeer.id !== peer.id) .filter((joinedPeer) => joinedPeer.id !== peer.id)
.map((joinedPeer) => (joinedPeer.peerInfo)); .map((joinedPeer) => (joinedPeer.peerInfo));
const lobbyPeers = this._lobby.peerList(); let lobbyPeers = [];
if ( // Allowed to promote peers, notify about lobbypeers
peer.roles.some((role) =>
permissionsFromRoles.PROMOTE_PEER.includes(role)
)
)
lobbyPeers = this._lobby.peerList();
cb(null, { cb(null, {
roles : peer.roles, roles : peer.roles,
@ -1430,6 +1447,29 @@ class Room extends EventEmitter
break; break;
} }
case 'moderator:lowerHand':
{
if (
!peer.roles.some(
(role) => permissionsFromRoles.MODERATE_ROOM.includes(role)
)
)
throw new Error('peer not authorized');
const { peerId } = request.data;
const lowerPeer = this._peers[peerId];
if (!lowerPeer)
throw new Error(`peer with id "${peerId}" not found`);
this._notification(lowerPeer.socket, 'moderator:lowerHand');
cb();
break;
}
default: default:
{ {
logger.error('unknown request.method "%s"', request.method); logger.error('unknown request.method "%s"', request.method);

View File

@ -7,7 +7,7 @@
"license": "MIT", "license": "MIT",
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "scripts": {
"start": "DEBUG=${DEBUG:='*mediasoup* *INFO* *WARN* *ERROR*'} INTERACTIVE=${INTERACTIVE:='true'} node server.js", "start": "node server.js",
"connect": "node connect.js", "connect": "node connect.js",
"lint": "eslint -c .eslintrc.json --ext .js *.js lib/" "lint": "eslint -c .eslintrc.json --ext .js *.js lib/"
}, },

View File

@ -126,6 +126,8 @@ let oidcClient;
let oidcStrategy; let oidcStrategy;
async function run() async function run()
{
try
{ {
// Open the interactive server. // Open the interactive server.
await interactiveServer(rooms, peers); await interactiveServer(rooms, peers);
@ -154,8 +156,7 @@ async function run()
// Run WebSocketServer. // Run WebSocketServer.
await runWebSocketServer(); await runWebSocketServer();
// eslint-disable-next-line no-unused-vars const errorHandler = (err, req, res, next) =>
function errorHandler(err, req, res, next)
{ {
const trackingId = uuidv4(); const trackingId = uuidv4();
@ -169,27 +170,15 @@ async function run()
logger.error( logger.error(
'Express error handler dump with tracking ID: %s, error dump: %o', 'Express error handler dump with tracking ID: %s, error dump: %o',
trackingId, err); trackingId, err);
} };
// eslint-disable-next-line no-unused-vars
app.use(errorHandler); app.use(errorHandler);
// Log rooms status every 30 seconds.
setInterval(() =>
{
for (const room of rooms.values())
{
room.logStatus();
} }
}, 120000); catch (error)
// check for deserted rooms
setInterval(() =>
{ {
for (const room of rooms.values()) logger.error('run() [error:"%o"]', error);
{
room.checkEmpty();
} }
}, 10000);
} }
function statusLog() function statusLog()
@ -197,8 +186,8 @@ function statusLog()
if (statusLogger) if (statusLogger)
{ {
statusLogger.log({ statusLogger.log({
rooms : rooms.size, rooms : rooms,
peers : peers.size peers : peers
}); });
} }
} }