-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Optimize report ordering in the LHN #10784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fed705a
44a2ff6
57a4c2e
4b40492
00ebe57
103b126
bb57fb0
f3a7fa0
35cfd23
8e8ba1f
6a26a03
d973776
b770d0c
8a6ea06
9626972
6091608
56d6d34
853f8b8
44e258c
bd05cec
475f0ed
80615c9
de15223
8512aa0
ee56ec4
e7f7b33
8057f21
ff49948
7c51a86
fd60c45
9fad973
ceb2ea9
2ef3622
9ceb909
25825d0
6eb03cf
42ece5b
66d147d
d03e6fb
47aa0b8
99532c2
988e7c6
4036325
34a60c9
a41a30a
6b87f56
629c4c4
55bd67f
84b1be4
5ca3b5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,6 @@ import _ from 'underscore'; | |
| import Onyx from 'react-native-onyx'; | ||
| import lodashGet from 'lodash/get'; | ||
| import lodashOrderBy from 'lodash/orderBy'; | ||
| import memoizeOne from 'memoize-one'; | ||
| import Str from 'expensify-common/lib/str'; | ||
| import ONYXKEYS from '../ONYXKEYS'; | ||
| import CONST from '../CONST'; | ||
|
|
@@ -143,39 +142,64 @@ function getParticipantNames(personalDetailList) { | |
| return participantNames; | ||
| } | ||
|
|
||
| /** | ||
| * A very optimized method to remove unique items from an array. | ||
| * Taken from https://stackoverflow.com/a/9229821/9114791 | ||
| * | ||
| * @param {Array} items | ||
| * @returns {Array} | ||
| */ | ||
| function uniqFast(items) { | ||
| const seenItems = {}; | ||
| const result = []; | ||
| let j = 0; | ||
| for (let i = 0; i < items.length; i++) { | ||
| const item = items[i]; | ||
| if (seenItems[item] !== 1) { | ||
| seenItems[item] = 1; | ||
| result[j++] = item; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait it is slower to push an item into an array than do this? 🤯
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the general answer is "yes, it's faster", but there are differences between JS engines which make the testing somewhat unreliable. Generally, |
||
| } | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| /** | ||
| * Returns a string with all relevant search terms. | ||
| * Default should be serachable by policy/domain name but not by participants. | ||
| * | ||
| * This method must be incredibly performant. It was found to be a big performance bottleneck | ||
| * when dealing with accounts that have thousands of reports. For loops are more efficient than _.each | ||
| * Array.prototype.push.apply is faster than using the spread operator, and concat() is faster than push(). | ||
| * | ||
| * @param {Object} report | ||
| * @param {String} reportName | ||
| * @param {Array} personalDetailList | ||
| * @param {Boolean} isChatRoomOrPolicyExpenseChat | ||
| * @return {String} | ||
| */ | ||
| function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolicyExpenseChat) { | ||
| const searchTerms = []; | ||
| let searchTerms = []; | ||
|
|
||
| if (!isChatRoomOrPolicyExpenseChat) { | ||
| _.each(personalDetailList, (personalDetail) => { | ||
| searchTerms.push(personalDetail.displayName); | ||
| searchTerms.push(personalDetail.login.replace(/\./g, '')); | ||
| }); | ||
| for (let i = 0; i < personalDetailList.length; i++) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should leave a note explaining why
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add a comment about it in the method docs, because I think it should also explain why spread operators aren't being used. |
||
| const personalDetail = personalDetailList[i]; | ||
| searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login.replace(/\./g, '')]); | ||
| } | ||
| } | ||
| if (report) { | ||
| searchTerms.push(...reportName); | ||
| searchTerms.push(..._.map(reportName.split(','), name => name.trim())); | ||
| Array.prototype.push.apply(searchTerms, reportName.split('')); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a comment to clarify why we are using
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious about the explanation and +1 |
||
| Array.prototype.push.apply(searchTerms, reportName.split(',')); | ||
|
|
||
| if (isChatRoomOrPolicyExpenseChat) { | ||
| const chatRoomSubtitle = ReportUtils.getChatRoomSubtitle(report, policies); | ||
| searchTerms.push(...chatRoomSubtitle); | ||
| searchTerms.push(..._.map(chatRoomSubtitle.split(','), name => name.trim())); | ||
| Array.prototype.push.apply(searchTerms, chatRoomSubtitle.split('')); | ||
| Array.prototype.push.apply(searchTerms, chatRoomSubtitle.split(',')); | ||
| } else { | ||
| searchTerms.push(...report.participants); | ||
| searchTerms = searchTerms.concat(report.participants); | ||
| } | ||
| } | ||
|
|
||
| return _.unique(searchTerms).join(' '); | ||
| return uniqFast(searchTerms).join(' '); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -217,80 +241,118 @@ function createOption(logins, personalDetails, report, reportActions = {}, { | |
| showChatPreviewLine = false, | ||
| forcePolicyNamePreview = false, | ||
| }) { | ||
| const isChatRoom = ReportUtils.isChatRoom(report); | ||
| const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); | ||
| const result = { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's hard for me to tell what is style and what is an improvement. Is there some benefit to declaring the object with all the properties it might have instead of assigning them later?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My reason for this change is that before, 100% of the logic was running regardless if there was a report or not. There is logic for reports AND personal details but for the LHN, we only need the logic for the reports. By being more strategic with the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds intuitive to me. Mostly asking as I'm curious which of these changes had the biggest impact on performance (for my own understanding).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I could have taken better notes while doing this, but in the end, I don't think there are hugely practical takeaways. At large scale, ANY piece of code can become inefficient, and the same thing that fixes one bottleneck isn't going to fix all bottle necks and shouldn't be used everywhere just for the sake of performance (like I think the better takeaway for anyone would be to learn how to do performance testing. This is something that I could do a LOU about because it seems like very few of our engineers are familiar with how to do this. Just for a quick sample though, here were the notes that I did take:
The changes to getSearchText() were to stop using |
||
| text: null, | ||
| alternateText: null, | ||
| brickRoadIndicator: null, | ||
| icons: null, | ||
| tooltipText: null, | ||
| ownerEmail: null, | ||
| subtitle: null, | ||
| participantsList: null, | ||
| login: null, | ||
| reportID: null, | ||
| phoneNumber: null, | ||
| payPalMeAddress: null, | ||
| isUnread: null, | ||
| hasDraftComment: false, | ||
| keyForList: null, | ||
| searchText: null, | ||
| isDefaultRoom: false, | ||
| isPinned: false, | ||
| hasOutstandingIOU: false, | ||
| iouReportID: null, | ||
| isIOUReportOwner: null, | ||
| iouReportAmount: 0, | ||
| isChatRoom: false, | ||
| isArchivedRoom: false, | ||
| shouldShowSubscript: false, | ||
| isPolicyExpenseChat: false, | ||
| }; | ||
|
|
||
| const personalDetailMap = getPersonalDetailsForLogins(logins, personalDetails); | ||
| const personalDetailList = _.values(personalDetailMap); | ||
| const isArchivedRoom = ReportUtils.isArchivedRoom(report); | ||
| const isDefaultRoom = ReportUtils.isDefaultRoom(report); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we initialize
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes! This came from me solving a merge conflict. |
||
| const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom || isPolicyExpenseChat; | ||
| const personalDetail = personalDetailList[0]; | ||
| const hasOutstandingIOU = lodashGet(report, 'hasOutstandingIOU', false); | ||
| const iouReport = hasOutstandingIOU | ||
| ? lodashGet(iouReports, `${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, {}) | ||
| : {}; | ||
|
|
||
| const lastActorDetails = report ? _.find(personalDetailList, {login: report.lastActorEmail}) : null; | ||
| const lastMessageTextFromReport = ReportUtils.isReportMessageAttachment({text: lodashGet(report, 'lastMessageText', ''), html: lodashGet(report, 'lastMessageHtml', '')}) | ||
| ? `[${Localize.translateLocal('common.attachment')}]` | ||
| : Str.htmlDecode(lodashGet(report, 'lastMessageText', '')); | ||
| let lastMessageText = report && hasMultipleParticipants && lastActorDetails | ||
| ? `${lastActorDetails.displayName}: ` | ||
| : ''; | ||
| lastMessageText += report ? lastMessageTextFromReport : ''; | ||
|
|
||
| if (isPolicyExpenseChat && isArchivedRoom) { | ||
| const archiveReason = lodashGet(lastReportActions[report.reportID], 'originalMessage.reason', CONST.REPORT.ARCHIVE_REASON.DEFAULT); | ||
| lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, { | ||
| displayName: lodashGet(lastActorDetails, 'displayName', report.lastActorEmail), | ||
| policyName: ReportUtils.getPolicyName(report, policies), | ||
| }); | ||
| } | ||
| let hasMultipleParticipants = personalDetailList.length > 1; | ||
| let subtitle; | ||
|
|
||
| const tooltipText = ReportUtils.getReportParticipantsTitle(lodashGet(report, ['participants'], [])); | ||
| const subtitle = ReportUtils.getChatRoomSubtitle(report, policies); | ||
| const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); | ||
| let alternateText; | ||
| if (isChatRoom || isPolicyExpenseChat) { | ||
| alternateText = (showChatPreviewLine && !forcePolicyNamePreview && lastMessageText) | ||
| ? lastMessageText | ||
| : subtitle; | ||
| if (report) { | ||
| result.isChatRoom = ReportUtils.isChatRoom(report); | ||
| result.isDefaultRoom = ReportUtils.isDefaultRoom(report); | ||
| result.isArchivedRoom = ReportUtils.isArchivedRoom(report); | ||
| result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); | ||
| result.shouldShowSubscript = result.isPolicyExpenseChat && !report.isOwnPolicyExpenseChat && !result.isArchivedRoom; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NAB because I know you didn't introduce this variable name, but
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like it could maybe be renamed to |
||
| result.brickRoadIndicator = getBrickRoadIndicatorStatusForReport(report, reportActions); | ||
| result.ownerEmail = report.ownerEmail; | ||
| result.reportID = report.reportID; | ||
| result.isUnread = ReportUtils.isUnread(report); | ||
| result.hasDraftComment = report.hasDraft; | ||
| result.isPinned = report.isPinned; | ||
| result.iouReportID = report.iouReportID; | ||
| result.keyForList = String(report.reportID); | ||
| result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participants || []); | ||
| result.hasOutstandingIOU = report.hasOutstandingIOU; | ||
|
|
||
| hasMultipleParticipants = personalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat; | ||
| subtitle = ReportUtils.getChatRoomSubtitle(report, policies); | ||
|
|
||
| let lastMessageTextFromReport = ''; | ||
| if (ReportUtils.isReportMessageAttachment({text: report.lastMessageText, html: report.lastMessageHtml})) { | ||
| lastMessageTextFromReport = `[${Localize.translateLocal('common.attachment')}]`; | ||
| } else { | ||
| lastMessageTextFromReport = Str.htmlDecode(report ? report.lastMessageText : ''); | ||
| } | ||
|
|
||
| const lastActorDetails = personalDetailMap[report.lastActorEmail] || null; | ||
| let lastMessageText = hasMultipleParticipants && lastActorDetails | ||
| ? `${lastActorDetails.displayName}: ` | ||
| : ''; | ||
| lastMessageText += report ? lastMessageTextFromReport : ''; | ||
|
|
||
| if (result.isPolicyExpenseChat && result.isArchivedRoom) { | ||
| const archiveReason = (lastReportActions[report.reportID] && lastReportActions[report.reportID].originalMessage && lastReportActions[report.reportID].originalMessage.reason) | ||
| || CONST.REPORT.ARCHIVE_REASON.DEFAULT; | ||
| lastMessageText = Localize.translate(preferredLocale, `reportArchiveReasons.${archiveReason}`, { | ||
| displayName: archiveReason.displayName || report.lastActorEmail, | ||
| policyName: ReportUtils.getPolicyName(report, policies), | ||
| }); | ||
| } | ||
|
|
||
| if (result.isChatRoom || result.isPolicyExpenseChat) { | ||
| result.alternateText = (showChatPreviewLine && !forcePolicyNamePreview && lastMessageText) | ||
| ? lastMessageText | ||
| : subtitle; | ||
| } else { | ||
| result.alternateText = (showChatPreviewLine && lastMessageText) | ||
| ? lastMessageText | ||
| : Str.removeSMSDomain(personalDetail.login); | ||
| } | ||
| } else { | ||
| alternateText = (showChatPreviewLine && lastMessageText) | ||
| ? lastMessageText | ||
| : Str.removeSMSDomain(personalDetail.login); | ||
| result.keyForList = personalDetail.login; | ||
| } | ||
| return { | ||
| text: reportName, | ||
| alternateText, | ||
| brickRoadIndicator: getBrickRoadIndicatorStatusForReport(report, reportActions), | ||
| icons: ReportUtils.getIcons(report, personalDetails, policies, lodashGet(personalDetail, ['avatar'])), | ||
| tooltipText, | ||
| ownerEmail: lodashGet(report, ['ownerEmail']), | ||
| subtitle, | ||
| participantsList: personalDetailList, | ||
|
|
||
| // It doesn't make sense to provide a login in the case of a report with multiple participants since | ||
| // there isn't any one single login to refer to for a report. | ||
| login: !hasMultipleParticipants ? personalDetail.login : null, | ||
| reportID: report ? report.reportID : null, | ||
| phoneNumber: !hasMultipleParticipants ? personalDetail.phoneNumber : null, | ||
| payPalMeAddress: !hasMultipleParticipants ? personalDetail.payPalMeAddress : null, | ||
| isUnread: ReportUtils.isUnread(report), | ||
| hasDraftComment: lodashGet(report, 'hasDraft', false), | ||
| keyForList: report ? String(report.reportID) : personalDetail.login, | ||
| searchText: getSearchText(report, reportName, personalDetailList, isChatRoom || isPolicyExpenseChat), | ||
| isPinned: lodashGet(report, 'isPinned', false), | ||
| hasOutstandingIOU, | ||
| iouReportID: lodashGet(report, 'iouReportID'), | ||
| isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, | ||
| iouReportAmount: lodashGet(iouReport, 'total', 0), | ||
| isChatRoom, | ||
| isArchivedRoom, | ||
| isDefaultRoom, | ||
| shouldShowSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat && !isArchivedRoom, | ||
| isPolicyExpenseChat, | ||
| }; | ||
|
|
||
| if (result.hasOutstandingIOU) { | ||
| const iouReport = iouReports[`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`] || null; | ||
| if (iouReport) { | ||
| result.isIOUReportOwner = iouReport.ownerEmail === currentUserLogin; | ||
| result.iouReportAmount = iouReport.total; | ||
| } | ||
| } | ||
|
|
||
| if (!hasMultipleParticipants) { | ||
| result.login = personalDetail.login; | ||
| result.phoneNumber = personalDetail.phoneNumber; | ||
| result.payPalMeAddress = personalDetail.payPalMeAddress; | ||
| } | ||
|
|
||
| const reportName = ReportUtils.getReportName(report, personalDetailMap, policies); | ||
| result.text = reportName; | ||
| result.subtitle = subtitle; | ||
| result.participantsList = personalDetailList; | ||
| result.icons = ReportUtils.getIcons(report, personalDetails, policies, personalDetail.avatar); | ||
| result.searchText = getSearchText(report, reportName, personalDetailList, result.isChatRoom || result.isPolicyExpenseChat); | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -351,7 +413,7 @@ function isCurrentUser(userDetails) { | |
| * | ||
| * @param {Object} reports | ||
| * @param {Object} personalDetails | ||
| * @param {Number} activeReportID | ||
| * @param {String} activeReportID | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When did reportID become strings and are all reportID now strings in JS?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is being discussed in Slack to make sure we're getting to the right conclusion: https://expensify.slack.com/archives/C02HWMSMZEC/p1662382397049269 Regardless, we're not treating them consistently everywhere yet, but we want to! |
||
| * @param {Object} options | ||
| * @returns {Object} | ||
| * @private | ||
|
|
@@ -404,20 +466,24 @@ function getOptions(reports, personalDetails, activeReportID, { | |
|
|
||
| const allReportOptions = []; | ||
| _.each(orderedReports, (report) => { | ||
| if (!report) { | ||
| return; | ||
| } | ||
| const isChatRoom = ReportUtils.isChatRoom(report); | ||
| const isDefaultRoom = ReportUtils.isDefaultRoom(report); | ||
| const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); | ||
| const logins = lodashGet(report, ['participants'], []); | ||
| const logins = report.participants || []; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we know for sure that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. report is defined as the _.each iterator, so I think it should always be defined
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm that's a good point. I'm not sure either 🤔
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, there are a few things here... This particular line of code (and several lines down below it) need to have null protection. There are two solutions around this typically...
I think I'm going to do number |
||
|
|
||
| // Report data can sometimes be incomplete. If we have no logins or reportID then we will skip this entry. | ||
| const shouldFilterNoParticipants = _.isEmpty(logins) && !isChatRoom && !isDefaultRoom && !isPolicyExpenseChat; | ||
| if (!report || !report.reportID || shouldFilterNoParticipants) { | ||
| if (!report.reportID || shouldFilterNoParticipants) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we do this sooner on line 469? if (!report || !report.reportID) {
return;
}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably could. I'm honestly a bit perplexed by this and the comment. Since reports are indexed in Onyx by their ID, I don't think it should ever be possible for a report to not have an ID. If it is possible, I think it is a bug that we should track down and fix. So, I'd be more willing to either remove this check entirely, or at least add a log if we detect there is no reportID.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm feeling cautious about removing that since it looks like we use the "report without a reportID" as a kind of "hook" to fetch the report. Which was the expected behavior at one point. But also looks like there's maybe some further cleanup to do here: We could solve this by sending the report and comment when a new message is added.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh wait scratch everything I just said haha that code looks for
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still feeling cautious and agree we should try to figure out if/why a report object can be merged with no
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. About the best I can offer in that case then is to add a log somewhere to detect if a report ID is missing. I don't think this code is the right place for it though. I would add it somewhere in Onyx.update() probably? Something like:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. but that doesn't really work because of doing something like
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kind of just feel here like we need to trust that we would never have a report without a reportID. And if it happens, we will find out about it in buggy behavior and crashes. |
||
| return; | ||
| } | ||
|
|
||
| const hasDraftComment = lodashGet(report, 'hasDraft', false); | ||
| const iouReportOwner = lodashGet(report, 'hasOutstandingIOU', false) | ||
| ? lodashGet(iouReports, [`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`, 'ownerEmail'], '') | ||
| const hasDraftComment = report.hasDraft || false; | ||
| const iouReport = report.iouReportID && iouReports[`${ONYXKEYS.COLLECTION.REPORT_IOUS}${report.iouReportID}`]; | ||
| const iouReportOwner = report.hasOutstandingIOU && iouReport | ||
| ? iouReport.ownerEmail | ||
| : ''; | ||
|
|
||
| const reportContainsIOUDebt = iouReportOwner && iouReportOwner !== currentUserLogin; | ||
|
|
@@ -431,7 +497,7 @@ function getOptions(reports, personalDetails, activeReportID, { | |
| const shouldFilterReportIfRead = hideReadReports && !ReportUtils.isUnread(report); | ||
| const shouldFilterReport = shouldFilterReportIfEmpty || shouldFilterReportIfRead; | ||
|
|
||
| if (report.reportID !== activeReportID | ||
| if (report.reportID.toString() !== activeReportID | ||
| && (!report.isPinned || isDefaultRoom) | ||
| && !hasDraftComment | ||
| && shouldFilterReport | ||
|
|
@@ -762,7 +828,7 @@ function getMemberInviteOptions( | |
| * @param {Object} reportActions | ||
| * @returns {Object} | ||
| */ | ||
| function calculateSidebarOptions(reports, personalDetails, activeReportID, priorityMode, betas, reportActions) { | ||
| function getSidebarOptions(reports, personalDetails, activeReportID, priorityMode, betas, reportActions) { | ||
| let sideBarOptions = { | ||
| prioritizeIOUDebts: true, | ||
| prioritizeReportsWithDraftComments: true, | ||
|
|
@@ -786,8 +852,6 @@ function calculateSidebarOptions(reports, personalDetails, activeReportID, prior | |
| }); | ||
| } | ||
|
|
||
| const getSidebarOptions = memoizeOne(calculateSidebarOptions); | ||
|
|
||
| /** | ||
| * Helper method that returns the text to be used for the header's message and title (if any) | ||
| * | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.