Compare commits

...
Author SHA1 Message Date
Mike Grabowski 5db36da8a1 [0.41.0] Bump version numbers 2017-02-02 18:51:58 +01:00
Emil SjolanderandMike Grabowski d32cf68ff8 Resolve conflicts 2017-02-02 18:50:41 +01:00
rh389andMike Grabowski 2b087c2c94 Fix template release build: Add -ObjC and -lc++ to tests target
Summary:
Fixes https://github.com/facebook/react-native/issues/11861 - the release config is currently broken for projects created by `react-native init` in `master`, 0.40 and 0.39.

I'm still investigating when and how this got broken but this seems to be a clean fix. I've added `-ObjC` as well to match the main target but I'm not sure yet whether that's necessary.

To test:
```
react-native init fooproject --version react-native@rh389/react-native#missinglinkerflags
```
Open in XCode, Edit scheme (⌘<), Change `Build Configuration` to `Release`, build.

Update: The `-lc++` flag became necessary when https://github.com/facebook/react-native/commit/33deaad196834e77a507cad7b13039161258c059 landed because of the libstdc++ dependencies of `RCTLog`. Still not sure about `-ObjC`. javache ?
Closes https://github.com/facebook/react-native/pull/11889

Differential Revision: D4421685

Pulled By: javache

fbshipit-source-id: 954edaef773f8cef7b7ad671fa4d1f2bfc2f20f2
2017-02-02 17:45:45 +01:00
Tomas RoosandMike Grabowski 7f98028e71 Fixes podspec for master #11640
Summary:
Currently the master Podspec is broken because tvOS files are being included, to avoid this compile error the file is being excluded.

https://github.com/facebook/react-native/commit/c92ad5f6ae74c1d398c7cd93d5c4c50da0ca0430

Thats the commit which introduced the breakage anything later that that will fail. Aka RN 0.41 will fail because of this.

**Test plan (required)**

Tested on new project against master

// cc ide
Closes https://github.com/facebook/react-native/pull/11667

Differential Revision: D4375453

Pulled By: ericvicenti

fbshipit-source-id: 035cdb8ef36054b40d1aaf59551cdc2e16f0cb19
2017-02-02 17:45:18 +01:00
Martin Konicek f1fdd8914a [0.41.0-rc.1] Bump version numbers 2017-01-30 18:44:24 +00:00
Martin Konicek 75f4033ca0 Support ScrollView.scrollToEnd on Android natively
Summary:
This is a followup for https://github.com/facebook/react-native/pull/12088 and implements the scrolling to end on Android natively rather than sending a large scroll offset from JS.

This turned out to be an OK amount of code, and some reduction in the amount of JavaScript. The only part I'm not particularly happy about is:

```
// ScrollView always has one child - the scrollable area
int bottom = scrollView.getChildAt(0).getHeight() + scrollView.getPaddingBottom();
```

According to multiple sources (e.g. [this SO answer](http://stackoverflow.com/questions/3609297/android-total-height-of-scrollview)) it is the way to get the total size of the scrollable area, similar to`scrollView.contentSize` on iOS but more ugly and relying on the fact the ScrollView always has a single child (hopefully this won't change in future versions of Android).

An alternative is:

```
View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
int bottom = lastChild.getBottom() + scrollLayout.getPadd
Closes https://github.com/facebook/react-native/pull/12101

Differential Revision: D4481523

Pulled By: mkonicek

fbshipit-source-id: 8c7967a0b9e06890c1e1ea70ad573c6eceb03daf
2017-01-30 18:42:46 +00:00
Martin Konicek 7f42a44751 Add scrollToEnd to ScrollView and ListView
Summary:
**Motivation**

A basic task of making a React Native ScrollView or ListView scroll to the bottom is currently very hard to accomplish:
- https://github.com/facebook/react-native/issues/8003
- https://github.com/facebook/react-native/issues/913
- http://stackoverflow.com/questions/29829375/how-to-scroll-to-bottom-in-react-native-listview

**NOTE:** If you're building something like a chat app where you want a ListView to keep scrolling to the bottom at all times, it's easiest to use the [react-native-invertible-scrollview](https://github.com/exponent/react-native-invertible-scroll-view) component rather calling `scrollToEnd` manually when layout changes. The invertible-scrollview uses a clever trick to invert the direction of the ScrollView.

This pull request adds a `scrollToEnd` method which scrolls to the bottom if the ScrollView is vertical, to the right if the ScrollView is horizontal.

The implementation is based on this SO answer:
http://stackoverflow.com/questions/952412/uiscrollview-scrol
Closes https://github.com/facebook/react-native/pull/12088

Differential Revision: D4474974

Pulled By: mkonicek

fbshipit-source-id: 6ecf8b3435f47dd3a31e2fd5be6859062711c233
2017-01-30 18:42:35 +00:00
Mike Grabowski b570c23cfe [0.41.0-rc.0] Bump version numbers 2017-01-04 13:48:22 +01:00
17 changed files with 210 additions and 22 deletions
@@ -57,6 +57,11 @@ exports.examples = [
onPress={() => { _scrollView.scrollTo({y: 0}); }}>
<Text>Scroll to top</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => { _scrollView.scrollToEnd({animated: true}); }}>
<Text>Scroll to bottom</Text>
</TouchableOpacity>
</View>
);
}
@@ -79,6 +84,11 @@ exports.examples = [
onPress={() => { _scrollView.scrollTo({x: 0}); }}>
<Text>Scroll to start</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => { _scrollView.scrollToEnd({animated: true}); }}>
<Text>Scroll to end</Text>
</TouchableOpacity>
</View>
);
}
+23 -3
View File
@@ -377,11 +377,11 @@ var ScrollResponderMixin = {
},
/**
* A helper function to scroll to a specific point in the scrollview.
* This is currently used to help focus on child textviews, but can also
* A helper function to scroll to a specific point in the ScrollView.
* This is currently used to help focus child TextViews, but can also
* be used to quickly scroll to any element we want to focus. Syntax:
*
* scrollResponderScrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})
* `scrollResponderScrollTo(options: {x: number = 0; y: number = 0; animated: boolean = true})`
*
* Note: The weird argument signature is due to the fact that, for historical reasons,
* the function also accepts separate arguments as as alternative to the options object.
@@ -404,6 +404,26 @@ var ScrollResponderMixin = {
);
},
/**
* Scrolls to the end of the ScrollView, either immediately or with a smooth
* animation.
*
* Example:
*
* `scrollResponderScrollToEnd({animated: true})`
*/
scrollResponderScrollToEnd: function(
options?: { animated?: boolean },
) {
// Default to true
const animated = (options && options.animated) !== false;
UIManager.dispatchViewManagerCommand(
this.scrollResponderGetScrollableNode(),
UIManager.RCTScrollView.Commands.scrollToEnd,
[animated],
);
},
/**
* Deprecated, do not use.
*/
+22 -4
View File
@@ -382,11 +382,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.
*/
@@ -404,7 +404,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');
@@ -287,6 +287,29 @@ var ListView = React.createClass({
}
},
/**
* If this is a vertical ListView scrolls to the bottom.
* If this is a horizontal ListView 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.
*
* See `ScrollView#scrollToEnd`.
*/
scrollToEnd: function(options?: { animated?: boolean }) {
if (this._scrollComponent) {
if (this._scrollComponent.scrollToEnd) {
this._scrollComponent.scrollToEnd(options);
} else {
console.warn(
'The scroll component used by the ListView does not support ' +
'scrollToEnd. Check the renderScrollComponent prop of your ListView.'
);
}
}
},
setNativeProps: function(props: Object) {
if (this._scrollComponent) {
this._scrollComponent.setNativeProps(props);
+7 -2
View File
@@ -4,7 +4,7 @@ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
Pod::Spec.new do |s|
s.name = "React"
s.version = package['version']
s.version = "0.41.0"
s.summary = package['description']
s.description = <<-DESC
React Native apps are built using the React JS
@@ -34,11 +34,16 @@ Pod::Spec.new do |s|
ss.dependency 'React/yoga'
ss.dependency 'React/cxxreact'
ss.source_files = "React/**/*.{c,h,m,mm,S}"
ss.exclude_files = "**/__tests__/*", "IntegrationTests/*", "ReactCommon/yoga/*"
ss.exclude_files = "**/__tests__/*", "IntegrationTests/*", "React/**/RCTTVView.*", "ReactCommon/yoga/*"
ss.frameworks = "JavaScriptCore"
ss.libraries = "stdc++"
end
s.subspec 'tvOS' do |ss|
ss.dependency 'React/Core'
ss.source_files = "React/**/RCTTVView.{h, m}"
end
s.subspec 'jschelpers' do |ss|
ss.source_files = 'ReactCommon/jschelpers/{JavaScriptCore,JSCWrapper}.{cpp,h}'
ss.header_dir = 'jschelpers'
+4 -4
View File
@@ -480,10 +480,10 @@ SEL RCTParseMethodSignature(NSString *methodSignature, NSArray<RCTMethodArgument
expectedCount -= 2;
}
RCTLogError(@"%@.%@ was called with %zd arguments, but expects %zd. \
If you haven\'t changed this method yourself, this usually means that \
your versions of the native code and JavaScript code are out of sync. \
Updating both should make this error go away.",
RCTLogError(@"%@.%@ was called with %zd arguments but expects %zd arguments. "
@"If you haven\'t changed this method yourself, this usually means that "
@"your versions of the native code and JavaScript code are out of sync. "
@"Updating both should make this error go away.",
RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName,
actualCount, expectedCount);
return nil;
+26 -1
View File
@@ -588,6 +588,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_scrollView.contentOffset = contentOffset;
}
- (BOOL)isHorizontal:(UIScrollView *)scrollView
{
return scrollView.contentSize.width > self.frame.size.width;
}
- (void)scrollToOffset:(CGPoint)offset
{
[self scrollToOffset:offset animated:YES];
@@ -602,6 +607,26 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
}
}
/**
* If this is a vertical scroll view, scrolls to the bottom.
* If this is a horizontal scroll view, scrolls to the right.
*/
- (void)scrollToEnd:(BOOL)animated
{
BOOL isHorizontal = [self isHorizontal:_scrollView];
CGPoint offset;
if (isHorizontal) {
offset = CGPointMake(_scrollView.contentSize.width - _scrollView.bounds.size.width, 0);
} else {
offset = CGPointMake(0, _scrollView.contentSize.height - _scrollView.bounds.size.height);
}
if (!CGPointEqualToPoint(_scrollView.contentOffset, offset)) {
// Ensure at least one scroll event will fire
_allowNextScrollNoMatterWhat = YES;
[_scrollView setContentOffset:offset animated:animated];
}
}
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
{
[_scrollView zoomToRect:rect animated:animated];
@@ -727,7 +752,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, onScroll)
CGFloat snapToIntervalF = (CGFloat)self.snapToInterval;
// Find which axis to snap
BOOL isHorizontal = (scrollView.contentSize.width > self.frame.size.width);
BOOL isHorizontal = [self isHorizontal:scrollView];
// What is the current offset?
CGFloat targetContentOffsetAlongAxis = isHorizontal ? targetContentOffset->x : targetContentOffset->y;
+15
View File
@@ -147,6 +147,21 @@ RCT_EXPORT_METHOD(scrollTo:(nonnull NSNumber *)reactTag
}];
}
RCT_EXPORT_METHOD(scrollToEnd:(nonnull NSNumber *)reactTag
animated:(BOOL)animated)
{
[self.bridge.uiManager addUIBlock:
^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry){
UIView *view = viewRegistry[reactTag];
if ([view conformsToProtocol:@protocol(RCTScrollableProtocol)]) {
[(id<RCTScrollableProtocol>)view scrollToEnd:animated];
} else {
RCTLogError(@"tried to scrollTo: on non-RCTScrollableProtocol view %@ "
"with tag #%@", view, reactTag);
}
}];
}
RCT_EXPORT_METHOD(zoomToRect:(nonnull NSNumber *)reactTag
withRect:(CGRect)rect
animated:(BOOL)animated)
+5
View File
@@ -19,6 +19,11 @@
- (void)scrollToOffset:(CGPoint)offset;
- (void)scrollToOffset:(CGPoint)offset animated:(BOOL)animated;
/**
* If this is a vertical scroll view, scrolls to the bottom.
* If this is a horizontal scroll view, scrolls to the right.
*/
- (void)scrollToEnd:(BOOL)animated;
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated;
- (void)addScrollListener:(NSObject<UIScrollViewDelegate> *)scrollListener;
+1 -1
View File
@@ -1,4 +1,4 @@
VERSION_NAME=1000.0.0-master
VERSION_NAME=0.41.0
GROUP=com.facebook.react
POM_NAME=ReactNative
@@ -80,6 +80,15 @@ public class RecyclerViewBackedScrollViewManager extends
scrollView.scrollTo(data.mDestX, data.mDestY, data.mAnimated);
}
@Override
public void scrollToEnd(
RecyclerViewBackedScrollView scrollView,
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
// Not implemented.
// RecyclerViewBackedScrollView is deprecated and will be removed.
// People should use a standard ScrollView or ListView instead.
}
@Override
public @Nullable
Map getExportedCustomDirectEventTypeConstants() {
@@ -117,6 +117,20 @@ public class ReactHorizontalScrollViewManager
}
}
@Override
public void scrollToEnd(
ReactHorizontalScrollView scrollView,
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
// ScrollView always has one child - the scrollable area
int right =
scrollView.getChildAt(0).getWidth() + scrollView.getPaddingRight();
if (data.mAnimated) {
scrollView.smoothScrollTo(right, scrollView.getScrollY());
} else {
scrollView.scrollTo(right, scrollView.getScrollY());
}
}
/**
* When set, fills the rest of the scrollview with a color to avoid setting a background and
* creating unnecessary overdraw.
@@ -25,9 +25,11 @@ import com.facebook.react.common.MapBuilder;
public class ReactScrollViewCommandHelper {
public static final int COMMAND_SCROLL_TO = 1;
public static final int COMMAND_SCROLL_TO_END = 2;
public interface ScrollCommandHandler<T> {
void scrollTo(T scrollView, ScrollToCommandData data);
void scrollToEnd(T scrollView, ScrollToEndCommandData data);
}
public static class ScrollToCommandData {
@@ -42,10 +44,21 @@ public class ReactScrollViewCommandHelper {
}
}
public static class ScrollToEndCommandData {
public final boolean mAnimated;
ScrollToEndCommandData(boolean animated) {
mAnimated = animated;
}
}
public static Map<String,Integer> getCommandsMap() {
return MapBuilder.of(
"scrollTo",
COMMAND_SCROLL_TO);
COMMAND_SCROLL_TO,
"scrollToEnd",
COMMAND_SCROLL_TO_END);
}
public static <T> void receiveCommand(
@@ -64,6 +77,11 @@ public class ReactScrollViewCommandHelper {
viewManager.scrollTo(scrollView, new ScrollToCommandData(destX, destY, animated));
return;
}
case COMMAND_SCROLL_TO_END: {
boolean animated = args.getBoolean(0);
viewManager.scrollToEnd(scrollView, new ScrollToEndCommandData(animated));
return;
}
default:
throw new IllegalArgumentException(String.format(
"Unsupported command %d received by %s.",
@@ -131,6 +131,20 @@ public class ReactScrollViewManager
}
}
@Override
public void scrollToEnd(
ReactScrollView scrollView,
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
// ScrollView always has one child - the scrollable area
int bottom =
scrollView.getChildAt(0).getHeight() + scrollView.getPaddingBottom();
if (data.mAnimated) {
scrollView.smoothScrollTo(scrollView.getScrollX(), bottom);
} else {
scrollView.scrollTo(scrollView.getScrollX(), bottom);
}
}
@Override
public @Nullable Map getExportedCustomDirectEventTypeConstants() {
return createExportedCustomDirectEventTypeConstants();
+8 -4
View File
@@ -2520,19 +2520,22 @@ static void YGNodelayoutImpl(const YGNodeRef node,
// If the user didn't specify a width or height for the node, set the
// dimensions based on the children.
if (measureModeMainDim == YGMeasureModeUndefined) {
if (measureModeMainDim == YGMeasureModeUndefined ||
(node->style.overflow != YGOverflowScroll && measureModeMainDim == YGMeasureModeAtMost)) {
// Clamp the size to the min/max size, if specified, and make sure it
// doesn't go below the padding and border amount.
node->layout.measuredDimensions[dim[mainAxis]] =
YGNodeBoundAxis(node, mainAxis, maxLineMainDim, mainAxisParentSize, parentWidth);
} else if (measureModeMainDim == YGMeasureModeAtMost) {
} else if (measureModeMainDim == YGMeasureModeAtMost &&
node->style.overflow == YGOverflowScroll) {
node->layout.measuredDimensions[dim[mainAxis]] = fmaxf(
fminf(availableInnerMainDim + paddingAndBorderAxisMain,
YGNodeBoundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim, mainAxisParentSize)),
paddingAndBorderAxisMain);
}
if (measureModeCrossDim == YGMeasureModeUndefined) {
if (measureModeCrossDim == YGMeasureModeUndefined ||
(node->style.overflow != YGOverflowScroll && measureModeCrossDim == YGMeasureModeAtMost)) {
// Clamp the size to the min/max size, if specified, and make sure it
// doesn't go below the padding and border amount.
node->layout.measuredDimensions[dim[crossAxis]] =
@@ -2541,7 +2544,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
totalLineCrossDim + paddingAndBorderAxisCross,
crossAxisParentSize,
parentWidth);
} else if (measureModeCrossDim == YGMeasureModeAtMost) {
} else if (measureModeCrossDim == YGMeasureModeAtMost &&
node->style.overflow == YGOverflowScroll) {
node->layout.measuredDimensions[dim[crossAxis]] =
fmaxf(fminf(availableInnerCrossDim + paddingAndBorderAxisCross,
YGNodeBoundAxisWithinMinAndMax(node,
@@ -966,6 +966,10 @@
INFOPLIST_FILE = HelloWorldTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
);
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HelloWorld.app/HelloWorld";
};
@@ -979,6 +983,10 @@
INFOPLIST_FILE = HelloWorldTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_LDFLAGS = (
"-ObjC",
"-lc++",
);
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HelloWorld.app/HelloWorld";
};
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "1000.0.0",
"version": "0.41.0",
"description": "A framework for building native apps using React",
"license": "BSD-3-Clause",
"repository": {
@@ -209,4 +209,4 @@
"shelljs": "0.6.0",
"sinon": "^2.0.0-pre.2"
}
}
}