1- import { useIsFocused } from '@react-navigation/native' ;
1+ import { useIsFocused , useRoute } from '@react-navigation/native' ;
22import { FlashList } from '@shopify/flash-list' ;
33import type { FlashListProps , ViewToken } from '@shopify/flash-list' ;
4- import React , { forwardRef , useCallback , useEffect , useImperativeHandle , useMemo , useRef , useState } from 'react' ;
4+ import React , { forwardRef , useCallback , useContext , useEffect , useImperativeHandle , useMemo , useRef , useState } from 'react' ;
55import type { ForwardedRef } from 'react' ;
66import { View } from 'react-native' ;
77import type { NativeSyntheticEvent , StyleProp , ViewStyle } from 'react-native' ;
@@ -12,6 +12,7 @@ import MenuItem from '@components/MenuItem';
1212import Modal from '@components/Modal' ;
1313import { usePersonalDetails } from '@components/OnyxListItemProvider' ;
1414import { PressableWithFeedback } from '@components/Pressable' ;
15+ import { ScrollOffsetContext } from '@components/ScrollOffsetContextProvider' ;
1516import type ChatListItem from '@components/SelectionList/ChatListItem' ;
1617import type TaskListItem from '@components/SelectionList/Search/TaskListItem' ;
1718import type TransactionGroupListItem from '@components/SelectionList/Search/TransactionGroupListItem' ;
@@ -182,6 +183,9 @@ function SearchList(
182183 const [ isUserValidated ] = useOnyx ( ONYXKEYS . ACCOUNT , { selector : ( account ) => account ?. validated , canBeMissing : true } ) ;
183184 const [ userBillingFundID ] = useOnyx ( ONYXKEYS . NVP_BILLING_FUND_ID , { canBeMissing : true } ) ;
184185
186+ const route = useRoute ( ) ;
187+ const { saveScrollOffset, getScrollOffset} = useContext ( ScrollOffsetContext ) ;
188+
185189 const handleLongPressRow = useCallback (
186190 ( item : SearchListItem ) => {
187191 // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
@@ -420,6 +424,39 @@ function SearchList(
420424 } ;
421425 } , [ calculatedListHeight , calculatedListWidth ] ) ;
422426
427+ const handleScroll = useCallback < NonNullable < FlashListProps < SearchListItem > [ 'onScroll' ] > > (
428+ ( e ) => {
429+ if ( onScroll && typeof onScroll === 'function' ) {
430+ onScroll ( e ) ;
431+ }
432+
433+ if ( e . nativeEvent . layoutMeasurement . height > 0 ) {
434+ saveScrollOffset ( route , e . nativeEvent . contentOffset . y ) ;
435+ }
436+ } ,
437+ [ onScroll , route , saveScrollOffset ] ,
438+ ) ;
439+
440+ const handleLayout = useCallback ( ( ) => {
441+ if ( onLayout && typeof onLayout === 'function' ) {
442+ onLayout ( ) ;
443+ }
444+
445+ const offset = getScrollOffset ( route ) ;
446+ if ( ! offset || ! listRef . current ) {
447+ return ;
448+ }
449+
450+ // Use requestAnimationFrame to ensure proper scrolling on iOS
451+ requestAnimationFrame ( ( ) => {
452+ if ( ! offset || ! listRef . current ) {
453+ return ;
454+ }
455+
456+ listRef . current . scrollToOffset ( { offset} ) ;
457+ } ) ;
458+ } , [ onLayout , getScrollOffset , route ] ) ;
459+
423460 return (
424461 < View style = { [ styles . flex1 , ! isKeyboardShown && safeAreaPaddingBottomStyle , containerStyle ] } >
425462 { tableHeaderVisible && (
@@ -457,15 +494,15 @@ function SearchList(
457494 data = { data }
458495 renderItem = { renderItem }
459496 keyExtractor = { keyExtractor }
460- onScroll = { onScroll }
497+ onScroll = { handleScroll }
461498 showsVerticalScrollIndicator = { false }
462499 ref = { listRef }
463500 extraData = { [ focusedIndex , isFocused ] }
464501 onEndReached = { onEndReached }
465502 onEndReachedThreshold = { onEndReachedThreshold }
466503 ListFooterComponent = { ListFooterComponent }
467504 onViewableItemsChanged = { onViewableItemsChanged }
468- onLayout = { onLayout }
505+ onLayout = { handleLayout }
469506 removeClippedSubviews
470507 drawDistance = { 1000 }
471508 estimatedItemSize = { estimatedItemSize }
0 commit comments