remove paper refresh control patch

This commit is contained in:
Samuel Newman
2026-09-03 17:40:28 +03:00
parent 8af501de62
commit 0cb8a27b2f
3 changed files with 340 additions and 412 deletions
-74
View File
@@ -262,80 +262,6 @@ index b033b7c71914d287470b7b86bd6bf39d311294ba..7e10dc929147fa4474ca9f955f5cd85d
layer.contents = (id)image.CGImage;
layer.contentsScale = image.scale;
diff --git a/React/Views/RefreshControl/RCTRefreshControl.h b/React/Views/RefreshControl/RCTRefreshControl.h
index ed306d7cadbf36a2fed79be8bd9d68b5dca135bd..d447dad534fefa9fcbdbbde6dcbbdcddadd5a824 100644
--- a/React/Views/RefreshControl/RCTRefreshControl.h
+++ b/React/Views/RefreshControl/RCTRefreshControl.h
@@ -18,6 +18,7 @@ __attribute__((deprecated("This API will be removed along with the legacy archit
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) RCTDirectEventBlock onRefresh;
@property (nonatomic, weak) UIScrollView *scrollView;
+@property (nonatomic, copy) UIColor *customTintColor;
@end
diff --git a/React/Views/RefreshControl/RCTRefreshControl.m b/React/Views/RefreshControl/RCTRefreshControl.m
index 2dc86e464264c9450eef18d7b153d35bf6a5cc55..6661dc69a04766afa0284d6e83839b219e98cf57 100644
--- a/React/Views/RefreshControl/RCTRefreshControl.m
+++ b/React/Views/RefreshControl/RCTRefreshControl.m
@@ -25,6 +25,7 @@ @implementation RCTRefreshControl {
UIColor *_titleColor;
CGFloat _progressViewOffset;
BOOL _hasMovedToWindow;
+ UIColor *_customTintColor;
}
- (instancetype)init
@@ -60,6 +61,12 @@ - (void)layoutSubviews
_isInitialRender = false;
}
+- (void)didMoveToSuperview
+{
+ [super didMoveToSuperview];
+ [self setTintColor:_customTintColor];
+}
+
- (void)didMoveToWindow
{
[super didMoveToWindow];
@@ -225,6 +232,18 @@ - (void)refreshControlValueChanged
}
}
+// Fix for https://github.com/facebook/react-native/issues/43388
+// A bug in iOS 17.4 causes the haptic to not play when refreshing if the tintColor
+// is set before the refresh control gets added to the scrollview. We'll call this
+// function whenever the superview changes. We'll also call it if the value of customTintColor
+// changes.
+- (void)setTintColor:(UIColor *)tintColor
+{
+ if ([self.superview isKindOfClass:[UIScrollView class]] && self.tintColor != tintColor) {
+ [super setTintColor:tintColor];
+ }
+}
+
@end
#endif // RCT_REMOVE_LEGACY_ARCH
diff --git a/React/Views/RefreshControl/RCTRefreshControlManager.m b/React/Views/RefreshControl/RCTRefreshControlManager.m
index 1e9ff527f4e6691d716da624031113a397876981..44329c5422c6f24d8a437fa35c6f2bad6bf8622b 100644
--- a/React/Views/RefreshControl/RCTRefreshControlManager.m
+++ b/React/Views/RefreshControl/RCTRefreshControlManager.m
@@ -24,11 +24,12 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(onRefresh, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(refreshing, BOOL)
-RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
RCT_EXPORT_VIEW_PROPERTY(title, NSString)
RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor)
RCT_EXPORT_VIEW_PROPERTY(progressViewOffset, CGFloat)
+RCT_REMAP_VIEW_PROPERTY(tintColor, customTintColor, UIColor)
+
RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt
index 59775241c80bec99ad3ec080f2425aacc8900c24..426de3aa77cda2032d7b0991e2ca3f8482a438d3 100644
--- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt
+14 -12
View File
@@ -1,4 +1,4 @@
# ***This second part of this patch is load bearing, do not remove.***
# React Native 0.86 patch notes
## Scheduler delegate invalidation - iOS use-after-free
@@ -31,12 +31,6 @@ holds the current revision's `shared_ptr` for the entire traversal.
**TODO: Remove after bumping React Native to a release containing
facebook/react-native#56850.**
## RefreshControl Patch - iOS 17.4 Haptic Regression
Patching `RCTRefreshControl.mm` temporarily to play an impact haptic on refresh when using iOS 17.4 or higher. Since
17.4, there has been a regression somewhere causing haptics to not play on iOS on refresh. Should monitor for an update
in the RN repo: https://github.com/facebook/react-native/issues/43388
## RCTPullToRefreshViewComponentView.mm Patch - iOS 17.4+ haptic regression and iOS 26 progressViewOffset cancellation on New Arch
Both bugs share one root cause, established by instrumented frame-logging runs on the iOS 26
@@ -61,11 +55,10 @@ home header (home is the only screen passing a non-zero offset). Stock RN appear
by accident: its own pre-attach `tintColor` write materialized the content view at origin 0
*before* the offset write. Possibly related upstream: react-native#54183.
**2. Haptic (react-native#43388).** The Paper fix above does not cover Fabric: `updateProps`
writes `tintColor` pre-attach, and a tint write on a detached control materializes the content
view outside the scroll view, permanently suppressing the trigger haptic on iOS 17.4+ (the
creation-time-state story likely explains this too, though the haptic wiring itself is not
observable in logs).
**2. Haptic (react-native#43388).** Fabric's `updateProps` writes `tintColor` pre-attach. A tint
write on a detached control materializes the content view outside the scroll view, permanently
suppressing the trigger haptic on iOS 17.4+ (the creation-time-state story likely explains this
too, though the haptic wiring itself is not observable in logs).
**The fix**: both `tintColor` and `progressViewOffset` are parked in the component view
(`_pendingTintColor` / `_pendingProgressViewOffset`, no `UIRefreshControl` subclass) and applied
@@ -134,6 +127,15 @@ content-less area are attributed to the `UIScrollView`.
Issue: https://github.com/facebook/react-native/issues/54123
PR: https://github.com/react/react-native/pull/56747
## RCTScrollViewComponentView.mm Patch - Disable ScrollView component-view recycling on New Arch
Fabric ScrollView component-view recycling is disabled by returning `NO` from
`shouldBeRecycled`. This was added in social-app#8295 to prevent a recycled ScrollView from
carrying `contentInset` mutations, such as those made by Reanimated, into the next rendered
ScrollView. The original patch also reset the inset in `prepareForRecycle`; that reset no longer
survives, leaving the recycling override as the remaining protection. Re-evaluate this hunk when
upgrading React Native rather than assuming it belongs to either ScrollView fix above.
## ReactViewGroup.kt Patch - Fatal "Required value was null" during subview clipping on Android
Fixes Sentry issue APP-T20Q: `IllegalStateException: Required value was null` thrown by
+326 -326
View File
File diff suppressed because it is too large Load Diff