Compare commits

...
Author SHA1 Message Date
Valentin Shergin ab64f7b9e8 [0.48.0-rc.1] Bump version numbers 2017-08-16 15:14:05 +02:00
Ats Jenk 96b32d7be8 Separate window dimensions change from orientation
Summary:
**Summary:**
There was a bug with RN.Dimensions returning incorrect window dimensions. In certain cases when device was in portrait, window dimensions reported landscape dimensions and vice versa.

This happened because in certain scenarios, after device orientation changed, dimensions update event from ReactRootView had incorrect dimensions.
Was able to reproduce this when device was rotated during app launch. After rotation global layout listener callback gets invoked. Inside the callback current and previous orientations are compared. When a change is detected, orientation and dimension change events are sent to JS. It is assumed, when orientation changes, new dimensions are available immediately. This is not the case for window dimensions as they are retrieved from resources object which gets updated asynchronously after orientation change. In cases when app is doing a lot of work on the main thread, like app startup, it takes more time to update the resources object. And when orientation change is detected in global layout, resources object is not updated with new dimensions yet. This causes dimensions update to be sent to JS with old window dimensions.
Global layout listener callback does get invoked a second time when resources object is finally updated with new dimensions, but since orientation no longer changes, no event is sent to JS.

Fixed this by separating dimensions update from orientation update. Now RN keeps track of previous window and screen dimension values. When a change is detected, an event is sent to JS with updated dimensions. This ensures that whenever dimensions change, JS gets the updated values.

This has a side effect of sending dimension update twice in some cases.
One example is the case above where window dimensions take time to update, but screen dimensions are updated immediately. This will cause two events to be sent to JS. One for window dimensions and one for screen dimensions update.
Other change is that initial value for both window and screen fields is empty. Which results in first change to trigger an event. Previously initial orientation value was 0 which meant when app started in normal portrait orientation, first layout did not trigger a dimension update event. Now even first layout sends the event. This should not be an issue as it is to make sure dimensions in JS side are correct.

**Testing:**
Verified with a sample app that correct dimensions are available when app launches.
Verified that after orientation dimensions are updated.
Verified that in the scenario described above where window dimensions are updated later, we get correct dimension values in JS.
We have incorporated this fix into our app and have been testing it internally.

Ats Jenk
Microsoft Corp.

<!--
Thank you for sending the PR!

If you changed any code, please provide us with clear instructions on how you verified your changes work. In other words, a test plan is *required*. Bonus points for screenshots and videos!

Please read the Contribution Guidelines at https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md to learn more about contributing to React Native.

Happy contributing!
-->
Closes https://github.com/facebook/react-native/pull/15181

Differential Revision: D5552195

Pulled By: shergin

fbshipit-source-id: d1f190cb960090468886ff56cda58cac296745db
2017-08-16 15:11:47 +02:00
Luke Rhodes 4d572cd0f8 Fixes unintended side effects caused by #14684
Summary:
I had fixed this locally but hadn't updated the original pull request, sorry. This commit is working for us in production.
Closes https://github.com/facebook/react-native/pull/14900

Differential Revision: D5539787

Pulled By: hramos

fbshipit-source-id: 6c826ada4a7f36607c65508ced6c9dce32002f74
2017-08-16 15:11:40 +02:00
Mike Grabowski 580805968c [0.48.0-rc.0] Bump version numbers 2017-08-01 20:42:16 +02:00
6 changed files with 37 additions and 52 deletions
@@ -72,7 +72,6 @@ const SwipeableRow = createReactClass({
propTypes: {
children: PropTypes.any,
isOpen: PropTypes.bool,
preventSwipeLeft: PropTypes.bool,
preventSwipeRight: PropTypes.bool,
maxSwipeDistance: PropTypes.number.isRequired,
onOpen: PropTypes.func.isRequired,
@@ -110,7 +109,6 @@ const SwipeableRow = createReactClass({
getDefaultProps(): Object {
return {
isOpen: false,
preventSwipeLeft: false,
preventSwipeRight: false,
maxSwipeDistance: 0,
onOpen: emptyFunction,
@@ -339,12 +337,10 @@ const SwipeableRow = createReactClass({
// Ignore swipes due to user's finger moving slightly when tapping
_isValidSwipe(gestureState: Object): boolean {
if (this.props.preventSwipeLeft && gestureState.dx < 0) {
return false;
}
if (this.props.preventSwipeRight && gestureState.dx > 0) {
if (this.props.preventSwipeRight && this._previousLeft === CLOSED_LEFT_POSITION && gestureState.dx > 0) {
return false;
}
return Math.abs(gestureState.dx) > HORIZONTAL_SWIPE_DISTANCE_THRESHOLD;
},
+1 -1
View File
@@ -1,4 +1,4 @@
VERSION_NAME=1000.0.0-master
VERSION_NAME=0.48.0-rc.1
GROUP=com.facebook.react
POM_NAME=ReactNative
@@ -16,6 +16,7 @@ import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -357,6 +358,8 @@ public class ReactRootView extends SizeMonitoringFrameLayout implements RootView
private int mKeyboardHeight = 0;
private int mDeviceRotation = 0;
private DisplayMetrics mWindowMetrics = new DisplayMetrics();
private DisplayMetrics mScreenMetrics = new DisplayMetrics();
/* package */ CustomGlobalLayoutListener() {
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(getContext().getApplicationContext());
@@ -372,6 +375,7 @@ public class ReactRootView extends SizeMonitoringFrameLayout implements RootView
}
checkForKeyboardEvents();
checkForDeviceOrientationChanges();
checkForDeviceDimensionsChanges();
}
private void checkForKeyboardEvents() {
@@ -404,13 +408,37 @@ public class ReactRootView extends SizeMonitoringFrameLayout implements RootView
return;
}
mDeviceRotation = rotation;
// It's important to repopulate DisplayMetrics and export them before emitting the
// orientation change event, so that the Dimensions object returns the correct new values.
DisplayMetricsHolder.initDisplayMetrics(getContext());
emitUpdateDimensionsEvent();
emitOrientationChanged(rotation);
}
private void checkForDeviceDimensionsChanges() {
// Get current display metrics.
DisplayMetricsHolder.initDisplayMetrics(getContext());
// Check changes to both window and screen display metrics since they may not update at the same time.
if (!areMetricsEqual(mWindowMetrics, DisplayMetricsHolder.getWindowDisplayMetrics()) ||
!areMetricsEqual(mScreenMetrics, DisplayMetricsHolder.getScreenDisplayMetrics())) {
mWindowMetrics.setTo(DisplayMetricsHolder.getWindowDisplayMetrics());
mScreenMetrics.setTo(DisplayMetricsHolder.getScreenDisplayMetrics());
emitUpdateDimensionsEvent();
}
}
private boolean areMetricsEqual(DisplayMetrics displayMetrics, DisplayMetrics otherMetrics) {
if (Build.VERSION.SDK_INT >= 17) {
return displayMetrics.equals(otherMetrics);
} else {
// DisplayMetrics didn't have an equals method before API 17.
// Check all public fields manually.
return displayMetrics.widthPixels == otherMetrics.widthPixels &&
displayMetrics.heightPixels == otherMetrics.heightPixels &&
displayMetrics.density == otherMetrics.density &&
displayMetrics.densityDpi == otherMetrics.densityDpi &&
displayMetrics.scaledDensity == otherMetrics.scaledDensity &&
displayMetrics.xdpi == otherMetrics.xdpi &&
displayMetrics.ydpi == otherMetrics.ydpi;
}
}
private void emitOrientationChanged(final int newRotation) {
String name;
double rotationDegrees;
-9
View File
@@ -82,16 +82,7 @@ All we need now is to apply this patch to your source files. While the old `reac
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
<<<<<<< ours
CODE_SIGN_IDENTITY = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/HockeySDK.embeddedframework",
"$(PROJECT_DIR)/HockeySDK-iOS/HockeySDK.embeddedframework",
);
=======
CURRENT_PROJECT_VERSION = 1;
>>>>>>> theirs
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-native",
"version": "1000.0.0",
"version": "0.48.0-rc.1",
"description": "A framework for building native apps using React",
"license": "BSD-3-Clause",
"repository": {
@@ -241,4 +241,4 @@
"shelljs": "0.6.0",
"sinon": "^2.2.0"
}
}
}
-30
View File
@@ -37,36 +37,6 @@ rm -rf android
success "Generated artifacts for Maven"
npm install
success "Killing any running packagers"
lsof -i :8081 | grep LISTEN
lsof -i :8081 | grep LISTEN | /usr/bin/awk '{print $2}' | xargs kill
info "Start the packager in another terminal by running 'npm start' from the root"
info "and then press any key."
info ""
read -n 1
./gradlew :RNTester:android:app:installDebug || error "Couln't build RNTester Android"
info "Press any key to run RNTester in an already running Android emulator/device"
info ""
read -n 1
adb shell am start -n com.facebook.react.uiapp/.RNTesterActivity
info "Press any key to open the project in Xcode, then build and test manually."
info ""
read -n 1
open "RNTester/RNTester.xcodeproj"
info "When done testing RNTester app on iOS and Android press any key to continue."
info ""
read -n 1
success "Killing packager"
lsof -i :8081 | grep LISTEN
lsof -i :8081 | grep LISTEN | /usr/bin/awk '{print $2}' | xargs kill
npm pack
PACKAGE=$(pwd)/react-native-$PACKAGE_VERSION.tgz