From ac67f552e9d3f90cd85fa8d50fe2fae6febcc60b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Thu, 10 Jul 2025 13:51:35 +0200 Subject: [PATCH 1/3] fix: show selected item first --- .../SelectionList/BaseSelectionList.tsx | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index f544a65442a97..70c5aeed28c37 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -186,8 +186,16 @@ function BaseSelectionList( const incrementPage = () => setCurrentPage((prev) => prev + 1); const isItemSelected = useCallback( - (item: TItem) => item.isSelected ?? ((isSelected?.(item) ?? selectedItems.includes(item.keyForList ?? '')) && canSelectMultiple), - [isSelected, selectedItems, canSelectMultiple], + (item: TItem) => { + if (item.isSelected !== undefined) { + return item.isSelected; + } + if (isSelected) { + return isSelected(item); + } + return selectedItems.includes(item.keyForList ?? ''); + }, + [isSelected, selectedItems], ); /** @@ -217,12 +225,20 @@ function BaseSelectionList( offset += sectionHeaderHeight; section.data?.forEach((item, optionIndex) => { - // Add item to the general flattened array - allOptions.push({ - ...item, - sectionIndex, - index: optionIndex, - }); + // Add item to the general flattened array. Selected items should be in front of the array. + if (isItemSelected(item) && !canSelectMultiple) { + allOptions.unshift({ + ...item, + sectionIndex, + index: 0, + }); + } else { + allOptions.push({ + ...item, + sectionIndex, + index: optionIndex, + }); + } // If disabled, add to the disabled indexes array const isItemDisabled = !!section.isDisabled || (item.isDisabled && !isItemSelected(item)); @@ -276,12 +292,34 @@ function BaseSelectionList( let remainingOptionsLimit = CONST.MAX_SELECTION_LIST_PAGE_LENGTH * currentPage; const processedSections = getSectionsWithIndexOffset( sections.map((section) => { - const data = !isEmpty(section.data) && remainingOptionsLimit > 0 ? section.data.slice(0, remainingOptionsLimit) : []; - remainingOptionsLimit -= data.length; + if (isEmpty(section.data) || remainingOptionsLimit <= 0) { + return { + ...section, + data: [], + }; + } + + let sectionData = section.data; + if (!canSelectMultiple) { + const sectionSelectedItems: TItem[] = []; + const sectionUnselectedItems: TItem[] = []; + section.data.forEach((item) => { + if (isItemSelected(item)) { + sectionSelectedItems.push(item); + } else { + sectionUnselectedItems.push(item); + } + }); + + sectionData = [...sectionSelectedItems, ...sectionUnselectedItems]; + } + + const slicedData = sectionData.slice(0, remainingOptionsLimit); + remainingOptionsLimit -= slicedData.length; return { ...section, - data, + data: slicedData, }; }), ); From aaf3afe3154c56c025f14201f172077d25804385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Thu, 10 Jul 2025 15:57:21 +0200 Subject: [PATCH 2/3] fix: load items up to selected option --- .../SelectionList/BaseSelectionList.tsx | 89 +++++++++---------- 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 70c5aeed28c37..b378f81da0bda 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -186,18 +186,39 @@ function BaseSelectionList( const incrementPage = () => setCurrentPage((prev) => prev + 1); const isItemSelected = useCallback( - (item: TItem) => { - if (item.isSelected !== undefined) { - return item.isSelected; - } - if (isSelected) { - return isSelected(item); - } - return selectedItems.includes(item.keyForList ?? ''); - }, - [isSelected, selectedItems], + (item: TItem) => item.isSelected ?? ((isSelected?.(item) ?? selectedItems.includes(item.keyForList ?? '')) && canSelectMultiple), + [isSelected, selectedItems, canSelectMultiple], ); + // Calculate initial page count so selected item is loaded + const initialPageCount = useMemo(() => { + if (canSelectMultiple || sections.length === 0) { + return 1; + } + + let currentIndex = 0; + for (const section of sections) { + if (section.data) { + for (const item of section.data) { + if (isItemSelected(item)) { + return Math.floor(currentIndex / CONST.MAX_SELECTION_LIST_PAGE_LENGTH) + 1; + } + currentIndex++; + } + } + } + + return 1; + }, [sections, canSelectMultiple, isItemSelected]); + + useEffect(() => { + if (initialPageCount < 1) { + return; + } + + setCurrentPage(initialPageCount); + }, [initialPageCount]); + /** * Iterates through the sections and items inside each section, and builds 4 arrays along the way: * - `allOptions`: Contains all the items in the list, flattened, regardless of section @@ -225,20 +246,12 @@ function BaseSelectionList( offset += sectionHeaderHeight; section.data?.forEach((item, optionIndex) => { - // Add item to the general flattened array. Selected items should be in front of the array. - if (isItemSelected(item) && !canSelectMultiple) { - allOptions.unshift({ - ...item, - sectionIndex, - index: 0, - }); - } else { - allOptions.push({ - ...item, - sectionIndex, - index: optionIndex, - }); - } + // Add item to the general flattened array + allOptions.push({ + ...item, + sectionIndex, + index: optionIndex, + }); // If disabled, add to the disabled indexes array const isItemDisabled = !!section.isDisabled || (item.isDisabled && !isItemSelected(item)); @@ -292,34 +305,12 @@ function BaseSelectionList( let remainingOptionsLimit = CONST.MAX_SELECTION_LIST_PAGE_LENGTH * currentPage; const processedSections = getSectionsWithIndexOffset( sections.map((section) => { - if (isEmpty(section.data) || remainingOptionsLimit <= 0) { - return { - ...section, - data: [], - }; - } - - let sectionData = section.data; - if (!canSelectMultiple) { - const sectionSelectedItems: TItem[] = []; - const sectionUnselectedItems: TItem[] = []; - section.data.forEach((item) => { - if (isItemSelected(item)) { - sectionSelectedItems.push(item); - } else { - sectionUnselectedItems.push(item); - } - }); - - sectionData = [...sectionSelectedItems, ...sectionUnselectedItems]; - } - - const slicedData = sectionData.slice(0, remainingOptionsLimit); - remainingOptionsLimit -= slicedData.length; + const data = !isEmpty(section.data) && remainingOptionsLimit > 0 ? section.data.slice(0, remainingOptionsLimit) : []; + remainingOptionsLimit -= data.length; return { ...section, - data: slicedData, + data, }; }), ); From 53f398e744ccc11d21909b6ac68e9040d14119f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Thu, 10 Jul 2025 16:00:47 +0200 Subject: [PATCH 3/3] fix: restore --- Mobile-Expensify | 2 +- src/CONST/index.ts | 2 +- src/components/SelectionList/BaseSelectionList.tsx | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 32922dcca0de2..63d6c7944e420 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 32922dcca0de2dae6060cfccb1a3a40f1397c68b +Subproject commit 63d6c7944e4201ad488835fa9131f29b20a65580 diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 7babab52b0e19..4ce75a44e6ea6 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -5191,7 +5191,7 @@ const CONST = { * The maximum count of items per page for SelectionList. * When paginate, it multiplies by page number. */ - MAX_SELECTION_LIST_PAGE_LENGTH: 500, + MAX_SELECTION_LIST_PAGE_LENGTH: 50, /** * Bank account names diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index b8bb481ba429d..e0790727cb938 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -806,7 +806,9 @@ function BaseSelectionList( : 0; // Reset the current page to 1 when the user types something - setCurrentPage(1); + if (prevTextInputValue !== textInputValue) { + setCurrentPage(1); + } updateAndScrollToFocusedIndex(newSelectedIndex); }, [