From c2fdd48bb649fb30ffd798a9cc02a5c25f3363a0 Mon Sep 17 00:00:00 2001 From: daledah Date: Mon, 14 Oct 2024 13:52:41 +0700 Subject: [PATCH 1/2] fix: header flickering on selection mode and fix regressions --- src/components/Search/index.tsx | 8 +++- .../SelectionListWithModal/index.tsx | 44 ++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 2f4f239cbf2b..670cfef54df8 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -93,7 +93,7 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr const lastSearchResultsRef = useRef>(); const {setCurrentSearchHash, setSelectedTransactions, selectedTransactions, clearSelectedTransactions, setShouldShowStatusBarLoading, lastSearchType, setLastSearchType} = useSearchContext(); - const {selectionMode} = useMobileSelectionMode(); + const {selectionMode} = useMobileSelectionMode(false); const [offset, setOffset] = useState(0); const {type, status, sortBy, sortOrder, hash} = queryJSON; @@ -400,6 +400,12 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr /> ) } + isSelected={(item) => + status !== CONST.SEARCH.STATUS.EXPENSE.ALL && SearchUtils.isReportListItemType(item) + ? item.transactions.some((transaction) => selectedTransactions[transaction.keyForList]?.isSelected) + : !!item.isSelected + } + shouldAutoTurnOff={false} onScroll={onSearchListScroll} canSelectMultiple={type !== CONST.SEARCH.DATA_TYPES.CHAT && canSelectMultiple} customListHeaderHeight={searchHeaderHeight} diff --git a/src/components/SelectionListWithModal/index.tsx b/src/components/SelectionListWithModal/index.tsx index 2d218bc815fe..12d8f1ff9071 100644 --- a/src/components/SelectionListWithModal/index.tsx +++ b/src/components/SelectionListWithModal/index.tsx @@ -1,5 +1,6 @@ +import {useIsFocused} from '@react-navigation/native'; import type {ForwardedRef} from 'react'; -import React, {forwardRef, useEffect, useState} from 'react'; +import React, {forwardRef, useEffect, useRef, useState} from 'react'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; import Modal from '@components/Modal'; @@ -14,10 +15,12 @@ import CONST from '@src/CONST'; type SelectionListWithModalProps = BaseSelectionListProps & { turnOnSelectionModeOnLongPress?: boolean; onTurnOnSelectionMode?: (item: TItem | null) => void; + shouldAutoTurnOff?: boolean; + isSelected?: (item: TItem) => boolean; }; function SelectionListWithModal( - {turnOnSelectionModeOnLongPress, onTurnOnSelectionMode, onLongPressRow, sections, ...rest}: SelectionListWithModalProps, + {turnOnSelectionModeOnLongPress, onTurnOnSelectionMode, onLongPressRow, sections, shouldAutoTurnOff, isSelected, ...rest}: SelectionListWithModalProps, ref: ForwardedRef, ) { const [isModalVisible, setIsModalVisible] = useState(false); @@ -26,21 +29,52 @@ function SelectionListWithModal( // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout here because there is a race condition that causes shouldUseNarrowLayout to change indefinitely in this component // See https://github.com/Expensify/App/issues/48675 for more details const {isSmallScreenWidth} = useResponsiveLayout(); - const {selectionMode} = useMobileSelectionMode(true); + const isFocused = useIsFocused(); + + const {selectionMode} = useMobileSelectionMode(shouldAutoTurnOff); + // Check if selection should be on when the modal is opened + const wasSelectionOnRef = useRef(false); + // Keep track of the number of selected items to determine if we should turn off selection mode + const selectionRef = useRef(0); useEffect(() => { // We can access 0 index safely as we are not displaying multiple sections in table view - const selectedItems = sections[0].data.filter((item) => item.isSelected); + const selectedItems = sections[0].data.filter((item) => { + if (isSelected) { + return isSelected(item); + } + return !!item.isSelected; + }); + selectionRef.current = selectedItems.length; + if (!isSmallScreenWidth) { if (selectedItems.length === 0) { turnOffMobileSelectionMode(); } return; } + if (!isFocused && isSmallScreenWidth) { + return; + } + if (!wasSelectionOnRef.current && selectedItems.length > 0) { + wasSelectionOnRef.current = true; + } if (selectedItems.length > 0 && !selectionMode?.isEnabled) { turnOnMobileSelectionMode(); + } else if (selectedItems.length === 0 && selectionMode?.isEnabled && !wasSelectionOnRef.current) { + turnOffMobileSelectionMode(); } - }, [sections, selectionMode, isSmallScreenWidth]); + }, [sections, selectionMode, isSmallScreenWidth, isSelected, isFocused]); + + useEffect( + () => () => { + if (selectionRef.current !== 0) { + return; + } + turnOffMobileSelectionMode(); + }, + [], + ); const handleLongPressRow = (item: TItem) => { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing From 8616d295ad861f5a764b1449c03c581c9fe82126 Mon Sep 17 00:00:00 2001 From: daledah Date: Mon, 14 Oct 2024 16:56:55 +0700 Subject: [PATCH 2/2] fix: remove redundant condition --- src/components/SelectionListWithModal/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionListWithModal/index.tsx b/src/components/SelectionListWithModal/index.tsx index 12d8f1ff9071..46d6494d1d21 100644 --- a/src/components/SelectionListWithModal/index.tsx +++ b/src/components/SelectionListWithModal/index.tsx @@ -53,7 +53,7 @@ function SelectionListWithModal( } return; } - if (!isFocused && isSmallScreenWidth) { + if (!isFocused) { return; } if (!wasSelectionOnRef.current && selectedItems.length > 0) {