Additional render optimizations

This commit is contained in:
Fedor Indutny 2021-08-18 06:34:22 -07:00 committed by GitHub
parent 6343e7c902
commit 7a8363c7c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 70 deletions

View file

@ -1,9 +1,10 @@
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { debounce, get, isNumber, pick } from 'lodash';
import { debounce, get, isNumber, pick, identity } from 'lodash';
import classNames from 'classnames';
import React, { CSSProperties, ReactChild, ReactNode } from 'react';
import { createSelector } from 'reselect';
import {
AutoSizer,
CellMeasurer,
@ -214,6 +215,74 @@ type StateType = {
lastMeasuredWarningHeight: number;
};
const getActions = createSelector(
// It is expensive to pick so many properties out of the `props` object so we
// use `createSelector` to memoize them by the last seen `props` object.
identity,
(props: PropsType): PropsActionsType => {
const unsafe = pick(props, [
'acknowledgeGroupMemberNameCollisions',
'clearChangedMessages',
'clearInvitedConversationsForNewlyCreatedGroup',
'closeContactSpoofingReview',
'setLoadCountdownStart',
'setIsNearBottom',
'reviewGroupMemberNameCollision',
'reviewMessageRequestNameCollision',
'learnMoreAboutDeliveryIssue',
'loadAndScroll',
'loadOlderMessages',
'loadNewerMessages',
'loadNewestMessages',
'markMessageRead',
'markViewed',
'onBlock',
'onBlockAndReportSpam',
'onDelete',
'onUnblock',
'removeMember',
'selectMessage',
'clearSelectedMessage',
'unblurAvatar',
'updateSharedGroups',
'doubleCheckMissingQuoteReference',
'onHeightChange',
'checkForAccount',
'reactToMessage',
'replyToMessage',
'retrySend',
'showForwardMessageModal',
'deleteMessage',
'deleteMessageForEveryone',
'showMessageDetail',
'openConversation',
'showContactDetail',
'showContactModal',
'kickOffAttachmentDownload',
'markAttachmentAsCorrupted',
'showVisualAttachment',
'downloadAttachment',
'displayTapToViewMessage',
'openLink',
'scrollToQuotedMessage',
'showExpiredIncomingTapToViewToast',
'showExpiredOutgoingTapToViewToast',
'showIdentity',
'downloadNewVersion',
'contactSupport',
]);
const safe: AssertProps<PropsActionsType, typeof unsafe> = unsafe;
return safe;
}
);
export class Timeline extends React.PureComponent<PropsType, StateType> {
public cellSizeCache = new CellMeasurerCache({
defaultHeight: 64,
@ -728,6 +797,8 @@ export class Timeline extends React.PureComponent<PropsType, StateType> {
const messageId = items[itemIndex];
stableKey = messageId;
const actions = getActions(this.props);
rowContents = (
<div
id={messageId}
@ -737,7 +808,7 @@ export class Timeline extends React.PureComponent<PropsType, StateType> {
role="row"
>
<ErrorBoundary i18n={i18n} showDebugLog={() => window.showDebugLog()}>
{renderItem(messageId, id, this.resizeMessage, this.getActions())}
{renderItem(messageId, id, this.resizeMessage, actions)}
</ErrorBoundary>
</div>
);
@ -1481,66 +1552,4 @@ export class Timeline extends React.PureComponent<PropsType, StateType> {
throw missingCaseError(warning);
}
}
private getActions(): PropsActionsType {
const unsafe = pick(this.props, [
'acknowledgeGroupMemberNameCollisions',
'clearChangedMessages',
'clearInvitedConversationsForNewlyCreatedGroup',
'closeContactSpoofingReview',
'setLoadCountdownStart',
'setIsNearBottom',
'reviewGroupMemberNameCollision',
'reviewMessageRequestNameCollision',
'learnMoreAboutDeliveryIssue',
'loadAndScroll',
'loadOlderMessages',
'loadNewerMessages',
'loadNewestMessages',
'markMessageRead',
'markViewed',
'onBlock',
'onBlockAndReportSpam',
'onDelete',
'onUnblock',
'removeMember',
'selectMessage',
'clearSelectedMessage',
'unblurAvatar',
'updateSharedGroups',
'doubleCheckMissingQuoteReference',
'onHeightChange',
'checkForAccount',
'reactToMessage',
'replyToMessage',
'retrySend',
'showForwardMessageModal',
'deleteMessage',
'deleteMessageForEveryone',
'showMessageDetail',
'openConversation',
'showContactDetail',
'showContactModal',
'kickOffAttachmentDownload',
'markAttachmentAsCorrupted',
'showVisualAttachment',
'downloadAttachment',
'displayTapToViewMessage',
'openLink',
'scrollToQuotedMessage',
'showExpiredIncomingTapToViewToast',
'showExpiredOutgoingTapToViewToast',
'showIdentity',
'downloadNewVersion',
'contactSupport',
]);
const safe: AssertProps<PropsActionsType, typeof unsafe> = unsafe;
return safe;
}
}