@@ -8,7 +8,7 @@ import {DeviceEventEmitter, InteractionManager, View} from 'react-native';
88import type { OnyxEntry } from 'react-native-onyx' ;
99import { renderScrollComponent as renderActionSheetAwareScrollView } from '@components/ActionSheetAwareScrollView' ;
1010import Button from '@components/Button' ;
11- import FlatList from '@components/FlatList/FlatList ' ;
11+ import FlatListWithScrollKey from '@components/FlatList/FlatListWithScrollKey ' ;
1212import { usePersonalDetails } from '@components/OnyxListItemProvider' ;
1313import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView' ;
1414import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' ;
@@ -242,6 +242,8 @@ function ReportActionsList({
242242 } , [ ] ) ;
243243
244244 const scrollingVerticalOffset = useRef ( 0 ) ;
245+ const hasTriggeredTopPagination = useRef ( false ) ;
246+ const hasTriggeredBottomPagination = useRef ( false ) ;
245247 const readActionSkipped = useRef ( false ) ;
246248 const hasHeaderRendered = useRef ( false ) ;
247249 const linkedReportActionID = route ?. params ?. reportActionID ;
@@ -382,6 +384,44 @@ function ReportActionsList({
382384 hasNewestReportActionRef . current = hasNewestReportAction ;
383385 const sortedVisibleReportActionsRef = useRef ( sortedVisibleReportActions ) ;
384386
387+ const maybeLoadChatsOnScroll = useCallback (
388+ ( event : NativeSyntheticEvent < NativeScrollEvent > ) => {
389+ const {
390+ contentOffset : { y} ,
391+ contentSize : { height : contentHeight } ,
392+ layoutMeasurement : { height : layoutHeight } ,
393+ } = event . nativeEvent ;
394+
395+ const distanceFromTop = y ;
396+ const distanceFromBottom = contentHeight - layoutHeight - y ;
397+
398+ if ( distanceFromTop <= 0 ) {
399+ if ( ! hasTriggeredTopPagination . current ) {
400+ hasTriggeredTopPagination . current = true ;
401+ loadNewerChats ( false ) ;
402+ }
403+ } else {
404+ hasTriggeredTopPagination . current = false ;
405+ }
406+
407+ if ( distanceFromBottom <= 0 ) {
408+ if ( ! hasTriggeredBottomPagination . current ) {
409+ hasTriggeredBottomPagination . current = true ;
410+ if ( ! isSearchTopmostFullScreenRoute ( ) ) {
411+ loadOlderChats ( false ) ;
412+ return ;
413+ }
414+
415+ // eslint-disable-next-line @typescript-eslint/no-deprecated
416+ InteractionManager . runAfterInteractions ( ( ) => requestAnimationFrame ( ( ) => loadOlderChats ( false ) ) ) ;
417+ }
418+ } else {
419+ hasTriggeredBottomPagination . current = false ;
420+ }
421+ } ,
422+ [ loadNewerChats , loadOlderChats ] ,
423+ ) ;
424+
385425 const { isFloatingMessageCounterVisible, setIsFloatingMessageCounterVisible, trackVerticalScrolling, onViewableItemsChanged} = useReportUnreadMessageScrollTracking ( {
386426 reportID : report . reportID ,
387427 currentVerticalScrollingOffsetRef : scrollingVerticalOffset ,
@@ -390,6 +430,7 @@ function ReportActionsList({
390430 isInverted : false ,
391431 onTrackScrolling : ( event : NativeSyntheticEvent < NativeScrollEvent > ) => {
392432 scrollingVerticalOffset . current = event . nativeEvent . contentOffset . y ;
433+ maybeLoadChatsOnScroll ( event ) ;
393434 onScroll ?.( event ) ;
394435 if ( shouldScrollToEndAfterLayout && ( ! hasCreatedActionAdded || isOffline ) ) {
395436 setShouldScrollToEndAfterLayout ( false ) ;
@@ -874,20 +915,6 @@ function ReportActionsList({
874915 ) ;
875916 } , [ hideComposer , initialNumToRender , renderItem , shouldShowReportRecipientLocalTime , sortedVisibleReportActions , styles ] ) ;
876917
877- const onStartReached = useCallback ( ( ) => {
878- if ( ! isSearchTopmostFullScreenRoute ( ) ) {
879- loadOlderChats ( false ) ;
880- return ;
881- }
882-
883- // eslint-disable-next-line @typescript-eslint/no-deprecated
884- InteractionManager . runAfterInteractions ( ( ) => requestAnimationFrame ( ( ) => loadOlderChats ( false ) ) ) ;
885- } , [ loadOlderChats ] ) ;
886-
887- const onEndReached = useCallback ( ( ) => {
888- loadNewerChats ( false ) ;
889- } , [ loadNewerChats ] ) ;
890-
891918 const renderFlatListItem = useCallback (
892919 ( { item} : ListRenderItemInfo < OnyxTypes . ReportAction > ) => {
893920 const originalIndex = sortedVisibleReportActions . findIndex ( ( action ) => action . reportActionID === item . reportActionID ) ;
@@ -908,7 +935,7 @@ function ReportActionsList({
908935 fsClass = { reportActionsListFSClass }
909936 >
910937 { shouldScrollToEndAfterLayout && topReportAction ? renderTopReportActions ( ) : undefined }
911- < FlatList
938+ < FlatListWithScrollKey
912939 accessibilityLabel = { translate ( 'sidebarScreen.listOfChatMessages' ) }
913940 ref = { reportScrollManager . ref }
914941 testID = "report-actions-list"
@@ -922,9 +949,7 @@ function ReportActionsList({
922949 showsVerticalScrollIndicator = { ! shouldScrollToEndAfterLayout }
923950 keyExtractor = { keyExtractor }
924951 initialNumToRender = { initialNumToRender }
925- onEndReached = { onEndReached }
926952 onEndReachedThreshold = { 0.75 }
927- onStartReached = { onStartReached }
928953 onStartReachedThreshold = { 0.75 }
929954 ListHeaderComponent = { listHeaderComponent }
930955 ListFooterComponent = { listFooterComponent }
@@ -935,6 +960,7 @@ function ReportActionsList({
935960 onScrollToIndexFailed = { onScrollToIndexFailed }
936961 extraData = { extraData }
937962 key = { listID }
963+ initialScrollKey = { linkedReportActionID }
938964 onContentSizeChange = { ( ) => {
939965 trackVerticalScrolling ( undefined ) ;
940966 } }
0 commit comments