From 2d80a248cd0467dfec937f1c3fcd5249b610df04 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 19 Nov 2019 10:02:26 -0800 Subject: [PATCH] Migrate RefreshControl to Native Commands Summary: Changelog: [Internal] Introduce native command `setNativeRefreshing`, it has the word Native in order to avoid name conflict with setRefreshing in Android implementation. Even this component is iOS only, it would make it easier to merge them in the future. Introduce `RCTRefreshableProtocol` and make `RCTRefreshControl` and `RCTPullToRefreshViewComponentView` to conform to the protocol so view manager can forward command to both, Paper and Fabric component. Reviewed By: mmmulani Differential Revision: D18475804 fbshipit-source-id: 4c19225784efc931b7b8f2d2671cc839bce429bf --- .../PullToRefreshViewNativeComponent.js | 15 ++++++++ .../RCTPullToRefreshViewComponentView.mm | 35 +++++++++++++++++++ .../{ => RefreshControl}/RCTRefreshControl.h | 0 .../{ => RefreshControl}/RCTRefreshControl.m | 8 +++-- .../RCTRefreshControlManager.h | 0 .../RCTRefreshControlManager.m | 17 ++++++++- .../RefreshControl/RCTRefreshableProtocol.h | 20 +++++++++++ .../PullToRefreshViewManagerDelegate.java | 9 +++++ .../PullToRefreshViewManagerInterface.java | 1 + 9 files changed, 102 insertions(+), 3 deletions(-) rename React/Views/{ => RefreshControl}/RCTRefreshControl.h (100%) rename React/Views/{ => RefreshControl}/RCTRefreshControl.m (96%) rename React/Views/{ => RefreshControl}/RCTRefreshControlManager.h (100%) rename React/Views/{ => RefreshControl}/RCTRefreshControlManager.m (51%) create mode 100644 React/Views/RefreshControl/RCTRefreshableProtocol.h diff --git a/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js b/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js index 44ee3de85fd..c3142b11e7d 100644 --- a/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js +++ b/Libraries/Components/RefreshControl/PullToRefreshViewNativeComponent.js @@ -13,9 +13,11 @@ import type {DirectEventHandler, WithDefault} from '../../Types/CodegenTypes'; import type {ColorValue} from '../../StyleSheet/StyleSheetTypes'; import type {ViewProps} from '../View/ViewPropTypes'; +import * as React from 'react'; import codegenNativeComponent from '../../Utilities/codegenNativeComponent'; import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; type NativeProps = $ReadOnly<{| ...ViewProps, @@ -44,6 +46,19 @@ type NativeProps = $ReadOnly<{| refreshing: boolean, |}>; +type ComponentType = HostComponent; + +interface NativeCommands { + +setNativeRefreshing: ( + viewRef: React.ElementRef, + refreshing: boolean, + ) => void; +} + +export const Commands: NativeCommands = codegenNativeCommands({ + supportedCommands: ['setNativeRefreshing'], +}); + export default (codegenNativeComponent('PullToRefreshView', { paperComponentName: 'RCTRefreshControl', }): HostComponent); diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm index 84c218197fc..6bb0c800e44 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTPullToRefreshViewComponentView.mm @@ -10,12 +10,17 @@ #import #import #import +#import #import +#import #import using namespace facebook::react; +@interface RCTPullToRefreshViewComponentView () +@end + @implementation RCTPullToRefreshViewComponentView { UIRefreshControl *_refreshControl; RCTScrollViewComponentView *_scrollViewComponentView; @@ -145,4 +150,34 @@ using namespace facebook::react; _scrollViewComponentView = nil; } +#pragma mark - Native commands + +- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args +{ + RCTPullToRefreshViewHandleCommand(self, commandName, args); +} + +- (void)setNativeRefreshing:(BOOL)refreshing +{ + if (refreshing) { + [_refreshControl beginRefreshing]; + } else { + [_refreshControl endRefreshing]; + } +} + +#pragma mark - RCTRefreshableProtocol + +- (void)setRefreshing:(BOOL)refreshing +{ + [self setNativeRefreshing:refreshing]; +} + +#pragma mark - + +- (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN +{ + return @"RefreshControl"; +} + @end diff --git a/React/Views/RCTRefreshControl.h b/React/Views/RefreshControl/RCTRefreshControl.h similarity index 100% rename from React/Views/RCTRefreshControl.h rename to React/Views/RefreshControl/RCTRefreshControl.h diff --git a/React/Views/RCTRefreshControl.m b/React/Views/RefreshControl/RCTRefreshControl.m similarity index 96% rename from React/Views/RCTRefreshControl.m rename to React/Views/RefreshControl/RCTRefreshControl.m index 661616d2245..4887a888b09 100644 --- a/React/Views/RCTRefreshControl.m +++ b/React/Views/RefreshControl/RCTRefreshControl.m @@ -6,9 +6,13 @@ */ #import "RCTRefreshControl.h" +#import "RCTRefreshableProtocol.h" #import "RCTUtils.h" +@interface RCTRefreshControl () +@end + @implementation RCTRefreshControl { BOOL _isInitialRender; BOOL _currentRefreshingState; @@ -45,9 +49,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) // If the control is refreshing when mounted we need to call // beginRefreshing in layoutSubview or it doesn't work. - if (_currentRefreshingState && _isInitialRender) { + if (_currentRefreshingState && _isInitialRender) { [self beginRefreshingProgrammatically]; - } + } _isInitialRender = false; } diff --git a/React/Views/RCTRefreshControlManager.h b/React/Views/RefreshControl/RCTRefreshControlManager.h similarity index 100% rename from React/Views/RCTRefreshControlManager.h rename to React/Views/RefreshControl/RCTRefreshControlManager.h diff --git a/React/Views/RCTRefreshControlManager.m b/React/Views/RefreshControl/RCTRefreshControlManager.m similarity index 51% rename from React/Views/RCTRefreshControlManager.m rename to React/Views/RefreshControl/RCTRefreshControlManager.m index e5ef33215be..2e6282c1d4c 100644 --- a/React/Views/RCTRefreshControlManager.m +++ b/React/Views/RefreshControl/RCTRefreshControlManager.m @@ -5,8 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -#import "RCTRefreshControlManager.h" +#import +#import "RCTRefreshControlManager.h" +#import "RCTRefreshableProtocol.h" #import "RCTRefreshControl.h" @implementation RCTRefreshControlManager @@ -24,4 +26,17 @@ RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor) RCT_EXPORT_VIEW_PROPERTY(title, NSString) RCT_EXPORT_VIEW_PROPERTY(titleColor, UIColor) +RCT_EXPORT_METHOD(setNativeRefreshing : (nonnull NSNumber *)viewTag toRefreshing : (BOOL)refreshing) +{ + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + UIView *view = viewRegistry[viewTag]; + + if ([view conformsToProtocol:@protocol(RCTRefreshableProtocol)]) { + [(id)view setRefreshing: refreshing]; + } else { + RCTLogError(@"view must conform to protocol RCTRefreshableProtocol"); + } + }]; +} + @end diff --git a/React/Views/RefreshControl/RCTRefreshableProtocol.h b/React/Views/RefreshControl/RCTRefreshableProtocol.h new file mode 100644 index 00000000000..1f885d845eb --- /dev/null +++ b/React/Views/RefreshControl/RCTRefreshableProtocol.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +/** + * Protocol used to dispatch commands in `RCTRefreshControlManager.h`. + * This is in order to support commands for both Paper and Fabric components + * during migration. + */ +@protocol RCTRefreshableProtocol + +- (void)setRefreshing:(BOOL)refreshing; + +@end diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java index 77fb5e2a002..7425904720b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java @@ -11,6 +11,7 @@ package com.facebook.react.viewmanagers; import android.view.View; import androidx.annotation.Nullable; +import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.BaseViewManagerDelegate; import com.facebook.react.uimanager.BaseViewManagerInterface; import com.facebook.react.uimanager.LayoutShadowNode; @@ -38,4 +39,12 @@ public class PullToRefreshViewManagerDelegate viewManager, T view, String commandName, ReadableArray args) { + switch (commandName) { + case "setNativeRefreshing": + viewManager.setNativeRefreshing(view, args.getBoolean(0)); + break; + } + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java index cbc8f16b672..4f40ee89cbb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java +++ b/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java @@ -17,4 +17,5 @@ public interface PullToRefreshViewManagerInterface { void setTitleColor(T view, @Nullable Integer value); void setTitle(T view, @Nullable String value); void setRefreshing(T view, boolean value); + void setNativeRefreshing(T view, boolean refreshing); }