From 38db6fa4658e8074a91f2c541bee3d00fe3ea50a Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 25 Nov 2015 03:07:06 -0800 Subject: [PATCH] Remove scrollview support from UIManager, remove mainScrollView(delegate) Reviewed By: nicklockwood Differential Revision: D2692749 fb-gh-sync-id: 48975d2f09f3b2902dfa2e56ff9d34257b2395bc --- Libraries/Components/ScrollResponder.js | 34 +++++----- Libraries/Components/ScrollView/ScrollView.js | 1 - React/Modules/RCTUIManager.h | 13 ---- React/Modules/RCTUIManager.m | 67 ------------------- React/Views/RCTScrollView.m | 14 ++-- React/Views/RCTScrollViewManager.h | 1 - React/Views/RCTScrollViewManager.m | 40 +++++++++-- React/Views/RCTScrollableProtocol.h | 2 +- .../react/uimanager/UIManagerModule.java | 5 -- 9 files changed, 62 insertions(+), 115 deletions(-) diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index 75ceb561d..3374cf22d 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -12,18 +12,19 @@ 'use strict'; var Dimensions = require('Dimensions'); -var NativeModules = require('NativeModules'); var Platform = require('Platform'); var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); var React = require('React'); var Subscribable = require('Subscribable'); var TextInputState = require('TextInputState'); -var RCTUIManager = NativeModules.UIManager; -var RCTScrollViewConsts = RCTUIManager.RCTScrollView.Constants; +var { UIManager, ScrollViewManager } = require('NativeModules'); +var invariant = require('invariant'); var warning = require('warning'); +import type ReactComponent from 'ReactComponent'; + /** * Mixin that can be integrated in order to handle scrolling that plays well * with `ResponderEventPlugin`. Integrate with your platform specific scroll @@ -115,7 +116,6 @@ type Event = Object; var ScrollResponderMixin = { mixins: [Subscribable.Mixin], - statics: RCTScrollViewConsts, scrollResponderMixinGetInitialState: function(): State { return { isTouching: false, @@ -353,16 +353,15 @@ var ScrollResponderMixin = { */ scrollResponderScrollTo: function(offsetX: number, offsetY: number) { if (Platform.OS === 'android') { - RCTUIManager.dispatchViewManagerCommand( + UIManager.dispatchViewManagerCommand( React.findNodeHandle(this), - RCTUIManager.RCTScrollView.Commands.scrollTo, + UIManager.RCTScrollView.Commands.scrollTo, [Math.round(offsetX), Math.round(offsetY)], ); } else { - RCTUIManager.scrollTo( + ScrollViewManager.scrollTo( React.findNodeHandle(this), - offsetX, - offsetY, + { x: offsetX, y: offsetY } ); } }, @@ -373,16 +372,15 @@ var ScrollResponderMixin = { */ scrollResponderScrollWithouthAnimationTo: function(offsetX: number, offsetY: number) { if (Platform.OS === 'android') { - RCTUIManager.dispatchViewManagerCommand( + UIManager.dispatchViewManagerCommand( React.findNodeHandle(this), - RCTUIManager.RCTScrollView.Commands.scrollWithoutAnimationTo, + UIManager.RCTScrollView.Commands.scrollWithoutAnimationTo, [offsetX, offsetY], ); } else { - RCTUIManager.scrollWithoutAnimationTo( + ScrollViewManager.scrollWithoutAnimationTo( React.findNodeHandle(this), - offsetX, - offsetY + { x: offsetX, y: offsetY } ); } }, @@ -392,7 +390,11 @@ var ScrollResponderMixin = { * @param {object} rect Should have shape {x, y, width, height} */ scrollResponderZoomTo: function(rect: { x: number; y: number; width: number; height: number; }) { - RCTUIManager.zoomToRect(React.findNodeHandle(this), rect); + if (Platform.OS === 'android') { + invariant('zoomToRect is not implemented'); + } else { + ScrollViewManager.zoomToRect(React.findNodeHandle(this), rect); + } }, /** @@ -408,7 +410,7 @@ var ScrollResponderMixin = { scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle: any, additionalOffset?: number, preventNegativeScrollOffset?: bool) { this.additionalScrollOffset = additionalOffset || 0; this.preventNegativeScrollOffset = !!preventNegativeScrollOffset; - RCTUIManager.measureLayout( + UIManager.measureLayout( nodeHandle, React.findNodeHandle(this.getInnerViewNode()), this.scrollResponderTextInputFocusError, diff --git a/Libraries/Components/ScrollView/ScrollView.js b/Libraries/Components/ScrollView/ScrollView.js index 62b619ca3..8069b9647 100644 --- a/Libraries/Components/ScrollView/ScrollView.js +++ b/Libraries/Components/ScrollView/ScrollView.js @@ -18,7 +18,6 @@ var RCTScrollView = require('NativeModules').UIManager.RCTScrollView; var RCTScrollViewManager = require('NativeModules').ScrollViewManager; var React = require('React'); var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); -var RCTUIManager = require('NativeModules').UIManager; var ScrollResponder = require('ScrollResponder'); var StyleSheet = require('StyleSheet'); var StyleSheetPropType = require('StyleSheetPropType'); diff --git a/React/Modules/RCTUIManager.h b/React/Modules/RCTUIManager.h index 9fd8cb7e8..daaf40ac2 100644 --- a/React/Modules/RCTUIManager.h +++ b/React/Modules/RCTUIManager.h @@ -44,19 +44,6 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey; */ @interface RCTUIManager : NSObject -/** - * The UIIManager has the concept of a designated "main scroll view", which is - * useful for apps built around a central scrolling content area (e.g. a - * timeline). - */ -@property (nonatomic, weak) id mainScrollView; - -/** - * Allows native environment code to respond to "the main scroll view" events. - * see `RCTUIManager`'s `setMainScrollViewTag`. - */ -@property (nonatomic, readwrite, weak) id nativeMainScrollDelegate; - /** * Register a root view with the RCTUIManager. */ diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 679e84767..a15d25164 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -1095,73 +1095,6 @@ RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect callback(@[results]); } -RCT_EXPORT_METHOD(setMainScrollViewTag:(nonnull NSNumber *)reactTag) -{ - [self addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { - // - There should be at most one designated "main scroll view" - // - There should be at most one designated "`nativeMainScrollDelegate`" - // - The one designated main scroll view should have the one designated - // `nativeMainScrollDelegate` set as its `nativeMainScrollDelegate`. - if (uiManager.mainScrollView) { - uiManager.mainScrollView.nativeMainScrollDelegate = nil; - } - id view = viewRegistry[reactTag]; - if (view) { - if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - uiManager.mainScrollView = (id)view; - uiManager.mainScrollView.nativeMainScrollDelegate = uiManager.nativeMainScrollDelegate; - } else { - RCTLogError(@"Tag #%@ does not conform to RCTScrollableProtocol", reactTag); - } - } else { - uiManager.mainScrollView = nil; - } - }]; -} - -// TODO: we could just pass point property -RCT_EXPORT_METHOD(scrollTo:(nonnull NSNumber *)reactTag - withOffsetX:(CGFloat)offsetX - offsetY:(CGFloat)offsetY) -{ - [self addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){ - UIView *view = viewRegistry[reactTag]; - if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - [(id)view scrollToOffset:(CGPoint){offsetX, offsetY} animated:YES]; - } else { - RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag #%@", view, reactTag); - } - }]; -} - -// TODO: we could just pass point property -RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(nonnull NSNumber *)reactTag - offsetX:(CGFloat)offsetX - offsetY:(CGFloat)offsetY) -{ - [self addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){ - UIView *view = viewRegistry[reactTag]; - if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - [(id)view scrollToOffset:(CGPoint){offsetX, offsetY} animated:NO]; - } else { - RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag #%@", view, reactTag); - } - }]; -} - -RCT_EXPORT_METHOD(zoomToRect:(nonnull NSNumber *)reactTag - withRect:(CGRect)rect) -{ - [self addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){ - UIView *view = viewRegistry[reactTag]; - if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { - [(id)view zoomToRect:rect animated:YES]; - } else { - RCTLogError(@"tried to zoomToRect: on non-RCTScrollableProtocol view %@ with tag #%@", view, reactTag); - } - }]; -} - /** * JS sets what *it* considers to be the responder. Later, scroll views can use * this in order to determine if scrolling is appropriate. diff --git a/React/Views/RCTScrollView.m b/React/Views/RCTScrollView.m index 2dc6f3886..f1ef89572 100644 --- a/React/Views/RCTScrollView.m +++ b/React/Views/RCTScrollView.m @@ -375,7 +375,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) CGRect _lastClippedToRect; } -@synthesize nativeMainScrollDelegate = _nativeMainScrollDelegate; +@synthesize nativeScrollDelegate = _nativeScrollDelegate; - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher { @@ -542,14 +542,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) - (void)delegateMethod:(UIScrollView *)scrollView \ { \ [_eventDispatcher sendScrollEventWithType:eventName reactTag:self.reactTag scrollView:scrollView userData:nil]; \ - if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \ - [_nativeMainScrollDelegate delegateMethod:scrollView]; \ + if ([_nativeScrollDelegate respondsToSelector:_cmd]) { \ + [_nativeScrollDelegate delegateMethod:scrollView]; \ } \ } #define RCT_FORWARD_SCROLL_EVENT(call) \ -if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { \ - [_nativeMainScrollDelegate call]; \ +if ([_nativeScrollDelegate respondsToSelector:_cmd]) { \ + [_nativeScrollDelegate call]; \ } RCT_SCROLL_EVENT_HANDLER(scrollViewDidEndScrollingAnimation, RCTScrollEventTypeEndDeceleration) @@ -706,8 +706,8 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove) - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView { - if ([_nativeMainScrollDelegate respondsToSelector:_cmd]) { - return [_nativeMainScrollDelegate scrollViewShouldScrollToTop:scrollView]; + if ([_nativeScrollDelegate respondsToSelector:_cmd]) { + return [_nativeScrollDelegate scrollViewShouldScrollToTop:scrollView]; } return YES; } diff --git a/React/Views/RCTScrollViewManager.h b/React/Views/RCTScrollViewManager.h index 83b3126e8..a53bf4c80 100644 --- a/React/Views/RCTScrollViewManager.h +++ b/React/Views/RCTScrollViewManager.h @@ -19,4 +19,3 @@ @interface RCTScrollViewManager : RCTViewManager @end - diff --git a/React/Views/RCTScrollViewManager.m b/React/Views/RCTScrollViewManager.m index fdefe32cc..702b75043 100644 --- a/React/Views/RCTScrollViewManager.m +++ b/React/Views/RCTScrollViewManager.m @@ -70,7 +70,6 @@ RCT_EXPORT_VIEW_PROPERTY(onRefreshStart, RCTDirectEventBlock) - (NSDictionary *)constantsToExport { return @{ - // TODO: unused - remove these? @"DecelerationRate": @{ @"normal": @(UIScrollViewDecelerationRateNormal), @"fast": @(UIScrollViewDecelerationRateFast), @@ -118,7 +117,7 @@ RCT_EXPORT_METHOD(calculateChildFrames:(nonnull NSNumber *)reactTag RCT_EXPORT_METHOD(endRefreshing:(nonnull NSNumber *)reactTag) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { - + RCTScrollView *view = viewRegistry[reactTag]; if (!view || ![view isKindOfClass:[RCTScrollView class]]) { RCTLogError(@"Cannot find RCTScrollView with tag #%@", reactTag); @@ -126,10 +125,44 @@ RCT_EXPORT_METHOD(endRefreshing:(nonnull NSNumber *)reactTag) } [view endRefreshing]; - }]; } +RCT_EXPORT_METHOD(scrollTo:(nonnull NSNumber *)reactTag withOffset:(CGPoint)offset) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){ + UIView *view = viewRegistry[reactTag]; + if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { + [(id)view scrollToOffset:offset animated:YES]; + } else { + RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag #%@", view, reactTag); + } + }]; +} + +RCT_EXPORT_METHOD(scrollWithoutAnimationTo:(nonnull NSNumber *)reactTag withOffset:(CGPoint)offset) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){ + UIView *view = viewRegistry[reactTag]; + if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { + [(id)view scrollToOffset:offset animated:NO]; + } else { + RCTLogError(@"tried to scrollToOffset: on non-RCTScrollableProtocol view %@ with tag #%@", view, reactTag); + } + }]; +} + +RCT_EXPORT_METHOD(zoomToRect:(nonnull NSNumber *)reactTag withRect:(CGRect)rect) +{ + [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry){ + UIView *view = viewRegistry[reactTag]; + if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) { + [(id)view zoomToRect:rect animated:YES]; + } else { + RCTLogError(@"tried to zoomToRect: on non-RCTScrollableProtocol view %@ with tag #%@", view, reactTag); + } + }]; +} - (NSArray *)customDirectEventTypes { @@ -144,4 +177,3 @@ RCT_EXPORT_METHOD(endRefreshing:(nonnull NSNumber *)reactTag) } @end - diff --git a/React/Views/RCTScrollableProtocol.h b/React/Views/RCTScrollableProtocol.h index f612a7afa..f871d5192 100644 --- a/React/Views/RCTScrollableProtocol.h +++ b/React/Views/RCTScrollableProtocol.h @@ -15,7 +15,7 @@ */ @protocol RCTScrollableProtocol -@property (nonatomic, weak) NSObject *nativeMainScrollDelegate; +@property (nonatomic, weak) NSObject *nativeScrollDelegate; @property (nonatomic, readonly) CGSize contentSize; - (void)scrollToOffset:(CGPoint)offset; diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 67b171ee9..38e78cc65 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -719,11 +719,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements mOperationsQueue.enqueueShowPopupMenu(reactTag, items, error, success); } - @ReactMethod - public void setMainScrollViewTag(int reactTag) { - // TODO(6588266): Implement if required - } - @ReactMethod public void configureNextLayoutAnimation( ReadableMap config,