From 74a7507814cdb994b9deafea6b9145a464b10f8d Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sun, 30 Aug 2026 22:23:24 +0200 Subject: [PATCH] fix(android): keep timeline still when tapping text Selectable Android text takes touch focus. React Native then scrolls focused children using untransformed coordinates, which moves inverted timelines even though the user did not scroll.\n\nSkip that auto-scroll only for touch-focused, selectable, non-editable text in inverted vertical scroll views, preserving normal focus navigation and editable inputs. --- patches/react-native+0.81.5.patch | 37 +++++++++++++++++++++++++++++++ scripts/postinstall-patches.mjs | 4 ++++ 2 files changed, 41 insertions(+) create mode 100644 patches/react-native+0.81.5.patch diff --git a/patches/react-native+0.81.5.patch b/patches/react-native+0.81.5.patch new file mode 100644 index 0000000000..41c0d868f0 --- /dev/null +++ b/patches/react-native+0.81.5.patch @@ -0,0 +1,37 @@ +diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +index f708543..26df5e0 100644 +--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java ++++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +@@ -29,6 +29,7 @@ import android.view.ViewGroup; + import android.view.accessibility.AccessibilityNodeInfo; + import android.widget.OverScroller; + import android.widget.ScrollView; ++import android.widget.TextView; + import androidx.annotation.NonNull; + import androidx.annotation.Nullable; + import androidx.core.view.ViewCompat; +@@ -425,12 +426,23 @@ public class ReactScrollView extends ScrollView + */ + @Override + public void requestChildFocus(View child, View focused) { +- if (focused != null) { ++ if (focused != null && shouldScrollToFocusedChild(focused)) { + scrollToChild(focused); + } + super.requestChildFocus(child, focused); + } + ++ private boolean shouldScrollToFocusedChild(View focused) { ++ if (getScaleY() >= 0 || !focused.isInTouchMode() || !(focused instanceof TextView)) { ++ return true; ++ } ++ ++ // Selectable text takes focus when tapped. In inverted lists, scrolling to that focus uses ++ // untransformed coordinates and unexpectedly moves the timeline. ++ TextView textView = (TextView) focused; ++ return !textView.isTextSelectable() || textView.onCheckIsTextEditor(); ++ } ++ + private int getScrollDelta(View descendent) { + descendent.getDrawingRect(mTempRect); + offsetDescendantRectToMyCoords(descendent, mTempRect); diff --git a/scripts/postinstall-patches.mjs b/scripts/postinstall-patches.mjs index 2a762c7a5f..53b8395480 100644 --- a/scripts/postinstall-patches.mjs +++ b/scripts/postinstall-patches.mjs @@ -12,6 +12,10 @@ const patchedPackages = [ nodeModulesPath: "node_modules/react-native-markdown-display", patchPrefix: "react-native-markdown-display+", }, + { + nodeModulesPath: "node_modules/react-native", + patchPrefix: "react-native+", + }, { nodeModulesPath: "node_modules/react-native-draggable-flatlist", patchPrefix: "react-native-draggable-flatlist+",