Skip to content

Commit 2133bef

Browse files
authored
Merge pull request #30852 from Expensify/revert-28469-perf/refactor-heavy-operations-for-draft
[NoQA] Revert "perf: refactor heavy operations when user starts to type"
2 parents 17ce0c2 + 82d0f7c commit 2133bef

File tree

9 files changed

+24
-82
lines changed

9 files changed

+24
-82
lines changed

src/components/LHNOptionsList/OptionRowLHNData.js

+1-6
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,14 @@ export default React.memo(
168168
},
169169
fullReport: {
170170
key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
171-
initialValue: {},
172171
},
173172
reportActions: {
174173
key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
175174
canEvict: false,
176-
initialValue: {},
177175
},
178176
personalDetails: {
179177
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
180178
selector: personalDetailsSelector,
181-
initialValue: {},
182179
},
183180
preferredLocale: {
184181
key: ONYXKEYS.NVP_PREFERRED_LOCALE,
@@ -189,17 +186,15 @@ export default React.memo(
189186
parentReportActions: {
190187
key: ({fullReport}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${fullReport.parentReportID}`,
191188
canEvict: false,
192-
initialValue: {},
193189
},
194190
policy: {
195191
key: ({fullReport}) => `${ONYXKEYS.COLLECTION.POLICY}${fullReport.policyID}`,
196-
initialValue: {},
197192
},
198193
// Ideally, we aim to access only the last transaction for the current report by listening to changes in reportActions.
199194
// In some scenarios, a transaction might be created after reportActions have been modified.
200195
// This can lead to situations where `lastTransaction` doesn't update and retains the previous value.
201196
// However, performance overhead of this is minimized by using memos inside the component.
202-
receiptTransactions: {key: ONYXKEYS.COLLECTION.TRANSACTION, initialValue: {}},
197+
receiptTransactions: {key: ONYXKEYS.COLLECTION.TRANSACTION},
203198
}),
204199
// eslint-disable-next-line rulesdir/no-multiple-onyx-in-file
205200
withOnyx({

src/libs/OptionsListUtils.js

-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ Onyx.connect({
8787
const policyExpenseReports = {};
8888
Onyx.connect({
8989
key: ONYXKEYS.COLLECTION.REPORT,
90-
waitForCollectionCallback: true,
9190
callback: (report, key) => {
9291
if (!ReportUtils.isPolicyExpenseChat(report)) {
9392
return;

src/libs/ReportActionsUtils.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,9 @@ function getLastVisibleMessage(reportID: string, actionsToMerge: ReportActions =
406406
};
407407
}
408408

409-
let messageText = message?.text ?? '';
410-
if (messageText) {
411-
messageText = String(messageText).replace(CONST.REGEX.AFTER_FIRST_LINE_BREAK, '').substring(0, CONST.REPORT.LAST_MESSAGE_TEXT_MAX_LENGTH).trim();
412-
}
409+
const messageText = message?.text ?? '';
413410
return {
414-
lastMessageText: messageText,
411+
lastMessageText: String(messageText).replace(CONST.REGEX.AFTER_FIRST_LINE_BREAK, '').substring(0, CONST.REPORT.LAST_MESSAGE_TEXT_MAX_LENGTH).trim(),
415412
};
416413
}
417414

src/libs/ReportUtils.js

+4-22
Original file line numberDiff line numberDiff line change
@@ -818,15 +818,8 @@ function isOneOnOneChat(report) {
818818
* @returns {Object}
819819
*/
820820
function getReport(reportID) {
821-
/**
822-
* Using typical string concatenation here due to performance issues
823-
* with template literals.
824-
*/
825-
if (!allReports) {
826-
return {};
827-
}
828-
829-
return allReports[ONYXKEYS.COLLECTION.REPORT + reportID] || {};
821+
// Deleted reports are set to null and lodashGet will still return null in that case, so we need to add an extra check
822+
return lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {}) || {};
830823
}
831824

832825
/**
@@ -1530,25 +1523,14 @@ function getMoneyRequestSpendBreakdown(report, allReportsDict = null) {
15301523
* @returns {String}
15311524
*/
15321525
function getPolicyExpenseChatName(report, policy = undefined) {
1533-
const ownerAccountID = report.ownerAccountID;
1534-
const personalDetails = allPersonalDetails[ownerAccountID];
1535-
const login = personalDetails ? personalDetails.login : null;
1536-
const reportOwnerDisplayName = getDisplayNameForParticipant(report.ownerAccountID) || login || report.reportName;
1526+
const reportOwnerDisplayName = getDisplayNameForParticipant(report.ownerAccountID) || lodashGet(allPersonalDetails, [report.ownerAccountID, 'login']) || report.reportName;
15371527

15381528
// If the policy expense chat is owned by this user, use the name of the policy as the report name.
15391529
if (report.isOwnPolicyExpenseChat) {
15401530
return getPolicyName(report, false, policy);
15411531
}
15421532

1543-
let policyExpenseChatRole = 'user';
1544-
/**
1545-
* Using typical string concatenation here due to performance issues
1546-
* with template literals.
1547-
*/
1548-
const policyItem = allPolicies[ONYXKEYS.COLLECTION.POLICY + report.policyID];
1549-
if (policyItem) {
1550-
policyExpenseChatRole = policyItem.role || 'user';
1551-
}
1533+
const policyExpenseChatRole = lodashGet(allPolicies, [`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'role']) || 'user';
15521534

15531535
// If this user is not admin and this policy expense chat has been archived because of account merging, this must be an old workspace chat
15541536
// of the account which was merged into the current user's account. Use the name of the policy as the name of the report.

src/libs/SidebarUtils.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@ function getOrderedReportIDs(
156156
}
157157
}
158158

159+
// There are a few properties that need to be calculated for the report which are used when sorting reports.
160+
reportsToDisplay.forEach((report) => {
161+
// Normally, the spread operator would be used here to clone the report and prevent the need to reassign the params.
162+
// However, this code needs to be very performant to handle thousands of reports, so in the interest of speed, we're just going to disable this lint rule and add
163+
// the reportDisplayName property to the report object directly.
164+
// eslint-disable-next-line no-param-reassign
165+
report.displayName = ReportUtils.getReportName(report);
166+
167+
// eslint-disable-next-line no-param-reassign
168+
report.iouReportAmount = ReportUtils.getMoneyRequestReimbursableTotal(report, allReports);
169+
});
170+
159171
// The LHN is split into four distinct groups, and each group is sorted a little differently. The groups will ALWAYS be in this order:
160172
// 1. Pinned/GBR - Always sorted by reportDisplayName
161173
// 2. Drafts - Always sorted by reportDisplayName
@@ -169,17 +181,7 @@ function getOrderedReportIDs(
169181
const draftReports: Report[] = [];
170182
const nonArchivedReports: Report[] = [];
171183
const archivedReports: Report[] = [];
172-
173184
reportsToDisplay.forEach((report) => {
174-
// Normally, the spread operator would be used here to clone the report and prevent the need to reassign the params.
175-
// However, this code needs to be very performant to handle thousands of reports, so in the interest of speed, we're just going to disable this lint rule and add
176-
// the reportDisplayName property to the report object directly.
177-
// eslint-disable-next-line no-param-reassign
178-
report.displayName = ReportUtils.getReportName(report);
179-
180-
// eslint-disable-next-line no-param-reassign
181-
report.iouReportAmount = ReportUtils.getMoneyRequestReimbursableTotal(report, allReports);
182-
183185
const isPinned = report.isPinned ?? false;
184186
if (isPinned || ReportUtils.requiresAttentionFromCurrentUser(report)) {
185187
pinnedAndGBRReports.push(report);
+2-25
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,15 @@
1-
import {InteractionManager} from 'react-native';
21
import Onyx from 'react-native-onyx';
32
import _ from 'underscore';
43
import * as ReportUtils from '@libs/ReportUtils';
54
import CONST from '@src/CONST';
65
import ONYXKEYS from '@src/ONYXKEYS';
76
import updateUnread from './updateUnread/index';
87

9-
let previousUnreadCount = 0;
10-
118
Onyx.connect({
129
key: ONYXKEYS.COLLECTION.REPORT,
1310
waitForCollectionCallback: true,
1411
callback: (reportsFromOnyx) => {
15-
if (!reportsFromOnyx) {
16-
return;
17-
}
18-
19-
/**
20-
* We need to wait until after interactions have finished to update the unread count because otherwise
21-
* the unread count will be updated while the interactions/animations are in progress and we don't want
22-
* to put more work on the main thread.
23-
*
24-
* For eg. On web we are manipulating DOM and it makes it a better candidate to wait until after interactions
25-
* have finished.
26-
*
27-
* More info: https://reactnative.dev/docs/interactionmanager
28-
*/
29-
InteractionManager.runAfterInteractions(() => {
30-
const unreadReports = _.filter(reportsFromOnyx, (report) => ReportUtils.isUnread(report) && report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN);
31-
const unreadReportsCount = _.size(unreadReports);
32-
if (previousUnreadCount !== unreadReportsCount) {
33-
previousUnreadCount = unreadReportsCount;
34-
updateUnread(unreadReportsCount);
35-
}
36-
});
12+
const unreadReports = _.filter(reportsFromOnyx, (report) => ReportUtils.isUnread(report) && report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN);
13+
updateUnread(_.size(unreadReports));
3714
},
3815
});

src/libs/actions/Report.js

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ Onyx.connect({
6565
const currentReportData = {};
6666
Onyx.connect({
6767
key: ONYXKEYS.COLLECTION.REPORT,
68-
waitForCollectionCallback: true,
6968
callback: (data, key) => {
7069
if (!key || !data) {
7170
return;

src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,8 @@ function ComposerWithSuggestions({
278278
}
279279
}
280280
const newCommentConverted = convertToLTRForComposer(newComment);
281-
const isNewCommentEmpty = !!newCommentConverted.match(/^(\s)*$/);
282-
const isPrevCommentEmpty = !!commentRef.current.match(/^(\s)*$/);
283-
284-
/** Only update isCommentEmpty state if it's different from previous one */
285-
if (isNewCommentEmpty !== isPrevCommentEmpty) {
286-
setIsCommentEmpty(isNewCommentEmpty);
287-
}
288281
emojisPresentBefore.current = emojis;
282+
setIsCommentEmpty(!!newCommentConverted.match(/^(\s)*$/));
289283
setValue(newCommentConverted);
290284
if (commentValue !== newComment) {
291285
const remainder = ComposerUtils.getCommonSuffixLength(commentValue, newComment);
@@ -562,7 +556,9 @@ function ComposerWithSuggestions({
562556
if (value.length === 0) {
563557
return;
564558
}
559+
565560
Report.setReportWithDraft(reportID, true);
561+
566562
// eslint-disable-next-line react-hooks/exhaustive-deps
567563
}, []);
568564

src/pages/home/sidebar/SidebarLinksData.js

-5
Original file line numberDiff line numberDiff line change
@@ -198,28 +198,23 @@ export default compose(
198198
chatReports: {
199199
key: ONYXKEYS.COLLECTION.REPORT,
200200
selector: chatReportSelector,
201-
initialValue: {},
202201
},
203202
isLoadingReportData: {
204203
key: ONYXKEYS.IS_LOADING_REPORT_DATA,
205204
},
206205
priorityMode: {
207206
key: ONYXKEYS.NVP_PRIORITY_MODE,
208-
initialValue: CONST.PRIORITY_MODE.DEFAULT,
209207
},
210208
betas: {
211209
key: ONYXKEYS.BETAS,
212-
initialValue: [],
213210
},
214211
allReportActions: {
215212
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
216213
selector: reportActionsSelector,
217-
initialValue: {},
218214
},
219215
policies: {
220216
key: ONYXKEYS.COLLECTION.POLICY,
221217
selector: policySelector,
222-
initialValue: {},
223218
},
224219
}),
225220
)(SidebarLinksData);

0 commit comments

Comments
 (0)