From c6d70dcdc71a368782cdcc7579460a96cecfd9f0 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 12:31:07 -0700 Subject: [PATCH 01/11] add fix --- .../MoneyRequestParticipantsSelector.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index 1263dd5db2b9..8e075b9b7efc 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -116,6 +116,26 @@ function MoneyRequestParticipantsSelector({ indexOffset, }); indexOffset += participants.length; + } else { + // Check to see if any of the selected participants that match the search term that are not already in the recent reports or personal details + const selectedParticipantsWithoutDetails = _.filter(participants, (participant) => { + const accountID = lodashGet(participant, 'accountID', null); + const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); + const isReportInRecentReports = _.some(newChatOptions.recentReports, (report) => report.accountID === accountID); + const isReportInPersonalDetails = _.some(newChatOptions.personalDetails, (personalDetail) => personalDetail.accountID === accountID); + return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; + }); + + newSections.push({ + title: undefined, + data: _.map(selectedParticipantsWithoutDetails, (participant) => { + const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); + return isPolicyExpenseChat ? OptionsListUtils.getPolicyExpenseReportOption(participant) : OptionsListUtils.getParticipantsOption(participant, personalDetails); + }), + shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), + indexOffset, + }); + indexOffset += selectedParticipantsWithoutDetails.length; } if (maxParticipantsReached) { From 36d67a9bae2faab60048ba3c0f181552ced518f6 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 12:38:03 -0700 Subject: [PATCH 02/11] Add comment to help clarify what is happening --- .../MoneyRequestParticipantsSelector.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index 8e075b9b7efc..a4b9b0924d13 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -117,7 +117,8 @@ function MoneyRequestParticipantsSelector({ }); indexOffset += participants.length; } else { - // Check to see if any of the selected participants that match the search term that are not already in the recent reports or personal details + // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details + // This will add them to the list of options, deduping them if they already exist in the other lists const selectedParticipantsWithoutDetails = _.filter(participants, (participant) => { const accountID = lodashGet(participant, 'accountID', null); const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); From 7148df6ca14827003ff4b7d10c6209b36c6a17ff Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 12:41:56 -0700 Subject: [PATCH 03/11] Duplicate changes to New Group --- src/pages/NewChatPage.js | 23 ++++++++++++++++++- .../MoneyRequestParticipantsSelector.js | 4 +++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index a9401bce684e..b1c712bb457f 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -3,6 +3,7 @@ import React, {useState, useEffect, useMemo, useCallback} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import OptionsSelector from '../components/OptionsSelector'; import * as OptionsListUtils from '../libs/OptionsListUtils'; import Permissions from '../libs/Permissions'; @@ -71,7 +72,9 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i const sectionsList = []; let indexOffset = 0; - // Only show the selected participants if the search is empty + // We show the selected participants at the top of the list when there is no search term + // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results + // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time if (searchTerm === '') { sectionsList.push({ title: undefined, @@ -80,6 +83,24 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i indexOffset, }); indexOffset += selectedOptions.length; + } else { + // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details + // This will add them to the list of options, deduping them if they already exist in the other lists + const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { + const accountID = lodashGet(participant, 'accountID', null); + const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); + const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); + const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); + return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; + }); + + sectionsList.push({ + title: undefined, + data: selectedParticipantsWithoutDetails, + shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), + indexOffset, + }); + indexOffset += selectedParticipantsWithoutDetails.length; } if (maxParticipantsReached) { diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index a4b9b0924d13..af02003a87b3 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -104,7 +104,9 @@ function MoneyRequestParticipantsSelector({ const newSections = []; let indexOffset = 0; - // Only show the selected participants if the search is empty + // We show the selected participants at the top of the list when there is no search term + // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results + // This clears up space on mobile views, where if you split with 4+ people you can't see the selected participants and the search results at the same time if (searchTerm === '') { newSections.push({ title: undefined, From f13440e14fe852090a118d1ea57e42f5cd12b8bc Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 13:31:19 -0700 Subject: [PATCH 04/11] Add new method for formatting sections --- src/libs/OptionsListUtils.js | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index ba86339f7270..c7e83fad6d7a 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1585,6 +1585,61 @@ function shouldOptionShowTooltip(option) { return (!option.isChatRoom || option.isThread) && !option.isArchivedRoom; } +/** + * Handles the logic for displaying selected participants from the search term + * @param {String} searchTerm + * @param {Array} sectionList + * @param {Array} selectedOptions + * @param {Array} filteredRecentReports + * @param {Array} filteredPersonalDetails + * @param {Object} personalDetails + * @param {Boolean} shouldGetOptionDetails + * @param {Number} indexOffset + * @returns {Number} newIndexOffset + */ +function formatSectionsFromSearchTerm(searchTerm, sectionList, selectedOptions, filteredRecentReports, filteredPersonalDetails, personalDetails = {}, shouldGetOptionDetails = false, indexOffset) +{ + // We show the selected participants at the top of the list when there is no search term + // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results + // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time + let newIndexOffset = indexOffset; + if (searchTerm === '') { + sectionList.push({ + title: undefined, + data: shouldGetOptionDetails ? _.map(selectedOptions, (participant) => { + const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + }) : selectedOptions, + shouldShow: !_.isEmpty(selectedOptions), + indexOffset, + }); + newIndexOffset += selectedOptions.length; + } else { + // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details + // This will add them to the list of options, deduping them if they already exist in the other lists + const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { + const accountID = lodashGet(participant, 'accountID', null); + const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); + const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); + const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); + return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; + }); + + sectionList.push({ + title: undefined, + data: shouldGetOptionDetails ? _.map(selectedParticipantsWithoutDetails, (participant) => { + const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + }) : selectedParticipantsWithoutDetails, + shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), + indexOffset, + }); + newIndexOffset += selectedParticipantsWithoutDetails.length; + } + + return newIndexOffset; +} + export { addSMSDomainIfPhoneNumber, getAvatarsForAccountIDs, @@ -1610,4 +1665,5 @@ export { hasEnabledOptions, getCategoryOptionTree, formatMemberForList, + formatSectionsFromSearchTerm, }; From ba0990f99d130e17bdcea578c626994d9252a168 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 13:31:41 -0700 Subject: [PATCH 05/11] Replace the money request participants with the method --- .../MoneyRequestParticipantsSelector.js | 39 +------------------ 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index af02003a87b3..ff2eedc2cd37 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -103,43 +103,8 @@ function MoneyRequestParticipantsSelector({ const sections = useMemo(() => { const newSections = []; let indexOffset = 0; - - // We show the selected participants at the top of the list when there is no search term - // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results - // This clears up space on mobile views, where if you split with 4+ people you can't see the selected participants and the search results at the same time - if (searchTerm === '') { - newSections.push({ - title: undefined, - data: _.map(participants, (participant) => { - const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); - return isPolicyExpenseChat ? OptionsListUtils.getPolicyExpenseReportOption(participant) : OptionsListUtils.getParticipantsOption(participant, personalDetails); - }), - shouldShow: true, - indexOffset, - }); - indexOffset += participants.length; - } else { - // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details - // This will add them to the list of options, deduping them if they already exist in the other lists - const selectedParticipantsWithoutDetails = _.filter(participants, (participant) => { - const accountID = lodashGet(participant, 'accountID', null); - const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); - const isReportInRecentReports = _.some(newChatOptions.recentReports, (report) => report.accountID === accountID); - const isReportInPersonalDetails = _.some(newChatOptions.personalDetails, (personalDetail) => personalDetail.accountID === accountID); - return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; - }); - - newSections.push({ - title: undefined, - data: _.map(selectedParticipantsWithoutDetails, (participant) => { - const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); - return isPolicyExpenseChat ? OptionsListUtils.getPolicyExpenseReportOption(participant) : OptionsListUtils.getParticipantsOption(participant, personalDetails); - }), - shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), - indexOffset, - }); - indexOffset += selectedParticipantsWithoutDetails.length; - } + + indexOffset = OptionsListUtils.formatSectionsFromSearchTerm(searchTerm, newSections, participants, newChatOptions.recentReports, newChatOptions.personalDetails, personalDetails, true, indexOffset); if (maxParticipantsReached) { return newSections; From 42afc185efb46af8152a5def93f43b4073aaab3d Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 13:34:32 -0700 Subject: [PATCH 06/11] Replace new chat page with this method --- src/pages/NewChatPage.js | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index b1c712bb457f..1cc5c295d3e7 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -72,36 +72,7 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i const sectionsList = []; let indexOffset = 0; - // We show the selected participants at the top of the list when there is no search term - // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results - // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time - if (searchTerm === '') { - sectionsList.push({ - title: undefined, - data: selectedOptions, - shouldShow: !_.isEmpty(selectedOptions), - indexOffset, - }); - indexOffset += selectedOptions.length; - } else { - // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details - // This will add them to the list of options, deduping them if they already exist in the other lists - const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { - const accountID = lodashGet(participant, 'accountID', null); - const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); - const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); - const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); - return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; - }); - - sectionsList.push({ - title: undefined, - data: selectedParticipantsWithoutDetails, - shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), - indexOffset, - }); - indexOffset += selectedParticipantsWithoutDetails.length; - } + indexOffset = OptionsListUtils.formatSectionsFromSearchTerm(searchTerm, sectionsList, selectedOptions, filteredRecentReports, filteredPersonalDetails, {}, false, indexOffset); if (maxParticipantsReached) { return sectionsList; From 688df1539642cda86473ad0a02a2d565615eabfd Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 13:34:47 -0700 Subject: [PATCH 07/11] prettier --- src/libs/OptionsListUtils.js | 102 ++++++++++-------- .../MoneyRequestParticipantsSelector.js | 13 ++- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index c7e83fad6d7a..8898f37a2cba 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1587,57 +1587,69 @@ function shouldOptionShowTooltip(option) { /** * Handles the logic for displaying selected participants from the search term - * @param {String} searchTerm - * @param {Array} sectionList - * @param {Array} selectedOptions - * @param {Array} filteredRecentReports - * @param {Array} filteredPersonalDetails + * @param {String} searchTerm + * @param {Array} sectionList + * @param {Array} selectedOptions + * @param {Array} filteredRecentReports + * @param {Array} filteredPersonalDetails * @param {Object} personalDetails * @param {Boolean} shouldGetOptionDetails - * @param {Number} indexOffset + * @param {Number} indexOffset * @returns {Number} newIndexOffset */ -function formatSectionsFromSearchTerm(searchTerm, sectionList, selectedOptions, filteredRecentReports, filteredPersonalDetails, personalDetails = {}, shouldGetOptionDetails = false, indexOffset) -{ - // We show the selected participants at the top of the list when there is no search term - // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results - // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time - let newIndexOffset = indexOffset; - if (searchTerm === '') { - sectionList.push({ - title: undefined, - data: shouldGetOptionDetails ? _.map(selectedOptions, (participant) => { - const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); - }) : selectedOptions, - shouldShow: !_.isEmpty(selectedOptions), - indexOffset, - }); - newIndexOffset += selectedOptions.length; - } else { - // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details - // This will add them to the list of options, deduping them if they already exist in the other lists - const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { - const accountID = lodashGet(participant, 'accountID', null); - const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); - const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); - const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); - return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; - }); +function formatSectionsFromSearchTerm( + searchTerm, + sectionList, + selectedOptions, + filteredRecentReports, + filteredPersonalDetails, + personalDetails = {}, + shouldGetOptionDetails = false, + indexOffset, +) { + // We show the selected participants at the top of the list when there is no search term + // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results + // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time + let newIndexOffset = indexOffset; + if (searchTerm === '') { + sectionList.push({ + title: undefined, + data: shouldGetOptionDetails + ? _.map(selectedOptions, (participant) => { + const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + }) + : selectedOptions, + shouldShow: !_.isEmpty(selectedOptions), + indexOffset, + }); + newIndexOffset += selectedOptions.length; + } else { + // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details + // This will add them to the list of options, deduping them if they already exist in the other lists + const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { + const accountID = lodashGet(participant, 'accountID', null); + const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); + const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); + const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); + return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; + }); - sectionList.push({ - title: undefined, - data: shouldGetOptionDetails ? _.map(selectedParticipantsWithoutDetails, (participant) => { - const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); - }) : selectedParticipantsWithoutDetails, - shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), - indexOffset, - }); - newIndexOffset += selectedParticipantsWithoutDetails.length; - } + sectionList.push({ + title: undefined, + data: shouldGetOptionDetails + ? _.map(selectedParticipantsWithoutDetails, (participant) => { + const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + }) + : selectedParticipantsWithoutDetails, + shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), + indexOffset, + }); + newIndexOffset += selectedParticipantsWithoutDetails.length; + } - return newIndexOffset; + return newIndexOffset; } export { diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index ff2eedc2cd37..a61df689cf13 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -103,8 +103,17 @@ function MoneyRequestParticipantsSelector({ const sections = useMemo(() => { const newSections = []; let indexOffset = 0; - - indexOffset = OptionsListUtils.formatSectionsFromSearchTerm(searchTerm, newSections, participants, newChatOptions.recentReports, newChatOptions.personalDetails, personalDetails, true, indexOffset); + + indexOffset = OptionsListUtils.formatSectionsFromSearchTerm( + searchTerm, + newSections, + participants, + newChatOptions.recentReports, + newChatOptions.personalDetails, + personalDetails, + true, + indexOffset, + ); if (maxParticipantsReached) { return newSections; From 89888a7d38a470e19a015dcbb938677da3e20bbd Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 13:55:29 -0700 Subject: [PATCH 08/11] Return more items --- src/libs/OptionsListUtils.js | 7 +++++-- src/pages/NewChatPage.js | 15 +++++++++++++-- .../MoneyRequestParticipantsSelector.js | 6 ++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 8898f37a2cba..5e9544653990 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1595,7 +1595,7 @@ function shouldOptionShowTooltip(option) { * @param {Object} personalDetails * @param {Boolean} shouldGetOptionDetails * @param {Number} indexOffset - * @returns {Number} newIndexOffset + * @returns {Object} */ function formatSectionsFromSearchTerm( searchTerm, @@ -1649,7 +1649,10 @@ function formatSectionsFromSearchTerm( newIndexOffset += selectedParticipantsWithoutDetails.length; } - return newIndexOffset; + return { + sectionList, + newIndexOffset, + }; } export { diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 1cc5c295d3e7..1d6fdccdb25d 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -69,10 +69,21 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails); const sections = useMemo(() => { - const sectionsList = []; + let sectionsList = []; let indexOffset = 0; - indexOffset = OptionsListUtils.formatSectionsFromSearchTerm(searchTerm, sectionsList, selectedOptions, filteredRecentReports, filteredPersonalDetails, {}, false, indexOffset); + const formatResults = OptionsListUtils.formatSectionsFromSearchTerm( + searchTerm, + sectionsList, + selectedOptions, + filteredRecentReports, + filteredPersonalDetails, + {}, + false, + indexOffset, + ); + sectionsList = formatResults.sectionsList; + indexOffset = formatResults.indexOffset; if (maxParticipantsReached) { return sectionsList; diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index a61df689cf13..1d62437ac633 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -101,10 +101,10 @@ function MoneyRequestParticipantsSelector({ * @returns {Array} */ const sections = useMemo(() => { - const newSections = []; + let newSections = []; let indexOffset = 0; - indexOffset = OptionsListUtils.formatSectionsFromSearchTerm( + const formatResults = OptionsListUtils.formatSectionsFromSearchTerm( searchTerm, newSections, participants, @@ -114,6 +114,8 @@ function MoneyRequestParticipantsSelector({ true, indexOffset, ); + indexOffset = formatResults.indexOffset; + newSections = formatResults.sectionList; if (maxParticipantsReached) { return newSections; From fbc90704894d6a2d9ab531d7fb87f193123ad928 Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 14:18:55 -0700 Subject: [PATCH 09/11] fix the throw on newChatPage --- src/pages/NewChatPage.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 1d6fdccdb25d..2212028cc1fd 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -3,7 +3,6 @@ import React, {useState, useEffect, useMemo, useCallback} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; import OptionsSelector from '../components/OptionsSelector'; import * as OptionsListUtils from '../libs/OptionsListUtils'; import Permissions from '../libs/Permissions'; @@ -82,7 +81,7 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i false, indexOffset, ); - sectionsList = formatResults.sectionsList; + sectionsList = formatResults.sectionList; indexOffset = formatResults.indexOffset; if (maxParticipantsReached) { From a3d3afbcbd2ba193313e9b16e8446a5bbacd331a Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 14:26:38 -0700 Subject: [PATCH 10/11] Remove the unneeded function param --- src/libs/OptionsListUtils.js | 19 +++++-------------- src/pages/NewChatPage.js | 13 ++----------- .../MoneyRequestParticipantsSelector.js | 3 +-- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 5e9544653990..2a7e03293cc8 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1588,7 +1588,6 @@ function shouldOptionShowTooltip(option) { /** * Handles the logic for displaying selected participants from the search term * @param {String} searchTerm - * @param {Array} sectionList * @param {Array} selectedOptions * @param {Array} filteredRecentReports * @param {Array} filteredPersonalDetails @@ -1597,22 +1596,14 @@ function shouldOptionShowTooltip(option) { * @param {Number} indexOffset * @returns {Object} */ -function formatSectionsFromSearchTerm( - searchTerm, - sectionList, - selectedOptions, - filteredRecentReports, - filteredPersonalDetails, - personalDetails = {}, - shouldGetOptionDetails = false, - indexOffset, -) { +function formatSectionsFromSearchTerm(searchTerm, selectedOptions, filteredRecentReports, filteredPersonalDetails, personalDetails = {}, shouldGetOptionDetails = false, indexOffset) { // We show the selected participants at the top of the list when there is no search term // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time let newIndexOffset = indexOffset; + const sections = []; if (searchTerm === '') { - sectionList.push({ + sections.push({ title: undefined, data: shouldGetOptionDetails ? _.map(selectedOptions, (participant) => { @@ -1635,7 +1626,7 @@ function formatSectionsFromSearchTerm( return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; }); - sectionList.push({ + sections.push({ title: undefined, data: shouldGetOptionDetails ? _.map(selectedParticipantsWithoutDetails, (participant) => { @@ -1650,7 +1641,7 @@ function formatSectionsFromSearchTerm( } return { - sectionList, + sectionList: sections, newIndexOffset, }; } diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 2212028cc1fd..fdff49558fc5 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -71,17 +71,8 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i let sectionsList = []; let indexOffset = 0; - const formatResults = OptionsListUtils.formatSectionsFromSearchTerm( - searchTerm, - sectionsList, - selectedOptions, - filteredRecentReports, - filteredPersonalDetails, - {}, - false, - indexOffset, - ); - sectionsList = formatResults.sectionList; + const formatResults = OptionsListUtils.formatSectionsFromSearchTerm(searchTerm, selectedOptions, filteredRecentReports, filteredPersonalDetails, {}, false, indexOffset); + sectionsList = sectionsList.concat(formatResults.sectionList); indexOffset = formatResults.indexOffset; if (maxParticipantsReached) { diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index 1d62437ac633..353911abf1b1 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -106,7 +106,6 @@ function MoneyRequestParticipantsSelector({ const formatResults = OptionsListUtils.formatSectionsFromSearchTerm( searchTerm, - newSections, participants, newChatOptions.recentReports, newChatOptions.personalDetails, @@ -115,7 +114,7 @@ function MoneyRequestParticipantsSelector({ indexOffset, ); indexOffset = formatResults.indexOffset; - newSections = formatResults.sectionList; + newSections = newSections.concat(formatResults.sectionList); if (maxParticipantsReached) { return newSections; From 39afd7ba62b13323fe4f091f7ed309cb8428c82a Mon Sep 17 00:00:00 2001 From: Jack Nam Date: Thu, 19 Oct 2023 14:36:31 -0700 Subject: [PATCH 11/11] Clean up the utility method --- src/libs/OptionsListUtils.js | 61 +++++++++---------- src/pages/NewChatPage.js | 6 +- .../MoneyRequestParticipantsSelector.js | 6 +- 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 2a7e03293cc8..00e00e3b4a17 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1600,33 +1600,35 @@ function formatSectionsFromSearchTerm(searchTerm, selectedOptions, filteredRecen // We show the selected participants at the top of the list when there is no search term // However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results // This clears up space on mobile views, where if you create a group with 4+ people you can't see the selected participants and the search results at the same time - let newIndexOffset = indexOffset; - const sections = []; if (searchTerm === '') { - sections.push({ - title: undefined, - data: shouldGetOptionDetails - ? _.map(selectedOptions, (participant) => { - const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); - }) - : selectedOptions, - shouldShow: !_.isEmpty(selectedOptions), - indexOffset, - }); - newIndexOffset += selectedOptions.length; - } else { - // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details - // This will add them to the list of options, deduping them if they already exist in the other lists - const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { - const accountID = lodashGet(participant, 'accountID', null); - const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); - const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); - const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); - return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; - }); + return { + section: { + title: undefined, + data: shouldGetOptionDetails + ? _.map(selectedOptions, (participant) => { + const isPolicyExpenseChat = lodashGet(participant, 'isPolicyExpenseChat', false); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant) : getParticipantsOption(participant, personalDetails); + }) + : selectedOptions, + shouldShow: !_.isEmpty(selectedOptions), + indexOffset, + }, + newIndexOffset: indexOffset + selectedOptions.length, + }; + } - sections.push({ + // If you select a new user you don't have a contact for, they won't get returned as part of a recent report or personal details + // This will add them to the list of options, deduping them if they already exist in the other lists + const selectedParticipantsWithoutDetails = _.filter(selectedOptions, (participant) => { + const accountID = lodashGet(participant, 'accountID', null); + const isPartOfSearchTerm = participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase()); + const isReportInRecentReports = _.some(filteredRecentReports, (report) => report.accountID === accountID); + const isReportInPersonalDetails = _.some(filteredPersonalDetails, (personalDetail) => personalDetail.accountID === accountID); + return isPartOfSearchTerm && !isReportInRecentReports && !isReportInPersonalDetails; + }); + + return { + section: { title: undefined, data: shouldGetOptionDetails ? _.map(selectedParticipantsWithoutDetails, (participant) => { @@ -1636,13 +1638,8 @@ function formatSectionsFromSearchTerm(searchTerm, selectedOptions, filteredRecen : selectedParticipantsWithoutDetails, shouldShow: !_.isEmpty(selectedParticipantsWithoutDetails), indexOffset, - }); - newIndexOffset += selectedParticipantsWithoutDetails.length; - } - - return { - sectionList: sections, - newIndexOffset, + }, + newIndexOffset: indexOffset + selectedParticipantsWithoutDetails.length, }; } diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index fdff49558fc5..9ee5f838aafd 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -68,12 +68,12 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails); const sections = useMemo(() => { - let sectionsList = []; + const sectionsList = []; let indexOffset = 0; const formatResults = OptionsListUtils.formatSectionsFromSearchTerm(searchTerm, selectedOptions, filteredRecentReports, filteredPersonalDetails, {}, false, indexOffset); - sectionsList = sectionsList.concat(formatResults.sectionList); - indexOffset = formatResults.indexOffset; + sectionsList.push(formatResults.section); + indexOffset = formatResults.newIndexOffset; if (maxParticipantsReached) { return sectionsList; diff --git a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js index 353911abf1b1..9f1e5a416995 100755 --- a/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js +++ b/src/pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsSelector.js @@ -101,7 +101,7 @@ function MoneyRequestParticipantsSelector({ * @returns {Array} */ const sections = useMemo(() => { - let newSections = []; + const newSections = []; let indexOffset = 0; const formatResults = OptionsListUtils.formatSectionsFromSearchTerm( @@ -113,8 +113,8 @@ function MoneyRequestParticipantsSelector({ true, indexOffset, ); - indexOffset = formatResults.indexOffset; - newSections = newSections.concat(formatResults.sectionList); + newSections.push(formatResults.section); + indexOffset = formatResults.newIndexOffset; if (maxParticipantsReached) { return newSections;