Merge remote-tracking branch 'upstream/master' into nav-bar-performance-issue
This commit is contained in:
commit
cffe9e34be
@ -25,6 +25,7 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait {
|
||||
disablePrivChat = msg.body.disablePrivChat,
|
||||
disablePubChat = msg.body.disablePubChat,
|
||||
disableNote = msg.body.disableNote,
|
||||
hideUserList = msg.body.hideUserList,
|
||||
lockedLayout = msg.body.lockedLayout,
|
||||
lockOnJoin = msg.body.lockOnJoin,
|
||||
lockOnJoinConfigurable = msg.body.lockOnJoinConfigurable
|
||||
@ -50,6 +51,7 @@ trait ChangeLockSettingsInMeetingCmdMsgHdlr extends RightsManagementTrait {
|
||||
disablePrivChat = settings.disablePrivChat,
|
||||
disablePubChat = settings.disablePubChat,
|
||||
disableNote = settings.disableNote,
|
||||
hideUserList = settings.hideUserList,
|
||||
lockedLayout = settings.lockedLayout,
|
||||
lockOnJoin = settings.lockOnJoin,
|
||||
lockOnJoinConfigurable = settings.lockOnJoinConfigurable,
|
||||
|
@ -17,9 +17,14 @@ trait GetLockSettingsReqMsgHdlr {
|
||||
val envelope = BbbCoreEnvelope(GetLockSettingsRespMsg.NAME, routing)
|
||||
val body = GetLockSettingsRespMsgBody(
|
||||
disableCam = settings.disableCam,
|
||||
disableMic = settings.disableMic, disablePrivChat = settings.disablePrivChat,
|
||||
disablePubChat = settings.disablePubChat, disableNote = settings.disableNote, lockedLayout = settings.lockedLayout,
|
||||
lockOnJoin = settings.lockOnJoin, lockOnJoinConfigurable = settings.lockOnJoinConfigurable
|
||||
disableMic = settings.disableMic,
|
||||
disablePrivChat = settings.disablePrivChat,
|
||||
disablePubChat = settings.disablePubChat,
|
||||
disableNote = settings.disableNote,
|
||||
hideUserList = settings.hideUserList,
|
||||
lockedLayout = settings.lockedLayout,
|
||||
lockOnJoin = settings.lockOnJoin,
|
||||
lockOnJoinConfigurable = settings.lockOnJoinConfigurable
|
||||
)
|
||||
val header = BbbClientMsgHeader(GetLockSettingsRespMsg.NAME, meetingId, requestedBy)
|
||||
val event = GetLockSettingsRespMsg(header, body)
|
||||
|
@ -234,6 +234,7 @@ class MeetingActor(
|
||||
disablePrivChat = lockSettingsProp.disablePrivateChat,
|
||||
disablePubChat = lockSettingsProp.disablePublicChat,
|
||||
disableNote = lockSettingsProp.disableNote,
|
||||
hideUserList = lockSettingsProp.hideUserList,
|
||||
lockedLayout = lockSettingsProp.lockedLayout,
|
||||
lockOnJoin = lockSettingsProp.lockOnJoin,
|
||||
lockOnJoinConfigurable = lockSettingsProp.lockOnJoinConfigurable
|
||||
|
@ -10,6 +10,7 @@ case class Permissions(
|
||||
disablePrivChat: Boolean = false,
|
||||
disablePubChat: Boolean = false,
|
||||
disableNote: Boolean = false,
|
||||
hideUserList: Boolean = false,
|
||||
lockedLayout: Boolean = false,
|
||||
lockOnJoin: Boolean = true,
|
||||
lockOnJoinConfigurable: Boolean = false
|
||||
|
@ -39,6 +39,7 @@ case class LockSettingsProps(
|
||||
disablePrivateChat: Boolean,
|
||||
disablePublicChat: Boolean,
|
||||
disableNote: Boolean,
|
||||
hideUserList: Boolean,
|
||||
lockedLayout: Boolean,
|
||||
lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean
|
||||
|
@ -253,7 +253,7 @@ case class ChangeLockSettingsInMeetingCmdMsg(
|
||||
body: ChangeLockSettingsInMeetingCmdMsgBody
|
||||
) extends StandardMsg
|
||||
case class ChangeLockSettingsInMeetingCmdMsgBody(disableCam: Boolean, disableMic: Boolean, disablePrivChat: Boolean,
|
||||
disablePubChat: Boolean, disableNote: Boolean, lockedLayout: Boolean, lockOnJoin: Boolean,
|
||||
disablePubChat: Boolean, disableNote: Boolean, hideUserList: Boolean, lockedLayout: Boolean, lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean, setBy: String)
|
||||
|
||||
object LockSettingsInMeetingChangedEvtMsg { val NAME = "LockSettingsInMeetingChangedEvtMsg" }
|
||||
@ -262,7 +262,7 @@ case class LockSettingsInMeetingChangedEvtMsg(
|
||||
body: LockSettingsInMeetingChangedEvtMsgBody
|
||||
) extends BbbCoreMsg
|
||||
case class LockSettingsInMeetingChangedEvtMsgBody(disableCam: Boolean, disableMic: Boolean, disablePrivChat: Boolean,
|
||||
disablePubChat: Boolean, disableNote: Boolean, lockedLayout: Boolean, lockOnJoin: Boolean,
|
||||
disablePubChat: Boolean, disableNote: Boolean, hideUserList: Boolean, lockedLayout: Boolean, lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean, setBy: String)
|
||||
|
||||
/**
|
||||
@ -278,7 +278,7 @@ case class GetLockSettingsReqMsgBody(requesterId: String)
|
||||
object GetLockSettingsRespMsg { val NAME = "GetLockSettingsRespMsg" }
|
||||
case class GetLockSettingsRespMsg(header: BbbClientMsgHeader, body: GetLockSettingsRespMsgBody) extends BbbCoreMsg
|
||||
case class GetLockSettingsRespMsgBody(disableCam: Boolean, disableMic: Boolean, disablePrivChat: Boolean,
|
||||
disablePubChat: Boolean, disableNote: Boolean, lockedLayout: Boolean, lockOnJoin: Boolean,
|
||||
disablePubChat: Boolean, disableNote: Boolean, hideUserList: Boolean, lockedLayout: Boolean, lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean)
|
||||
|
||||
object LockSettingsNotInitializedRespMsg { val NAME = "LockSettingsNotInitializedRespMsg" }
|
||||
|
@ -65,6 +65,7 @@ public class ApiParams {
|
||||
public static final String LOCK_SETTINGS_DISABLE_PRIVATE_CHAT = "lockSettingsDisablePrivateChat";
|
||||
public static final String LOCK_SETTINGS_DISABLE_PUBLIC_CHAT = "lockSettingsDisablePublicChat";
|
||||
public static final String LOCK_SETTINGS_DISABLE_NOTE = "lockSettingsDisableNote";
|
||||
public static final String LOCK_SETTINGS_HIDE_USER_LIST = "lockSettingsHideUserList";
|
||||
public static final String LOCK_SETTINGS_LOCKED_LAYOUT = "lockSettingsLockedLayout";
|
||||
public static final String LOCK_SETTINGS_LOCK_ON_JOIN = "lockSettingsLockOnJoin";
|
||||
public static final String LOCK_SETTINGS_LOCK_ON_JOIN_CONFIGURABLE = "lockSettingsLockOnJoinConfigurable";
|
||||
|
@ -103,6 +103,7 @@ public class ParamsProcessorUtil {
|
||||
private boolean defaultLockSettingsDisablePrivateChat;
|
||||
private boolean defaultLockSettingsDisablePublicChat;
|
||||
private boolean defaultLockSettingsDisableNote;
|
||||
private boolean defaultLockSettingsHideUserList;
|
||||
private boolean defaultLockSettingsLockedLayout;
|
||||
private boolean defaultLockSettingsLockOnJoin;
|
||||
private boolean defaultLockSettingsLockOnJoinConfigurable;
|
||||
@ -279,6 +280,12 @@ public class ParamsProcessorUtil {
|
||||
lockSettingsDisableNote = Boolean.parseBoolean(lockSettingsDisableNoteParam);
|
||||
}
|
||||
|
||||
Boolean lockSettingsHideUserList = defaultLockSettingsHideUserList;
|
||||
String lockSettingsHideUserListParam = params.get(ApiParams.LOCK_SETTINGS_HIDE_USER_LIST);
|
||||
if (!StringUtils.isEmpty(lockSettingsHideUserListParam)) {
|
||||
lockSettingsHideUserList = Boolean.parseBoolean(lockSettingsHideUserListParam);
|
||||
}
|
||||
|
||||
Boolean lockSettingsLockedLayout = defaultLockSettingsLockedLayout;
|
||||
String lockSettingsLockedLayoutParam = params.get(ApiParams.LOCK_SETTINGS_LOCKED_LAYOUT);
|
||||
if (!StringUtils.isEmpty(lockSettingsLockedLayoutParam)) {
|
||||
@ -302,6 +309,7 @@ public class ParamsProcessorUtil {
|
||||
lockSettingsDisablePrivateChat,
|
||||
lockSettingsDisablePublicChat,
|
||||
lockSettingsDisableNote,
|
||||
lockSettingsHideUserList,
|
||||
lockSettingsLockedLayout,
|
||||
lockSettingsLockOnJoin,
|
||||
lockSettingsLockOnJoinConfigurable);
|
||||
@ -1097,6 +1105,10 @@ public class ParamsProcessorUtil {
|
||||
this.defaultLockSettingsDisableNote = lockSettingsDisableNote;
|
||||
}
|
||||
|
||||
public void setLockSettingsHideUserList(Boolean lockSettingsHideUserList) {
|
||||
this.defaultLockSettingsHideUserList = lockSettingsHideUserList;
|
||||
}
|
||||
|
||||
public void setLockSettingsLockedLayout(Boolean lockSettingsLockedLayout) {
|
||||
this.defaultLockSettingsLockedLayout = lockSettingsLockedLayout;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ public class LockSettingsParams {
|
||||
public final Boolean disablePrivateChat;
|
||||
public final Boolean disablePublicChat;
|
||||
public final Boolean disableNote;
|
||||
public final Boolean hideUserList;
|
||||
public final Boolean lockedLayout;
|
||||
public final Boolean lockOnJoin;
|
||||
public final Boolean lockOnJoinConfigurable;
|
||||
@ -15,6 +16,7 @@ public class LockSettingsParams {
|
||||
Boolean disablePrivateChat,
|
||||
Boolean disablePublicChat,
|
||||
Boolean disableNote,
|
||||
Boolean hideUserList,
|
||||
Boolean lockedLayout,
|
||||
Boolean lockOnJoin,
|
||||
Boolean lockOnJoinConfigurable) {
|
||||
@ -23,6 +25,7 @@ public class LockSettingsParams {
|
||||
this.disablePrivateChat = disablePrivateChat;
|
||||
this.disablePublicChat = disablePublicChat;
|
||||
this.disableNote = disableNote;
|
||||
this.hideUserList = hideUserList;
|
||||
this.lockedLayout = lockedLayout;
|
||||
this.lockOnJoin = lockOnJoin;
|
||||
this.lockOnJoinConfigurable = lockOnJoinConfigurable;
|
||||
|
@ -188,6 +188,7 @@ class BbbWebApiGWApp(
|
||||
disablePrivateChat = lockSettingsParams.disablePrivateChat.booleanValue(),
|
||||
disablePublicChat = lockSettingsParams.disablePublicChat.booleanValue(),
|
||||
disableNote = lockSettingsParams.disableNote.booleanValue(),
|
||||
hideUserList = lockSettingsParams.hideUserList.booleanValue(),
|
||||
lockedLayout = lockSettingsParams.lockedLayout.booleanValue(),
|
||||
lockOnJoin = lockSettingsParams.lockOnJoin.booleanValue(),
|
||||
lockOnJoinConfigurable = lockSettingsParams.lockOnJoinConfigurable.booleanValue()
|
||||
|
@ -344,8 +344,9 @@ package org.bigbluebutton.core
|
||||
var lockOptions:LockOptions = Options.getOptions(LockOptions) as LockOptions;
|
||||
var lockSettings:LockSettingsVO = new LockSettingsVO(lockOptions.disableCam, lockOptions.disableMic,
|
||||
lockOptions.disablePrivateChat, lockOptions.disablePublicChat, lockOptions.disableNote,
|
||||
lockOptions.lockedLayout, lockOptions.lockOnJoin,
|
||||
lockOptions.lockOnJoinConfigurable);
|
||||
lockOptions.lockedLayout,
|
||||
false, // stubbed out hideUserList lock setting that is only used in the HTML5 client
|
||||
lockOptions.lockOnJoin, lockOptions.lockOnJoinConfigurable);
|
||||
var event:LockControlEvent = new LockControlEvent(LockControlEvent.SAVE_LOCK_SETTINGS);
|
||||
event.payload = lockSettings.toMap();
|
||||
|
||||
|
@ -27,6 +27,7 @@ package org.bigbluebutton.core.vo
|
||||
private var disablePublicChat:Boolean;
|
||||
private var disableNote:Boolean;
|
||||
private var lockedLayout:Boolean;
|
||||
private var hideUserList:Boolean;
|
||||
private var lockOnJoin:Boolean;
|
||||
|
||||
public function LockSettingsVO(pDisableCam:Boolean=false,
|
||||
@ -35,6 +36,7 @@ package org.bigbluebutton.core.vo
|
||||
pDisablePublicChat:Boolean=false,
|
||||
pDisableNote:Boolean=false,
|
||||
pLockLayout: Boolean=false,
|
||||
pHideUserList:Boolean=false,
|
||||
pLockOnJoin:Boolean=false,
|
||||
pLockOnJoinConfigurable:Boolean=false)
|
||||
{
|
||||
@ -44,6 +46,7 @@ package org.bigbluebutton.core.vo
|
||||
this.disablePublicChat = pDisablePublicChat;
|
||||
this.disableNote = pDisableNote;
|
||||
this.lockedLayout = pLockLayout;
|
||||
this.hideUserList = pHideUserList;
|
||||
this.lockOnJoin = pLockOnJoin;
|
||||
this.lockOnJoinConfigurable = pLockOnJoinConfigurable;
|
||||
}
|
||||
@ -56,6 +59,7 @@ package org.bigbluebutton.core.vo
|
||||
disablePublicChat: this.disablePublicChat,
|
||||
disableNote: this.disableNote,
|
||||
lockedLayout: this.lockedLayout,
|
||||
hideUserList: this.hideUserList,
|
||||
lockOnJoin: this.lockOnJoin,
|
||||
lockOnJoinConfigurable: this.lockOnJoinConfigurable
|
||||
};
|
||||
@ -87,6 +91,10 @@ package org.bigbluebutton.core.vo
|
||||
return lockedLayout;
|
||||
}
|
||||
|
||||
public function getHideUserList():Boolean {
|
||||
return hideUserList;
|
||||
}
|
||||
|
||||
public function getLockOnJoin():Boolean {
|
||||
return lockOnJoin;
|
||||
}
|
||||
|
3
bigbluebutton-client/src/org/bigbluebutton/main/views/LockSettings.mxml
Normal file → Executable file
3
bigbluebutton-client/src/org/bigbluebutton/main/views/LockSettings.mxml
Normal file → Executable file
@ -43,6 +43,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
[Bindable] public var disablePrivChat:Boolean = false;
|
||||
[Bindable] public var disableNote:Boolean = false;
|
||||
[Bindable] public var lockedLayout:Boolean = false;
|
||||
[Bindable] public var hideUserList:Boolean = false;
|
||||
[Bindable] public var lockOnJoin:Boolean = false;
|
||||
[Bindable] public var lockOnJoinConfigurable:Boolean = false;
|
||||
|
||||
@ -54,7 +55,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
private function onSaveClicked():void {
|
||||
var event:LockControlEvent = new LockControlEvent(LockControlEvent.SAVE_LOCK_SETTINGS);
|
||||
var lockSettings:LockSettingsVO = new LockSettingsVO(chkDisableWebcam.selected, chkDisableMicrophone.selected, chkDisablePrivateChat.selected, chkDisablePublicChat.selected, chkDisableNote.selected, chkDisableLayout.selected, chkLockOnJoin.selected, lockOnJoinConfigurable);
|
||||
var lockSettings:LockSettingsVO = new LockSettingsVO(chkDisableWebcam.selected, chkDisableMicrophone.selected, chkDisablePrivateChat.selected, chkDisablePublicChat.selected, chkDisableNote.selected, chkDisableLayout.selected, hideUserList, chkLockOnJoin.selected, lockOnJoinConfigurable);
|
||||
event.payload = lockSettings.toMap();
|
||||
dispatchEvent(event);
|
||||
|
||||
|
1
bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
Normal file → Executable file
1
bigbluebutton-client/src/org/bigbluebutton/main/views/MainApplicationShell.mxml
Normal file → Executable file
@ -762,6 +762,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
ls.disablePrivChat = lsv.getDisablePrivateChat();
|
||||
ls.disablePubChat = lsv.getDisablePublicChat();
|
||||
ls.disableNote = lsv.getDisableNote();
|
||||
ls.hideUserList = lsv.getHideUserList();
|
||||
ls.lockedLayout = lsv.getLockedLayout();
|
||||
ls.lockOnJoin = lsv.getLockOnJoin();
|
||||
ls.lockOnJoinConfigurable = lsv.getLockOnJoinConfigurable();
|
||||
|
@ -22,9 +22,9 @@ package org.bigbluebutton.modules.users.services
|
||||
|
||||
import flash.utils.setTimeout;
|
||||
|
||||
import mx.collections.ArrayCollection;
|
||||
import mx.controls.Alert;
|
||||
import mx.utils.ObjectUtil;
|
||||
import mx.collections.ArrayCollection;
|
||||
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
@ -695,6 +695,7 @@ package org.bigbluebutton.modules.users.services
|
||||
body.disablePubChat as Boolean,
|
||||
body.disableNote as Boolean,
|
||||
body.lockedLayout as Boolean,
|
||||
body.hideUserList as Boolean,
|
||||
body.lockOnJoin as Boolean,
|
||||
body.lockOnJoinConfigurable as Boolean);
|
||||
UsersUtil.setLockSettings(lockSettings);
|
||||
@ -711,6 +712,7 @@ package org.bigbluebutton.modules.users.services
|
||||
body.disablePubChat as Boolean,
|
||||
body.disableNote as Boolean,
|
||||
body.lockedLayout as Boolean,
|
||||
body.hideUserList as Boolean,
|
||||
body.lockOnJoin as Boolean,
|
||||
body.lockOnJoinConfigurable as Boolean);
|
||||
UsersUtil.setLockSettings(lockSettings);
|
||||
|
@ -653,7 +653,8 @@ package org.bigbluebutton.modules.users.services
|
||||
disablePrivChat: newLockSettings.disablePrivateChat,
|
||||
disablePubChat: newLockSettings.disablePublicChat,
|
||||
disableNote: newLockSettings.disableNote,
|
||||
lockedLayout: newLockSettings.lockedLayout,
|
||||
lockedLayout: newLockSettings.lockedLayout,
|
||||
hideUserList: newLockSettings.hideUserList,
|
||||
lockOnJoin: newLockSettings.lockOnJoin,
|
||||
lockOnJoinConfigurable: newLockSettings.lockOnJoinConfigurable,
|
||||
setBy: UsersUtil.getMyUserID()}
|
||||
|
@ -17,6 +17,7 @@ export default function toggleLockSettings(credentials, meeting) {
|
||||
disablePrivateChat: Boolean,
|
||||
disablePublicChat: Boolean,
|
||||
disableNote: Boolean,
|
||||
hideUserList: Boolean,
|
||||
lockedLayout: Boolean,
|
||||
lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean,
|
||||
@ -29,6 +30,7 @@ export default function toggleLockSettings(credentials, meeting) {
|
||||
disablePrivChat: meeting.lockSettingsProps.disablePrivateChat,
|
||||
disablePubChat: meeting.lockSettingsProps.disablePublicChat,
|
||||
disableNote: meeting.lockSettingsProps.disableNote,
|
||||
hideUserList: meeting.lockSettingsProps.hideUserList,
|
||||
lockedLayout: meeting.lockSettingsProps.lockedLayout,
|
||||
lockOnJoin: meeting.lockSettingsProps.lockOnJoin,
|
||||
lockOnJoinConfigurable: meeting.lockSettingsProps.lockOnJoinConfigurable,
|
||||
|
1
bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js
Normal file → Executable file
1
bigbluebutton-html5/imports/api/meetings/server/modifiers/addMeeting.js
Normal file → Executable file
@ -79,6 +79,7 @@ export default function addMeeting(meeting) {
|
||||
disablePrivateChat: Boolean,
|
||||
disablePublicChat: Boolean,
|
||||
disableNote: Boolean,
|
||||
hideUserList: Boolean,
|
||||
lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean,
|
||||
lockedLayout: Boolean,
|
||||
|
3
bigbluebutton-html5/imports/api/meetings/server/modifiers/changeLockSettings.js
Normal file → Executable file
3
bigbluebutton-html5/imports/api/meetings/server/modifiers/changeLockSettings.js
Normal file → Executable file
@ -10,6 +10,7 @@ export default function changeLockSettings(meetingId, payload) {
|
||||
disablePrivChat: Boolean,
|
||||
disablePubChat: Boolean,
|
||||
disableNote: Boolean,
|
||||
hideUserList: Boolean,
|
||||
lockedLayout: Boolean,
|
||||
lockOnJoin: Boolean,
|
||||
lockOnJoinConfigurable: Boolean,
|
||||
@ -22,6 +23,7 @@ export default function changeLockSettings(meetingId, payload) {
|
||||
disablePrivChat,
|
||||
disablePubChat,
|
||||
disableNote,
|
||||
hideUserList,
|
||||
lockedLayout,
|
||||
lockOnJoin,
|
||||
lockOnJoinConfigurable,
|
||||
@ -40,6 +42,7 @@ export default function changeLockSettings(meetingId, payload) {
|
||||
disablePrivateChat: disablePrivChat,
|
||||
disablePublicChat: disablePubChat,
|
||||
disableNote,
|
||||
hideUserList,
|
||||
lockedLayout,
|
||||
lockOnJoin,
|
||||
lockOnJoinConfigurable,
|
||||
|
@ -27,9 +27,7 @@ export default function handleEmojiStatus({ body }, meetingId) {
|
||||
}
|
||||
|
||||
if (numChanged) {
|
||||
Logger.info(`Assigned user emoji status${
|
||||
emoji} id=${userId} meeting=${meetingId}`,
|
||||
);
|
||||
Logger.info(`Assigned user emoji status ${emoji} id=${userId} meeting=${meetingId}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -81,7 +81,10 @@ const DesktopShare = ({
|
||||
},
|
||||
}, 'Default error handler for screenshare');
|
||||
}
|
||||
screenShareEndAlert();
|
||||
// Don't trigger the screen share end alert if presenter click to cancel on screen share dialog
|
||||
if (error && error.name !== 'NotAllowedError') {
|
||||
screenShareEndAlert();
|
||||
}
|
||||
};
|
||||
|
||||
const screenshareLocked = screenshareDataSavingSetting
|
||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import cx from 'classnames';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { defineMessages, injectIntl, intlShape } from 'react-intl';
|
||||
import Button from '/imports/ui/components/button/component';
|
||||
import screenreaderTrap from 'makeup-screenreader-trap';
|
||||
import { styles } from './styles';
|
||||
@ -26,37 +26,40 @@ const propTypes = {
|
||||
const children = props[propName];
|
||||
|
||||
if (!children || children.length < 2) {
|
||||
return new Error(`Invalid prop \`${propName}\` supplied to` +
|
||||
` \`${componentName}\`. Validation failed.`);
|
||||
return new Error(`Invalid prop \`${propName}\` supplied to`
|
||||
+ ` \`${componentName}\`. Validation failed.`);
|
||||
}
|
||||
|
||||
const trigger = children.find(x => x.type === DropdownTrigger);
|
||||
const content = children.find(x => x.type === DropdownContent);
|
||||
|
||||
if (!trigger) {
|
||||
return new Error(`Invalid prop \`${propName}\` supplied to` +
|
||||
` \`${componentName}\`. Missing \`DropdownTrigger\`. Validation failed.`);
|
||||
return new Error(`Invalid prop \`${propName}\` supplied to`
|
||||
+ ` \`${componentName}\`. Missing \`DropdownTrigger\`. Validation failed.`);
|
||||
}
|
||||
|
||||
if (!content) {
|
||||
return new Error(`Invalid prop \`${propName}\` supplied to` +
|
||||
` \`${componentName}\`. Missing \`DropdownContent\`. Validation failed.`);
|
||||
return new Error(`Invalid prop \`${propName}\` supplied to`
|
||||
+ ` \`${componentName}\`. Missing \`DropdownContent\`. Validation failed.`);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
isOpen: PropTypes.bool,
|
||||
keepOpen: PropTypes.bool,
|
||||
onHide: PropTypes.func,
|
||||
onShow: PropTypes.func,
|
||||
autoFocus: PropTypes.bool,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
children: null,
|
||||
keepOpen: null,
|
||||
onShow: noop,
|
||||
onHide: noop,
|
||||
autoFocus: false,
|
||||
isOpen: false,
|
||||
keepOpen: false,
|
||||
};
|
||||
|
||||
class Dropdown extends Component {
|
||||
@ -82,6 +85,7 @@ class Dropdown extends Component {
|
||||
|
||||
const { isOpen } = this.state;
|
||||
|
||||
|
||||
if (isOpen && !prevState.isOpen) { onShow(); }
|
||||
|
||||
if (!isOpen && prevState.isOpen) { onHide(); }
|
||||
@ -90,6 +94,7 @@ class Dropdown extends Component {
|
||||
}
|
||||
|
||||
handleShow() {
|
||||
Session.set('dropdownOpen', true);
|
||||
const {
|
||||
onShow,
|
||||
} = this.props;
|
||||
@ -101,6 +106,7 @@ class Dropdown extends Component {
|
||||
}
|
||||
|
||||
handleHide() {
|
||||
Session.set('dropdownOpen', false);
|
||||
const { onHide } = this.props;
|
||||
this.setState({ isOpen: false }, () => {
|
||||
const { removeEventListener } = window;
|
||||
@ -115,28 +121,33 @@ class Dropdown extends Component {
|
||||
const triggerElement = findDOMNode(this.trigger);
|
||||
const contentElement = findDOMNode(this.content);
|
||||
if (!(triggerElement && contentElement)) return;
|
||||
if (keepOpen === null) {
|
||||
if (triggerElement.contains(event.target)) {
|
||||
if (triggerElement && triggerElement.contains(event.target)) {
|
||||
if (keepOpen) {
|
||||
onHide();
|
||||
return;
|
||||
}
|
||||
if (isOpen) {
|
||||
this.handleHide();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerElement && triggerElement.contains(event.target)) {
|
||||
if (keepOpen) return onHide();
|
||||
if (isOpen) return this.handleHide();
|
||||
}
|
||||
|
||||
if (keepOpen && isOpen && !contentElement.contains(event.target)) {
|
||||
if (triggerElement) {
|
||||
const { parentElement } = triggerElement;
|
||||
if (parentElement) parentElement.focus();
|
||||
}
|
||||
onHide();
|
||||
this.handleHide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (keepOpen !== null) {
|
||||
return;
|
||||
|
||||
if (keepOpen && triggerElement) {
|
||||
const { parentElement } = triggerElement;
|
||||
if (parentElement) parentElement.focus();
|
||||
}
|
||||
|
||||
this.handleHide();
|
||||
if (!keepOpen) this.handleHide();
|
||||
}
|
||||
|
||||
handleToggle() {
|
||||
@ -148,12 +159,11 @@ class Dropdown extends Component {
|
||||
const {
|
||||
children,
|
||||
className,
|
||||
style,
|
||||
intl,
|
||||
keepOpen,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
|
||||
const { isOpen } = this.state;
|
||||
|
||||
let trigger = children.find(x => x.type === DropdownTrigger);
|
||||
@ -175,31 +185,31 @@ class Dropdown extends Component {
|
||||
dropdownShow: this.handleShow,
|
||||
dropdownHide: this.handleHide,
|
||||
});
|
||||
|
||||
|
||||
const showCloseBtn = (isOpen && keepOpen) || (isOpen && keepOpen === null);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={style}
|
||||
className={cx(styles.dropdown, className)}
|
||||
aria-live={otherProps['aria-live']}
|
||||
aria-relevant={otherProps['aria-relevant']}
|
||||
aria-haspopup={otherProps['aria-haspopup']}
|
||||
aria-label={otherProps['aria-label']}
|
||||
data-isopen={this.state.isOpen}
|
||||
ref={(node) => { this.dropdown = node; }}
|
||||
tabIndex={-1}
|
||||
>
|
||||
{trigger}
|
||||
{content}
|
||||
{showCloseBtn ?
|
||||
<Button
|
||||
className={styles.close}
|
||||
label={intl.formatMessage(intlMessages.close)}
|
||||
size="lg"
|
||||
color="default"
|
||||
onClick={this.handleHide}
|
||||
/> : null}
|
||||
{showCloseBtn
|
||||
? (
|
||||
<Button
|
||||
className={styles.close}
|
||||
label={intl.formatMessage(intlMessages.close)}
|
||||
size="lg"
|
||||
color="default"
|
||||
onClick={this.handleHide}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
62
bigbluebutton-html5/imports/ui/components/join-handler/component.jsx
Normal file → Executable file
62
bigbluebutton-html5/imports/ui/components/join-handler/component.jsx
Normal file → Executable file
@ -25,7 +25,6 @@ class JoinHandler extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.fetchToken = this.fetchToken.bind(this);
|
||||
this.numFetchTokenRetries = 0;
|
||||
|
||||
this.state = {
|
||||
joined: false,
|
||||
@ -34,7 +33,51 @@ class JoinHandler extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this.fetchToken();
|
||||
|
||||
if (!this.firstJoinTime) {
|
||||
this.firstJoinTime = new Date();
|
||||
}
|
||||
Tracker.autorun((c) => {
|
||||
const {
|
||||
connected,
|
||||
status,
|
||||
} = Meteor.status();
|
||||
|
||||
logger.debug(`Initial connection status change. status: ${status}, connected: ${connected}`);
|
||||
if (connected) {
|
||||
c.stop();
|
||||
|
||||
const msToConnect = (new Date() - this.firstJoinTime) / 1000;
|
||||
const secondsToConnect = parseFloat(msToConnect).toFixed(2);
|
||||
|
||||
logger.info({
|
||||
logCode: 'joinhandler_component_initial_connection_time',
|
||||
extraInfo: {
|
||||
attemptForUserInfo: Auth.fullInfo,
|
||||
timeToConnect: secondsToConnect,
|
||||
},
|
||||
}, `Connection to Meteor took ${secondsToConnect}s`);
|
||||
|
||||
this.firstJoinTime = undefined;
|
||||
this.fetchToken();
|
||||
} else if (status === 'failed') {
|
||||
c.stop();
|
||||
|
||||
const msToConnect = (new Date() - this.firstJoinTime) / 1000;
|
||||
const secondsToConnect = parseFloat(msToConnect).toFixed(2);
|
||||
logger.info({
|
||||
logCode: 'joinhandler_component_initial_connection_failed',
|
||||
extraInfo: {
|
||||
attemptForUserInfo: Auth.fullInfo,
|
||||
timeToConnect: secondsToConnect,
|
||||
},
|
||||
}, `Connection to Meteor failed, took ${secondsToConnect}s`);
|
||||
|
||||
JoinHandler.setError('400');
|
||||
Session.set('errorMessageDescription', 'Failed to connect to server');
|
||||
this.firstJoinTime = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -44,21 +87,6 @@ class JoinHandler extends Component {
|
||||
async fetchToken() {
|
||||
if (!this._isMounted) return;
|
||||
|
||||
if (!Meteor.status().connected) {
|
||||
if (this.numFetchTokenRetries % 9) {
|
||||
logger.error({
|
||||
logCode: 'joinhandler_component_fetchToken_not_connected',
|
||||
extraInfo: {
|
||||
attemptForUserInfo: Auth.fullInfo,
|
||||
numFetchTokenRetries: this.numFetchTokenRetries,
|
||||
},
|
||||
}, 'Meteor was not connected, retry in a few moments');
|
||||
}
|
||||
this.numFetchTokenRetries += 1;
|
||||
|
||||
setTimeout(() => this.fetchToken(), 200);
|
||||
return;
|
||||
}
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const sessionToken = urlParams.get('sessionToken');
|
||||
|
||||
|
@ -33,27 +33,31 @@ const intlMessages = defineMessages({
|
||||
},
|
||||
webcamLabel: {
|
||||
id: 'app.lock-viewers.webcamLabel',
|
||||
description: 'description for close button',
|
||||
description: 'label for webcam toggle',
|
||||
},
|
||||
otherViewersWebcamLabel: {
|
||||
id: 'app.lock-viewers.otherViewersWebcamLabel',
|
||||
description: 'description for close button',
|
||||
description: 'label for other viewers webcam toggle',
|
||||
},
|
||||
microphoneLable: {
|
||||
id: 'app.lock-viewers.microphoneLable',
|
||||
description: 'description for close button',
|
||||
description: 'label for microphone toggle',
|
||||
},
|
||||
publicChatLabel: {
|
||||
id: 'app.lock-viewers.PublicChatLabel',
|
||||
description: 'description for close button',
|
||||
description: 'label for public chat toggle',
|
||||
},
|
||||
privateChatLable: {
|
||||
id: 'app.lock-viewers.PrivateChatLable',
|
||||
description: 'description for close button',
|
||||
description: 'label for private chat toggle',
|
||||
},
|
||||
notesLabel: {
|
||||
id: 'app.lock-viewers.notesLabel',
|
||||
description: 'description for close button',
|
||||
description: 'label for shared notes toggle',
|
||||
},
|
||||
userListLabel: {
|
||||
id: 'app.lock-viewers.userListLabel',
|
||||
description: 'label for user list toggle',
|
||||
},
|
||||
ariaModalTitle: {
|
||||
id: 'app.lock-viewers.ariaTitle',
|
||||
@ -239,6 +243,29 @@ class LockViewersComponent extends React.PureComponent {
|
||||
)
|
||||
: null
|
||||
}
|
||||
|
||||
<div className={styles.row}>
|
||||
<div className={styles.col} aria-hidden="true">
|
||||
<div className={styles.formElement}>
|
||||
<div className={styles.label}>
|
||||
{intl.formatMessage(intlMessages.userListLabel)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.col}>
|
||||
<div className={cx(styles.formElement, styles.pullContentRight)}>
|
||||
<Toggle
|
||||
icons={false}
|
||||
defaultChecked={meeting.lockSettingsProps.hideUserList}
|
||||
onChange={() => {
|
||||
meeting.lockSettingsProps.hideUserList = !meeting.lockSettingsProps.hideUserList;
|
||||
toggleLockSettings(meeting);
|
||||
}}
|
||||
ariaLabel={intl.formatMessage(intlMessages.userListLabel)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
8
bigbluebutton-html5/imports/ui/components/lock-viewers/notify/component.jsx
Normal file → Executable file
8
bigbluebutton-html5/imports/ui/components/lock-viewers/notify/component.jsx
Normal file → Executable file
@ -24,6 +24,10 @@ const intlDisableMessages = defineMessages({
|
||||
id: 'app.userList.userOptions.disableNote',
|
||||
description: 'label to disable note notification',
|
||||
},
|
||||
hideUserList: {
|
||||
id: 'app.userList.userOptions.hideUserList',
|
||||
description: 'label to hide user list notification',
|
||||
},
|
||||
onlyModeratorWebcam: {
|
||||
id: 'app.userList.userOptions.webcamsOnlyForModerator',
|
||||
description: 'label to disable all webcams except for the moderators cam',
|
||||
@ -51,6 +55,10 @@ const intlEnableMessages = defineMessages({
|
||||
id: 'app.userList.userOptions.enableNote',
|
||||
description: 'label to enable note notification',
|
||||
},
|
||||
hideUserList: {
|
||||
id: 'app.userList.userOptions.showUserList',
|
||||
description: 'label to show user list notification',
|
||||
},
|
||||
onlyModeratorWebcam: {
|
||||
id: 'app.userList.userOptions.enableOnlyModeratorWebcam',
|
||||
description: 'label to enable all webcams except for the moderators cam',
|
||||
|
@ -17,6 +17,7 @@ import logger from '/imports/startup/client/logger';
|
||||
const CHAT_CONFIG = Meteor.settings.public.chat;
|
||||
const PUBLIC_GROUP_CHAT_ID = CHAT_CONFIG.public_group_id;
|
||||
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
||||
const ROLE_VIEWER = Meteor.settings.public.user.role_viewer;
|
||||
|
||||
const DIAL_IN_CLIENT_TYPE = 'dial-in-user';
|
||||
|
||||
@ -181,13 +182,22 @@ const userFindSorting = {
|
||||
};
|
||||
|
||||
const getUsers = () => {
|
||||
const users = Users
|
||||
let users = Users
|
||||
.find({
|
||||
meetingId: Auth.meetingID,
|
||||
connectionStatus: 'online',
|
||||
}, userFindSorting)
|
||||
.fetch();
|
||||
|
||||
const currentUser = Users.findOne({ userId: Auth.userID });
|
||||
if (currentUser && currentUser.role === ROLE_VIEWER && currentUser.locked) {
|
||||
const meeting = Meetings.findOne({ meetingId: Auth.meetingID });
|
||||
if (meeting && meeting.lockSettingsProps && meeting.lockSettingsProps.hideUserList) {
|
||||
const moderatorOrCurrentUser = u => u.role === ROLE_MODERATOR || u.userId === Auth.userID;
|
||||
users = users.filter(moderatorOrCurrentUser);
|
||||
}
|
||||
}
|
||||
|
||||
return users.sort(sortUsers);
|
||||
};
|
||||
|
||||
@ -358,12 +368,12 @@ const normalizeEmojiName = emoji => (
|
||||
emoji in EMOJI_STATUSES ? EMOJI_STATUSES[emoji] : emoji
|
||||
);
|
||||
|
||||
const setEmojiStatus = (data) => {
|
||||
const statusAvailable = (Object.keys(EMOJI_STATUSES).includes(data));
|
||||
const setEmojiStatus = (userId, emoji) => {
|
||||
const statusAvailable = (Object.keys(EMOJI_STATUSES).includes(emoji));
|
||||
|
||||
return statusAvailable
|
||||
? makeCall('setEmojiStatus', Auth.userID, data)
|
||||
: makeCall('setEmojiStatus', data, 'none');
|
||||
? makeCall('setEmojiStatus', Auth.userID, emoji)
|
||||
: makeCall('setEmojiStatus', userId, 'none');
|
||||
};
|
||||
|
||||
const assignPresenter = (userId) => { makeCall('assignPresenter', userId); };
|
||||
@ -394,8 +404,11 @@ const muteAllExceptPresenter = (userId) => { makeCall('muteAllExceptPresenter',
|
||||
|
||||
const changeRole = (userId, role) => { makeCall('changeRole', userId, role); };
|
||||
|
||||
const roving = (event, itemCount, changeState) => {
|
||||
if (document.activeElement.getAttribute('data-isopen') === 'true') {
|
||||
const roving = (event, changeState, elementsList, element) => {
|
||||
this.selectedElement = element;
|
||||
const menuOpen = Session.get('dropdownOpen') || false;
|
||||
|
||||
if (menuOpen) {
|
||||
const menuChildren = document.activeElement.getElementsByTagName('li');
|
||||
|
||||
if ([KEY_CODES.ESCAPE, KEY_CODES.ARROW_LEFT].includes(event.keyCode)) {
|
||||
@ -418,34 +431,23 @@ const roving = (event, itemCount, changeState) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selectedIndex === undefined) {
|
||||
this.selectedIndex = -1;
|
||||
}
|
||||
|
||||
if ([KEY_CODES.ESCAPE, KEY_CODES.TAB].includes(event.keyCode)) {
|
||||
document.activeElement.blur();
|
||||
this.selectedIndex = -1;
|
||||
changeState(this.selectedIndex);
|
||||
changeState(null);
|
||||
}
|
||||
|
||||
if (event.keyCode === KEY_CODES.ARROW_DOWN) {
|
||||
this.selectedIndex += 1;
|
||||
|
||||
if (this.selectedIndex === itemCount) {
|
||||
this.selectedIndex = 0;
|
||||
}
|
||||
|
||||
changeState(this.selectedIndex);
|
||||
const firstElement = elementsList.firstChild;
|
||||
let elRef = element ? element.nextSibling : firstElement;
|
||||
elRef = elRef || firstElement;
|
||||
changeState(elRef);
|
||||
}
|
||||
|
||||
if (event.keyCode === KEY_CODES.ARROW_UP) {
|
||||
this.selectedIndex -= 1;
|
||||
|
||||
if (this.selectedIndex < 0) {
|
||||
this.selectedIndex = itemCount - 1;
|
||||
}
|
||||
|
||||
changeState(this.selectedIndex);
|
||||
const lastElement = elementsList.lastChild;
|
||||
let elRef = element ? element.previousSibling : lastElement;
|
||||
elRef = elRef || lastElement;
|
||||
changeState(elRef);
|
||||
}
|
||||
|
||||
if ([KEY_CODES.ARROW_RIGHT, KEY_CODES.SPACE, KEY_CODES.ENTER].includes(event.keyCode)) {
|
||||
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
||||
import { defineMessages } from 'react-intl';
|
||||
import cx from 'classnames';
|
||||
import { styles } from '/imports/ui/components/user-list/user-list-content/styles';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import ChatListItemContainer from '../../chat-list-item/container';
|
||||
|
||||
const propTypes = {
|
||||
@ -41,38 +42,31 @@ class UserMessages extends PureComponent {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
index: -1,
|
||||
selectedChat: null,
|
||||
};
|
||||
|
||||
this.activeChatRefs = [];
|
||||
this.selectedIndex = -1;
|
||||
|
||||
this.focusActiveChatItem = this.focusActiveChatItem.bind(this);
|
||||
this.changeState = this.changeState.bind(this);
|
||||
this.rove = this.rove.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { compact, roving, activeChats } = this.props;
|
||||
const { compact } = this.props;
|
||||
if (!compact) {
|
||||
this._msgsList.addEventListener(
|
||||
'keydown',
|
||||
event => roving(
|
||||
event,
|
||||
activeChats.length,
|
||||
this.changeState,
|
||||
),
|
||||
this.rove,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { index } = this.state;
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
const { selectedChat } = this.state;
|
||||
|
||||
if (index !== prevState.index) {
|
||||
this.focusActiveChatItem(index);
|
||||
if (selectedChat && selectedChat !== prevState.selectedChat) {
|
||||
const { firstChild } = selectedChat;
|
||||
if (firstChild) firstChild.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,16 +102,15 @@ class UserMessages extends PureComponent {
|
||||
));
|
||||
}
|
||||
|
||||
changeState(newIndex) {
|
||||
this.setState({ index: newIndex });
|
||||
changeState(ref) {
|
||||
this.setState({ selectedChat: ref });
|
||||
}
|
||||
|
||||
focusActiveChatItem(index) {
|
||||
if (!this.activeChatRefs[index]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeChatRefs[index].firstChild.focus();
|
||||
rove(event) {
|
||||
const { roving } = this.props;
|
||||
const { selectedChat } = this.state;
|
||||
const msgItemsRef = findDOMNode(this._msgItems);
|
||||
roving(event, this.changeState, msgItemsRef, selectedChat);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
|
||||
import cx from 'classnames';
|
||||
import { styles } from '/imports/ui/components/user-list/user-list-content/styles';
|
||||
import _ from 'lodash';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import UserListItemContainer from './user-list-item/container';
|
||||
import UserOptionsContainer from './user-options/container';
|
||||
|
||||
@ -62,46 +63,43 @@ class UserParticipants extends Component {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
index: -1,
|
||||
selectedUser: null,
|
||||
};
|
||||
|
||||
this.userRefs = [];
|
||||
this.selectedIndex = -1;
|
||||
|
||||
this.getScrollContainerRef = this.getScrollContainerRef.bind(this);
|
||||
this.focusUserItem = this.focusUserItem.bind(this);
|
||||
this.rove = this.rove.bind(this);
|
||||
this.changeState = this.changeState.bind(this);
|
||||
this.getUsers = this.getUsers.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { compact, roving, users } = this.props;
|
||||
const { compact } = this.props;
|
||||
if (!compact) {
|
||||
this.refScrollContainer.addEventListener(
|
||||
'keydown',
|
||||
event => roving(
|
||||
event,
|
||||
users.length,
|
||||
this.changeState,
|
||||
),
|
||||
this.rove,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.refScrollContainer.removeEventListener('keydown', this.rove);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
const isPropsEqual = _.isEqual(this.props, nextProps);
|
||||
const isStateEqual = _.isEqual(this.state, nextState);
|
||||
return !isPropsEqual || !isStateEqual;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { index } = this.state;
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const { selectedUser } = this.state;
|
||||
|
||||
if (index !== prevState.index) {
|
||||
this.focusUserItem(index);
|
||||
if (selectedUser) {
|
||||
const { firstChild } = selectedUser;
|
||||
if (firstChild) firstChild.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,14 +175,15 @@ class UserParticipants extends Component {
|
||||
));
|
||||
}
|
||||
|
||||
focusUserItem(index) {
|
||||
if (!this.userRefs[index]) return;
|
||||
|
||||
this.userRefs[index].firstChild.focus();
|
||||
rove(event) {
|
||||
const { roving } = this.props;
|
||||
const { selectedUser } = this.state;
|
||||
const usersItemsRef = findDOMNode(this.refScrollItems);
|
||||
roving(event, this.changeState, usersItemsRef, selectedUser);
|
||||
}
|
||||
|
||||
changeState(newIndex) {
|
||||
this.setState({ index: newIndex });
|
||||
changeState(ref) {
|
||||
this.setState({ selectedUser: ref });
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -230,7 +229,6 @@ class UserParticipants extends Component {
|
||||
}
|
||||
<div
|
||||
className={styles.scrollableList}
|
||||
role="list"
|
||||
tabIndex={0}
|
||||
ref={(ref) => { this.refScrollContainer = ref; }}
|
||||
>
|
||||
|
@ -153,10 +153,13 @@ class UserDropdown extends PureComponent {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { dropdownVisible } = this.props;
|
||||
if (!dropdownVisible) document.activeElement.blur();
|
||||
this.checkDropdownDirection();
|
||||
}
|
||||
|
||||
onActionsShow() {
|
||||
Session.set('dropdownOpen', true);
|
||||
const { getScrollContainerRef } = this.props;
|
||||
const dropdown = this.getDropdownMenuParent();
|
||||
const scrollContainer = getScrollContainerRef();
|
||||
@ -193,6 +196,8 @@ class UserDropdown extends PureComponent {
|
||||
if (callback) {
|
||||
return callback;
|
||||
}
|
||||
|
||||
return Session.set('dropdownOpen', false);
|
||||
}
|
||||
|
||||
getUsersActions() {
|
||||
@ -251,7 +256,12 @@ class UserDropdown extends PureComponent {
|
||||
actions.push(this.makeDropdownItem(
|
||||
'back',
|
||||
intl.formatMessage(messages.backTriggerLabel),
|
||||
() => this.setState({ showNestedOptions: false, isActionsOpen: true }),
|
||||
() => this.setState(
|
||||
{
|
||||
showNestedOptions: false,
|
||||
isActionsOpen: true,
|
||||
}, Session.set('dropdownOpen', true),
|
||||
),
|
||||
'left_arrow',
|
||||
));
|
||||
}
|
||||
@ -262,7 +272,7 @@ class UserDropdown extends PureComponent {
|
||||
statuses.map(status => actions.push(this.makeDropdownItem(
|
||||
status,
|
||||
intl.formatMessage({ id: `app.actionsBar.emojiMenu.${status}Label` }),
|
||||
() => { handleEmojiChange(status); this.resetMenuState(); },
|
||||
() => { handleEmojiChange(user.id, status); this.resetMenuState(); },
|
||||
getEmojiList[status],
|
||||
)));
|
||||
|
||||
@ -273,7 +283,12 @@ class UserDropdown extends PureComponent {
|
||||
actions.push(this.makeDropdownItem(
|
||||
'setstatus',
|
||||
intl.formatMessage(messages.statusTriggerLabel),
|
||||
() => this.setState({ showNestedOptions: true, isActionsOpen: true }),
|
||||
() => this.setState(
|
||||
{
|
||||
showNestedOptions: true,
|
||||
isActionsOpen: true,
|
||||
}, Session.set('dropdownOpen', true),
|
||||
),
|
||||
'user',
|
||||
'right_arrow',
|
||||
));
|
||||
@ -440,7 +455,8 @@ class UserDropdown extends PureComponent {
|
||||
);
|
||||
|
||||
if (!isDropdownVisible) {
|
||||
const offsetPageTop = (dropdownTrigger.offsetTop + dropdownTrigger.offsetHeight) - scrollContainer.scrollTop;
|
||||
const { offsetTop, offsetHeight } = dropdownTrigger;
|
||||
const offsetPageTop = (offsetTop + offsetHeight) - scrollContainer.scrollTop;
|
||||
|
||||
nextState.dropdownOffset = window.innerHeight - offsetPageTop;
|
||||
nextState.dropdownDirection = 'bottom';
|
||||
|
2
bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/styles.scss
Normal file → Executable file
2
bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/styles.scss
Normal file → Executable file
@ -101,7 +101,7 @@
|
||||
}
|
||||
|
||||
.userAvatar {
|
||||
flex: 0 0 2.2rem;
|
||||
flex: 0 0 2.25rem;
|
||||
}
|
||||
|
||||
.userItemContents {
|
||||
|
@ -37,7 +37,7 @@ const UserOptionsContainer = withTracker((props) => {
|
||||
} = props;
|
||||
|
||||
const toggleStatus = () => {
|
||||
users.forEach(id => setEmojiStatus(id, 'none'));
|
||||
users.forEach(user => setEmojiStatus(user.userId, 'none'));
|
||||
notify(
|
||||
intl.formatMessage(intlMessages.clearStatusMessage), 'info', 'clear_status',
|
||||
);
|
||||
|
@ -75,6 +75,7 @@ class VideoService {
|
||||
getAllWebcamUsers() {
|
||||
const webcamsLocked = this.webcamsLocked();
|
||||
const webcamsOnlyForModerator = this.webcamsOnlyForModerator();
|
||||
const hideUserList = this.hideUserList();
|
||||
const currentUser = Users.findOne({ userId: Auth.userID });
|
||||
const currentUserIsViewer = currentUser.role === ROLE_VIEWER;
|
||||
const sharedWebcam = this.isSharing;
|
||||
@ -96,7 +97,7 @@ class VideoService {
|
||||
|
||||
const userIsModerator = user => user.role === ROLE_MODERATOR;
|
||||
|
||||
if (webcamsOnlyForModerator && currentUserIsViewer) {
|
||||
if ((webcamsOnlyForModerator || hideUserList) && currentUserIsViewer) {
|
||||
users = users.filter(userIsModerator);
|
||||
}
|
||||
|
||||
@ -117,6 +118,11 @@ class VideoService {
|
||||
return m.lockSettingsProps ? m.lockSettingsProps.disableCam : false;
|
||||
}
|
||||
|
||||
hideUserList() {
|
||||
const m = Meetings.findOne({ meetingId: Auth.meetingID }) || {};
|
||||
return m.lockSettingsProps ? m.lockSettingsProps.hideUserList : false;
|
||||
}
|
||||
|
||||
userId() {
|
||||
return Auth.userID;
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ const CURSOR_INTERVAL = 32;
|
||||
|
||||
export default class CursorListener extends Component {
|
||||
static touchCenterPoint(touches) {
|
||||
let totalX = 0; let
|
||||
totalY = 0;
|
||||
let totalX = 0;
|
||||
let totalY = 0;
|
||||
|
||||
for (let i = 0; i < touches.length; i += 1) {
|
||||
totalX += touches[i].clientX;
|
||||
@ -128,6 +128,12 @@ export default class CursorListener extends Component {
|
||||
this.checkCursor(-1, -1);
|
||||
}
|
||||
|
||||
clearTouchEvents() {
|
||||
this.removeTouchListeners();
|
||||
this.touchStarted = false;
|
||||
this.checkCursor(-1, -1);
|
||||
}
|
||||
|
||||
handleTouchStart(event) {
|
||||
event.preventDefault();
|
||||
|
||||
@ -153,20 +159,14 @@ export default class CursorListener extends Component {
|
||||
handleTouchEnd(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.touches.length === 1) {
|
||||
this.removeTouchListeners();
|
||||
this.touchStarted = false;
|
||||
this.checkCursor(-1, -1);
|
||||
}
|
||||
this.clearTouchEvents();
|
||||
}
|
||||
|
||||
handleTouchCancel(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.touches.length === 0) {
|
||||
this.removeTouchListeners();
|
||||
this.touchStarted = false;
|
||||
this.checkCursor(-1, -1);
|
||||
this.clearTouchEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,13 +71,20 @@ class WhiteboardToolbar extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { annotations } = this.props;
|
||||
const { annotations, multiUser, isPresenter } = this.props;
|
||||
|
||||
let annotationSelected = {
|
||||
icon: 'hand',
|
||||
value: 'hand',
|
||||
};
|
||||
|
||||
if (multiUser && !isPresenter) {
|
||||
annotationSelected = {
|
||||
icon: 'pen_tool',
|
||||
value: 'pencil',
|
||||
};
|
||||
}
|
||||
|
||||
if (!annotations.some(el => el.value === annotationSelected.value) && annotations.length > 0) {
|
||||
annotationSelected = annotations[annotations.length - 1];
|
||||
}
|
||||
@ -123,19 +130,28 @@ class WhiteboardToolbar extends Component {
|
||||
this.panOff = this.panOff.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { actions } = this.props;
|
||||
componentDidMount() {
|
||||
const { actions, multiUser, isPresenter } = this.props;
|
||||
const drawSettings = actions.getCurrentDrawSettings();
|
||||
const {
|
||||
annotationSelected, thicknessSelected, colorSelected, fontSizeSelected,
|
||||
} = this.state;
|
||||
|
||||
document.addEventListener('keydown', this.panOn);
|
||||
document.addEventListener('keyup', this.panOff);
|
||||
|
||||
// if there are saved drawSettings in the session storage
|
||||
// - retrieve them and update toolbar values
|
||||
if (drawSettings) {
|
||||
if (multiUser && !isPresenter) {
|
||||
drawSettings.whiteboardAnnotationTool = 'pencil';
|
||||
this.handleAnnotationChange({ icon: 'pen_tool', value: 'pencil' });
|
||||
}
|
||||
|
||||
this.setToolbarValues(drawSettings);
|
||||
// no drawSettings in the sessionStorage - setting default values
|
||||
} else {
|
||||
// setting default drawing settings if they haven't been set previously
|
||||
const {
|
||||
annotationSelected, thicknessSelected, colorSelected, fontSizeSelected,
|
||||
} = this.state;
|
||||
actions.setInitialWhiteboardToolbarValues(
|
||||
annotationSelected.value,
|
||||
thicknessSelected.value * 2,
|
||||
@ -147,13 +163,6 @@ class WhiteboardToolbar extends Component {
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { annotationSelected } = this.state;
|
||||
|
||||
document.addEventListener('keydown', this.panOn);
|
||||
document.addEventListener('keyup', this.panOff);
|
||||
|
||||
if (annotationSelected.value !== 'text') {
|
||||
// trigger initial animation on the thickness circle, otherwise it stays at 0
|
||||
|
@ -469,6 +469,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "الدردشة العامة",
|
||||
"app.lock-viewers.PrivateChatLable": "دردشة خاصة",
|
||||
"app.lock-viewers.notesLabel": "ملاحظات مشتركة",
|
||||
"app.lock-viewers.userListLabel": "قائمة المستخدمين",
|
||||
"app.lock-viewers.Layout": "مظهر",
|
||||
"app.lock-viewers.ariaTitle": "نافذة قفل المشاهدين",
|
||||
"app.recording.startTitle": "بدء التسجيل",
|
||||
|
@ -352,6 +352,7 @@
|
||||
"app.lock-viewers.microphoneLable": "Mikrofon",
|
||||
"app.lock-viewers.PublicChatLabel": "Veřejný chat",
|
||||
"app.lock-viewers.PrivateChatLable": "Soukromý chat",
|
||||
"app.lock-viewers.userListLabel": "Seznam uživatelů",
|
||||
"app.lock-viewers.Layout": "Rozložení obrazovky",
|
||||
"app.recording.startTitle": "Zahájit nahrávání",
|
||||
"app.recording.startDescription": "(Můžete využít nahrávací tlačítko později pro pozastavení nahrávání.)",
|
||||
|
@ -21,6 +21,9 @@
|
||||
"app.chat.offline": "Offline",
|
||||
"app.chat.emptyLogLabel": "Chat-Log ist leer",
|
||||
"app.chat.clearPublicChatMessage": "Der öffentliche Chatverlauf wurde durch einen Moderator gelöscht",
|
||||
"app.chat.severalPeople": "Mehrere Personen",
|
||||
"app.chat.pluralTyping": "tippen",
|
||||
"app.chat.singularTyping": "tippt",
|
||||
"app.captions.label": "Untertitel",
|
||||
"app.captions.menu.close": "Schließen",
|
||||
"app.captions.menu.start": "Start",
|
||||
@ -95,6 +98,7 @@
|
||||
"app.userList.userOptions.disablePrivChat": "Privater Chat ist deaktiviert",
|
||||
"app.userList.userOptions.disablePubChat": "Öffentlicher Chat ist deaktiviert",
|
||||
"app.userList.userOptions.disableNote": "Geteilte Notizen sind jetzt gesperrt",
|
||||
"app.userList.userOptions.hideUserList": "Die Teilnehmerliste ist jetzt für die Teilnehmer nicht mehr sichtbar",
|
||||
"app.userList.userOptions.webcamsOnlyForModerator": "Nur Moderatoren können die Teilnehmerwebcams sehen (wegen eingeschränkter Rechteeinstellungen)",
|
||||
"app.userList.content.participants.options.clearedStatus": "Status aller Teilnehmer zurückgesetzt",
|
||||
"app.userList.userOptions.enableCam": "Teilnehmer dürfen ihre Webcam verwenden",
|
||||
@ -102,11 +106,15 @@
|
||||
"app.userList.userOptions.enablePrivChat": "Privater Chat ist erlaubt",
|
||||
"app.userList.userOptions.enablePubChat": "Öffentlicher Chat ist erlaubt",
|
||||
"app.userList.userOptions.enableNote": "Geteilte Notizen sind erlaubt",
|
||||
"app.userList.userOptions.showUserList": "Die Teilnehmerliste ist jetzt für die Teilnehmer sichtbar",
|
||||
"app.userList.userOptions.enableOnlyModeratorWebcam": "Sie können Ihre Webcam jetzt freigeben, jeder wird Sie sehen.",
|
||||
"app.media.label": "Media",
|
||||
"app.media.autoplayAlertDesc": "Zugang erlauben",
|
||||
"app.media.screenshare.start": "Bildschirmfreigabe wurde gestartet",
|
||||
"app.media.screenshare.end": "Bildschirmfreigabe wurde gestoppt",
|
||||
"app.media.screenshare.safariNotSupported": "Bildschirmfreigabe wird gegenwärtig von Safari nicht unterstützt. Bitte verwenden Sie Firefox oder Google Chrome.",
|
||||
"app.media.screenshare.autoplayBlockedDesc": "Wir benötigen Ihre Zustimmung, um Ihnen den Bildschirm des Präsentators zu zeigen.",
|
||||
"app.media.screenshare.autoplayAllowLabel": "Geteilten Bildschirm ansehen",
|
||||
"app.meeting.ended": "Diese Konferenz wurde beendet",
|
||||
"app.meeting.meetingTimeRemaining": "Verbleibende Konferenzzeit: {0}",
|
||||
"app.meeting.meetingTimeHasEnded": "Die Zeit ist abgelaufen. Die Konferenz wird in Kürze beendet",
|
||||
@ -389,6 +397,9 @@
|
||||
"app.audioModal.audioDialTitle": "Mit dem Telefon teilnehmen",
|
||||
"app.audioDial.audioDialDescription": "Anrufen",
|
||||
"app.audioDial.audioDialConfrenceText": "und geben Sie die Konferenz-PIN-Nummer ein:",
|
||||
"app.audioModal.autoplayBlockedDesc": "Wir benötigen Ihre Zustimmung für die Audiowiedergabe.",
|
||||
"app.audioModal.playAudio": "Audio wiedergeben",
|
||||
"app.audioModal.playAudio.arialabel" : "Audio wiedergeben",
|
||||
"app.audioDial.tipIndicator": "Tipp",
|
||||
"app.audioDial.tipMessage": "Drücken Sie die '0' Taste Ihres Telefons, um sich stumm bzw. freizuschalten.",
|
||||
"app.audioModal.connecting": "Verbinde",
|
||||
@ -494,6 +505,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Öffentlicher Chat",
|
||||
"app.lock-viewers.PrivateChatLable": "Privater Chat",
|
||||
"app.lock-viewers.notesLabel": "Geteilte Notizen",
|
||||
"app.lock-viewers.userListLabel": "Teilnehmerliste",
|
||||
"app.lock-viewers.Layout": "Layout",
|
||||
"app.lock-viewers.ariaTitle": "Teilnehmerrechtedialog",
|
||||
"app.recording.startTitle": "Aufzeichnung starten",
|
||||
@ -599,6 +611,8 @@
|
||||
"app.videoDock.webcamFocusDesc": "Ausgewählte Webcam vergrößern",
|
||||
"app.videoDock.webcamUnfocusLabel": "Normalgröße",
|
||||
"app.videoDock.webcamUnfocusDesc": "Ausgewählte Webcam auf Normalgröße verkleinern",
|
||||
"app.videoDock.autoplayBlockedDesc": "Wir benötigen Ihre Zustimmung, um Ihnen die Webcams anderer Teilnehmer zu zeigen.",
|
||||
"app.videoDock.autoplayAllowLabel": "Webcams zeigen",
|
||||
"app.invitation.title": "Breakoutraum-Einladung",
|
||||
"app.invitation.confirm": "Einladen",
|
||||
"app.createBreakoutRoom.title": "Breakout-Räume",
|
||||
|
@ -98,6 +98,7 @@
|
||||
"app.userList.userOptions.disablePrivChat": "Private chat is disabled",
|
||||
"app.userList.userOptions.disablePubChat": "Public chat is disabled",
|
||||
"app.userList.userOptions.disableNote": "Shared notes are now locked",
|
||||
"app.userList.userOptions.hideUserList": "User list is now hidden for viewers",
|
||||
"app.userList.userOptions.webcamsOnlyForModerator": "Only moderators are able to see viewers' webcams (due to lock settings)",
|
||||
"app.userList.content.participants.options.clearedStatus": "Cleared all user status",
|
||||
"app.userList.userOptions.enableCam": "Viewers' webcams are enabled",
|
||||
@ -105,6 +106,7 @@
|
||||
"app.userList.userOptions.enablePrivChat": "Private chat is enabled",
|
||||
"app.userList.userOptions.enablePubChat": "Public chat is enabled",
|
||||
"app.userList.userOptions.enableNote": "Shared notes are now enabled",
|
||||
"app.userList.userOptions.showUserList": "User list is now shown to viewers",
|
||||
"app.userList.userOptions.enableOnlyModeratorWebcam": "You can enable your webcam now, everyone will see you",
|
||||
"app.media.label": "Media",
|
||||
"app.media.autoplayAlertDesc": "Allow Access",
|
||||
@ -503,6 +505,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Public chat",
|
||||
"app.lock-viewers.PrivateChatLable": "Private chat",
|
||||
"app.lock-viewers.notesLabel": "Shared notes",
|
||||
"app.lock-viewers.userListLabel": "User list",
|
||||
"app.lock-viewers.Layout": "Layout",
|
||||
"app.lock-viewers.ariaTitle": "Lock viewers modal",
|
||||
"app.recording.startTitle": "Start recording",
|
||||
|
@ -483,6 +483,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Chat público",
|
||||
"app.lock-viewers.PrivateChatLable": "Chat privado",
|
||||
"app.lock-viewers.notesLabel": "Notas compartidas",
|
||||
"app.lock-viewers.userListLabel": "Lista de usuarios",
|
||||
"app.lock-viewers.Layout": "Diseño de pantalla",
|
||||
"app.lock-viewers.ariaTitle": "Bloquear ventana flotante de espectadores",
|
||||
"app.recording.startTitle": "Iniciar grabación",
|
||||
|
@ -409,6 +409,7 @@
|
||||
"app.lock-viewers.microphoneLable": "Micrófono",
|
||||
"app.lock-viewers.PublicChatLabel": "Chat público",
|
||||
"app.lock-viewers.PrivateChatLable": "Chat privado",
|
||||
"app.lock-viewers.userListLabel": "Lista de usuarios",
|
||||
"app.lock-viewers.Layout": "Diseño de pantalla",
|
||||
"app.recording.startTitle": "Iniciar grabación",
|
||||
"app.recording.stopTitle": "Detener la grabación",
|
||||
|
@ -493,6 +493,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Txat publikoa",
|
||||
"app.lock-viewers.PrivateChatLable": "Txat pribatua",
|
||||
"app.lock-viewers.notesLabel": "Partekatutako oharrak",
|
||||
"app.lock-viewers.userListLabel": "Erabiltzaileen zerrenda",
|
||||
"app.lock-viewers.Layout": "Diseinua",
|
||||
"app.lock-viewers.ariaTitle": "Blokeatu ikusleen modua",
|
||||
"app.recording.startTitle": "Hasi grabatzen",
|
||||
|
@ -493,6 +493,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "گفتگوی عمومی",
|
||||
"app.lock-viewers.PrivateChatLable": "گفتگوی خصوصی",
|
||||
"app.lock-viewers.notesLabel": "یادداشت های اشتراکی",
|
||||
"app.lock-viewers.userListLabel": "لیست کاربر",
|
||||
"app.lock-viewers.Layout": "چینش صفحه",
|
||||
"app.lock-viewers.ariaTitle": "قفل کردن کادر کاربران",
|
||||
"app.recording.startTitle": "شروع ضبط",
|
||||
|
@ -477,6 +477,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Julkinen chat",
|
||||
"app.lock-viewers.PrivateChatLable": "Yksityinen chat",
|
||||
"app.lock-viewers.notesLabel": "Jaetut muistiinpanot",
|
||||
"app.lock-viewers.userListLabel": "Lista käyttäjistä",
|
||||
"app.lock-viewers.Layout": "Sommittelu",
|
||||
"app.recording.startTitle": "Aloita nauhoitus",
|
||||
"app.recording.stopTitle": "Tauota nauhoitus",
|
||||
|
@ -487,6 +487,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Discussion publique",
|
||||
"app.lock-viewers.PrivateChatLable": "Discussion privée",
|
||||
"app.lock-viewers.notesLabel": "Notes partagées",
|
||||
"app.lock-viewers.userListLabel": "Liste d'utilisateur",
|
||||
"app.lock-viewers.Layout": "Disposition",
|
||||
"app.lock-viewers.ariaTitle": "Verrouille la fenêtre modale des participants",
|
||||
"app.recording.startTitle": "Commencer l'enregistrement",
|
||||
|
@ -53,6 +53,7 @@
|
||||
"app.audioModal.no": "לא",
|
||||
"app.lock-viewers.PublicChatLabel": "צ'אט ציבורי",
|
||||
"app.lock-viewers.PrivateChatLable": "צ'אט פרטי",
|
||||
"app.lock-viewers.userListLabel": "משתתפים",
|
||||
"app.videoPreview.cancelLabel": "בטל",
|
||||
"app.video.cancel": "בטל",
|
||||
"app.externalVideo.noteLabel": "הערה: הסרטון לא יופיע בהקלטה, מומלץ לשלוח הקישור גם בצ'אט "
|
||||
|
@ -415,6 +415,7 @@
|
||||
"app.lock-viewers.microphoneLable": "माइक्रोफ़ोन",
|
||||
"app.lock-viewers.PublicChatLabel": "सार्वजनिक बातचीत",
|
||||
"app.lock-viewers.PrivateChatLable": "गोपनीय बातचीत",
|
||||
"app.lock-viewers.userListLabel": "उपयोगकर्ता सूची",
|
||||
"app.lock-viewers.Layout": "ख़ाका",
|
||||
"app.recording.startTitle": "रिकॉर्डिंग शुरू",
|
||||
"app.recording.stopTitle": "रिकॉर्डिंग रोके",
|
||||
|
@ -484,6 +484,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Nyilvános üzenetek",
|
||||
"app.lock-viewers.PrivateChatLable": "Privát üzenetek",
|
||||
"app.lock-viewers.notesLabel": "Megosztott jegyzetek",
|
||||
"app.lock-viewers.userListLabel": "Felhasználók",
|
||||
"app.lock-viewers.Layout": "Elrendezés",
|
||||
"app.lock-viewers.ariaTitle": "Zárolt felhasználók ablaka",
|
||||
"app.recording.startTitle": "Felvétel indítása",
|
||||
|
@ -442,6 +442,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Chat pubblica",
|
||||
"app.lock-viewers.PrivateChatLable": "Chat privata",
|
||||
"app.lock-viewers.notesLabel": "Note condivise",
|
||||
"app.lock-viewers.userListLabel": "Lista utenti",
|
||||
"app.lock-viewers.Layout": "Disposizione",
|
||||
"app.lock-viewers.ariaTitle": "Finestra di dialogo di blocco utente",
|
||||
"app.recording.startTitle": "Avvia registrazione",
|
||||
|
@ -464,6 +464,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "グループチャット",
|
||||
"app.lock-viewers.PrivateChatLable": "非公開チャット",
|
||||
"app.lock-viewers.notesLabel": "共有メモ",
|
||||
"app.lock-viewers.userListLabel": "ユーザーリスト",
|
||||
"app.lock-viewers.Layout": "レイアウト",
|
||||
"app.lock-viewers.ariaTitle": "ビューアーウィンドウをロック",
|
||||
"app.recording.startTitle": "録画開始",
|
||||
|
@ -464,6 +464,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "グループチャット",
|
||||
"app.lock-viewers.PrivateChatLable": "非公開チャット",
|
||||
"app.lock-viewers.notesLabel": "共有メモ",
|
||||
"app.lock-viewers.userListLabel": "ユーザーリスト",
|
||||
"app.lock-viewers.Layout": "レイアウト",
|
||||
"app.lock-viewers.ariaTitle": "ビューアーウィンドウをロック",
|
||||
"app.recording.startTitle": "録画開始",
|
||||
|
@ -484,6 +484,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "ជជែកសាធារណៈ",
|
||||
"app.lock-viewers.PrivateChatLable": "ជជែកឯកជន",
|
||||
"app.lock-viewers.notesLabel": "កំណត់ត្រារួម",
|
||||
"app.lock-viewers.userListLabel": "បញ្ជីអ្នកចូលរួម",
|
||||
"app.lock-viewers.Layout": "ទម្រង់",
|
||||
"app.lock-viewers.ariaTitle": "ផ្ទាំងបិទមុខងារសម្រាប់អ្នកមើល",
|
||||
"app.recording.startTitle": "ចាប់ផ្តើមថត",
|
||||
|
@ -456,6 +456,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Chat público",
|
||||
"app.lock-viewers.PrivateChatLable": "Chat privado",
|
||||
"app.lock-viewers.notesLabel": "Notas partilhadas",
|
||||
"app.lock-viewers.userListLabel": "Lista de utilizadores",
|
||||
"app.lock-viewers.Layout": "Layout",
|
||||
"app.lock-viewers.ariaTitle": "Bloquear a modal dos espetadores",
|
||||
"app.recording.startTitle": "Iniciar gravação",
|
||||
|
@ -483,6 +483,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Bate-papo público",
|
||||
"app.lock-viewers.PrivateChatLable": "Bate-papo privado",
|
||||
"app.lock-viewers.notesLabel": "Notas compartilhadas",
|
||||
"app.lock-viewers.userListLabel": "Lista de participantes",
|
||||
"app.lock-viewers.Layout": "Layout",
|
||||
"app.lock-viewers.ariaTitle": "Janela de restrição de participantes",
|
||||
"app.recording.startTitle": "Iniciar gravação",
|
||||
|
@ -489,6 +489,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Общий чат",
|
||||
"app.lock-viewers.PrivateChatLable": "Приватный чат",
|
||||
"app.lock-viewers.notesLabel": "Общие заметки",
|
||||
"app.lock-viewers.userListLabel": "Список пользователей",
|
||||
"app.lock-viewers.Layout": "Расположение окон",
|
||||
"app.lock-viewers.ariaTitle": "Окно блокировки участников",
|
||||
"app.recording.startTitle": "Включить запись",
|
||||
|
@ -484,6 +484,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Publik chatt",
|
||||
"app.lock-viewers.PrivateChatLable": "Privat chatt",
|
||||
"app.lock-viewers.notesLabel": "Delade anteckningar",
|
||||
"app.lock-viewers.userListLabel": "Användarlista",
|
||||
"app.lock-viewers.Layout": "Layout",
|
||||
"app.lock-viewers.ariaTitle": "Lås åhörarnas modal",
|
||||
"app.recording.startTitle": "Starta inspelningen",
|
||||
|
@ -439,6 +439,7 @@
|
||||
"app.lock-viewers.microphoneLable": "Мікрофон",
|
||||
"app.lock-viewers.PublicChatLabel": "Публічний чат",
|
||||
"app.lock-viewers.PrivateChatLable": "Приватний чат",
|
||||
"app.lock-viewers.userListLabel": "Список користувачів",
|
||||
"app.lock-viewers.Layout": "Розміщення вікон",
|
||||
"app.recording.startTitle": "Почати запис",
|
||||
"app.recording.startDescription": "(Ви зможете натиснути цю кнопку пізніше, щоб зробити паузу запису.)",
|
||||
|
@ -442,6 +442,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "Cuộc trò chuyện công cộng",
|
||||
"app.lock-viewers.PrivateChatLable": "Cuộc trò chuyện riêng tư",
|
||||
"app.lock-viewers.notesLabel": "Chia sẻ ghi chú",
|
||||
"app.lock-viewers.userListLabel": "Danh sách người dùng",
|
||||
"app.lock-viewers.Layout": "Layout",
|
||||
"app.lock-viewers.ariaTitle": "Khóa phương thức người xem",
|
||||
"app.recording.startTitle": "Bắt đầu ghi âm",
|
||||
|
@ -493,6 +493,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "公共聊天",
|
||||
"app.lock-viewers.PrivateChatLable": "私聊",
|
||||
"app.lock-viewers.notesLabel": "共享的笔记",
|
||||
"app.lock-viewers.userListLabel": "用户列表",
|
||||
"app.lock-viewers.Layout": "页面布局",
|
||||
"app.lock-viewers.ariaTitle": "锁定观众模式",
|
||||
"app.recording.startTitle": "开始录制",
|
||||
|
@ -4,6 +4,7 @@
|
||||
"app.chat.errorMinMessageLength": "訊息僅 {0} 個字(數),太短了",
|
||||
"app.chat.errorMaxMessageLength": "訊息有 {0} 個字(數),太長了",
|
||||
"app.chat.disconnected": "您已經斷線了,訊息無法被送出。",
|
||||
"app.chat.locked": "訊息已被鎖定,無法送出。",
|
||||
"app.chat.inputLabel": "聊天訊息輸入 {0}",
|
||||
"app.chat.inputPlaceholder": "發送訊息給 {0}",
|
||||
"app.chat.titlePublic": "公開聊天",
|
||||
@ -20,6 +21,9 @@
|
||||
"app.chat.offline": "下線",
|
||||
"app.chat.emptyLogLabel": "空的聊天紀錄",
|
||||
"app.chat.clearPublicChatMessage": "公開聊天紀錄已被主持人清空了",
|
||||
"app.chat.severalPeople": "許多參加者",
|
||||
"app.chat.pluralTyping": "許多人正在打字",
|
||||
"app.chat.singularTyping": "正在打字",
|
||||
"app.captions.label": "字幕",
|
||||
"app.captions.menu.close": "關閉",
|
||||
"app.captions.menu.start": "開始",
|
||||
@ -493,6 +497,7 @@
|
||||
"app.lock-viewers.PublicChatLabel": "公開聊天",
|
||||
"app.lock-viewers.PrivateChatLable": "私聊",
|
||||
"app.lock-viewers.notesLabel": "共享筆記",
|
||||
"app.lock-viewers.userListLabel": "用戶列表",
|
||||
"app.lock-viewers.Layout": "佈局",
|
||||
"app.lock-viewers.ariaTitle": "鎖定與會者模式",
|
||||
"app.recording.startTitle": "開始錄製",
|
||||
|
Binary file not shown.
@ -322,6 +322,7 @@ lockSettingsDisableMic=false
|
||||
lockSettingsDisablePrivateChat=false
|
||||
lockSettingsDisablePublicChat=false
|
||||
lockSettingsDisableNote=false
|
||||
lockSettingsHideUserList=false
|
||||
lockSettingsLockedLayout=false
|
||||
lockSettingsLockOnJoin=true
|
||||
lockSettingsLockOnJoinConfigurable=false
|
||||
|
@ -147,6 +147,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
<property name="lockSettingsDisablePrivateChat" value="${lockSettingsDisablePrivateChat}"/>
|
||||
<property name="lockSettingsDisablePublicChat" value="${lockSettingsDisablePublicChat}"/>
|
||||
<property name="lockSettingsDisableNote" value="${lockSettingsDisableNote}"/>
|
||||
<property name="lockSettingsHideUserList" value="${lockSettingsHideUserList}"/>
|
||||
<property name="lockSettingsLockedLayout" value="${lockSettingsLockedLayout}"/>
|
||||
<property name="lockSettingsLockOnJoin" value="${lockSettingsLockOnJoin}"/>
|
||||
<property name="lockSettingsLockOnJoinConfigurable" value="${lockSettingsLockOnJoinConfigurable}"/>
|
||||
|
@ -19,7 +19,7 @@ GEM
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mini_portile2 (2.4.0)
|
||||
nokogiri (1.10.3)
|
||||
nokogiri (1.10.4)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
open4 (1.3.4)
|
||||
parallel (1.17.0)
|
||||
|
Loading…
Reference in New Issue
Block a user