From 15546b6fa2aad0e74d8822bcaecebbf9b4187287 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Fri, 26 Jul 2024 12:18:56 -0400 Subject: [PATCH 1/7] Fix onStartReached not called in some cases --- ...zed-lists+0.73.4+002+osr-improvement.patch | 85 +++++++++- ...tive-web+0.19.12+005+osr-improvement.patch | 150 +++++++++++++++++- 2 files changed, 226 insertions(+), 9 deletions(-) diff --git a/patches/@react-native+virtualized-lists+0.73.4+002+osr-improvement.patch b/patches/@react-native+virtualized-lists+0.73.4+002+osr-improvement.patch index dc45a6758d5c..38871a2e7764 100644 --- a/patches/@react-native+virtualized-lists+0.73.4+002+osr-improvement.patch +++ b/patches/@react-native+virtualized-lists+0.73.4+002+osr-improvement.patch @@ -1,8 +1,87 @@ diff --git a/node_modules/@react-native/virtualized-lists/Lists/VirtualizedList.js b/node_modules/@react-native/virtualized-lists/Lists/VirtualizedList.js -index e338d90..70a59bf 100644 +index e338d90..238989f 100644 --- a/node_modules/@react-native/virtualized-lists/Lists/VirtualizedList.js +++ b/node_modules/@react-native/virtualized-lists/Lists/VirtualizedList.js -@@ -1219,7 +1219,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -89,6 +89,7 @@ type State = { + firstVisibleItemKey: ?string, + // When > 0 the scroll position available in JS is considered stale and should not be used. + pendingScrollUpdateCount: number, ++ lastItemCount: number, + }; + + function getScrollingThreshold(threshold: number, visibleLength: number) { +@@ -404,12 +405,13 @@ class VirtualizedList extends StateSafePureComponent { + + const minIndexForVisible = + this.props.maintainVisibleContentPosition?.minIndexForVisible ?? 0; ++ const itemCount = this.props.getItemCount(this.props.data); + + this.state = { + cellsAroundViewport: initialRenderRegion, + renderMask: VirtualizedList._createRenderMask(props, initialRenderRegion), + firstVisibleItemKey: +- this.props.getItemCount(this.props.data) > minIndexForVisible ++ itemCount > minIndexForVisible + ? VirtualizedList._getItemKey(this.props, minIndexForVisible) + : null, + // When we have a non-zero initialScrollIndex, we will receive a +@@ -420,6 +422,7 @@ class VirtualizedList extends StateSafePureComponent { + this.props.initialScrollIndex > 0 + ? 1 + : 0, ++ lastItemCount: itemCount, + }; + } + +@@ -701,16 +704,15 @@ class VirtualizedList extends StateSafePureComponent { + // first and last could be stale (e.g. if a new, shorter items props is passed in), so we make + // sure we're rendering a reasonable range here. + const itemCount = newProps.getItemCount(newProps.data); +- if (itemCount === prevState.renderMask.numCells()) { ++ if (itemCount === prevState.renderMask.numCells() && itemCount === prevState.lastItemCount) { + return prevState; + } +- + let maintainVisibleContentPositionAdjustment: ?number = null; + const prevFirstVisibleItemKey = prevState.firstVisibleItemKey; + const minIndexForVisible = + newProps.maintainVisibleContentPosition?.minIndexForVisible ?? 0; + const newFirstVisibleItemKey = +- newProps.getItemCount(newProps.data) > minIndexForVisible ++ itemCount > minIndexForVisible + ? VirtualizedList._getItemKey(newProps, minIndexForVisible) + : null; + if ( +@@ -758,6 +760,7 @@ class VirtualizedList extends StateSafePureComponent { + maintainVisibleContentPositionAdjustment != null + ? prevState.pendingScrollUpdateCount + 1 + : prevState.pendingScrollUpdateCount, ++ lastItemCount: itemCount, + }; + } + +@@ -1159,7 +1162,7 @@ class VirtualizedList extends StateSafePureComponent { + } + } + +- componentDidUpdate(prevProps: Props) { ++ componentDidUpdate(prevProps: Props, prevState: State) { + const {data, extraData} = this.props; + if (data !== prevProps.data || extraData !== prevProps.extraData) { + // clear the viewableIndices cache to also trigger +@@ -1181,6 +1184,11 @@ class VirtualizedList extends StateSafePureComponent { + if (hiPriInProgress) { + this._hiPriInProgress = false; + } ++ ++ if (this.state.cellsAroundViewport.first !== prevState.cellsAroundViewport.first || ++ this.state.cellsAroundViewport.last !== prevState.cellsAroundViewport.last) { ++ this._maybeCallOnEdgeReached(); ++ } + } + + _cellRefs: {[string]: null | CellRenderer} = {}; +@@ -1219,7 +1227,7 @@ class VirtualizedList extends StateSafePureComponent { zoomScale: 1, }; _scrollRef: ?React.ElementRef = null; @@ -11,7 +90,7 @@ index e338d90..70a59bf 100644 _sentEndForContentLength = 0; _updateCellsToRenderBatcher: Batchinator; _viewabilityTuples: Array = []; -@@ -1550,16 +1550,16 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1550,16 +1558,16 @@ class VirtualizedList extends StateSafePureComponent { onStartReached != null && this.state.cellsAroundViewport.first === 0 && isWithinStartThreshold && diff --git a/patches/react-native-web+0.19.12+005+osr-improvement.patch b/patches/react-native-web+0.19.12+005+osr-improvement.patch index 074cac3d0e6f..b1afa699e7a2 100644 --- a/patches/react-native-web+0.19.12+005+osr-improvement.patch +++ b/patches/react-native-web+0.19.12+005+osr-improvement.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js -index b05da08..80aea85 100644 +index bede95b..2aef4c6 100644 --- a/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js +++ b/node_modules/react-native-web/dist/vendor/react-native/VirtualizedList/index.js @@ -332,7 +332,7 @@ class VirtualizedList extends StateSafePureComponent { @@ -11,7 +11,75 @@ index b05da08..80aea85 100644 this._sentEndForContentLength = 0; this._totalCellLength = 0; this._totalCellsMeasured = 0; -@@ -1397,8 +1397,8 @@ class VirtualizedList extends StateSafePureComponent { +@@ -684,16 +684,18 @@ class VirtualizedList extends StateSafePureComponent { + }); + } + } ++ var itemCount = this.props.getItemCount(this.props.data); + var initialRenderRegion = VirtualizedList._initialRenderRegion(_props); + var minIndexForVisible = (_this$props$maintainV = (_this$props$maintainV2 = this.props.maintainVisibleContentPosition) == null ? void 0 : _this$props$maintainV2.minIndexForVisible) !== null && _this$props$maintainV !== void 0 ? _this$props$maintainV : 0; + this.state = { + cellsAroundViewport: initialRenderRegion, + renderMask: VirtualizedList._createRenderMask(_props, initialRenderRegion), +- firstVisibleItemKey: this.props.getItemCount(this.props.data) > minIndexForVisible ? VirtualizedList._getItemKey(this.props, minIndexForVisible) : null, ++ firstVisibleItemKey: itemCount > minIndexForVisible ? VirtualizedList._getItemKey(this.props, minIndexForVisible) : null, + // When we have a non-zero initialScrollIndex, we will receive a + // scroll event later so this will prevent the window from updating + // until we get a valid offset. +- pendingScrollUpdateCount: this.props.initialScrollIndex != null && this.props.initialScrollIndex > 0 ? 1 : 0 ++ pendingScrollUpdateCount: this.props.initialScrollIndex != null && this.props.initialScrollIndex > 0 ? 1 : 0, ++ lastItemCount: itemCount + }; + + // REACT-NATIVE-WEB patch to preserve during future RN merges: Support inverted wheel scroller. +@@ -919,13 +921,13 @@ class VirtualizedList extends StateSafePureComponent { + // first and last could be stale (e.g. if a new, shorter items props is passed in), so we make + // sure we're rendering a reasonable range here. + var itemCount = newProps.getItemCount(newProps.data); +- if (itemCount === prevState.renderMask.numCells()) { ++ if (itemCount === prevState.renderMask.numCells() && itemCount === prevState.lastItemCount) { + return prevState; + } + var maintainVisibleContentPositionAdjustment = null; + var prevFirstVisibleItemKey = prevState.firstVisibleItemKey; + var minIndexForVisible = (_newProps$maintainVis = (_newProps$maintainVis2 = newProps.maintainVisibleContentPosition) == null ? void 0 : _newProps$maintainVis2.minIndexForVisible) !== null && _newProps$maintainVis !== void 0 ? _newProps$maintainVis : 0; +- var newFirstVisibleItemKey = newProps.getItemCount(newProps.data) > minIndexForVisible ? VirtualizedList._getItemKey(newProps, minIndexForVisible) : null; ++ var newFirstVisibleItemKey = itemCount > minIndexForVisible ? VirtualizedList._getItemKey(newProps, minIndexForVisible) : null; + if (newProps.maintainVisibleContentPosition != null && prevFirstVisibleItemKey != null && newFirstVisibleItemKey != null) { + if (newFirstVisibleItemKey !== prevFirstVisibleItemKey) { + // Fast path if items were added at the start of the list. +@@ -944,7 +946,8 @@ class VirtualizedList extends StateSafePureComponent { + cellsAroundViewport: constrainedCells, + renderMask: VirtualizedList._createRenderMask(newProps, constrainedCells), + firstVisibleItemKey: newFirstVisibleItemKey, +- pendingScrollUpdateCount: maintainVisibleContentPositionAdjustment != null ? prevState.pendingScrollUpdateCount + 1 : prevState.pendingScrollUpdateCount ++ pendingScrollUpdateCount: maintainVisibleContentPositionAdjustment != null ? prevState.pendingScrollUpdateCount + 1 : prevState.pendingScrollUpdateCount, ++ lastItemCount: itemCount + }; + } + _pushCells(cells, stickyHeaderIndices, stickyIndicesFromProps, first, last, inversionStyle) { +@@ -1220,7 +1223,7 @@ class VirtualizedList extends StateSafePureComponent { + return ret; + } + } +- componentDidUpdate(prevProps) { ++ componentDidUpdate(prevProps, prevState) { + var _this$props7 = this.props, + data = _this$props7.data, + extraData = _this$props7.extraData; +@@ -1244,6 +1247,11 @@ class VirtualizedList extends StateSafePureComponent { + if (hiPriInProgress) { + this._hiPriInProgress = false; + } ++ ++ if (this.state.cellsAroundViewport.first !== prevState.cellsAroundViewport.first || ++ this.state.cellsAroundViewport.last !== prevState.cellsAroundViewport.last) { ++ this._maybeCallOnEdgeReached(); ++ } + } + + // Used for preventing scrollToIndex from being called multiple times for initialScrollIndex +@@ -1407,8 +1415,8 @@ class VirtualizedList extends StateSafePureComponent { // Next check if the user just scrolled within the start threshold // and call onStartReached only once for a given content length, // and only if onEndReached is not being executed @@ -22,7 +90,7 @@ index b05da08..80aea85 100644 onStartReached({ distanceFromStart }); -@@ -1407,7 +1407,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1417,7 +1425,7 @@ class VirtualizedList extends StateSafePureComponent { // If the user scrolls away from the start or end and back again, // cause onStartReached or onEndReached to be triggered again else { @@ -32,10 +100,80 @@ index b05da08..80aea85 100644 } } diff --git a/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js b/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js -index 459f017..799a6ee 100644 +index 459f017..d20115c 100644 --- a/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js +++ b/node_modules/react-native-web/src/vendor/react-native/VirtualizedList/index.js -@@ -1325,7 +1325,7 @@ class VirtualizedList extends StateSafePureComponent { +@@ -79,6 +79,7 @@ type State = { + firstVisibleItemKey: ?string, + // When > 0 the scroll position available in JS is considered stale and should not be used. + pendingScrollUpdateCount: number, ++ lastItemCount: number, + }; + + /** +@@ -453,12 +454,13 @@ class VirtualizedList extends StateSafePureComponent { + + const minIndexForVisible = + this.props.maintainVisibleContentPosition?.minIndexForVisible ?? 0; ++ const itemCount = this.props.getItemCount(this.props.data); + + this.state = { + cellsAroundViewport: initialRenderRegion, + renderMask: VirtualizedList._createRenderMask(props, initialRenderRegion), + firstVisibleItemKey: +- this.props.getItemCount(this.props.data) > minIndexForVisible ++ itemCount > minIndexForVisible + ? VirtualizedList._getItemKey(this.props, minIndexForVisible) + : null, + // When we have a non-zero initialScrollIndex, we will receive a +@@ -469,6 +471,7 @@ class VirtualizedList extends StateSafePureComponent { + this.props.initialScrollIndex > 0 + ? 1 + : 0, ++ lastItemCount: itemCount, + }; + + // REACT-NATIVE-WEB patch to preserve during future RN merges: Support inverted wheel scroller. +@@ -809,16 +812,15 @@ class VirtualizedList extends StateSafePureComponent { + // first and last could be stale (e.g. if a new, shorter items props is passed in), so we make + // sure we're rendering a reasonable range here. + const itemCount = newProps.getItemCount(newProps.data); +- if (itemCount === prevState.renderMask.numCells()) { ++ if (itemCount === prevState.renderMask.numCells() && itemCount === prevState.lastItemCount) { + return prevState; + } +- + let maintainVisibleContentPositionAdjustment: ?number = null; + const prevFirstVisibleItemKey = prevState.firstVisibleItemKey; + const minIndexForVisible = + newProps.maintainVisibleContentPosition?.minIndexForVisible ?? 0; + const newFirstVisibleItemKey = +- newProps.getItemCount(newProps.data) > minIndexForVisible ++ itemCount > minIndexForVisible + ? VirtualizedList._getItemKey(newProps, minIndexForVisible) + : null; + if ( +@@ -866,6 +868,7 @@ class VirtualizedList extends StateSafePureComponent { + maintainVisibleContentPositionAdjustment != null + ? prevState.pendingScrollUpdateCount + 1 + : prevState.pendingScrollUpdateCount, ++ lastItemCount: itemCount, + }; + } + +@@ -1285,6 +1288,11 @@ class VirtualizedList extends StateSafePureComponent { + if (hiPriInProgress) { + this._hiPriInProgress = false; + } ++ ++ if (this.state.cellsAroundViewport.first !== prevState.cellsAroundViewport.first || ++ this.state.cellsAroundViewport.last !== prevState.cellsAroundViewport.last) { ++ this._maybeCallOnEdgeReached(); ++ } + } + + _averageCellLength = 0; +@@ -1325,7 +1333,7 @@ class VirtualizedList extends StateSafePureComponent { zoomScale: 1, }; _scrollRef: ?React.ElementRef = null; @@ -44,7 +182,7 @@ index 459f017..799a6ee 100644 _sentEndForContentLength = 0; _totalCellLength = 0; _totalCellsMeasured = 0; -@@ -1675,18 +1675,18 @@ class VirtualizedList extends StateSafePureComponent { +@@ -1675,18 +1683,18 @@ class VirtualizedList extends StateSafePureComponent { onStartReached != null && this.state.cellsAroundViewport.first === 0 && isWithinStartThreshold && From 0b214f7f1c59b244b4e530377bb4707140377f02 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Sat, 27 Jul 2024 16:56:51 -0400 Subject: [PATCH 2/7] Fix mvcp on Android --- ...act-native+0.73.4+024+fixMVCPAndroid.patch | 334 ++++++++++++++++++ src/pages/home/report/ReportActionsView.tsx | 1 + 2 files changed, 335 insertions(+) create mode 100644 patches/react-native+0.73.4+024+fixMVCPAndroid.patch diff --git a/patches/react-native+0.73.4+024+fixMVCPAndroid.patch b/patches/react-native+0.73.4+024+fixMVCPAndroid.patch new file mode 100644 index 000000000000..fe37e38c3040 --- /dev/null +++ b/patches/react-native+0.73.4+024+fixMVCPAndroid.patch @@ -0,0 +1,334 @@ +diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java +index fff761f..2cebd6b 100644 +--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java ++++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java +@@ -82,6 +82,7 @@ public class MaintainVisibleScrollPositionHelper currentScroll || i == contentView.getChildCount() - 1) { +- mFirstVisibleView = new WeakReference<>(child); +- Rect frame = new Rect(); +- child.getHitRect(frame); +- mPrevFirstVisibleFrame = frame; +- break; ++ if ((position > currentScroll && position < firstVisibleViewPosition) || ++ (firstVisibleView == null && i == contentView.getChildCount() - 1)) { ++ firstVisibleView = child; ++ firstVisibleViewPosition = position; ++ } ++ } ++ mFirstVisibleView = new WeakReference<>(firstVisibleView); ++ } ++ ++ private View getFirstVisibleView() { ++ return mFirstVisibleView != null ? mFirstVisibleView.get() : null; ++ } ++ ++ private void willMountItemsInternal() { ++ View firstVisibleView = getFirstVisibleView(); ++ ++ // If we don't have a first visible view because no scroll happened call onScroll ++ // to update it. ++ if (firstVisibleView == null) { ++ onScroll(); ++ firstVisibleView = getFirstVisibleView(); ++ ++ // There are cases where it is possible for this to still be null so just bail out. ++ if (firstVisibleView == null) { ++ return; + } + } ++ Rect frame = new Rect(); ++ firstVisibleView.getHitRect(frame); ++ mPrevFirstVisibleFrame = frame; + } + + // UIManagerListener +@@ -177,19 +205,19 @@ public class MaintainVisibleScrollPositionHelper Date: Thu, 25 Jul 2024 14:33:46 -0400 Subject: [PATCH 3/7] Fix newer messages not loading after comment linking --- src/pages/home/report/ReportActionsView.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index c608a3105675..f59539d97ad3 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -10,7 +10,6 @@ import useInitialValue from '@hooks/useInitialValue'; import useNetwork from '@hooks/useNetwork'; import usePrevious from '@hooks/usePrevious'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useWindowDimensions from '@hooks/useWindowDimensions'; import DateUtils from '@libs/DateUtils'; import getIsReportFullyVisible from '@libs/getIsReportFullyVisible'; import type {AuthScreensParamList} from '@libs/Navigation/types'; @@ -79,9 +78,6 @@ type ReportActionsViewProps = ReportActionsViewOnyxProps & { transactionThreadReportID?: string | null; }; -const DIFF_BETWEEN_SCREEN_HEIGHT_AND_LIST = 120; -const SPACER = 16; - let listOldID = Math.round(Math.random() * 100); function ReportActionsView({ @@ -114,7 +110,6 @@ function ReportActionsView({ const isFirstLinkedActionRender = useRef(true); const network = useNetwork(); - const {windowHeight} = useWindowDimensions(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const contentListHeight = useRef(0); const isFocused = useIsFocused(); @@ -342,8 +337,6 @@ function ReportActionsView({ contentListHeight.current = h; }, []); - const checkIfContentSmallerThanList = useCallback(() => windowHeight - DIFF_BETWEEN_SCREEN_HEIGHT_AND_LIST - SPACER > contentListHeight.current, [windowHeight]); - /** * Retrieves the next set of report actions for the chat once we are nearing the end of what we are currently * displaying. @@ -397,10 +390,6 @@ function ReportActionsView({ const loadNewerChats = useCallback( (force = false) => { - // Determines if loading older reports is necessary when the content is smaller than the list - // and there are fewer than 23 items, indicating we've reached the oldest message. - const isLoadingOlderReportsFirstNeeded = checkIfContentSmallerThanList() && reportActions.length > 23; - if ( !force && (!reportActionID || @@ -417,18 +406,16 @@ function ReportActionsView({ didLoadNewerChats.current = true; - if ((reportActionID && indexOfLinkedAction > -1 && !isLoadingOlderReportsFirstNeeded) || (!reportActionID && !isLoadingOlderReportsFirstNeeded)) { + if ((reportActionID && indexOfLinkedAction > -1) || !reportActionID) { handleReportActionPagination({firstReportActionID: newestReportAction?.reportActionID}); } }, [ isLoadingInitialReportActions, isLoadingNewerReportActions, - checkIfContentSmallerThanList, reportActionID, indexOfLinkedAction, handleReportActionPagination, - reportActions.length, newestReportAction, isFocused, hasLoadingNewerReportActionsError, From c804881c26cf6275539c2f521c86da8cd2ceda95 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 25 Jul 2024 15:37:32 -0400 Subject: [PATCH 4/7] Fix not found view flicker when comment linking --- src/pages/home/ReportScreen.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 94089f880c92..533d9831292f 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -259,13 +259,6 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro const [currentUserAccountID = -1] = useOnyx(ONYXKEYS.SESSION, {selector: (value) => value?.accountID}); const {reportActions, linkedAction, sortedAllReportActions} = usePaginatedReportActions(report.reportID, reportActionIDFromRoute); - // Define here because reportActions are recalculated before mount, allowing data to display faster than useEffect can trigger. - // If we have cached reportActions, they will be shown immediately. - // We aim to display a loader first, then fetch relevant reportActions, and finally show them. - useLayoutEffect(() => { - setIsLinkingToMessage(!!reportActionIDFromRoute); - }, [route, reportActionIDFromRoute]); - const [isBannerVisible, setIsBannerVisible] = useState(true); const [scrollPosition, setScrollPosition] = useState({}); @@ -728,6 +721,16 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro Report.readNewestAction(report.reportID); }, [report]); + const lastRoute = usePrevious(route); + const lastReportActionIDFromRoute = usePrevious(reportActionIDFromRoute); + // Define here because reportActions are recalculated before mount, allowing data to display faster than useEffect can trigger. + // If we have cached reportActions, they will be shown immediately. + // We aim to display a loader first, then fetch relevant reportActions, and finally show them. + if ((lastRoute !== route || lastReportActionIDFromRoute !== reportActionIDFromRoute) && isLinkingToMessage !== !!reportActionIDFromRoute) { + setIsLinkingToMessage(!!reportActionIDFromRoute); + return null; + } + return ( From 13c9acb1a37667c7a2952c4a4080071992f21674 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 1 Aug 2024 14:48:53 -0400 Subject: [PATCH 5/7] Fix scrollTo called when not needed --- src/components/FlatList/index.android.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/FlatList/index.android.tsx b/src/components/FlatList/index.android.tsx index c8ce7ee10d6b..261d10488098 100644 --- a/src/components/FlatList/index.android.tsx +++ b/src/components/FlatList/index.android.tsx @@ -1,29 +1,30 @@ import {useFocusEffect} from '@react-navigation/native'; import type {ForwardedRef} from 'react'; -import React, {forwardRef, useCallback, useContext} from 'react'; +import React, {forwardRef, useCallback, useRef} from 'react'; import type {FlatListProps, NativeScrollEvent, NativeSyntheticEvent} from 'react-native'; import {FlatList} from 'react-native'; -import {ActionListContext} from '@pages/home/ReportScreenContext'; // FlatList wrapped with the freeze component will lose its scroll state when frozen (only for Android). // CustomFlatList saves the offset and use it for scrollToOffset() when unfrozen. function CustomFlatList(props: FlatListProps, ref: ForwardedRef) { - const {scrollPosition, setScrollPosition} = useContext(ActionListContext); + const lastScrollOffsetRef = useRef(0); const onScreenFocus = useCallback(() => { if (typeof ref === 'function') { return; } - if (!ref?.current || !scrollPosition?.offset) { + if (!ref?.current || !lastScrollOffsetRef.current) { return; } - if (ref.current && scrollPosition.offset) { - ref.current.scrollToOffset({offset: scrollPosition.offset, animated: false}); + if (ref.current && lastScrollOffsetRef.current) { + ref.current.scrollToOffset({offset: lastScrollOffsetRef.current, animated: false}); } - }, [scrollPosition?.offset, ref]); + }, [ref]); // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - const onMomentumScrollEnd = useCallback((event: NativeSyntheticEvent) => setScrollPosition({offset: event.nativeEvent.contentOffset.y}), []); + const onMomentumScrollEnd = useCallback((event: NativeSyntheticEvent) => { + lastScrollOffsetRef.current = event.nativeEvent.contentOffset.y; + }, []); useFocusEffect( useCallback(() => { From 9a2b1493db0b142ab6f4e8275cd028a872839933 Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 1 Aug 2024 18:45:53 -0400 Subject: [PATCH 6/7] Fix lint --- src/pages/home/ReportScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 533d9831292f..7a80a9a5f351 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -2,7 +2,7 @@ import {PortalHost} from '@gorhom/portal'; import {useIsFocused} from '@react-navigation/native'; import type {StackScreenProps} from '@react-navigation/stack'; import lodashIsEqual from 'lodash/isEqual'; -import React, {memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react'; +import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import type {FlatList, ViewStyle} from 'react-native'; import {InteractionManager, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; From 012ac2d356cd17d9906d666f54117b69ece0b7fb Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Fri, 16 Aug 2024 13:43:10 -0400 Subject: [PATCH 7/7] Fix flicker when comment linking --- ...+016+iOSCoreAnimationBorderRendering.patch | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/patches/react-native+0.73.4+016+iOSCoreAnimationBorderRendering.patch b/patches/react-native+0.73.4+016+iOSCoreAnimationBorderRendering.patch index b59729e79622..478e282e387d 100644 --- a/patches/react-native+0.73.4+016+iOSCoreAnimationBorderRendering.patch +++ b/patches/react-native+0.73.4+016+iOSCoreAnimationBorderRendering.patch @@ -1,22 +1,23 @@ diff --git a/node_modules/react-native/React/Fabric/Mounting/RCTMountingManager.mm b/node_modules/react-native/React/Fabric/Mounting/RCTMountingManager.mm -index b4cfb3d..7aa00e5 100644 +index b4cfb3d..fdfae56 100644 --- a/node_modules/react-native/React/Fabric/Mounting/RCTMountingManager.mm +++ b/node_modules/react-native/React/Fabric/Mounting/RCTMountingManager.mm -@@ -49,6 +49,9 @@ static void RCTPerformMountInstructions( - { - SystraceSection s("RCTPerformMountInstructions"); +@@ -265,6 +265,9 @@ static void RCTPerformMountInstructions( + auto surfaceId = mountingCoordinator.getSurfaceId(); + + [CATransaction begin]; + [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; + - for (const auto &mutation : mutations) { - switch (mutation.type) { - case ShadowViewMutation::Create: { -@@ -147,6 +150,7 @@ static void RCTPerformMountInstructions( - } - } - } + mountingCoordinator.getTelemetryController().pullTransaction( + [&](const MountingTransaction &transaction, const SurfaceTelemetry &surfaceTelemetry) { + [self.delegate mountingManager:self willMountComponentsWithRootTag:surfaceId]; +@@ -278,6 +281,8 @@ static void RCTPerformMountInstructions( + _observerCoordinator.notifyObserversMountingTransactionDidMount(transaction, surfaceTelemetry); + [self.delegate mountingManager:self didMountComponentsWithRootTag:surfaceId]; + }); ++ + [CATransaction commit]; } - @implementation RCTMountingManager { + - (void)setIsJSResponder:(BOOL)isJSResponder