diff --git a/app/public/config/config.example.js b/app/public/config/config.example.js index 7909284..e07d994 100644 --- a/app/public/config/config.example.js +++ b/app/public/config/config.example.js @@ -44,34 +44,47 @@ var config = }, defaultAudio : { - sampleRate : 48000, - channelCount : 1, - volume : 1.0, - autoGainControl : true, - echoCancellation : true, - noiseSuppression : true, - sampleSize : 16 + sampleRate : 48000, + channelCount : 1, + volume : 1.0, + autoGainControl : true, + echoCancellation : true, + noiseSuppression : true, + voiceActivityMute : false, + sampleSize : 16 }, - background : 'images/background.jpg', - defaultLayout : 'democratic', // democratic, filmstrip + + /** + * Set the auto mute / Push To Talk threshold + * default value is 4 + * + * Set it to 0 to disable auto mute functionality, + * but use it with caution + * full mesh audio strongly decrease room capacity! + */ + autoMuteThreshold : 4, + background : 'images/background.jpg', + defaultLayout : 'democratic', // democratic, filmstrip // If true, will show media control buttons in separate // control bar, not in the ME container. - buttonControlBar : false, + buttonControlBar : false, // If false, will push videos away to make room for side // drawer. If true, will overlay side drawer over videos - drawerOverlayed : true, + drawerOverlayed : true, + // Position of notifications + notificationPosition : 'right', // Timeout for autohiding topbar and button control bar - hideTimeout : 3000, - lastN : 4, - mobileLastN : 1, + hideTimeout : 3000, + lastN : 4, + mobileLastN : 1, // Highest number of speakers user can select - maxLastN : 5, + maxLastN : 5, // If truthy, users can NOT change number of speakers visible - lockLastN : false, + lockLastN : false, // Add file and uncomment for adding logo to appbar // logo : 'images/logo.svg', - title : 'Multiparty meeting', - theme : + title : 'Multiparty meeting', + theme : { palette : { diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index 3710793..9e5b6ff 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -306,6 +306,22 @@ export default class RoomClient switch (key) { + case String.fromCharCode(37): + { + const newPeerId = this._spotlights.getPrevAsSelected( + store.getState().room.selectedPeerId); + + if (newPeerId) this.setSelectedPeer(newPeerId); + break; + } + case String.fromCharCode(39): + { + const newPeerId = this._spotlights.getNextAsSelected( + store.getState().room.selectedPeerId); + + if (newPeerId) this.setSelectedPeer(newPeerId); + break; + } case 'A': // Activate advanced mode { store.dispatch(settingsActions.toggleAdvancedMode()); @@ -1025,37 +1041,50 @@ export default class RoomClient if (!this._harkStream.getAudioTracks()[0]) throw new Error('getMicStream():something went wrong with hark'); - this._hark = hark(this._harkStream, { play: false }); + this._hark = hark(this._harkStream, + { + play : false, + interval : 5, + threshold : store.getState().settings.noiseThreshold, + history : 30 + }); + this._hark.lastVolume = -100; - // eslint-disable-next-line no-unused-vars - this._hark.on('volume_change', (dBs, threshold) => + this._hark.on('volume_change', (volume) => { - // 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 exagerate - // 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) + if (this._micProducer && volume !== Math.round(this._hark.lastVolume)) { - this._micProducer.volume = volume; - + if (volume < this._hark.lastVolume * 1.02) + { + volume = this._hark.lastVolume * 1.02; + } + this._hark.lastVolume = volume; store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume)); } }); - this._hark.on('speaking', function() + this._hark.on('speaking', () => { store.dispatch(meActions.setIsSpeaking(true)); + if ((store.getState().settings.voiceActivatedUnmute || + store.getState().me.isAutoMuted) && + this._micProducer && + this._micProducer.paused) + { + this._micProducer.resume(); + } + store.dispatch(meActions.setAutoMuted(false)); // sanity action }); - this._hark.on('stopped_speaking', function() + this._hark.on('stopped_speaking', () => { store.dispatch(meActions.setIsSpeaking(false)); + if (store.getState().settings.voiceActivatedUnmute && + this._micProducer && + !this._micProducer.paused) + { + this._micProducer.pause(); + store.dispatch(meActions.setAutoMuted(true)); + } }); } @@ -1470,6 +1499,26 @@ export default class RoomClient peerActions.setStopPeerVideoInProgress(peerId, false)); } + async stopPeerScreenSharing(peerId) + { + logger.debug('stopPeerScreenSharing() [peerId:"%s"]', peerId); + + store.dispatch( + peerActions.setStopPeerScreenSharingInProgress(peerId, true)); + + try + { + await this.sendRequest('moderator:stopScreenSharing', { peerId }); + } + catch (error) + { + logger.error('stopPeerScreenSharing() failed: %o', error); + } + + store.dispatch( + peerActions.setStopPeerScreenSharingInProgress(peerId, false)); + } + async muteAllPeers() { logger.debug('muteAllPeers()'); @@ -1510,6 +1559,26 @@ export default class RoomClient roomActions.setStopAllVideoInProgress(false)); } + async stopAllPeerScreenSharing() + { + logger.debug('stopAllPeerScreenSharing()'); + + store.dispatch( + roomActions.setStopAllScreenSharingInProgress(true)); + + try + { + await this.sendRequest('moderator:stopAllScreenSharing'); + } + catch (error) + { + logger.error('stopAllPeerScreenSharing() failed: %o', error); + } + + store.dispatch( + roomActions.setStopAllScreenSharingInProgress(false)); + } + async closeMeeting() { logger.debug('closeMeeting()'); @@ -1944,23 +2013,12 @@ export default class RoomClient producerPaused } = request.data; - let codecOptions; - - if (kind === 'audio') - { - codecOptions = - { - opusStereo : 1 - }; - } - const consumer = await this._recvTransport.consume( { id, producerId, kind, rtpParameters, - codecOptions, appData : { ...appData, peerId } // Trick. }); @@ -2013,19 +2071,8 @@ export default class RoomClient consumer.hark = hark(stream, { play: false }); - // eslint-disable-next-line no-unused-vars - consumer.hark.on('volume_change', (dBs, threshold) => + consumer.hark.on('volume_change', (volume) => { - // 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 (consumer && volume !== consumer.volume) @@ -2631,7 +2678,6 @@ export default class RoomClient case 'moderator:stopVideo': { this.disableWebcam(); - this.disableScreenSharing(); store.dispatch(requestActions.notify( { @@ -2644,6 +2690,21 @@ export default class RoomClient break; } + case 'moderator:stopScreenSharing': + { + this.disableScreenSharing(); + + store.dispatch(requestActions.notify( + { + text : intl.formatMessage({ + id : 'moderator.muteScreenSharingModerator', + defaultMessage : 'Moderator stopped your screen sharing' + }) + })); + + break; + } + case 'moderator:kick': { // Need some feedback @@ -2999,7 +3060,9 @@ export default class RoomClient if (!this._muted) { await this.enableMic(); - if (peers.length > 4) + const { autoMuteThreshold } = store.getState().settings; + + if (autoMuteThreshold && peers.length > autoMuteThreshold) this.muteMic(); } @@ -3645,6 +3708,8 @@ export default class RoomClient this._screenSharingProducer = null; + this._screenSharing.stop(); + store.dispatch(meActions.setScreenShareInProgress(false)); } @@ -3853,6 +3918,14 @@ export default class RoomClient store.dispatch(meActions.setWebcamInProgress(false)); } + async _setNoiseThreshold(threshold) + { + logger.debug('_setNoiseThreshold:%s', threshold); + this._hark.setThreshold(threshold); + store.dispatch( + settingsActions.setNoiseThreshold(threshold)); + } + async _updateAudioDevices() { logger.debug('_updateAudioDevices()'); diff --git a/app/src/Spotlights.js b/app/src/Spotlights.js index 3d0673f..10d6638 100644 --- a/app/src/Spotlights.js +++ b/app/src/Spotlights.js @@ -12,6 +12,7 @@ export default class Spotlights extends EventEmitter this._signalingSocket = signalingSocket; this._maxSpotlights = maxSpotlights; this._peerList = []; + this._unmutablePeerList = []; this._selectedSpotlights = []; this._currentSpotlights = []; this._started = false; @@ -45,6 +46,74 @@ export default class Spotlights extends EventEmitter } } + getNextAsSelected(peerId) + { + let newSelectedPeer = null; + + if (peerId == null && this._unmutablePeerList.length > 0) + { + peerId = this._unmutablePeerList[0]; + } + + if (peerId != null && this._currentSpotlights.length < this._unmutablePeerList.length) + { + const oldIndex = this._unmutablePeerList.indexOf(peerId); + + let index = oldIndex; + + index++; + for (let i = 0; i < this._unmutablePeerList.length; i++) + { + if (index >= this._unmutablePeerList.length) + { + index = 0; + } + newSelectedPeer = this._unmutablePeerList[index]; + if (!this._currentSpotlights.includes(newSelectedPeer)) + { + break; + } + index++; + } + } + + return newSelectedPeer; + } + + getPrevAsSelected(peerId) + { + let newSelectedPeer = null; + + if (peerId == null && this._unmutablePeerList.length > 0) + { + peerId = this._unmutablePeerList[0]; + } + + if (peerId != null && this._currentSpotlights.length < this._unmutablePeerList.length) + { + const oldIndex = this._unmutablePeerList.indexOf(peerId); + + let index = oldIndex; + + index--; + for (let i = 0; i < this._unmutablePeerList.length; i++) + { + if (index < 0) + { + index = this._unmutablePeerList.length - 1; + } + newSelectedPeer = this._unmutablePeerList[index]; + if (!this._currentSpotlights.includes(newSelectedPeer)) + { + break; + } + index--; + } + } + + return newSelectedPeer; + } + setPeerSpotlight(peerId) { logger.debug('setPeerSpotlight() [peerId:"%s"]', peerId); @@ -114,6 +183,7 @@ export default class Spotlights extends EventEmitter logger.debug('_handlePeer() | adding peer [peerId: "%s"]', id); this._peerList.push(id); + this._unmutablePeerList.push(id); if (this._started) this._spotlightsUpdated(); @@ -126,6 +196,7 @@ export default class Spotlights extends EventEmitter 'room "peerClosed" event [peerId:%o]', id); this._peerList = this._peerList.filter((peer) => peer !== id); + this._unmutablePeerList = this._unmutablePeerList.filter((peer) => peer !== id); this._selectedSpotlights = this._selectedSpotlights.filter((peer) => peer !== id); diff --git a/app/src/actions/meActions.js b/app/src/actions/meActions.js index 7fb34ea..be7c1ee 100644 --- a/app/src/actions/meActions.js +++ b/app/src/actions/meActions.js @@ -110,3 +110,9 @@ export const setIsSpeaking = (flag) => type : 'SET_IS_SPEAKING', payload : { flag } }); + +export const setAutoMuted = (flag) => + ({ + type : 'SET_AUTO_MUTED', + payload : { flag } + }); diff --git a/app/src/actions/peerActions.js b/app/src/actions/peerActions.js index 5672b47..1a1e2d3 100644 --- a/app/src/actions/peerActions.js +++ b/app/src/actions/peerActions.js @@ -86,3 +86,9 @@ export const setStopPeerVideoInProgress = (peerId, flag) => type : 'STOP_PEER_VIDEO_IN_PROGRESS', payload : { peerId, flag } }); + +export const setStopPeerScreenSharingInProgress = (peerId, flag) => + ({ + type : 'STOP_PEER_SCREEN_SHARING_IN_PROGRESS', + payload : { peerId, flag } + }); diff --git a/app/src/actions/roomActions.js b/app/src/actions/roomActions.js index 5ae45e3..a73e18a 100644 --- a/app/src/actions/roomActions.js +++ b/app/src/actions/roomActions.js @@ -164,6 +164,12 @@ export const setStopAllVideoInProgress = (flag) => payload : { flag } }); +export const setStopAllScreenSharingInProgress = (flag) => + ({ + type : 'STOP_ALL_SCREEN_SHARING_IN_PROGRESS', + payload : { flag } + }); + export const setCloseMeetingInProgress = (flag) => ({ type : 'CLOSE_MEETING_IN_PROGRESS', diff --git a/app/src/actions/settingsActions.js b/app/src/actions/settingsActions.js index 21ff2fd..90b019a 100644 --- a/app/src/actions/settingsActions.js +++ b/app/src/actions/settingsActions.js @@ -71,6 +71,18 @@ export const setNoiseSuppression = (noiseSuppression) => payload : { noiseSuppression } }); +export const setVoiceActivatedUnmute = (voiceActivatedUnmute) => + ({ + type: 'SET_VOICE_ACTIVATED_UNMUTE', + payload: { voiceActivatedUnmute } + }); + +export const setNoiseThreshold = (noiseThreshold) => + ({ + type: 'SET_NOISE_THRESHOLD', + payload: { noiseThreshold } + }); + export const setDefaultAudio = (audio) => ({ type : 'SET_DEFAULT_AUDIO', diff --git a/app/src/components/Containers/Me.js b/app/src/components/Containers/Me.js index 3438631..5c7bb7a 100644 --- a/app/src/components/Containers/Me.js +++ b/app/src/components/Containers/Me.js @@ -137,14 +137,15 @@ const styles = (theme) => transform : 'translate(-50%, 0%)', color : 'rgba(255, 255, 255, 0.7)', fontSize : '1.3em', - backgroundColor : 'rgba(255, 0, 0, 0.9)', + backgroundColor : 'rgba(245, 0, 87, 0.70)', margin : '4px', padding : theme.spacing(2), - zIndex : 31, + zIndex : 1200, borderRadius : '20px', textAlign : 'center', opacity : 0, transition : 'opacity 1s ease', + pointerEvents : 'none', '&.enabled' : { transition : 'opacity 0.1s', @@ -176,7 +177,9 @@ const Me = (props) => extraVideoProducers, canShareScreen, classes, - transports + transports, + noiseVolume, + classes } = props; const videoVisible = ( @@ -285,6 +288,25 @@ const Me = (props) => defaultMessage : 'Start screen sharing' }); } + const [ + screenShareTooltipOpen, + screenShareTooltipSetOpen + ] = React.useState(false); + + const screenShareTooltipHandleClose = () => + { + screenShareTooltipSetOpen(false); + }; + + const screenShareTooltipHandleOpen = () => + { + screenShareTooltipSetOpen(true); + }; + + if (screenState === 'off' && me.screenShareInProgress && screenShareTooltipOpen) + { + screenShareTooltipHandleClose(); + } const spacingStyle = { @@ -346,7 +368,7 @@ const Me = (props) => style={spacingStyle} > - { me.browser.platform !== 'mobile' && + { me.browser.platform !== 'mobile' && smallContainer &&
+ />
}
+ { me.browser.platform !== 'mobile' && !smallContainer && +
+ +
+ }

})} className={classes.smallContainer} disabled={!me.canSendMic || me.audioInProgress} - color={micState === 'on' ? 'primary' : 'secondary'} + color={ + micState === 'on' ? + settings.voiceActivatedUnmute && !me.isAutoMuted ? + 'primary' + : 'default' + : 'secondary'} size='small' onClick={() => { @@ -422,7 +461,10 @@ const Me = (props) => }} > { micState === 'on' ? - + : } @@ -437,7 +479,10 @@ const Me = (props) => })} className={classes.fab} disabled={!me.canSendMic || me.audioInProgress} - color={micState === 'on' ? 'default' : 'secondary'} + color={micState === 'on' ? + settings.voiceActivatedUnmute && !me.isAutoMuted? 'primary' + : 'default' + : 'secondary'} size='large' onClick={() => { @@ -450,7 +495,11 @@ const Me = (props) => }} > { micState === 'on' ? - + : } @@ -512,7 +561,11 @@ const Me = (props) => } { me.browser.platform !== 'mobile' && - + { smallContainer ?

const mapStateToProps = (state) => { + let volume; + + // noiseVolume under threshold + if (state.peerVolumes[state.me.id] < state.settings.noiseThreshold) + { + // noiseVolume mapped to range 0.5 ... 1 (threshold switch) + volume = 1 + ((Math.abs(state.peerVolumes[state.me.id] - + state.settings.noiseThreshold) / (-120 - + state.settings.noiseThreshold))); + } + // noiseVolume over threshold: no noise but voice + else { volume = 0; } + return { me : state.me, ...meProducersSelector(state), settings : state.settings, activeSpeaker : state.me.id === state.room.activeSpeakerId, canShareScreen : hasPermission(state), - transports : state.transports + transports : state.transports, + noiseVolume : volume }; }; @@ -868,6 +936,8 @@ export default withRoomContext(connect( return ( prev.room === next.room && prev.me === next.me && + Math.round(prev.peerVolumes[prev.me.id]) === + Math.round(next.peerVolumes[next.me.id]) && prev.peers === next.peers && prev.producers === next.producers && prev.settings === next.settings, diff --git a/app/src/components/Containers/Volume.js b/app/src/components/Containers/Volume.js index 3c13a39..81a050b 100644 --- a/app/src/components/Containers/Volume.js +++ b/app/src/components/Containers/Volume.js @@ -94,17 +94,17 @@ const styles = () => smallBar : { flex : '0 0 auto', - margin : '0.3rem', backgroundSize : '75%', backgroundRepeat : 'no-repeat', backgroundColor : 'rgba(0, 0, 0, 1)', cursor : 'pointer', transitionProperty : 'opacity, background-color', width : 3, - borderRadius : 6, + borderRadius : 2, transitionDuration : '0.25s', position : 'absolute', - bottom : 0, + top : '50%', + transform : 'translateY(-50%)', '&.level0' : { height: 0 }, '&.level1' : { height: '0.2vh' }, '&.level2' : { height: '0.4vh' }, @@ -149,9 +149,16 @@ const makeMapStateToProps = (initialState, props) => { const mapStateToProps = (state) => { - return { - volume : state.peerVolumes[props.id] - }; + if (state.peerVolumes[props.id]>state.settings.noiseThreshold) + { + return { + volume : Math.round((state.peerVolumes[props.id]+100) / 10) + }; + } + else + { + return { volume: 0 }; + } }; return mapStateToProps; diff --git a/app/src/components/Controls/Help.js b/app/src/components/Controls/Help.js index 98415b5..ab188b8 100644 --- a/app/src/components/Controls/Help.js +++ b/app/src/components/Controls/Help.js @@ -23,7 +23,8 @@ const shortcuts=[ { key: '1', label: 'label.democratic', defaultMessage: 'Democratic View' }, { key: '2', label: 'label.filmstrip', defaultMessage: 'Filmstrip View' }, { key: 'space', label: 'me.mutedPTT', defaultMessage: 'Push SPACE to talk' }, - { key: 'a', label: 'label.advanced', defaultMessage: 'Show advanced information' } + { key: 'a', label: 'label.advanced', defaultMessage: 'Show advanced information' }, + { key: `${String.fromCharCode(8592)} ${String.fromCharCode(8594)}`, label: 'room.browsePeersSpotlight', defaultMessage: 'Browse participants into Spotlight' } ]; const styles = (theme) => ({ diff --git a/app/src/components/Controls/TopBar.js b/app/src/components/Controls/TopBar.js index bbf408d..148f4a7 100644 --- a/app/src/components/Controls/TopBar.js +++ b/app/src/components/Controls/TopBar.js @@ -480,6 +480,34 @@ const TopBar = (props) =>
+ { lobbyPeers.length > 0 && + + + setLockDialogOpen(!room.lockDialogOpen)} + > + + + + + + + }
+ +
); diff --git a/app/src/components/Notifications/Notifications.js b/app/src/components/Notifications/Notifications.js index ce2fcee..d5a21c7 100644 --- a/app/src/components/Notifications/Notifications.js +++ b/app/src/components/Notifications/Notifications.js @@ -4,6 +4,8 @@ import PropTypes from 'prop-types'; import { withSnackbar } from 'notistack'; import * as notificationActions from '../../actions/notificationActions'; +const notificationPosition = window.config.notificationPosition || 'right'; + class Notifications extends Component { displayed = []; @@ -45,7 +47,7 @@ class Notifications extends Component autoHideDuration : notification.timeout, anchorOrigin : { vertical : 'bottom', - horizontal : 'left' + horizontal : notificationPosition } } ); diff --git a/app/src/components/Settings/MediaSettings.js b/app/src/components/Settings/MediaSettings.js index 28a69a2..d326b91 100644 --- a/app/src/components/Settings/MediaSettings.js +++ b/app/src/components/Settings/MediaSettings.js @@ -6,31 +6,66 @@ import { withRoomContext } from '../../RoomContext'; import * as settingsActions from '../../actions/settingsActions'; import PropTypes from 'prop-types'; import { useIntl, FormattedMessage } from 'react-intl'; +import classnames from 'classnames'; import MenuItem from '@material-ui/core/MenuItem'; import FormHelperText from '@material-ui/core/FormHelperText'; import FormControl from '@material-ui/core/FormControl'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Select from '@material-ui/core/Select'; import Checkbox from '@material-ui/core/Checkbox'; +import Slider from '@material-ui/core/Slider'; +import Typography from '@material-ui/core/Typography'; -const styles = (theme) => - ({ - setting : +const NoiseSlider = withStyles( + { + root : { - padding : theme.spacing(2) + color : '#3880ff', + height : 2, + padding : '15px 0' }, - formControl : - { - display : 'flex' + track : { + height : 2 + }, + rail : { + height : 2, + opacity : 0.2 + }, + mark : { + backgroundColor : '#bfbfbf', + height : 10, + width : 3, + marginTop : -3 + }, + markActive : { + opacity : 1, + backgroundColor : 'currentColor' } - }); + })(Slider); + +const styles = (theme) => ({ + setting : + { + padding : theme.spacing(2) + }, + margin : + { + height : theme.spacing(3) + }, + formControl : + { + display : 'flex' + } +}); const MediaSettings = ({ setEchoCancellation, setAutoGainControl, setNoiseSuppression, + setVoiceActivatedUnmute, roomClient, me, + volume, settings, classes }) => @@ -135,6 +170,34 @@ const MediaSettings = ({ } + + + + + +
@@ -148,7 +211,7 @@ const MediaSettings = ({ displayEmpty name={intl.formatMessage({ id : 'settings.audio', - defaultMessage : 'Audio device' + defaultMessage : 'Audio input device' })} autoWidth className={classes.selectEmpty} @@ -165,12 +228,12 @@ const MediaSettings = ({ { audioDevices.length > 0 ? intl.formatMessage({ id : 'settings.selectAudio', - defaultMessage : 'Select audio device' + defaultMessage : 'Select audio input device' }) : intl.formatMessage({ id : 'settings.cantSelectAudio', - defaultMessage : 'Unable to select audio device' + defaultMessage : 'Unable to select audio input device' }) } @@ -225,34 +288,6 @@ const MediaSettings = ({ }
- - - - - - + + { + setVoiceActivatedUnmute(event.target.checked); + }} + />} + label={intl.formatMessage({ + id : 'settings.voiceActivatedUnmute', + defaultMessage : 'Voice activated unmute' + })} + /> +
+ + { + intl.formatMessage({ + id : 'settings.noiseThreshold', + defaultMessage : 'Noise threshold:' + }) + } + + + { + roomClient._setNoiseThreshold(value); + }} + marks={[ { value: volume, label: 'level' } ]} + /> +
); @@ -305,27 +377,31 @@ const MediaSettings = ({ MediaSettings.propTypes = { - roomClient : PropTypes.any.isRequired, - setEchoCancellation : PropTypes.func.isRequired, - setAutoGainControl : PropTypes.func.isRequired, - setNoiseSuppression : PropTypes.func.isRequired, - me : appPropTypes.Me.isRequired, - settings : PropTypes.object.isRequired, - classes : PropTypes.object.isRequired + roomClient : PropTypes.any.isRequired, + setEchoCancellation : PropTypes.func.isRequired, + setAutoGainControl : PropTypes.func.isRequired, + setNoiseSuppression : PropTypes.func.isRequired, + setVoiceActivatedUnmute : PropTypes.func.isRequired, + me : appPropTypes.Me.isRequired, + volume : PropTypes.number, + settings : PropTypes.object.isRequired, + classes : PropTypes.object.isRequired }; const mapStateToProps = (state) => { return { me : state.me, + volume : state.peerVolumes[state.me.id], settings : state.settings }; }; const mapDispatchToProps = { - setEchoCancellation : settingsActions.setEchoCancellation, - setAutoGainControl : settingsActions.toggleAutoGainControl, - setNoiseSuppression : settingsActions.toggleNoiseSuppression + setEchoCancellation : settingsActions.setEchoCancellation, + setAutoGainControl : settingsActions.toggleAutoGainControl, + setNoiseSuppression : settingsActions.toggleNoiseSuppression, + setVoiceActivatedUnmute : settingsActions.setVoiceActivatedUnmute }; export default withRoomContext(connect( @@ -337,7 +413,8 @@ export default withRoomContext(connect( { return ( prev.me === next.me && - prev.settings === next.settings + prev.settings === next.settings && + prev.peerVolumes[prev.me.id] === next[next.me.id] ); } } diff --git a/app/src/components/Settings/Settings.js b/app/src/components/Settings/Settings.js index 6633829..cbfb8b1 100644 --- a/app/src/components/Settings/Settings.js +++ b/app/src/components/Settings/Settings.js @@ -95,7 +95,7 @@ const Settings = ({ /> diff --git a/app/src/index.js b/app/src/index.js index e89d06d..c5f333d 100644 --- a/app/src/index.js +++ b/app/src/index.js @@ -31,7 +31,8 @@ import messagesFrench from './translations/fr'; import messagesGreek from './translations/el'; import messagesRomanian from './translations/ro'; import messagesPortuguese from './translations/pt'; -import messagesChinese from './translations/cn'; +import messagesChineseSimplified from './translations/cn'; +import messagesChineseTraditional from './translations/tw'; import messagesSpanish from './translations/es'; import messagesCroatian from './translations/hr'; import messagesCzech from './translations/cs'; @@ -49,26 +50,37 @@ const cache = createIntlCache(); const messages = { // 'en' : messagesEnglish, - 'nb' : messagesNorwegian, - 'de' : messagesGerman, - 'hu' : messagesHungarian, - 'pl' : messagesPolish, - 'dk' : messagesDanish, - 'fr' : messagesFrench, - 'el' : messagesGreek, - 'ro' : messagesRomanian, - 'pt' : messagesPortuguese, - 'zh' : messagesChinese, - 'es' : messagesSpanish, - 'hr' : messagesCroatian, - 'cs' : messagesCzech, - 'it' : messagesItalian, - 'uk' : messagesUkrainian, - 'tr' : messagesTurkish, - 'lv' : messagesLatvian + 'nb' : messagesNorwegian, + 'de' : messagesGerman, + 'hu' : messagesHungarian, + 'pl' : messagesPolish, + 'dk' : messagesDanish, + 'fr' : messagesFrench, + 'el' : messagesGreek, + 'ro' : messagesRomanian, + 'pt' : messagesPortuguese, + 'zh-hans' : messagesChineseSimplified, + 'zh-hant' : messagesChineseTraditional, + 'es' : messagesSpanish, + 'hr' : messagesCroatian, + 'cs' : messagesCzech, + 'it' : messagesItalian, + 'uk' : messagesUkrainian, + 'tr' : messagesTurkish, + 'lv' : messagesLatvian }; -const locale = navigator.language.split(/[-_]/)[0]; // language without region code +const browserLanguage = (navigator.language || navigator.browserLanguage).toLowerCase(); + +let locale = browserLanguage.split(/[-_]/)[0]; // language without region code + +if (locale === 'zh') +{ + if (browserLanguage === 'zh-cn') + locale = 'zh-hans'; + else + locale = 'zh-hant'; +} const intl = createIntl({ locale, diff --git a/app/src/reducers/me.js b/app/src/reducers/me.js index f3fff66..35336a6 100644 --- a/app/src/reducers/me.js +++ b/app/src/reducers/me.js @@ -18,7 +18,8 @@ const initialState = raisedHand : false, raisedHandInProgress : false, loggedIn : false, - isSpeaking : false + isSpeaking : false, + isAutoMuted : true }; const me = (state = initialState, action) => @@ -162,6 +163,13 @@ const me = (state = initialState, action) => return { ...state, isSpeaking: flag }; } + case 'SET_AUTO_MUTED': + { + const { flag } = action.payload; + + return { ...state, isAutoMuted: flag }; + } + default: return state; } diff --git a/app/src/reducers/peerVolumes.js b/app/src/reducers/peerVolumes.js index fafe739..826a038 100644 --- a/app/src/reducers/peerVolumes.js +++ b/app/src/reducers/peerVolumes.js @@ -31,9 +31,10 @@ const peerVolumes = (state = initialState, action) => case 'SET_PEER_VOLUME': { - const { peerId, volume } = action.payload; + const { peerId } = action.payload; + const dBs = action.payload.volume < -100 ? -100 : action.payload.volume; - return { ...state, [peerId]: volume }; + return { ...state, [peerId]: Math.round(dBs) }; } default: diff --git a/app/src/reducers/peers.js b/app/src/reducers/peers.js index 32d6fef..8e6a7f7 100644 --- a/app/src/reducers/peers.js +++ b/app/src/reducers/peers.js @@ -82,6 +82,11 @@ const peer = (state = initialState, action) => stopPeerVideoInProgress : action.payload.flag }; + case 'STOP_PEER_SCREEN_SHARING_IN_PROGRESS': + return { + ...state, + stopPeerScreenSharingInProgress : action.payload.flag + }; default: return state; } @@ -118,6 +123,7 @@ const peers = (state = initialState, action) => case 'REMOVE_PEER_ROLE': case 'STOP_PEER_AUDIO_IN_PROGRESS': case 'STOP_PEER_VIDEO_IN_PROGRESS': + case 'STOP_PEER_SCREEN_SHARING_IN_PROGRESS': { const oldPeer = state[action.payload.peerId]; diff --git a/app/src/reducers/room.js b/app/src/reducers/room.js index d784219..193e8e0 100644 --- a/app/src/reducers/room.js +++ b/app/src/reducers/room.js @@ -226,6 +226,9 @@ const room = (state = initialState, action) => case 'STOP_ALL_VIDEO_IN_PROGRESS': return { ...state, stopAllVideoInProgress: action.payload.flag }; + case 'STOP_ALL_SCREEN_SHARING_IN_PROGRESS': + return { ...state, stopAllScreenSharingInProgress: action.payload.flag }; + case 'CLOSE_MEETING_IN_PROGRESS': return { ...state, closeMeetingInProgress: action.payload.flag }; diff --git a/app/src/reducers/settings.js b/app/src/reducers/settings.js index 1c375bf..750df24 100644 --- a/app/src/reducers/settings.js +++ b/app/src/reducers/settings.js @@ -1,25 +1,28 @@ const initialState = { - displayName : 'Guest', - selectedWebcam : null, - selectedAudioDevice : null, - advancedMode : false, - sampleRate : 48000, - channelCount : 1, - volume : 1.0, - autoGainControl : true, - echoCancellation : true, - noiseSuppression : true, - sampleSize : 16, + displayName : 'Guest', + selectedWebcam : null, + selectedAudioDevice : null, + advancedMode : false, + sampleRate : 48000, + channelCount : 1, + volume : 1.0, + autoGainControl : false, + echoCancellation : true, + noiseSuppression : true, + voiceActivatedUnmute : false, + noiseThreshold : -50, + sampleSize : 16, // low, medium, high, veryhigh, ultra - resolution : window.config.defaultResolution || 'medium', - lastN : 4, - permanentTopBar : true, - hiddenControls : false, - showNotifications : true, - notificationSounds : true, - buttonControlBar : window.config.buttonControlBar || false, - drawerOverlayed : window.config.drawerOverlayed || true, + resolution : window.config.defaultResolution || 'medium', + lastN : 4, + permanentTopBar : true, + hiddenControls : false, + showNotifications : true, + notificationSounds : true, + buttonControlBar : window.config.buttonControlBar || false, + drawerOverlayed : window.config.drawerOverlayed || true, + autoMuteThreshold : window.config.autoMuteThreshold || 4, ...window.config.defaultAudio }; @@ -98,6 +101,20 @@ const settings = (state = initialState, action) => return { ...state, noiseSuppression }; } + case 'SET_VOICE_ACTIVATED_UNMUTE': + { + const { voiceActivatedUnmute } = action.payload; + + return { ...state, voiceActivatedUnmute }; + } + + case 'SET_NOISE_THRESHOLD': + { + const { noiseThreshold } = action.payload; + + return { ...state, noiseThreshold }; + } + case 'SET_DEFAULT_AUDIO': { const { audio } = action.payload; diff --git a/app/src/translations/cn.json b/app/src/translations/cn.json index 0ce5f5b..c5f79e4 100644 --- a/app/src/translations/cn.json +++ b/app/src/translations/cn.json @@ -63,6 +63,7 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, "me.mutedPTT": null, @@ -84,6 +85,10 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, + "room.stopAllScreenSharing": null, "label.roomName": "房间名称", "label.chooseRoomButton": "继续", @@ -109,7 +114,7 @@ "label.ultra": "超高 (UHD)", "label.close": "关闭", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } \ No newline at end of file diff --git a/app/src/translations/cs.json b/app/src/translations/cs.json index 3eac16c..c1ea569 100644 --- a/app/src/translations/cs.json +++ b/app/src/translations/cs.json @@ -62,6 +62,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -83,6 +85,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Jméno místnosti", "label.chooseRoomButton": "Pokračovat", @@ -108,7 +113,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Zavřít", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -182,5 +187,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null -} + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null +} \ No newline at end of file diff --git a/app/src/translations/de.json b/app/src/translations/de.json index c4b67fe..9339d4f 100644 --- a/app/src/translations/de.json +++ b/app/src/translations/de.json @@ -51,7 +51,7 @@ "room.videoPaused": "Video gestoppt", "room.muteAll": "Alle stummschalten", "room.stopAllVideo": "Alle Videos stoppen", - "room.closeMeeting": "Meeting schließen", + "room.closeMeeting": "Meeting beenden", "room.clearChat": "Liste löschen", "room.clearFileSharing": "Liste löschen", "room.speechUnsupported": "Dein Browser unterstützt keine Spracherkennung", @@ -61,10 +61,12 @@ "room.extraVideo": "Video hinzufügen", "room.overRoomLimit": "Der Raum ist voll, probiere es später nochmal", "room.help": "Hilfe", - "room.about": "Impressum", + "room.about": "Über", "room.shortcutKeys": "Tastaturkürzel", + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, - "me.mutedPTT": "Du bist stummgeschalted, Halte die SPACE-Taste um zu sprechen", + "me.mutedPTT": "Du bist stummgeschaltet. Halte die SPACE-Taste um zu sprechen", "roles.gotRole": "Rolle erhalten: {role}", "roles.lostRole": "Rolle entzogen: {role}", @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": "Video stoppen", "tooltip.raisedHand": "Hand heben", "tooltip.muteScreenSharing": "Stoppe Bildschirmfreigabe", + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Name des Raums", "label.chooseRoomButton": "Weiter", @@ -103,16 +108,16 @@ "label.democratic": "Demokratisch", "label.filmstrip": "Filmstreifen", "label.low": "Niedrig", - "label.medium": "Medium", + "label.medium": "Mittel", "label.high": "Hoch (HD)", "label.veryHigh": "Sehr hoch (FHD)", "label.ultra": "Ultra (UHD)", "label.close": "Schließen", "label.media": "Audio / Video", - "label.appearence": "Erscheinung", - "label.advanced": "Erweiter", + "label.appearance": "Ansicht", + "label.advanced": "Erweitert", "label.addVideo": "Video hinzufügen", - "label.promoteAllPeers": "Alle Teinehmer einlassen", + "label.promoteAllPeers": "Alle Teilnehmer reinlassen", "label.moreActions": "Weitere Aktionen", "settings.settings": "Einstellungen", @@ -134,7 +139,7 @@ "settings.hiddenControls": "Medienwerkzeugleiste automatisch ausblenden", "settings.notificationSounds": "Audiosignal bei Benachrichtigungen", "settings.showNotifications": "Zeige Benachrichtigungen", - "settings.buttonControlBar": "Seperate seitliche Medienwerkzeugleiste", + "settings.buttonControlBar": "Separate seitliche Medienwerkzeugleiste", "settings.echoCancellation": "Echounterdrückung", "settings.autoGainControl": "Automatische Pegelregelung (Audioeingang)", "settings.noiseSuppression": "Rauschunterdrückung", @@ -183,5 +188,6 @@ "moderator.clearChat": "Moderator hat Chat gelöscht", "moderator.clearFiles": "Moderator hat geteilte Dateiliste gelöscht", "moderator.muteAudio": "Moderator hat dich stummgeschaltet", - "moderator.muteVideo": "Moderator hat dein Video gestoppt" + "moderator.muteVideo": "Moderator hat dein Video gestoppt", + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/dk.json b/app/src/translations/dk.json index c5c3a2d..edeb619 100644 --- a/app/src/translations/dk.json +++ b/app/src/translations/dk.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Værelsesnavn", "label.chooseRoomButton": "Fortsæt", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Luk", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/el.json b/app/src/translations/el.json index d71764f..6807831 100644 --- a/app/src/translations/el.json +++ b/app/src/translations/el.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Όνομα δωματίου", "label.chooseRoomButton": "Συνέχεια", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Κλείσιμο", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } \ No newline at end of file diff --git a/app/src/translations/en.json b/app/src/translations/en.json index 344d660..30c21d7 100644 --- a/app/src/translations/en.json +++ b/app/src/translations/en.json @@ -63,6 +63,8 @@ "room.help": "Help", "room.about": "About", "room.shortcutKeys": "Shortcut Keys", + "room.browsePeersSpotlight": "Browse participants into Spotlight", + "room.stopAllScreenSharing": "Stop all screen sharing", "me.mutedPTT": "You are muted, hold down SPACE-BAR to talk", @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": "Mute participant video", "tooltip.raisedHand": "Raise hand", "tooltip.muteScreenSharing": "Mute participant share", + "tooltip.muteParticipantAudioModerator": "Mute participant audio globally", + "tooltip.muteParticipantVideoModerator": "Mute participant video globally", + "tooltip.muteScreenSharingModerator": "Mute participant screen share globally", "label.roomName": "Room name", "label.chooseRoomButton": "Continue", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Close", "label.media": "Media", - "label.appearence": "Appearence", + "label.appearance": "Appearence", "label.advanced": "Advanced", "label.addVideo": "Add video", "label.promoteAllPeers": "Promote all", @@ -183,5 +188,6 @@ "moderator.clearChat": "Moderator cleared the chat", "moderator.clearFiles": "Moderator cleared the files", "moderator.muteAudio": "Moderator muted your audio", - "moderator.muteVideo": "Moderator muted your video" + "moderator.muteVideo": "Moderator muted your video", + "moderator.muteScreenSharing": "Moderator muted your screen sharing" } \ No newline at end of file diff --git a/app/src/translations/es.json b/app/src/translations/es.json index 758b0c8..4e0c12a 100644 --- a/app/src/translations/es.json +++ b/app/src/translations/es.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Nombre de la sala", "label.chooseRoomButton": "Continuar", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Cerrar", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/fr.json b/app/src/translations/fr.json index 2eb7edf..0f2ac0b 100644 --- a/app/src/translations/fr.json +++ b/app/src/translations/fr.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Nom de la salle", "label.chooseRoomButton": "Continuer", @@ -109,7 +114,7 @@ "label.ultra": "Ultra Haute Définition", "label.close": "Fermer", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -182,5 +187,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/hr.json b/app/src/translations/hr.json index c0f8879..59873d4 100644 --- a/app/src/translations/hr.json +++ b/app/src/translations/hr.json @@ -46,7 +46,7 @@ "room.lobbyEmpty": "Trenutno nema nikoga u predvorju", "room.hiddenPeers": "{hiddenPeersCount, plural, one {participant} other {participants}}", "room.me": "Ja", - "room.spotlights": "Sudionici u fokusu", + "room.spotlights": "Sudionici u središtu pažnje", "room.passive": "Pasivni sudionici", "room.videoPaused": "Video pauziran", "room.muteAll": "Utišaj sve", @@ -60,9 +60,11 @@ "room.loweredHand": "{displayName} je spustio ruku", "room.extraVideo": "Dodatni video", "room.overRoomLimit": "Soba je popunjena, pokušajte ponovno kasnije.", - "room.help": null, - "room.about": null, - "room.shortcutKeys": null, + "room.help": "Pomoć", + "room.about": "O programu", + "room.shortcutKeys": "Prečaci", + "room.browsePeersSpotlight": "Pretražite sudionike u središtu pažnje", + "room.stopAllScreenSharing": null, "me.mutedPTT": "Utišani ste, pritisnite i držite SPACE tipku za razgovor", @@ -81,9 +83,12 @@ "tooltip.participants": "Prikaži sudionike", "tooltip.kickParticipant": "Izbaci sudionika", "tooltip.muteParticipant": "Utišaj sudionika", - "tooltip.muteParticipantVideo": "Ne primaj video sudionika", + "tooltip.muteParticipantVideo": "Ne prikazuj video sudionika", "tooltip.raisedHand": "Podigni ruku", - "tooltip.muteScreenSharing": null, + "tooltip.muteScreenSharing": "Ne prikazuj dijeljenje ekrana sudionika", + "tooltip.muteParticipantAudioModerator": "Utišaj sve sudionike", + "tooltip.muteParticipantVideoModerator": "Ne prikazuj video svih sudionika", + "tooltip.muteScreenSharingModerator": "Ne prikazuj dijeljenje ekrana svih sudionika", "label.roomName": "Naziv sobe", "label.chooseRoomButton": "Nastavi", @@ -109,11 +114,11 @@ "label.ultra": "Ultra visoka (UHD)", "label.close": "Zatvori", "label.media": "Medij", - "label.appearence": "Prikaz", + "label.appearance": "Prikaz", "label.advanced": "Napredno", "label.addVideo": "Dodaj video", "label.promoteAllPeers": "Promoviraj sve", - "label.moreActions": null, + "label.moreActions": "Više akcija", "settings.settings": "Postavke", "settings.camera": "Kamera", @@ -133,12 +138,12 @@ "settings.lastn": "Broj vidljivih videozapisa", "settings.hiddenControls": "Skrivene kontrole medija", "settings.notificationSounds": "Zvuk obavijesti", - "settings.showNotifications": null, - "settings.buttonControlBar": null, - "settings.echoCancellation": null, - "settings.autoGainControl": null, - "settings.noiseSuppression": null, - "settings.drawerOverlayed": null, + "settings.showNotifications": "Prikaži obavijesti", + "settings.buttonControlBar": "Razdvoji upravljanje medijima", + "settings.echoCancellation": "Poništavanje jeke", + "settings.autoGainControl": "Automatsko upravljanje jačinom zvuka", + "settings.noiseSuppression": "Poništavanje šuma", + "settings.drawerOverlayed": "Bočni izbornik iznad sadržaja", "filesharing.saveFileError": "Nije moguće spremiti datoteku", "filesharing.startingFileShare": "Pokušaj dijeljenja datoteke", @@ -183,5 +188,6 @@ "moderator.clearChat": "Moderator je izbrisao razgovor", "moderator.clearFiles": "Moderator je izbrisao datoteke", "moderator.muteAudio": "Moderator je utišao tvoj zvuk", - "moderator.muteVideo": "Moderator je zaustavio tvoj video" + "moderator.muteVideo": "Moderator je zaustavio tvoj video", + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/hu.json b/app/src/translations/hu.json index cf65f1d..1a2832b 100644 --- a/app/src/translations/hu.json +++ b/app/src/translations/hu.json @@ -49,8 +49,8 @@ "room.spotlights": "Látható résztvevők", "room.passive": "Passzív résztvevők", "room.videoPaused": "Ez a videóstream szünetel", - "room.muteAll": "Mindenki némítása", - "room.stopAllVideo": "Mindenki video némítása", + "room.muteAll": "Összes némítása", + "room.stopAllVideo": "Összes video némítása", "room.closeMeeting": "Konferencia lebontása", "room.clearChat": "Chat történelem kiürítése", "room.clearFileSharing": "File megosztás kiürítése", @@ -63,6 +63,8 @@ "room.help": "Segítség", "room.about": "Névjegy", "room.shortcutKeys": "Billentyűparancsok", + "room.browsePeersSpotlight": "Résztvevők böngészése", + "room.stopAllScreenSharing": "Összes képernyőmegosztás leállítása", "me.mutedPTT": "Némítva vagy, ha beszélnél nyomd le a szóköz billentyűt", @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": "Résztvevő videóstreamének némítása", "tooltip.raisedHand": "Jelentkezés", "tooltip.muteScreenSharing": "Képernyőmegosztás szüneteltetése", + "tooltip.muteParticipantAudioModerator": "Résztvevő hangjának általános némítása", + "tooltip.muteParticipantVideoModerator": "Résztvevő videójának általános némítása", + "tooltip.muteScreenSharingModerator": "Résztvevő képernyőmegosztásának általános némítása", "label.roomName": "Konferencia", "label.chooseRoomButton": "Tovább", @@ -109,7 +114,7 @@ "label.ultra": "Ultra magas (UHD)", "label.close": "Bezár", "label.media": "Média", - "label.appearence": "Megjelenés", + "label.appearance": "Megjelenés", "label.advanced": "Részletek", "label.addVideo": "Videó hozzáadása", "label.promoteAllPeers": "Mindenkit beengedek", @@ -138,7 +143,7 @@ "settings.echoCancellation": "Visszhangelnyomás", "settings.autoGainControl": "Automatikus hangerő", "settings.noiseSuppression": "Zajelnyomás", - "settings.drawerOverlayed": null, + "settings.drawerOverlayed": "Oldalsáv a tartalom felett", "filesharing.saveFileError": "A file-t nem sikerült elmenteni", "filesharing.startingFileShare": "Fájl megosztása", @@ -183,5 +188,6 @@ "moderator.clearChat": "A moderátor kiürítette a chat történelmet", "moderator.clearFiles": "A moderátor kiürítette a file megosztás történelmet", "moderator.muteAudio": "A moderátor elnémította a hangod", - "moderator.muteVideo": "A moderátor elnémította a videód" + "moderator.muteVideo": "A moderátor elnémította a videód", + "moderator.muteScreenSharing": "A moderátor leállította képernyőmegosztásod" } diff --git a/app/src/translations/it.json b/app/src/translations/it.json index 312a2ff..02b53e7 100644 --- a/app/src/translations/it.json +++ b/app/src/translations/it.json @@ -63,7 +63,9 @@ "room.help": "Aiuto", "room.about": "Informazioni su", "room.shortcutKeys": "Scorciatoie da tastiera", - + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, + "me.mutedPTT": "Sei mutato, tieni premuto SPAZIO per parlare", "roles.gotRole": "Hai ottenuto il ruolo: {role}", @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": "Ferma video partecipante", "tooltip.raisedHand": "Mano alzata", "tooltip.muteScreenSharing": "Ferma condivisione schermo partecipante", + "tooltip.muteParticipantAudioModerator": "Sospendi audio globale", + "tooltip.muteParticipantVideoModerator": "Sospendi video globale", + "tooltip.muteScreenSharingModerator": "Sospendi condivisione schermo globale", "label.roomName": "Nome della stanza", "label.chooseRoomButton": "Continua", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Chiudi", "label.media": "Media", - "label.appearence": "Aspetto", + "label.appearance": "Aspetto", "label.advanced": "Avanzate", "label.addVideo": "Aggiungi video", "label.promoteAllPeers": "Promuovi tutti", @@ -183,5 +188,6 @@ "moderator.clearChat": "Il moderatore ha pulito la chat", "moderator.clearFiles": "Il moderatore ha pulito i file", "moderator.muteAudio": "Il moderatore ha mutato il tuo audio", - "moderator.muteVideo": "Il moderatore ha fermato il tuo video" + "moderator.muteVideo": "Il moderatore ha fermato il tuo video", + "moderator.muteScreenSharing": null } \ No newline at end of file diff --git a/app/src/translations/lv.json b/app/src/translations/lv.json index 7bf0b24..62ee61e 100644 --- a/app/src/translations/lv.json +++ b/app/src/translations/lv.json @@ -62,6 +62,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": "Jūs esat noklusināts. Turiet taustiņu SPACE-BAR, lai runātu", @@ -83,6 +85,9 @@ "tooltip.muteParticipantVideo": "Atslēgt dalībnieka video", "tooltip.raisedHand": "Pacelt roku", "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Sapulces telpas nosaukums (ID)", "label.chooseRoomButton": "Turpināt", @@ -107,7 +112,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Aizvērt", "label.media": "Mediji", - "label.appearence": "Izskats", + "label.appearance": "Izskats", "label.advanced": "Advancēts", "label.addVideo": "Pievienot video", "label.moreActions": null, @@ -177,5 +182,6 @@ "moderator.clearChat": "Moderators nodzēsa tērziņus", "moderator.clearFiles": "Moderators notīrīja failus", "moderator.muteAudio": "Moderators noklusināja jūsu mikrofonu", - "moderator.muteVideo": "Moderators atslēdza jūsu kameru" + "moderator.muteVideo": "Moderators atslēdza jūsu kameru", + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/nb.json b/app/src/translations/nb.json index 251858b..5bafeb6 100644 --- a/app/src/translations/nb.json +++ b/app/src/translations/nb.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": "Du er dempet, hold nede SPACE for å snakke", @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": "Demp deltakervideo", "tooltip.raisedHand": "Rekk opp hånden", "tooltip.muteScreenSharing": "Demp deltaker skjermdeling", + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Møtenavn", "label.chooseRoomButton": "Fortsett", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Lukk", "label.media": "Media", - "label.appearence": "Utseende", + "label.appearance": "Utseende", "label.advanced": "Avansert", "label.addVideo": "Legg til video", "label.promoteAllPeers": "Slipp inn alle", @@ -183,5 +188,6 @@ "moderator.clearChat": "Moderator tømte chatten", "moderator.clearFiles": "Moderator fjernet filer", "moderator.muteAudio": "Moderator mutet lyden din", - "moderator.muteVideo": "Moderator mutet videoen din" + "moderator.muteVideo": "Moderator mutet videoen din", + "moderator.muteScreenSharing": null } \ No newline at end of file diff --git a/app/src/translations/pl.json b/app/src/translations/pl.json index 174684c..7612f99 100644 --- a/app/src/translations/pl.json +++ b/app/src/translations/pl.json @@ -63,6 +63,8 @@ "room.help": "Pomoc", "room.about": "O pogramie", "room.shortcutKeys": "Skróty klawiaturowe", + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": "Masz wyciszony mikrofon, przytrzymaj spację aby mówić", @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": "Wyłącz wideo użytkownika", "tooltip.raisedHand": "Podnieś rękę", "tooltip.muteScreenSharing": "Anuluj udostępniania pulpitu przez użytkownika", + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Nazwa konferencji", "label.chooseRoomButton": "Kontynuuj", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Zamknij", "label.media": "Media", - "label.appearence": "Wygląd", + "label.appearance": "Wygląd", "label.advanced": "Zaawansowane", "label.addVideo": "Dodaj wideo", "label.promoteAllPeers": "Wpuść wszystkich", @@ -183,5 +188,6 @@ "moderator.clearChat": "Moderator wyczyścił chat", "moderator.clearFiles": "Moderator wyczyścił pliki", "moderator.muteAudio": "Moderator wyciszył audio", - "moderator.muteVideo": "Moderator wyciszył twoje video" + "moderator.muteVideo": "Moderator wyciszył twoje video", + "moderator.muteScreenSharing": null } \ No newline at end of file diff --git a/app/src/translations/pt.json b/app/src/translations/pt.json index 8250231..a2a3310 100644 --- a/app/src/translations/pt.json +++ b/app/src/translations/pt.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Nome da sala", "label.chooseRoomButton": "Continuar", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Fechar", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/ro.json b/app/src/translations/ro.json index 1ba455c..7161bd4 100644 --- a/app/src/translations/ro.json +++ b/app/src/translations/ro.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Numele camerei", "label.chooseRoomButton": "Continuare", @@ -109,7 +114,7 @@ "label.ultra": "Rezoluție ultra înaltă (UHD)", "label.close": "Închide", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/tr.json b/app/src/translations/tr.json index 524c557..1876bab 100644 --- a/app/src/translations/tr.json +++ b/app/src/translations/tr.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Oda adı", "label.chooseRoomButton": "Devam", @@ -109,7 +114,7 @@ "label.ultra": "Ultra (UHD)", "label.close": "Kapat", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -175,5 +180,6 @@ "devices.screenSharingError": "Ekranınıza erişilirken bir hata oluştu", "devices.cameraDisconnected": "Kamera bağlı değil", - "devices.cameraError": "Kameranıza erişilirken bir hata oluştu" + "devices.cameraError": "Kameranıza erişilirken bir hata oluştu", + "moderator.muteScreenSharing": null } diff --git a/app/src/translations/tw.json b/app/src/translations/tw.json new file mode 100644 index 0000000..99c32d7 --- /dev/null +++ b/app/src/translations/tw.json @@ -0,0 +1,192 @@ +{ + "socket.disconnected": "您已斷開連接", + "socket.reconnecting": "嘗試重新連接", + "socket.reconnected": "您已重新連接", + "socket.requestError": "服務器請求錯誤", + + "room.chooseRoom": "選擇您要加入的房間的名稱", + "room.cookieConsent": "這個網站使用Cookies來提升您的使用者體驗", + "room.consentUnderstand": "了解", + "room.joined": "您已加入房間", + "room.cantJoin": "無法加入房間", + "room.youLocked": "您已鎖定房間", + "room.cantLock": "無法鎖定房間", + "room.youUnLocked": "您解鎖了房間", + "room.cantUnLock": "無法解鎖房間", + "room.locked": "房間已鎖定", + "room.unlocked": "房間現已解鎖", + "room.newLobbyPeer": "新參與者進入大廳", + "room.lobbyPeerLeft": "參與者離開大廳", + "room.lobbyPeerChangedDisplayName": "大廳的參與者將名稱變更為 {displayName}", + "room.lobbyPeerChangedPicture": "大廳的參與者變更了圖片", + "room.setAccessCode": "設置房間的進入密碼", + "room.accessCodeOn": "房間的進入密碼現已啟用", + "room.accessCodeOff": "房間的進入密碼已停用", + "room.peerChangedDisplayName": "{oldDisplayName} 已變更名稱為 {displayName}", + "room.newPeer": "{displayName} 加入了會議室", + "room.newFile": "有新文件", + "room.toggleAdvancedMode": "切換進階模式", + "room.setDemocraticView": "已更改為使用者佈局", + "room.setFilmStripView": "已更改為投影片佈局", + "room.loggedIn": "您已登入", + "room.loggedOut": "您已登出", + "room.changedDisplayName": "您的顯示名稱已變更為 {displayName}", + "room.changeDisplayNameError": "更改顯示名稱時發生錯誤", + "room.chatError": "無法發送聊天消息", + "room.aboutToJoin": "您即將參加會議", + "room.roomId": "房間ID: {roomName}", + "room.setYourName": "設置您的顯示名稱,並選擇您想加入的方式:", + "room.audioOnly": "僅通話", + "room.audioVideo": "通話和視訊", + "room.youAreReady": "準備完畢!", + "room.emptyRequireLogin": "房間是空的! 您可以登錄以開始會議或等待主持人加入", + "room.locketWait": "房間已鎖定! 請等待其他人允許您進入...", + "room.lobbyAdministration": "大廳管理", + "room.peersInLobby": "大廳的參與者", + "room.lobbyEmpty": "大廳目前沒有人", + "room.hiddenPeers": "{hiddenPeersCount, plural, one {participant} other {participants}}", + "room.me": "我", + "room.spotlights": "Spotlight中的參與者", + "room.passive": "被動參與者", + "room.videoPaused": "視訊已關閉", + "room.muteAll": "全部靜音", + "room.stopAllVideo": "關閉全部視訊", + "room.closeMeeting": "關閉會議", + "room.clearChat": "清除聊天", + "room.clearFileSharing": "清除檔案", + "room.speechUnsupported": "您的瀏覽器不支援語音辨識", + "room.moderatoractions": "管理員動作", + "room.raisedHand": "{displayName} 舉手了", + "room.loweredHand": "{displayName} 放下了他的手", + "room.extraVideo": "其他視訊", + "room.overRoomLimit": "房間已滿,請稍後重試", + "room.help": "幫助", + "room.about": "關於", + "room.shortcutKeys": "鍵盤快速鍵", + "room.stopAllScreenSharing": null, + + "me.mutedPTT": "您已靜音,請按下 空白鍵 來說話", + + "roles.gotRole": "您已取得身份: {role}", + "roles.lostRole": "您的 {role} 身份已被撤銷", + + "tooltip.login": "登入", + "tooltip.logout": "登出", + "tooltip.admitFromLobby": "從大廳允許", + "tooltip.lockRoom": "鎖定房間", + "tooltip.unLockRoom": "解鎖房間", + "tooltip.enterFullscreen": "進入全螢幕", + "tooltip.leaveFullscreen": "退出全螢幕", + "tooltip.lobby": "顯示大廳", + "tooltip.settings": "顯示設置", + "tooltip.participants": "顯示參加者", + "tooltip.kickParticipant": "踢出", + "tooltip.muteParticipant": "靜音", + "tooltip.muteParticipantVideo": "隱藏視訊", + "tooltip.raisedHand": "舉手", + "tooltip.muteScreenSharing": "隱藏螢幕分享", + "tooltip.muteParticipantAudioModerator": "關閉聲音", + "tooltip.muteParticipantVideoModerator": "關閉視訊", + "tooltip.muteScreenSharingModerator": "關閉螢幕分享", + + "label.roomName": "房間名稱", + "label.chooseRoomButton": "繼續", + "label.yourName": "您的名字", + "label.newWindow": "新視窗", + "label.fullscreen": "全螢幕", + "label.openDrawer": "打開側邊欄", + "label.leave": "離開", + "label.chatInput": "輸入聊天訊息", + "label.chat": "聊天", + "label.filesharing": "文件分享", + "label.participants": "參與者", + "label.shareFile": "分享文件", + "label.shareGalleryFile": "分享圖片", + "label.fileSharingUnsupported": "不支援文件分享", + "label.unknown": "未知", + "label.democratic": "使用者佈局", + "label.filmstrip": "投影片佈局", + "label.low": "低", + "label.medium": "中", + "label.high": "高 (HD)", + "label.veryHigh": "非常高 (FHD)", + "label.ultra": "超高 (UHD)", + "label.close": "關閉", + "label.media": "媒體", + "label.appearance": "外觀", + "label.advanced": "進階", + "label.addVideo": "新增視訊", + "label.promoteAllPeers": "提升全部", + "label.moreActions": "更多", + + "settings.settings": "設置", + "settings.camera": "視訊來源", + "settings.selectCamera": "選擇視訊來源", + "settings.cantSelectCamera": "無法選擇此視訊來源", + "settings.audio": "音訊來源", + "settings.selectAudio": "選擇音訊來源", + "settings.cantSelectAudio": "無法選擇音訊來源", + "settings.audioOutput": "音訊輸出", + "settings.selectAudioOutput": "選擇音訊輸出設備", + "settings.cantSelectAudioOutput": "無法選擇音訊輸出設備", + "settings.resolution": "選擇視訊解析度", + "settings.layout": "房間佈局", + "settings.selectRoomLayout": "選擇房間佈局", + "settings.advancedMode": "進階模式", + "settings.permanentTopBar": "固定頂端列", + "settings.lastn": "視訊數量上限", + "settings.hiddenControls": "隱藏控制按鈕", + "settings.notificationSounds": "通知音效", + "settings.showNotifications": "顯示通知", + "settings.buttonControlBar": "獨立控制按鈕", + "settings.echoCancellation": "回音消除", + "settings.autoGainControl": "自動增益控制", + "settings.noiseSuppression": "噪音消除", + "settings.drawerOverlayed": "側邊欄覆蓋畫面", + + "filesharing.saveFileError": "無法保存文件", + "filesharing.startingFileShare": "開始分享文件", + "filesharing.successfulFileShare": "文件已成功分享", + "filesharing.unableToShare": "無法分享文件", + "filesharing.error": "文件分享發生錯誤", + "filesharing.finished": "文件分享成功", + "filesharing.save": "保存文件", + "filesharing.sharedFile": "{displayName} 分享了一個文件", + "filesharing.download": "下載文件", + "filesharing.missingSeeds": "如果過了很久還是無法下載,則可能沒有人播種了。請讓上傳者重新上傳您想要的文件。", + + "devices.devicesChanged": "您的設備已更改,請在設置中設定您的設備", + + "device.audioUnsupported": "不支援您的音訊格式", + "device.activateAudio": "開啟音訊", + "device.muteAudio": "靜音", + "device.unMuteAudio": "取消靜音", + + "device.videoUnsupported": "不支援您的視訊格式", + "device.startVideo": "開啟視訊", + "device.stopVideo": "關閉視訊", + + "device.screenSharingUnsupported": "不支援您的螢幕分享格式", + "device.startScreenSharing": "開始螢幕分享", + "device.stopScreenSharing": "停止螢幕分享", + + "devices.microphoneDisconnected": "麥克風已斷開", + "devices.microphoneError": "麥克風發生錯誤", + "devices.microphoneMute": "麥克風靜音", + "devices.microphoneUnMute": "取消麥克風靜音", + "devices.microphoneEnable": "麥克風已啟用", + "devices.microphoneMuteError": "無法使麥克風靜音", + "devices.microphoneUnMuteError": "無法取消麥克風靜音", + + "devices.screenSharingDisconnected" : "螢幕分享已斷開", + "devices.screenSharingError": "螢幕分享時發生錯誤", + + "devices.cameraDisconnected": "相機已斷開連接", + "devices.cameraError": "存取相機時發生錯誤", + + "moderator.clearChat": "管理員清除了聊天", + "moderator.clearFiles": "管理員清除了所有檔案", + "moderator.muteAudio": "您已被管理員靜音", + "moderator.muteVideo": "您的視訊已被管理員關閉", + "moderator.muteScreenSharing": null +} \ No newline at end of file diff --git a/app/src/translations/uk.json b/app/src/translations/uk.json index a8cc077..2ee6774 100644 --- a/app/src/translations/uk.json +++ b/app/src/translations/uk.json @@ -63,6 +63,8 @@ "room.help": null, "room.about": null, "room.shortcutKeys": null, + "room.browsePeersSpotlight": null, + "room.stopAllScreenSharing": null, "me.mutedPTT": null, @@ -84,6 +86,9 @@ "tooltip.muteParticipantVideo": null, "tooltip.raisedHand": null, "tooltip.muteScreenSharing": null, + "tooltip.muteParticipantAudioModerator": null, + "tooltip.muteParticipantVideoModerator": null, + "tooltip.muteScreenSharingModerator": null, "label.roomName": "Назва кімнати", "label.chooseRoomButton": "Продовжити", @@ -109,7 +114,7 @@ "label.ultra": "Ультра (UHD)", "label.close": "Закрити", "label.media": null, - "label.appearence": null, + "label.appearance": null, "label.advanced": null, "label.addVideo": null, "label.promoteAllPeers": null, @@ -183,5 +188,6 @@ "moderator.clearChat": null, "moderator.clearFiles": null, "moderator.muteAudio": null, - "moderator.muteVideo": null -} \ No newline at end of file + "moderator.muteVideo": null, + "moderator.muteScreenSharing": null +} \ No newline at end of file diff --git a/server/lib/Room.js b/server/lib/Room.js index 74accc4..f110327 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -1441,6 +1441,38 @@ class Room extends EventEmitter break; } + case 'moderator:stopAllScreenSharing': + { + if (!this._hasPermission(peer, MODERATE_ROOM)) + throw new Error('peer not authorized'); + + // Spread to others + this._notification(peer.socket, 'moderator:stopScreenSharing', null, true); + + cb(); + + break; + } + + case 'moderator:stopScreenSharing': + { + if (!this._hasPermission(peer, MODERATE_ROOM)) + throw new Error('peer not authorized'); + + const { peerId } = request.data; + + const stopVideoPeer = this._peers[peerId]; + + if (!stopVideoPeer) + throw new Error(`peer with id "${peerId}" not found`); + + this._notification(stopVideoPeer.socket, 'moderator:stopScreenSharing'); + + cb(); + + break; + } + case 'moderator:closeMeeting': { if (!this._hasPermission(peer, MODERATE_ROOM))