Merge remote-tracking branch 'upstream/v2.0.x-release' into webcams-styling
This commit is contained in:
commit
ad246a1c7f
@ -142,7 +142,7 @@ class ActionsDropdown extends Component {
|
||||
|
||||
return (
|
||||
<Dropdown ref={(ref) => { this._dropdown = ref; }} >
|
||||
<DropdownTrigger tabIndex={0} >
|
||||
<DropdownTrigger tabIndex={0} accessKey="a">
|
||||
<Button
|
||||
hideLabel
|
||||
aria-label={intl.formatMessage(intlMessages.actionsLabel)}
|
||||
|
@ -61,6 +61,7 @@ const EmojiSelect = ({
|
||||
size="lg"
|
||||
color="primary"
|
||||
onClick={() => null}
|
||||
accessKey="s"
|
||||
>
|
||||
<div id="currentStatus" hidden>
|
||||
{ intl.formatMessage(intlMessages.currentStatusDesc, { 0: selected }) }
|
||||
|
@ -64,6 +64,7 @@ const AudioControls = ({
|
||||
icon={unmute ? 'mute' : 'unmute'}
|
||||
size="lg"
|
||||
circle
|
||||
accessKey="m"
|
||||
/> : null}
|
||||
<Button
|
||||
className={styles.button}
|
||||
@ -76,6 +77,7 @@ const AudioControls = ({
|
||||
icon={join ? 'audio_off' : 'audio_on'}
|
||||
size="lg"
|
||||
circle
|
||||
accessKey={join ? 'l' : 'j'}
|
||||
/>
|
||||
</span>);
|
||||
|
||||
|
@ -5,14 +5,22 @@ import { defineMessages, intlShape, injectIntl } from 'react-intl';
|
||||
import { styles } from './styles';
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
yes: {
|
||||
confirmLabel: {
|
||||
id: 'app.audioModal.yes',
|
||||
description: 'Hear yourself yes',
|
||||
},
|
||||
no: {
|
||||
disconfirmLabel: {
|
||||
id: 'app.audioModal.no',
|
||||
description: 'Hear yourself no',
|
||||
},
|
||||
confirmAriaLabel: {
|
||||
id: 'app.audioModal.yes.arialabel',
|
||||
description: 'provides better context for yes btn label',
|
||||
},
|
||||
disconfirmAriaLabel: {
|
||||
id: 'app.audioModal.no.arialabel',
|
||||
description: 'provides better context for no btn label',
|
||||
},
|
||||
});
|
||||
|
||||
const propTypes = {
|
||||
@ -38,7 +46,8 @@ class EchoTest extends Component {
|
||||
<span className={styles.echoTest}>
|
||||
<Button
|
||||
className={styles.button}
|
||||
label={intl.formatMessage(intlMessages.yes)}
|
||||
label={intl.formatMessage(intlMessages.confirmLabel)}
|
||||
aria-label={intl.formatMessage(intlMessages.confirmAriaLabel)}
|
||||
icon="thumbs_up"
|
||||
circle
|
||||
color="success"
|
||||
@ -47,7 +56,8 @@ class EchoTest extends Component {
|
||||
/>
|
||||
<Button
|
||||
className={styles.button}
|
||||
label={intl.formatMessage(intlMessages.no)}
|
||||
label={intl.formatMessage(intlMessages.disconfirmLabel)}
|
||||
aria-label={intl.formatMessage(intlMessages.disconfirmAriaLabel)}
|
||||
icon="thumbs_down"
|
||||
circle
|
||||
color="danger"
|
||||
|
@ -54,6 +54,7 @@ const Chat = (props) => {
|
||||
to="/users"
|
||||
role="button"
|
||||
aria-label={intl.formatMessage(intlMessages.hideChatLabel, { 0: title })}
|
||||
accessKey="h"
|
||||
>
|
||||
<Icon iconName="left_arrow" /> {title}
|
||||
</Link>
|
||||
@ -73,6 +74,7 @@ const Chat = (props) => {
|
||||
onClick={() => actions.handleClosePrivateChat(chatID)}
|
||||
aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })}
|
||||
label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })}
|
||||
accessKey="g"
|
||||
/>
|
||||
</Link> :
|
||||
<ChatDropdown />
|
||||
|
@ -143,6 +143,7 @@ class MessageList extends Component {
|
||||
if (hasUnreadMessages && scrollPosition !== null) {
|
||||
return (
|
||||
<Button
|
||||
aria-hidden="true"
|
||||
className={styles.unreadButton}
|
||||
size="sm"
|
||||
label={intl.formatMessage(intlMessages.moreMessages)}
|
||||
|
7
bigbluebutton-html5/imports/ui/components/media/container.jsx
Normal file → Executable file
7
bigbluebutton-html5/imports/ui/components/media/container.jsx
Normal file → Executable file
@ -1,8 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import Meetings from '/imports/api/meetings/';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
import Media from './component';
|
||||
@ -85,9 +83,6 @@ export default withTracker(() => {
|
||||
const data = {};
|
||||
data.currentPresentation = MediaService.getPresentationInfo();
|
||||
|
||||
const meeting = Meetings.findOne({ meetingId: Auth.meetingID });
|
||||
const webcamOnlyModerator = meeting.usersProp.webcamsOnlyForModerator;
|
||||
|
||||
data.content = <DefaultContent />;
|
||||
|
||||
if (MediaService.shouldShowWhiteboard()) {
|
||||
@ -98,7 +93,7 @@ export default withTracker(() => {
|
||||
data.content = <ScreenshareContainer />;
|
||||
}
|
||||
|
||||
if (MediaService.shouldShowOverlay() && viewParticipantsWebcams && !webcamOnlyModerator) {
|
||||
if (MediaService.shouldShowOverlay() && viewParticipantsWebcams) {
|
||||
data.overlay = <VideoProviderContainer />;
|
||||
}
|
||||
|
||||
|
@ -198,6 +198,7 @@ class NavBar extends Component {
|
||||
className={cx(toggleBtnClasses)}
|
||||
aria-expanded={isExpanded}
|
||||
aria-describedby="newMessage"
|
||||
accessKey="u"
|
||||
/>
|
||||
<div
|
||||
id="newMessage"
|
||||
|
@ -154,7 +154,7 @@ class SettingsDropdown extends Component {
|
||||
onShow={this.onActionsShow}
|
||||
onHide={this.onActionsHide}
|
||||
>
|
||||
<DropdownTrigger tabIndex={0}>
|
||||
<DropdownTrigger tabIndex={0} accessKey="o">
|
||||
<Button
|
||||
label={intl.formatMessage(intlMessages.optionsLabel)}
|
||||
icon="more"
|
||||
|
@ -71,6 +71,7 @@ const ChatListItem = (props) => {
|
||||
role="button"
|
||||
aria-expanded={isCurrentChat}
|
||||
tabIndex={tabIndex}
|
||||
accessKey={isPublicChat(chat) ? 'p' : null}
|
||||
>
|
||||
<div className={styles.chatListItemLink}>
|
||||
<div className={styles.chatIcon}>
|
||||
|
@ -86,11 +86,11 @@ class VideoDock extends Component {
|
||||
<div id="webcamArea" className={styles.webcamArea}>
|
||||
{this.props.users.map(user => (
|
||||
<VideoElement
|
||||
shared={id === user.userId && sharedWebcam}
|
||||
videoId={user.userId}
|
||||
key={user.userId}
|
||||
shared={id === user.id && sharedWebcam}
|
||||
videoId={user.id}
|
||||
key={user.id}
|
||||
name={user.name}
|
||||
localCamera={id === user.userId}
|
||||
localCamera={id === user.id}
|
||||
onShareWebcam={this.props.onShareWebcam.bind(this)}
|
||||
onMount={this.props.onStart.bind(this)}
|
||||
onUnmount={this.props.onStop.bind(this)}
|
||||
|
32
bigbluebutton-html5/imports/ui/components/video-provider/video-dock/container.jsx
Normal file → Executable file
32
bigbluebutton-html5/imports/ui/components/video-provider/video-dock/container.jsx
Normal file → Executable file
@ -1,34 +1,40 @@
|
||||
import React from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import mapUser from '../../../services/user/mapUser';
|
||||
import Meetings from '/imports/api/meetings/';
|
||||
import Users from '/imports/api/users/';
|
||||
import mapUser from '/imports/ui/services/user/mapUser';
|
||||
import VideoDock from './component';
|
||||
import VideoService from '../service';
|
||||
|
||||
const VideoDockContainer = ({ children, ...props }) => <VideoDock {...props}>{children}</VideoDock>;
|
||||
|
||||
export default withTracker(({sharedWebcam}) => {
|
||||
export default withTracker(({ sharedWebcam }) => {
|
||||
const meeting = Meetings.findOne({ meetingId: Auth.meetingID });
|
||||
const lockCam = meeting.lockSettingsProp ? meeting.lockSettingsProp.disableCam : false;
|
||||
const userId = Auth.userID;
|
||||
const user = Users.findOne({ userId });
|
||||
const userLocked = mapUser(user).isLocked;
|
||||
const currentUser = Users.findOne({ userId });
|
||||
const currentUserIsModerator = mapUser(currentUser).isModerator;
|
||||
|
||||
const withActiveStreams = (users) => {
|
||||
const activeFilter = (user) => {
|
||||
const isLocked = lockCam && user.locked;
|
||||
return !isLocked && (user.has_stream || (sharedWebcam && user.userId == userId));
|
||||
};
|
||||
const isSharingWebcam = user => user.isSharingWebcam || (sharedWebcam && user.isCurrent);
|
||||
const isNotLocked = user => !(lockCam && user.isLocked);
|
||||
|
||||
return users.filter(activeFilter);
|
||||
}
|
||||
|
||||
const users = withActiveStreams(VideoService.getAllUsers());
|
||||
const isWebcamOnlyModerator = VideoService.webcamOnlyModerator();
|
||||
const allowedSeeViewersWebcams = !isWebcamOnlyModerator || currentUserIsModerator;
|
||||
const webcamOnlyModerator = (user) => {
|
||||
if (allowedSeeViewersWebcams) return true;
|
||||
return user.isModerator || user.isCurrent;
|
||||
};
|
||||
|
||||
const users = VideoService.getAllUsers()
|
||||
.map(mapUser)
|
||||
.filter(isSharingWebcam)
|
||||
.filter(isNotLocked)
|
||||
.filter(webcamOnlyModerator);
|
||||
|
||||
return {
|
||||
users,
|
||||
userId
|
||||
userId,
|
||||
};
|
||||
})(VideoDockContainer);
|
||||
|
@ -46,7 +46,7 @@ const JoinVideoOptionsContainer = (props) => {
|
||||
iconPath: `${baseName}/resources/images/video-menu/icon-webcam-off.svg`,
|
||||
description: intl.formatMessage(intlMessages[isSharingVideo ? 'leaveVideo' : 'joinVideo']),
|
||||
label: intl.formatMessage(intlMessages[isSharingVideo ? 'leaveVideo' : 'joinVideo']),
|
||||
disabled: isDisabled,
|
||||
disabled: isDisabled && !isSharingVideo,
|
||||
click: isSharingVideo ? handleCloseVideo : handleJoinVideo,
|
||||
},
|
||||
];
|
||||
|
@ -19,12 +19,14 @@ const isDisabled = () => {
|
||||
const videoSettings = Settings.dataSaving;
|
||||
const enableShare = videoSettings.viewParticipantsWebcams;
|
||||
const lockCam = VideoService.isLocked();
|
||||
const webcamOnlyModerator = VideoService.webcamOnlyModerator();
|
||||
|
||||
const user = Users.findOne({ userId: Auth.userID });
|
||||
const userLocked = mapUser(user).isLocked;
|
||||
|
||||
const isConnecting = (!isSharingVideo && isConnected);
|
||||
const isLocked = (lockCam && userLocked) || webcamOnlyModerator;
|
||||
|
||||
|
||||
const isLocked = (lockCam && userLocked);
|
||||
|
||||
return isLocked
|
||||
|| isWaitingResponse
|
||||
|
2
bigbluebutton-html5/imports/ui/services/user/mapUser.js
Normal file → Executable file
2
bigbluebutton-html5/imports/ui/services/user/mapUser.js
Normal file → Executable file
@ -26,7 +26,7 @@ const mapUser = (user) => {
|
||||
isMuted: voiceUser ? voiceUser.muted : false,
|
||||
isTalking: voiceUser ? voiceUser.talking : false,
|
||||
isListenOnly: voiceUser ? voiceUser.listenOnly : false,
|
||||
isSharingWebcam: 0,
|
||||
isSharingWebcam: user.has_stream,
|
||||
isPhoneUser: user.phone_user,
|
||||
isOnline: user.connectionStatus === 'online',
|
||||
};
|
||||
|
@ -36,7 +36,7 @@
|
||||
"app.userList.menu.removeUser.label": "Remove user",
|
||||
"app.userList.menu.muteUserAudio.label": "Mute user",
|
||||
"app.userList.menu.unmuteUserAudio.label": "Unmute user",
|
||||
"app.userList.userAriaLabel": "User : {0} Role: {1} Person: {2} Status: {3}",
|
||||
"app.userList.userAriaLabel": "{0} {1} {2} Status {3}",
|
||||
"app.userList.menu.promoteUser.label": "Promote {0} to moderator",
|
||||
"app.userList.menu.demoteUser.label": "Demote {0} to viewer",
|
||||
"app.media.label": "Media",
|
||||
@ -93,7 +93,7 @@
|
||||
"app.navBar.settingsDropdown.leaveSessionDesc": "Leave the meeting",
|
||||
"app.navBar.settingsDropdown.exitFullscreenDesc": "Exit fullscreen mode",
|
||||
"app.navBar.userListToggleBtnLabel": "User List Toggle",
|
||||
"app.navBar.toggleUserList.ariaLabel": "Users / Conversations Toggle",
|
||||
"app.navBar.toggleUserList.ariaLabel": "Users and Conversations Toggle",
|
||||
"app.navBar.toggleUserList.newMessages": "with new message notification",
|
||||
"app.navBar.recording": "This session is being recorded",
|
||||
"app.navBar.recording.on": "Recording",
|
||||
@ -247,6 +247,8 @@
|
||||
"app.audioModal.closeLabel": "Close",
|
||||
"app.audioModal.yes": "Yes",
|
||||
"app.audioModal.no": "No",
|
||||
"app.audioModal.yes.arialabel" : "Echo is audible",
|
||||
"app.audioModal.no.arialabel" : "Echo is inaudible",
|
||||
"app.audioModal.echoTestTitle": "This is a private echo test. Speak a few words. Did you hear audio?",
|
||||
"app.audioModal.settingsTitle": "Change your audio settings",
|
||||
"app.audioModal.helpTitle": "There was an issue with your media devices",
|
||||
|
Loading…
Reference in New Issue
Block a user