diff --git a/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js b/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js index e497288..5465e97 100644 --- a/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js +++ b/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js @@ -1776,9 +1776,15 @@ class ScrollView extends React.Component { // Note: we should split props.style on the inner and outer props // however, the ScrollView still needs the baseStyle to be scrollable const {outer, inner} = splitLayoutProps(flattenStyle(props.style)); + let inverted; + if (inner.scaleY) { + inverted = {scaleY: -1}; + delete inner['scaleY'] + } + return React.cloneElement( refreshControl, - {style: StyleSheet.compose(baseStyle, outer)}, + {style: [baseStyle, outer, inverted]}, { * Param `animated` (`true` by default) defines whether the list * should do an animation while scrolling. */ - scrollToOffset(params: {animated?: ?boolean, offset: number, ...}) { - const {animated, offset} = params; +scrollToOffset(params: {animated?: ?boolean, offset: number, ...}) { + const {animated, offset} = params; - if (this._scrollRef == null) { - return; - } - - if (this._scrollRef.scrollTo == null) { - console.warn( - 'No scrollTo method provided. This may be because you have two nested ' + - 'VirtualizedLists with the same orientation, or because you are ' + - 'using a custom component that does not implement scrollTo.', - ); - return; - } + if (this._scrollRef == null) { + return; + } - this._scrollRef.scrollTo( - horizontalOrDefault(this.props.horizontal) - ? {x: offset, animated} - : {y: offset, animated}, + if (this._scrollRef.scrollTo == null) { + console.warn( + 'No scrollTo method provided. This may be because you have two nested ' + + 'VirtualizedLists with the same orientation, or because you are ' + + 'using a custom component that does not implement scrollTo.', ); + return; } + this._scrollRef.scrollTo( + horizontalOrDefault(this.props.horizontal) + ? {x: offset, animated} + : {y: offset, animated}, + ); +} + recordInteraction() { this._nestedChildLists.forEach(childList => { childList.ref && childList.ref.recordInteraction(); @@ -1221,6 +1222,7 @@ class VirtualizedList extends React.PureComponent { _totalCellsMeasured = 0; _updateCellsToRenderBatcher: Batchinator; _viewabilityTuples: Array = []; + _hasDoneFirstScroll = false; _captureScrollRef = ref => { this._scrollRef = ref; @@ -1495,31 +1497,40 @@ class VirtualizedList extends React.PureComponent { return !horizontalOrDefault(this.props.horizontal) ? metrics.y : metrics.x; } - _maybeCallOnEndReached() { - const { - data, - getItemCount, - onEndReached, - onEndReachedThreshold, - } = this.props; - const {contentLength, visibleLength, offset} = this._scrollMetrics; - const distanceFromEnd = contentLength - visibleLength - offset; - const threshold = - onEndReachedThreshold != null ? onEndReachedThreshold * visibleLength : 2; + _maybeCallOnEndReached(hasShrunkContentLength: boolean = false) { + const {onEndReached, onEndReachedThreshold} = this.props; + if (!onEndReached) { + return; + } + const {contentLength, visibleLength, offset, dOffset} = this._scrollMetrics; + // If this is just after the initial rendering if ( - onEndReached && - this.state.last === getItemCount(data) - 1 && - distanceFromEnd < threshold && - this._scrollMetrics.contentLength !== this._sentEndForContentLength + !hasShrunkContentLength && + !this._hasDoneFirstScroll && + offset === 0 ) { - // Only call onEndReached once for a given content length - this._sentEndForContentLength = this._scrollMetrics.contentLength; - onEndReached({distanceFromEnd}); - } else if (distanceFromEnd > threshold) { - // If the user scrolls away from the end and back again cause - // an onEndReached to be triggered again - this._sentEndForContentLength = 0; + return; + } + // If scrolled up in the vertical list + if (dOffset < 0) { + return; + } + // If contentLength has not changed + if (contentLength === this._sentEndForContentLength) { + return; + } + const distanceFromEnd = contentLength - visibleLength - offset; + // If the distance is so farther than the area shown on the screen + if (distanceFromEnd >= visibleLength * 1.5) { + return; + } + // $FlowFixMe + const minimumDistanceFromEnd = onEndReachedThreshold !== null ? onEndReachedThreshold * visibleLength : 2; + if (distanceFromEnd >= minimumDistanceFromEnd) { + return; } + this._sentEndForContentLength = contentLength; + onEndReached({distanceFromEnd}); } _onContentSizeChange = (width: number, height: number) => { @@ -1541,9 +1552,21 @@ class VirtualizedList extends React.PureComponent { if (this.props.onContentSizeChange) { this.props.onContentSizeChange(width, height); } - this._scrollMetrics.contentLength = this._selectLength({height, width}); + const {contentLength: currentContentLength} = this._scrollMetrics; + const contentLength = this._selectLength({height, width}); + this._scrollMetrics.contentLength = contentLength; this._scheduleCellsToRenderUpdate(); - this._maybeCallOnEndReached(); + const hasShrunkContentLength = + currentContentLength > 0 && + contentLength > 0 && + contentLength < currentContentLength; + if ( + hasShrunkContentLength && + this._sentEndForContentLength >= contentLength + ) { + this._sentEndForContentLength = 0; + } + this._maybeCallOnEndReached(hasShrunkContentLength); }; /* Translates metrics from a scroll event in a parent VirtualizedList into @@ -1631,6 +1654,7 @@ class VirtualizedList extends React.PureComponent { if (!this.props) { return; } + this._hasDoneFirstScroll = true; this._maybeCallOnEndReached(); if (velocity !== 0) { this._fillRateHelper.activate(); @@ -2119,7 +2143,14 @@ function describeNestedLists(childList: { const styles = StyleSheet.create({ verticallyInverted: { - transform: [{scaleY: -1}], + ...Platform.select({ + android: { + scaleY: -1, + }, + ios: { + transform: [{scaleY: -1}], + }, + }), }, horizontallyInverted: { transform: [{scaleX: -1}], diff --git a/node_modules/react-native/react.gradle b/node_modules/react-native/react.gradle index ff46476..90e66db 100644 --- a/node_modules/react-native/react.gradle +++ b/node_modules/react-native/react.gradle @@ -151,7 +151,7 @@ afterEvaluate { // Set up dev mode def devEnabled = !(config."devDisabledIn${targetName}" - || targetName.toLowerCase().contains("release")) + || targetName.toLowerCase().contains("release") || targetName.toLowerCase().contains("unsigned")) def extraArgs = [] @@ -180,7 +180,7 @@ afterEvaluate { def hermesFlags; def hbcTempFile = file("${jsBundleFile}.hbc") exec { - if (targetName.toLowerCase().contains("release")) { + if (targetName.toLowerCase().contains("release") || targetName.toLowerCase().contains("unsigned")) { // Can't use ?: since that will also substitute valid empty lists hermesFlags = config.hermesFlagsRelease if (hermesFlags == null) hermesFlags = ["-O", "-output-source-map"] @@ -224,7 +224,7 @@ afterEvaluate { ? config."bundleIn${targetName}" : config."bundleIn${variant.buildType.name.capitalize()}" != null ? config."bundleIn${variant.buildType.name.capitalize()}" - : targetName.toLowerCase().contains("release") + : (targetName.toLowerCase().contains("release") || targetName.toLowerCase().contains("unsigned")) } // Expose a minimal interface on the application variant and the task itself: @@ -328,7 +328,7 @@ afterEvaluate { // This should really be done by packaging all Hermes related libs into // two separate HermesDebug and HermesRelease AARs, but until then we'll // kludge it by deleting the .so files out of the /transforms/ directory. - def isRelease = targetName.toLowerCase().contains("release") + def isRelease = targetName.toLowerCase().contains("release") || targetName.toLowerCase().contains("unsigned") def libDir = "$buildDir/intermediates/transforms/" def vmSelectionAction = { fileTree(libDir).matching {