@@ -14,6 +14,7 @@ import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
14
14
import useNetwork from '@hooks/useNetwork' ;
15
15
import usePrevious from '@hooks/usePrevious' ;
16
16
import useResponsiveLayout from '@hooks/useResponsiveLayout' ;
17
+ import useSearchHighlightAndScroll from '@hooks/useSearchHighlightAndScroll' ;
17
18
import useThemeStyles from '@hooks/useThemeStyles' ;
18
19
import { turnOffMobileSelectionMode , turnOnMobileSelectionMode } from '@libs/actions/MobileSelectionMode' ;
19
20
import * as SearchActions from '@libs/actions/Search' ;
@@ -49,19 +50,26 @@ function mapTransactionItemToSelectedEntry(item: TransactionListItemType): [stri
49
50
return [ item . keyForList , { isSelected : true , canDelete : item . canDelete , canHold : item . canHold , canUnhold : item . canUnhold , action : item . action } ] ;
50
51
}
51
52
52
- function mapToTransactionItemWithSelectionInfo ( item : TransactionListItemType , selectedTransactions : SelectedTransactions , canSelectMultiple : boolean ) {
53
- return { ...item , isSelected : selectedTransactions [ item . keyForList ] ?. isSelected && canSelectMultiple } ;
53
+ function mapToTransactionItemWithSelectionInfo ( item : TransactionListItemType , selectedTransactions : SelectedTransactions , canSelectMultiple : boolean , shouldAnimateInHighlight : boolean ) {
54
+ return { ...item , shouldAnimateInHighlight , isSelected : selectedTransactions [ item . keyForList ] ?. isSelected && canSelectMultiple } ;
54
55
}
55
56
56
- function mapToItemWithSelectionInfo ( item : TransactionListItemType | ReportListItemType | ReportActionListItemType , selectedTransactions : SelectedTransactions , canSelectMultiple : boolean ) {
57
+ function mapToItemWithSelectionInfo (
58
+ item : TransactionListItemType | ReportListItemType | ReportActionListItemType ,
59
+ selectedTransactions : SelectedTransactions ,
60
+ canSelectMultiple : boolean ,
61
+ shouldAnimateInHighlight : boolean ,
62
+ ) {
57
63
if ( SearchUtils . isReportActionListItemType ( item ) ) {
58
64
return item ;
59
65
}
66
+
60
67
return SearchUtils . isTransactionListItemType ( item )
61
- ? mapToTransactionItemWithSelectionInfo ( item , selectedTransactions , canSelectMultiple )
68
+ ? mapToTransactionItemWithSelectionInfo ( item , selectedTransactions , canSelectMultiple , shouldAnimateInHighlight )
62
69
: {
63
70
...item ,
64
- transactions : item . transactions ?. map ( ( transaction ) => mapToTransactionItemWithSelectionInfo ( transaction , selectedTransactions , canSelectMultiple ) ) ,
71
+ shouldAnimateInHighlight,
72
+ transactions : item . transactions ?. map ( ( transaction ) => mapToTransactionItemWithSelectionInfo ( transaction , selectedTransactions , canSelectMultiple , shouldAnimateInHighlight ) ) ,
65
73
isSelected : item . transactions . every ( ( transaction ) => selectedTransactions [ transaction . keyForList ] ?. isSelected && canSelectMultiple ) ,
66
74
} ;
67
75
}
@@ -90,6 +98,8 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr
90
98
const { type, status, sortBy, sortOrder, hash} = queryJSON ;
91
99
92
100
const [ currentSearchResults ] = useOnyx ( `${ ONYXKEYS . COLLECTION . SNAPSHOT } ${ hash } ` ) ;
101
+ const [ transactions ] = useOnyx ( ONYXKEYS . COLLECTION . TRANSACTION ) ;
102
+ const previousTransactions = usePrevious ( transactions ) ;
93
103
94
104
const canSelectMultiple = isSmallScreenWidth ? ! ! selectionMode ?. isEnabled : true ;
95
105
@@ -117,7 +127,6 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr
117
127
}
118
128
119
129
SearchActions . search ( { queryJSON, offset} ) ;
120
- // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
121
130
} , [ isOffline , offset , queryJSON ] ) ;
122
131
123
132
const getItemHeight = useCallback (
@@ -156,6 +165,14 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr
156
165
157
166
const searchResults = currentSearchResults ?. data ? currentSearchResults : lastSearchResultsRef . current ;
158
167
168
+ const { newSearchResultKey, handleSelectionListScroll} = useSearchHighlightAndScroll ( {
169
+ searchResults,
170
+ transactions,
171
+ previousTransactions,
172
+ queryJSON,
173
+ offset,
174
+ } ) ;
175
+
159
176
// There's a race condition in Onyx which makes it return data from the previous Search, so in addition to checking that the data is loaded
160
177
// we also need to check that the searchResults matches the type and status of the current search
161
178
const isDataLoaded = searchResults ?. data !== undefined && searchResults ?. search ?. type === type && searchResults ?. search ?. status === status ;
@@ -193,7 +210,20 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr
193
210
const ListItem = SearchUtils . getListItem ( type , status ) ;
194
211
const data = SearchUtils . getSections ( type , status , searchResults . data , searchResults . search ) ;
195
212
const sortedData = SearchUtils . getSortedSections ( type , status , data , sortBy , sortOrder ) ;
196
- const sortedSelectedData = sortedData . map ( ( item ) => mapToItemWithSelectionInfo ( item , selectedTransactions , canSelectMultiple ) ) ;
213
+ const sortedSelectedData = sortedData . map ( ( item ) => {
214
+ const baseKey = `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ ( item as TransactionListItemType ) . transactionID } ` ;
215
+ // Check if the base key matches the newSearchResultKey (TransactionListItemType)
216
+ const isBaseKeyMatch = baseKey === newSearchResultKey ;
217
+ // Check if any transaction within the transactions array (ReportListItemType) matches the newSearchResultKey
218
+ const isAnyTransactionMatch = ( item as ReportListItemType ) ?. transactions ?. some ( ( transaction ) => {
219
+ const transactionKey = `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ transaction . transactionID } ` ;
220
+ return transactionKey === newSearchResultKey ;
221
+ } ) ;
222
+ // Determine if either the base key or any transaction key matches
223
+ const shouldAnimateInHighlight = isBaseKeyMatch || isAnyTransactionMatch ;
224
+
225
+ return mapToItemWithSelectionInfo ( item , selectedTransactions , canSelectMultiple , shouldAnimateInHighlight ) ;
226
+ } ) ;
197
227
198
228
const shouldShowEmptyState = ! isDataLoaded || data . length === 0 ;
199
229
@@ -299,6 +329,7 @@ function Search({queryJSON, onSearchListScroll, contentContainerStyle}: SearchPr
299
329
300
330
return (
301
331
< SelectionListWithModal < ReportListItemType | TransactionListItemType | ReportActionListItemType >
332
+ ref = { handleSelectionListScroll ( sortedSelectedData ) }
302
333
sections = { [ { data : sortedSelectedData , isDisabled : false } ] }
303
334
turnOnSelectionModeOnLongPress = { type !== CONST . SEARCH . DATA_TYPES . CHAT }
304
335
onTurnOnSelectionMode = { ( item ) => item && toggleTransaction ( item ) }
0 commit comments