linting some files

This commit is contained in:
Vitor Mateus De Almeida 2021-08-09 11:24:02 -03:00
parent 73b5b2d046
commit 145ca61d40
59 changed files with 861 additions and 716 deletions

View File

@ -297,7 +297,13 @@ class Base extends Component {
}
if (((meetingHasEnded && !meetingIsBreakout)) || (codeError && User?.loggedOut)) {
return (<MeetingEnded code={codeError} endedReason={meetingEndedReason} ejectedReason={ejectedReason} />);
return (
<MeetingEnded
code={codeError}
endedReason={meetingEndedReason}
ejectedReason={ejectedReason}
/>
);
}
if (codeError && !meetingHasEnded) {

View File

@ -42,7 +42,8 @@ const AboutComponent = ({ intl, clientBuild, copyright }) => (
description: intl.formatMessage(intlMessages.dismissDesc),
}}
>
{`${intl.formatMessage(intlMessages.copyright)} ${copyright}`} <br />
{`${intl.formatMessage(intlMessages.copyright)} ${copyright}`}
<br />
{`${intl.formatMessage(intlMessages.version)} ${clientBuild}`}
</Modal>
);

View File

@ -3,17 +3,20 @@ import { withTracker } from 'meteor/react-meteor-data';
import AboutComponent from './component';
const AboutContainer = props => (
<AboutComponent {...props}>
{props.children}
</AboutComponent>
);
const getClientBuildInfo = function () {
return {
clientBuild: Meteor.settings.public.app.html5ClientBuild,
copyright: Meteor.settings.public.app.copyright,
};
const AboutContainer = (props) => {
const { children } = props;
return (
<AboutComponent {...props}>
{children}
</AboutComponent>
);
};
const getClientBuildInfo = () => (
{
clientBuild: Meteor.settings.public.app.html5ClientBuild,
copyright: Meteor.settings.public.app.copyright,
}
);
export default withTracker(() => getClientBuildInfo())(AboutContainer);

View File

@ -14,7 +14,9 @@ import { PANELS, ACTIONS } from '../../layout/enums';
const propTypes = {
amIPresenter: PropTypes.bool.isRequired,
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
mountModal: PropTypes.func.isRequired,
amIModerator: PropTypes.bool.isRequired,
shortcuts: PropTypes.string,
@ -260,7 +262,7 @@ class ActionsDropdown extends PureComponent {
isMeteorConnected,
isDropdownOpen,
sidebarContent,
sidebarNavigation
sidebarNavigation,
} = this.props;
const availableActions = this.getAvailableActions();

View File

@ -6,7 +6,9 @@ import { styles } from '/imports/ui/components/actions-bar/styles';
import Button from '/imports/ui/components/button/component';
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
isActive: PropTypes.bool.isRequired,
handleOnClick: PropTypes.func.isRequired,
};

View File

@ -5,7 +5,7 @@ import CaptionsService from '/imports/ui/components/captions/service';
import CaptionsReaderMenuContainer from '/imports/ui/components/actions-bar/captions/reader-menu/container';
import CaptionsButton from './component';
const CaptionsButtonContainer = props => <CaptionsButton {...props} />;
const CaptionsButtonContainer = (props) => <CaptionsButton {...props} />;
export default withModalMounter(withTracker(({ mountModal }) => ({
isActive: CaptionsService.isCaptionsActive(),

View File

@ -133,22 +133,6 @@ class ReaderMenu extends PureComponent {
this.getPreviewStyle = this.getPreviewStyle.bind(this);
}
getPreviewStyle() {
const {
backgroundColor,
fontColor,
fontFamily,
fontSize,
} = this.state;
return {
fontFamily,
fontSize,
color: fontColor,
background: backgroundColor,
};
}
handleColorPickerClick(fieldname) {
const obj = {};
// eslint-disable-next-line react/destructuring-assignment
@ -199,6 +183,22 @@ class ReaderMenu extends PureComponent {
closeModal();
}
getPreviewStyle() {
const {
backgroundColor,
fontColor,
fontFamily,
fontSize,
} = this.state;
return {
fontFamily,
fontSize,
color: fontColor,
background: backgroundColor,
};
}
render() {
const {
intl,
@ -255,14 +255,15 @@ class ReaderMenu extends PureComponent {
>
{intl.formatMessage(intlMessages.select)}
</option>
{ownedLocales.map(loc => (
{ownedLocales.map((loc) => (
<option
key={loc.locale}
value={loc.locale}
lang={loc.locale}
>
{loc.name}
</option>))}
</option>
))}
</select>
</div>
@ -275,25 +276,34 @@ class ReaderMenu extends PureComponent {
tabIndex={DEFAULT_INDEX}
className={styles.swatch}
onClick={this.handleColorPickerClick.bind(this, 'displayFontColorPicker')}
onKeyPress={() => { }}
role="button"
>
<div className={styles.swatchInner} style={{ background: fontColor }} />
</div>
{displayFontColorPicker
? (
<div className={styles.colorPickerPopover}>
<div
className={styles.colorPickerOverlay}
onClick={this.handleCloseColorPicker.bind(this)}
/>
<GithubPicker
onChange={this.handleColorChange.bind(this, 'fontColor')}
colors={COLORS}
width="140px"
triangle="hide"
/>
</div>
) : null
}
{
displayFontColorPicker
? (
<div className={styles.colorPickerPopover}>
<div
className={styles.colorPickerOverlay}
onClick={this.handleCloseColorPicker.bind(this)}
onKeyPress={() => { }}
role="button"
tabIndex={0}
aria-label={ariaTextColor}
/>
<GithubPicker
// eslint-disable-next-line react/jsx-no-bind
onChange={this.handleColorChange.bind(this, 'fontColor')}
colors={COLORS}
width="140px"
triangle="hide"
/>
</div>
)
: null
}
</div>
<div className={styles.row}>
@ -305,25 +315,34 @@ class ReaderMenu extends PureComponent {
tabIndex={DEFAULT_INDEX}
className={styles.swatch}
onClick={this.handleColorPickerClick.bind(this, 'displayBackgroundColorPicker')}
role="button"
onKeyPress={() => { }}
>
<div className={styles.swatchInner} style={{ background: backgroundColor }} />
</div>
{displayBackgroundColorPicker
? (
<div className={styles.colorPickerPopover}>
<div
className={styles.colorPickerOverlay}
onClick={this.handleCloseColorPicker.bind(this)}
/>
<GithubPicker
onChange={this.handleColorChange.bind(this, 'backgroundColor')}
colors={COLORS}
width="140px"
triangle="hide"
/>
</div>
) : null
}
{
displayBackgroundColorPicker
? (
<div className={styles.colorPickerPopover}>
<div
aria-label={ariaBackgroundColor}
className={styles.colorPickerOverlay}
onClick={this.handleCloseColorPicker.bind(this)}
tabIndex={0}
role="button"
onKeyPress={() => { }}
/>
<GithubPicker
// eslint-disable-next-line react/jsx-no-bind
onChange={this.handleColorChange.bind(this, 'backgroundColor')}
colors={COLORS}
width="140px"
triangle="hide"
/>
</div>
)
: null
}
</div>
<div className={styles.row}>

View File

@ -4,7 +4,7 @@ import { withModalMounter } from '/imports/ui/components/modal/service';
import ReaderMenu from './component';
import CaptionsService from '/imports/ui/components/captions/service';
const ReaderMenuContainer = props => <ReaderMenu {...props} />;
const ReaderMenuContainer = (props) => <ReaderMenu {...props} />;
export default withModalMounter(withTracker(({ mountModal }) => ({
closeModal: () => mountModal(null),

View File

@ -217,14 +217,49 @@ class BreakoutRoom extends PureComponent {
}
}
componentDidUpdate(prevProps, prevstate) {
if (this.listOfUsers) {
for (let i = 0; i < this.listOfUsers.children.length; i += 1) {
const roomList = this.listOfUsers.children[i].getElementsByTagName('div')[0];
roomList.addEventListener('keydown', this.handleMoveEvent, true);
}
}
const { numberOfRooms } = this.state;
const { users } = this.props;
const { users: prevUsers } = prevProps;
if (numberOfRooms < prevstate.numberOfRooms) {
this.resetUserWhenRoomsChange(numberOfRooms);
}
const usersCount = users.length;
const prevUsersCount = prevUsers.length;
if (usersCount > prevUsersCount) {
this.setRoomUsers();
}
if (usersCount < prevUsersCount) {
this.removeRoomUsers();
}
}
componentWillUnmount() {
if (this.listOfUsers) {
for (let i = 0; i < this.listOfUsers.children.length; i += 1) {
const roomList = this.listOfUsers.children[i].getElementsByTagName('div')[0];
roomList.removeEventListener('keydown', this.handleMoveEvent, true);
}
}
this.handleDismiss();
}
handleShiftUser(activeListSibling) {
const { users } = this.state;
if (activeListSibling) {
const text = activeListSibling.getElementsByTagName('p')[0].innerText;
const roomNumber = text.match(/\d/g).join('');
users.forEach((u) => {
users.forEach((u, index) => {
if (u.userId === document.activeElement.id) {
u.room = text.substr(text.length - 1).includes(')') ? 0 : parseInt(roomNumber);
users[index].room = text.substr(text.length - 1).includes(')') ? 0 : parseInt(roomNumber, 10);
}
});
}
@ -278,41 +313,19 @@ class BreakoutRoom extends PureComponent {
this.setRoomUsers();
}
return true;
}
componentWillUnmount() {
if (this.listOfUsers) {
for (let i = 0; i < this.listOfUsers.children.length; i++) {
const roomList = this.listOfUsers.children[i].getElementsByTagName('div')[0];
roomList.removeEventListener('keydown', this.handleMoveEvent, true);
}
}
this.handleDismiss();
}
handleDismiss() {
const { mountModal } = this.props;
componentDidUpdate(prevProps, prevstate) {
if (this.listOfUsers) {
for (let i = 0; i < this.listOfUsers.children.length; i++) {
const roomList = this.listOfUsers.children[i].getElementsByTagName('div')[0];
roomList.addEventListener('keydown', this.handleMoveEvent, true);
}
}
return new Promise((resolve) => {
mountModal(null);
const { numberOfRooms } = this.state;
const { users } = this.props;
const { users: prevUsers } = prevProps;
if (numberOfRooms < prevstate.numberOfRooms) {
this.resetUserWhenRoomsChange(numberOfRooms);
}
const usersCount = users.length;
const prevUsersCount = prevUsers.length;
if (usersCount > prevUsersCount) {
this.setRoomUsers();
}
if (usersCount < prevUsersCount) {
this.removeRoomUsers();
}
this.setState({
preventClosing: false,
}, resolve);
});
}
onCreateBreakouts() {
@ -349,7 +362,8 @@ class BreakoutRoom extends PureComponent {
return;
}
const emptyNames = _.range(1, numberOfRooms + 1).filter((n) => this.getRoomName(n).length === 0);
const emptyNames = _.range(1, numberOfRooms + 1)
.filter((n) => this.getRoomName(n).length === 0);
if (emptyNames.length > 0) {
this.setState({ roomNameEmptyIsValid: false });
return;
@ -456,27 +470,21 @@ class BreakoutRoom extends PureComponent {
return breakoutJoinedUsers.filter((room) => room.sequence === sequence)[0].joinedUsers || [];
}
removeRoomUsers() {
const { users } = this.props;
const { users: stateUsers } = this.state;
const userIds = users.map((user) => user.userId);
const removeUsers = stateUsers.filter((user) => userIds.includes(user.userId));
getRoomName(position) {
const { intl } = this.props;
const { roomNamesChanged } = this.state;
this.setState({
users: removeUsers,
});
if (this.hasNameChanged(position)) {
return roomNamesChanged[position];
}
return intl.formatMessage(intlMessages.breakoutRoom, { 0: position });
}
handleDismiss() {
const { mountModal } = this.props;
getFullName(position) {
const { meetingName } = this.props;
return new Promise((resolve) => {
mountModal(null);
this.setState({
preventClosing: false,
}, resolve);
});
return `${meetingName} (${this.getRoomName(position)})`;
}
resetUserWhenRoomsChange(rooms) {
@ -537,21 +545,15 @@ class BreakoutRoom extends PureComponent {
});
}
getRoomName(position) {
const { intl } = this.props;
const { roomNamesChanged } = this.state;
removeRoomUsers() {
const { users } = this.props;
const { users: stateUsers } = this.state;
const userIds = users.map((user) => user.userId);
const removeUsers = stateUsers.filter((user) => userIds.includes(user.userId));
if (this.hasNameChanged(position)) {
return roomNamesChanged[position];
}
return intl.formatMessage(intlMessages.breakoutRoom, { 0: position });
}
getFullName(position) {
const { meetingName } = this.props;
return `${meetingName} (${this.getRoomName(position)})`;
this.setState({
users: removeUsers,
});
}
hasNameChanged(position) {
@ -559,11 +561,11 @@ class BreakoutRoom extends PureComponent {
const { roomNamesChanged } = this.state;
if (typeof roomNamesChanged[position] !== 'undefined'
&& roomNamesChanged[position] !== intl.formatMessage(intlMessages.breakoutRoom, { 0: position })) {
&& roomNamesChanged[position] !== intl
.formatMessage(intlMessages.breakoutRoom, { 0: position })) {
return true;
} else {
return false;
}
return false;
}
hasNameDuplicated(position) {
@ -599,7 +601,7 @@ class BreakoutRoom extends PureComponent {
};
const changeRoomName = (position) => (ev) => {
let newRoomsNames = [...roomNamesChanged];
const newRoomsNames = [...roomNamesChanged];
newRoomsNames[position] = ev.target.value;
this.setState({
@ -610,17 +612,19 @@ class BreakoutRoom extends PureComponent {
};
return (
<div className={styles.boxContainer} key="rooms-grid-" ref={(r) => this.listOfUsers = r}>
<div className={styles.boxContainer} key="rooms-grid-" ref={(r) => { this.listOfUsers = r; }}>
<div className={!leastOneUserIsValid ? styles.changeToWarn : null}>
<p className={styles.freeJoinLabel}>
<input
type="text"
readOnly={true}
className={styles.breakoutNameInput}
value={intl.formatMessage(intlMessages.notAssigned, { 0: this.getUserByRoom(0).length })}
type="text"
readOnly
className={styles.breakoutNameInput}
value={
intl.formatMessage(intlMessages.notAssigned, { 0: this.getUserByRoom(0).length })
}
/>
</p>
<div className={styles.breakoutBox} onDrop={drop(0)} onDragOver={allowDrop} tabIndex={0}>
<div className={styles.breakoutBox} onDrop={drop(0)} onDragOver={allowDrop}>
{this.renderUserItemByRoom(0)}
</div>
<span className={leastOneUserIsValid ? styles.dontShow : styles.spanWarn}>
@ -643,20 +647,20 @@ class BreakoutRoom extends PureComponent {
aria-label={intl.formatMessage(intlMessages.duration)}
/>
</p>
<div className={styles.breakoutBox} onDrop={drop(value)} onDragOver={allowDrop} tabIndex={0}>
<div className={styles.breakoutBox} onDrop={drop(value)} onDragOver={allowDrop}>
{this.renderUserItemByRoom(value)}
{isInvitation && this.renderJoinedUsers(value)}
</div>
{ this.hasNameDuplicated(value) ? (
{this.hasNameDuplicated(value) ? (
<span className={styles.spanWarn}>
{intl.formatMessage(intlMessages.roomNameDuplicatedIsValid)}
</span>
) : null }
{ this.getRoomName(value).length === 0 ? (
) : null}
{this.getRoomName(value).length === 0 ? (
<span className={styles.spanWarn}>
{intl.formatMessage(intlMessages.roomNameEmptyIsValid)}
</span>
) : null }
) : null}
</div>
))
}
@ -754,7 +758,12 @@ class BreakoutRoom extends PureComponent {
</HoldButton>
</div>
<span className={durationIsValid ? styles.dontShow : styles.leastOneWarn}>
{intl.formatMessage(intlMessages.minimumDurationWarnBreakout, { 0: MIN_BREAKOUT_TIME })}
{
intl.formatMessage(
intlMessages.minimumDurationWarnBreakout,
{ 0: MIN_BREAKOUT_TIME },
)
}
</span>
</label>
@ -862,7 +871,6 @@ class BreakoutRoom extends PureComponent {
return this.getUserByRoom(room)
.map((user) => (
<p
tabIndex={0}
id={user.userId}
key={user.userId}
className={cx(
@ -953,15 +961,15 @@ class BreakoutRoom extends PureComponent {
)}
{!roomNameDuplicatedIsValid
&& (
<span className={styles.withError}>
{intl.formatMessage(intlMessages.roomNameDuplicatedIsValid)}
</span>
<span className={styles.withError}>
{intl.formatMessage(intlMessages.roomNameDuplicatedIsValid)}
</span>
)}
{!roomNameEmptyIsValid
&& (
<span className={styles.withError}>
{intl.formatMessage(intlMessages.roomNameEmptyIsValid)}
</span>
<span className={styles.withError}>
{intl.formatMessage(intlMessages.roomNameEmptyIsValid)}
</span>
)}
</>
);
@ -1048,11 +1056,11 @@ class BreakoutRoom extends PureComponent {
: intl.formatMessage(intlMessages.confirmButton),
callback: isInvitation ? this.onInviteBreakout : this.onCreateBreakouts,
disabled: !leastOneUserIsValid
|| !numberOfRoomsIsValid
|| !roomNameDuplicatedIsValid
|| !roomNameEmptyIsValid
|| !durationIsValid
,
|| !numberOfRoomsIsValid
|| !roomNameDuplicatedIsValid
|| !roomNameEmptyIsValid
|| !durationIsValid
,
}
}
dismiss={{

View File

@ -4,12 +4,15 @@ import ActionsBarService from '/imports/ui/components/actions-bar/service';
import CreateBreakoutRoomModal from './component';
const CreateBreakoutRoomContainer = (props) => (
props.amIModerator
&& (
<CreateBreakoutRoomModal {...props} />
)
);
const CreateBreakoutRoomContainer = (props) => {
const { amIModerator } = props;
return (
amIModerator
&& (
<CreateBreakoutRoomModal {...props} />
)
);
};
export default withTracker(() => ({
createBreakoutRoom: ActionsBarService.createBreakoutRoom,

View File

@ -13,8 +13,8 @@ const propTypes = {
};
const defaultProps = {
onCheck: () => {},
onUncheck: () => {},
onCheck: () => { },
onUncheck: () => { },
};
const intlMessages = defineMessages({
@ -99,7 +99,8 @@ class SortUsers extends Component {
{user.userName}
{user.room && !(user.room === room) ? `\t[${user.room}]` : ''}
</span>
</div>));
</div>
));
}
renderJoinedUserItem() {
@ -107,19 +108,19 @@ class SortUsers extends Component {
if (!joinedUsers.length) return null;
return joinedUsers
.map(b => b.joinedUsers.map(u => ({ ...u, room: b.sequence })))
.map((b) => b.joinedUsers.map((u) => ({ ...u, room: b.sequence })))
.flat()
.map(user => (
.map((user) => (
<div className={styles.selectUserContainer}>
<span className={styles.lockIcon} />
<span className={styles.textName}>
{user.name}
{`\t[${user.room}]`}
</span>
</div>));
</div>
));
}
render() {
const {
intl,

View File

@ -5,7 +5,9 @@ import Button from '/imports/ui/components/button/component';
import MediaService from '/imports/ui/components/media/service';
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
toggleSwapLayout: PropTypes.func.isRequired,
};
@ -20,13 +22,15 @@ const intlMessages = defineMessages({
},
});
const shouldUnswapLayout = () => MediaService.shouldShowScreenshare() || MediaService.shouldShowExternalVideo();
const shouldUnswapLayout = () => (
MediaService.shouldShowScreenshare() || MediaService.shouldShowExternalVideo()
);
const PresentationOptionsContainer = ({
intl,
toggleSwapLayout,
isThereCurrentPresentation,
layoutContextDispatch
layoutContextDispatch,
}) => {
if (shouldUnswapLayout()) toggleSwapLayout();
return (

View File

@ -58,21 +58,23 @@ const handleClickQuickPoll = (layoutContextDispatch) => {
Session.set('pollInitiated', true);
};
const getAvailableQuickPolls = (slideId, parsedSlides, startPoll, pollTypes, layoutContextDispatch) => {
const getAvailableQuickPolls = (
slideId, parsedSlides, startPoll, pollTypes, layoutContextDispatch,
) => {
const pollItemElements = parsedSlides.map((poll) => {
const { poll: label } = poll;
let { type } = poll;
const { type } = poll;
let itemLabel = label;
let letterAnswers = [];
const letterAnswers = [];
if (type !== pollTypes.YesNo &&
type !== pollTypes.YesNoAbstention &&
type !== pollTypes.TrueFalse) {
if (type !== pollTypes.YesNo
&& type !== pollTypes.YesNoAbstention
&& type !== pollTypes.TrueFalse) {
const { options } = itemLabel;
itemLabel = options.join('/').replace(/[\n.)]/g, '');
if (type === pollTypes.Custom) {
for (const option of options) {
const letterOption = option.replace(/[\r.)]/g, '');
for (let i = 0; i < options.length; i += 1) {
const letterOption = options[i].replace(/[\r.)]/g, '');
if (letterAnswers.length < MAX_CUSTOM_FIELDS) {
letterAnswers.push(letterOption);
} else {
@ -138,7 +140,9 @@ class QuickPollDropdown extends Component {
);
const { slideId, quickPollOptions } = parsedSlide;
const quickPolls = getAvailableQuickPolls(slideId, quickPollOptions, startPoll, pollTypes, layoutContextDispatch);
const quickPolls = getAvailableQuickPolls(
slideId, quickPollOptions, startPoll, pollTypes, layoutContextDispatch,
);
if (quickPollOptions.length === 0) return null;
@ -209,7 +213,6 @@ class QuickPollDropdown extends Component {
}
}
QuickPollDropdown.propTypes = propTypes;
export default QuickPollDropdown;

View File

@ -112,7 +112,7 @@ const getErrorLocale = (errorCode) => {
default:
return intlMessages.retryError;
}
}
};
const ScreenshareButton = ({
intl,
@ -128,7 +128,7 @@ const ScreenshareButton = ({
const handleFailure = (error) => {
const {
errorCode = SCREENSHARING_ERRORS.UNKNOWN_ERROR.errorCode,
errorMessage
errorMessage,
} = error;
logger.error({
@ -141,22 +141,20 @@ const ScreenshareButton = ({
screenshareHasEnded();
};
const renderScreenshareUnavailableModal = () => {
return mountModal(
<Modal
overlayClassName={styles.overlay}
className={styles.modal}
onRequestClose={() => mountModal(null)}
hideBorder
contentLabel={intl.formatMessage(intlMessages.screenShareUnavailable)}
>
<h3 className={styles.title}>
{intl.formatMessage(intlMessages.screenShareUnavailable)}
</h3>
<p>{intl.formatMessage(intlMessages.screenShareNotSupported)}</p>
</Modal>
)
};
const renderScreenshareUnavailableModal = () => mountModal(
<Modal
overlayClassName={styles.overlay}
className={styles.modal}
onRequestClose={() => mountModal(null)}
hideBorder
contentLabel={intl.formatMessage(intlMessages.screenShareUnavailable)}
>
<h3 className={styles.title}>
{intl.formatMessage(intlMessages.screenShareUnavailable)}
</h3>
<p>{intl.formatMessage(intlMessages.screenShareNotSupported)}</p>
</Modal>,
);
const screenshareLocked = screenshareDataSavingSetting
? intlMessages.desktopShareLabel : intlMessages.lockedDesktopShareLabel;
@ -192,8 +190,7 @@ const ScreenshareButton = ({
} else {
shareScreen(handleFailure);
}
}
}
}}
id={isVideoBroadcasting ? 'unshare-screen-button' : 'share-screen-button'}
/>
) : null;

View File

@ -8,7 +8,7 @@ import {
dataSavingSetting,
} from '/imports/ui/components/screenshare/service';
const ScreenshareButtonContainer = props => <ScreenshareButton {...props} />;
const ScreenshareButtonContainer = (props) => <ScreenshareButton {...props} />;
/*
* All props, including the ones that are inherited from actions-bar
@ -18,11 +18,11 @@ const ScreenshareButtonContainer = props => <ScreenshareButton {...props} />;
* isMeteorConnected,
* screenshareDataSavingSetting,
*/
export default withModalMounter(withTracker(({ mountModal }) => ({
export default withModalMounter(withTracker(() => ({
isVideoBroadcasting: isVideoBroadcasting(),
screenshareDataSavingSetting: dataSavingSetting(),
enabled: getFromUserSettings(
'bbb_enable_screen_sharing',
Meteor.settings.public.kurento.enableScreensharing
Meteor.settings.public.kurento.enableScreensharing,
),
}))(ScreenshareButtonContainer));

View File

@ -6,11 +6,13 @@ import Button from '/imports/ui/components/button/component';
import Modal from '/imports/ui/components/modal/simple/component';
import { makeCall } from '/imports/ui/services/api';
import { Meteor } from 'meteor/meteor';
import { styles } from './styles';
import { Meteor } from "meteor/meteor";
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
responseDelay: PropTypes.number.isRequired,
};
@ -64,7 +66,7 @@ class ActivityCheck extends Component {
const { responseDelay } = this.state;
return setInterval(() => {
if(responseDelay == 0) return;
if (responseDelay === 0) return;
const remainingTime = responseDelay - 1;

View File

@ -2,6 +2,6 @@ import React from 'react';
import { injectIntl } from 'react-intl';
import ActivityCheck from './component';
const ActivityCheckContainer = props => <ActivityCheck {...props} />;
const ActivityCheckContainer = (props) => <ActivityCheck {...props} />;
export default injectIntl(ActivityCheckContainer);

View File

@ -84,33 +84,40 @@ const {
joinListenOnly,
} = Service;
export default withUsersConsumer(lockContextContainer(withModalMounter(withTracker(({ mountModal, userLocks, users }) => {
const currentUser = users[Auth.meetingID][Auth.userID];
const isViewer = currentUser.role === ROLE_VIEWER;
const isPresenter = currentUser.presenter;
const { status } = Service.getBreakoutAudioTransferStatus();
export default withUsersConsumer(
lockContextContainer(
withModalMounter(withTracker(({ mountModal, userLocks, users }) => {
const currentUser = users[Auth.meetingID][Auth.userID];
const isViewer = currentUser.role === ROLE_VIEWER;
const isPresenter = currentUser.presenter;
const { status } = Service.getBreakoutAudioTransferStatus();
if (status === AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.RETURNING) {
Service.setBreakoutAudioTransferStatus({
status: AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.DISCONNECTED,
});
Service.recoverMicState();
}
if (status === AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.RETURNING) {
Service.setBreakoutAudioTransferStatus({
status: AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.DISCONNECTED,
});
Service.recoverMicState();
}
return ({
processToggleMuteFromOutside: (arg) => processToggleMuteFromOutside(arg),
showMute: isConnected() && !isListenOnly() && !isEchoTest() && !userLocks.userMic,
muted: isConnected() && !isListenOnly() && isMuted(),
inAudio: isConnected() && !isEchoTest(),
listenOnly: isConnected() && isListenOnly(),
disable: isConnecting() || isHangingUp() || !Meteor.status().connected,
talking: isTalking() && !isMuted(),
isVoiceUser: isVoiceUser(),
handleToggleMuteMicrophone: () => toggleMuteMicrophone(),
handleJoinAudio: () => (isConnected() ? joinListenOnly() : mountModal(<AudioModalContainer />)),
handleLeaveAudio,
inputStream: AudioManager.inputStream,
isViewer,
isPresenter,
});
})(AudioControlsContainer))));
return ({
processToggleMuteFromOutside: (arg) => processToggleMuteFromOutside(arg),
showMute: isConnected() && !isListenOnly() && !isEchoTest() && !userLocks.userMic,
muted: isConnected() && !isListenOnly() && isMuted(),
inAudio: isConnected() && !isEchoTest(),
listenOnly: isConnected() && isListenOnly(),
disable: isConnecting() || isHangingUp() || !Meteor.status().connected,
talking: isTalking() && !isMuted(),
isVoiceUser: isVoiceUser(),
handleToggleMuteMicrophone: () => toggleMuteMicrophone(),
handleJoinAudio: () => (isConnected()
? joinListenOnly()
: mountModal(<AudioModalContainer />)
),
handleLeaveAudio,
inputStream: AudioManager.inputStream,
isViewer,
isPresenter,
});
})(AudioControlsContainer)),
),
);

View File

@ -315,7 +315,9 @@ class InputStreamLiveSelector extends Component {
</Button>
</Dropdown.DropdownTrigger>
<Dropdown.DropdownContent className={styles.dropdownContent}>
<Dropdown.DropdownList className={cx(styles.scrollableList, styles.dropdownListContainer)}>
<Dropdown.DropdownList
className={cx(styles.scrollableList, styles.dropdownListContainer)}
>
{dropdownListComplete}
</Dropdown.DropdownList>
</Dropdown.DropdownContent>

View File

@ -23,7 +23,9 @@ const intlMessages = defineMessages({
});
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
formattedDialNum: PropTypes.string.isRequired,
telVoice: PropTypes.string.isRequired,
};

View File

@ -16,7 +16,9 @@ import AudioDial from '../audio-dial/component';
import AudioAutoplayPrompt from '../autoplay/component';
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
closeModal: PropTypes.func.isRequired,
joinMicrophone: PropTypes.func.isRequired,
joinListenOnly: PropTypes.func.isRequired,
@ -173,13 +175,18 @@ class AudioModal extends Component {
if (joinFullAudioImmediately && !listenOnlyMode) return this.handleJoinMicrophone();
}
return false;
}
componentDidUpdate(prevProps) {
const { autoplayBlocked, closeModal } = this.props;
if (autoplayBlocked !== prevProps.autoplayBlocked) {
autoplayBlocked ? this.setState({ content: 'autoplayBlocked' }) : closeModal();
if (autoplayBlocked) {
this.setContent('autoplayBlocked');
} else {
closeModal();
}
}
}
@ -244,7 +251,7 @@ class AudioModal extends Component {
disableActions,
} = this.state;
if (disableActions && isConnecting) return;
if (disableActions && isConnecting) return null;
this.setState({
hasError: false,
@ -292,7 +299,7 @@ class AudioModal extends Component {
disableActions,
} = this.state;
if (disableActions && isConnecting) return;
if (disableActions && isConnecting) return null;
this.setState({
disableActions: true,
@ -335,6 +342,10 @@ class AudioModal extends Component {
}).catch(this.handleGoToAudioOptions);
}
setContent(content) {
this.setState(content);
}
skipAudioOptions() {
const {
isConnecting,
@ -377,7 +388,11 @@ class AudioModal extends Component {
circle
size="jumbo"
disabled={audioLocked}
onClick={joinFullAudioImmediately ? this.handleJoinMicrophone : this.handleGoToEchoTest}
onClick={
joinFullAudioImmediately
? this.handleJoinMicrophone
: this.handleGoToEchoTest
}
/>
)
: null}
@ -430,16 +445,18 @@ class AudioModal extends Component {
<div className={styles.text}>
{intl.formatMessage(intlMessages.iOSErrorRecommendation)}
</div>
</div>);
</div>
);
}
if (this.skipAudioOptions()) {
return (
<div className={styles.connecting} role="alert">
<span data-test={!isEchoTest ? 'connecting' : 'connectingToEchoTest'}>
{!isEchoTest
? intl.formatMessage(intlMessages.connecting)
: intl.formatMessage(intlMessages.connectingEchoTest)
{
!isEchoTest
? intl.formatMessage(intlMessages.connecting)
: intl.formatMessage(intlMessages.connectingEchoTest)
}
</span>
<span className={styles.connectingAnimation} />
@ -556,25 +573,26 @@ class AudioModal extends Component {
/>
</p>
) : null}
{!this.skipAudioOptions()
? (
<header
data-test="audioModalHeader"
className={styles.header}
>
{
isIOSChrome ? null
: (
<h2 className={styles.title}>
{content
? intl.formatMessage(this.contents[content].title)
: intl.formatMessage(intlMessages.audioChoiceLabel)}
</h2>
)
}
</header>
)
: null
{
!this.skipAudioOptions()
? (
<header
data-test="audioModalHeader"
className={styles.header}
>
{
isIOSChrome ? null
: (
<h2 className={styles.title}>
{content
? intl.formatMessage(this.contents[content].title)
: intl.formatMessage(intlMessages.audioChoiceLabel)}
</h2>
)
}
</header>
)
: null
}
<div className={styles.content}>
{this.renderContent()}

View File

@ -49,8 +49,16 @@ export default lockContextContainer(withModalMounter(withTracker(({ userLocks })
const meetingIsBreakout = AppService.meetingIsBreakout();
const joinFullAudioImmediately = (autoJoin && (skipCheck || skipCheckOnJoin && !getEchoTest))
|| (skipCheck || skipCheckOnJoin && !getEchoTest);
const joinFullAudioImmediately = (
autoJoin
&& (
skipCheck
|| (skipCheckOnJoin && !getEchoTest)
))
|| (
skipCheck
|| (skipCheckOnJoin && !getEchoTest)
);
const forceListenOnlyAttendee = forceListenOnly && !Service.isUserModerator();

View File

@ -9,7 +9,9 @@ import cx from 'classnames';
import { styles } from './styles';
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
changeInputDevice: PropTypes.func.isRequired,
changeOutputDevice: PropTypes.func.isRequired,
handleBack: PropTypes.func.isRequired,
@ -94,6 +96,8 @@ class AudioSettings extends React.Component {
handleRetry,
} = this.props;
const { inputDeviceId, outputDeviceId } = this.state;
return (
<div className={styles.formWrapper}>
<div className={styles.form}>
@ -113,7 +117,7 @@ class AudioSettings extends React.Component {
{intl.formatMessage(intlMessages.micSourceLabel)}
<DeviceSelector
id="inputDeviceSelector"
value={this.state.inputDeviceId}
value={inputDeviceId}
className={styles.select}
kind="audioinput"
onChange={this.handleInputChange}
@ -130,7 +134,7 @@ class AudioSettings extends React.Component {
{intl.formatMessage(intlMessages.speakerSourceLabel)}
<DeviceSelector
id="outputDeviceSelector"
value={this.state.outputDeviceId}
value={outputDeviceId}
className={styles.select}
kind="audiooutput"
onChange={this.handleOutputChange}
@ -142,6 +146,7 @@ class AudioSettings extends React.Component {
<div className={styles.row}>
<div className={cx(styles.col, styles.spacedLeft)}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label
htmlFor="audioTest"
className={styles.labelSmall}
@ -153,7 +158,6 @@ class AudioSettings extends React.Component {
</div>
</div>
<div className={styles.enterAudio}>
<Button
className={styles.backBtn}

View File

@ -19,6 +19,13 @@ const defaultProps = {
const AudioContext = window.AudioContext || window.webkitAudioContext;
class AudioStreamVolume extends Component {
static handleError(error) {
logger.error({
logCode: 'audiostreamvolume_handleError',
extraInfo: { error },
}, 'Encountered error while creating audio context');
}
constructor(props) {
super(props);
@ -26,7 +33,7 @@ class AudioStreamVolume extends Component {
this.closeAudioContext = this.closeAudioContext.bind(this);
this.handleConnectStreamToProcessor = this.handleConnectStreamToProcessor.bind(this);
this.handleAudioProcess = this.handleAudioProcess.bind(this);
this.handleError = this.handleError.bind(this);
this.handleError = AudioStreamVolume.handleError.bind(this);
this.state = {
slow: 0,
@ -53,6 +60,22 @@ class AudioStreamVolume extends Component {
this.closeAudioContext();
}
handleConnectStreamToProcessor(stream) {
this.source = this.audioContext.createMediaStreamSource(stream);
this.source.connect(this.scriptProcessor);
this.scriptProcessor.connect(this.audioContext.destination);
}
handleAudioProcess(event) {
const input = event.inputBuffer.getChannelData(0);
const sum = input.reduce((a, b) => a + (b * b), 0);
const instant = Math.sqrt(sum / input.length);
this.setState((prevState) => ({
slow: (0.75 * prevState.slow) + (0.25 * instant),
}));
}
createAudioContext() {
this.audioContext = new AudioContext();
this.scriptProcessor = this.audioContext.createScriptProcessor(2048, 1, 1);
@ -85,30 +108,6 @@ class AudioStreamVolume extends Component {
});
}
handleConnectStreamToProcessor(stream) {
this.source = this.audioContext.createMediaStreamSource(stream);
this.source.connect(this.scriptProcessor);
this.scriptProcessor.connect(this.audioContext.destination);
}
handleAudioProcess(event) {
const input = event.inputBuffer.getChannelData(0);
const sum = input.reduce((a, b) => a + (b * b), 0);
const instant = Math.sqrt(sum / input.length);
this.setState(prevState => ({
instant,
slow: (0.75 * prevState.slow) + (0.25 * instant),
}));
}
handleError(error) {
logger.error({
logCode: 'audiostreamvolume_handleError',
extraInfo: { error },
}, 'Encountered error while creating audio context');
}
render() {
const {
low, optimum, high, ...props

View File

@ -5,7 +5,9 @@ import { defineMessages, injectIntl } from 'react-intl';
import { styles } from './styles.scss';
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
handlePlayAudioSample: PropTypes.func.isRequired,
outputDeviceId: PropTypes.string,
};
@ -38,9 +40,9 @@ class AudioTest extends React.Component {
<Button
className={styles.testAudioBtn}
label={intl.formatMessage(intlMessages.playSoundLabel)}
icon={'unmute'}
size={'sm'}
color={'primary'}
icon="unmute"
size="sm"
color="primary"
onClick={() => this.handlePlayAudioSample(outputDeviceId)}
/>
);

View File

@ -3,7 +3,7 @@ import { withTracker } from 'meteor/react-meteor-data';
import Service from '/imports/ui/components/audio/service';
import AudioTest from './component';
const AudioTestContainer = props => <AudioTest {...props} />;
const AudioTestContainer = (props) => <AudioTest {...props} />;
export default withTracker(() => ({
outputDeviceId: Service.outputDeviceId(),

View File

@ -4,7 +4,6 @@ import Button from '/imports/ui/components/button/component';
import { defineMessages, injectIntl } from 'react-intl';
import { styles } from './styles';
const intlMessages = defineMessages({
confirmLabel: {
id: 'app.audioModal.playAudio',
@ -18,7 +17,9 @@ const intlMessages = defineMessages({
const propTypes = {
handleAllowAutoplay: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
};
class AudioAutoplayPrompt extends PureComponent {

View File

@ -35,7 +35,7 @@ class DeviceSelector extends Component {
componentDidMount() {
const { kind } = this.props;
const handleEnumerateDevicesSuccess = (deviceInfos) => {
const devices = deviceInfos.filter(d => d.kind === kind);
const devices = deviceInfos.filter((d) => d.kind === kind);
logger.info({
logCode: 'audiodeviceselector_component_enumeratedevices_success',
extraInfo: {
@ -56,7 +56,7 @@ class DeviceSelector extends Component {
navigator.mediaDevices
.enumerateDevices()
.then(handleEnumerateDevicesSuccess)
.catch((err) => {
.catch(() => {
logger.error({
logCode: 'audiodeviceselector_component_enumeratedevices_error',
extraInfo: {
@ -71,7 +71,7 @@ class DeviceSelector extends Component {
const { onChange } = this.props;
const { devices } = this.state;
this.setState({ value }, () => {
const selectedDevice = devices.find(d => d.deviceId === value);
const selectedDevice = devices.find((d) => d.deviceId === value);
onChange(selectedDevice.deviceId, selectedDevice, event);
});
}
@ -84,6 +84,14 @@ class DeviceSelector extends Component {
const { options, value } = this.state;
const { isSafari } = browserInfo;
let notFoundOption;
if (kind === 'audiooutput' && isSafari) {
notFoundOption = <option value="not-found">Default</option>;
} else {
notFoundOption = <option value="not-found">{`no ${kind} found`}</option>;
}
return (
<select
{...props}
@ -94,7 +102,7 @@ class DeviceSelector extends Component {
>
{
options.length
? options.map(option => (
? options.map((option) => (
<option
key={option.key}
value={option.value}
@ -102,11 +110,7 @@ class DeviceSelector extends Component {
{option.label}
</option>
))
: (
(kind === 'audiooutput' && isSafari)
? <option value="not-found">Default</option>
: <option value="not-found">{`no ${kind} found`}</option>
)
: notFoundOption
}
</select>
);

View File

@ -27,7 +27,9 @@ const intlMessages = defineMessages({
const propTypes = {
handleYes: PropTypes.func.isRequired,
handleNo: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
};
class EchoTest extends Component {
@ -52,7 +54,8 @@ class EchoTest extends Component {
const {
intl,
} = this.props;
const disableYesButtonClicked = callback => () => {
const { disabled } = this.state;
const disableYesButtonClicked = (callback) => () => {
this.setState({ disabled: true }, callback);
};
return (
@ -62,7 +65,7 @@ class EchoTest extends Component {
label={intl.formatMessage(intlMessages.confirmLabel)}
aria-label={intl.formatMessage(intlMessages.confirmAriaLabel)}
icon="thumbs_up"
disabled={this.state.disabled}
disabled={disabled}
circle
color="success"
size="jumbo"

View File

@ -4,11 +4,13 @@ import NotificationsBar from '/imports/ui/components/notifications-bar/component
import { styles } from './styles';
import { ACTIONS } from '../layout/enums';
const BannerBar = ({ text, color, hasBanner: propsHasBanner, layoutContextDispatch }) => {
const BannerBar = ({
text, color, hasBanner: propsHasBanner, layoutContextDispatch,
}) => {
useEffect(() => {
const localHasBanner = !!text;
if(localHasBanner !== propsHasBanner){
if (localHasBanner !== propsHasBanner) {
layoutContextDispatch({
type: ACTIONS.SET_HAS_BANNER_BAR,
value: localHasBanner,
@ -25,7 +27,7 @@ const BannerBar = ({ text, color, hasBanner: propsHasBanner, layoutContextDispat
</span>
</NotificationsBar>
);
}
};
BannerBar.propTypes = {
text: PropTypes.string.isRequired,

View File

@ -4,6 +4,7 @@ import _ from 'lodash';
import Button from '/imports/ui/components/button/component';
import { Session } from 'meteor/session';
import logger from '/imports/startup/client/logger';
import cx from 'classnames';
import { styles } from './styles';
import Service from './service';
import BreakoutRoomContainer from './breakout-remaining-time/container';
@ -12,7 +13,6 @@ import { PANELS, ACTIONS } from '../layout/enums';
import { screenshareHasEnded } from '/imports/ui/components/screenshare/service';
import UserListService from '/imports/ui/components/user-list/service';
import AudioManager from '/imports/ui/services/audio-manager';
import cx from "classnames";
const intlMessages = defineMessages({
breakoutTitle: {
@ -135,7 +135,7 @@ class BreakoutRoom extends PureComponent {
if (waiting) {
const breakoutUser = breakoutRoomUser(requestedBreakoutId);
if (!breakoutUser) return;
if (!breakoutUser) return false;
if (breakoutUser.redirectToHtml5JoinURL !== '') {
window.open(breakoutUser.redirectToHtml5JoinURL, '_blank');
_.delay(() => this.setState({ waiting: false }), 1000);
@ -149,6 +149,7 @@ class BreakoutRoom extends PureComponent {
status: AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.DISCONNECTED,
});
}
return true;
}
getBreakoutURL(breakoutId) {
@ -273,35 +274,35 @@ class BreakoutRoom extends PureComponent {
};
return (
<div className={styles.breakoutActions}>
{isUserInBreakoutRoom(joinedUsers)
? (
<span className={styles.alreadyConnected}>
{intl.formatMessage(intlMessages.alreadyConnected)}
</span>
)
: (
<Button
label={intl.formatMessage(intlMessages.breakoutJoin)}
data-test="breakoutJoin"
aria-label={`${intl.formatMessage(intlMessages.breakoutJoin)} ${number}`}
onClick={() => {
this.getBreakoutURL(breakoutId);
// leave main room's audio,
// and stops video and screenshare when joining a breakout room
exitAudio();
logger.debug({
logCode: 'breakoutroom_join',
extraInfo: { logType: 'user_action' },
}, 'joining breakout room closed audio in the main room');
VideoService.storeDeviceIds();
VideoService.exitVideo();
if (UserListService.amIPresenter()) screenshareHasEnded();
}
}
disabled={disable}
className={styles.joinButton}
/>
)
{
isUserInBreakoutRoom(joinedUsers)
? (
<span className={styles.alreadyConnected}>
{intl.formatMessage(intlMessages.alreadyConnected)}
</span>
)
: (
<Button
label={intl.formatMessage(intlMessages.breakoutJoin)}
data-test="breakoutJoin"
aria-label={`${intl.formatMessage(intlMessages.breakoutJoin)} ${number}`}
onClick={() => {
this.getBreakoutURL(breakoutId);
// leave main room's audio,
// and stops video and screenshare when joining a breakout room
exitAudio();
logger.debug({
logCode: 'breakoutroom_join',
extraInfo: { logType: 'user_action' },
}, 'joining breakout room closed audio in the main room');
VideoService.storeDeviceIds();
VideoService.exitVideo();
if (UserListService.amIPresenter()) screenshareHasEnded();
}}
disabled={disable}
className={styles.joinButton}
/>
)
}
{
moderatorJoinedAudio
@ -328,7 +329,6 @@ class BreakoutRoom extends PureComponent {
);
}
renderBreakoutRooms() {
const {
breakoutRooms,
@ -340,16 +340,16 @@ class BreakoutRoom extends PureComponent {
requestedBreakoutId,
} = this.state;
const roomItems = breakoutRooms.map(breakout => (
const roomItems = breakoutRooms.map((breakout) => (
<div
className={styles.breakoutItems}
key={`breakoutRoomItems-${breakout.breakoutId}`}
>
<div className={styles.content} key={`breakoutRoomList-${breakout.breakoutId}`}>
<span className={styles.breakoutRoomListNameLabel} aria-hidden>
{ breakout.isDefaultName
{breakout.isDefaultName
? intl.formatMessage(intlMessages.breakoutRoom, { 0: breakout.sequence })
: breakout.shortName }
: breakout.shortName}
<span className={styles.usersAssignedNumberLabel}>
(
{breakout.joinedUsers.length}
@ -372,7 +372,7 @@ class BreakoutRoom extends PureComponent {
.sort(BreakoutRoom.sortById)
.filter((value, idx, arr) => !(value.userId === (arr[idx + 1] || {}).userId))
.sort(Service.sortUsersByName)
.map(u => u.name)
.map((u) => u.name)
.join(', ')}
</div>
</div>
@ -389,12 +389,21 @@ class BreakoutRoom extends PureComponent {
renderDuration() {
const {
intl, breakoutRooms, amIModerator, isMeteorConnected, extendBreakoutsTime, isExtendTimeHigherThanMeetingRemaining,
intl,
breakoutRooms,
amIModerator,
isMeteorConnected,
extendBreakoutsTime,
isExtendTimeHigherThanMeetingRemaining,
} = this.props;
const { extendTime, visibleExtendTimeForm, visibleExtendTimeHigherThanMeetingTimeError } = this.state;
const {
extendTime,
visibleExtendTimeForm,
visibleExtendTimeHigherThanMeetingTimeError,
} = this.state;
return (
<div className={styles.durationContainer}>
{ amIModerator && visibleExtendTimeForm ? (
{amIModerator && visibleExtendTimeForm ? (
<div className={styles.extendTimeContainer}>
<label
htmlFor="inputExtendTimeSelector"
@ -414,13 +423,13 @@ class BreakoutRoom extends PureComponent {
/>
<br />
<br />
{ visibleExtendTimeHigherThanMeetingTimeError ? (
{visibleExtendTimeHigherThanMeetingTimeError ? (
<span className={styles.withError}>
{intl.formatMessage(intlMessages.extendTimeHigherThanMeetingTimeError)}
<br />
<br />
</span>
) : null }
) : null}
<Button
color="default"
disabled={!isMeteorConnected}
@ -446,13 +455,13 @@ class BreakoutRoom extends PureComponent {
}}
/>
</div>
) : null }
) : null}
<span className={styles.duration}>
<BreakoutRoomContainer
messageDuration={intlMessages.breakoutDuration}
breakoutRoom={breakoutRooms[0]}
/>
{ !visibleExtendTimeForm
{!visibleExtendTimeForm
? (
<Button
onClick={this.showExtendTimeForm}
@ -466,7 +475,7 @@ class BreakoutRoom extends PureComponent {
disabled={!isMeteorConnected}
/>
)
: null }
: null}
</span>
</div>
);

View File

@ -12,7 +12,6 @@ const BreakoutContainer = (props) => {
return <BreakoutComponent {...{ layoutContextDispatch, ...props }} />;
};
export default withTracker((props) => {
const {
endAllBreakouts,

View File

@ -104,10 +104,12 @@ class Pad extends PureComponent {
currentUserId,
} = this.props;
const { listening } = this.state;
if (this.recognition) {
if (ownerId !== currentUserId) {
this.recognition.stop();
} else if (this.state.listening && this.recognition.lang !== locale) {
} else if (listening && this.recognition.lang !== locale) {
this.recognition.stop();
this.stopListen();
}

View File

@ -7,7 +7,6 @@ import Auth from '/imports/ui/services/auth';
import LayoutContext from '../../layout/context';
import { ACTIONS, PANELS } from '../../layout/enums';
const PadContainer = (props) => {
const layoutContext = useContext(LayoutContext);
const { layoutContextDispatch } = layoutContext;

View File

@ -116,9 +116,10 @@ class WriterMenu extends PureComponent {
</h3>
</header>
<div className={styles.content}>
<label>
<span>
{intl.formatMessage(intlMessages.subtitle)}
</label>
</span>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label
aria-hidden
htmlFor="captionsLangSelector"

View File

@ -14,5 +14,5 @@ const WriterMenuContainer = (props) => {
export default withModalMounter(withTracker(({ mountModal }) => ({
closeModal: () => mountModal(null),
allLocales: CaptionsService.getAvailableLocales(),
takeOwnership: locale => CaptionsService.takeOwnership(locale),
takeOwnership: (locale) => CaptionsService.takeOwnership(locale),
}))(WriterMenuContainer));

View File

@ -145,7 +145,7 @@ const Chat = (props) => {
syncing,
syncedPercent,
lastTimeWindowValuesBuild,
userSentMessage
userSentMessage,
}}
/>
<MessageFormContainer

View File

@ -17,7 +17,7 @@ const MessageFormContainer = (props) => {
return ChatService.sendGroupMessage(message, idChatOpen);
};
const startUserTyping = _.throttle(
chatId => makeCall('startUserTyping', chatId),
(chatId) => makeCall('startUserTyping', chatId),
START_TYPING_THROTTLE_INTERVAL,
);
const stopUserTyping = () => makeCall('stopUserTyping');

View File

@ -182,7 +182,8 @@ class DebugWindow extends Component {
>
{
chatLoggerLevelsNames.map((i, index) => {
return (<option key={`${i}-${index}`}>{i}</option>);
const idx = index;
return (<option key={`${i}-${idx}`}>{i}</option>);
})
}
</select>

View File

@ -2,7 +2,6 @@ import React, { Component } from 'react';
import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
import { defineMessages, injectIntl } from 'react-intl';
import ReactPlayer from 'react-player';
import _ from 'lodash';
import {
sendMessage,
onMessage,
@ -19,8 +18,8 @@ import logger from '/imports/startup/client/logger';
import VolumeSlider from './volume-slider/component';
import ReloadButton from '/imports/ui/components/reload-button/component';
import ArcPlayer from './custom-players/arc-player';
import PeerTubePlayer from './custom-players/peertube';
import ArcPlayer from '/imports/ui/components/external-video-player/custom-players/arc-player';
import PeerTubePlayer from '/imports/ui/components/external-video-player/custom-players/peertube';
import { styles } from './styles';
@ -359,6 +358,7 @@ class VideoPlayer extends Component {
this.lastMessage = msg;
this.lastMessageTimestamp = timestamp;
}
return true;
}
registerVideoListeners() {
@ -454,6 +454,7 @@ class VideoPlayer extends Component {
extraInfo: { time },
}, `Seek external video to: ${time}`);
}
return true;
}
render() {
@ -535,8 +536,8 @@ class VideoPlayer extends Component {
<ReloadButton
handleReload={this.handleReload}
label={intl.formatMessage(intlMessages.refreshLabel)}>
</ReloadButton>
label={intl.formatMessage(intlMessages.refreshLabel)}
/>
</div>
),
(this.isMobile && playing) && (

View File

@ -1,6 +1,5 @@
import React, { useContext } from 'react';
import FullscreenButtonComponent from './component';
import FullscreenService from './service';
import LayoutContext from '../layout/context';
const FullscreenButtonContainer = (props) => <FullscreenButtonComponent {...props} />;

View File

@ -54,14 +54,6 @@ class CustomLayout extends Component {
}
}
mainWidth() {
return window.document.documentElement.clientWidth;
}
mainHeight() {
return window.document.documentElement.clientHeight;
}
bannerAreaHeight() {
const { layoutContextState } = this.props;
const { input } = layoutContextState;
@ -77,9 +69,9 @@ class CustomLayout extends Component {
const { layoutContextState } = this.props;
const { isRTL } = layoutContextState;
const { height: actionBarHeight } = this.calculatesActionbarHeight();
const mediaAreaHeight = this.mainHeight()
const mediaAreaHeight = windowHeight()
- (DEFAULT_VALUES.navBarHeight + actionBarHeight);
const mediaAreaWidth = this.mainWidth() - (sidebarNavWidth + sidebarContentWidth);
const mediaAreaWidth = windowWidth() - (sidebarNavWidth + sidebarContentWidth);
const DROP_ZONE_DEFAUL_SIZE = 100;
const dropZones = {};
const sidebarSize = sidebarNavWidth + sidebarContentWidth;
@ -95,7 +87,7 @@ class CustomLayout extends Component {
dropZones[CAMERADOCK_POSITION.CONTENT_RIGHT] = {
top: DEFAULT_VALUES.navBarHeight + DROP_ZONE_DEFAUL_SIZE,
left: !isRTL ? this.mainWidth() - DROP_ZONE_DEFAUL_SIZE : 0,
left: !isRTL ? windowWidth() - DROP_ZONE_DEFAUL_SIZE : 0,
height: mediaAreaHeight
- (2 * DROP_ZONE_DEFAUL_SIZE),
width: DROP_ZONE_DEFAUL_SIZE,
@ -124,7 +116,7 @@ class CustomLayout extends Component {
};
dropZones[CAMERADOCK_POSITION.SIDEBAR_CONTENT_BOTTOM] = {
top: this.mainHeight() - DROP_ZONE_DEFAUL_SIZE,
top: windowHeight() - DROP_ZONE_DEFAUL_SIZE,
left: !isRTL ? sidebarNavWidth : null,
right: isRTL ? sidebarNavWidth : null,
width: sidebarContentWidth,
@ -241,7 +233,7 @@ class CustomLayout extends Component {
height: actionBarHeight.height,
innerHeight: actionBarHeight.innerHeight,
padding: actionBarHeight.padding,
top: this.mainHeight() - actionBarHeight.height,
top: windowHeight() - actionBarHeight.height,
left: !isRTL ? mediaAreaBounds.left : 0,
zIndex: 1,
};
@ -259,12 +251,12 @@ class CustomLayout extends Component {
let maxWidth = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarNavigation.width === 0) {
width = min(max((this.mainWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
width = min(max((windowWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
} else {
width = min(max(input.sidebarNavigation.width, sidebarNavMinWidth), sidebarNavMaxWidth);
}
@ -289,9 +281,9 @@ class CustomLayout extends Component {
let sidebarNavHeight = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
sidebarNavHeight = this.mainHeight() - DEFAULT_VALUES.navBarHeight;
sidebarNavHeight = windowHeight() - DEFAULT_VALUES.navBarHeight;
} else {
sidebarNavHeight = this.mainHeight();
sidebarNavHeight = windowHeight();
}
sidebarNavHeight -= this.bannerAreaHeight();
}
@ -329,13 +321,13 @@ class CustomLayout extends Component {
let maxWidth = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarContent.width === 0) {
width = min(
max((this.mainWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
max((windowWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
);
} else {
width = min(max(input.sidebarContent.width, sidebarContentMinWidth),
@ -365,13 +357,13 @@ class CustomLayout extends Component {
let sidebarContentHeight = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
sidebarContentHeight = this.mainHeight() - DEFAULT_VALUES.navBarHeight;
sidebarContentHeight = windowHeight() - DEFAULT_VALUES.navBarHeight;
} else if (input.cameraDock.numCameras > 0
&& input.cameraDock.position === CAMERADOCK_POSITION.SIDEBAR_CONTENT_BOTTOM
&& isOpen) {
sidebarContentHeight = this.mainHeight() - cameraDockHeight;
sidebarContentHeight = windowHeight() - cameraDockHeight;
} else {
sidebarContentHeight = this.mainHeight();
sidebarContentHeight = windowHeight();
}
sidebarContentHeight -= this.bannerAreaHeight();
}
@ -388,10 +380,16 @@ class CustomLayout extends Component {
top = DEFAULT_VALUES.navBarHeight + this.bannerAreaHeight();
}
let left = deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth;
left = !isRTL ? left : null;
let right = deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth;
right = isRTL ? right : null;
return {
top,
left: !isRTL ? (deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth) : null,
right: isRTL ? (deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth) : null,
left,
right,
zIndex: deviceType === DEVICE_TYPE.MOBILE ? 11 : 1,
};
}
@ -405,15 +403,15 @@ class CustomLayout extends Component {
let width = 0;
if (deviceType === DEVICE_TYPE.MOBILE) {
left = 0;
width = this.mainWidth();
width = windowWidth();
} else {
left = !isRTL ? sidebarNavWidth + sidebarContentWidth : 0;
width = this.mainWidth() - sidebarNavWidth - sidebarContentWidth;
width = windowWidth() - sidebarNavWidth - sidebarContentWidth;
}
return {
width,
height: this.mainHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
height: windowHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
top: DEFAULT_VALUES.navBarHeight + this.bannerAreaHeight(),
left,
};
@ -421,7 +419,9 @@ class CustomLayout extends Component {
calculatesCameraDockBounds(sidebarNavWidth, sidebarContentWidth, mediaAreaBounds) {
const { layoutContextState } = this.props;
const { input, fullscreen, isRTL, deviceType } = layoutContextState;
const {
input, fullscreen, isRTL, deviceType,
} = layoutContextState;
const { presentation } = input;
const { isOpen } = presentation;
const { camerasMargin } = DEFAULT_VALUES;
@ -442,7 +442,7 @@ class CustomLayout extends Component {
let cameraDockHeight = 0;
let cameraDockWidth = 0;
switch (input.cameraDock.position) {
case CAMERADOCK_POSITION.CONTENT_TOP:
case CAMERADOCK_POSITION.CONTENT_TOP: {
cameraDockLeft = mediaAreaBounds.left;
if (input.cameraDock.height === 0 || deviceType === DEVICE_TYPE.MOBILE) {
@ -471,7 +471,8 @@ class CustomLayout extends Component {
cameraDockBounds.height = cameraDockHeight - camerasMargin;
cameraDockBounds.maxHeight = mediaAreaBounds.height * 0.8;
break;
case CAMERADOCK_POSITION.CONTENT_RIGHT:
}
case CAMERADOCK_POSITION.CONTENT_RIGHT: {
if (input.cameraDock.width === 0) {
if (input.presentation.isOpen) {
cameraDockWidth = min(
@ -497,12 +498,15 @@ class CustomLayout extends Component {
cameraDockBounds.minWidth = DEFAULT_VALUES.cameraDockMinWidth;
cameraDockBounds.width = cameraDockWidth - (camerasMargin * 2);
cameraDockBounds.maxWidth = mediaAreaBounds.width * 0.8;
cameraDockBounds.presenterMaxWidth = mediaAreaBounds.width - DEFAULT_VALUES.presentationToolbarMinWidth - camerasMargin;
cameraDockBounds.presenterMaxWidth = mediaAreaBounds.width
- DEFAULT_VALUES.presentationToolbarMinWidth
- camerasMargin;
cameraDockBounds.minHeight = DEFAULT_VALUES.cameraDockMinHeight;
cameraDockBounds.height = mediaAreaBounds.height;
cameraDockBounds.maxHeight = mediaAreaBounds.height;
break;
case CAMERADOCK_POSITION.CONTENT_BOTTOM:
}
case CAMERADOCK_POSITION.CONTENT_BOTTOM: {
cameraDockLeft = mediaAreaBounds.left;
if (input.cameraDock.height === 0) {
@ -532,7 +536,8 @@ class CustomLayout extends Component {
cameraDockBounds.height = cameraDockHeight - camerasMargin;
cameraDockBounds.maxHeight = mediaAreaBounds.height * 0.8;
break;
case CAMERADOCK_POSITION.CONTENT_LEFT:
}
case CAMERADOCK_POSITION.CONTENT_LEFT: {
if (input.cameraDock.width === 0) {
if (input.presentation.isOpen) {
cameraDockWidth = min(
@ -553,27 +558,30 @@ class CustomLayout extends Component {
cameraDockBounds.left = mediaAreaBounds.left + camerasMargin;
cameraDockBounds.right = isRTL ? sidebarSize + (camerasMargin * 2) : null;
cameraDockBounds.minWidth = DEFAULT_VALUES.cameraDockMinWidth;
cameraDockBounds.width = cameraDockWidth - (camerasMargin *2);
cameraDockBounds.width = cameraDockWidth - (camerasMargin * 2);
cameraDockBounds.maxWidth = mediaAreaBounds.width * 0.8;
cameraDockBounds.presenterMaxWidth = mediaAreaBounds.width - DEFAULT_VALUES.presentationToolbarMinWidth - camerasMargin;
cameraDockBounds.presenterMaxWidth = mediaAreaBounds.width
- DEFAULT_VALUES.presentationToolbarMinWidth
- camerasMargin;
cameraDockBounds.minHeight = mediaAreaBounds.height;
cameraDockBounds.height = mediaAreaBounds.height;
cameraDockBounds.maxHeight = mediaAreaBounds.height;
break;
case CAMERADOCK_POSITION.SIDEBAR_CONTENT_BOTTOM:
}
case CAMERADOCK_POSITION.SIDEBAR_CONTENT_BOTTOM: {
if (input.cameraDock.height === 0) {
cameraDockHeight = min(
max((this.mainHeight() * 0.2), DEFAULT_VALUES.cameraDockMinHeight),
(this.mainHeight() - DEFAULT_VALUES.cameraDockMinHeight),
max((windowHeight() * 0.2), DEFAULT_VALUES.cameraDockMinHeight),
(windowHeight() - DEFAULT_VALUES.cameraDockMinHeight),
);
} else {
cameraDockHeight = min(
max(input.cameraDock.height, DEFAULT_VALUES.cameraDockMinHeight),
(this.mainHeight() - DEFAULT_VALUES.cameraDockMinHeight),
(windowHeight() - DEFAULT_VALUES.cameraDockMinHeight),
);
}
cameraDockBounds.top = this.mainHeight() - cameraDockHeight;
cameraDockBounds.top = windowHeight() - cameraDockHeight;
cameraDockBounds.left = !isRTL ? sidebarNavWidth : 0;
cameraDockBounds.right = isRTL ? sidebarNavWidth : 0;
cameraDockBounds.minWidth = sidebarContentWidth;
@ -581,10 +589,12 @@ class CustomLayout extends Component {
cameraDockBounds.maxWidth = sidebarContentWidth;
cameraDockBounds.minHeight = DEFAULT_VALUES.cameraDockMinHeight;
cameraDockBounds.height = cameraDockHeight;
cameraDockBounds.maxHeight = this.mainHeight() * 0.8;
cameraDockBounds.maxHeight = windowHeight() * 0.8;
break;
default:
}
default: {
console.log('default');
}
}
if (fullscreen.group === 'webcams') {
@ -618,9 +628,9 @@ class CustomLayout extends Component {
const { presentation } = input;
const { isOpen } = presentation;
const { height: actionBarHeight } = this.calculatesActionbarHeight();
const mediaAreaHeight = this.mainHeight()
const mediaAreaHeight = windowHeight()
- (DEFAULT_VALUES.navBarHeight + actionBarHeight);
const mediaAreaWidth = this.mainWidth() - (sidebarNavWidth + sidebarContentWidth);
const mediaAreaWidth = windowWidth() - (sidebarNavWidth + sidebarContentWidth);
const mediaBounds = {};
const { element: fullscreenElement } = fullscreen;
const { navBarHeight, camerasMargin } = DEFAULT_VALUES;
@ -636,8 +646,8 @@ class CustomLayout extends Component {
}
if (fullscreenElement === 'Presentation' || fullscreenElement === 'Screenshare') {
mediaBounds.width = this.mainWidth();
mediaBounds.height = this.mainHeight();
mediaBounds.width = windowWidth();
mediaBounds.height = windowHeight();
mediaBounds.top = 0;
mediaBounds.left = !isRTL ? 0 : null;
mediaBounds.right = isRTL ? 0 : null;
@ -649,29 +659,32 @@ class CustomLayout extends Component {
if (input.cameraDock.numCameras > 0 && !input.cameraDock.isDragging) {
switch (input.cameraDock.position) {
case CAMERADOCK_POSITION.CONTENT_TOP:
case CAMERADOCK_POSITION.CONTENT_TOP: {
mediaBounds.width = mediaAreaWidth;
mediaBounds.height = mediaAreaHeight - cameraDockBounds.height - camerasMargin;
mediaBounds.top = navBarHeight + cameraDockBounds.height + camerasMargin;
mediaBounds.left = !isRTL ? sidebarSize : null;
mediaBounds.right = isRTL ? sidebarSize : null;
break;
case CAMERADOCK_POSITION.CONTENT_RIGHT:
mediaBounds.width = mediaAreaWidth - cameraDockBounds.width - (camerasMargin * 2);
}
case CAMERADOCK_POSITION.CONTENT_RIGHT: {
mediaBounds.width = mediaAreaWidth - cameraDockBounds.width - camerasMargin;
mediaBounds.height = mediaAreaHeight;
mediaBounds.top = navBarHeight;
mediaBounds.left = !isRTL ? sidebarSize : null;
mediaBounds.right = isRTL ? sidebarSize - (camerasMargin *2) : null;
mediaBounds.right = isRTL ? sidebarSize - (camerasMargin * 2) : null;
break;
case CAMERADOCK_POSITION.CONTENT_BOTTOM:
}
case CAMERADOCK_POSITION.CONTENT_BOTTOM: {
mediaBounds.width = mediaAreaWidth;
mediaBounds.height = mediaAreaHeight - cameraDockBounds.height - camerasMargin;
mediaBounds.top = navBarHeight - camerasMargin;
mediaBounds.left = !isRTL ? sidebarSize : null;
mediaBounds.right = isRTL ? sidebarSize : null;
break;
case CAMERADOCK_POSITION.CONTENT_LEFT:
mediaBounds.width = mediaAreaWidth - cameraDockBounds.width - (camerasMargin * 2);
}
case CAMERADOCK_POSITION.CONTENT_LEFT: {
mediaBounds.width = mediaAreaWidth - cameraDockBounds.width - camerasMargin;
mediaBounds.height = mediaAreaHeight;
mediaBounds.top = navBarHeight;
const sizeValue = sidebarNavWidth
@ -679,15 +692,18 @@ class CustomLayout extends Component {
mediaBounds.left = !isRTL ? sizeValue : null;
mediaBounds.right = isRTL ? sidebarSize : null;
break;
case CAMERADOCK_POSITION.SIDEBAR_CONTENT_BOTTOM:
}
case CAMERADOCK_POSITION.SIDEBAR_CONTENT_BOTTOM: {
mediaBounds.width = mediaAreaWidth;
mediaBounds.height = mediaAreaHeight;
mediaBounds.top = navBarHeight;
mediaBounds.left = !isRTL ? sidebarSize : null;
mediaBounds.right = isRTL ? sidebarSize : null;
break;
default:
}
default: {
console.log('presentation - camera default');
}
}
mediaBounds.zIndex = 1;
} else {
@ -827,8 +843,8 @@ class CustomLayout extends Component {
layoutContextDispatch({
type: ACTIONS.SET_MEDIA_AREA_SIZE,
value: {
width: this.mainWidth() - sidebarNavWidth.width - sidebarContentWidth.width,
height: this.mainHeight() - DEFAULT_VALUES.navBarHeight - actionBarHeight,
width: windowWidth() - sidebarNavWidth.width - sidebarContentWidth.width,
height: windowHeight() - DEFAULT_VALUES.navBarHeight - actionBarHeight,
},
});

View File

@ -51,14 +51,6 @@ class PresentationFocusLayout extends Component {
}
}
mainWidth() {
return window.document.documentElement.clientWidth;
}
mainHeight() {
return window.document.documentElement.clientHeight;
}
bannerAreaHeight() {
const { layoutContextState } = this.props;
const { input } = layoutContextState;
@ -176,7 +168,7 @@ class PresentationFocusLayout extends Component {
height: actionBarHeight.height,
innerHeight: actionBarHeight.innerHeight,
padding: actionBarHeight.padding,
top: this.mainHeight() - actionBarHeight.height,
top: windowHeight() - actionBarHeight.height,
left: !isRTL ? mediaAreaBounds.left : 0,
zIndex: 1,
};
@ -194,12 +186,12 @@ class PresentationFocusLayout extends Component {
let maxWidth = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarNavigation.width === 0) {
width = min(max((this.mainWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
width = min(max((windowWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
} else {
width = min(max(input.sidebarNavigation.width, sidebarNavMinWidth), sidebarNavMaxWidth);
}
@ -221,9 +213,9 @@ class PresentationFocusLayout extends Component {
let sidebarNavHeight = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
sidebarNavHeight = this.mainHeight() - navBarHeight - this.bannerAreaHeight();
sidebarNavHeight = windowHeight() - navBarHeight - this.bannerAreaHeight();
} else {
sidebarNavHeight = this.mainHeight() - this.bannerAreaHeight();
sidebarNavHeight = windowHeight() - this.bannerAreaHeight();
}
}
return sidebarNavHeight;
@ -258,13 +250,13 @@ class PresentationFocusLayout extends Component {
let maxWidth = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarContent.width === 0) {
width = min(
max((this.mainWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
max((windowWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
);
} else {
width = min(max(input.sidebarContent.width, sidebarContentMinWidth),
@ -293,20 +285,20 @@ class PresentationFocusLayout extends Component {
let maxHeight = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
height = this.mainHeight() - navBarHeight - this.bannerAreaHeight();
height = windowHeight() - navBarHeight - this.bannerAreaHeight();
minHeight = height;
maxHeight = height;
} else if (input.cameraDock.numCameras > 0) {
if (input.sidebarContent.height === 0) {
height = (this.mainHeight() * 0.75) - this.bannerAreaHeight();
height = (windowHeight() * 0.75) - this.bannerAreaHeight();
} else {
height = min(max(input.sidebarContent.height, sidebarContentMinHeight),
this.mainHeight());
windowHeight());
}
minHeight = this.mainHeight() * 0.25 - this.bannerAreaHeight();
maxHeight = this.mainHeight() * 0.75 - this.bannerAreaHeight();
minHeight = windowHeight() * 0.25 - this.bannerAreaHeight();
maxHeight = windowHeight() * 0.75 - this.bannerAreaHeight();
} else {
height = this.mainHeight() - this.bannerAreaHeight();
height = windowHeight() - this.bannerAreaHeight();
minHeight = height;
maxHeight = height;
}
@ -351,15 +343,15 @@ class PresentationFocusLayout extends Component {
let width = 0;
if (deviceType === DEVICE_TYPE.MOBILE) {
left = 0;
width = this.mainWidth();
width = windowWidth();
} else {
left = !isRTL ? sidebarNavWidth + sidebarContentWidth : 0;
width = this.mainWidth() - sidebarNavWidth - sidebarContentWidth;
width = windowWidth() - sidebarNavWidth - sidebarContentWidth;
}
return {
width,
height: this.mainHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
height: windowHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
top: navBarHeight + this.bannerAreaHeight(),
left,
};
@ -408,16 +400,16 @@ class PresentationFocusLayout extends Component {
} else {
if (input.cameraDock.height === 0) {
cameraDockHeight = min(
max((this.mainHeight() - sidebarContentHeight), DEFAULT_VALUES.cameraDockMinHeight),
(this.mainHeight() - DEFAULT_VALUES.cameraDockMinHeight),
max((windowHeight() - sidebarContentHeight), DEFAULT_VALUES.cameraDockMinHeight),
(windowHeight() - DEFAULT_VALUES.cameraDockMinHeight),
);
} else {
cameraDockHeight = min(
max(input.cameraDock.height, DEFAULT_VALUES.cameraDockMinHeight),
(this.mainHeight() - DEFAULT_VALUES.cameraDockMinHeight),
(windowHeight() - DEFAULT_VALUES.cameraDockMinHeight),
);
}
cameraDockBounds.top = this.mainHeight() - cameraDockHeight;
cameraDockBounds.top = windowHeight() - cameraDockHeight;
cameraDockBounds.left = !isRTL ? sidebarNavWidth : 0;
cameraDockBounds.right = isRTL ? sidebarNavWidth : 0;
cameraDockBounds.minWidth = sidebarContentWidth;
@ -425,7 +417,7 @@ class PresentationFocusLayout extends Component {
cameraDockBounds.maxWidth = sidebarContentWidth;
cameraDockBounds.minHeight = DEFAULT_VALUES.cameraDockMinHeight;
cameraDockBounds.height = cameraDockHeight;
cameraDockBounds.maxHeight = this.mainHeight() - sidebarContentHeight;
cameraDockBounds.maxHeight = windowHeight() - sidebarContentHeight;
cameraDockBounds.zIndex = 1;
}
} else {
@ -444,8 +436,8 @@ class PresentationFocusLayout extends Component {
const { element: fullscreenElement } = fullscreen;
if (fullscreenElement === 'Presentation' || fullscreenElement === 'Screenshare') {
mediaBounds.width = this.mainWidth();
mediaBounds.height = this.mainHeight();
mediaBounds.width = windowWidth();
mediaBounds.height = windowHeight();
mediaBounds.top = 0;
mediaBounds.left = !isRTL ? 0 : null;
mediaBounds.right = isRTL ? 0 : null;

View File

@ -51,14 +51,6 @@ class SmartLayout extends Component {
}
}
mainWidth() {
return window.document.documentElement.clientWidth;
}
mainHeight() {
return window.document.documentElement.clientHeight;
}
bannerAreaHeight() {
const { layoutContextState } = this.props;
const { input } = layoutContextState;
@ -176,7 +168,7 @@ class SmartLayout extends Component {
height: actionBarHeight.height,
innerHeight: actionBarHeight.innerHeight,
padding: actionBarHeight.padding,
top: this.mainHeight() - actionBarHeight.height,
top: windowHeight() - actionBarHeight.height,
left: !isRTL ? mediaAreaBounds.left : 0,
zIndex: 1,
};
@ -194,12 +186,12 @@ class SmartLayout extends Component {
let maxWidth = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarNavigation.width === 0) {
width = min(max((this.mainWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
width = min(max((windowWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
} else {
width = min(max(input.sidebarNavigation.width, sidebarNavMinWidth), sidebarNavMaxWidth);
}
@ -220,9 +212,9 @@ class SmartLayout extends Component {
let sidebarNavHeight = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
sidebarNavHeight = this.mainHeight() - DEFAULT_VALUES.navBarHeight;
sidebarNavHeight = windowHeight() - DEFAULT_VALUES.navBarHeight;
} else {
sidebarNavHeight = this.mainHeight();
sidebarNavHeight = windowHeight();
}
sidebarNavHeight -= this.bannerAreaHeight();
}
@ -258,13 +250,13 @@ class SmartLayout extends Component {
let maxWidth = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarContent.width === 0) {
width = min(
max((this.mainWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
max((windowWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
);
} else {
width = min(max(input.sidebarContent.width, sidebarContentMinWidth),
@ -287,9 +279,9 @@ class SmartLayout extends Component {
let sidebarContentHeight = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
sidebarContentHeight = this.mainHeight() - DEFAULT_VALUES.navBarHeight;
sidebarContentHeight = windowHeight() - DEFAULT_VALUES.navBarHeight;
} else {
sidebarContentHeight = this.mainHeight();
sidebarContentHeight = windowHeight();
}
sidebarContentHeight -= this.bannerAreaHeight();
}
@ -305,10 +297,16 @@ class SmartLayout extends Component {
if (deviceType === DEVICE_TYPE.MOBILE) top = navBarHeight + this.bannerAreaHeight();
let left = deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth;
left = !isRTL ? left : null;
let right = deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth;
right = isRTL ? right : null;
return {
top,
left: !isRTL ? (deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth) : null,
right: isRTL ? (deviceType === DEVICE_TYPE.MOBILE ? 0 : sidebarNavWidth) : null,
left,
right,
zIndex: deviceType === DEVICE_TYPE.MOBILE ? 11 : 1,
};
}
@ -322,15 +320,15 @@ class SmartLayout extends Component {
let width = 0;
if (deviceType === DEVICE_TYPE.MOBILE) {
left = 0;
width = this.mainWidth();
width = windowWidth();
} else {
left = !isRTL ? sidebarNavWidth + sidebarContentWidth : 0;
width = this.mainWidth() - sidebarNavWidth - sidebarContentWidth;
width = windowWidth() - sidebarNavWidth - sidebarContentWidth;
}
return {
width,
height: this.mainHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
height: windowHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
top: navBarHeight + this.bannerAreaHeight(),
left,
};
@ -453,8 +451,8 @@ class SmartLayout extends Component {
}
if (fullscreenElement === 'Presentation' || fullscreenElement === 'Screenshare') {
mediaBounds.width = this.mainWidth();
mediaBounds.height = this.mainHeight();
mediaBounds.width = windowWidth();
mediaBounds.height = windowHeight();
mediaBounds.top = 0;
mediaBounds.left = !isRTL ? 0 : null;
mediaBounds.right = isRTL ? 0 : null;
@ -531,7 +529,8 @@ class SmartLayout extends Component {
const slideSize = this.calculatesSlideSize(mediaAreaBounds);
const sidebarSize = sidebarContentWidth.width + sidebarNavWidth.width;
const mediaBounds = this.calculatesMediaBounds(mediaAreaBounds, slideSize, sidebarSize);
const cameraDockBounds = this.calculatesCameraDockBounds(mediaAreaBounds, mediaBounds, sidebarSize);
const cameraDockBounds = this
.calculatesCameraDockBounds(mediaAreaBounds, mediaBounds, sidebarSize);
const horizontalCameraDiff = cameraDockBounds.isCameraHorizontal
? cameraDockBounds.width + (camerasMargin * 2)
: 0;

View File

@ -51,14 +51,6 @@ class VideoFocusLayout extends Component {
}
}
mainWidth() {
return window.document.documentElement.clientWidth;
}
mainHeight() {
return window.document.documentElement.clientHeight;
}
bannerAreaHeight() {
const { layoutContextState } = this.props;
const { input } = layoutContextState;
@ -183,7 +175,7 @@ class VideoFocusLayout extends Component {
height: actionBarHeight.height,
innerHeight: actionBarHeight.innerHeight,
padding: actionBarHeight.padding,
top: this.mainHeight() - actionBarHeight.height,
top: windowHeight() - actionBarHeight.height,
left: !isRTL ? mediaAreaBounds.left : 0,
zIndex: 1,
};
@ -201,12 +193,12 @@ class VideoFocusLayout extends Component {
let maxWidth = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarNavigation.width === 0) {
width = min(max((this.mainWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
width = min(max((windowWidth() * 0.2), sidebarNavMinWidth), sidebarNavMaxWidth);
} else {
width = min(max(input.sidebarNavigation.width, sidebarNavMinWidth), sidebarNavMaxWidth);
}
@ -227,9 +219,9 @@ class VideoFocusLayout extends Component {
let sidebarNavHeight = 0;
if (input.sidebarNavigation.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
sidebarNavHeight = this.mainHeight() - DEFAULT_VALUES.navBarHeight;
sidebarNavHeight = windowHeight() - DEFAULT_VALUES.navBarHeight;
} else {
sidebarNavHeight = this.mainHeight();
sidebarNavHeight = windowHeight();
}
sidebarNavHeight -= this.bannerAreaHeight();
}
@ -265,13 +257,13 @@ class VideoFocusLayout extends Component {
let maxWidth = 0;
if (input.sidebarContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
minWidth = this.mainWidth();
width = this.mainWidth();
maxWidth = this.mainWidth();
minWidth = windowWidth();
width = windowWidth();
maxWidth = windowWidth();
} else {
if (input.sidebarContent.width === 0) {
width = min(
max((this.mainWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
max((windowWidth() * 0.2), sidebarContentMinWidth), sidebarContentMaxWidth,
);
} else {
width = min(max(input.sidebarContent.width, sidebarContentMinWidth),
@ -298,29 +290,25 @@ class VideoFocusLayout extends Component {
let maxHeight = 0;
if (inputContent.isOpen) {
if (deviceType === DEVICE_TYPE.MOBILE) {
height = this.mainHeight() - DEFAULT_VALUES.navBarHeight - this.bannerAreaHeight();
height = windowHeight() - DEFAULT_VALUES.navBarHeight - this.bannerAreaHeight();
minHeight = height;
maxHeight = height;
} else if (input.cameraDock.numCameras > 0 && presentation.isOpen) {
if (inputContent.height > 0 && inputContent.height < this.mainHeight()) {
if (inputContent.height > 0 && inputContent.height < windowHeight()) {
height = inputContent.height - this.bannerAreaHeight();
} else {
const { size: slideSize } = input.presentation.currentSlide;
let calculatedHeight = (this.mainHeight() - this.bannerAreaHeight()) * 0.3;
let calculatedHeight = (windowHeight() - this.bannerAreaHeight()) * 0.3;
if (slideSize.height > 0 && slideSize.width > 0) {
calculatedHeight = (slideSize.height * outputContent.width) / slideSize.width;
}
height = this.mainHeight() - calculatedHeight - this.bannerAreaHeight();
}
maxHeight = this.mainHeight() * 0.75 - this.bannerAreaHeight();
minHeight = this.mainHeight() * 0.25 - this.bannerAreaHeight();
if (height > maxHeight) {
height = maxHeight;
height = windowHeight() - calculatedHeight - this.bannerAreaHeight();
}
maxHeight = windowHeight() * 0.75 - this.bannerAreaHeight();
minHeight = windowHeight() * 0.25 - this.bannerAreaHeight();
} else {
height = this.mainHeight() - this.bannerAreaHeight();
height = windowHeight() - this.bannerAreaHeight();
maxHeight = height;
minHeight = height;
}
@ -363,15 +351,15 @@ class VideoFocusLayout extends Component {
let width = 0;
if (deviceType === DEVICE_TYPE.MOBILE) {
left = 0;
width = this.mainWidth();
width = windowWidth();
} else {
left = !isRTL ? sidebarNavWidth + sidebarContentWidth : 0;
width = this.mainWidth() - sidebarNavWidth - sidebarContentWidth;
width = windowWidth() - sidebarNavWidth - sidebarContentWidth;
}
return {
width,
height: this.mainHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
height: windowHeight() - (navBarHeight + actionBarHeight + this.bannerAreaHeight()),
top: navBarHeight + this.bannerAreaHeight(),
left,
};
@ -447,8 +435,8 @@ class VideoFocusLayout extends Component {
const sidebarSize = sidebarNavWidth + sidebarContentWidth;
if (fullscreenElement === 'Presentation' || fullscreenElement === 'Screenshare') {
mediaBounds.width = this.mainWidth();
mediaBounds.height = this.mainHeight();
mediaBounds.width = windowWidth();
mediaBounds.height = windowHeight();
mediaBounds.top = 0;
mediaBounds.left = 0;
mediaBounds.right = 0;
@ -462,7 +450,7 @@ class VideoFocusLayout extends Component {
mediaBounds.top = mediaAreaBounds.top + cameraDockBounds.height;
mediaBounds.width = mediaAreaBounds.width;
} else if (input.cameraDock.numCameras > 0) {
mediaBounds.height = this.mainHeight() - sidebarContentHeight;
mediaBounds.height = windowHeight() - sidebarContentHeight;
mediaBounds.left = !isRTL ? sidebarNavWidth : 0;
mediaBounds.right = isRTL ? sidebarNavWidth : 0;
mediaBounds.top = sidebarContentHeight;

View File

@ -85,7 +85,7 @@ const NotificationsBarContainer = (props) => {
useEffect(() => {
const localHasNotification = !!message;
if(localHasNotification !== hasNotification){
if (localHasNotification !== hasNotification) {
layoutContextDispatch({
type: ACTIONS.SET_HAS_NOTIFICATIONS_BAR,
value: localHasNotification,
@ -97,7 +97,6 @@ const NotificationsBarContainer = (props) => {
return null;
}
return (
<NotificationsBar color={color}>
{message}
@ -153,12 +152,12 @@ export default injectIntl(withTracker(({ intl }) => {
const sec = Math.round((retryTime - (new Date()).getTime()) / 1000);
retryInterval = startCounter(sec, setRetrySeconds, getRetrySeconds, retryInterval);
data.message = (
<Fragment>
<>
{intl.formatMessage(intlMessages.waitingMessage, { 0: getRetrySeconds() })}
<button className={styles.retryButton} type="button" onClick={reconnect}>
{intl.formatMessage(intlMessages.retryNow)}
</button>
</Fragment>
</>
);
break;
}
@ -172,10 +171,10 @@ export default injectIntl(withTracker(({ intl }) => {
const meetingId = Auth.meetingID;
const breakouts = breakoutService.getBreakouts();
const msg = { id: `${intlMessages.alertBreakoutEndsUnderMinutes.id}${REMAINING_TIME_ALERT_THRESHOLD == 1 ? 'Singular' : 'Plural'}` };
let msg = { id: `${intlMessages.alertBreakoutEndsUnderMinutes.id}${REMAINING_TIME_ALERT_THRESHOLD === 1 ? 'Singular' : 'Plural'}` };
if (breakouts.length > 0) {
const currentBreakout = breakouts.find(b => b.breakoutId === meetingId);
const currentBreakout = breakouts.find((b) => b.breakoutId === meetingId);
if (currentBreakout) {
data.message = (
@ -184,7 +183,7 @@ export default injectIntl(withTracker(({ intl }) => {
messageDuration={intlMessages.breakoutTimeRemaining}
timeEndedMessage={intlMessages.breakoutWillClose}
alertMessage={
intl.formatMessage(msg, {0: REMAINING_TIME_ALERT_THRESHOLD})
intl.formatMessage(msg, { 0: REMAINING_TIME_ALERT_THRESHOLD })
}
alertUnderMinutes={REMAINING_TIME_ALERT_THRESHOLD}
/>
@ -201,7 +200,7 @@ export default injectIntl(withTracker(({ intl }) => {
const { isBreakout } = Meeting.meetingProp;
const underThirtyMin = timeRemaining && timeRemaining <= (REMAINING_TIME_THRESHOLD * 60);
const msg = { id: `${intlMessages.alertMeetingEndsUnderMinutes.id}${REMAINING_TIME_ALERT_THRESHOLD == 1 ? 'Singular' : 'Plural'}` };
msg = { id: `${intlMessages.alertMeetingEndsUnderMinutes.id}${REMAINING_TIME_ALERT_THRESHOLD === 1 ? 'Singular' : 'Plural'}` };
if (underThirtyMin && !isBreakout) {
data.message = (
@ -210,7 +209,7 @@ export default injectIntl(withTracker(({ intl }) => {
messageDuration={intlMessages.meetingTimeRemaining}
timeEndedMessage={intlMessages.meetingWillClose}
alertMessage={
intl.formatMessage(msg, {0: REMAINING_TIME_ALERT_THRESHOLD})
intl.formatMessage(msg, { 0: REMAINING_TIME_ALERT_THRESHOLD })
}
alertUnderMinutes={REMAINING_TIME_ALERT_THRESHOLD}
/>

View File

@ -452,7 +452,11 @@ class Poll extends Component {
],
});
}}
className={cx(styles.pBtn, styles.btnMR, { [styles.selectedBtnBlue]: type === pollTypes.TrueFalse })}
className={
cx(styles.pBtn, styles.btnMR, {
[styles.selectedBtnBlue]: type === pollTypes.TrueFalse,
})
}
/>
<Button
label={intl.formatMessage(intlMessages.a4)}
@ -468,7 +472,11 @@ class Poll extends Component {
],
});
}}
className={cx(styles.pBtn, styles.btnML, { [styles.selectedBtnBlue]: type === pollTypes.Letter })}
className={
cx(styles.pBtn, styles.btnML, {
[styles.selectedBtnBlue]: type === pollTypes.Letter,
})
}
/>
</div>
<Button
@ -484,16 +492,24 @@ class Poll extends Component {
],
});
}}
className={cx(styles.pBtn, styles.yna, { [styles.selectedBtnBlue]: type === pollTypes.YesNoAbstention })}
className={
cx(styles.pBtn, styles.yna, {
[styles.selectedBtnBlue]: type === pollTypes.YesNoAbstention,
})
}
/>
<Button
label={intl.formatMessage(intlMessages.userResponse)}
color="default"
onClick={() => { this.setState({ type: pollTypes.Response }); }}
className={cx(styles.pBtn, styles.fullWidth, { [styles.selectedBtnWhite]: type === pollTypes.Response })}
className={
cx(styles.pBtn, styles.fullWidth, {
[styles.selectedBtnWhite]: type === pollTypes.Response,
})
}
/>
</div>
{ type
{type
&& (
<div data-test="responseChoices">
<h4>{intl.formatMessage(intlMessages.responseChoices)}</h4>
@ -534,11 +550,13 @@ class Poll extends Component {
)}
<div className={styles.row}>
<div className={styles.col} aria-hidden="true">
<label className={styles.label}>
{intl.formatMessage(intlMessages.secretPollLabel)}
</label>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={styles.label}>
{intl.formatMessage(intlMessages.secretPollLabel)}
</label>
</div>
<div className={styles.col}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={styles.toggle}>
<Toggle
icons={false}
@ -550,7 +568,11 @@ class Poll extends Component {
</div>
</div>
<div>
{intl.formatMessage(secretPoll ? intlMessages.isSecretPollLabel : intlMessages.nonSecretPollLabel)}
{
intl.formatMessage(secretPoll
? intlMessages.isSecretPollLabel
: intlMessages.nonSecretPollLabel)
}
</div>
<Button
className={styles.startPollBtn}
@ -564,8 +586,12 @@ class Poll extends Component {
});
let err = null;
if (type === pollTypes.Response && question.length === 0) err = intl.formatMessage(intlMessages.questionErr);
if (!hasVal && type !== pollTypes.Response) err = intl.formatMessage(intlMessages.optionErr);
if (type === pollTypes.Response && question.length === 0) {
err = intl.formatMessage(intlMessages.questionErr);
}
if (!hasVal && type !== pollTypes.Response) {
err = intl.formatMessage(intlMessages.optionErr);
}
if (err) return this.setState({ error: err });
return this.setState({ isPolling: true }, () => {
@ -576,7 +602,7 @@ class Poll extends Component {
intl.formatMessage(intlMessages.no),
intl.formatMessage(intlMessages.abstention),
intl.formatMessage(intlMessages.true),
intl.formatMessage(intlMessages.false)
intl.formatMessage(intlMessages.false),
);
const verifiedOptions = optList.map((o) => {
if (o.val.length > 0) return o.val;
@ -596,7 +622,9 @@ class Poll extends Component {
}}
/>
{
FILE_DRAG_AND_DROP_ENABLED && type !== pollTypes.Response && this.renderDragDrop()
FILE_DRAG_AND_DROP_ENABLED
&& type !== pollTypes.Response
&& this.renderDragDrop()
}
</div>
)

View File

@ -57,6 +57,14 @@ const intlMessages = defineMessages({
const ALLOW_FULLSCREEN = Meteor.settings.public.app.allowFullscreen;
class ScreenshareComponent extends React.Component {
static renderScreenshareContainerInside(mainText) {
return (
<div className={styles.screenshareContainerInside}>
<h1 className={styles.mainText}>{mainText}</h1>
</div>
);
}
constructor() {
super();
this.state = {
@ -118,33 +126,6 @@ class ScreenshareComponent extends React.Component {
notify(intl.formatMessage(intlMessages.screenshareEnded), 'info', 'desktop');
}
onStreamStateChange(event) {
const { streamState } = event.detail;
const { isStreamHealthy } = this.state;
const newHealthState = !isStreamStateUnhealthy(streamState);
event.stopPropagation();
if (newHealthState !== isStreamHealthy) {
this.setState({ isStreamHealthy: newHealthState });
}
}
onLoadedData() {
this.setState({ loaded: true });
}
onSwitched() {
this.setState(prevState => ({ switched: !prevState.switched }));
}
onFullscreenChange() {
const { isFullscreen } = this.state;
const newIsFullscreen = FullscreenService.isFullScreen(this.screenshareContainer);
if (isFullscreen !== newIsFullscreen) {
this.setState({ isFullscreen: newIsFullscreen });
}
}
handleAllowAutoplay() {
const { autoplayBlocked } = this.state;
@ -186,6 +167,33 @@ class ScreenshareComponent extends React.Component {
}
}
onStreamStateChange(event) {
const { streamState } = event.detail;
const { isStreamHealthy } = this.state;
const newHealthState = !isStreamStateUnhealthy(streamState);
event.stopPropagation();
if (newHealthState !== isStreamHealthy) {
this.setState({ isStreamHealthy: newHealthState });
}
}
onLoadedData() {
this.setState({ loaded: true });
}
onSwitched() {
this.setState((prevState) => ({ switched: !prevState.switched }));
}
onFullscreenChange() {
const { isFullscreen } = this.state;
const newIsFullscreen = FullscreenService.isFullScreen(this.screenshareContainer);
if (isFullscreen !== newIsFullscreen) {
this.setState({ isFullscreen: newIsFullscreen });
}
}
renderFullscreenButton() {
const { intl, fullscreenElementId } = this.props;
const { isFullscreen } = this.state;
@ -250,15 +258,6 @@ class ScreenshareComponent extends React.Component {
);
}
renderScreenshareContainerInside(mainText) {
return (
<div className={styles.screenshareContainerInside}>
<h1 className={styles.mainText}>{mainText}</h1>
</div>
);
}
renderScreensharePresenter() {
const { switched } = this.state;
const { isGloballyBroadcasting, intl } = this.props;
@ -272,14 +271,19 @@ class ScreenshareComponent extends React.Component {
{isGloballyBroadcasting && this.renderSwitchButton()}
{this.renderVideo(switched)}
{isGloballyBroadcasting
? (
<div>
{!switched
&& this.renderScreenshareContainerInside(intl.formatMessage(intlMessages.presenterSharingLabel))}
</div>
)
: this.renderScreenshareContainerInside(intl.formatMessage(intlMessages.presenterLoadingLabel))
{
isGloballyBroadcasting
? (
<div>
{!switched
&& ScreenshareComponent.renderScreenshareContainerInside(
intl.formatMessage(intlMessages.presenterSharingLabel),
)}
</div>
)
: ScreenshareComponent.renderScreenshareContainerInside(
intl.formatMessage(intlMessages.presenterLoadingLabel),
)
}
</div>
);
@ -305,11 +309,12 @@ class ScreenshareComponent extends React.Component {
{this.renderVideo(true)}
<div className={styles.screenshareContainerDefault}>
{!loaded
? this.renderScreenshareContainerInside(
intl.formatMessage(intlMessages.viewerLoadingLabel),
)
: null
{
!loaded
? ScreenshareComponent.renderScreenshareContainerInside(
intl.formatMessage(intlMessages.viewerLoadingLabel),
)
: null
}
</div>
</div>
@ -337,7 +342,7 @@ class ScreenshareComponent extends React.Component {
// state transitioned to an unhealthy stream. tl;dr: screen sharing reconnection
const shouldRenderConnectingState = !loaded
|| (isPresenter && !isGloballyBroadcasting)
|| !isStreamHealthy && loaded && isGloballyBroadcasting;
|| (!isStreamHealthy && loaded && isGloballyBroadcasting);
return (
<div
@ -378,6 +383,8 @@ class ScreenshareComponent extends React.Component {
export default injectIntl(ScreenshareComponent);
ScreenshareComponent.propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
isPresenter: PropTypes.bool.isRequired,
};

View File

@ -11,11 +11,11 @@ import {
getAvailableLocales,
} from './service';
const SettingsContainer = props => {
const SettingsContainer = (props) => {
const layoutContext = useContext(LayoutContext);
const { layoutContextDispatch } = layoutContext;
return <Settings {...props} layoutContextDispatch={layoutContextDispatch} />
return <Settings {...props} layoutContextDispatch={layoutContextDispatch} />;
};
export default withTracker(() => ({

View File

@ -130,9 +130,7 @@ class ApplicationMenu extends BaseMenu {
componentWillUnmount() {
// fix Warning: Can't perform a React state update on an unmounted component
this.setState = (state, callback) => {
};
this.setState = () => {};
}
setInitialFontSize() {
@ -175,7 +173,7 @@ class ApplicationMenu extends BaseMenu {
: _constraints || {};
isAnyFilterEnabled = Object.values(constraints).find(
constraintValue => _isConstraintEnabled(constraintValue),
(constraintValue) => _isConstraintEnabled(constraintValue),
);
return isAnyFilterEnabled;
@ -212,7 +210,7 @@ class ApplicationMenu extends BaseMenu {
layoutContextDispatch({
type: ACTIONS.SET_FONT_SIZE,
value: parseInt(size.slice(0, -2)),
value: parseInt(size.slice(0, -2), 10),
});
}
@ -282,7 +280,7 @@ class ApplicationMenu extends BaseMenu {
renderPaginationToggle() {
// See VideoService's method for an explanation
if (!VideoService.shouldRenderPaginationToggle()) return;
if (!VideoService.shouldRenderPaginationToggle()) return false;
const { intl, showToggleLabel, displaySettingsStatus } = this.props;
const { settings } = this.state;
@ -291,6 +289,7 @@ class ApplicationMenu extends BaseMenu {
<div className={styles.row}>
<div className={styles.col} aria-hidden="true">
<div className={styles.formElement}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={styles.label}>
{intl.formatMessage(intlMessages.paginationEnabledLabel)}
</label>
@ -313,7 +312,9 @@ class ApplicationMenu extends BaseMenu {
}
renderChangeLayout() {
const { intl, showToggleLabel, displaySettingsStatus, isModerator } = this.props;
const {
intl, showToggleLabel, displaySettingsStatus, isModerator,
} = this.props;
const { settings } = this.state;
return (
@ -330,7 +331,7 @@ class ApplicationMenu extends BaseMenu {
<div className={cx(styles.formElement, styles.pullContentRight)}>
<select
className={styles.select}
onChange={e => this.handleSelectChange('selectedLayout', e)}
onChange={(e) => this.handleSelectChange('selectedLayout', e)}
id="layoutList"
value={settings.selectedLayout}
>
@ -347,6 +348,7 @@ class ApplicationMenu extends BaseMenu {
<div className={styles.row}>
<div className={styles.col} aria-hidden="true">
<div className={styles.formElement}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={styles.label}>
{intl.formatMessage(intlMessages.pushLayoutOptionLabel)}
</label>
@ -405,6 +407,7 @@ class ApplicationMenu extends BaseMenu {
<div className={styles.row}>
<div className={styles.col} aria-hidden="true">
<div className={styles.formElement}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={styles.label}>
{intl.formatMessage(intlMessages.animationsLabel)}
</label>
@ -444,7 +447,7 @@ class ApplicationMenu extends BaseMenu {
{showSelect ? (
<LocalesDropdown
allLocales={allLocales}
handleChange={e => this.handleSelectChange('locale', e)}
handleChange={(e) => this.handleSelectChange('locale', e)}
value={settings.locale}
elementId="langSelector"
elementClass={styles.select}
@ -465,6 +468,7 @@ class ApplicationMenu extends BaseMenu {
<div className={styles.row}>
<div className={styles.col}>
<div className={styles.formElement}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={styles.label}>
{intl.formatMessage(intlMessages.fontSizeControlLabel)}
</label>
@ -472,6 +476,7 @@ class ApplicationMenu extends BaseMenu {
</div>
<div className={styles.col}>
<div aria-hidden className={cx(styles.formElement, styles.pullContentCenter)}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className={cx(styles.label, styles.bold)}>
{`${pixelPercentage[settings.fontSize]}`}
</label>

View File

@ -7,7 +7,9 @@ import { styles } from '/imports/ui/components/user-list/user-list-content/style
import { PANELS, ACTIONS } from '../../layout/enums';
const propTypes = {
intl: PropTypes.object.isRequired,
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
locale: PropTypes.shape({
locale: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,

View File

@ -48,6 +48,7 @@ const BreakoutRoomItem = ({
data-test="breakoutRoomsItem"
className={styles.listItem}
aria-label={intl.formatMessage(intlMessages.breakoutTitle)}
onKeyPress={() => {}}
>
<Icon iconName="rooms" />
<span aria-hidden>{intl.formatMessage(intlMessages.breakoutTitle)}</span>

View File

@ -51,7 +51,7 @@ class UserCaptions extends Component {
layoutContextDispatch,
} = this.props;
return ownedLocales.map(locale => (
return ownedLocales.map((locale) => (
<CSSTransition
classNames={listTransition}
appear
@ -62,7 +62,12 @@ class UserCaptions extends Component {
className={styles.captionsList}
key={locale.locale}
>
<CaptionsListItem {...{ locale, layoutContextDispatch, sidebarContentPanel }} tabIndex={-1} />
<CaptionsListItem
{...{
locale, layoutContextDispatch, sidebarContentPanel,
}}
tabIndex={-1}
/>
</CSSTransition>
));
}

View File

@ -73,7 +73,7 @@ class UserNotes extends Component {
renderNotes() {
const {
intl, disableNote, sidebarContentPanel, layoutContextDispatch
intl, disableNote, sidebarContentPanel, layoutContextDispatch,
} = this.props;
const { unread } = this.state;

View File

@ -4,13 +4,13 @@ import _ from 'lodash';
import { Session } from 'meteor/session';
import PropTypes from 'prop-types';
import { findDOMNode } from 'react-dom';
import cx from 'classnames'
import cx from 'classnames';
import UserAvatar from '/imports/ui/components/user-avatar/component';
import Icon from '/imports/ui/components/icon/component';
import lockContextContainer from '/imports/ui/components/lock-viewers/context/container';
import { withModalMounter } from '/imports/ui/components/modal/service';
import RemoveUserModal from '/imports/ui/components/modal/remove-user/component';
import BBBMenu from "/imports/ui/components/menu/component";
import BBBMenu from '/imports/ui/components/menu/component';
import { styles } from './styles';
import UserName from '../user-name/component';
import { PANELS, ACTIONS } from '../../../../../layout/enums';
@ -150,7 +150,6 @@ class UserDropdown extends PureComponent {
this.state = {
isActionsOpen: false,
dropdownDirection: 'top',
dropdownVisible: false,
showNestedOptions: false,
selected: false,
@ -167,6 +166,17 @@ class UserDropdown extends PureComponent {
this.seperator = _.uniqueId('action-separator-');
}
handleScroll() {
this.setState({
isActionsOpen: false,
showNestedOptions: false,
});
}
handleClose() {
this.setState({ selected: null });
}
onActionsShow() {
Session.set('dropdownOpen', true);
const { getScrollContainerRef } = this.props;
@ -174,14 +184,14 @@ class UserDropdown extends PureComponent {
const scrollContainer = getScrollContainerRef();
if (dropdown && scrollContainer) {
// eslint-disable-next-line react/no-find-dom-node
const list = findDOMNode(this.list);
const children = [].slice.call(list.children);
children.find(child => child.getAttribute('role') === 'menuitem').focus();
children.find((child) => child.getAttribute('role') === 'menuitem').focus();
this.setState({
isActionsOpen: true,
dropdownVisible: false,
dropdownDirection: 'top',
});
scrollContainer.addEventListener('scroll', this.handleScroll, false);
@ -237,12 +247,8 @@ class UserDropdown extends PureComponent {
const amIPresenter = currentUser.presenter;
const amIModerator = currentUser.role === ROLE_MODERATOR;
const actionPermissions = getAvailableActions(amIModerator,
meetingIsBreakout,
user,
voiceUser,
usersProp,
amIPresenter
const actionPermissions = getAvailableActions(
amIModerator, meetingIsBreakout, user, voiceUser, usersProp, amIPresenter,
);
const actions = [];
@ -274,7 +280,7 @@ class UserDropdown extends PureComponent {
if (showNestedOptions && isMeteorConnected) {
if (allowedToChangeStatus) {
actions.push({
key: "back",
key: 'back',
label: intl.formatMessage(messages.backTriggerLabel),
onClick: () => this.setState({ showNestedOptions: false }),
icon: 'left_arrow',
@ -284,7 +290,7 @@ class UserDropdown extends PureComponent {
const statuses = Object.keys(getEmojiList);
statuses.forEach(s => {
statuses.forEach((s) => {
actions.push({
key: s,
label: intl.formatMessage({ id: `app.actionsBar.emojiMenu.${s}Label` }),
@ -294,19 +300,19 @@ class UserDropdown extends PureComponent {
this.handleClose();
},
icon: getEmojiList[s],
})
});
});
return actions;
}
if (allowedToChangeStatus && isMeteorConnected) {
actions.push({
key: "setstatus",
key: 'setstatus',
label: intl.formatMessage(messages.statusTriggerLabel),
onClick: () => this.setState({ showNestedOptions: true }),
icon: 'user',
iconRight: 'right_arrow',
})
});
}
const showChatOption = CHAT_ENABLED
@ -317,8 +323,7 @@ class UserDropdown extends PureComponent {
if (showChatOption) {
actions.push({
dataTest: "activeChat",
key: "activeChat",
key: 'activeChat',
label: intl.formatMessage(messages.StartPrivateChat),
onClick: () => {
this.handleClose();
@ -342,7 +347,7 @@ class UserDropdown extends PureComponent {
if (allowedToResetStatus && user.emoji !== 'none' && isMeteorConnected) {
actions.push({
key: "clearStatus",
key: 'clearStatus',
label: intl.formatMessage(messages.ClearStatusLabel),
onClick: () => {
this.onActionsHide(setEmojiStatus(user.userId, 'none'));
@ -354,7 +359,7 @@ class UserDropdown extends PureComponent {
if (allowedToMuteAudio && isMeteorConnected && !meetingIsBreakout) {
actions.push({
key: "mute",
key: 'mute',
label: intl.formatMessage(messages.MuteUserAudioLabel),
onClick: () => {
this.onActionsHide(toggleVoice(user.userId));
@ -366,7 +371,7 @@ class UserDropdown extends PureComponent {
if (allowedToUnmuteAudio && !userLocks.userMic && isMeteorConnected && !meetingIsBreakout) {
actions.push({
key: "unmute",
key: 'unmute',
label: intl.formatMessage(messages.UnmuteUserAudioLabel),
onClick: () => {
this.onActionsHide(toggleVoice(user.userId));
@ -382,8 +387,8 @@ class UserDropdown extends PureComponent {
: intl.formatMessage(messages.giveWhiteboardAccess);
actions.push({
key: "changeWhiteboardAccess",
label: label,
key: 'changeWhiteboardAccess',
label,
onClick: () => {
WhiteboardService.changeWhiteboardAccess(user.userId, !user.whiteboardAccess);
this.handleClose();
@ -394,12 +399,12 @@ class UserDropdown extends PureComponent {
if (allowedToSetPresenter && isMeteorConnected) {
actions.push({
key: "setPresenter",
key: 'setPresenter',
label: isMe(user.userId)
? intl.formatMessage(messages.takePresenterLabel)
: intl.formatMessage(messages.makePresenterLabel),
? intl.formatMessage(messages.takePresenterLabel)
: intl.formatMessage(messages.makePresenterLabel),
onClick: () => {
this.onActionsHide(assignPresenter(user.userId))
this.onActionsHide(assignPresenter(user.userId));
this.handleClose();
},
icon: 'presentation',
@ -408,7 +413,7 @@ class UserDropdown extends PureComponent {
if (allowedToPromote && isMeteorConnected) {
actions.push({
key: "promote",
key: 'promote',
label: intl.formatMessage(messages.PromoteUserLabel),
onClick: () => {
this.onActionsHide(changeRole(user.userId, 'MODERATOR'));
@ -420,7 +425,7 @@ class UserDropdown extends PureComponent {
if (allowedToDemote && isMeteorConnected) {
actions.push({
key: "demote",
key: 'demote',
label: intl.formatMessage(messages.DemoteUserLabel),
onClick: () => {
this.onActionsHide(changeRole(user.userId, 'VIEWER'));
@ -434,9 +439,9 @@ class UserDropdown extends PureComponent {
const userLocked = user.locked && user.role !== ROLE_MODERATOR;
actions.push({
key: "unlockUser",
key: 'unlockUser',
label: userLocked ? intl.formatMessage(messages.UnlockUserLabel, { 0: user.name })
: intl.formatMessage(messages.LockUserLabel, { 0: user.name }),
: intl.formatMessage(messages.LockUserLabel, { 0: user.name }),
onClick: () => {
this.onActionsHide(toggleUserLock(user.userId, !userLocked));
this.handleClose();
@ -447,7 +452,7 @@ class UserDropdown extends PureComponent {
if (allowUserLookup && isMeteorConnected) {
actions.push({
key: "directoryLookup",
key: 'directoryLookup',
label: intl.formatMessage(messages.DirectoryLookupLabel),
onClick: () => {
this.onActionsHide(requestUserInformation(user.extId));
@ -459,7 +464,7 @@ class UserDropdown extends PureComponent {
if (allowedToRemove && isMeteorConnected) {
actions.push({
key: "remove",
key: 'remove',
label: intl.formatMessage(messages.RemoveUserLabel, { 0: user.name }),
onClick: () => {
this.onActionsHide(mountModal(
@ -468,7 +473,7 @@ class UserDropdown extends PureComponent {
user={user}
onConfirm={removeUser}
/>,
))
));
this.handleClose();
},
@ -480,44 +485,27 @@ class UserDropdown extends PureComponent {
}
getDropdownMenuParent() {
// eslint-disable-next-line react/no-find-dom-node
return findDOMNode(this.dropdown);
}
resetMenuState() {
return this.setState({
isActionsOpen: false,
dropdownDirection: 'top',
dropdownVisible: false,
showNestedOptions: false,
selected: false,
});
}
handleScroll() {
this.setState({
isActionsOpen: false,
showNestedOptions: false,
});
}
/**
* Check if the dropdown is visible, if so, check if should be draw on top or bottom direction.
*/
checkDropdownDirection() {
const { scrollArea } = this.props;
if (this.isDropdownActivedByUser()) {
const nextState = {
dropdownVisible: true,
};
const dropdownContent = findDOMNode(this.dropdownContent);
const dropdownBoundaries = dropdownContent.getBoundingClientRect();
const isDropdownVisible = UserDropdown.checkIfDropdownIsVisible(
dropdownBoundaries.y,
dropdownBoundaries.height,
);
if (!isDropdownVisible && scrollArea) nextState.dropdownDirection = 'bottom';
this.setState(nextState);
}
@ -534,10 +522,6 @@ class UserDropdown extends PureComponent {
return isActionsOpen && !dropdownVisible;
}
handleClose() {
this.setState({ selected: null });
}
renderUserAvatar() {
const {
normalizeEmojiName,
@ -573,9 +557,10 @@ class UserDropdown extends PureComponent {
avatar={user.avatar}
>
{
userInBreakout
&& !meetingIsBreakout
? breakoutSequence : userIcon}
userInBreakout
&& !meetingIsBreakout
? breakoutSequence : userIcon
}
</UserAvatar>
);
}
@ -630,7 +615,7 @@ class UserDropdown extends PureComponent {
<div className={styles.userAvatar}>
{this.renderUserAvatar()}
</div>
{<UserName
<UserName
{...{
user,
compact,
@ -640,7 +625,7 @@ class UserDropdown extends PureComponent {
isActionsOpen,
isMe,
}}
/>}
/>
</div>
</div>
);
@ -650,15 +635,20 @@ class UserDropdown extends PureComponent {
return (
<BBBMenu
trigger={
<div
tabIndex={-1}
onClick={() => this.setState({ selected: true })}
className={cx(userItemContentsStyle)}
aria-controls="default-dropdown-menu"
aria-haspopup="true"
style={{ width: '100%', marginLeft: '.5rem'}}>
{contents}
</div>
(
<div
tabIndex={-1}
onClick={() => this.setState({ selected: true })}
className={cx(userItemContentsStyle)}
aria-controls="default-dropdown-menu"
aria-haspopup="true"
style={{ width: '100%', marginLeft: '.5rem' }}
onKeyPress={() => {}}
role="button"
>
{contents}
</div>
)
}
actions={actions}
selectedEmoji={user.emoji}

View File

@ -79,7 +79,7 @@ const findOptimalGrid = (canvasWidth, canvasHeight, gutter, aspectRatio, numItem
const ASPECT_RATIO = 4 / 3;
const ACTION_NAME_FOCUS = 'focus';
const ACTION_NAME_MIRROR = 'mirror';
const ACTION_NAME_BACKGROUND = 'blurBackground';
// const ACTION_NAME_BACKGROUND = 'blurBackground';
class VideoList extends Component {
constructor(props) {
@ -242,7 +242,7 @@ class VideoList extends Component {
const { mirroredCameras } = this.state;
if (this.cameraIsMirrored(stream)) {
this.setState({
mirroredCameras: mirroredCameras.filter((x) => x != stream),
mirroredCameras: mirroredCameras.filter((x) => x !== stream),
});
} else {
this.setState({

View File

@ -152,7 +152,6 @@ class VideoListItem extends Component {
render() {
const {
videoIsReady,
isFullscreen,
isStreamHealthy,
isPortrait,
} = this.state;
@ -160,7 +159,6 @@ class VideoListItem extends Component {
name,
voiceUser,
numOfStreams,
swapLayout,
mirrored,
isFullscreenContext,
} = this.props;

View File

@ -237,7 +237,9 @@ const WaitingUsers = (props) => {
},
];
const buttonsData = authenticatedGuest ? _.concat(authGuestButtonsData, guestButtonsData) : guestButtonsData;
const buttonsData = authenticatedGuest
? _.concat(authGuestButtonsData, guestButtonsData)
: guestButtonsData;
return (
<div

View File

@ -21,7 +21,6 @@ export default withTracker(() => {
denied: false,
}).fetch();
const authenticatedUsers = GuestUsers.find({
meetingId: Auth.meetingID,
authenticated: true,