Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ScrollView): Update ScrollView JS to latest from upstream #993

Merged
merged 2 commits into from
Feb 9, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 109 additions & 35 deletions Libraries/Components/ScrollView/ScrollView.windows.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ const requireNativeComponent = require('requireNativeComponent');
*
* Doesn't yet support other contained responders from blocking this scroll
* view from becoming the responder.
*
*
* `<ScrollView>` vs `<ListView>` - which one to use?
* ScrollView simply renders all its react child components at once. That
* makes it very easy to understand and use.
* On the other hand, this has a performance downside. Imagine you have a very
* long list of items you want to display, worth of couple of your ScrollView’s
* heights. Creating JS components and native views upfront for all its items,
* which may not even be shown, will contribute to slow rendering of your
* screen and increased memory usage.
*
* This is where ListView comes into play. ListView renders items lazily,
* just when they are about to appear. This laziness comes at cost of a more
* complicated API, which is worth it unless you are rendering a small fixed
* set of items.
*/
const ScrollView = React.createClass({
propTypes: {
Expand Down Expand Up @@ -177,12 +192,18 @@ const ScrollView = React.createClass({
'on-drag',
]),
/**
* When false, tapping outside of the focused text input when the keyboard
* is up dismisses the keyboard. When true, the keyboard will not dismiss
* automatically, and the scroll view will not catch taps, but children of
* the scroll view can catch taps. The default value is false.
* Determines when the keyboard should stay visible after a tap.
*
* - 'never' (the default), tapping outside of the focused text input when the keyboard
* is up dismisses the keyboard. When this happens, children won't receive the tap.
* - 'always', the keyboard will not dismiss automatically, and the scroll view will not
* catch taps, but children of the scroll view can catch taps.
* - 'handled', the keyboard will not dismiss automatically when the tap was handled by
* a children, (or captured by an ancestor).
* - false, deprecated, use 'never' instead
* - true, deprecated, use 'always' instead
*/
keyboardShouldPersistTaps: PropTypes.bool,
keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled', false, true]),
/**
* The maximum allowed zoom scale. The default value is 1.0.
* @platform ios
Expand Down Expand Up @@ -305,7 +326,8 @@ const ScrollView = React.createClass({

/**
* A RefreshControl component, used to provide pull-to-refresh
* functionality for the ScrollView.
* functionality for the ScrollView. Only works for vertical ScrollViews
* (`horizontal` prop must be `false`).
*
* See [RefreshControl](docs/refreshcontrol.html).
*/
Expand All @@ -329,6 +351,24 @@ const ScrollView = React.createClass({
*/
scrollPerfTag: PropTypes.string,

/**
* Used to override default value of overScroll mode.
*
* Possible values:
*
* - `'auto'` - Default value, allow a user to over-scroll
* this view only if the content is large enough to meaningfully scroll.
* - `'always'` - Always allow a user to over-scroll this view.
* - `'never'` - Never allow a user to over-scroll this view.
*
* @platform android
*/
overScrollMode: PropTypes.oneOf([
'auto',
'always',
'never',
]),

/**
* Enables zoom on a scroll view for Windows.
* @platform windows
Expand Down Expand Up @@ -367,11 +407,11 @@ const ScrollView = React.createClass({
/**
* Scrolls to a given x, y offset, either immediately or with a smooth animation.
*
* Syntax:
* Example:
*
* `scrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})`
* `scrollTo({x: 0; y: 0; animated: true})`
*
* Note: The weird argument signature is due to the fact that, for historical reasons,
* Note: The weird function signature is due to the fact that, for historical reasons,
* the function also accepts separate arguments as as alternative to the options object.
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
*/
Expand All @@ -389,7 +429,25 @@ const ScrollView = React.createClass({
},

/**
* Deprecated, do not use.
* If this is a vertical ScrollView scrolls to the bottom.
* If this is a horizontal ScrollView scrolls to the right.
*
* Use `scrollToEnd({animated: true})` for smooth animated scrolling,
* `scrollToEnd({animated: false})` for immediate scrolling.
* If no options are passed, `animated` defaults to true.
*/
scrollToEnd: function(
options?: { animated?: boolean },
) {
// Default to true
const animated = (options && options.animated) !== false;
this.getScrollResponder().scrollResponderScrollToEnd({
animated: animated,
});
},

/**
* Deprecated, use `scrollTo` instead.
*/
scrollWithoutAnimationTo: function(y: number = 0, x: number = 0) {
console.warn('`scrollWithoutAnimationTo` is deprecated. Use `scrollTo` instead');
Expand Down Expand Up @@ -432,6 +490,33 @@ const ScrollView = React.createClass({
},

render: function() {
let ScrollViewClass;
let ScrollContentContainerViewClass;
if (Platform.OS === 'ios') {
ScrollViewClass = RCTScrollView;
ScrollContentContainerViewClass = RCTScrollContentView;
} else if (Platform.OS === 'android') {
if (this.props.horizontal) {
ScrollViewClass = AndroidHorizontalScrollView;
} else {
ScrollViewClass = AndroidScrollView;
}
ScrollContentContainerViewClass = View;
} else if (Platform.OS === 'windows') {
ScrollViewClass = RCTScrollView;
ScrollContentContainerViewClass = View;
}

invariant(
ScrollViewClass !== undefined,
'ScrollViewClass must not be undefined'
);

invariant(
ScrollContentContainerViewClass !== undefined,
'ScrollContentContainerViewClass must not be undefined'
);

const contentContainerStyle = [
this.props.horizontal && styles.contentContainerHorizontal,
this.props.contentContainerStyle,
Expand All @@ -456,14 +541,14 @@ const ScrollView = React.createClass({
}

const contentContainer =
<View
<ScrollContentContainerViewClass
{...contentSizeChangeProps}
ref={this._setInnerViewRef}
style={contentContainerStyle}
removeClippedSubviews={this.props.removeClippedSubviews}
collapsable={false}>
{this.props.children}
</View>;
</ScrollContentContainerViewClass>;

const alwaysBounceHorizontal =
this.props.alwaysBounceHorizontal !== undefined ?
Expand Down Expand Up @@ -508,23 +593,6 @@ const ScrollView = React.createClass({
props.decelerationRate = processDecelerationRate(decelerationRate);
}

let ScrollViewClass;
if (Platform.OS === 'ios') {
ScrollViewClass = RCTScrollView;
} else if (Platform.OS === 'android') {
if (this.props.horizontal) {
ScrollViewClass = AndroidHorizontalScrollView;
} else {
ScrollViewClass = AndroidScrollView;
}
} else if (Platform.OS === 'windows') {
ScrollViewClass = RCTScrollView;
}
invariant(
ScrollViewClass !== undefined,
'ScrollViewClass must not be undefined'
);

const refreshControl = this.props.refreshControl;
if (refreshControl) {
if (Platform.OS === 'ios') {
Expand All @@ -539,10 +607,13 @@ const ScrollView = React.createClass({
// On Android wrap the ScrollView with a AndroidSwipeRefreshLayout.
// Since the ScrollView is wrapped add the style props to the
// AndroidSwipeRefreshLayout and use flex: 1 for the ScrollView.
// Note: we should only apply props.style on the wrapper
// however, the ScrollView still needs the baseStyle to be scrollable

return React.cloneElement(
refreshControl,
{style: props.style},
<ScrollViewClass {...props} ref={this._setScrollViewRef}>
<ScrollViewClass {...props} style={baseStyle} ref={this._setScrollViewRef}>
{contentContainer}
</ScrollViewClass>
);
Expand All @@ -558,12 +629,14 @@ const ScrollView = React.createClass({

const styles = StyleSheet.create({
baseVertical: {
flex: 1,
flexGrow: 1,
flexShrink: 1,
flexDirection: 'column',
overflow: 'scroll',
},
baseHorizontal: {
flex: 1,
flexGrow: 1,
flexShrink: 1,
flexDirection: 'row',
overflow: 'scroll',
},
Expand All @@ -572,7 +645,7 @@ const styles = StyleSheet.create({
},
});

let nativeOnlyProps, AndroidScrollView, AndroidHorizontalScrollView, RCTScrollView;
let nativeOnlyProps, AndroidScrollView, AndroidHorizontalScrollView, RCTScrollView, RCTScrollContentView;
if (Platform.OS === 'android') {
nativeOnlyProps = {
nativeOnly: {
Expand All @@ -595,8 +668,9 @@ if (Platform.OS === 'android') {
}
};
RCTScrollView = requireNativeComponent('RCTScrollView', ScrollView, nativeOnlyProps);
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
} else if (Platform.OS === 'windows') {
RCTScrollView = requireNativeComponent('RCTScrollView', ScrollView);
RCTScrollView = requireNativeComponent('RCTScrollView', ScrollView);
}

module.exports = ScrollView;
module.exports = ScrollView;