diff --git a/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js b/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js new file mode 100644 index 00000000000000..78558aac78b808 --- /dev/null +++ b/Libraries/Components/RefreshControl/AndroidSwipeRefreshLayoutNativeComponent.js @@ -0,0 +1,68 @@ +/** + * 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. + * + * @format + * @flow + */ + +'use strict'; + +const requireNativeComponent = require('requireNativeComponent'); + +import type {ColorValue} from 'StyleSheetTypes'; +import type {ViewProps} from 'ViewPropTypes'; +import type {NativeComponent} from 'ReactNative'; + +const AndroidSwipeRefreshLayout = require('UIManager').getViewManagerConfig( + 'AndroidSwipeRefreshLayout', +); +const RefreshLayoutConsts = AndroidSwipeRefreshLayout + ? AndroidSwipeRefreshLayout.Constants + : {SIZE: {}}; + +type NativeProps = $ReadOnly<{| + ...ViewProps, + + /** + * Whether the pull to refresh functionality is enabled. + */ + enabled?: ?boolean, + /** + * The colors (at least one) that will be used to draw the refresh indicator. + */ + colors?: ?$ReadOnlyArray, + /** + * The background color of the refresh indicator. + */ + progressBackgroundColor?: ?ColorValue, + /** + * Size of the refresh indicator, see RefreshControl.SIZE. + */ + size?: ?( + | typeof RefreshLayoutConsts.SIZE.DEFAULT + | typeof RefreshLayoutConsts.SIZE.LARGE + ), + /** + * Progress view top offset + */ + progressViewOffset?: ?number, + + /** + * Called when the view starts refreshing. + */ + onRefresh?: ?() => mixed, + + /** + * Whether the view should be indicating an active refresh. + */ + refreshing: boolean, +|}>; + +type AndroidSwipeRefreshLayoutNativeType = Class>; + +module.exports = ((requireNativeComponent( + 'AndroidSwipeRefreshLayout', +): any): AndroidSwipeRefreshLayoutNativeType); diff --git a/Libraries/Components/RefreshControl/RCTRefreshControlNativeComponent.js b/Libraries/Components/RefreshControl/RCTRefreshControlNativeComponent.js new file mode 100644 index 00000000000000..a3262d46436e60 --- /dev/null +++ b/Libraries/Components/RefreshControl/RCTRefreshControlNativeComponent.js @@ -0,0 +1,50 @@ +/** + * 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. + * + * @format + * @flow + */ + +'use strict'; + +const requireNativeComponent = require('requireNativeComponent'); + +import type {ColorValue} from 'StyleSheetTypes'; +import type {ViewProps} from 'ViewPropTypes'; +import type {NativeComponent} from 'ReactNative'; + +export type NativeProps = $ReadOnly<{| + ...ViewProps, + + /** + * The color of the refresh indicator. + */ + tintColor?: ?ColorValue, + /** + * Title color. + */ + titleColor?: ?ColorValue, + /** + * The title displayed under the refresh indicator. + */ + title?: ?string, + + /** + * Called when the view starts refreshing. + */ + onRefresh?: ?() => mixed, + + /** + * Whether the view should be indicating an active refresh. + */ + refreshing: boolean, +|}>; + +type RCTRefreshControlNativeType = Class>; + +module.exports = ((requireNativeComponent( + 'RCTRefreshControl', +): any): RCTRefreshControlNativeType); diff --git a/Libraries/Components/RefreshControl/RefreshControl.js b/Libraries/Components/RefreshControl/RefreshControl.js index ac6853e2addcb5..bbb3246a47d50e 100644 --- a/Libraries/Components/RefreshControl/RefreshControl.js +++ b/Libraries/Components/RefreshControl/RefreshControl.js @@ -14,7 +14,8 @@ const Platform = require('Platform'); const React = require('React'); const {NativeComponent} = require('ReactNative'); -const requireNativeComponent = require('requireNativeComponent'); +const AndroidSwipeRefreshLayoutNativeComponent = require('AndroidSwipeRefreshLayoutNativeComponent'); +const RCTRefreshControlNativeComponent = require('RCTRefreshControlNativeComponent'); const nullthrows = require('nullthrows'); import type {ColorValue} from 'StyleSheetTypes'; @@ -31,12 +32,6 @@ if (Platform.OS === 'android') { } else { RefreshLayoutConsts = {SIZE: {}}; } -type NativeRefreshControlType = Class>; - -const NativeRefreshControl: NativeRefreshControlType = - Platform.OS === 'ios' - ? (requireNativeComponent('RCTRefreshControl'): any) - : (requireNativeComponent('AndroidSwipeRefreshLayout'): any); type IOSProps = $ReadOnly<{| /** @@ -143,7 +138,7 @@ export type RefreshControlProps = $ReadOnly<{| class RefreshControl extends React.Component { static SIZE = RefreshLayoutConsts.SIZE; - _nativeRef: ?React.ElementRef = null; + _setNativePropsOnRef: ?({refreshing: boolean}) => void; _lastNativeRefreshing = false; componentDidMount() { @@ -156,8 +151,11 @@ class RefreshControl extends React.Component { // the js value. if (this.props.refreshing !== prevProps.refreshing) { this._lastNativeRefreshing = this.props.refreshing; - } else if (this.props.refreshing !== this._lastNativeRefreshing) { - nullthrows(this._nativeRef).setNativeProps({ + } else if ( + this.props.refreshing !== this._lastNativeRefreshing && + this._setNativePropsOnRef + ) { + this._setNativePropsOnRef({ refreshing: this.props.refreshing, }); this._lastNativeRefreshing = this.props.refreshing; @@ -165,15 +163,34 @@ class RefreshControl extends React.Component { } render() { - return ( - { - this._nativeRef = ref; - }} - onRefresh={this._onRefresh} - /> - ); + const setRef = ref => + (this._setNativePropsOnRef = ref ? ref.setNativeProps.bind(ref) : null); + if (Platform.OS === 'ios') { + const { + enabled, + colors, + progressBackgroundColor, + size, + progressViewOffset, + ...props + } = this.props; + return ( + + ); + } else { + const {tintColor, titleColor, title, ...props} = this.props; + return ( + + ); + } } _onRefresh = () => {