From 43b44ecc6aede8d1221a65a8df79259dc4602686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Francisco=20Siebel?= <jfsiebel@gmail.com> Date: Fri, 23 Nov 2018 12:14:48 -0200 Subject: [PATCH] Improve user-list-content performance. close #6268 --- .../imports/ui/components/modal/service.js | 4 +- .../ui/components/nav-bar/component.jsx | 4 +- .../nav-bar/settings-dropdown/component.jsx | 10 +- .../nav-bar/settings-dropdown/container.jsx | 6 +- .../ui/components/user-list/component.jsx | 18 ++-- .../ui/components/user-list/container.jsx | 7 +- .../ui/components/user-list/service.js | 3 + .../breakout-room/component.jsx | 3 +- .../user-list/user-list-content/component.jsx | 23 ++-- .../user-list/user-list-content/container.jsx | 4 +- .../user-messages/component.jsx | 4 +- .../user-participants/component.jsx | 102 ++++++++++-------- .../user-participants/container.jsx | 11 ++ .../user-list-item/component.jsx | 20 ++-- .../user-list-item/container.jsx | 11 ++ .../user-dropdown/component.jsx | 9 +- .../user-list-item/user-name/component.jsx | 16 ++- .../user-options/component.jsx | 4 +- .../user-options/container.jsx | 4 +- .../user-polls/component.jsx | 8 +- bigbluebutton-html5/package-lock.json | 2 +- 21 files changed, 144 insertions(+), 129 deletions(-) create mode 100644 bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/container.jsx create mode 100644 bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/container.jsx diff --git a/bigbluebutton-html5/imports/ui/components/modal/service.js b/bigbluebutton-html5/imports/ui/components/modal/service.js index d920ec8390..f842730245 100644 --- a/bigbluebutton-html5/imports/ui/components/modal/service.js +++ b/bigbluebutton-html5/imports/ui/components/modal/service.js @@ -1,5 +1,5 @@ import { Tracker } from 'meteor/tracker'; -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; const currentModal = { component: null, @@ -19,7 +19,7 @@ export const getModal = () => { }; export const withModalMounter = ComponentToWrap => - class ModalMounterWrapper extends Component { + class ModalMounterWrapper extends PureComponent { static mount(modalComponent) { showModal(null); // defer the execution to a subsequent event loop diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx index fb8ae22b3a..d4a16804c4 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; import cx from 'classnames'; @@ -67,7 +67,7 @@ const openBreakoutJoinConfirmation = (breakout, breakoutName, mountModal) => const closeBreakoutJoinConfirmation = mountModal => mountModal(null); -class NavBar extends Component { +class NavBar extends PureComponent { constructor(props) { super(props); diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx index 108b08ce51..5b263c094f 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import cx from 'classnames'; import _ from 'lodash'; @@ -81,7 +81,7 @@ const intlMessages = defineMessages({ }, }); -class SettingsDropdown extends Component { +class SettingsDropdown extends PureComponent { constructor(props) { super(props); @@ -98,7 +98,7 @@ class SettingsDropdown extends Component { const { fullscreenLabel, fullscreenDesc, fullscreenIcon } = this.checkFullscreen(this.props); const { showHelpButton: helpButton } = Meteor.settings.public.app; - this.menuItems =_.compact( [(<DropdownListItem + this.menuItems = _.compact([(<DropdownListItem key={_.uniqueId('list-item-')} icon={fullscreenIcon} label={fullscreenLabel} @@ -142,14 +142,12 @@ class SettingsDropdown extends Component { description={intl.formatMessage(intlMessages.leaveSessionDesc)} onClick={() => mountModal(<LogoutConfirmationContainer />)} />), - ]) + ]); // Removes fullscreen button if not on Android if (!isAndroid) { this.menuItems.shift(); } - - } componentWillReceiveProps(nextProps) { diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx index 6a13b39a6e..9036ae76a5 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx @@ -1,9 +1,9 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import browser from 'browser-detect'; import SettingsDropdown from './component'; import { toggleFullScreen } from './service'; -export default class SettingsDropdownContainer extends Component { +export default class SettingsDropdownContainer extends PureComponent { constructor(props) { super(props); @@ -51,7 +51,7 @@ export default class SettingsDropdownContainer extends Component { render() { const handleToggleFullscreen = toggleFullScreen; - const isFullScreen = this.state.isFullScreen; + const { isFullScreen } = this.state; const result = browser(); const isAndroid = (result && result.os) ? result.os.includes('Android') : false; diff --git a/bigbluebutton-html5/imports/ui/components/user-list/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/component.jsx index 3643ae3170..8b6c91d395 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import { injectIntl } from 'react-intl'; import PropTypes from 'prop-types'; import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component'; @@ -8,13 +8,14 @@ import UserContentContainer from './user-list-content/container'; const propTypes = { openChats: PropTypes.arrayOf(String).isRequired, - users: PropTypes.arrayOf(Object).isRequired, compact: PropTypes.bool, intl: PropTypes.shape({ formatMessage: PropTypes.func.isRequired, }).isRequired, currentUser: PropTypes.shape({}).isRequired, - meeting: PropTypes.shape({}), + CustomLogoUrl: PropTypes.string.isRequired, + handleEmojiChange: PropTypes.func.isRequired, + getUsersId: PropTypes.func.isRequired, isBreakoutRoom: PropTypes.bool, getAvailableActions: PropTypes.func.isRequired, normalizeEmojiName: PropTypes.func.isRequired, @@ -35,17 +36,13 @@ const propTypes = { const defaultProps = { compact: false, isBreakoutRoom: false, - // This one is kinda tricky, meteor takes sometime to fetch the data and passing down - // So the first time its create, the meeting comes as null, sending an error to the client. - meeting: {}, }; -class UserList extends Component { +class UserList extends PureComponent { render() { const { intl, openChats, - users, compact, currentUser, isBreakoutRoom, @@ -56,7 +53,6 @@ class UserList extends Component { muteAllUsers, muteAllExceptPresenter, changeRole, - meeting, getAvailableActions, normalizeEmojiName, isMeetingLocked, @@ -69,6 +65,7 @@ class UserList extends Component { getEmoji, showBranding, hasBreakoutRoom, + getUsersId, } = this.props; return ( @@ -83,7 +80,6 @@ class UserList extends Component { {...{ intl, openChats, - users, compact, currentUser, isBreakoutRoom, @@ -94,7 +90,6 @@ class UserList extends Component { muteAllUsers, muteAllExceptPresenter, changeRole, - meeting, getAvailableActions, normalizeEmojiName, isMeetingLocked, @@ -105,6 +100,7 @@ class UserList extends Component { getEmojiList, getEmoji, hasBreakoutRoom, + getUsersId, } } />} diff --git a/bigbluebutton-html5/imports/ui/components/user-list/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/container.jsx index c6d4b916d8..8599e4c68d 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/container.jsx @@ -2,16 +2,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import { withTracker } from 'meteor/react-meteor-data'; import { meetingIsBreakout } from '/imports/ui/components/app/service'; -import Meetings from '/imports/api/meetings'; import getFromUserSettings from '/imports/ui/services/users-settings'; import Service from './service'; import UserList from './component'; const propTypes = { openChats: PropTypes.arrayOf(String).isRequired, - users: PropTypes.arrayOf(Object).isRequired, currentUser: PropTypes.shape({}).isRequired, - meeting: PropTypes.shape({}).isRequired, + getUsersId: PropTypes.func.isRequired, isBreakoutRoom: PropTypes.bool.isRequired, getAvailableActions: PropTypes.func.isRequired, normalizeEmojiName: PropTypes.func.isRequired, @@ -33,9 +31,8 @@ const UserListContainer = props => <UserList {...props} />; UserListContainer.propTypes = propTypes; export default withTracker(({ chatID, compact }) => ({ - users: Service.getUsers(), - meeting: Meetings.findOne({}), hasBreakoutRoom: Service.hasBreakoutRoom(), + getUsersId: Service.getUsersId, currentUser: Service.getCurrentUser(), openChats: Service.getOpenChats(chatID), isBreakoutRoom: meetingIsBreakout(), diff --git a/bigbluebutton-html5/imports/ui/components/user-list/service.js b/bigbluebutton-html5/imports/ui/components/user-list/service.js index 3678f7d61d..dbae3223c6 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/service.js +++ b/bigbluebutton-html5/imports/ui/components/user-list/service.js @@ -188,6 +188,8 @@ const getUsers = () => { .sort(sortUsers); }; +const getUsersId = () => getUsers().map(u => u.id); + const hasBreakoutRoom = () => Breakouts.find({ parentMeetingId: Auth.meetingID }).count() > 0; const getOpenChats = (chatID) => { @@ -443,6 +445,7 @@ export default { muteAllExceptPresenter, changeRole, getUsers, + getUsersId, getOpenChats, getCurrentUser, getAvailableActions, diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx index b0df572d51..5638e6ce9d 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/breakout-room/component.jsx @@ -1,5 +1,4 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import { Session } from 'meteor/session'; import Icon from '/imports/ui/components/icon/component'; diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx index 9932dee6e9..17188a23ad 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/component.jsx @@ -1,20 +1,18 @@ -import React from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { styles } from './styles'; -import UserParticipants from './user-participants/component'; +import UserParticipantsContainer from './user-participants/container'; import UserMessages from './user-messages/component'; import UserPolls from './user-polls/component'; import BreakoutRoomItem from './breakout-room/component'; const propTypes = { openChats: PropTypes.arrayOf(String).isRequired, - users: PropTypes.arrayOf(Object).isRequired, compact: PropTypes.bool, intl: PropTypes.shape({ formatMessage: PropTypes.func.isRequired, }).isRequired, currentUser: PropTypes.shape({}).isRequired, - meeting: PropTypes.shape({}), isBreakoutRoom: PropTypes.bool, getAvailableActions: PropTypes.func.isRequired, normalizeEmojiName: PropTypes.func.isRequired, @@ -29,24 +27,23 @@ const propTypes = { changeRole: PropTypes.func.isRequired, roving: PropTypes.func.isRequired, getGroupChatPrivate: PropTypes.func.isRequired, + handleEmojiChange: PropTypes.func.isRequired, + getUsersId: PropTypes.func.isRequired, + pollIsOpen: PropTypes.bool.isRequired, + forcePollOpen: PropTypes.bool.isRequired, }; const defaultProps = { compact: false, isBreakoutRoom: false, - // This one is kinda tricky, meteor takes sometime to fetch the data and passing down - // So the first time its create, the meeting comes as null, sending an error to the client. - meeting: {}, }; -class UserContent extends React.Component { +class UserContent extends PureComponent { render() { const { - users, compact, intl, currentUser, - meeting, isBreakoutRoom, setEmojiStatus, assignPresenter, @@ -68,6 +65,7 @@ class UserContent extends React.Component { pollIsOpen, forcePollOpen, hasBreakoutRoom, + getUsersId, } = this.props; return ( @@ -93,13 +91,11 @@ class UserContent extends React.Component { }} /> <BreakoutRoomItem isPresenter={currentUser.isPresenter} hasBreakoutRoom={hasBreakoutRoom} /> - <UserParticipants + <UserParticipantsContainer {...{ - users, compact, intl, currentUser, - meeting, isBreakoutRoom, setEmojiStatus, assignPresenter, @@ -116,6 +112,7 @@ class UserContent extends React.Component { getEmojiList, getEmoji, getGroupChatPrivate, + getUsersId, }} /> </div> diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx index f9daa37e1f..2e85bee545 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/container.jsx @@ -3,9 +3,9 @@ import { withTracker } from 'meteor/react-meteor-data'; import { Session } from 'meteor/session'; import UserContent from './component'; -const UserContentContainer = ({ ...props }) => <UserContent {...props} />; +const UserContentContainer = props => <UserContent {...props} />; -export default withTracker(({ }) => ({ +export default withTracker(() => ({ pollIsOpen: Session.equals('isPollOpen', true), forcePollOpen: Session.equals('forcePollOpen', true), }))(UserContentContainer); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/component.jsx index ca2b28c5a4..cfb12a669f 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-messages/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import PropTypes from 'prop-types'; import { defineMessages } from 'react-intl'; @@ -38,7 +38,7 @@ const intlMessages = defineMessages({ }, }); -class UserMessages extends Component { +class UserMessages extends PureComponent { constructor() { super(); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx index b3907e9329..ad4c2ab6cf 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx @@ -4,17 +4,21 @@ import { defineMessages } from 'react-intl'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { styles } from '/imports/ui/components/user-list/user-list-content/styles'; -import UserListItem from './user-list-item/component'; +import _ from 'lodash'; +import UserListItemContainer from './user-list-item/container'; import UserOptionsContainer from './user-options/container'; const propTypes = { - users: PropTypes.arrayOf(Object).isRequired, compact: PropTypes.bool, intl: PropTypes.shape({ formatMessage: PropTypes.func.isRequired, }).isRequired, currentUser: PropTypes.shape({}).isRequired, - meeting: PropTypes.shape({}), + meeting: PropTypes.shape({}).isRequired, + users: PropTypes.arrayOf(PropTypes.string).isRequired, + getGroupChatPrivate: PropTypes.func.isRequired, + handleEmojiChange: PropTypes.func.isRequired, + getUsersId: PropTypes.func.isRequired, isBreakoutRoom: PropTypes.bool, setEmojiStatus: PropTypes.func.isRequired, assignPresenter: PropTypes.func.isRequired, @@ -32,9 +36,6 @@ const propTypes = { const defaultProps = { compact: false, isBreakoutRoom: false, - // This one is kinda tricky, meteor takes sometime to fetch the data and passing down - // So the first time its create, the meeting comes as null, sending an error to the client. - meeting: {}, }; const listTransition = { @@ -83,6 +84,12 @@ class UserParticipants extends Component { } } + shouldComponentUpdate(nextProps, nextState) { + const isPropsEqual = _.isEqual(this.props, nextProps); + const isStateEqual = _.isEqual(this.state, nextState); + return !isPropsEqual || !isStateEqual; + } + componentDidUpdate(prevProps, prevState) { if (this.state.index === -1) { return; @@ -106,57 +113,60 @@ class UserParticipants extends Component { getAvailableActions, normalizeEmojiName, isMeetingLocked, - users, changeRole, assignPresenter, setEmojiStatus, removeUser, toggleVoice, - getGroupChatPrivate, // // TODO check if this is used - handleEmojiChange, // // TODO add to props validation + getGroupChatPrivate, + handleEmojiChange, getEmojiList, getEmoji, + users, } = this.props; let index = -1; - return users.map(user => ( - <CSSTransition - classNames={listTransition} - appear - enter - exit - timeout={0} - component="div" - className={cx(styles.participantsList)} - key={user.id} - > - <div ref={(node) => { this.userRefs[index += 1] = node; }}> - <UserListItem - {...{ - user, - currentUser, - compact, - isBreakoutRoom, - meeting, - getAvailableActions, - normalizeEmojiName, - isMeetingLocked, - handleEmojiChange, - getEmojiList, - getEmoji, - setEmojiStatus, - assignPresenter, - removeUser, - toggleVoice, - changeRole, - getGroupChatPrivate, - }} - getScrollContainerRef={this.getScrollContainerRef} - /> - </div> - </CSSTransition> - )); + const { meetingId } = meeting; + + return users.map(u => + ( + <CSSTransition + classNames={listTransition} + appear + enter + exit + timeout={0} + component="div" + className={cx(styles.participantsList)} + key={u} + > + <div ref={(node) => { this.userRefs[index += 1] = node; }}> + <UserListItemContainer + {...{ + currentUser, + compact, + isBreakoutRoom, + meetingId, + getAvailableActions, + normalizeEmojiName, + isMeetingLocked, + handleEmojiChange, + getEmojiList, + getEmoji, + setEmojiStatus, + assignPresenter, + removeUser, + toggleVoice, + changeRole, + getGroupChatPrivate, + }} + userId={u} + getScrollContainerRef={this.getScrollContainerRef} + /> + </div> + </CSSTransition> + )); } focusUserItem(index) { diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/container.jsx new file mode 100644 index 0000000000..b5ef848a0d --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/container.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { withTracker } from 'meteor/react-meteor-data'; +import Meetings from '/imports/api/meetings'; +import UserParticipants from './component'; + +const UserParticipantsContainer = ({ ...props }) => <UserParticipants {...props} />; + +export default withTracker(({ getUsersId }) => ({ + meeting: Meetings.findOne({}), + users: getUsersId(), +}))(UserParticipantsContainer); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx index 54d5fa0d7b..1bafe9249b 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx @@ -1,17 +1,10 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { injectIntl } from 'react-intl'; +import _ from 'lodash'; import UserDropdown from './user-dropdown/component'; const propTypes = { - user: PropTypes.shape({ - name: PropTypes.string.isRequired, - isPresenter: PropTypes.bool.isRequired, - isVoiceUser: PropTypes.bool.isRequired, - isModerator: PropTypes.bool.isRequired, - image: PropTypes.string, - }).isRequired, - currentUser: PropTypes.shape({ id: PropTypes.string.isRequired, }).isRequired, @@ -22,7 +15,6 @@ const propTypes = { }).isRequired, isBreakoutRoom: PropTypes.bool, getAvailableActions: PropTypes.func.isRequired, - meeting: PropTypes.shape({}).isRequired, isMeetingLocked: PropTypes.func.isRequired, normalizeEmojiName: PropTypes.func.isRequired, getScrollContainerRef: PropTypes.func.isRequired, @@ -32,9 +24,10 @@ const defaultProps = { isBreakoutRoom: false, }; -class UserListItem extends Component { +class UserListItem extends PureComponent { render() { const { + user, assignPresenter, compact, currentUser, @@ -48,12 +41,11 @@ class UserListItem extends Component { intl, isBreakoutRoom, isMeetingLocked, - meeting, + meetingId, normalizeEmojiName, removeUser, setEmojiStatus, toggleVoice, - user, } = this.props; const contents = (<UserDropdown @@ -71,7 +63,7 @@ class UserListItem extends Component { intl, isBreakoutRoom, isMeetingLocked, - meeting, + meetingId, normalizeEmojiName, removeUser, setEmojiStatus, diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/container.jsx new file mode 100644 index 0000000000..e27d54154b --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/container.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { withTracker } from 'meteor/react-meteor-data'; +import Users from '/imports/api/users'; +import mapUser from '/imports/ui/services/user/mapUser'; +import UserListItem from './component'; + +const UserListItemContainer = props => <UserListItem {...props} />; + +export default withTracker(({ userId }) => ({ + user: mapUser(Users.findOne({ userId })), +}))(UserListItemContainer); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx index ccb9aa475b..8285826f0f 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import { defineMessages } from 'react-intl'; import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; @@ -90,12 +90,11 @@ const propTypes = { formatMessage: PropTypes.func.isRequired, }).isRequired, normalizeEmojiName: PropTypes.func.isRequired, - meeting: PropTypes.shape({}).isRequired, isMeetingLocked: PropTypes.func.isRequired, getScrollContainerRef: PropTypes.func.isRequired, }; -class UserDropdown extends Component { +class UserDropdown extends PureComponent { /** * Return true if the content fit on the screen, false otherwise. * @@ -436,7 +435,7 @@ class UserDropdown extends Component { user, intl, isMeetingLocked, - meeting, + meetingId, } = this.props; const { @@ -484,7 +483,7 @@ class UserDropdown extends Component { user, compact, intl, - meeting, + meetingId, isMeetingLocked, userAriaLabel, isActionsOpen, diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-name/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-name/component.jsx index 231171c78e..d3c7e26181 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-name/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-name/component.jsx @@ -43,9 +43,10 @@ const propTypes = { intl: PropTypes.shape({ formatMessage: PropTypes.func.isRequired, }).isRequired, - meeting: PropTypes.shape({}).isRequired, isMeetingLocked: PropTypes.func.isRequired, userAriaLabel: PropTypes.string.isRequired, + meetingId: PropTypes.string.isRequired, + isActionsOpen: PropTypes.bool.isRequired, }; const UserName = (props) => { @@ -54,7 +55,7 @@ const UserName = (props) => { intl, compact, isMeetingLocked, - meeting, + meetingId, userAriaLabel, isActionsOpen, } = props; @@ -69,7 +70,7 @@ const UserName = (props) => { return null; } - if (isMeetingLocked(meeting.meetingId) && user.isLocked) { + if (isMeetingLocked(meetingId) && user.isLocked) { userNameSub.push(<span> <Icon iconName="lock" /> {intl.formatMessage(messages.locked)} @@ -81,7 +82,12 @@ const UserName = (props) => { } return ( - <div className={styles.userName} role="button" aria-label={userAriaLabel} aria-expanded={isActionsOpen}> + <div + className={styles.userName} + role="button" + aria-label={userAriaLabel} + aria-expanded={isActionsOpen} + > <span className={styles.userNameMain}> {user.name} <i>{(user.isCurrent) ? `(${intl.formatMessage(messages.you)})` : ''}</i> </span> @@ -90,7 +96,7 @@ const UserName = (props) => { <span className={styles.userNameSub}> {userNameSub.reduce((prev, curr) => [prev, ' | ', curr])} </span> - : null + : null } </div> ); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx index 3e689940ef..2f4e7eb515 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { defineMessages, injectIntl } from 'react-intl'; import _ from 'lodash'; @@ -69,7 +69,7 @@ const intlMessages = defineMessages({ }, }); -class UserOptions extends Component { +class UserOptions extends PureComponent { constructor(props) { super(props); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx index 59561dab0d..03872beb03 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import logger from '/imports/startup/client/logger'; import Auth from '/imports/ui/services/auth'; @@ -15,7 +15,7 @@ const propTypes = { setEmojiStatus: PropTypes.func.isRequired, }; -export default class UserOptionsContainer extends Component { +export default class UserOptionsContainer extends PureComponent { constructor(props) { super(props); const meeting = Meetings.findOne({ meetingId: Auth.meetingID }); diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx index 1d9098daea..f0776f8253 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-polls/component.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { PureComponent } from 'react'; import _ from 'lodash'; import { defineMessages, injectIntl } from 'react-intl'; import Icon from '/imports/ui/components/icon/component'; @@ -12,11 +12,7 @@ const intlMessages = defineMessages({ }, }); -class UserPolls extends Component { - constructor(props) { - super(props); - } - +class UserPolls extends PureComponent { render() { const { intl, diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json index 7b6939da5f..4d75af4431 100755 --- a/bigbluebutton-html5/package-lock.json +++ b/bigbluebutton-html5/package-lock.json @@ -6085,4 +6085,4 @@ } } } -} +} \ No newline at end of file -- GitLab