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;
}
}

View file

@ -7,6 +7,11 @@ import { StateType as RootStateType } from '../reducer';
import { AttachmentType } from '../../types/Attachment';
import { MessageAttributesType } from '../../model-types.d';
import { LinkPreviewWithDomain } from '../../types/LinkPreview';
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
import {
REMOVE_PREVIEW as REMOVE_LINK_PREVIEW,
RemoveLinkPreviewActionType,
} from './linkPreviews';
// State
@ -58,6 +63,7 @@ type ComposerActionType =
| ResetComposerActionType
| SetHighQualitySettingActionType
| SetLinkPreviewResultActionType
| RemoveLinkPreviewActionType
| SetQuotedMessageActionType;
// Action Creators
@ -176,5 +182,12 @@ export function reducer(
};
}
if (action.type === REMOVE_LINK_PREVIEW) {
return assignWithNoUnnecessaryAllocation(state, {
linkPreviewLoading: false,
linkPreviewResult: undefined,
});
}
return state;
}

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { LinkPreviewType } from '../../types/message/LinkPreviews';
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
// State
@ -12,14 +13,14 @@ export type LinkPreviewsStateType = {
// Actions
const ADD_PREVIEW = 'linkPreviews/ADD_PREVIEW';
const REMOVE_PREVIEW = 'linkPreviews/REMOVE_PREVIEW';
export const REMOVE_PREVIEW = 'linkPreviews/REMOVE_PREVIEW';
type AddLinkPreviewActionType = {
type: 'linkPreviews/ADD_PREVIEW';
payload: LinkPreviewType;
};
type RemoveLinkPreviewActionType = {
export type RemoveLinkPreviewActionType = {
type: 'linkPreviews/REMOVE_PREVIEW';
};
@ -68,9 +69,9 @@ export function reducer(
}
if (action.type === REMOVE_PREVIEW) {
return {
return assignWithNoUnnecessaryAllocation(state, {
linkPreview: undefined,
};
});
}
return state;

View file

@ -4137,12 +4137,12 @@ Whisper.ConversationView = Whisper.View.extend({
URL.revokeObjectURL(item.url);
}
});
window.reduxActions.linkPreviews.removeLinkPreview();
this.preview = null;
this.currentlyMatchedLink = null;
this.linkPreviewAbortController?.abort();
this.linkPreviewAbortController = null;
this.renderLinkPreview();
window.reduxActions.linkPreviews.removeLinkPreview();
},
async getStickerPackPreview(