From c032401b6724c99fbb80f158c82bd4fe690bf40e Mon Sep 17 00:00:00 2001 From: Paige Sun Date: Mon, 11 Apr 2022 15:30:14 -0700 Subject: [PATCH] Fix sticky headers for scrollviews by sending onScroll event to legacy RCTEventDispatcher Summary: Changelog: [Internal][Bridgeless] Fix sticky headers for scrollviews by sending onScroll event to legacy RCTEventDispatcher ## Extra Context FYI. is the only Fabric component view that needs to send events via the legacy RCTEventDispatcher. Ideally, all component views should only use `ViewEventEmitter` to send events to JS and not use RCTEventDispatcher. This ScrollView does use ScrollViewEventEmitter, a subclass of ViewEventEmitter: ``` std::static_pointer_cast(_eventEmitter)->onScroll([self _scrollViewMetrics]); ``` However, it also needs RCTEventDispatcher for animations using `Animated.event` for `useNativeDriver: true`. See [ScrollView.js](https://github.com/facebook/react-native/blob/370c65b94379a72e74f5dfd5b6202f282841a950/Libraries/Components/ScrollView/ScrollView.js#L1124-L1129). Reviewed By: RSNara Differential Revision: D35540277 fbshipit-source-id: a28535ed10cac8e003523ecda6080574fbb89b85 --- .../ScrollView/RCTScrollViewComponentView.mm | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 79f3cf315ed..7752626d2d8 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -52,7 +52,11 @@ static UIScrollViewIndicatorStyle RCTUIScrollViewIndicatorStyleFromProps(ScrollV } } -static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteger tag) +// Once Fabric implements proper NativeAnimationDriver, this should be removed. +// This is just a workaround to allow animations based on onScroll event. +// This is only used to animate sticky headers in ScrollViews, and only the contentOffset and tag is used. +// TODO: T116850910 [Fabric][iOS] Make Fabric not use legacy RCTEventDispatcher for native-driven AnimatedEvents +static void RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrollView, NSInteger tag) { static uint16_t coalescingKey = 0; RCTScrollEvent *scrollEvent = [[RCTScrollEvent alloc] initWithEventName:@"onScroll" @@ -64,7 +68,15 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg scrollViewZoomScale:scrollView.zoomScale userData:nil coalescingKey:coalescingKey]; - [[RCTBridge currentBridge].eventDispatcher sendEvent:scrollEvent]; + RCTBridge *bridge = [RCTBridge currentBridge]; + if (bridge) { + [bridge.eventDispatcher sendEvent:scrollEvent]; + } else { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:scrollEvent, @"event", nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTSendEventToLegacyEventDispatcher" + object:nil + userInfo:userInfo]; + } } @interface RCTScrollViewComponentView () < @@ -403,9 +415,8 @@ static void RCTSendPaperScrollEvent_DEPRECATED(UIScrollView *scrollView, NSInteg if (_eventEmitter) { std::static_pointer_cast(_eventEmitter)->onScroll([self _scrollViewMetrics]); } - // Once Fabric implements proper NativeAnimationDriver, this should be removed. - // This is just a workaround to allow animations based on onScroll event. - RCTSendPaperScrollEvent_DEPRECATED(scrollView, self.tag); + + RCTSendScrollEventForNativeAnimations_DEPRECATED(scrollView, self.tag); } [self _remountChildrenIfNeeded];