From bd8a7edbd2f9e3058b67d39fdc1c78156902f995 Mon Sep 17 00:00:00 2001 From: Hristo Terezov Date: Tue, 25 Feb 2020 15:09:52 +0000 Subject: [PATCH] fix(optimise): mapStateToProps for some components (#5085) --- .../components/ChromeExtensionBanner.web.js | 5 ++++- react/features/filmstrip/components/web/Toolbar.js | 6 +++++- .../invite/components/info-dialog/web/InfoDialog.js | 12 +++++++----- .../components/info-dialog/web/InfoDialogButton.js | 10 +++++----- .../subtitles/components/AbstractCaptions.js | 9 ++++++--- react/features/toolbox/components/web/Toolbox.js | 9 +++++---- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/react/features/chrome-extension-banner/components/ChromeExtensionBanner.web.js b/react/features/chrome-extension-banner/components/ChromeExtensionBanner.web.js index ac3582675..d258b378b 100644 --- a/react/features/chrome-extension-banner/components/ChromeExtensionBanner.web.js +++ b/react/features/chrome-extension-banner/components/ChromeExtensionBanner.web.js @@ -17,6 +17,8 @@ import { declare var interfaceConfig: Object; +const emptyObject = {}; + /** * Local storage key name for flag telling if user checked 'Don't show again' checkbox on the banner * If the user checks this before closing the banner, next time he will access a jitsi domain @@ -271,7 +273,8 @@ class ChromeExtensionBanner extends PureComponent { */ const _mapStateToProps = state => { return { - bannerCfg: state['features/base/config'].chromeExtensionBanner || {}, + // Using emptyObject so that we don't change the reference every time when _mapStateToProps is called. + bannerCfg: state['features/base/config'].chromeExtensionBanner || emptyObject, conference: getCurrentConference(state), iAmRecorder: state['features/base/config'].iAmRecorder }; diff --git a/react/features/filmstrip/components/web/Toolbar.js b/react/features/filmstrip/components/web/Toolbar.js index 5499ddf7d..ecc0690fe 100644 --- a/react/features/filmstrip/components/web/Toolbar.js +++ b/react/features/filmstrip/components/web/Toolbar.js @@ -12,6 +12,10 @@ import { declare var interfaceConfig: Object; +// XXX: We are not currently using state here, but in the future, when +// interfaceConfig is part of redux we will. This has to be retrieved from the store. +const visibleButtons = new Set(interfaceConfig.TOOLBAR_BUTTONS); + /** * The type of the React {@code Component} props of {@link Toolbar}. */ @@ -86,7 +90,7 @@ function _mapStateToProps(state): Object { // eslint-disable-line no-unused-vars // interfaceConfig is part of redux we will. return { - _visibleButtons: new Set(interfaceConfig.TOOLBAR_BUTTONS) + _visibleButtons: visibleButtons }; } diff --git a/react/features/invite/components/info-dialog/web/InfoDialog.js b/react/features/invite/components/info-dialog/web/InfoDialog.js index 5215a2024..a3ec994ba 100644 --- a/react/features/invite/components/info-dialog/web/InfoDialog.js +++ b/react/features/invite/components/info-dialog/web/InfoDialog.js @@ -59,7 +59,7 @@ type Props = { /** * The redux representation of the local participant. */ - _localParticipant: Object, + _localParticipantName: ?string, /** * The current location url of the conference. @@ -316,11 +316,11 @@ class InfoDialog extends Component { * @returns {string} */ _getTextToCopy() { - const { _localParticipant, liveStreamViewURL, t } = this.props; + const { _localParticipantName, liveStreamViewURL, t } = this.props; const _inviteURL = _decodeRoomURI(this.props._inviteURL); - let invite = _localParticipant && _localParticipant.name - ? t('info.inviteURLFirstPartPersonal', { name: _localParticipant.name }) + let invite = _localParticipantName + ? t('info.inviteURLFirstPartPersonal', { name: _localParticipantName }) : t('info.inviteURLFirstPartGeneral'); invite += t('info.inviteURLSecondPart', { @@ -613,6 +613,7 @@ class InfoDialog extends Component { * _conference: Object, * _conferenceName: string, * _inviteURL: string, + * _localParticipantName: ?string, * _locationURL: string, * _locked: string, * _password: string @@ -625,6 +626,7 @@ function _mapStateToProps(state) { password, room } = state['features/base/conference']; + const localParticipant = getLocalParticipant(state); return { _canEditPassword: isLocalParticipantModerator(state, state['features/base/config'].lockRoomGuestEnabled), @@ -632,7 +634,7 @@ function _mapStateToProps(state) { _conferenceName: room, _passwordNumberOfDigits: state['features/base/config'].roomPasswordNumberOfDigits, _inviteURL: getInviteURL(state), - _localParticipant: getLocalParticipant(state), + _localParticipantName: localParticipant?.name, _locationURL: state['features/base/connection'].locationURL, _locked: locked, _password: password diff --git a/react/features/invite/components/info-dialog/web/InfoDialogButton.js b/react/features/invite/components/info-dialog/web/InfoDialogButton.js index 292cc275c..afb0345ec 100644 --- a/react/features/invite/components/info-dialog/web/InfoDialogButton.js +++ b/react/features/invite/components/info-dialog/web/InfoDialogButton.js @@ -47,10 +47,10 @@ type Props = { _liveStreamViewURL: ?string, /** - * The number of real participants in the call. If in a lonely call, the + * True if the number of real participants in the call is less than 2. If in a lonely call, the * {@code InfoDialog} will be automatically shown. */ - _participantCount: number, + _isLonelyCall: boolean, /** * Whether or not the toolbox, in which this component exists, is visible. @@ -108,7 +108,7 @@ class InfoDialogButton extends Component { showDialog: (props._toolboxVisible && state.showDialog) || (!state.hasConnectedToConference && props._isConferenceJoined - && props._participantCount < 2 + && props._isLonelyCall && props._toolboxVisible && !props._disableAutoShow) }; @@ -243,7 +243,7 @@ class InfoDialogButton extends Component { * _disableAutoShow: boolean, * _isConferenceIsJoined: boolean, * _liveStreamViewURL: string, - * _participantCount: number, + * _isLonelyCall: boolean, * _toolboxVisible: boolean * }} */ @@ -260,7 +260,7 @@ function _mapStateToProps(state) { _liveStreamViewURL: currentLiveStreamingSession && currentLiveStreamingSession.liveStreamViewURL, - _participantCount: getParticipantCount(state), + _isLonelyCall: getParticipantCount(state) < 2, _toolboxVisible: state['features/toolbox'].visible }; } diff --git a/react/features/subtitles/components/AbstractCaptions.js b/react/features/subtitles/components/AbstractCaptions.js index 3225b024e..4e0d13c7f 100644 --- a/react/features/subtitles/components/AbstractCaptions.js +++ b/react/features/subtitles/components/AbstractCaptions.js @@ -17,7 +17,7 @@ export type AbstractCaptionsProps = { * Mapped by id just to have the keys for convenience during the rendering * process. */ - _transcripts: Map + _transcripts: ?Map }; /** @@ -36,7 +36,7 @@ export class AbstractCaptions render() { const { _requestingSubtitles, _transcripts } = this.props; - if (!_requestingSubtitles || !_transcripts.size) { + if (!_requestingSubtitles || !_transcripts || !_transcripts.size) { return null; } @@ -120,9 +120,12 @@ function _constructTranscripts(state: Object): Map { */ export function _abstractMapStateToProps(state: Object) { const { _requestingSubtitles } = state['features/subtitles']; + const transcripts = _constructTranscripts(state); return { _requestingSubtitles, - _transcripts: _constructTranscripts(state) + + // avoid rerenders by setting to props new empty Map instances. + _transcripts: transcripts.size === 0 ? undefined : transcripts }; } diff --git a/react/features/toolbox/components/web/Toolbox.js b/react/features/toolbox/components/web/Toolbox.js index 0396cdaa2..7dbcc47eb 100644 --- a/react/features/toolbox/components/web/Toolbox.js +++ b/react/features/toolbox/components/web/Toolbox.js @@ -206,6 +206,10 @@ type State = { declare var APP: Object; declare var interfaceConfig: Object; +// XXX: We are not currently using state here, but in the future, when +// interfaceConfig is part of redux we will. This will have to be retrieved from the store. +const visibleButtons = new Set(interfaceConfig.TOOLBAR_BUTTONS); + /** * Implements the conference toolbox on React/Web. * @@ -1347,10 +1351,7 @@ function _mapStateToProps(state) { || sharedVideoStatus === 'start' || sharedVideoStatus === 'pause', _visible: isToolboxVisible(state), - - // XXX: We are not currently using state here, but in the future, when - // interfaceConfig is part of redux we will. - _visibleButtons: new Set(interfaceConfig.TOOLBAR_BUTTONS) + _visibleButtons: visibleButtons }; }