Add posibility to have separate media buttons, fixes #309

auto_join_3.3
Håvar Aambø Fosstveit 2020-05-07 13:35:29 +02:00
parent 7e91609276
commit cfdaceed22
28 changed files with 739 additions and 381 deletions

View File

@ -54,6 +54,9 @@ var config =
},
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,
lastN : 4,
mobileLastN : 1,
// Highest number of speakers user can select

View File

@ -38,6 +38,11 @@ export const togglePermanentTopBar = () =>
type : 'TOGGLE_PERMANENT_TOPBAR'
});
export const toggleButtonControlBar = () =>
({
type : 'TOGGLE_BUTTON_CONTROL_BAR'
});
export const toggleShowNotifications = () =>
({
type : 'TOGGLE_SHOW_NOTIFICATIONS'

View File

@ -77,7 +77,29 @@ const styles = (theme) =>
{
position : 'relative',
width : '100%',
height : '100%'
height : '100%',
'& p' :
{
position : 'absolute',
float : 'left',
top : '50%',
left : '50%',
transform : 'translate(-50%, -50%)',
color : 'rgba(255, 255, 255, 0.5)',
fontSize : '7em',
zIndex : 30,
margin : 0,
opacity : 0,
transition : 'opacity 0.1s ease-in-out',
'&.hover' :
{
opacity : 1
},
'&.smallContainer' :
{
fontSize : '3em'
}
}
},
controls :
{
@ -100,27 +122,6 @@ const styles = (theme) =>
'&.hover' :
{
opacity : 1
},
'& p' :
{
position : 'absolute',
float : 'left',
top : '50%',
left : '50%',
transform : 'translate(-50%, -50%)',
color : 'rgba(255, 255, 255, 0.5)',
fontSize : '7em',
margin : 0,
opacity : 0,
transition : 'opacity 0.1s ease-in-out',
'&.hover' :
{
opacity : 1
},
'&.smallContainer' :
{
fontSize : '3em'
}
}
},
ptt :
@ -330,6 +331,18 @@ const Me = (props) =>
/>
</div>
}
<p className={
classnames(
hover ? 'hover' : null,
smallContainer ? 'smallContainer' : null
)}
>
<FormattedMessage
id='room.me'
defaultMessage='ME'
/>
</p>
{ !settings.buttonControlBar &&
<div
className={classnames(
classes.controls,
@ -356,21 +369,8 @@ const Me = (props) =>
}, 2000);
}}
>
<p className={
classnames(
hover ? 'hover' : null,
smallContainer ? 'smallContainer' : null
)}
>
<FormattedMessage
id='room.me'
defaultMessage='ME'
/>
</p>
<React.Fragment>
<Tooltip title={micTip} placement='left'>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -424,10 +424,8 @@ const Me = (props) =>
}
</Fab>
}
</div>
</Tooltip>
<Tooltip title={webcamTip} placement='left'>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -475,11 +473,9 @@ const Me = (props) =>
}
</Fab>
}
</div>
</Tooltip>
{ me.browser.platform !== 'mobile' &&
<Tooltip title={screenTip} placement='left'>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -566,11 +562,11 @@ const Me = (props) =>
}
</Fab>
}
</div>
</Tooltip>
}
</React.Fragment>
</div>
}
<VideoView
isMe
@ -659,7 +655,6 @@ const Me = (props) =>
</p>
<Tooltip title={webcamTip} placement='left'>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -695,7 +690,6 @@ const Me = (props) =>
<VideoIcon />
</Fab>
}
</div>
</Tooltip>
</div>

View File

@ -249,7 +249,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -297,7 +296,6 @@ const Peer = (props) =>
}
</Fab>
}
</div>
</Tooltip>
{ browser.platform !== 'mobile' &&
@ -308,7 +306,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -349,7 +346,6 @@ const Peer = (props) =>
<NewWindowIcon />
</Fab>
}
</div>
</Tooltip>
}
@ -360,7 +356,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -395,7 +390,6 @@ const Peer = (props) =>
<FullScreenIcon />
</Fab>
}
</div>
</Tooltip>
</div>
@ -507,7 +501,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -548,7 +541,6 @@ const Peer = (props) =>
<NewWindowIcon />
</Fab>
}
</div>
</Tooltip>
}
@ -559,7 +551,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
{ smallContainer ?
<IconButton
aria-label={intl.formatMessage({
@ -594,7 +585,6 @@ const Peer = (props) =>
<FullScreenIcon />
</Fab>
}
</div>
</Tooltip>
</div>
@ -694,7 +684,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
<Fab
aria-label={intl.formatMessage({
id : 'label.newWindow',
@ -713,7 +702,6 @@ const Peer = (props) =>
>
<NewWindowIcon />
</Fab>
</div>
</Tooltip>
}
@ -724,7 +712,6 @@ const Peer = (props) =>
})}
placement={smallScreen ? 'top' : 'left'}
>
<div>
<Fab
aria-label={intl.formatMessage({
id : 'label.fullscreen',
@ -740,7 +727,6 @@ const Peer = (props) =>
>
<FullScreenIcon />
</Fab>
</div>
</Tooltip>
</div>
<VideoView

View File

@ -0,0 +1,256 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { meProducersSelector } from '../Selectors';
import { withStyles } from '@material-ui/core/styles';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import classnames from 'classnames';
import * as appPropTypes from '../appPropTypes';
import { withRoomContext } from '../../RoomContext';
import Fab from '@material-ui/core/Fab';
import Tooltip from '@material-ui/core/Tooltip';
import MicIcon from '@material-ui/icons/Mic';
import MicOffIcon from '@material-ui/icons/MicOff';
import VideoIcon from '@material-ui/icons/Videocam';
import VideoOffIcon from '@material-ui/icons/VideocamOff';
import ScreenIcon from '@material-ui/icons/ScreenShare';
import ScreenOffIcon from '@material-ui/icons/StopScreenShare';
const styles = (theme) =>
({
root :
{
position : 'fixed',
display : 'flex',
[theme.breakpoints.up('md')] :
{
top : '50%',
transform : 'translate(0%, -50%)',
flexDirection : 'column',
justifyContent : 'center',
alignItems : 'center',
left : theme.spacing(1)
},
[theme.breakpoints.down('sm')] :
{
flexDirection : 'row',
bottom : theme.spacing(1),
left : '50%',
transform : 'translate(-50%, -0%)'
}
},
fab :
{
margin : theme.spacing(1)
},
show :
{
opacity : 1,
transition : 'opacity .5s'
},
hide :
{
opacity : 0,
transition : 'opacity .5s'
}
});
const ButtonControlBar = (props) =>
{
const {
roomClient,
toolbarsVisible,
me,
micProducer,
webcamProducer,
screenProducer,
classes,
theme
} = props;
let micState;
let micTip;
if (!me.canSendMic || !micProducer)
{
micState = 'unsupported';
micTip = 'Audio unsupported';
}
else if (!micProducer.locallyPaused && !micProducer.remotelyPaused)
{
micState = 'on';
micTip = 'Mute audio';
}
else
{
micState = 'off';
micTip = 'Unmute audio';
}
let webcamState;
let webcamTip;
if (!me.canSendWebcam)
{
webcamState = 'unsupported';
webcamTip = 'Video unsupported';
}
else if (webcamProducer)
{
webcamState = 'on';
webcamTip = 'Stop video';
}
else
{
webcamState = 'off';
webcamTip = 'Start video';
}
let screenState;
let screenTip;
if (!me.canShareScreen)
{
screenState = 'unsupported';
screenTip = 'Screen sharing not supported';
}
else if (screenProducer)
{
screenState = 'on';
screenTip = 'Stop screen sharing';
}
else
{
screenState = 'off';
screenTip = 'Start screen sharing';
}
const smallScreen = useMediaQuery(theme.breakpoints.down('sm'));
return (
<div
className={
classnames(classes.root, toolbarsVisible ? classes.show : classes.hide)
}
>
<Tooltip title={micTip} placement={smallScreen ? 'top' : 'right'}>
<Fab
aria-label='Mute mic'
className={classes.fab}
disabled={!me.canSendMic || me.audioInProgress}
color={micState === 'on' ? 'default' : 'secondary'}
size={smallScreen ? 'large' : 'medium'}
onClick={() =>
{
micState === 'on' ?
roomClient.muteMic() :
roomClient.unmuteMic();
}}
>
{ micState === 'on' ?
<MicIcon />
:
<MicOffIcon />
}
</Fab>
</Tooltip>
<Tooltip title={webcamTip} placement={smallScreen ? 'top' : 'right'}>
<Fab
aria-label='Mute video'
className={classes.fab}
disabled={!me.canSendWebcam || me.webcamInProgress}
color={webcamState === 'on' ? 'default' : 'secondary'}
size={smallScreen ? 'large' : 'medium'}
onClick={() =>
{
webcamState === 'on' ?
roomClient.disableWebcam() :
roomClient.enableWebcam();
}}
>
{ webcamState === 'on' ?
<VideoIcon />
:
<VideoOffIcon />
}
</Fab>
</Tooltip>
<Tooltip title={screenTip} placement={smallScreen ? 'top' : 'right'}>
<Fab
aria-label='Share screen'
className={classes.fab}
disabled={!me.canShareScreen || me.screenShareInProgress}
color={screenState === 'on' ? 'primary' : 'default'}
size={smallScreen ? 'large' : 'medium'}
onClick={() =>
{
switch (screenState)
{
case 'on':
{
roomClient.disableScreenSharing();
break;
}
case 'off':
{
roomClient.enableScreenSharing();
break;
}
default:
{
break;
}
}
}}
>
{ screenState === 'on' || screenState === 'unsupported' ?
<ScreenOffIcon/>
:null
}
{ screenState === 'off' ?
<ScreenIcon/>
:null
}
</Fab>
</Tooltip>
</div>
);
};
ButtonControlBar.propTypes =
{
roomClient : PropTypes.any.isRequired,
toolbarsVisible : PropTypes.bool.isRequired,
me : appPropTypes.Me.isRequired,
micProducer : appPropTypes.Producer,
webcamProducer : appPropTypes.Producer,
screenProducer : appPropTypes.Producer,
classes : PropTypes.object.isRequired,
theme : PropTypes.object.isRequired
};
const mapStateToProps = (state) =>
({
toolbarsVisible : state.room.toolbarsVisible,
...meProducersSelector(state),
me : state.me
});
export default withRoomContext(connect(
mapStateToProps,
null,
null,
{
areStatesEqual : (next, prev) =>
{
return (
prev.room.toolbarsVisible === next.room.toolbarsVisible &&
prev.producers === next.producers &&
prev.me === next.me
);
}
}
)(withStyles(styles, { withTheme: true })(ButtonControlBar)));

View File

@ -11,10 +11,9 @@ import Peer from '../Containers/Peer';
import Me from '../Containers/Me';
const RATIO = 1.334;
const PADDING_V = 50;
const PADDING_H = 0;
const PADDING = 60;
const styles = () =>
const styles = (theme) =>
({
root :
{
@ -36,6 +35,14 @@ const styles = () =>
{
paddingTop : 60,
transition : 'padding .5s'
},
buttonControlBar :
{
paddingLeft : 60,
[theme.breakpoints.down('sm')] :
{
paddingLeft : 0
}
}
});
@ -66,9 +73,11 @@ class Democratic extends React.PureComponent
return;
}
const width = this.peersRef.current.clientWidth - PADDING_H;
const height = this.peersRef.current.clientHeight -
(this.props.toolbarsVisible || this.props.permanentTopBar ? PADDING_V : PADDING_H);
const width =
this.peersRef.current.clientWidth - (this.props.buttonControlBar ? PADDING : 0);
const height =
this.peersRef.current.clientHeight -
(this.props.toolbarsVisible || this.props.permanentTopBar ? PADDING : 0);
let x, y, space;
@ -130,6 +139,7 @@ class Democratic extends React.PureComponent
spotlightsPeers,
toolbarsVisible,
permanentTopBar,
buttonControlBar,
classes
} = this.props;
@ -144,7 +154,8 @@ class Democratic extends React.PureComponent
className={classnames(
classes.root,
toolbarsVisible || permanentTopBar ?
classes.showingToolBar : classes.hiddenToolBar
classes.showingToolBar : classes.hiddenToolBar,
buttonControlBar ? classes.buttonControlBar : null
)}
ref={this.peersRef}
>
@ -176,7 +187,8 @@ Democratic.propTypes =
boxes : PropTypes.number,
spotlightsPeers : PropTypes.array.isRequired,
toolbarsVisible : PropTypes.bool.isRequired,
permanentTopBar : PropTypes.bool,
permanentTopBar : PropTypes.bool.isRequired,
buttonControlBar : PropTypes.bool.isRequired,
classes : PropTypes.object.isRequired
};
@ -186,7 +198,8 @@ const mapStateToProps = (state) =>
boxes : videoBoxesSelector(state),
spotlightsPeers : spotlightPeersSelector(state),
toolbarsVisible : state.room.toolbarsVisible,
permanentTopBar : state.settings.permanentTopBar
permanentTopBar : state.settings.permanentTopBar,
buttonControlBar : state.settings.buttonControlBar
};
};
@ -203,8 +216,9 @@ export default connect(
prev.consumers === next.consumers &&
prev.room.spotlights === next.room.spotlights &&
prev.room.toolbarsVisible === next.room.toolbarsVisible &&
prev.settings.permanentTopBar === next.settings.permanentTopBar
prev.settings.permanentTopBar === next.settings.permanentTopBar &&
prev.settings.buttonControlBar === next.settings.buttonControlBar
);
}
}
)(withStyles(styles)(Democratic));
)(withStyles(styles, { withTheme: true })(Democratic));

View File

@ -25,6 +25,7 @@ import Settings from './Settings/Settings';
import TopBar from './Controls/TopBar';
import WakeLock from 'react-wakelock-react16';
import ExtraVideo from './Controls/ExtraVideo';
import ButtonControlBar from './Controls/ButtonControlBar';
const TIMEOUT = 5 * 1000;
@ -143,6 +144,7 @@ class Room extends React.PureComponent
browser,
advancedMode,
showNotifications,
buttonControlBar,
toolAreaOpen,
toggleToolArea,
classes,
@ -214,6 +216,10 @@ class Room extends React.PureComponent
<View advancedMode={advancedMode} />
{ buttonControlBar &&
<ButtonControlBar />
}
{ room.lockDialogOpen &&
<LockDialog />
}
@ -236,6 +242,7 @@ Room.propTypes =
browser : PropTypes.object.isRequired,
advancedMode : PropTypes.bool.isRequired,
showNotifications : PropTypes.bool.isRequired,
buttonControlBar : PropTypes.bool.isRequired,
toolAreaOpen : PropTypes.bool.isRequired,
setToolbarsVisible : PropTypes.func.isRequired,
toggleToolArea : PropTypes.func.isRequired,
@ -249,6 +256,7 @@ const mapStateToProps = (state) =>
browser : state.me.browser,
advancedMode : state.settings.advancedMode,
showNotifications : state.settings.showNotifications,
buttonControlBar : state.settings.buttonControlBar,
toolAreaOpen : state.toolarea.toolAreaOpen
});
@ -276,6 +284,7 @@ export default connect(
prev.me.browser === next.me.browser &&
prev.settings.advancedMode === next.settings.advancedMode &&
prev.settings.showNotifications === next.settings.showNotifications &&
prev.settings.buttonControlBar === next.settings.buttonControlBar &&
prev.toolarea.toolAreaOpen === next.toolarea.toolAreaOpen
);
}

View File

@ -30,6 +30,7 @@ const AppearenceSettings = ({
settings,
onTogglePermanentTopBar,
onToggleHiddenControls,
onToggleButtonControlBar,
onToggleShowNotifications,
handleChangeMode,
classes
@ -102,6 +103,14 @@ const AppearenceSettings = ({
defaultMessage : 'Hidden media controls'
})}
/>
<FormControlLabel
className={classes.setting}
control={<Checkbox checked={settings.buttonControlBar} onChange={onToggleButtonControlBar} value='buttonControlBar' />}
label={intl.formatMessage({
id : 'settings.buttonControlBar',
defaultMessage : 'Separate media controls'
})}
/>
<FormControlLabel
className={classes.setting}
control={<Checkbox checked={settings.showNotifications} onChange={onToggleShowNotifications} value='showNotifications' />}
@ -120,6 +129,7 @@ AppearenceSettings.propTypes =
settings : PropTypes.object.isRequired,
onTogglePermanentTopBar : PropTypes.func.isRequired,
onToggleHiddenControls : PropTypes.func.isRequired,
onToggleButtonControlBar : PropTypes.func.isRequired,
onToggleShowNotifications : PropTypes.func.isRequired,
handleChangeMode : PropTypes.func.isRequired,
classes : PropTypes.object.isRequired
@ -135,6 +145,7 @@ const mapDispatchToProps = {
onTogglePermanentTopBar : settingsActions.togglePermanentTopBar,
onToggleHiddenControls : settingsActions.toggleHiddenControls,
onToggleShowNotifications : settingsActions.toggleShowNotifications,
onToggleButtonControlBar : settingsActions.toggleButtonControlBar,
handleChangeMode : roomActions.setDisplayMode
};

View File

@ -265,7 +265,7 @@ const MediaSettings = ({
/>}
label={intl.formatMessage({
id : 'settings.echoCancellation',
defaultMessage : 'Echo Cancellation'
defaultMessage : 'Echo cancellation'
})}
/>
<FormControlLabel
@ -280,7 +280,7 @@ const MediaSettings = ({
/>}
label={intl.formatMessage({
id : 'settings.autoGainControl',
defaultMessage : 'Auto Gain Control'
defaultMessage : 'Auto gain control'
})}
/>
<FormControlLabel
@ -295,7 +295,7 @@ const MediaSettings = ({
/>}
label={intl.formatMessage({
id : 'settings.noiseSuppression',
defaultMessage : 'Noise Suppression'
defaultMessage : 'Noise suppression'
})}
/>
</form>

View File

@ -18,6 +18,7 @@ const initialState =
hiddenControls : false,
showNotifications : true,
notificationSounds : true,
buttonControlBar : window.config.buttonControlBar || false,
...window.config.defaultAudio
};
@ -145,6 +146,13 @@ const settings = (state = initialState, action) =>
return { ...state, permanentTopBar };
}
case 'TOGGLE_BUTTON_CONTROL_BAR':
{
const buttonControlBar = !state.buttonControlBar;
return { ...state, buttonControlBar };
}
case 'TOGGLE_HIDDEN_CONTROLS':
{
const hiddenControls = !state.hiddenControls;

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "无法保存文件",
"filesharing.startingFileShare": "正在尝试共享文件",

View File

@ -130,6 +130,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Není možné uložit soubor",
"filesharing.startingFileShare": "Pokouším se sdílet soubor",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Fehler beim Speichern der Datei",
"filesharing.startingFileShare": "Starte Teilen der Datei",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Kan ikke gemme fil",
"filesharing.startingFileShare": "Forsøger at dele filen",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Αδυναμία αποθήκευσης του αρχείου",
"filesharing.startingFileShare": "Προσπάθεια διαμοιρασμού αρχείου",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": "Hidden media controls",
"settings.notificationSounds": "Notification sounds",
"settings.showNotifications": "Show notifications",
"settings.buttonControlBar": "Separate media controls",
"settings.echoCancellation": "Echo cancellation",
"settings.autoGainControl": "Auto gain control",
"settings.noiseSuppression": "Noise suppression",
"filesharing.saveFileError": "Unable to save file",
"filesharing.startingFileShare": "Attempting to share file",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "No ha sido posible guardar el fichero",
"filesharing.startingFileShare": "Intentando compartir el fichero",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Impossible d'enregistrer le fichier",
"filesharing.startingFileShare": "Début du transfert de fichier",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": "Skrivene kontrole medija",
"settings.notificationSounds": "Zvuk obavijesti",
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Nije moguće spremiti datoteku",
"filesharing.startingFileShare": "Pokušaj dijeljenja datoteke",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": "Média Gombok automatikus elrejtése",
"settings.notificationSounds": "Értesítések hangjelzéssel",
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "A file-t nem sikerült elmenteni",
"filesharing.startingFileShare": "Fájl megosztása",

View File

@ -130,6 +130,10 @@
"settings.hiddenControls": "Controlli media nascosti",
"settings.notificationSounds": "Suoni di notifica",
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Impossibile salvare file",
"filesharing.startingFileShare": "Tentativo di condivisione file",

View File

@ -125,6 +125,10 @@
"settings.hiddenControls": "Slēpto mediju vadība",
"settings.notificationSounds": "Paziņojumu skaņas",
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Nav iespējams saglabāt failu",
"filesharing.startingFileShare": "Tiek mēģināts kopīgot failu",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": "Skjul media knapper",
"settings.notificationSounds": "Varslingslyder",
"settings.showNotifications": "Vis varslinger",
"settings.buttonControlBar": "Separate media knapper",
"settings.echoCancellation": "Echokansellering",
"settings.autoGainControl": "Auto gain kontroll",
"settings.noiseSuppression": "Støy reduksjon",
"filesharing.saveFileError": "Klarte ikke å lagre fil",
"filesharing.startingFileShare": "Starter fildeling",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Nie można zapisać pliku",
"filesharing.startingFileShare": "Próba udostępnienia pliku",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Impossível de gravar o ficheiro",
"filesharing.startingFileShare": "Tentando partilha de ficheiro",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Încercarea de a salva fișierul a eșuat",
"filesharing.startingFileShare": "Partajarea fișierului",

View File

@ -128,6 +128,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Dosya kaydedilemiyor",
"filesharing.startingFileShare": "Paylaşılan dosyaya erişiliyor",

View File

@ -131,6 +131,10 @@
"settings.hiddenControls": null,
"settings.notificationSounds": null,
"settings.showNotifications": null,
"settings.buttonControlBar": null,
"settings.echoCancellation": null,
"settings.autoGainControl": null,
"settings.noiseSuppression": null,
"filesharing.saveFileError": "Неможливо зберегти файл",
"filesharing.startingFileShare": "Спроба поділитися файлом",