Compare commits
@@ -1,8 +1,8 @@
|
||||
environment:
|
||||
ANDROID_HOME: "C:\\android-sdk-windows"
|
||||
ANDROID_NDK: "C:\\android-sdk-windows\\android-ndk-r17c"
|
||||
ANDROID_BUILD_VERSION: 27
|
||||
ANDROID_TOOLS_VERSION: 27.0.3
|
||||
ANDROID_BUILD_VERSION: 28
|
||||
ANDROID_TOOLS_VERSION: 28.0.2
|
||||
|
||||
GRADLE_OPTS: -Dorg.gradle.daemon=false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
[android]
|
||||
target = android-27
|
||||
target = android-28
|
||||
|
||||
[download]
|
||||
max_number_of_retries = 3
|
||||
|
||||
@@ -28,11 +28,11 @@ aliases:
|
||||
|
||||
- &restore-cache-android-packages
|
||||
keys:
|
||||
- v1-android-sdkmanager-packages-api-27-alpha-{{ checksum "scripts/.tests.env" }}
|
||||
- v1-android-sdkmanager-packages-api-28-alpha-{{ checksum "scripts/.tests.env" }}
|
||||
- &save-cache-android-packages
|
||||
paths:
|
||||
- /opt/android/sdk
|
||||
key: v1-android-sdkmanager-packages-api-27-alpha-{{ checksum "scripts/.tests.env" }}
|
||||
key: v1-android-sdkmanager-packages-api-28-alpha-{{ checksum "scripts/.tests.env" }}
|
||||
|
||||
- &restore-cache-gradle
|
||||
keys:
|
||||
@@ -84,6 +84,14 @@ aliases:
|
||||
- ReactAndroid/build/third-party-ndk
|
||||
key: v1-gradle-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }}
|
||||
|
||||
- &restore-cache-homebrew
|
||||
keys:
|
||||
- v1-homebrew
|
||||
- &save-cache-homebrew
|
||||
paths:
|
||||
- /usr/local/Homebrew
|
||||
key: v1-homebrew
|
||||
|
||||
# Branch Filtering
|
||||
- &filter-only-master-stable
|
||||
branches:
|
||||
@@ -277,20 +285,12 @@ aliases:
|
||||
|
||||
- &boot-simulator-iphone
|
||||
name: Boot iPhone Simulator
|
||||
command: xcrun simctl boot "iPhone 5s" || true
|
||||
|
||||
- &boot-simulator-appletv
|
||||
name: Boot Apple TV Simulator
|
||||
command: xcrun simctl boot "Apple TV" || true
|
||||
command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true
|
||||
|
||||
- &run-objc-ios-tests
|
||||
name: iOS Test Suite
|
||||
command: ./scripts/objc-test-ios.sh test
|
||||
|
||||
- &run-objc-tvos-tests
|
||||
name: tvOS Test Suite
|
||||
command: ./scripts/objc-test-tvos.sh test
|
||||
|
||||
- &display-broken-tests-warning
|
||||
name: Running broken tests (Ignore any failures past this point)
|
||||
command: |
|
||||
@@ -304,16 +304,12 @@ aliases:
|
||||
|
||||
- &run-e2e-tests
|
||||
name: End-to-End Test Suite (Disabled)
|
||||
command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --ios --tvos --js --retries 3;
|
||||
command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --ios --js --retries 3;
|
||||
|
||||
- &run-objc-ios-e2e-tests
|
||||
name: iOS End-to-End Test Suite (Disabled)
|
||||
command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --ios --retries 3;
|
||||
|
||||
- &run-objc-tvos-e2e-tests
|
||||
name: tvOS End-to-End Test Suite (Disabled)
|
||||
command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3;
|
||||
|
||||
- &run-android-e2e-tests
|
||||
name: Android End-to-End Test Suite (Disabled)
|
||||
command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --retries 3;
|
||||
@@ -337,7 +333,7 @@ js_defaults: &js_defaults
|
||||
android_defaults: &android_defaults
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/android:api-27-node8-alpha
|
||||
- image: circleci/android:api-28-node8-alpha
|
||||
resource_class: "large"
|
||||
environment:
|
||||
- TERM: "dumb"
|
||||
@@ -350,7 +346,7 @@ android_defaults: &android_defaults
|
||||
macos_defaults: &macos_defaults
|
||||
<<: *defaults
|
||||
macos:
|
||||
xcode: "9.4.0"
|
||||
xcode: "10.1.0"
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
@@ -416,51 +412,19 @@ jobs:
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Runs unit tests on iOS and Apple TV devices
|
||||
test_objc:
|
||||
# Runs unit tests on iOS devices
|
||||
test_ios:
|
||||
<<: *macos_defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/react-native
|
||||
|
||||
- run: *boot-simulator-iphone
|
||||
- run: *boot-simulator-appletv
|
||||
|
||||
- restore-cache: *restore-cache-homebrew
|
||||
- run: *brew-install-watchman
|
||||
|
||||
- save-cache: *save-cache-homebrew
|
||||
- run: *run-objc-ios-tests
|
||||
- run: *run-objc-tvos-tests
|
||||
|
||||
# TODO: Fix these failing tests.
|
||||
- run: *display-broken-tests-warning
|
||||
- run: *run-podspec-tests
|
||||
- run: *run-objc-ios-e2e-tests
|
||||
- run: *run-objc-tvos-e2e-tests
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
|
||||
# Xcode 10: Runs unit tests on iOS and Apple TV devices
|
||||
test_objc_xcode10:
|
||||
<<: *defaults
|
||||
macos:
|
||||
xcode: "10.0.0"
|
||||
steps:
|
||||
- checkout
|
||||
- run: *setup-artifacts
|
||||
- run: *yarn
|
||||
|
||||
- run: *boot-simulator-iphone
|
||||
- run: *boot-simulator-appletv
|
||||
- run: *brew-install-watchman
|
||||
|
||||
- run: *run-objc-ios-tests
|
||||
- run: *run-objc-tvos-tests
|
||||
|
||||
# TODO: Fix these failing tests.
|
||||
- run: *display-broken-tests-warning
|
||||
- run: *run-podspec-tests
|
||||
- run: *run-objc-ios-e2e-tests
|
||||
- run: *run-objc-tvos-e2e-tests
|
||||
|
||||
- store_test_results:
|
||||
path: ~/react-native/reports/junit
|
||||
@@ -703,8 +667,8 @@ workflows:
|
||||
requires:
|
||||
- checkout_code
|
||||
|
||||
# Test iOS & tvOS
|
||||
- test_objc:
|
||||
# Test iOS
|
||||
- test_ios:
|
||||
filters: *filter-ignore-gh-pages
|
||||
requires:
|
||||
- checkout_code
|
||||
@@ -715,8 +679,6 @@ workflows:
|
||||
- checkout_code
|
||||
|
||||
# Tooling Compatibility Checks
|
||||
- test_objc_xcode10:
|
||||
filters: *filter-ignore-gh-pages
|
||||
- test_node10:
|
||||
filters: *filter-ignore-gh-pages
|
||||
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
; Ignore polyfills
|
||||
.*/Libraries/polyfills/.*
|
||||
|
||||
; Ignore metro
|
||||
.*/node_modules/metro/.*
|
||||
|
||||
; These should not be required directly
|
||||
; require from fbjs/lib instead: require('fbjs/lib/invariant')
|
||||
.*/node_modules/invariant/.*
|
||||
@@ -101,4 +98,7 @@ untyped-import
|
||||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.86.0
|
||||
^0.85.0
|
||||
|
||||
[untyped]
|
||||
.*/node_modules/metro/.*
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
; Ignore polyfills
|
||||
.*/Libraries/polyfills/.*
|
||||
|
||||
; Ignore metro
|
||||
.*/node_modules/metro/.*
|
||||
|
||||
; These should not be required directly
|
||||
; require from fbjs/lib instead: require('fbjs/lib/invariant')
|
||||
.*/node_modules/invariant/.*
|
||||
@@ -101,4 +98,7 @@ untyped-import
|
||||
untyped-type-import
|
||||
|
||||
[version]
|
||||
^0.86.0
|
||||
^0.85.0
|
||||
|
||||
[untyped]
|
||||
.*/node_modules/metro/.*
|
||||
|
||||
@@ -23,8 +23,8 @@ LABEL maintainer="Héctor Ramos <hector@fb.com>"
|
||||
|
||||
# set default build arguments
|
||||
ARG SDK_VERSION=sdk-tools-linux-3859397.zip
|
||||
ARG ANDROID_BUILD_VERSION=27
|
||||
ARG ANDROID_TOOLS_VERSION=27.0.3
|
||||
ARG ANDROID_BUILD_VERSION=28
|
||||
ARG ANDROID_TOOLS_VERSION=28.0.2
|
||||
ARG BUCK_VERSION=v2018.10.29.01
|
||||
ARG NDK_VERSION=17c
|
||||
ARG NODE_VERSION=8.10.0
|
||||
|
||||
@@ -349,6 +349,9 @@ class AnimatedInterpolation extends AnimatedWithChildren {
|
||||
__transformDataType(range: Array<any>) {
|
||||
// Change the string array type to number array
|
||||
// So we can reuse the same logic in iOS and Android platform
|
||||
/* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.70 was deployed. To see the error delete this
|
||||
* comment and run Flow. */
|
||||
return range.map(function(value) {
|
||||
if (typeof value !== 'string') {
|
||||
return value;
|
||||
|
||||
@@ -16,16 +16,6 @@
|
||||
#import <React/RCTRootView.h>
|
||||
#import <React/RCTUtils.h>
|
||||
|
||||
@interface RCTImagePickerController : UIImagePickerController
|
||||
|
||||
@property (nonatomic, assign) BOOL unmirrorFrontFacingCamera;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTImagePickerController
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTImagePickerManager () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
|
||||
|
||||
@end
|
||||
@@ -41,22 +31,6 @@ RCT_EXPORT_MODULE(ImagePickerIOS);
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(cameraChanged:)
|
||||
name:@"AVCaptureDeviceDidStartRunningNotification"
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVCaptureDeviceDidStartRunningNotification" object:nil];
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
@@ -82,10 +56,9 @@ RCT_EXPORT_METHOD(openCameraDialog:(NSDictionary *)config
|
||||
return;
|
||||
}
|
||||
|
||||
RCTImagePickerController *imagePicker = [RCTImagePickerController new];
|
||||
UIImagePickerController *imagePicker = [UIImagePickerController new];
|
||||
imagePicker.delegate = self;
|
||||
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
|
||||
imagePicker.unmirrorFrontFacingCamera = [RCTConvert BOOL:config[@"unmirrorFrontFacingCamera"]];
|
||||
|
||||
if ([RCTConvert BOOL:config[@"videoMode"]]) {
|
||||
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
|
||||
@@ -202,17 +175,4 @@ didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cameraChanged:(NSNotification *)notification
|
||||
{
|
||||
for (UIImagePickerController *picker in _pickers) {
|
||||
if ([picker isKindOfClass:[RCTImagePickerController class]]
|
||||
&& ((RCTImagePickerController *)picker).unmirrorFrontFacingCamera
|
||||
&& picker.cameraDevice == UIImagePickerControllerCameraDeviceFront) {
|
||||
picker.cameraViewTransform = CGAffineTransformScale(CGAffineTransformIdentity, -1, 1);
|
||||
} else {
|
||||
picker.cameraViewTransform = CGAffineTransformIdentity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -112,6 +112,7 @@ const ActivityIndicator = (
|
||||
|
||||
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
|
||||
const ActivityIndicatorWithRef = React.forwardRef(ActivityIndicator);
|
||||
ActivityIndicatorWithRef.displayName = 'ActivityIndicator';
|
||||
|
||||
ActivityIndicatorWithRef.defaultProps = {
|
||||
animating: true,
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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
|
||||
* @emails oncall+react_native
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('React');
|
||||
const ActivityIndicator = require('ActivityIndicator');
|
||||
const render = require('../../../../jest/renderer');
|
||||
|
||||
describe('ActivityIndicator', () => {
|
||||
it('should set displayName to prevent <Component /> regressions', () => {
|
||||
expect(ActivityIndicator.displayName).toBe('ActivityIndicator');
|
||||
});
|
||||
|
||||
it('should render as <ActivityIndicator> when mocked', () => {
|
||||
const instance = render.create(
|
||||
<ActivityIndicator size="large" color="#0000ff" />,
|
||||
);
|
||||
expect(instance).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should shallow render as <ActivityIndicator> when mocked', () => {
|
||||
const output = render.shallow(
|
||||
<ActivityIndicator size="large" color="#0000ff" />,
|
||||
);
|
||||
expect(output).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should shallow render as <ForwardRef(ActivityIndicator)> when not mocked', () => {
|
||||
jest.dontMock('ActivityIndicator');
|
||||
|
||||
const output = render.shallow(
|
||||
<ActivityIndicator size="large" color="#0000ff" />,
|
||||
);
|
||||
expect(output).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render as <View> when not mocked', () => {
|
||||
jest.dontMock('ActivityIndicator');
|
||||
|
||||
const instance = render.create(
|
||||
<ActivityIndicator size="large" color="#0000ff" />,
|
||||
);
|
||||
expect(instance).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ActivityIndicator should render as <ActivityIndicator> when mocked 1`] = `
|
||||
<ActivityIndicator
|
||||
animating={true}
|
||||
color="#0000ff"
|
||||
hidesWhenStopped={true}
|
||||
size="large"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ActivityIndicator should render as <View> when not mocked 1`] = `
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"justifyContent": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
<RCTActivityIndicatorView
|
||||
animating={true}
|
||||
color="#0000ff"
|
||||
hidesWhenStopped={true}
|
||||
indeterminate={true}
|
||||
size="large"
|
||||
style={
|
||||
Object {
|
||||
"height": 36,
|
||||
"width": 36,
|
||||
}
|
||||
}
|
||||
styleAttr="Normal"
|
||||
/>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`ActivityIndicator should shallow render as <ActivityIndicator> when mocked 1`] = `
|
||||
<ActivityIndicator
|
||||
animating={true}
|
||||
color="#0000ff"
|
||||
hidesWhenStopped={true}
|
||||
size="large"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`ActivityIndicator should shallow render as <ForwardRef(ActivityIndicator)> when not mocked 1`] = `
|
||||
<ForwardRef(ActivityIndicator)
|
||||
animating={true}
|
||||
color="#0000ff"
|
||||
hidesWhenStopped={true}
|
||||
size="large"
|
||||
/>
|
||||
`;
|
||||
@@ -14,42 +14,27 @@ export type TVParallaxPropertiesType = $ReadOnly<{|
|
||||
/**
|
||||
* If true, parallax effects are enabled. Defaults to true.
|
||||
*/
|
||||
enabled?: boolean,
|
||||
enabled: boolean,
|
||||
|
||||
/**
|
||||
* Defaults to 2.0.
|
||||
*/
|
||||
shiftDistanceX?: number,
|
||||
shiftDistanceX: number,
|
||||
|
||||
/**
|
||||
* Defaults to 2.0.
|
||||
*/
|
||||
shiftDistanceY?: number,
|
||||
shiftDistanceY: number,
|
||||
|
||||
/**
|
||||
* Defaults to 0.05.
|
||||
*/
|
||||
tiltAngle?: number,
|
||||
tiltAngle: number,
|
||||
|
||||
/**
|
||||
* Defaults to 1.0
|
||||
*/
|
||||
magnification?: number,
|
||||
|
||||
/**
|
||||
* Defaults to 1.0
|
||||
*/
|
||||
pressMagnification?: number,
|
||||
|
||||
/**
|
||||
* Defaults to 0.3
|
||||
*/
|
||||
pressDuration?: number,
|
||||
|
||||
/**
|
||||
* Defaults to 0.3
|
||||
*/
|
||||
pressDelay?: number,
|
||||
magnification: number,
|
||||
|}>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,6 +148,7 @@ class DatePickerIOS extends React.Component<Props> {
|
||||
return (
|
||||
<View style={props.style}>
|
||||
<RCTDatePickerIOS
|
||||
testID={props.testID}
|
||||
ref={picker => {
|
||||
this._picker = picker;
|
||||
}}
|
||||
|
||||
@@ -4,150 +4,35 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const DeprecatedColorPropType = require('DeprecatedColorPropType');
|
||||
const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes');
|
||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
const Platform = require('Platform');
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('React');
|
||||
const ReactNative = require('ReactNative');
|
||||
const StatusBar = require('StatusBar');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const UIManager = require('UIManager');
|
||||
const View = require('View');
|
||||
const nullthrows = require('nullthrows');
|
||||
|
||||
const DrawerConsts = UIManager.getViewManagerConfig('AndroidDrawerLayout')
|
||||
.Constants;
|
||||
|
||||
const createReactClass = require('create-react-class');
|
||||
const dismissKeyboard = require('dismissKeyboard');
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
const RK_DRAWER_REF = 'drawerlayout';
|
||||
const INNERVIEW_REF = 'innerView';
|
||||
|
||||
const DRAWER_STATES = ['Idle', 'Dragging', 'Settling'];
|
||||
|
||||
import type {ViewStyleProp} from 'StyleSheet';
|
||||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
import type {SyntheticEvent} from 'CoreEventTypes';
|
||||
import type {
|
||||
MeasureOnSuccessCallback,
|
||||
MeasureInWindowOnSuccessCallback,
|
||||
MeasureLayoutOnSuccessCallback,
|
||||
} from 'ReactNativeTypes';
|
||||
|
||||
type DrawerStates = 'Idle' | 'Dragging' | 'Settling';
|
||||
|
||||
type DrawerStateEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
drawerState: number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
type DrawerSlideEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
offset: number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
/**
|
||||
* Determines whether the keyboard gets dismissed in response to a drag.
|
||||
* - 'none' (the default), drags do not dismiss the keyboard.
|
||||
* - 'on-drag', the keyboard is dismissed when a drag begins.
|
||||
*/
|
||||
keyboardDismissMode?: ?('none' | 'on-drag'),
|
||||
|
||||
/**
|
||||
* Specifies the background color of the drawer. The default value is white.
|
||||
* If you want to set the opacity of the drawer, use rgba. Example:
|
||||
*
|
||||
* ```
|
||||
* return (
|
||||
* <DrawerLayoutAndroid drawerBackgroundColor="rgba(0,0,0,0.5)">
|
||||
* </DrawerLayoutAndroid>
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
drawerBackgroundColor: ColorValue,
|
||||
|
||||
/**
|
||||
* Specifies the side of the screen from which the drawer will slide in.
|
||||
*/
|
||||
drawerPosition: ?number,
|
||||
|
||||
/**
|
||||
* Specifies the width of the drawer, more precisely the width of the view that be pulled in
|
||||
* from the edge of the window.
|
||||
*/
|
||||
drawerWidth?: ?number,
|
||||
|
||||
/**
|
||||
* Specifies the lock mode of the drawer. The drawer can be locked in 3 states:
|
||||
* - unlocked (default), meaning that the drawer will respond (open/close) to touch gestures.
|
||||
* - locked-closed, meaning that the drawer will stay closed and not respond to gestures.
|
||||
* - locked-open, meaning that the drawer will stay opened and not respond to gestures.
|
||||
* The drawer may still be opened and closed programmatically (`openDrawer`/`closeDrawer`).
|
||||
*/
|
||||
drawerLockMode?: ?('unlocked' | 'locked-closed' | 'locked-open'),
|
||||
|
||||
/**
|
||||
* Function called whenever there is an interaction with the navigation view.
|
||||
*/
|
||||
onDrawerSlide?: ?(event: DrawerSlideEvent) => mixed,
|
||||
|
||||
/**
|
||||
* Function called when the drawer state has changed. The drawer can be in 3 states:
|
||||
* - Idle, meaning there is no interaction with the navigation view happening at the time
|
||||
* - Dragging, meaning there is currently an interaction with the navigation view
|
||||
* - Settling, meaning that there was an interaction with the navigation view, and the
|
||||
* navigation view is now finishing its closing or opening animation
|
||||
*/
|
||||
onDrawerStateChanged?: ?(state: DrawerStates) => mixed,
|
||||
|
||||
/**
|
||||
* Function called whenever the navigation view has been opened.
|
||||
*/
|
||||
onDrawerOpen?: ?() => mixed,
|
||||
|
||||
/**
|
||||
* Function called whenever the navigation view has been closed.
|
||||
*/
|
||||
onDrawerClose?: ?() => mixed,
|
||||
|
||||
/**
|
||||
* The navigation view that will be rendered to the side of the screen and can be pulled in.
|
||||
*/
|
||||
renderNavigationView: () => React.Element<any>,
|
||||
|
||||
/**
|
||||
* Make the drawer take the entire screen and draw the background of the
|
||||
* status bar to allow it to open over the status bar. It will only have an
|
||||
* effect on API 21+.
|
||||
*/
|
||||
statusBarBackgroundColor?: ?ColorValue,
|
||||
|
||||
children?: React.Node,
|
||||
style?: ?ViewStyleProp,
|
||||
|}>;
|
||||
|
||||
type NativeProps = $ReadOnly<{|
|
||||
...$Diff<
|
||||
Props,
|
||||
$ReadOnly<{onDrawerStateChanged?: ?(state: DrawerStates) => mixed}>,
|
||||
>,
|
||||
onDrawerStateChanged?: ?(state: DrawerStateEvent) => mixed,
|
||||
|}>;
|
||||
|
||||
type State = {|
|
||||
statusBarBackgroundColor: ColorValue,
|
||||
|};
|
||||
|
||||
// The View that contains both the actual drawer and the main view
|
||||
const AndroidDrawerLayout = ((requireNativeComponent(
|
||||
'AndroidDrawerLayout',
|
||||
): any): Class<ReactNative.NativeComponent<NativeProps>>);
|
||||
|
||||
/**
|
||||
* React component that wraps the platform `DrawerLayout` (Android only). The
|
||||
* Drawer (typically used for navigation) is rendered with `renderNavigationView`
|
||||
@@ -179,20 +64,109 @@ const AndroidDrawerLayout = ((requireNativeComponent(
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
class DrawerLayoutAndroid extends React.Component<Props, State> {
|
||||
static positions = DrawerConsts.DrawerPosition;
|
||||
static defaultProps = {
|
||||
drawerBackgroundColor: 'white',
|
||||
};
|
||||
const DrawerLayoutAndroid = createReactClass({
|
||||
displayName: 'DrawerLayoutAndroid',
|
||||
statics: {
|
||||
positions: DrawerConsts.DrawerPosition,
|
||||
},
|
||||
|
||||
_nativeRef = React.createRef<
|
||||
Class<ReactNative.NativeComponent<NativeProps>>,
|
||||
>();
|
||||
propTypes: {
|
||||
...DeprecatedViewPropTypes,
|
||||
/**
|
||||
* Determines whether the keyboard gets dismissed in response to a drag.
|
||||
* - 'none' (the default), drags do not dismiss the keyboard.
|
||||
* - 'on-drag', the keyboard is dismissed when a drag begins.
|
||||
*/
|
||||
keyboardDismissMode: PropTypes.oneOf([
|
||||
'none', // default
|
||||
'on-drag',
|
||||
]),
|
||||
/**
|
||||
* Specifies the background color of the drawer. The default value is white.
|
||||
* If you want to set the opacity of the drawer, use rgba. Example:
|
||||
*
|
||||
* ```
|
||||
* return (
|
||||
* <DrawerLayoutAndroid drawerBackgroundColor="rgba(0,0,0,0.5)">
|
||||
* </DrawerLayoutAndroid>
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
drawerBackgroundColor: DeprecatedColorPropType,
|
||||
/**
|
||||
* Specifies the side of the screen from which the drawer will slide in.
|
||||
*/
|
||||
drawerPosition: PropTypes.oneOf([
|
||||
DrawerConsts.DrawerPosition.Left,
|
||||
DrawerConsts.DrawerPosition.Right,
|
||||
]),
|
||||
/**
|
||||
* Specifies the width of the drawer, more precisely the width of the view that be pulled in
|
||||
* from the edge of the window.
|
||||
*/
|
||||
drawerWidth: PropTypes.number,
|
||||
/**
|
||||
* Specifies the lock mode of the drawer. The drawer can be locked in 3 states:
|
||||
* - unlocked (default), meaning that the drawer will respond (open/close) to touch gestures.
|
||||
* - locked-closed, meaning that the drawer will stay closed and not respond to gestures.
|
||||
* - locked-open, meaning that the drawer will stay opened and not respond to gestures.
|
||||
* The drawer may still be opened and closed programmatically (`openDrawer`/`closeDrawer`).
|
||||
*/
|
||||
drawerLockMode: PropTypes.oneOf([
|
||||
'unlocked',
|
||||
'locked-closed',
|
||||
'locked-open',
|
||||
]),
|
||||
/**
|
||||
* Function called whenever there is an interaction with the navigation view.
|
||||
*/
|
||||
onDrawerSlide: PropTypes.func,
|
||||
/**
|
||||
* Function called when the drawer state has changed. The drawer can be in 3 states:
|
||||
* - idle, meaning there is no interaction with the navigation view happening at the time
|
||||
* - dragging, meaning there is currently an interaction with the navigation view
|
||||
* - settling, meaning that there was an interaction with the navigation view, and the
|
||||
* navigation view is now finishing its closing or opening animation
|
||||
*/
|
||||
onDrawerStateChanged: PropTypes.func,
|
||||
/**
|
||||
* Function called whenever the navigation view has been opened.
|
||||
*/
|
||||
onDrawerOpen: PropTypes.func,
|
||||
/**
|
||||
* Function called whenever the navigation view has been closed.
|
||||
*/
|
||||
onDrawerClose: PropTypes.func,
|
||||
/**
|
||||
* The navigation view that will be rendered to the side of the screen and can be pulled in.
|
||||
*/
|
||||
renderNavigationView: PropTypes.func.isRequired,
|
||||
|
||||
state = {statusBarBackgroundColor: null};
|
||||
/**
|
||||
* Make the drawer take the entire screen and draw the background of the
|
||||
* status bar to allow it to open over the status bar. It will only have an
|
||||
* effect on API 21+.
|
||||
*/
|
||||
statusBarBackgroundColor: DeprecatedColorPropType,
|
||||
},
|
||||
|
||||
render() {
|
||||
const {onDrawerStateChanged, ...props} = this.props;
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
getDefaultProps: function(): {drawerBackgroundColor: string} {
|
||||
return {
|
||||
drawerBackgroundColor: 'white',
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {statusBarBackgroundColor: undefined};
|
||||
},
|
||||
|
||||
getInnerViewNode: function() {
|
||||
return this.refs[INNERVIEW_REF].getInnerViewNode();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const drawStatusBar =
|
||||
Platform.Version >= 21 && this.props.statusBarBackgroundColor;
|
||||
const drawerViewWrapper = (
|
||||
@@ -210,7 +184,7 @@ class DrawerLayoutAndroid extends React.Component<Props, State> {
|
||||
</View>
|
||||
);
|
||||
const childrenWrapper = (
|
||||
<View style={styles.mainSubview} collapsable={false}>
|
||||
<View ref={INNERVIEW_REF} style={styles.mainSubview} collapsable={false}>
|
||||
{drawStatusBar && (
|
||||
<StatusBar
|
||||
translucent
|
||||
@@ -230,8 +204,8 @@ class DrawerLayoutAndroid extends React.Component<Props, State> {
|
||||
);
|
||||
return (
|
||||
<AndroidDrawerLayout
|
||||
{...props}
|
||||
ref={this._nativeRef}
|
||||
{...this.props}
|
||||
ref={RK_DRAWER_REF}
|
||||
drawerWidth={this.props.drawerWidth}
|
||||
drawerPosition={this.props.drawerPosition}
|
||||
drawerLockMode={this.props.drawerLockMode}
|
||||
@@ -244,60 +218,59 @@ class DrawerLayoutAndroid extends React.Component<Props, State> {
|
||||
{drawerViewWrapper}
|
||||
</AndroidDrawerLayout>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_onDrawerSlide = (event: DrawerSlideEvent) => {
|
||||
_onDrawerSlide: function(event) {
|
||||
if (this.props.onDrawerSlide) {
|
||||
this.props.onDrawerSlide(event);
|
||||
}
|
||||
if (this.props.keyboardDismissMode === 'on-drag') {
|
||||
dismissKeyboard();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_onDrawerOpen = () => {
|
||||
_onDrawerOpen: function() {
|
||||
if (this.props.onDrawerOpen) {
|
||||
this.props.onDrawerOpen();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_onDrawerClose = () => {
|
||||
_onDrawerClose: function() {
|
||||
if (this.props.onDrawerClose) {
|
||||
this.props.onDrawerClose();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_onDrawerStateChanged = (event: DrawerStateEvent) => {
|
||||
_onDrawerStateChanged: function(event) {
|
||||
if (this.props.onDrawerStateChanged) {
|
||||
this.props.onDrawerStateChanged(
|
||||
DRAWER_STATES[event.nativeEvent.drawerState],
|
||||
);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the drawer.
|
||||
*/
|
||||
openDrawer() {
|
||||
openDrawer: function() {
|
||||
UIManager.dispatchViewManagerCommand(
|
||||
this._getDrawerLayoutHandle(),
|
||||
UIManager.getViewManagerConfig('AndroidDrawerLayout').Commands.openDrawer,
|
||||
null,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the drawer.
|
||||
*/
|
||||
closeDrawer() {
|
||||
closeDrawer: function() {
|
||||
UIManager.dispatchViewManagerCommand(
|
||||
this._getDrawerLayoutHandle(),
|
||||
UIManager.getViewManagerConfig('AndroidDrawerLayout').Commands
|
||||
.closeDrawer,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
* Closing and opening example
|
||||
* Note: To access the drawer you have to give it a ref. Refs do not work on stateless components
|
||||
@@ -314,45 +287,10 @@ class DrawerLayoutAndroid extends React.Component<Props, State> {
|
||||
* )
|
||||
* }
|
||||
*/
|
||||
_getDrawerLayoutHandle() {
|
||||
return ReactNative.findNodeHandle(this._nativeRef.current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Native methods
|
||||
*/
|
||||
blur() {
|
||||
nullthrows(this._nativeRef.current).blur();
|
||||
}
|
||||
|
||||
focus() {
|
||||
nullthrows(this._nativeRef.current).focus();
|
||||
}
|
||||
|
||||
measure(callback: MeasureOnSuccessCallback) {
|
||||
nullthrows(this._nativeRef.current).measure(callback);
|
||||
}
|
||||
|
||||
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
|
||||
nullthrows(this._nativeRef.current).measureInWindow(callback);
|
||||
}
|
||||
|
||||
measureLayout(
|
||||
relativeToNativeNode: number,
|
||||
onSuccess: MeasureLayoutOnSuccessCallback,
|
||||
onFail?: () => void,
|
||||
) {
|
||||
nullthrows(this._nativeRef.current).measureLayout(
|
||||
relativeToNativeNode,
|
||||
onSuccess,
|
||||
onFail,
|
||||
);
|
||||
}
|
||||
|
||||
setNativeProps(nativeProps: Object) {
|
||||
nullthrows(this._nativeRef.current).setNativeProps(nativeProps);
|
||||
}
|
||||
}
|
||||
_getDrawerLayoutHandle: function() {
|
||||
return ReactNative.findNodeHandle(this.refs[RK_DRAWER_REF]);
|
||||
},
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
@@ -384,4 +322,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
// The View that contains both the actual drawer and the main view
|
||||
const AndroidDrawerLayout = requireNativeComponent('AndroidDrawerLayout');
|
||||
|
||||
module.exports = DrawerLayoutAndroid;
|
||||
|
||||
@@ -47,6 +47,7 @@ type RCTPickerIOSType = Class<
|
||||
onStartShouldSetResponder: () => boolean,
|
||||
selectedIndex: number,
|
||||
style?: ?TextStyleProp,
|
||||
testID?: ?string,
|
||||
|}>,
|
||||
>,
|
||||
>;
|
||||
@@ -114,6 +115,7 @@ class PickerIOS extends React.Component<Props, State> {
|
||||
ref={picker => {
|
||||
this._picker = picker;
|
||||
}}
|
||||
testID={this.props.testID}
|
||||
style={[styles.pickerIOS, this.props.itemStyle]}
|
||||
items={this.state.items}
|
||||
selectedIndex={this.state.selectedIndex}
|
||||
|
||||
@@ -24,8 +24,6 @@ const warning = require('fbjs/lib/warning');
|
||||
|
||||
const {ScrollViewManager} = require('NativeModules');
|
||||
|
||||
import type {PressEvent, ScrollEvent} from 'CoreEventTypes';
|
||||
import type {KeyboardEvent} from 'Keyboard';
|
||||
import type EmitterSubscription from 'EmitterSubscription';
|
||||
|
||||
/**
|
||||
@@ -115,6 +113,7 @@ type State = {
|
||||
observedScrollSinceBecomingResponder: boolean,
|
||||
becameResponderWhileAnimating: boolean,
|
||||
};
|
||||
type Event = Object;
|
||||
|
||||
const ScrollResponderMixin = {
|
||||
_subscriptionKeyboardWillShow: (null: ?EmitterSubscription),
|
||||
@@ -169,9 +168,7 @@ const ScrollResponderMixin = {
|
||||
* true.
|
||||
*
|
||||
*/
|
||||
scrollResponderHandleStartShouldSetResponder: function(
|
||||
e: PressEvent,
|
||||
): boolean {
|
||||
scrollResponderHandleStartShouldSetResponder: function(e: Event): boolean {
|
||||
const currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
|
||||
if (
|
||||
@@ -196,7 +193,7 @@ const ScrollResponderMixin = {
|
||||
* Invoke this from an `onStartShouldSetResponderCapture` event.
|
||||
*/
|
||||
scrollResponderHandleStartShouldSetResponderCapture: function(
|
||||
e: PressEvent,
|
||||
e: Event,
|
||||
): boolean {
|
||||
// The scroll view should receive taps instead of its descendants if:
|
||||
// * it is already animating/decelerating
|
||||
@@ -215,7 +212,6 @@ const ScrollResponderMixin = {
|
||||
if (
|
||||
keyboardNeverPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target &&
|
||||
!TextInputState.isTextInput(e.target)
|
||||
) {
|
||||
return true;
|
||||
@@ -258,9 +254,9 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onTouchEnd` event.
|
||||
*
|
||||
* @param {PressEvent} e Event.
|
||||
* @param {SyntheticEvent} e Event.
|
||||
*/
|
||||
scrollResponderHandleTouchEnd: function(e: PressEvent) {
|
||||
scrollResponderHandleTouchEnd: function(e: Event) {
|
||||
const nativeEvent = e.nativeEvent;
|
||||
this.state.isTouching = nativeEvent.touches.length !== 0;
|
||||
this.props.onTouchEnd && this.props.onTouchEnd(e);
|
||||
@@ -269,9 +265,9 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onTouchCancel` event.
|
||||
*
|
||||
* @param {PressEvent} e Event.
|
||||
* @param {SyntheticEvent} e Event.
|
||||
*/
|
||||
scrollResponderHandleTouchCancel: function(e: PressEvent) {
|
||||
scrollResponderHandleTouchCancel: function(e: Event) {
|
||||
this.state.isTouching = false;
|
||||
this.props.onTouchCancel && this.props.onTouchCancel(e);
|
||||
},
|
||||
@@ -279,7 +275,7 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onResponderRelease` event.
|
||||
*/
|
||||
scrollResponderHandleResponderRelease: function(e: PressEvent) {
|
||||
scrollResponderHandleResponderRelease: function(e: Event) {
|
||||
this.props.onResponderRelease && this.props.onResponderRelease(e);
|
||||
|
||||
// By default scroll views will unfocus a textField
|
||||
@@ -299,7 +295,7 @@ const ScrollResponderMixin = {
|
||||
}
|
||||
},
|
||||
|
||||
scrollResponderHandleScroll: function(e: ScrollEvent) {
|
||||
scrollResponderHandleScroll: function(e: Event) {
|
||||
this.state.observedScrollSinceBecomingResponder = true;
|
||||
this.props.onScroll && this.props.onScroll(e);
|
||||
},
|
||||
@@ -307,7 +303,7 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onResponderGrant` event.
|
||||
*/
|
||||
scrollResponderHandleResponderGrant: function(e: ScrollEvent) {
|
||||
scrollResponderHandleResponderGrant: function(e: Event) {
|
||||
this.state.observedScrollSinceBecomingResponder = false;
|
||||
this.props.onResponderGrant && this.props.onResponderGrant(e);
|
||||
this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating();
|
||||
@@ -320,7 +316,7 @@ const ScrollResponderMixin = {
|
||||
*
|
||||
* Invoke this from an `onScrollBeginDrag` event.
|
||||
*/
|
||||
scrollResponderHandleScrollBeginDrag: function(e: ScrollEvent) {
|
||||
scrollResponderHandleScrollBeginDrag: function(e: Event) {
|
||||
FrameRateLogger.beginScroll(); // TODO: track all scrolls after implementing onScrollEndAnimation
|
||||
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
|
||||
},
|
||||
@@ -328,7 +324,7 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onScrollEndDrag` event.
|
||||
*/
|
||||
scrollResponderHandleScrollEndDrag: function(e: ScrollEvent) {
|
||||
scrollResponderHandleScrollEndDrag: function(e: Event) {
|
||||
const {velocity} = e.nativeEvent;
|
||||
// - If we are animating, then this is a "drag" that is stopping the scrollview and momentum end
|
||||
// will fire.
|
||||
@@ -347,7 +343,7 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onMomentumScrollBegin` event.
|
||||
*/
|
||||
scrollResponderHandleMomentumScrollBegin: function(e: ScrollEvent) {
|
||||
scrollResponderHandleMomentumScrollBegin: function(e: Event) {
|
||||
this.state.lastMomentumScrollBeginTime = performanceNow();
|
||||
this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e);
|
||||
},
|
||||
@@ -355,7 +351,7 @@ const ScrollResponderMixin = {
|
||||
/**
|
||||
* Invoke this from an `onMomentumScrollEnd` event.
|
||||
*/
|
||||
scrollResponderHandleMomentumScrollEnd: function(e: ScrollEvent) {
|
||||
scrollResponderHandleMomentumScrollEnd: function(e: Event) {
|
||||
FrameRateLogger.endScroll();
|
||||
this.state.lastMomentumScrollEndTime = performanceNow();
|
||||
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e);
|
||||
@@ -370,9 +366,9 @@ const ScrollResponderMixin = {
|
||||
* responder). The `onResponderReject` won't fire in that case - it only
|
||||
* fires when a *current* responder rejects our request.
|
||||
*
|
||||
* @param {PressEvent} e Touch Start event.
|
||||
* @param {SyntheticEvent} e Touch Start event.
|
||||
*/
|
||||
scrollResponderHandleTouchStart: function(e: PressEvent) {
|
||||
scrollResponderHandleTouchStart: function(e: Event) {
|
||||
this.state.isTouching = true;
|
||||
this.props.onTouchStart && this.props.onTouchStart(e);
|
||||
},
|
||||
@@ -386,9 +382,9 @@ const ScrollResponderMixin = {
|
||||
* responder). The `onResponderReject` won't fire in that case - it only
|
||||
* fires when a *current* responder rejects our request.
|
||||
*
|
||||
* @param {PressEvent} e Touch Start event.
|
||||
* @param {SyntheticEvent} e Touch Start event.
|
||||
*/
|
||||
scrollResponderHandleTouchMove: function(e: PressEvent) {
|
||||
scrollResponderHandleTouchMove: function(e: Event) {
|
||||
this.props.onTouchMove && this.props.onTouchMove(e);
|
||||
},
|
||||
|
||||
@@ -413,7 +409,7 @@ const ScrollResponderMixin = {
|
||||
* Components can pass what node to use by defining a `getScrollableNode`
|
||||
* function otherwise `this` is used.
|
||||
*/
|
||||
scrollResponderGetScrollableNode: function(): ?number {
|
||||
scrollResponderGetScrollableNode: function(): any {
|
||||
return this.getScrollableNode
|
||||
? this.getScrollableNode()
|
||||
: ReactNative.findNodeHandle(this);
|
||||
@@ -531,14 +527,14 @@ const ScrollResponderMixin = {
|
||||
* This method should be used as the callback to onFocus in a TextInputs'
|
||||
* parent view. Note that any module using this mixin needs to return
|
||||
* the parent view's ref in getScrollViewRef() in order to use this method.
|
||||
* @param {number} nodeHandle The TextInput node handle
|
||||
* @param {any} nodeHandle The TextInput node handle
|
||||
* @param {number} additionalOffset The scroll view's bottom "contentInset".
|
||||
* Default is 0.
|
||||
* @param {bool} preventNegativeScrolling Whether to allow pulling the content
|
||||
* down to make it meet the keyboard's top. Default is false.
|
||||
*/
|
||||
scrollResponderScrollNativeHandleToKeyboard: function(
|
||||
nodeHandle: number,
|
||||
nodeHandle: any,
|
||||
additionalOffset?: number,
|
||||
preventNegativeScrollOffset?: boolean,
|
||||
) {
|
||||
@@ -588,8 +584,8 @@ const ScrollResponderMixin = {
|
||||
this.preventNegativeScrollOffset = false;
|
||||
},
|
||||
|
||||
scrollResponderTextInputFocusError: function(msg: string) {
|
||||
console.error('Error measuring text field: ', msg);
|
||||
scrollResponderTextInputFocusError: function(e: Event) {
|
||||
console.error('Error measuring text field: ', e);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -671,17 +667,17 @@ const ScrollResponderMixin = {
|
||||
* relevant to you. (For example, only if you receive these callbacks after
|
||||
* you had explicitly focused a node etc).
|
||||
*/
|
||||
scrollResponderKeyboardWillShow: function(e: KeyboardEvent) {
|
||||
scrollResponderKeyboardWillShow: function(e: Event) {
|
||||
this.keyboardWillOpenTo = e;
|
||||
this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e);
|
||||
},
|
||||
|
||||
scrollResponderKeyboardWillHide: function(e: KeyboardEvent) {
|
||||
scrollResponderKeyboardWillHide: function(e: Event) {
|
||||
this.keyboardWillOpenTo = null;
|
||||
this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e);
|
||||
},
|
||||
|
||||
scrollResponderKeyboardDidShow: function(e: KeyboardEvent) {
|
||||
scrollResponderKeyboardDidShow: function(e: Event) {
|
||||
// TODO(7693961): The event for DidShow is not available on iOS yet.
|
||||
// Use the one from WillShow and do not assign.
|
||||
if (e) {
|
||||
@@ -690,7 +686,7 @@ const ScrollResponderMixin = {
|
||||
this.props.onKeyboardDidShow && this.props.onKeyboardDidShow(e);
|
||||
},
|
||||
|
||||
scrollResponderKeyboardDidHide: function(e: KeyboardEvent) {
|
||||
scrollResponderKeyboardDidHide: function(e: Event) {
|
||||
this.keyboardWillOpenTo = null;
|
||||
this.props.onKeyboardDidHide && this.props.onKeyboardDidHide(e);
|
||||
},
|
||||
|
||||
@@ -396,8 +396,8 @@ export type Props = $ReadOnly<{|
|
||||
* - `false`, deprecated, use 'never' instead
|
||||
* - `true`, deprecated, use 'always' instead
|
||||
*/
|
||||
/* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an error
|
||||
* found when Flow v0.86 was deployed. To see the error, delete this comment
|
||||
/* $FlowFixMe(>=0.85.0 site=react_native_fb) This comment suppresses an error
|
||||
* found when Flow v0.85 was deployed. To see the error, delete this comment
|
||||
* and run Flow. */
|
||||
keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | false | true),
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -103,56 +103,13 @@ type Props = $ReadOnly<{|
|
||||
barStyle?: ?('default' | 'light-content' | 'dark-content'),
|
||||
|}>;
|
||||
|
||||
type StackEntryProps = {|
|
||||
/**
|
||||
* The background color of the status bar.
|
||||
*
|
||||
* @platform android
|
||||
*/
|
||||
backgroundColor: {|
|
||||
value: ?string,
|
||||
animated: ?boolean,
|
||||
|},
|
||||
/**
|
||||
* Sets the color of the status bar text.
|
||||
*/
|
||||
barStyle: {|
|
||||
value: ?string,
|
||||
animated: ?boolean,
|
||||
|},
|
||||
/**
|
||||
* If the status bar is translucent.
|
||||
* When translucent is set to true, the app will draw under the status bar.
|
||||
* This is useful when using a semi transparent status bar color.
|
||||
*/
|
||||
translucent: ?boolean,
|
||||
/**
|
||||
*
|
||||
*/
|
||||
hidden: {|
|
||||
value: ?boolean,
|
||||
animated: boolean,
|
||||
transition: ?('slide' | 'fade'),
|
||||
|},
|
||||
/**
|
||||
* If the network activity indicator should be visible.
|
||||
*
|
||||
* @platform ios
|
||||
*/
|
||||
networkActivityIndicatorVisible: ?boolean,
|
||||
|};
|
||||
|
||||
/**
|
||||
* Merges the prop stack with the default values.
|
||||
*/
|
||||
function mergePropsStack(
|
||||
propsStack: $ReadOnlyArray<StackEntryProps>,
|
||||
defaultValues: StackEntryProps,
|
||||
): StackEntryProps {
|
||||
const init: StackEntryProps = {
|
||||
...defaultValues,
|
||||
};
|
||||
|
||||
propsStack: Array<Object>,
|
||||
defaultValues: Object,
|
||||
): Object {
|
||||
return propsStack.reduce((prev, cur) => {
|
||||
for (const prop in cur) {
|
||||
if (cur[prop] != null) {
|
||||
@@ -160,31 +117,39 @@ function mergePropsStack(
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
}, init);
|
||||
}, Object.assign({}, defaultValues));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object to insert in the props stack from the props
|
||||
* and the transition/animation info.
|
||||
*/
|
||||
function createStackEntry(props: Props): StackEntryProps {
|
||||
function createStackEntry(props: any): any {
|
||||
return {
|
||||
backgroundColor: {
|
||||
value: props.backgroundColor,
|
||||
animated: props.animated,
|
||||
},
|
||||
barStyle: {
|
||||
value: props.barStyle,
|
||||
animated: props.animated,
|
||||
},
|
||||
translucent: props.translucent || false,
|
||||
hidden: {
|
||||
value: props.hidden,
|
||||
animated: props.animated || false,
|
||||
transition: props.showHideTransition,
|
||||
},
|
||||
networkActivityIndicatorVisible:
|
||||
props.networkActivityIndicatorVisible || false,
|
||||
backgroundColor:
|
||||
props.backgroundColor != null
|
||||
? {
|
||||
value: props.backgroundColor,
|
||||
animated: props.animated,
|
||||
}
|
||||
: null,
|
||||
barStyle:
|
||||
props.barStyle != null
|
||||
? {
|
||||
value: props.barStyle,
|
||||
animated: props.animated,
|
||||
}
|
||||
: null,
|
||||
translucent: props.translucent,
|
||||
hidden:
|
||||
props.hidden != null
|
||||
? {
|
||||
value: props.hidden,
|
||||
animated: props.animated,
|
||||
transition: props.showHideTransition,
|
||||
}
|
||||
: null,
|
||||
networkActivityIndicatorVisible: props.networkActivityIndicatorVisible,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -228,9 +193,9 @@ function createStackEntry(props: Props): StackEntryProps {
|
||||
* `currentHeight` (Android only) The height of the status bar.
|
||||
*/
|
||||
class StatusBar extends React.Component<Props> {
|
||||
static _propsStack: Array<StackEntryProps> = [];
|
||||
static _propsStack = [];
|
||||
|
||||
static _defaultProps: StackEntryProps = createStackEntry({
|
||||
static _defaultProps = createStackEntry({
|
||||
animated: false,
|
||||
showHideTransition: 'fade',
|
||||
backgroundColor: 'black',
|
||||
@@ -265,9 +230,10 @@ class StatusBar extends React.Component<Props> {
|
||||
* changing the status bar hidden property.
|
||||
*/
|
||||
static setHidden(hidden: boolean, animation?: StatusBarAnimation) {
|
||||
animation = animation || 'none';
|
||||
StatusBar._defaultProps.hidden.value = hidden;
|
||||
if (Platform.OS === 'ios') {
|
||||
StatusBarManager.setHidden(hidden, animation || 'none');
|
||||
StatusBarManager.setHidden(hidden, animation);
|
||||
} else if (Platform.OS === 'android') {
|
||||
StatusBarManager.setHidden(hidden);
|
||||
}
|
||||
@@ -279,9 +245,10 @@ class StatusBar extends React.Component<Props> {
|
||||
* @param animated Animate the style change.
|
||||
*/
|
||||
static setBarStyle(style: StatusBarStyle, animated?: boolean) {
|
||||
animated = animated || false;
|
||||
StatusBar._defaultProps.barStyle.value = style;
|
||||
if (Platform.OS === 'ios') {
|
||||
StatusBarManager.setStyle(style, animated || false);
|
||||
StatusBarManager.setStyle(style, animated);
|
||||
} else if (Platform.OS === 'android') {
|
||||
StatusBarManager.setStyle(style);
|
||||
}
|
||||
@@ -312,8 +279,9 @@ class StatusBar extends React.Component<Props> {
|
||||
console.warn('`setBackgroundColor` is only available on Android');
|
||||
return;
|
||||
}
|
||||
animated = animated || false;
|
||||
StatusBar._defaultProps.backgroundColor.value = color;
|
||||
StatusBarManager.setColor(processColor(color), animated || false);
|
||||
StatusBarManager.setColor(processColor(color), animated);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,8 +34,6 @@ const warning = require('fbjs/lib/warning');
|
||||
import type {TextStyleProp, ViewStyleProp} from 'StyleSheet';
|
||||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {SyntheticEvent, ScrollEvent} from 'CoreEventTypes';
|
||||
import type {PressEvent} from 'CoreEventTypes';
|
||||
|
||||
let AndroidTextInput;
|
||||
let RCTMultilineTextInputView;
|
||||
@@ -57,73 +55,11 @@ const onlyMultiline = {
|
||||
children: true,
|
||||
};
|
||||
|
||||
export type ChangeEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
eventCount: number,
|
||||
target: number,
|
||||
text: string,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
export type TextInputEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
eventCount: number,
|
||||
previousText: string,
|
||||
range: $ReadOnly<{|
|
||||
start: number,
|
||||
end: number,
|
||||
|}>,
|
||||
target: number,
|
||||
text: string,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
export type ContentSizeChangeEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
target: number,
|
||||
contentSize: $ReadOnly<{|
|
||||
width: number,
|
||||
height: number,
|
||||
|}>,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
type TargetEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
target: number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
export type BlurEvent = TargetEvent;
|
||||
export type FocusEvent = TargetEvent;
|
||||
|
||||
type Selection = $ReadOnly<{|
|
||||
type Event = Object;
|
||||
type Selection = {
|
||||
start: number,
|
||||
end: number,
|
||||
|}>;
|
||||
|
||||
export type SelectionChangeEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
selection: Selection,
|
||||
target: number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
export type KeyPressEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
key: string,
|
||||
target?: ?number,
|
||||
eventCount?: ?number,
|
||||
|}>,
|
||||
>;
|
||||
|
||||
export type EditingEvent = SyntheticEvent<
|
||||
$ReadOnly<{|
|
||||
eventCount: number,
|
||||
text: string,
|
||||
target: number,
|
||||
|}>,
|
||||
>;
|
||||
end?: number,
|
||||
};
|
||||
|
||||
const DataDetectorTypes = [
|
||||
'phoneNumber',
|
||||
@@ -248,17 +184,17 @@ type Props = $ReadOnly<{|
|
||||
returnKeyType?: ?ReturnKeyType,
|
||||
maxLength?: ?number,
|
||||
multiline?: ?boolean,
|
||||
onBlur?: ?(e: BlurEvent) => void,
|
||||
onFocus?: ?(e: FocusEvent) => void,
|
||||
onChange?: ?(e: ChangeEvent) => void,
|
||||
onChangeText?: ?(text: string) => void,
|
||||
onContentSizeChange?: ?(e: ContentSizeChangeEvent) => void,
|
||||
onTextInput?: ?(e: TextInputEvent) => void,
|
||||
onEndEditing?: ?(e: EditingEvent) => void,
|
||||
onSelectionChange?: ?(e: SelectionChangeEvent) => void,
|
||||
onSubmitEditing?: ?(e: EditingEvent) => void,
|
||||
onKeyPress?: ?(e: KeyPressEvent) => void,
|
||||
onScroll?: ?(e: ScrollEvent) => void,
|
||||
onBlur?: ?Function,
|
||||
onFocus?: ?Function,
|
||||
onChange?: ?Function,
|
||||
onChangeText?: ?Function,
|
||||
onContentSizeChange?: ?Function,
|
||||
onTextInput?: ?Function,
|
||||
onEndEditing?: ?Function,
|
||||
onSelectionChange?: ?Function,
|
||||
onSubmitEditing?: ?Function,
|
||||
onKeyPress?: ?Function,
|
||||
onScroll?: ?Function,
|
||||
placeholder?: ?Stringish,
|
||||
placeholderTextColor?: ?ColorValue,
|
||||
secureTextEntry?: ?boolean,
|
||||
@@ -856,7 +792,7 @@ const TextInput = createReactClass({
|
||||
'oneTimeCode',
|
||||
]),
|
||||
},
|
||||
getDefaultProps() {
|
||||
getDefaultProps(): Object {
|
||||
return {
|
||||
allowFontScaling: true,
|
||||
underlineColorAndroid: 'transparent',
|
||||
@@ -1172,7 +1108,7 @@ const TextInput = createReactClass({
|
||||
);
|
||||
},
|
||||
|
||||
_onFocus: function(event: FocusEvent) {
|
||||
_onFocus: function(event: Event) {
|
||||
if (this.props.onFocus) {
|
||||
this.props.onFocus(event);
|
||||
}
|
||||
@@ -1182,16 +1118,16 @@ const TextInput = createReactClass({
|
||||
}
|
||||
},
|
||||
|
||||
_onPress: function(event: PressEvent) {
|
||||
_onPress: function(event: Event) {
|
||||
if (this.props.editable || this.props.editable === undefined) {
|
||||
this.focus();
|
||||
}
|
||||
},
|
||||
|
||||
_onChange: function(event: ChangeEvent) {
|
||||
_onChange: function(event: Event) {
|
||||
// Make sure to fire the mostRecentEventCount first so it is already set on
|
||||
// native when the text value is set.
|
||||
if (this._inputRef && this._inputRef.setNativeProps) {
|
||||
if (this._inputRef) {
|
||||
this._inputRef.setNativeProps({
|
||||
mostRecentEventCount: event.nativeEvent.eventCount,
|
||||
});
|
||||
@@ -1211,7 +1147,7 @@ const TextInput = createReactClass({
|
||||
this.forceUpdate();
|
||||
},
|
||||
|
||||
_onSelectionChange: function(event: SelectionChangeEvent) {
|
||||
_onSelectionChange: function(event: Event) {
|
||||
this.props.onSelectionChange && this.props.onSelectionChange(event);
|
||||
|
||||
if (!this._inputRef) {
|
||||
@@ -1252,11 +1188,7 @@ const TextInput = createReactClass({
|
||||
nativeProps.selection = this.props.selection;
|
||||
}
|
||||
|
||||
if (
|
||||
Object.keys(nativeProps).length > 0 &&
|
||||
this._inputRef &&
|
||||
this._inputRef.setNativeProps
|
||||
) {
|
||||
if (Object.keys(nativeProps).length > 0 && this._inputRef) {
|
||||
this._inputRef.setNativeProps(nativeProps);
|
||||
}
|
||||
|
||||
@@ -1265,7 +1197,11 @@ const TextInput = createReactClass({
|
||||
}
|
||||
},
|
||||
|
||||
_onBlur: function(event: BlurEvent) {
|
||||
_onBlur: function(event: Event) {
|
||||
// This is a hack to fix https://fburl.com/toehyir8
|
||||
// @todo(rsnara) Figure out why this is necessary.
|
||||
this.blur();
|
||||
|
||||
if (this.props.onBlur) {
|
||||
this.props.onBlur(event);
|
||||
}
|
||||
@@ -1275,11 +1211,11 @@ const TextInput = createReactClass({
|
||||
}
|
||||
},
|
||||
|
||||
_onTextInput: function(event: TextInputEvent) {
|
||||
_onTextInput: function(event: Event) {
|
||||
this.props.onTextInput && this.props.onTextInput(event);
|
||||
},
|
||||
|
||||
_onScroll: function(event: ScrollEvent) {
|
||||
_onScroll: function(event: Event) {
|
||||
this.props.onScroll && this.props.onScroll(event);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @format
|
||||
* @flow-strict
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('React');
|
||||
const ReactTestRenderer = require('react-test-renderer');
|
||||
const TextInput = require('TextInput');
|
||||
|
||||
import Component from '@reactions/component';
|
||||
|
||||
const {enter} = require('ReactNativeTestTools');
|
||||
|
||||
jest.unmock('TextInput');
|
||||
|
||||
describe('TextInput tests', () => {
|
||||
let input;
|
||||
let onChangeListener;
|
||||
let onChangeTextListener;
|
||||
const initialValue = 'initialValue';
|
||||
beforeEach(() => {
|
||||
onChangeListener = jest.fn();
|
||||
onChangeTextListener = jest.fn();
|
||||
const renderTree = ReactTestRenderer.create(
|
||||
<Component initialState={{text: initialValue}}>
|
||||
{({setState, state}) => (
|
||||
<TextInput
|
||||
value={state.text}
|
||||
onChangeText={text => {
|
||||
onChangeTextListener(text);
|
||||
setState({text});
|
||||
}}
|
||||
onChange={event => {
|
||||
onChangeListener(event);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Component>,
|
||||
);
|
||||
input = renderTree.root.findByType(TextInput);
|
||||
});
|
||||
it('has expected instance functions', () => {
|
||||
expect(input.instance.isFocused).toBeInstanceOf(Function); // Would have prevented S168585
|
||||
expect(input.instance.clear).toBeInstanceOf(Function);
|
||||
expect(input.instance.focus).toBeInstanceOf(Function);
|
||||
expect(input.instance.blur).toBeInstanceOf(Function);
|
||||
expect(input.instance.setNativeProps).toBeInstanceOf(Function);
|
||||
expect(input.instance.measure).toBeInstanceOf(Function);
|
||||
expect(input.instance.measureInWindow).toBeInstanceOf(Function);
|
||||
expect(input.instance.measureLayout).toBeInstanceOf(Function);
|
||||
});
|
||||
it('calls onChange callbacks', () => {
|
||||
expect(input.props.value).toBe(initialValue);
|
||||
const message = 'This is a test message';
|
||||
enter(input, message);
|
||||
expect(input.props.value).toBe(message);
|
||||
expect(onChangeTextListener).toHaveBeenCalledWith(message);
|
||||
expect(onChangeListener).toHaveBeenCalledWith({
|
||||
nativeEvent: {text: message},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,18 +5,13 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const TimePickerModule = require('NativeModules').TimePickerAndroid;
|
||||
|
||||
import type {
|
||||
TimePickerOptions,
|
||||
TimePickerResult,
|
||||
} from './TimePickerAndroidTypes';
|
||||
|
||||
/**
|
||||
* Opens the standard Android time picker dialog.
|
||||
*
|
||||
@@ -57,18 +52,22 @@ class TimePickerAndroid {
|
||||
* still be resolved with action being `TimePickerAndroid.dismissedAction` and all the other keys
|
||||
* being undefined. **Always** check whether the `action` before reading the values.
|
||||
*/
|
||||
static async open(options: TimePickerOptions): Promise<TimePickerResult> {
|
||||
static async open(options: Object): Promise<Object> {
|
||||
return TimePickerModule.open(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A time has been selected.
|
||||
*/
|
||||
static +timeSetAction: 'timeSetAction' = 'timeSetAction';
|
||||
static get timeSetAction() {
|
||||
return 'timeSetAction';
|
||||
}
|
||||
/**
|
||||
* The dialog has been dismissed.
|
||||
*/
|
||||
static +dismissedAction: 'dismissedAction' = 'dismissedAction';
|
||||
static get dismissedAction() {
|
||||
return 'dismissedAction';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TimePickerAndroid;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* 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 strict-local
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
export type TimePickerOptions = {|
|
||||
hour?: number,
|
||||
minute?: number,
|
||||
is24Hour?: boolean,
|
||||
mode?: 'clock' | 'spinner' | 'default',
|
||||
|};
|
||||
|
||||
export type TimePickerResult = $ReadOnly<{|
|
||||
action: string,
|
||||
hour: number,
|
||||
minute: number,
|
||||
|}>;
|
||||
@@ -4,7 +4,6 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
@@ -24,9 +23,6 @@ const View = require('View');
|
||||
const keyMirror = require('fbjs/lib/keyMirror');
|
||||
const normalizeColor = require('normalizeColor');
|
||||
|
||||
import type {PressEvent} from 'CoreEventTypes';
|
||||
import type {EdgeInsetsProp} from 'EdgeInsetsPropType';
|
||||
|
||||
/**
|
||||
* `Touchable`: Taps done right.
|
||||
*
|
||||
@@ -115,7 +111,6 @@ import type {EdgeInsetsProp} from 'EdgeInsetsPropType';
|
||||
/**
|
||||
* Touchable states.
|
||||
*/
|
||||
|
||||
const States = keyMirror({
|
||||
NOT_RESPONDER: null, // Not the responder
|
||||
RESPONDER_INACTIVE_PRESS_IN: null, // Responder, inactive, in the `PressRect`
|
||||
@@ -127,33 +122,10 @@ const States = keyMirror({
|
||||
ERROR: null,
|
||||
});
|
||||
|
||||
type State =
|
||||
| typeof States.NOT_RESPONDER
|
||||
| typeof States.RESPONDER_INACTIVE_PRESS_IN
|
||||
| typeof States.RESPONDER_INACTIVE_PRESS_OUT
|
||||
| typeof States.RESPONDER_ACTIVE_PRESS_IN
|
||||
| typeof States.RESPONDER_ACTIVE_PRESS_OUT
|
||||
| typeof States.RESPONDER_ACTIVE_LONG_PRESS_IN
|
||||
| typeof States.RESPONDER_ACTIVE_LONG_PRESS_OUT
|
||||
| typeof States.ERROR;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Quick lookup map for states that are considered to be "active"
|
||||
*/
|
||||
|
||||
const baseStatesConditions = {
|
||||
NOT_RESPONDER: false,
|
||||
RESPONDER_INACTIVE_PRESS_IN: false,
|
||||
RESPONDER_INACTIVE_PRESS_OUT: false,
|
||||
RESPONDER_ACTIVE_PRESS_IN: false,
|
||||
RESPONDER_ACTIVE_PRESS_OUT: false,
|
||||
RESPONDER_ACTIVE_LONG_PRESS_IN: false,
|
||||
RESPONDER_ACTIVE_LONG_PRESS_OUT: false,
|
||||
ERROR: false,
|
||||
};
|
||||
|
||||
const IsActive = {
|
||||
...baseStatesConditions,
|
||||
RESPONDER_ACTIVE_PRESS_OUT: true,
|
||||
RESPONDER_ACTIVE_PRESS_IN: true,
|
||||
};
|
||||
@@ -163,14 +135,12 @@ const IsActive = {
|
||||
* therefore eligible to result in a "selection" if the press stops.
|
||||
*/
|
||||
const IsPressingIn = {
|
||||
...baseStatesConditions,
|
||||
RESPONDER_INACTIVE_PRESS_IN: true,
|
||||
RESPONDER_ACTIVE_PRESS_IN: true,
|
||||
RESPONDER_ACTIVE_LONG_PRESS_IN: true,
|
||||
};
|
||||
|
||||
const IsLongPressingIn = {
|
||||
...baseStatesConditions,
|
||||
RESPONDER_ACTIVE_LONG_PRESS_IN: true,
|
||||
};
|
||||
|
||||
@@ -187,15 +157,6 @@ const Signals = keyMirror({
|
||||
LONG_PRESS_DETECTED: null,
|
||||
});
|
||||
|
||||
type Signal =
|
||||
| typeof Signals.DELAY
|
||||
| typeof Signals.RESPONDER_GRANT
|
||||
| typeof Signals.RESPONDER_RELEASE
|
||||
| typeof Signals.RESPONDER_TERMINATED
|
||||
| typeof Signals.ENTER_PRESS_RECT
|
||||
| typeof Signals.LEAVE_PRESS_RECT
|
||||
| typeof Signals.LONG_PRESS_DETECTED;
|
||||
|
||||
/**
|
||||
* Mapping from States x Signals => States
|
||||
*/
|
||||
@@ -430,7 +391,7 @@ const TouchableMixin = {
|
||||
* @param {SyntheticEvent} e Synthetic event from event system.
|
||||
*
|
||||
*/
|
||||
touchableHandleResponderGrant: function(e: PressEvent) {
|
||||
touchableHandleResponderGrant: function(e) {
|
||||
const dispatchID = e.currentTarget;
|
||||
// Since e is used in a callback invoked on another event loop
|
||||
// (as in setTimeout etc), we need to call e.persist() on the
|
||||
@@ -471,21 +432,21 @@ const TouchableMixin = {
|
||||
/**
|
||||
* Place as callback for a DOM element's `onResponderRelease` event.
|
||||
*/
|
||||
touchableHandleResponderRelease: function(e: PressEvent) {
|
||||
touchableHandleResponderRelease: function(e) {
|
||||
this._receiveSignal(Signals.RESPONDER_RELEASE, e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Place as callback for a DOM element's `onResponderTerminate` event.
|
||||
*/
|
||||
touchableHandleResponderTerminate: function(e: PressEvent) {
|
||||
touchableHandleResponderTerminate: function(e) {
|
||||
this._receiveSignal(Signals.RESPONDER_TERMINATED, e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Place as callback for a DOM element's `onResponderMove` event.
|
||||
*/
|
||||
touchableHandleResponderMove: function(e: PressEvent) {
|
||||
touchableHandleResponderMove: function(e) {
|
||||
// Not enough time elapsed yet, wait for highlight -
|
||||
// this is just a perf optimization.
|
||||
if (
|
||||
@@ -672,14 +633,7 @@ const TouchableMixin = {
|
||||
UIManager.measure(tag, this._handleQueryLayout);
|
||||
},
|
||||
|
||||
_handleQueryLayout: function(
|
||||
l: number,
|
||||
t: number,
|
||||
w: number,
|
||||
h: number,
|
||||
globalX: number,
|
||||
globalY: number,
|
||||
) {
|
||||
_handleQueryLayout: function(l, t, w, h, globalX, globalY) {
|
||||
//don't do anything UIManager failed to measure node
|
||||
if (!l && !t && !w && !h && !globalX && !globalY) {
|
||||
return;
|
||||
@@ -698,12 +652,12 @@ const TouchableMixin = {
|
||||
);
|
||||
},
|
||||
|
||||
_handleDelay: function(e: PressEvent) {
|
||||
_handleDelay: function(e) {
|
||||
this.touchableDelayTimeout = null;
|
||||
this._receiveSignal(Signals.DELAY, e);
|
||||
},
|
||||
|
||||
_handleLongDelay: function(e: PressEvent) {
|
||||
_handleLongDelay: function(e) {
|
||||
this.longPressDelayTimeout = null;
|
||||
const curState = this.state.touchable.touchState;
|
||||
if (
|
||||
@@ -731,7 +685,7 @@ const TouchableMixin = {
|
||||
* @throws Error if invalid state transition or unrecognized signal.
|
||||
* @sideeffects
|
||||
*/
|
||||
_receiveSignal: function(signal: Signal, e: PressEvent) {
|
||||
_receiveSignal: function(signal, e) {
|
||||
const responderID = this.state.touchable.responderID;
|
||||
const curState = this.state.touchable.touchState;
|
||||
const nextState = Transitions[curState] && Transitions[curState][signal];
|
||||
@@ -771,14 +725,14 @@ const TouchableMixin = {
|
||||
this.longPressDelayTimeout = null;
|
||||
},
|
||||
|
||||
_isHighlight: function(state: State) {
|
||||
_isHighlight: function(state) {
|
||||
return (
|
||||
state === States.RESPONDER_ACTIVE_PRESS_IN ||
|
||||
state === States.RESPONDER_ACTIVE_LONG_PRESS_IN
|
||||
);
|
||||
},
|
||||
|
||||
_savePressInLocation: function(e: PressEvent) {
|
||||
_savePressInLocation: function(e) {
|
||||
const touch = TouchEventUtils.extractSingleTouch(e.nativeEvent);
|
||||
const pageX = touch && touch.pageX;
|
||||
const pageY = touch && touch.pageY;
|
||||
@@ -787,12 +741,7 @@ const TouchableMixin = {
|
||||
this.pressInLocation = {pageX, pageY, locationX, locationY};
|
||||
},
|
||||
|
||||
_getDistanceBetweenPoints: function(
|
||||
aX: number,
|
||||
aY: number,
|
||||
bX: number,
|
||||
bY: number,
|
||||
) {
|
||||
_getDistanceBetweenPoints: function(aX, aY, bX, bY) {
|
||||
const deltaX = aX - bX;
|
||||
const deltaY = aY - bY;
|
||||
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
@@ -809,12 +758,7 @@ const TouchableMixin = {
|
||||
* @param {Event} e Native event.
|
||||
* @sideeffects
|
||||
*/
|
||||
_performSideEffectsForTransition: function(
|
||||
curState: State,
|
||||
nextState: State,
|
||||
signal: Signal,
|
||||
e: PressEvent,
|
||||
) {
|
||||
_performSideEffectsForTransition: function(curState, nextState, signal, e) {
|
||||
const curIsHighlight = this._isHighlight(curState);
|
||||
const newIsHighlight = this._isHighlight(nextState);
|
||||
|
||||
@@ -869,12 +813,12 @@ const TouchableMixin = {
|
||||
UIManager.playTouchSound();
|
||||
},
|
||||
|
||||
_startHighlight: function(e: PressEvent) {
|
||||
_startHighlight: function(e) {
|
||||
this._savePressInLocation(e);
|
||||
this.touchableHandleActivePressIn && this.touchableHandleActivePressIn(e);
|
||||
},
|
||||
|
||||
_endHighlight: function(e: PressEvent) {
|
||||
_endHighlight: function(e) {
|
||||
if (this.touchableHandleActivePressOut) {
|
||||
if (
|
||||
this.touchableGetPressOutDelayMS &&
|
||||
@@ -896,13 +840,7 @@ const Touchable = {
|
||||
/**
|
||||
* Renders a debugging overlay to visualize touch target with hitSlop (might not work on Android).
|
||||
*/
|
||||
renderDebugView: ({
|
||||
color,
|
||||
hitSlop,
|
||||
}: {
|
||||
color: string | number,
|
||||
hitSlop: EdgeInsetsProp,
|
||||
}) => {
|
||||
renderDebugView: ({color, hitSlop}) => {
|
||||
if (!Touchable.TOUCH_TARGET_DEBUG) {
|
||||
return null;
|
||||
}
|
||||
@@ -916,12 +854,8 @@ const Touchable = {
|
||||
for (const key in hitSlop) {
|
||||
debugHitSlopStyle[key] = -hitSlop[key];
|
||||
}
|
||||
const normalizedColor = normalizeColor(color);
|
||||
if (typeof normalizedColor !== 'number') {
|
||||
return null;
|
||||
}
|
||||
const hexColor =
|
||||
'#' + ('00000000' + normalizedColor.toString(16)).substr(-8);
|
||||
'#' + ('00000000' + normalizeColor(color).toString(16)).substr(-8);
|
||||
return (
|
||||
<View
|
||||
pointerEvents="none"
|
||||
|
||||
@@ -23,7 +23,8 @@ const createReactClass = require('create-react-class');
|
||||
import type {EdgeInsetsProp} from 'EdgeInsetsPropType';
|
||||
import type {ViewStyleProp} from 'StyleSheet';
|
||||
import type {Props as TouchableWithoutFeedbackProps} from 'TouchableWithoutFeedback';
|
||||
import type {PressEvent} from 'CoreEventTypes';
|
||||
|
||||
type Event = Object;
|
||||
|
||||
type State = {
|
||||
animationID: ?number,
|
||||
@@ -35,8 +36,8 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
|
||||
type Props = $ReadOnly<{|
|
||||
...TouchableWithoutFeedbackProps,
|
||||
|
||||
onPressWithCompletion?: ?(fn: () => void) => void,
|
||||
onPressAnimationComplete?: ?() => void,
|
||||
onPressWithCompletion?: ?Function,
|
||||
onPressAnimationComplete?: ?Function,
|
||||
pressRetentionOffset?: ?EdgeInsetsProp,
|
||||
releaseVelocity?: ?number,
|
||||
releaseBounciness?: ?number,
|
||||
@@ -94,7 +95,7 @@ const TouchableBounce = ((createReactClass({
|
||||
value: number,
|
||||
velocity: number,
|
||||
bounciness: number,
|
||||
callback?: ?() => void,
|
||||
callback?: ?Function,
|
||||
) {
|
||||
Animated.spring(this.state.scale, {
|
||||
toValue: value,
|
||||
@@ -104,28 +105,21 @@ const TouchableBounce = ((createReactClass({
|
||||
}).start(callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Triggers a bounce animation without invoking any callbacks.
|
||||
*/
|
||||
bounce: function() {
|
||||
this.bounceTo(0.93, 0.1, 0, () => this.bounceTo(1, 0.4, 0));
|
||||
},
|
||||
|
||||
/**
|
||||
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
|
||||
* defined on your component.
|
||||
*/
|
||||
touchableHandleActivePressIn: function(e: PressEvent) {
|
||||
touchableHandleActivePressIn: function(e: Event) {
|
||||
this.bounceTo(0.93, 0.1, 0);
|
||||
this.props.onPressIn && this.props.onPressIn(e);
|
||||
},
|
||||
|
||||
touchableHandleActivePressOut: function(e: PressEvent) {
|
||||
touchableHandleActivePressOut: function(e: Event) {
|
||||
this.bounceTo(1, 0.4, 0);
|
||||
this.props.onPressOut && this.props.onPressOut(e);
|
||||
},
|
||||
|
||||
touchableHandlePress: function(e: PressEvent) {
|
||||
touchableHandlePress: function(e: Event) {
|
||||
const onPressWithCompletion = this.props.onPressWithCompletion;
|
||||
if (onPressWithCompletion) {
|
||||
onPressWithCompletion(() => {
|
||||
@@ -153,7 +147,7 @@ const TouchableBounce = ((createReactClass({
|
||||
return this.props.pressRetentionOffset || PRESS_RETENTION_OFFSET;
|
||||
},
|
||||
|
||||
touchableGetHitSlop: function(): ?EdgeInsetsProp {
|
||||
touchableGetHitSlop: function(): ?Object {
|
||||
return this.props.hitSlop;
|
||||
},
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import type {PressEvent} from 'CoreEventTypes';
|
||||
import type {ViewStyleProp} from 'StyleSheet';
|
||||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
import type {Props as TouchableWithoutFeedbackProps} from 'TouchableWithoutFeedback';
|
||||
import type {TVParallaxPropertiesType} from 'TVViewPropTypes';
|
||||
|
||||
const DEFAULT_PROPS = {
|
||||
activeOpacity: 0.85,
|
||||
@@ -40,7 +39,7 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
|
||||
|
||||
type IOSProps = $ReadOnly<{|
|
||||
hasTVPreferredFocus?: ?boolean,
|
||||
tvParallaxProperties?: ?TVParallaxPropertiesType,
|
||||
tvParallaxProperties?: ?Object,
|
||||
|}>;
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
@@ -50,8 +49,8 @@ type Props = $ReadOnly<{|
|
||||
activeOpacity?: ?number,
|
||||
underlayColor?: ?ColorValue,
|
||||
style?: ?ViewStyleProp,
|
||||
onShowUnderlay?: ?() => void,
|
||||
onHideUnderlay?: ?() => void,
|
||||
onShowUnderlay?: ?Function,
|
||||
onHideUnderlay?: ?Function,
|
||||
testOnly_pressed?: ?boolean,
|
||||
|}>;
|
||||
|
||||
@@ -186,7 +185,18 @@ const TouchableHighlight = ((createReactClass({
|
||||
*/
|
||||
hasTVPreferredFocus: PropTypes.bool,
|
||||
/**
|
||||
* Apple TV parallax effects
|
||||
* *(Apple TV only)* Object with properties to control Apple TV parallax effects.
|
||||
*
|
||||
* enabled: If true, parallax effects are enabled. Defaults to true.
|
||||
* shiftDistanceX: Defaults to 2.0.
|
||||
* shiftDistanceY: Defaults to 2.0.
|
||||
* tiltAngle: Defaults to 0.05.
|
||||
* magnification: Defaults to 1.0.
|
||||
* pressMagnification: Defaults to 1.0.
|
||||
* pressDuration: Defaults to 0.3.
|
||||
* pressDelay: Defaults to 0.0.
|
||||
*
|
||||
* @platform ios
|
||||
*/
|
||||
tvParallaxProperties: PropTypes.object,
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
@@ -23,8 +22,6 @@ const createReactClass = require('create-react-class');
|
||||
const ensurePositiveDelayProps = require('ensurePositiveDelayProps');
|
||||
const processColor = require('processColor');
|
||||
|
||||
import type {PressEvent} from 'CoreEventTypes';
|
||||
|
||||
const rippleBackgroundPropType = PropTypes.shape({
|
||||
type: PropTypes.oneOf(['RippleAndroid']),
|
||||
color: PropTypes.number,
|
||||
@@ -41,6 +38,8 @@ const backgroundPropType = PropTypes.oneOfType([
|
||||
themeAttributeBackgroundPropType,
|
||||
]);
|
||||
|
||||
type Event = Object;
|
||||
|
||||
const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
|
||||
|
||||
/**
|
||||
@@ -168,7 +167,7 @@ const TouchableNativeFeedback = createReactClass({
|
||||
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
|
||||
* defined on your component.
|
||||
*/
|
||||
touchableHandleActivePressIn: function(e: PressEvent) {
|
||||
touchableHandleActivePressIn: function(e: Event) {
|
||||
this.props.onPressIn && this.props.onPressIn(e);
|
||||
this._dispatchPressedStateChange(true);
|
||||
if (this.pressInLocation) {
|
||||
@@ -179,16 +178,16 @@ const TouchableNativeFeedback = createReactClass({
|
||||
}
|
||||
},
|
||||
|
||||
touchableHandleActivePressOut: function(e: PressEvent) {
|
||||
touchableHandleActivePressOut: function(e: Event) {
|
||||
this.props.onPressOut && this.props.onPressOut(e);
|
||||
this._dispatchPressedStateChange(false);
|
||||
},
|
||||
|
||||
touchableHandlePress: function(e: PressEvent) {
|
||||
touchableHandlePress: function(e: Event) {
|
||||
this.props.onPress && this.props.onPress(e);
|
||||
},
|
||||
|
||||
touchableHandleLongPress: function(e: PressEvent) {
|
||||
touchableHandleLongPress: function(e: Event) {
|
||||
this.props.onLongPress && this.props.onLongPress(e);
|
||||
},
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/**
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*
|
||||
* 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
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
* @flow
|
||||
*/
|
||||
|
||||
exports.version = {
|
||||
major: 0,
|
||||
minor: 0,
|
||||
minor: 58,
|
||||
patch: 0,
|
||||
prerelease: null,
|
||||
prerelease: 'rc.3',
|
||||
};
|
||||
|
||||
@@ -32,8 +32,18 @@ RCT_EXPORT_MODULE()
|
||||
{
|
||||
CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
|
||||
NSDictionary<NSString *, id> *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(imageSource, NULL);
|
||||
NSUInteger loopCount = [properties[(id)kCGImagePropertyGIFDictionary][(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue];
|
||||
|
||||
NSUInteger loopCount = 0;
|
||||
if ([[properties[(id)kCGImagePropertyGIFDictionary] allKeys] containsObject:(id)kCGImagePropertyGIFLoopCount]) {
|
||||
loopCount = [properties[(id)kCGImagePropertyGIFDictionary][(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue];
|
||||
if (loopCount == 0) {
|
||||
// A loop count of 0 means infinite
|
||||
loopCount = HUGE_VALF;
|
||||
} else {
|
||||
// A loop count of 1 means it should repeat twice, 2 means, thrice, etc.
|
||||
loopCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
UIImage *image = nil;
|
||||
size_t imageCount = CGImageSourceGetCount(imageSource);
|
||||
if (imageCount > 1) {
|
||||
@@ -84,11 +94,12 @@ RCT_EXPORT_MODULE()
|
||||
// Create animation
|
||||
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
|
||||
animation.calculationMode = kCAAnimationDiscrete;
|
||||
animation.repeatCount = loopCount == 0 ? HUGE_VALF : loopCount;
|
||||
animation.repeatCount = loopCount;
|
||||
animation.keyTimes = keyTimes;
|
||||
animation.values = images;
|
||||
animation.duration = duration;
|
||||
animation.removedOnCompletion = NO;
|
||||
animation.fillMode = kCAFillModeForwards;
|
||||
image.reactKeyframeAnimation = animation;
|
||||
|
||||
} else {
|
||||
|
||||
@@ -32,8 +32,6 @@ static NSString *RCTCacheKeyForImage(NSString *imageTag, CGSize size, CGFloat sc
|
||||
NSOperationQueue *_imageDecodeQueue;
|
||||
NSCache *_decodedImageCache;
|
||||
NSMutableDictionary *_cacheStaleTimes;
|
||||
|
||||
NSDateFormatter *_headerDateFormatter;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
@@ -50,7 +48,7 @@ static NSString *RCTCacheKeyForImage(NSString *imageTag, CGSize size, CGFloat sc
|
||||
selector:@selector(clearCache)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -137,14 +135,16 @@ static NSString *RCTCacheKeyForImage(NSString *imageTag, CGSize size, CGFloat sc
|
||||
}
|
||||
|
||||
- (NSDate *)dateWithHeaderString:(NSString *)headerDateString {
|
||||
if (_headerDateFormatter == nil) {
|
||||
_headerDateFormatter = [[NSDateFormatter alloc] init];
|
||||
_headerDateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
|
||||
_headerDateFormatter.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
|
||||
_headerDateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
|
||||
}
|
||||
static NSDateFormatter *formatter;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
formatter = [[NSDateFormatter alloc] init];
|
||||
formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
|
||||
formatter.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
|
||||
formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
|
||||
});
|
||||
|
||||
return [_headerDateFormatter dateFromString:headerDateString];
|
||||
return [formatter dateFromString:headerDateString];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,7 +12,12 @@
|
||||
|
||||
jest.mock('ErrorUtils').mock('BatchedBridge');
|
||||
|
||||
const isWindows = process.platform === 'win32';
|
||||
function expectToBeCalledOnce(fn) {
|
||||
// todo fix this test case on widnows
|
||||
if (isWindows) {
|
||||
return;
|
||||
}
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,18 +33,12 @@ const UIManagerStatTracker = {
|
||||
const createViewOrig = UIManager.createView;
|
||||
UIManager.createView = function(tag, className, rootTag, props) {
|
||||
incStat('createView', 1);
|
||||
/* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.86 was deployed. To see the error, delete
|
||||
* this comment and run Flow. */
|
||||
incStat('setProp', Object.keys(props || []).length);
|
||||
createViewOrig(tag, className, rootTag, props);
|
||||
};
|
||||
const updateViewOrig = UIManager.updateView;
|
||||
UIManager.updateView = function(tag, className, props) {
|
||||
incStat('updateView', 1);
|
||||
/* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.86 was deployed. To see the error, delete
|
||||
* this comment and run Flow. */
|
||||
incStat('setProp', Object.keys(props || []).length);
|
||||
updateViewOrig(tag, className, props);
|
||||
};
|
||||
@@ -58,13 +52,7 @@ const UIManagerStatTracker = {
|
||||
remove,
|
||||
) {
|
||||
incStat('manageChildren', 1);
|
||||
/* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.86 was deployed. To see the error, delete
|
||||
* this comment and run Flow. */
|
||||
incStat('move', Object.keys(moveFrom || []).length);
|
||||
/* $FlowFixMe(>=0.86.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.86 was deployed. To see the error, delete
|
||||
* this comment and run Flow. */
|
||||
incStat('remove', Object.keys(remove || []).length);
|
||||
manageChildrenOrig(tag, moveFrom, moveTo, addTags, addIndices, remove);
|
||||
};
|
||||
|
||||
@@ -49,8 +49,8 @@ function renderApplication<Props: Object>(
|
||||
RootComponent.prototype.unstable_isAsyncReactComponent === true
|
||||
) {
|
||||
// $FlowFixMe This is not yet part of the official public API
|
||||
const ConcurrentMode = React.unstable_ConcurrentMode;
|
||||
renderable = <ConcurrentMode>{renderable}</ConcurrentMode>;
|
||||
const AsyncMode = React.unstable_AsyncMode;
|
||||
renderable = <AsyncMode>{renderable}</AsyncMode>;
|
||||
}
|
||||
|
||||
if (fabric) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
3ff2c7ccd4d174786aed0f16cc0dd784816ae977
|
||||
6bf5e859860938b8cb7153ee928c01ad45656969
|
||||
@@ -956,10 +956,6 @@ var eventTypes$1 = {
|
||||
}
|
||||
}
|
||||
},
|
||||
customBubblingEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes,
|
||||
customDirectEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes,
|
||||
ReactNativeBridgeEventPlugin = {
|
||||
eventTypes: ReactNativeViewConfigRegistry.eventTypes,
|
||||
extractEvents: function(
|
||||
@@ -969,8 +965,10 @@ var eventTypes$1 = {
|
||||
nativeEventTarget
|
||||
) {
|
||||
if (null == targetInst) return null;
|
||||
var bubbleDispatchConfig = customBubblingEventTypes$1[topLevelType],
|
||||
directDispatchConfig = customDirectEventTypes$1[topLevelType];
|
||||
var bubbleDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes[topLevelType],
|
||||
directDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes[topLevelType];
|
||||
invariant(
|
||||
bubbleDispatchConfig || directDispatchConfig,
|
||||
'Unsupported top level event type "%s" dispatched',
|
||||
@@ -1505,7 +1503,7 @@ function dispatchEvent(target, topLevelType, nativeEvent) {
|
||||
function shim$1() {
|
||||
invariant(
|
||||
!1,
|
||||
"The current renderer does not support hyration. This error is likely caused by a bug in React. Please file an issue."
|
||||
"The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue."
|
||||
);
|
||||
}
|
||||
var nextReactTag = 2;
|
||||
@@ -1619,17 +1617,19 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
var info = "";
|
||||
do {
|
||||
a: switch (workInProgress.tag) {
|
||||
case 2:
|
||||
case 16:
|
||||
case 0:
|
||||
case 1:
|
||||
case 5:
|
||||
case 8:
|
||||
case 13:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 10:
|
||||
case 9:
|
||||
var JSCompiler_inline_result = "";
|
||||
break a;
|
||||
default:
|
||||
var owner = workInProgress._debugOwner,
|
||||
source = workInProgress._debugSource,
|
||||
name = getComponentName(workInProgress.type);
|
||||
var JSCompiler_inline_result = null;
|
||||
JSCompiler_inline_result = null;
|
||||
owner && (JSCompiler_inline_result = getComponentName(owner.type));
|
||||
owner = name;
|
||||
name = "";
|
||||
@@ -1643,9 +1643,6 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
: JSCompiler_inline_result &&
|
||||
(name = " (created by " + JSCompiler_inline_result + ")");
|
||||
JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name;
|
||||
break a;
|
||||
default:
|
||||
JSCompiler_inline_result = "";
|
||||
}
|
||||
info += JSCompiler_inline_result;
|
||||
workInProgress = workInProgress.return;
|
||||
@@ -3379,7 +3376,8 @@ function updateMemoComponent(
|
||||
"function" === typeof type &&
|
||||
!shouldConstruct(type) &&
|
||||
void 0 === type.defaultProps &&
|
||||
null === Component.compare
|
||||
null === Component.compare &&
|
||||
void 0 === Component.defaultProps
|
||||
)
|
||||
return (
|
||||
(workInProgress.tag = 15),
|
||||
@@ -3817,7 +3815,6 @@ function updateSuspenseComponent(
|
||||
nextDidTimeout
|
||||
? ((renderExpirationTime = nextProps.fallback),
|
||||
(nextProps = createWorkInProgress(mode, mode.pendingProps, 0)),
|
||||
(nextProps.effectTag |= 2),
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
((nextDidTimeout =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -3830,7 +3827,6 @@ function updateSuspenseComponent(
|
||||
renderExpirationTime,
|
||||
current$$1.expirationTime
|
||||
)),
|
||||
(mode.effectTag |= 2),
|
||||
(renderExpirationTime = nextProps),
|
||||
(nextProps.childExpirationTime = 0),
|
||||
(renderExpirationTime.return = mode.return = workInProgress))
|
||||
@@ -3844,9 +3840,7 @@ function updateSuspenseComponent(
|
||||
nextDidTimeout
|
||||
? ((nextDidTimeout = nextProps.fallback),
|
||||
(nextProps = createFiberFromFragment(null, mode, 0, null)),
|
||||
(nextProps.effectTag |= 2),
|
||||
(nextProps.child = current$$1),
|
||||
(current$$1.return = nextProps),
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
(nextProps.child =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -4082,8 +4076,9 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
default:
|
||||
invariant(
|
||||
!1,
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.",
|
||||
current$$1
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Lazy element type must resolve to a class or function.%s",
|
||||
current$$1,
|
||||
""
|
||||
);
|
||||
}
|
||||
return getDerivedStateFromProps;
|
||||
@@ -4390,9 +4385,10 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
return (
|
||||
(context = workInProgress.type),
|
||||
(hasContext = resolveDefaultProps(
|
||||
context.type,
|
||||
context,
|
||||
workInProgress.pendingProps
|
||||
)),
|
||||
(hasContext = resolveDefaultProps(context.type, hasContext)),
|
||||
updateMemoComponent(
|
||||
current$$1,
|
||||
workInProgress,
|
||||
@@ -4979,20 +4975,22 @@ function completeUnitOfWork(workInProgress) {
|
||||
break a;
|
||||
}
|
||||
instance = null !== instance;
|
||||
viewConfig = null !== current && null !== current.memoizedState;
|
||||
renderExpirationTime =
|
||||
null !== current && null !== current.memoizedState;
|
||||
null !== current &&
|
||||
!instance &&
|
||||
viewConfig &&
|
||||
renderExpirationTime &&
|
||||
((current = current.child.sibling),
|
||||
null !== current &&
|
||||
reconcileChildFibers(
|
||||
current$$1,
|
||||
current,
|
||||
null,
|
||||
renderExpirationTime
|
||||
));
|
||||
((viewConfig = current$$1.firstEffect),
|
||||
null !== viewConfig
|
||||
? ((current$$1.firstEffect = current),
|
||||
(current.nextEffect = viewConfig))
|
||||
: ((current$$1.firstEffect = current$$1.lastEffect = current),
|
||||
(current.nextEffect = null)),
|
||||
(current.effectTag = 8)));
|
||||
if (
|
||||
instance !== viewConfig ||
|
||||
instance !== renderExpirationTime ||
|
||||
(0 === (current$$1.effectTag & 1) && instance)
|
||||
)
|
||||
current$$1.effectTag |= 4;
|
||||
@@ -5183,14 +5181,7 @@ function renderRoot(root$jscomp$0, isYieldy) {
|
||||
thenable.then(returnFiber$jscomp$0, returnFiber$jscomp$0);
|
||||
if (0 === (value.mode & 1)) {
|
||||
value.effectTag |= 64;
|
||||
reconcileChildren(
|
||||
sourceFiber$jscomp$0.alternate,
|
||||
sourceFiber$jscomp$0,
|
||||
null,
|
||||
returnFiber
|
||||
);
|
||||
sourceFiber$jscomp$0.effectTag &= -1025;
|
||||
sourceFiber$jscomp$0.effectTag &= -933;
|
||||
sourceFiber$jscomp$0.effectTag &= -1957;
|
||||
1 === sourceFiber$jscomp$0.tag &&
|
||||
null === sourceFiber$jscomp$0.alternate &&
|
||||
(sourceFiber$jscomp$0.tag = 17);
|
||||
@@ -5447,7 +5438,7 @@ function scheduleWorkToRoot(fiber, expirationTime) {
|
||||
}
|
||||
node = node.return;
|
||||
}
|
||||
return null === root ? null : root;
|
||||
return root;
|
||||
}
|
||||
function scheduleWork(fiber, expirationTime) {
|
||||
fiber = scheduleWorkToRoot(fiber, expirationTime);
|
||||
@@ -5944,9 +5935,14 @@ function completeRoot$1(root, finishedWork$jscomp$0, expirationTime) {
|
||||
}
|
||||
prevState.return = null;
|
||||
prevState.child = null;
|
||||
prevState.alternate &&
|
||||
((prevState.alternate.child = null),
|
||||
(prevState.alternate.return = null));
|
||||
prevState.memoizedState = null;
|
||||
prevState.updateQueue = null;
|
||||
var alternate = prevState.alternate;
|
||||
null !== alternate &&
|
||||
((alternate.return = null),
|
||||
(alternate.child = null),
|
||||
(alternate.memoizedState = null),
|
||||
(alternate.updateQueue = null));
|
||||
}
|
||||
nextEffect = nextEffect.nextEffect;
|
||||
}
|
||||
@@ -6101,7 +6097,7 @@ function onUncaughtError(error) {
|
||||
nextFlushedRoot.expirationTime = 0;
|
||||
hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error));
|
||||
}
|
||||
function findHostInstance$1(component) {
|
||||
function findHostInstance(component) {
|
||||
var fiber = component._reactInternalFiber;
|
||||
void 0 === fiber &&
|
||||
("function" === typeof component.render
|
||||
@@ -6214,7 +6210,7 @@ function findNodeHandle(componentOrHandle) {
|
||||
if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag;
|
||||
if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag)
|
||||
return componentOrHandle.canonical._nativeTag;
|
||||
componentOrHandle = findHostInstance$1(componentOrHandle);
|
||||
componentOrHandle = findHostInstance(componentOrHandle);
|
||||
return null == componentOrHandle
|
||||
? componentOrHandle
|
||||
: componentOrHandle.canonical
|
||||
@@ -6310,7 +6306,7 @@ var roots = new Map(),
|
||||
};
|
||||
return ReactNativeComponent;
|
||||
})(React.Component);
|
||||
})(findNodeHandle, findHostInstance$1),
|
||||
})(findNodeHandle, findHostInstance),
|
||||
findNodeHandle: findNodeHandle,
|
||||
render: function(element, containerTag, callback) {
|
||||
var root = roots.get(containerTag);
|
||||
@@ -6418,7 +6414,7 @@ var roots = new Map(),
|
||||
TextInputState.blurTextInput(findNodeHandle(this));
|
||||
}
|
||||
};
|
||||
})(findNodeHandle, findHostInstance$1)
|
||||
})(findNodeHandle, findHostInstance)
|
||||
}
|
||||
};
|
||||
(function(devToolsConfig) {
|
||||
|
||||
@@ -957,10 +957,6 @@ var eventTypes$1 = {
|
||||
}
|
||||
}
|
||||
},
|
||||
customBubblingEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes,
|
||||
customDirectEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes,
|
||||
ReactNativeBridgeEventPlugin = {
|
||||
eventTypes: ReactNativeViewConfigRegistry.eventTypes,
|
||||
extractEvents: function(
|
||||
@@ -970,8 +966,10 @@ var eventTypes$1 = {
|
||||
nativeEventTarget
|
||||
) {
|
||||
if (null == targetInst) return null;
|
||||
var bubbleDispatchConfig = customBubblingEventTypes$1[topLevelType],
|
||||
directDispatchConfig = customDirectEventTypes$1[topLevelType];
|
||||
var bubbleDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes[topLevelType],
|
||||
directDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes[topLevelType];
|
||||
invariant(
|
||||
bubbleDispatchConfig || directDispatchConfig,
|
||||
'Unsupported top level event type "%s" dispatched',
|
||||
@@ -1506,7 +1504,7 @@ function dispatchEvent(target, topLevelType, nativeEvent) {
|
||||
function shim$1() {
|
||||
invariant(
|
||||
!1,
|
||||
"The current renderer does not support hyration. This error is likely caused by a bug in React. Please file an issue."
|
||||
"The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue."
|
||||
);
|
||||
}
|
||||
var nextReactTag = 2;
|
||||
@@ -1620,17 +1618,19 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
var info = "";
|
||||
do {
|
||||
a: switch (workInProgress.tag) {
|
||||
case 2:
|
||||
case 16:
|
||||
case 0:
|
||||
case 1:
|
||||
case 5:
|
||||
case 8:
|
||||
case 13:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 10:
|
||||
case 9:
|
||||
var JSCompiler_inline_result = "";
|
||||
break a;
|
||||
default:
|
||||
var owner = workInProgress._debugOwner,
|
||||
source = workInProgress._debugSource,
|
||||
name = getComponentName(workInProgress.type);
|
||||
var JSCompiler_inline_result = null;
|
||||
JSCompiler_inline_result = null;
|
||||
owner && (JSCompiler_inline_result = getComponentName(owner.type));
|
||||
owner = name;
|
||||
name = "";
|
||||
@@ -1644,9 +1644,6 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
: JSCompiler_inline_result &&
|
||||
(name = " (created by " + JSCompiler_inline_result + ")");
|
||||
JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name;
|
||||
break a;
|
||||
default:
|
||||
JSCompiler_inline_result = "";
|
||||
}
|
||||
info += JSCompiler_inline_result;
|
||||
workInProgress = workInProgress.return;
|
||||
@@ -3437,7 +3434,8 @@ function updateMemoComponent(
|
||||
"function" === typeof type &&
|
||||
!shouldConstruct(type) &&
|
||||
void 0 === type.defaultProps &&
|
||||
null === Component.compare
|
||||
null === Component.compare &&
|
||||
void 0 === Component.defaultProps
|
||||
)
|
||||
return (
|
||||
(workInProgress.tag = 15),
|
||||
@@ -3885,7 +3883,6 @@ function updateSuspenseComponent(
|
||||
current$$1.pendingProps,
|
||||
0
|
||||
);
|
||||
renderExpirationTime.effectTag |= 2;
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
((nextDidTimeout =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -3905,7 +3902,6 @@ function updateSuspenseComponent(
|
||||
nextProps,
|
||||
mode.expirationTime
|
||||
);
|
||||
nextProps.effectTag |= 2;
|
||||
mode = renderExpirationTime;
|
||||
renderExpirationTime.childExpirationTime = 0;
|
||||
renderExpirationTime = nextProps;
|
||||
@@ -3920,9 +3916,7 @@ function updateSuspenseComponent(
|
||||
else if (((current$$1 = current$$1.child), nextDidTimeout)) {
|
||||
nextDidTimeout = nextProps.fallback;
|
||||
nextProps = createFiberFromFragment(null, mode, 0, null);
|
||||
nextProps.effectTag |= 2;
|
||||
nextProps.child = current$$1;
|
||||
current$$1.return = nextProps;
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
(nextProps.child =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -4170,8 +4164,9 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
default:
|
||||
invariant(
|
||||
!1,
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.",
|
||||
current$$1
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Lazy element type must resolve to a class or function.%s",
|
||||
current$$1,
|
||||
""
|
||||
);
|
||||
}
|
||||
return getDerivedStateFromProps;
|
||||
@@ -4479,9 +4474,10 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
return (
|
||||
(context = workInProgress.type),
|
||||
(hasContext = resolveDefaultProps(
|
||||
context.type,
|
||||
context,
|
||||
workInProgress.pendingProps
|
||||
)),
|
||||
(hasContext = resolveDefaultProps(context.type, hasContext)),
|
||||
updateMemoComponent(
|
||||
current$$1,
|
||||
workInProgress,
|
||||
@@ -4906,14 +4902,7 @@ function throwException(
|
||||
thenable.then(returnFiber, returnFiber);
|
||||
if (0 === (value.mode & 1)) {
|
||||
value.effectTag |= 64;
|
||||
reconcileChildren(
|
||||
sourceFiber.alternate,
|
||||
sourceFiber,
|
||||
null,
|
||||
renderExpirationTime
|
||||
);
|
||||
sourceFiber.effectTag &= -1025;
|
||||
sourceFiber.effectTag &= -933;
|
||||
sourceFiber.effectTag &= -1957;
|
||||
1 === sourceFiber.tag &&
|
||||
null === sourceFiber.alternate &&
|
||||
(sourceFiber.tag = 17);
|
||||
@@ -5033,7 +5022,7 @@ var DispatcherWithoutHooks = { readContext: readContext },
|
||||
invariant(
|
||||
null != tracing.__interactionsRef &&
|
||||
null != tracing.__interactionsRef.current,
|
||||
"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracing` module with `schedule/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling"
|
||||
"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling"
|
||||
);
|
||||
var isWorking = !1,
|
||||
nextUnitOfWork = null,
|
||||
@@ -5171,9 +5160,14 @@ function commitAllHostEffects() {
|
||||
}
|
||||
effectTag.return = null;
|
||||
effectTag.child = null;
|
||||
effectTag.alternate &&
|
||||
((effectTag.alternate.child = null),
|
||||
(effectTag.alternate.return = null));
|
||||
effectTag.memoizedState = null;
|
||||
effectTag.updateQueue = null;
|
||||
effectTag = effectTag.alternate;
|
||||
null !== effectTag &&
|
||||
((effectTag.return = null),
|
||||
(effectTag.child = null),
|
||||
(effectTag.memoizedState = null),
|
||||
(effectTag.updateQueue = null));
|
||||
}
|
||||
nextEffect = nextEffect.nextEffect;
|
||||
}
|
||||
@@ -5586,20 +5580,22 @@ function completeUnitOfWork(workInProgress) {
|
||||
break a;
|
||||
}
|
||||
fiber = null !== fiber;
|
||||
viewConfig = null !== current && null !== current.memoizedState;
|
||||
renderExpirationTime =
|
||||
null !== current && null !== current.memoizedState;
|
||||
null !== current &&
|
||||
!fiber &&
|
||||
viewConfig &&
|
||||
renderExpirationTime &&
|
||||
((current = current.child.sibling),
|
||||
null !== current &&
|
||||
reconcileChildFibers(
|
||||
current$$1,
|
||||
current,
|
||||
null,
|
||||
renderExpirationTime
|
||||
));
|
||||
((viewConfig = current$$1.firstEffect),
|
||||
null !== viewConfig
|
||||
? ((current$$1.firstEffect = current),
|
||||
(current.nextEffect = viewConfig))
|
||||
: ((current$$1.firstEffect = current$$1.lastEffect = current),
|
||||
(current.nextEffect = null)),
|
||||
(current.effectTag = 8)));
|
||||
if (
|
||||
fiber !== viewConfig ||
|
||||
fiber !== renderExpirationTime ||
|
||||
(0 === (current$$1.effectTag & 1) && fiber)
|
||||
)
|
||||
current$$1.effectTag |= 4;
|
||||
@@ -5959,9 +5955,10 @@ function scheduleWorkToRoot(fiber, expirationTime) {
|
||||
}
|
||||
node = node.return;
|
||||
}
|
||||
if (null === root) return null;
|
||||
fiber = tracing.__interactionsRef.current;
|
||||
if (0 < fiber.size) {
|
||||
if (
|
||||
null !== root &&
|
||||
((fiber = tracing.__interactionsRef.current), 0 < fiber.size)
|
||||
) {
|
||||
alternate = root.pendingInteractionMap;
|
||||
var pendingInteractions = alternate.get(expirationTime);
|
||||
null != pendingInteractions
|
||||
@@ -6290,7 +6287,7 @@ function onUncaughtError(error) {
|
||||
nextFlushedRoot.expirationTime = 0;
|
||||
hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error));
|
||||
}
|
||||
function findHostInstance$1(component) {
|
||||
function findHostInstance(component) {
|
||||
var fiber = component._reactInternalFiber;
|
||||
void 0 === fiber &&
|
||||
("function" === typeof component.render
|
||||
@@ -6403,7 +6400,7 @@ function findNodeHandle(componentOrHandle) {
|
||||
if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag;
|
||||
if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag)
|
||||
return componentOrHandle.canonical._nativeTag;
|
||||
componentOrHandle = findHostInstance$1(componentOrHandle);
|
||||
componentOrHandle = findHostInstance(componentOrHandle);
|
||||
return null == componentOrHandle
|
||||
? componentOrHandle
|
||||
: componentOrHandle.canonical
|
||||
@@ -6499,7 +6496,7 @@ var roots = new Map(),
|
||||
};
|
||||
return ReactNativeComponent;
|
||||
})(React.Component);
|
||||
})(findNodeHandle, findHostInstance$1),
|
||||
})(findNodeHandle, findHostInstance),
|
||||
findNodeHandle: findNodeHandle,
|
||||
render: function(element, containerTag, callback) {
|
||||
var root = roots.get(containerTag);
|
||||
@@ -6612,7 +6609,7 @@ var roots = new Map(),
|
||||
TextInputState.blurTextInput(findNodeHandle(this));
|
||||
}
|
||||
};
|
||||
})(findNodeHandle, findHostInstance$1)
|
||||
})(findNodeHandle, findHostInstance)
|
||||
}
|
||||
};
|
||||
(function(devToolsConfig) {
|
||||
|
||||
@@ -956,10 +956,6 @@ var eventTypes$1 = {
|
||||
}
|
||||
}
|
||||
},
|
||||
customBubblingEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes,
|
||||
customDirectEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes,
|
||||
ReactNativeBridgeEventPlugin = {
|
||||
eventTypes: ReactNativeViewConfigRegistry.eventTypes,
|
||||
extractEvents: function(
|
||||
@@ -969,8 +965,10 @@ var eventTypes$1 = {
|
||||
nativeEventTarget
|
||||
) {
|
||||
if (null == targetInst) return null;
|
||||
var bubbleDispatchConfig = customBubblingEventTypes$1[topLevelType],
|
||||
directDispatchConfig = customDirectEventTypes$1[topLevelType];
|
||||
var bubbleDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes[topLevelType],
|
||||
directDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes[topLevelType];
|
||||
invariant(
|
||||
bubbleDispatchConfig || directDispatchConfig,
|
||||
'Unsupported top level event type "%s" dispatched',
|
||||
@@ -1077,9 +1075,6 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) {
|
||||
});
|
||||
}
|
||||
RCTEventEmitter.register({
|
||||
getListener: getListener,
|
||||
registrationNames: registrationNameModules,
|
||||
_receiveRootNodeIDEvent: _receiveRootNodeIDEvent,
|
||||
receiveEvent: function(rootNodeID, topLevelType, nativeEventParam) {
|
||||
_receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);
|
||||
},
|
||||
@@ -1606,7 +1601,7 @@ function setTimeoutCallback() {
|
||||
function shim$1() {
|
||||
invariant(
|
||||
!1,
|
||||
"The current renderer does not support hyration. This error is likely caused by a bug in React. Please file an issue."
|
||||
"The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue."
|
||||
);
|
||||
}
|
||||
var UPDATE_SIGNAL = {},
|
||||
@@ -1642,17 +1637,19 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
var info = "";
|
||||
do {
|
||||
a: switch (workInProgress.tag) {
|
||||
case 2:
|
||||
case 16:
|
||||
case 0:
|
||||
case 1:
|
||||
case 5:
|
||||
case 8:
|
||||
case 13:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 10:
|
||||
case 9:
|
||||
var JSCompiler_inline_result = "";
|
||||
break a;
|
||||
default:
|
||||
var owner = workInProgress._debugOwner,
|
||||
source = workInProgress._debugSource,
|
||||
name = getComponentName(workInProgress.type);
|
||||
var JSCompiler_inline_result = null;
|
||||
JSCompiler_inline_result = null;
|
||||
owner && (JSCompiler_inline_result = getComponentName(owner.type));
|
||||
owner = name;
|
||||
name = "";
|
||||
@@ -1666,9 +1663,6 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
: JSCompiler_inline_result &&
|
||||
(name = " (created by " + JSCompiler_inline_result + ")");
|
||||
JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name;
|
||||
break a;
|
||||
default:
|
||||
JSCompiler_inline_result = "";
|
||||
}
|
||||
info += JSCompiler_inline_result;
|
||||
workInProgress = workInProgress.return;
|
||||
@@ -3402,7 +3396,8 @@ function updateMemoComponent(
|
||||
"function" === typeof type &&
|
||||
!shouldConstruct(type) &&
|
||||
void 0 === type.defaultProps &&
|
||||
null === Component.compare
|
||||
null === Component.compare &&
|
||||
void 0 === Component.defaultProps
|
||||
)
|
||||
return (
|
||||
(workInProgress.tag = 15),
|
||||
@@ -3840,7 +3835,6 @@ function updateSuspenseComponent(
|
||||
nextDidTimeout
|
||||
? ((renderExpirationTime = nextProps.fallback),
|
||||
(nextProps = createWorkInProgress(mode, mode.pendingProps, 0)),
|
||||
(nextProps.effectTag |= 2),
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
((nextDidTimeout =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -3853,7 +3847,6 @@ function updateSuspenseComponent(
|
||||
renderExpirationTime,
|
||||
current$$1.expirationTime
|
||||
)),
|
||||
(mode.effectTag |= 2),
|
||||
(renderExpirationTime = nextProps),
|
||||
(nextProps.childExpirationTime = 0),
|
||||
(renderExpirationTime.return = mode.return = workInProgress))
|
||||
@@ -3867,9 +3860,7 @@ function updateSuspenseComponent(
|
||||
nextDidTimeout
|
||||
? ((nextDidTimeout = nextProps.fallback),
|
||||
(nextProps = createFiberFromFragment(null, mode, 0, null)),
|
||||
(nextProps.effectTag |= 2),
|
||||
(nextProps.child = current$$1),
|
||||
(current$$1.return = nextProps),
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
(nextProps.child =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -4105,8 +4096,9 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
default:
|
||||
invariant(
|
||||
!1,
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.",
|
||||
current$$1
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Lazy element type must resolve to a class or function.%s",
|
||||
current$$1,
|
||||
""
|
||||
);
|
||||
}
|
||||
return getDerivedStateFromProps;
|
||||
@@ -4413,9 +4405,10 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
return (
|
||||
(context = workInProgress.type),
|
||||
(hasContext = resolveDefaultProps(
|
||||
context.type,
|
||||
context,
|
||||
workInProgress.pendingProps
|
||||
)),
|
||||
(hasContext = resolveDefaultProps(context.type, hasContext)),
|
||||
updateMemoComponent(
|
||||
current$$1,
|
||||
workInProgress,
|
||||
@@ -4942,7 +4935,12 @@ function commitWork(current$$1, finishedWork) {
|
||||
}
|
||||
else {
|
||||
if (6 === newProps.tag) throw Error("Not yet implemented.");
|
||||
if (null !== newProps.child) {
|
||||
if (13 === newProps.tag && null !== newProps.memoizedState) {
|
||||
current$$1 = newProps.child.sibling;
|
||||
current$$1.return = newProps;
|
||||
newProps = current$$1;
|
||||
continue;
|
||||
} else if (null !== newProps.child) {
|
||||
newProps.child.return = newProps;
|
||||
newProps = newProps.child;
|
||||
continue;
|
||||
@@ -5225,20 +5223,22 @@ function completeUnitOfWork(workInProgress) {
|
||||
break a;
|
||||
}
|
||||
newProps = null !== newProps;
|
||||
type = null !== current && null !== current.memoizedState;
|
||||
renderExpirationTime =
|
||||
null !== current && null !== current.memoizedState;
|
||||
null !== current &&
|
||||
!newProps &&
|
||||
type &&
|
||||
((current = current.child.sibling),
|
||||
null !== current &&
|
||||
reconcileChildFibers(
|
||||
current$$1,
|
||||
current,
|
||||
null,
|
||||
renderExpirationTime
|
||||
));
|
||||
renderExpirationTime &&
|
||||
((type = current.child.sibling),
|
||||
null !== type &&
|
||||
((current = current$$1.firstEffect),
|
||||
null !== current
|
||||
? ((current$$1.firstEffect = type),
|
||||
(type.nextEffect = current))
|
||||
: ((current$$1.firstEffect = current$$1.lastEffect = type),
|
||||
(type.nextEffect = null)),
|
||||
(type.effectTag = 8)));
|
||||
if (
|
||||
newProps !== type ||
|
||||
newProps !== renderExpirationTime ||
|
||||
(0 === (current$$1.effectTag & 1) && newProps)
|
||||
)
|
||||
current$$1.effectTag |= 4;
|
||||
@@ -5432,14 +5432,7 @@ function renderRoot(root$jscomp$0, isYieldy) {
|
||||
thenable.then(returnFiber$jscomp$0, returnFiber$jscomp$0);
|
||||
if (0 === (value.mode & 1)) {
|
||||
value.effectTag |= 64;
|
||||
reconcileChildren(
|
||||
sourceFiber$jscomp$0.alternate,
|
||||
sourceFiber$jscomp$0,
|
||||
null,
|
||||
returnFiber
|
||||
);
|
||||
sourceFiber$jscomp$0.effectTag &= -1025;
|
||||
sourceFiber$jscomp$0.effectTag &= -933;
|
||||
sourceFiber$jscomp$0.effectTag &= -1957;
|
||||
1 === sourceFiber$jscomp$0.tag &&
|
||||
null === sourceFiber$jscomp$0.alternate &&
|
||||
(sourceFiber$jscomp$0.tag = 17);
|
||||
@@ -5696,7 +5689,7 @@ function scheduleWorkToRoot(fiber, expirationTime) {
|
||||
}
|
||||
node = node.return;
|
||||
}
|
||||
return null === root ? null : root;
|
||||
return root;
|
||||
}
|
||||
function scheduleWork(fiber, expirationTime) {
|
||||
fiber = scheduleWorkToRoot(fiber, expirationTime);
|
||||
@@ -6121,13 +6114,18 @@ function completeRoot(root, finishedWork$jscomp$0, expirationTime) {
|
||||
commitWork(nextEffect.alternate, nextEffect);
|
||||
break;
|
||||
case 8:
|
||||
(prevState = nextEffect),
|
||||
unmountHostComponents(prevState),
|
||||
(prevState.return = null),
|
||||
(prevState.child = null),
|
||||
prevState.alternate &&
|
||||
((prevState.alternate.child = null),
|
||||
(prevState.alternate.return = null));
|
||||
prevState = nextEffect;
|
||||
unmountHostComponents(prevState);
|
||||
prevState.return = null;
|
||||
prevState.child = null;
|
||||
prevState.memoizedState = null;
|
||||
prevState.updateQueue = null;
|
||||
var alternate = prevState.alternate;
|
||||
null !== alternate &&
|
||||
((alternate.return = null),
|
||||
(alternate.child = null),
|
||||
(alternate.memoizedState = null),
|
||||
(alternate.updateQueue = null));
|
||||
}
|
||||
nextEffect = nextEffect.nextEffect;
|
||||
}
|
||||
@@ -6151,24 +6149,24 @@ function completeRoot(root, finishedWork$jscomp$0, expirationTime) {
|
||||
var effectTag$jscomp$0 = nextEffect.effectTag;
|
||||
if (effectTag$jscomp$0 & 36) {
|
||||
var current$$1$jscomp$1 = nextEffect.alternate;
|
||||
current$$1 = nextEffect;
|
||||
prevProps = currentRef;
|
||||
switch (current$$1.tag) {
|
||||
alternate = nextEffect;
|
||||
current$$1 = currentRef;
|
||||
switch (alternate.tag) {
|
||||
case 0:
|
||||
case 11:
|
||||
case 15:
|
||||
break;
|
||||
case 1:
|
||||
var instance$jscomp$0 = current$$1.stateNode;
|
||||
if (current$$1.effectTag & 4)
|
||||
var instance$jscomp$0 = alternate.stateNode;
|
||||
if (alternate.effectTag & 4)
|
||||
if (null === current$$1$jscomp$1)
|
||||
instance$jscomp$0.componentDidMount();
|
||||
else {
|
||||
var prevProps$jscomp$0 =
|
||||
current$$1.elementType === current$$1.type
|
||||
alternate.elementType === alternate.type
|
||||
? current$$1$jscomp$1.memoizedProps
|
||||
: resolveDefaultProps(
|
||||
current$$1.type,
|
||||
alternate.type,
|
||||
current$$1$jscomp$1.memoizedProps
|
||||
);
|
||||
instance$jscomp$0.componentDidUpdate(
|
||||
@@ -6177,32 +6175,32 @@ function completeRoot(root, finishedWork$jscomp$0, expirationTime) {
|
||||
instance$jscomp$0.__reactInternalSnapshotBeforeUpdate
|
||||
);
|
||||
}
|
||||
var updateQueue = current$$1.updateQueue;
|
||||
var updateQueue = alternate.updateQueue;
|
||||
null !== updateQueue &&
|
||||
commitUpdateQueue(
|
||||
current$$1,
|
||||
alternate,
|
||||
updateQueue,
|
||||
instance$jscomp$0,
|
||||
prevProps
|
||||
current$$1
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
var _updateQueue = current$$1.updateQueue;
|
||||
var _updateQueue = alternate.updateQueue;
|
||||
if (null !== _updateQueue) {
|
||||
prevState = null;
|
||||
if (null !== current$$1.child)
|
||||
switch (current$$1.child.tag) {
|
||||
prevProps = null;
|
||||
if (null !== alternate.child)
|
||||
switch (alternate.child.tag) {
|
||||
case 5:
|
||||
prevState = current$$1.child.stateNode;
|
||||
prevProps = alternate.child.stateNode;
|
||||
break;
|
||||
case 1:
|
||||
prevState = current$$1.child.stateNode;
|
||||
prevProps = alternate.child.stateNode;
|
||||
}
|
||||
commitUpdateQueue(
|
||||
current$$1,
|
||||
alternate,
|
||||
_updateQueue,
|
||||
prevState,
|
||||
prevProps
|
||||
prevProps,
|
||||
current$$1
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -6276,7 +6274,7 @@ function onUncaughtError(error) {
|
||||
nextFlushedRoot.expirationTime = 0;
|
||||
hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error));
|
||||
}
|
||||
function findHostInstance$1(component) {
|
||||
function findHostInstance(component) {
|
||||
var fiber = component._reactInternalFiber;
|
||||
void 0 === fiber &&
|
||||
("function" === typeof component.render
|
||||
@@ -6389,7 +6387,7 @@ function findNodeHandle(componentOrHandle) {
|
||||
if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag;
|
||||
if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag)
|
||||
return componentOrHandle.canonical._nativeTag;
|
||||
componentOrHandle = findHostInstance$1(componentOrHandle);
|
||||
componentOrHandle = findHostInstance(componentOrHandle);
|
||||
return null == componentOrHandle
|
||||
? componentOrHandle
|
||||
: componentOrHandle.canonical
|
||||
@@ -6485,7 +6483,7 @@ var roots = new Map(),
|
||||
};
|
||||
return ReactNativeComponent;
|
||||
})(React.Component);
|
||||
})(findNodeHandle, findHostInstance$1),
|
||||
})(findNodeHandle, findHostInstance),
|
||||
findNodeHandle: findNodeHandle,
|
||||
render: function(element, containerTag, callback) {
|
||||
var root = roots.get(containerTag);
|
||||
@@ -6598,7 +6596,7 @@ var roots = new Map(),
|
||||
TextInputState.blurTextInput(findNodeHandle(this));
|
||||
}
|
||||
};
|
||||
})(findNodeHandle, findHostInstance$1),
|
||||
})(findNodeHandle, findHostInstance),
|
||||
computeComponentStackForErrorReporting: function(reactTag) {
|
||||
return (reactTag = getInstanceFromTag(reactTag))
|
||||
? getStackByFiberInDevAndProd(reactTag)
|
||||
|
||||
@@ -957,10 +957,6 @@ var eventTypes$1 = {
|
||||
}
|
||||
}
|
||||
},
|
||||
customBubblingEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes,
|
||||
customDirectEventTypes$1 =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes,
|
||||
ReactNativeBridgeEventPlugin = {
|
||||
eventTypes: ReactNativeViewConfigRegistry.eventTypes,
|
||||
extractEvents: function(
|
||||
@@ -970,8 +966,10 @@ var eventTypes$1 = {
|
||||
nativeEventTarget
|
||||
) {
|
||||
if (null == targetInst) return null;
|
||||
var bubbleDispatchConfig = customBubblingEventTypes$1[topLevelType],
|
||||
directDispatchConfig = customDirectEventTypes$1[topLevelType];
|
||||
var bubbleDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customBubblingEventTypes[topLevelType],
|
||||
directDispatchConfig =
|
||||
ReactNativeViewConfigRegistry.customDirectEventTypes[topLevelType];
|
||||
invariant(
|
||||
bubbleDispatchConfig || directDispatchConfig,
|
||||
'Unsupported top level event type "%s" dispatched',
|
||||
@@ -1078,9 +1076,6 @@ function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) {
|
||||
});
|
||||
}
|
||||
RCTEventEmitter.register({
|
||||
getListener: getListener,
|
||||
registrationNames: registrationNameModules,
|
||||
_receiveRootNodeIDEvent: _receiveRootNodeIDEvent,
|
||||
receiveEvent: function(rootNodeID, topLevelType, nativeEventParam) {
|
||||
_receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);
|
||||
},
|
||||
@@ -1607,7 +1602,7 @@ function setTimeoutCallback() {
|
||||
function shim$1() {
|
||||
invariant(
|
||||
!1,
|
||||
"The current renderer does not support hyration. This error is likely caused by a bug in React. Please file an issue."
|
||||
"The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue."
|
||||
);
|
||||
}
|
||||
var UPDATE_SIGNAL = {},
|
||||
@@ -1643,17 +1638,19 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
var info = "";
|
||||
do {
|
||||
a: switch (workInProgress.tag) {
|
||||
case 2:
|
||||
case 16:
|
||||
case 0:
|
||||
case 1:
|
||||
case 5:
|
||||
case 8:
|
||||
case 13:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 10:
|
||||
case 9:
|
||||
var JSCompiler_inline_result = "";
|
||||
break a;
|
||||
default:
|
||||
var owner = workInProgress._debugOwner,
|
||||
source = workInProgress._debugSource,
|
||||
name = getComponentName(workInProgress.type);
|
||||
var JSCompiler_inline_result = null;
|
||||
JSCompiler_inline_result = null;
|
||||
owner && (JSCompiler_inline_result = getComponentName(owner.type));
|
||||
owner = name;
|
||||
name = "";
|
||||
@@ -1667,9 +1664,6 @@ function getStackByFiberInDevAndProd(workInProgress) {
|
||||
: JSCompiler_inline_result &&
|
||||
(name = " (created by " + JSCompiler_inline_result + ")");
|
||||
JSCompiler_inline_result = "\n in " + (owner || "Unknown") + name;
|
||||
break a;
|
||||
default:
|
||||
JSCompiler_inline_result = "";
|
||||
}
|
||||
info += JSCompiler_inline_result;
|
||||
workInProgress = workInProgress.return;
|
||||
@@ -3460,7 +3454,8 @@ function updateMemoComponent(
|
||||
"function" === typeof type &&
|
||||
!shouldConstruct(type) &&
|
||||
void 0 === type.defaultProps &&
|
||||
null === Component.compare
|
||||
null === Component.compare &&
|
||||
void 0 === Component.defaultProps
|
||||
)
|
||||
return (
|
||||
(workInProgress.tag = 15),
|
||||
@@ -3908,7 +3903,6 @@ function updateSuspenseComponent(
|
||||
current$$1.pendingProps,
|
||||
0
|
||||
);
|
||||
renderExpirationTime.effectTag |= 2;
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
((nextDidTimeout =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -3928,7 +3922,6 @@ function updateSuspenseComponent(
|
||||
nextProps,
|
||||
mode.expirationTime
|
||||
);
|
||||
nextProps.effectTag |= 2;
|
||||
mode = renderExpirationTime;
|
||||
renderExpirationTime.childExpirationTime = 0;
|
||||
renderExpirationTime = nextProps;
|
||||
@@ -3943,9 +3936,7 @@ function updateSuspenseComponent(
|
||||
else if (((current$$1 = current$$1.child), nextDidTimeout)) {
|
||||
nextDidTimeout = nextProps.fallback;
|
||||
nextProps = createFiberFromFragment(null, mode, 0, null);
|
||||
nextProps.effectTag |= 2;
|
||||
nextProps.child = current$$1;
|
||||
current$$1.return = nextProps;
|
||||
0 === (workInProgress.mode & 1) &&
|
||||
(nextProps.child =
|
||||
null !== workInProgress.memoizedState
|
||||
@@ -4193,8 +4184,9 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
default:
|
||||
invariant(
|
||||
!1,
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Promise elements must resolve to a class or function.",
|
||||
current$$1
|
||||
"Element type is invalid. Received a promise that resolves to: %s. Lazy element type must resolve to a class or function.%s",
|
||||
current$$1,
|
||||
""
|
||||
);
|
||||
}
|
||||
return getDerivedStateFromProps;
|
||||
@@ -4502,9 +4494,10 @@ function beginWork(current$$1, workInProgress, renderExpirationTime) {
|
||||
return (
|
||||
(context = workInProgress.type),
|
||||
(hasContext = resolveDefaultProps(
|
||||
context.type,
|
||||
context,
|
||||
workInProgress.pendingProps
|
||||
)),
|
||||
(hasContext = resolveDefaultProps(context.type, hasContext)),
|
||||
updateMemoComponent(
|
||||
current$$1,
|
||||
workInProgress,
|
||||
@@ -5031,7 +5024,12 @@ function commitWork(current$$1, finishedWork) {
|
||||
}
|
||||
else {
|
||||
if (6 === newProps.tag) throw Error("Not yet implemented.");
|
||||
if (null !== newProps.child) {
|
||||
if (13 === newProps.tag && null !== newProps.memoizedState) {
|
||||
current$$1 = newProps.child.sibling;
|
||||
current$$1.return = newProps;
|
||||
newProps = current$$1;
|
||||
continue;
|
||||
} else if (null !== newProps.child) {
|
||||
newProps.child.return = newProps;
|
||||
newProps = newProps.child;
|
||||
continue;
|
||||
@@ -5149,14 +5147,7 @@ function throwException(
|
||||
thenable.then(returnFiber, returnFiber);
|
||||
if (0 === (value.mode & 1)) {
|
||||
value.effectTag |= 64;
|
||||
reconcileChildren(
|
||||
sourceFiber.alternate,
|
||||
sourceFiber,
|
||||
null,
|
||||
renderExpirationTime
|
||||
);
|
||||
sourceFiber.effectTag &= -1025;
|
||||
sourceFiber.effectTag &= -933;
|
||||
sourceFiber.effectTag &= -1957;
|
||||
1 === sourceFiber.tag &&
|
||||
null === sourceFiber.alternate &&
|
||||
(sourceFiber.tag = 17);
|
||||
@@ -5276,7 +5267,7 @@ var DispatcherWithoutHooks = { readContext: readContext },
|
||||
invariant(
|
||||
null != tracing.__interactionsRef &&
|
||||
null != tracing.__interactionsRef.current,
|
||||
"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `schedule/tracing` module with `schedule/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling"
|
||||
"It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling"
|
||||
);
|
||||
var isWorking = !1,
|
||||
nextUnitOfWork = null,
|
||||
@@ -5356,9 +5347,14 @@ function commitAllHostEffects() {
|
||||
unmountHostComponents(effectTag),
|
||||
(effectTag.return = null),
|
||||
(effectTag.child = null),
|
||||
effectTag.alternate &&
|
||||
((effectTag.alternate.child = null),
|
||||
(effectTag.alternate.return = null));
|
||||
(effectTag.memoizedState = null),
|
||||
(effectTag.updateQueue = null),
|
||||
(effectTag = effectTag.alternate),
|
||||
null !== effectTag &&
|
||||
((effectTag.return = null),
|
||||
(effectTag.child = null),
|
||||
(effectTag.memoizedState = null),
|
||||
(effectTag.updateQueue = null));
|
||||
}
|
||||
nextEffect = nextEffect.nextEffect;
|
||||
}
|
||||
@@ -5769,19 +5765,24 @@ function completeUnitOfWork(workInProgress) {
|
||||
break a;
|
||||
}
|
||||
fiber = null !== fiber;
|
||||
type = null !== current && null !== current.memoizedState;
|
||||
renderExpirationTime =
|
||||
null !== current && null !== current.memoizedState;
|
||||
null !== current &&
|
||||
!fiber &&
|
||||
type &&
|
||||
((current = current.child.sibling),
|
||||
null !== current &&
|
||||
reconcileChildFibers(
|
||||
current$$1,
|
||||
current,
|
||||
null,
|
||||
renderExpirationTime
|
||||
));
|
||||
if (fiber !== type || (0 === (current$$1.effectTag & 1) && fiber))
|
||||
renderExpirationTime &&
|
||||
((type = current.child.sibling),
|
||||
null !== type &&
|
||||
((current = current$$1.firstEffect),
|
||||
null !== current
|
||||
? ((current$$1.firstEffect = type),
|
||||
(type.nextEffect = current))
|
||||
: ((current$$1.firstEffect = current$$1.lastEffect = type),
|
||||
(type.nextEffect = null)),
|
||||
(type.effectTag = 8)));
|
||||
if (
|
||||
fiber !== renderExpirationTime ||
|
||||
(0 === (current$$1.effectTag & 1) && fiber)
|
||||
)
|
||||
current$$1.effectTag |= 4;
|
||||
break;
|
||||
case 7:
|
||||
@@ -6147,9 +6148,10 @@ function scheduleWorkToRoot(fiber, expirationTime) {
|
||||
}
|
||||
node = node.return;
|
||||
}
|
||||
if (null === root) return null;
|
||||
fiber = tracing.__interactionsRef.current;
|
||||
if (0 < fiber.size) {
|
||||
if (
|
||||
null !== root &&
|
||||
((fiber = tracing.__interactionsRef.current), 0 < fiber.size)
|
||||
) {
|
||||
alternate = root.pendingInteractionMap;
|
||||
var pendingInteractions = alternate.get(expirationTime);
|
||||
null != pendingInteractions
|
||||
@@ -6478,7 +6480,7 @@ function onUncaughtError(error) {
|
||||
nextFlushedRoot.expirationTime = 0;
|
||||
hasUnhandledError || ((hasUnhandledError = !0), (unhandledError = error));
|
||||
}
|
||||
function findHostInstance$1(component) {
|
||||
function findHostInstance(component) {
|
||||
var fiber = component._reactInternalFiber;
|
||||
void 0 === fiber &&
|
||||
("function" === typeof component.render
|
||||
@@ -6591,7 +6593,7 @@ function findNodeHandle(componentOrHandle) {
|
||||
if (componentOrHandle._nativeTag) return componentOrHandle._nativeTag;
|
||||
if (componentOrHandle.canonical && componentOrHandle.canonical._nativeTag)
|
||||
return componentOrHandle.canonical._nativeTag;
|
||||
componentOrHandle = findHostInstance$1(componentOrHandle);
|
||||
componentOrHandle = findHostInstance(componentOrHandle);
|
||||
return null == componentOrHandle
|
||||
? componentOrHandle
|
||||
: componentOrHandle.canonical
|
||||
@@ -6687,7 +6689,7 @@ var roots = new Map(),
|
||||
};
|
||||
return ReactNativeComponent;
|
||||
})(React.Component);
|
||||
})(findNodeHandle, findHostInstance$1),
|
||||
})(findNodeHandle, findHostInstance),
|
||||
findNodeHandle: findNodeHandle,
|
||||
render: function(element, containerTag, callback) {
|
||||
var root = roots.get(containerTag);
|
||||
@@ -6805,7 +6807,7 @@ var roots = new Map(),
|
||||
TextInputState.blurTextInput(findNodeHandle(this));
|
||||
}
|
||||
};
|
||||
})(findNodeHandle, findHostInstance$1),
|
||||
})(findNodeHandle, findHostInstance),
|
||||
computeComponentStackForErrorReporting: function(reactTag) {
|
||||
return (reactTag = getInstanceFromTag(reactTag))
|
||||
? getStackByFiberInDevAndProd(reactTag)
|
||||
|
||||
@@ -59,6 +59,7 @@ export type ReactContext<T> = {
|
||||
|
||||
_currentValue: T,
|
||||
_currentValue2: T,
|
||||
_threadCount: number,
|
||||
|
||||
// DEV only
|
||||
_currentRenderer?: Object | null,
|
||||
|
||||
@@ -339,7 +339,7 @@ module.exports = {
|
||||
) {
|
||||
let value;
|
||||
|
||||
if (ReactNativeStyleAttributes[property] === true) {
|
||||
if (typeof ReactNativeStyleAttributes[property] === 'string') {
|
||||
value = {};
|
||||
} else if (typeof ReactNativeStyleAttributes[property] === 'object') {
|
||||
value = ReactNativeStyleAttributes[property];
|
||||
|
||||
@@ -27,10 +27,10 @@ import type {PressRetentionOffset, TextProps} from 'TextProps';
|
||||
|
||||
type ResponseHandlers = $ReadOnly<{|
|
||||
onStartShouldSetResponder: () => boolean,
|
||||
onResponderGrant: (event: PressEvent, dispatchID: string) => void,
|
||||
onResponderMove: (event: PressEvent) => void,
|
||||
onResponderRelease: (event: PressEvent) => void,
|
||||
onResponderTerminate: (event: PressEvent) => void,
|
||||
onResponderGrant: (event: SyntheticEvent<>, dispatchID: string) => void,
|
||||
onResponderMove: (event: SyntheticEvent<>) => void,
|
||||
onResponderRelease: (event: SyntheticEvent<>) => void,
|
||||
onResponderTerminate: (event: SyntheticEvent<>) => void,
|
||||
onResponderTerminationRequest: () => boolean,
|
||||
|}>;
|
||||
|
||||
@@ -93,12 +93,12 @@ class TouchableText extends React.Component<Props, State> {
|
||||
touchableHandleLongPress: ?(event: PressEvent) => void;
|
||||
touchableHandlePress: ?(event: PressEvent) => void;
|
||||
touchableHandleResponderGrant: ?(
|
||||
event: PressEvent,
|
||||
event: SyntheticEvent<>,
|
||||
dispatchID: string,
|
||||
) => void;
|
||||
touchableHandleResponderMove: ?(event: PressEvent) => void;
|
||||
touchableHandleResponderRelease: ?(event: PressEvent) => void;
|
||||
touchableHandleResponderTerminate: ?(event: PressEvent) => void;
|
||||
touchableHandleResponderMove: ?(event: SyntheticEvent<>) => void;
|
||||
touchableHandleResponderRelease: ?(event: SyntheticEvent<>) => void;
|
||||
touchableHandleResponderTerminate: ?(event: SyntheticEvent<>) => void;
|
||||
touchableHandleResponderTerminationRequest: ?() => boolean;
|
||||
|
||||
state = {
|
||||
@@ -173,25 +173,25 @@ class TouchableText extends React.Component<Props, State> {
|
||||
}
|
||||
return shouldSetResponder;
|
||||
},
|
||||
onResponderGrant: (event: PressEvent, dispatchID: string): void => {
|
||||
onResponderGrant: (event: SyntheticEvent<>, dispatchID: string): void => {
|
||||
nullthrows(this.touchableHandleResponderGrant)(event, dispatchID);
|
||||
if (this.props.onResponderGrant != null) {
|
||||
this.props.onResponderGrant.call(this, event, dispatchID);
|
||||
}
|
||||
},
|
||||
onResponderMove: (event: PressEvent): void => {
|
||||
onResponderMove: (event: SyntheticEvent<>): void => {
|
||||
nullthrows(this.touchableHandleResponderMove)(event);
|
||||
if (this.props.onResponderMove != null) {
|
||||
this.props.onResponderMove.call(this, event);
|
||||
}
|
||||
},
|
||||
onResponderRelease: (event: PressEvent): void => {
|
||||
onResponderRelease: (event: SyntheticEvent<>): void => {
|
||||
nullthrows(this.touchableHandleResponderRelease)(event);
|
||||
if (this.props.onResponderRelease != null) {
|
||||
this.props.onResponderRelease.call(this, event);
|
||||
}
|
||||
},
|
||||
onResponderTerminate: (event: PressEvent): void => {
|
||||
onResponderTerminate: (event: SyntheticEvent<>): void => {
|
||||
nullthrows(this.touchableHandleResponderTerminate)(event);
|
||||
if (this.props.onResponderTerminate != null) {
|
||||
this.props.onResponderTerminate.call(this, event);
|
||||
|
||||
@@ -290,9 +290,6 @@
|
||||
RCTRoundPixelValue(attachmentSize.width),
|
||||
RCTRoundPixelValue(attachmentSize.height)
|
||||
}};
|
||||
|
||||
NSRange truncatedGlyphRange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:range.location];
|
||||
BOOL viewIsTruncated = NSIntersectionRange(range, truncatedGlyphRange).length != 0;
|
||||
|
||||
RCTLayoutContext localLayoutContext = layoutContext;
|
||||
localLayoutContext.absolutePosition.x += frame.origin.x;
|
||||
@@ -303,11 +300,9 @@
|
||||
layoutDirection:self.layoutMetrics.layoutDirection
|
||||
layoutContext:localLayoutContext];
|
||||
|
||||
// Reinforcing a proper frame origin for the Shadow View.
|
||||
RCTLayoutMetrics localLayoutMetrics = shadowView.layoutMetrics;
|
||||
localLayoutMetrics.frame.origin = frame.origin; // Reinforcing a proper frame origin for the Shadow View.
|
||||
if (viewIsTruncated) {
|
||||
localLayoutMetrics.displayType = RCTDisplayTypeNone;
|
||||
}
|
||||
localLayoutMetrics.frame.origin = frame.origin;
|
||||
[shadowView layoutWithMetrics:localLayoutMetrics layoutContext:localLayoutContext];
|
||||
}
|
||||
];
|
||||
|
||||
@@ -110,7 +110,21 @@ static UIColor *defaultPlaceholderColor()
|
||||
|
||||
- (void)setAttributedText:(NSAttributedString *)attributedText
|
||||
{
|
||||
[super setAttributedText:attributedText];
|
||||
// Using `setAttributedString:` while user is typing breaks some internal mechanics
|
||||
// when entering complex input languages such as Chinese, Korean or Japanese.
|
||||
// see: https://github.com/facebook/react-native/issues/19339
|
||||
|
||||
// We try to avoid calling this method as much as we can.
|
||||
// If the text has changed, there is nothing we can do.
|
||||
if (![super.attributedText.string isEqualToString:attributedText.string]) {
|
||||
[super setAttributedText:attributedText];
|
||||
} else {
|
||||
// But if the text is preserved, we just copying the attributes from the source string.
|
||||
if (![super.attributedText isEqualToAttributedString:attributedText]) {
|
||||
[self copyTextAttributesFrom:attributedText];
|
||||
}
|
||||
}
|
||||
|
||||
[self textDidChange];
|
||||
}
|
||||
|
||||
@@ -241,4 +255,20 @@ static UIColor *defaultPlaceholderColor()
|
||||
_placeholderView.hidden = !isVisible;
|
||||
}
|
||||
|
||||
#pragma mark - Utility Methods
|
||||
|
||||
- (void)copyTextAttributesFrom:(NSAttributedString *)sourceString
|
||||
{
|
||||
[self.textStorage beginEditing];
|
||||
|
||||
NSTextStorage *textStorage = self.textStorage;
|
||||
[sourceString enumerateAttributesInRange:NSMakeRange(0, sourceString.length)
|
||||
options:NSAttributedStringEnumerationReverse
|
||||
usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
|
||||
[textStorage setAttributes:attrs range:range];
|
||||
}];
|
||||
|
||||
[self.textStorage endEditing];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
@@ -106,12 +106,12 @@ export type TextProps = $ReadOnly<{
|
||||
* See https://facebook.github.io/react-native/docs/text.html#onpress
|
||||
*/
|
||||
onPress?: ?(event: PressEvent) => mixed,
|
||||
onResponderGrant?: ?(event: PressEvent, dispatchID: string) => void,
|
||||
onResponderMove?: ?(event: PressEvent) => void,
|
||||
onResponderRelease?: ?(event: PressEvent) => void,
|
||||
onResponderTerminate?: ?(event: PressEvent) => void,
|
||||
onResponderTerminationRequest?: ?() => boolean,
|
||||
onStartShouldSetResponder?: ?() => boolean,
|
||||
onResponderGrant?: ?Function,
|
||||
onResponderMove?: ?Function,
|
||||
onResponderRelease?: ?Function,
|
||||
onResponderTerminate?: ?Function,
|
||||
onResponderTerminationRequest?: ?Function,
|
||||
onStartShouldSetResponder?: ?Function,
|
||||
onTextLayout?: ?(event: TextLayoutEvent) => mixed,
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,11 +19,8 @@ const Platform = {
|
||||
return constants && constants.Version;
|
||||
},
|
||||
get isTesting(): boolean {
|
||||
if (__DEV__) {
|
||||
const constants = NativeModules.PlatformConstants;
|
||||
return constants && constants.isTesting;
|
||||
}
|
||||
return false;
|
||||
const constants = NativeModules.PlatformConstants;
|
||||
return constants && constants.isTesting;
|
||||
},
|
||||
get isTV(): boolean {
|
||||
const constants = NativeModules.PlatformConstants;
|
||||
|
||||
@@ -33,11 +33,8 @@ const Platform = {
|
||||
return constants ? constants.interfaceIdiom === 'tv' : false;
|
||||
},
|
||||
get isTesting(): boolean {
|
||||
if (__DEV__) {
|
||||
const constants = NativeModules.PlatformConstants;
|
||||
return constants && constants.isTesting;
|
||||
}
|
||||
return false;
|
||||
const constants = NativeModules.PlatformConstants;
|
||||
return constants && constants.isTesting;
|
||||
},
|
||||
select: (obj: Object) => ('ios' in obj ? obj.ios : obj.default),
|
||||
};
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('React');
|
||||
const ReactTestRenderer = require('react-test-renderer');
|
||||
|
||||
const {Switch, Text, TextInput, VirtualizedList} = require('react-native');
|
||||
|
||||
import type {
|
||||
ReactTestInstance,
|
||||
ReactTestRendererNode,
|
||||
Predicate,
|
||||
} from 'react-test-renderer';
|
||||
|
||||
function byClickable(): Predicate {
|
||||
return withMessage(
|
||||
node =>
|
||||
// note: <Text /> lazy-mounts press handlers after the first press,
|
||||
// so this is a workaround for targeting text nodes.
|
||||
(node.type === Text &&
|
||||
node.props &&
|
||||
typeof node.props.onPress === 'function') ||
|
||||
// note: Special casing <Switch /> since it doesn't use touchable
|
||||
(node.type === Switch && node.props && node.props.disabled !== true) ||
|
||||
(node.instance &&
|
||||
typeof node.instance.touchableHandlePress === 'function'),
|
||||
'is clickable',
|
||||
);
|
||||
}
|
||||
|
||||
function byTestID(testID: string): Predicate {
|
||||
return withMessage(
|
||||
node => node.props && node.props.testID === testID,
|
||||
`testID prop equals ${testID}`,
|
||||
);
|
||||
}
|
||||
|
||||
function byTextMatching(regex: RegExp): Predicate {
|
||||
return withMessage(
|
||||
node => node.props && regex.exec(node.props.children),
|
||||
`text content matches ${regex.toString()}`,
|
||||
);
|
||||
}
|
||||
|
||||
function enter(instance: ReactTestInstance, text: string) {
|
||||
const input = instance.findByType(TextInput);
|
||||
input.instance._onChange({nativeEvent: {text}});
|
||||
}
|
||||
|
||||
// Returns null if there is no error, otherwise returns an error message string.
|
||||
function maximumDepthError(
|
||||
tree: {toJSON: () => ReactTestRendererNode},
|
||||
maxDepthLimit: number,
|
||||
): ?string {
|
||||
const maxDepth = maximumDepthOfJSON(tree.toJSON());
|
||||
if (maxDepth > maxDepthLimit) {
|
||||
return (
|
||||
`maximumDepth of ${maxDepth} exceeded limit of ${maxDepthLimit} - this is a proxy ` +
|
||||
'metric to protect against stack overflow errors:\n\n' +
|
||||
'https://fburl.com/rn-view-stack-overflow.\n\n' +
|
||||
'To fix, you need to remove native layers from your hierarchy, such as unnecessary View ' +
|
||||
'wrappers.'
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function expectNoConsoleWarn() {
|
||||
(jest: $FlowFixMe).spyOn(console, 'warn').mockImplementation((...args) => {
|
||||
expect(args).toBeFalsy();
|
||||
});
|
||||
}
|
||||
|
||||
function expectNoConsoleError() {
|
||||
let hasNotFailed = true;
|
||||
(jest: $FlowFixMe).spyOn(console, 'error').mockImplementation((...args) => {
|
||||
if (hasNotFailed) {
|
||||
hasNotFailed = false; // set false to prevent infinite recursion
|
||||
expect(args).toBeFalsy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Takes a node from toJSON()
|
||||
function maximumDepthOfJSON(node: ReactTestRendererNode): number {
|
||||
if (node == null) {
|
||||
return 0;
|
||||
} else if (typeof node === 'string' || node.children == null) {
|
||||
return 1;
|
||||
} else {
|
||||
let maxDepth = 0;
|
||||
node.children.forEach(child => {
|
||||
maxDepth = Math.max(maximumDepthOfJSON(child) + 1, maxDepth);
|
||||
});
|
||||
return maxDepth;
|
||||
}
|
||||
}
|
||||
|
||||
function renderAndEnforceStrictMode(element: React.Node) {
|
||||
expectNoConsoleError();
|
||||
return renderWithStrictMode(element);
|
||||
}
|
||||
|
||||
function renderWithStrictMode(element: React.Node) {
|
||||
const WorkAroundBugWithStrictModeInTestRenderer = prps => prps.children;
|
||||
const StrictMode = (React: $FlowFixMe).StrictMode;
|
||||
return ReactTestRenderer.create(
|
||||
<WorkAroundBugWithStrictModeInTestRenderer>
|
||||
<StrictMode>{element}</StrictMode>
|
||||
</WorkAroundBugWithStrictModeInTestRenderer>,
|
||||
);
|
||||
}
|
||||
|
||||
function tap(instance: ReactTestInstance) {
|
||||
const touchable = instance.find(byClickable());
|
||||
if (touchable.type === Text && touchable.props && touchable.props.onPress) {
|
||||
touchable.props.onPress();
|
||||
} else if (touchable.type === Switch && touchable.props) {
|
||||
const value = !touchable.props.value;
|
||||
const {onChange, onValueChange} = touchable.props;
|
||||
onChange && onChange({nativeEvent: {value}});
|
||||
onValueChange && onValueChange(value);
|
||||
} else {
|
||||
// Only tap when props.disabled isn't set (or there aren't any props)
|
||||
if (!touchable.props || !touchable.props.disabled) {
|
||||
touchable.instance.touchableHandlePress({nativeEvent: {}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToBottom(instance: ReactTestInstance) {
|
||||
const list = instance.findByType(VirtualizedList);
|
||||
list.props && list.props.onEndReached();
|
||||
}
|
||||
|
||||
// To make error messages a little bit better, we attach a custom toString
|
||||
// implementation to a predicate
|
||||
function withMessage(fn: Predicate, message: string): Predicate {
|
||||
(fn: any).toString = () => message;
|
||||
return fn;
|
||||
}
|
||||
|
||||
export {byClickable};
|
||||
export {byTestID};
|
||||
export {byTextMatching};
|
||||
export {enter};
|
||||
export {expectNoConsoleWarn};
|
||||
export {expectNoConsoleError};
|
||||
export {maximumDepthError};
|
||||
export {maximumDepthOfJSON};
|
||||
export {renderAndEnforceStrictMode};
|
||||
export {renderWithStrictMode};
|
||||
export {scrollToBottom};
|
||||
export {tap};
|
||||
export {withMessage};
|
||||
@@ -14,6 +14,7 @@ const invariant = require('fbjs/lib/invariant');
|
||||
|
||||
let showedListViewDeprecation = false;
|
||||
let showedSwipeableListViewDeprecation = false;
|
||||
let showedWebWiewDeprecation = false;
|
||||
|
||||
// Export React, plus some native additions.
|
||||
module.exports = {
|
||||
@@ -170,6 +171,15 @@ module.exports = {
|
||||
return require('VirtualizedList');
|
||||
},
|
||||
get WebView() {
|
||||
if (!showedWebWiewDeprecation) {
|
||||
console.warn(
|
||||
'WebView has been extracted from react-native core and will be removed in a future release. ' +
|
||||
"It can now be installed and imported from 'react-native-webview' instead of 'react-native'. " +
|
||||
'See https://github.com/react-native-community/react-native-webview for more informations.',
|
||||
);
|
||||
|
||||
showedWebWiewDeprecation = true;
|
||||
}
|
||||
return require('WebView');
|
||||
},
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ function mergeInto(one, two) {
|
||||
if (two != null) {
|
||||
checkMergeObjectArg(two);
|
||||
for (var key in two) {
|
||||
if (!two.hasOwnProperty(key)) {
|
||||
if (!Object.prototype.hasOwnProperty.call(two, key)) {
|
||||
continue;
|
||||
}
|
||||
one[key] = two[key];
|
||||
|
||||
@@ -104,10 +104,10 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
|
||||
Folly: cd7933b82a5f7673ed71bafe631f44a575ae77ab
|
||||
Folly: de497beb10f102453a1afa9edbf8cf8a251890de
|
||||
glog: aefd1eb5dda2ab95ba0938556f34b98e2da3a60d
|
||||
React: 9b873b38b92ed8012d7cdf3b965477095ed364c4
|
||||
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
|
||||
yoga: 0885622311729a02c2bc02dca97167787a51488b
|
||||
|
||||
PODFILE CHECKSUM: 7af77fbc34af9646e8c6389e7e2c0b4663bb16d9
|
||||
|
||||
|
||||
@@ -58,6 +58,29 @@ Run the following commands from the react-native folder:
|
||||
|
||||
_Note: The native libs are still built using gradle. Full build with buck is coming soon(tm)._
|
||||
|
||||
## Running Detox Tests on iOS
|
||||
|
||||
Install Detox from [here](https://github.com/wix/Detox/blob/master/docs/Introduction.GettingStarted.md).
|
||||
|
||||
To run the e2e tests locally, run the following commands from the react-native folder:
|
||||
|
||||
yarn build-ios-e2e
|
||||
yarn test-ios-e2e
|
||||
|
||||
These are the equivalent of running:
|
||||
|
||||
detox build -c ios.sim.release
|
||||
detox test -c ios.sim.release --cleanup
|
||||
|
||||
These build the app in Release mode, so the production code is bundled and included in the built app.
|
||||
|
||||
When developing E2E tests, you may want to run in development mode, so that changes to the production code show up immediately. To do this, run:
|
||||
|
||||
detox build -c ios.sim.debug
|
||||
detox test -c ios.sim.debug
|
||||
|
||||
You will also need to have Metro Bundler running in another terminal. Note that if you've previously run the E2E tests in release mode, you may need to delete the `RNTester/build` folder before rerunning `detox build`.
|
||||
|
||||
## Built from source
|
||||
|
||||
Building the app on both iOS and Android means building the React Native framework from source. This way you're running the latest native and JS code the way you see it in your clone of the github repo.
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
C654F0B31EB34A73000B7A9A /* RNTesterTestModule.m in Sources */ = {isa = PBXBuildFile; fileRef = C654F0B21EB34A73000B7A9A /* RNTesterTestModule.m */; };
|
||||
C654F17E1EB34D24000B7A9A /* RNTesterTestModule.m in Sources */ = {isa = PBXBuildFile; fileRef = C654F0B21EB34A73000B7A9A /* RNTesterTestModule.m */; };
|
||||
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
E77B20F321C481F8007FDF6D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEBC7DA214C681C00DD5AC8 /* JavaScriptCore.framework */; };
|
||||
ED2970992150247000B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2970982150247000B7C4FE /* JavaScriptCore.framework */; };
|
||||
EDEBC856214C774100DD5AC8 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEBC7DA214C681C00DD5AC8 /* JavaScriptCore.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -573,6 +574,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E77B20F321C481F8007FDF6D /* JavaScriptCore.framework in Frameworks */,
|
||||
19BA89031F8439A700741C5A /* libRCTBlob.a in Frameworks */,
|
||||
192F69DA1E8240E2008692C7 /* libRCTAnimation.a in Frameworks */,
|
||||
14D6D71E1B2222EF001FB087 /* libRCTActionSheet.a in Frameworks */,
|
||||
@@ -1682,7 +1684,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n$SRCROOT/../scripts/react-native-xcode.sh RNTester/js/RNTesterApp.ios.js";
|
||||
shellScript = "export NODE_BINARY=node\n$SRCROOT/../scripts/react-native-xcode.sh RNTester/js/RNTesterApp.ios.js\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIStatusBarStyle</key>
|
||||
<string>UIStatusBarStyleBlackTranslucent</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
||||
@@ -49,20 +49,21 @@
|
||||
configurationBlock:nil];
|
||||
}
|
||||
|
||||
- (void)testTheTester_ExpectError
|
||||
{
|
||||
[_runner runTest:_cmd
|
||||
module:@"IntegrationTestHarnessTest"
|
||||
initialProps:@{@"shouldThrow": @YES}
|
||||
configurationBlock:nil
|
||||
expectErrorRegex:@"because shouldThrow"];
|
||||
}
|
||||
// Disabled
|
||||
//- (void)testTheTester_ExpectError
|
||||
//{
|
||||
// [_runner runTest:_cmd
|
||||
// module:@"IntegrationTestHarnessTest"
|
||||
// initialProps:@{@"shouldThrow": @YES}
|
||||
//configurationBlock:nil
|
||||
// expectErrorRegex:@"because shouldThrow"];
|
||||
//}
|
||||
|
||||
#pragma mark - JS tests
|
||||
|
||||
// This list should be kept in sync with IntegrationTestsApp.js
|
||||
RCT_TEST(IntegrationTestHarnessTest)
|
||||
RCT_TEST(TimersTest)
|
||||
// RCT_TEST(TimersTest) // Disabled due to issue introduced in 61346d3
|
||||
RCT_TEST(AsyncStorageTest)
|
||||
RCT_TEST(AppEventsTest)
|
||||
//RCT_TEST(ImageCachePolicyTest) // This test never passed.
|
||||
@@ -71,7 +72,7 @@ RCT_TEST(ImageSnapshotTest)
|
||||
RCT_TEST(SimpleSnapshotTest)
|
||||
RCT_TEST(SyncMethodTest)
|
||||
RCT_TEST(PromiseTest)
|
||||
RCT_TEST_ONLY_WITH_PACKAGER(WebSocketTest)
|
||||
RCT_TEST_ONLY_WITH_PACKAGER(WebSocketTest) // Requires a WebSocket test server, see scripts/objc-test.sh
|
||||
RCT_TEST(AccessibilityManagerTest)
|
||||
|
||||
#if !TARGET_OS_TV // tvOS does not fully support WebView
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 153 KiB |
|
After Width: | Height: | Size: 313 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 285 KiB |
|
After Width: | Height: | Size: 586 KiB |
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 336 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 365 KiB After Width: | Height: | Size: 322 KiB |
|
After Width: | Height: | Size: 562 KiB |
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
|
After Width: | Height: | Size: 367 KiB |
@@ -91,8 +91,8 @@ def enableSeparateBuildPerCPUArchitecture = true
|
||||
def enableProguardInReleaseBuilds = true
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.2"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.facebook.react.uiapp"
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @format
|
||||
*/
|
||||
|
||||
/* global device, element, by, expect */
|
||||
|
||||
describe('Button', () => {
|
||||
beforeAll(async () => {
|
||||
await device.reloadReactNative();
|
||||
await element(by.id('explorer_search')).replaceText('<Button>');
|
||||
await element(
|
||||
by.label('<Button> Simple React Native button component.'),
|
||||
).tap();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
//TODO - remove app state persistency, till then, we must go back to main screen,
|
||||
await element(by.label('Back')).tap();
|
||||
});
|
||||
|
||||
it('Simple button should be tappable', async () => {
|
||||
await element(by.label('Press Me')).tap();
|
||||
await expect(element(by.text('Simple has been pressed!'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('Adjusted color button should be tappable', async () => {
|
||||
await element(by.label('Press Purple')).tap();
|
||||
await expect(element(by.text('Purple has been pressed!'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it("Two buttons with JustifyContent:'space-between' should be tappable", async () => {
|
||||
await element(by.label('This looks great!')).tap();
|
||||
await expect(element(by.text('Left has been pressed!'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
await element(by.label('Ok!')).tap();
|
||||
await expect(element(by.text('Right has been pressed!'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('Disabled button should not interact', async () => {
|
||||
await element(by.label('I Am Disabled')).tap();
|
||||
await expect(
|
||||
element(by.text('Disabled has been pressed!')),
|
||||
).toBeNotVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @format
|
||||
*/
|
||||
|
||||
/* global element, by, expect */
|
||||
|
||||
describe('DatePickerIOS', () => {
|
||||
beforeAll(async () => {
|
||||
await element(by.id('explorer_search')).replaceText('<DatePickerIOS>');
|
||||
await element(
|
||||
by.label(
|
||||
'<DatePickerIOS> Select dates and times using the native UIDatePicker.',
|
||||
),
|
||||
).tap();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await element(by.label('Back')).tap();
|
||||
});
|
||||
|
||||
it('Should change indicator with datetime picker', async () => {
|
||||
const testID = 'date-and-time';
|
||||
const indicatorID = 'date-and-time-indicator';
|
||||
|
||||
const testElement = await element(
|
||||
by.type('UIPickerView').withAncestor(by.id(testID)),
|
||||
);
|
||||
const indicator = await element(by.id(indicatorID));
|
||||
|
||||
await expect(testElement).toBeVisible();
|
||||
await expect(indicator).toBeVisible();
|
||||
|
||||
await testElement.setColumnToValue(0, 'Dec 4');
|
||||
await testElement.setColumnToValue(1, '4');
|
||||
await testElement.setColumnToValue(2, '10');
|
||||
await testElement.setColumnToValue(3, 'AM');
|
||||
|
||||
await expect(indicator).toHaveText('12/4/2005 4:10 AM');
|
||||
});
|
||||
|
||||
it('Should change indicator with date-only picker', async () => {
|
||||
const testID = 'date-only';
|
||||
const indicatorID = 'date-and-time-indicator';
|
||||
|
||||
const testElement = await element(
|
||||
by.type('UIPickerView').withAncestor(by.id(testID)),
|
||||
);
|
||||
const indicator = await element(by.id(indicatorID));
|
||||
|
||||
await expect(testElement).toBeVisible();
|
||||
await expect(indicator).toBeVisible();
|
||||
|
||||
await testElement.setColumnToValue(0, 'November');
|
||||
await testElement.setColumnToValue(1, '3');
|
||||
await testElement.setColumnToValue(2, '2006');
|
||||
|
||||
await expect(indicator).toHaveText('11/3/2006 4:10 AM');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @format
|
||||
*/
|
||||
|
||||
/* global element, by, expect */
|
||||
|
||||
describe('Picker', () => {
|
||||
beforeAll(async () => {
|
||||
await element(by.id('explorer_search')).replaceText('<Picker>');
|
||||
await element(
|
||||
by.label(
|
||||
'<Picker> Provides multiple options to choose from, using either a dropdown menu or a dialog.',
|
||||
),
|
||||
).tap();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await element(by.label('Back')).tap();
|
||||
});
|
||||
|
||||
it('should be selectable by ID', async () => {
|
||||
await expect(element(by.id('basic-picker'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @format
|
||||
*/
|
||||
|
||||
/* global device, element, by, expect */
|
||||
|
||||
const jestExpect = require('expect');
|
||||
|
||||
describe('Switch', () => {
|
||||
beforeEach(async () => {
|
||||
await device.reloadReactNative();
|
||||
await element(by.id('explorer_search')).replaceText('<Switch>');
|
||||
await element(by.label('<Switch> Native boolean input')).tap();
|
||||
});
|
||||
|
||||
it('Switch that starts off should switch', async () => {
|
||||
const testID = 'on-off-initial-off';
|
||||
const indicatorID = 'on-off-initial-off-indicator';
|
||||
|
||||
await expect(element(by.id(testID))).toHaveValue('0');
|
||||
await expect(element(by.id(indicatorID))).toHaveText('Off');
|
||||
await element(by.id(testID)).tap();
|
||||
await expect(element(by.id(testID))).toHaveValue('1');
|
||||
await expect(element(by.id(indicatorID))).toHaveText('On');
|
||||
});
|
||||
|
||||
it('Switch that starts on should switch', async () => {
|
||||
const testID = 'on-off-initial-on';
|
||||
const indicatorID = 'on-off-initial-on-indicator';
|
||||
|
||||
await expect(element(by.id(testID))).toHaveValue('1');
|
||||
await expect(element(by.id(indicatorID))).toHaveText('On');
|
||||
await element(by.id(testID)).tap();
|
||||
await expect(element(by.id(testID))).toHaveValue('0');
|
||||
await expect(element(by.id(indicatorID))).toHaveText('Off');
|
||||
});
|
||||
|
||||
it('disabled switch should not toggle', async () => {
|
||||
const onTestID = 'disabled-initial-on';
|
||||
const offTestID = 'disabled-initial-off';
|
||||
const onIndicatorID = 'disabled-initial-on-indicator';
|
||||
const offIndicatorID = 'disabled-initial-off-indicator';
|
||||
|
||||
await expect(element(by.id(onTestID))).toHaveValue('1');
|
||||
await expect(element(by.id(onIndicatorID))).toHaveText('On');
|
||||
|
||||
try {
|
||||
await element(by.id(onTestID)).tap();
|
||||
throw new Error('Does not match');
|
||||
} catch (err) {
|
||||
jestExpect(err.message.message).toEqual(
|
||||
jestExpect.stringContaining(
|
||||
'Cannot perform action due to constraint(s) failure',
|
||||
),
|
||||
);
|
||||
}
|
||||
await expect(element(by.id(onTestID))).toHaveValue('1');
|
||||
await expect(element(by.id(onIndicatorID))).toHaveText('On');
|
||||
|
||||
await expect(element(by.id(offTestID))).toHaveValue('0');
|
||||
await expect(element(by.id(offIndicatorID))).toHaveText('Off');
|
||||
try {
|
||||
await element(by.id(offTestID)).tap();
|
||||
throw new Error('Does not match');
|
||||
} catch (err) {
|
||||
jestExpect(err.message.message).toEqual(
|
||||
jestExpect.stringContaining(
|
||||
'Cannot perform action due to constraint(s) failure',
|
||||
),
|
||||
);
|
||||
}
|
||||
await expect(element(by.id(offTestID))).toHaveValue('0');
|
||||
await expect(element(by.id(offIndicatorID))).toHaveText('Off');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @emails oncall+react_native
|
||||
* @format
|
||||
*/
|
||||
|
||||
/* global element, by, expect */
|
||||
|
||||
describe('Touchable', () => {
|
||||
beforeAll(async () => {
|
||||
await element(by.id('explorer_search')).replaceText('<Touchable*');
|
||||
await element(
|
||||
by.label('<Touchable*> and onPress Touchable and onPress examples.'),
|
||||
).tap();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
//TODO - remove app state persistency, till then, we must go back to main screen,
|
||||
await element(by.label('Back')).tap();
|
||||
});
|
||||
|
||||
it('Touchable Highlight should be tappable', async () => {
|
||||
const buttonID = 'touchable_highlight_image_button';
|
||||
const button2ID = 'touchable_highlight_text_button';
|
||||
const consoleID = 'touchable_highlight_console';
|
||||
|
||||
await element(by.id(buttonID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText(
|
||||
'TouchableHighlight onPress',
|
||||
);
|
||||
|
||||
await element(by.id(buttonID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText(
|
||||
'2x TouchableHighlight onPress',
|
||||
);
|
||||
|
||||
await element(by.id(button2ID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText(
|
||||
'3x TouchableHighlight onPress',
|
||||
);
|
||||
});
|
||||
|
||||
it('Touchable Without Feedback should be tappable', async () => {
|
||||
const buttonID = 'touchable_without_feedback_button';
|
||||
const consoleID = 'touchable_without_feedback_console';
|
||||
|
||||
await element(by.id(buttonID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText(
|
||||
'TouchableWithoutFeedback onPress',
|
||||
);
|
||||
|
||||
await element(by.id(buttonID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText(
|
||||
'2x TouchableWithoutFeedback onPress',
|
||||
);
|
||||
});
|
||||
|
||||
it('Text should be tappable', async () => {
|
||||
const buttonID = 'tappable_text';
|
||||
const consoleID = 'tappable_text_console';
|
||||
|
||||
await element(by.id(buttonID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText('text onPress');
|
||||
|
||||
await element(by.id(buttonID)).tap();
|
||||
await expect(element(by.id(consoleID))).toHaveText('2x text onPress');
|
||||
});
|
||||
});
|
||||
@@ -12,22 +12,18 @@
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {AccessibilityInfo, Text, View, TouchableOpacity, Alert} = ReactNative;
|
||||
const {AccessibilityInfo, Text, View, TouchableOpacity} = ReactNative;
|
||||
|
||||
class AccessibilityIOSExample extends React.Component<{}> {
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<View
|
||||
onAccessibilityTap={() =>
|
||||
Alert.alert('Alert', 'onAccessibilityTap success')
|
||||
}
|
||||
onAccessibilityTap={() => alert('onAccessibilityTap success')}
|
||||
accessible={true}>
|
||||
<Text>Accessibility normal tap example</Text>
|
||||
</View>
|
||||
<View
|
||||
onMagicTap={() => Alert.alert('Alert', 'onMagicTap success')}
|
||||
accessible={true}>
|
||||
<View onMagicTap={() => alert('onMagicTap success')} accessible={true}>
|
||||
<Text>Accessibility magic tap example</Text>
|
||||
</View>
|
||||
<View accessibilityLabel="Some announcement" accessible={true}>
|
||||
|
||||
@@ -12,14 +12,7 @@
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {
|
||||
ActionSheetIOS,
|
||||
StyleSheet,
|
||||
takeSnapshot,
|
||||
Text,
|
||||
View,
|
||||
Alert,
|
||||
} = ReactNative;
|
||||
const {ActionSheetIOS, StyleSheet, takeSnapshot, Text, View} = ReactNative;
|
||||
|
||||
const BUTTONS = ['Option 0', 'Option 1', 'Option 2', 'Delete', 'Cancel'];
|
||||
const DESTRUCTIVE_INDEX = 3;
|
||||
@@ -113,7 +106,7 @@ class ShareActionSheetExample extends React.Component<
|
||||
subject: 'a subject to go in the email heading',
|
||||
excludedActivityTypes: ['com.apple.UIKit.activity.PostToTwitter'],
|
||||
},
|
||||
error => Alert.alert('Error', error),
|
||||
error => alert(error),
|
||||
(completed, method) => {
|
||||
let text;
|
||||
if (completed) {
|
||||
@@ -153,7 +146,7 @@ class ShareScreenshotExample extends React.Component<{}, $FlowFixMeState> {
|
||||
url: uri,
|
||||
excludedActivityTypes: ['com.apple.UIKit.activity.PostToTwitter'],
|
||||
},
|
||||
error => Alert.alert('Error', error),
|
||||
error => alert(error),
|
||||
(completed, method) => {
|
||||
let text;
|
||||
if (completed) {
|
||||
@@ -165,7 +158,7 @@ class ShareScreenshotExample extends React.Component<{}, $FlowFixMeState> {
|
||||
},
|
||||
);
|
||||
})
|
||||
.catch(error => Alert.alert('Error', error));
|
||||
.catch(error => alert(error));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,13 @@ class DatePickerExample extends React.Component<
|
||||
return (
|
||||
<View>
|
||||
<WithLabel label="Value:">
|
||||
<Text>
|
||||
<Text testID="date-and-time-indicator">
|
||||
{this.state.date.toLocaleDateString() +
|
||||
' ' +
|
||||
this.state.date.toLocaleTimeString()}
|
||||
this.state.date.toLocaleTimeString([], {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
</Text>
|
||||
</WithLabel>
|
||||
<WithLabel label="Timezone:">
|
||||
@@ -62,6 +65,7 @@ class DatePickerExample extends React.Component<
|
||||
</WithLabel>
|
||||
<Heading label="Date + time picker" />
|
||||
<DatePickerIOS
|
||||
testID="date-and-time"
|
||||
date={this.state.date}
|
||||
mode="datetime"
|
||||
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
|
||||
@@ -69,6 +73,7 @@ class DatePickerExample extends React.Component<
|
||||
/>
|
||||
<Heading label="Date picker" />
|
||||
<DatePickerIOS
|
||||
testID="date-only"
|
||||
date={this.state.date}
|
||||
mode="date"
|
||||
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
|
||||
@@ -76,6 +81,7 @@ class DatePickerExample extends React.Component<
|
||||
/>
|
||||
<Heading label="Time picker, 10-minute interval" />
|
||||
<DatePickerIOS
|
||||
testID="time-only"
|
||||
date={this.state.date}
|
||||
mode="time"
|
||||
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {StyleSheet, Text, View, Alert} = ReactNative;
|
||||
const {StyleSheet, Text, View} = ReactNative;
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'Geolocation';
|
||||
@@ -41,7 +41,7 @@ class GeolocationExample extends React.Component<{}, $FlowFixMeState> {
|
||||
const initialPosition = JSON.stringify(position);
|
||||
this.setState({initialPosition});
|
||||
},
|
||||
error => Alert.alert('Error', JSON.stringify(error)),
|
||||
error => alert(JSON.stringify(error)),
|
||||
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000},
|
||||
);
|
||||
this.watchID = navigator.geolocation.watchPosition(position => {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {FlatList, StyleSheet, Text, View, Alert} = ReactNative;
|
||||
const {FlatList, StyleSheet, Text, View} = ReactNative;
|
||||
|
||||
const RNTesterPage = require('./RNTesterPage');
|
||||
|
||||
@@ -91,9 +91,7 @@ class MultiColumnExample extends React.PureComponent<
|
||||
data={filteredData}
|
||||
key={this.state.numColumns + (this.state.fixedHeight ? 'f' : 'v')}
|
||||
numColumns={this.state.numColumns || 1}
|
||||
onRefresh={() =>
|
||||
Alert.alert('Alert', 'onRefresh: nothing to refresh :P')
|
||||
}
|
||||
onRefresh={() => alert('onRefresh: nothing to refresh :P')}
|
||||
refreshing={false}
|
||||
renderItem={this._renderItemComponent}
|
||||
disableVirtualization={!this.state.virtualized}
|
||||
|
||||
@@ -38,6 +38,7 @@ class PickerExample extends React.Component<{}, $FlowFixMeState> {
|
||||
<RNTesterPage title="<Picker>">
|
||||
<RNTesterBlock title="Basic Picker">
|
||||
<Picker
|
||||
testID="basic-picker"
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selected1}
|
||||
onValueChange={this.onValueChange.bind(this, 'selected1')}>
|
||||
|
||||
@@ -70,17 +70,8 @@ class RNTesterApp extends React.Component<Props, RNTesterNavigationState> {
|
||||
);
|
||||
const urlAction = URIActionMap(url);
|
||||
const launchAction = exampleAction || urlAction;
|
||||
if (err || !storedString) {
|
||||
const initialAction = launchAction || {type: 'InitialAction'};
|
||||
this.setState(RNTesterNavigationReducer(undefined, initialAction));
|
||||
return;
|
||||
}
|
||||
const storedState = JSON.parse(storedString);
|
||||
if (launchAction) {
|
||||
this.setState(RNTesterNavigationReducer(storedState, launchAction));
|
||||
return;
|
||||
}
|
||||
this.setState(storedState);
|
||||
const initialAction = launchAction || {type: 'InitialAction'};
|
||||
this.setState(RNTesterNavigationReducer(undefined, initialAction));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -179,7 +170,10 @@ RNTesterList.ComponentExamples.concat(RNTesterList.APIExamples).forEach(
|
||||
render() {
|
||||
return (
|
||||
<SnapshotViewIOS>
|
||||
<RNTesterExampleContainer module={ExampleModule} />
|
||||
<RNTesterExampleContainer
|
||||
module={ExampleModule}
|
||||
displayFilter={false}
|
||||
/>
|
||||
</SnapshotViewIOS>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
const React = require('react');
|
||||
const {Platform} = require('react-native');
|
||||
const RNTesterBlock = require('./RNTesterBlock');
|
||||
const RNTesterExampleFilter = require('./RNTesterExampleFilter');
|
||||
const RNTesterPage = require('./RNTesterPage');
|
||||
|
||||
class RNTesterExampleContainer extends React.Component {
|
||||
@@ -37,9 +38,36 @@ class RNTesterExampleContainer extends React.Component {
|
||||
return <this.props.module />;
|
||||
}
|
||||
|
||||
if (
|
||||
this.props.displayFilter === false ||
|
||||
this.props.module.examples.length === 1
|
||||
) {
|
||||
return (
|
||||
<RNTesterPage title={this.props.title}>
|
||||
{this.props.module.examples.map(this.renderExample)}
|
||||
</RNTesterPage>
|
||||
);
|
||||
}
|
||||
|
||||
const filter = ({example, filterRegex}) => filterRegex.test(example.title);
|
||||
|
||||
const sections = [
|
||||
{
|
||||
data: this.props.module.examples,
|
||||
title: 'EXAMPLES',
|
||||
key: 'e',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<RNTesterPage title={this.props.title}>
|
||||
{this.props.module.examples.map(this.renderExample)}
|
||||
<RNTesterExampleFilter
|
||||
sections={sections}
|
||||
filter={filter}
|
||||
render={({filteredSections}) =>
|
||||
filteredSections[0].data.map(this.renderExample)
|
||||
}
|
||||
/>
|
||||
</RNTesterPage>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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 React = require('react');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const TextInput = require('TextInput');
|
||||
const View = require('View');
|
||||
|
||||
type Props = {
|
||||
filter: Function,
|
||||
render: Function,
|
||||
/*
|
||||
* $FlowFixMe: We shoudl better type this (ideally so that render and filter are
|
||||
* aware of what they receive)
|
||||
*/
|
||||
sections: Object,
|
||||
disableSearch?: boolean,
|
||||
};
|
||||
|
||||
type State = {
|
||||
filter: string,
|
||||
};
|
||||
|
||||
class RNTesterExampleFilter extends React.Component<Props, State> {
|
||||
state = {filter: ''};
|
||||
|
||||
render() {
|
||||
const filterText = this.state.filter;
|
||||
let filterRegex = /.*/;
|
||||
|
||||
try {
|
||||
filterRegex = new RegExp(String(filterText), 'i');
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Failed to create RegExp: %s\n%s',
|
||||
filterText,
|
||||
error.message,
|
||||
);
|
||||
}
|
||||
|
||||
const filter = example =>
|
||||
this.props.disableSearch || this.props.filter({example, filterRegex});
|
||||
|
||||
const filteredSections = this.props.sections.map(section => ({
|
||||
...section,
|
||||
data: section.data.filter(filter),
|
||||
}));
|
||||
|
||||
return (
|
||||
<View>
|
||||
{this._renderTextInput()}
|
||||
{this.props.render({filteredSections})}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderTextInput(): ?React.Element<any> {
|
||||
if (this.props.disableSearch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View style={styles.searchRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
clearButtonMode="always"
|
||||
onChangeText={text => {
|
||||
this.setState(() => ({filter: text}));
|
||||
}}
|
||||
placeholder="Search..."
|
||||
underlineColorAndroid="transparent"
|
||||
style={styles.searchTextInput}
|
||||
testID="explorer_search"
|
||||
value={this.state.filter}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
searchRow: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 10,
|
||||
},
|
||||
searchTextInput: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
paddingLeft: 8,
|
||||
paddingVertical: 0,
|
||||
height: 35,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = RNTesterExampleFilter;
|
||||
@@ -15,17 +15,15 @@ const React = require('react');
|
||||
const SectionList = require('SectionList');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const Text = require('Text');
|
||||
const TextInput = require('TextInput');
|
||||
const TouchableHighlight = require('TouchableHighlight');
|
||||
const RNTesterActions = require('./RNTesterActions');
|
||||
const RNTesterStatePersister = require('./RNTesterStatePersister');
|
||||
const RNTesterExampleFilter = require('./RNTesterExampleFilter');
|
||||
const View = require('View');
|
||||
|
||||
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found when
|
||||
* making Flow check .android.js files. */
|
||||
import type {RNTesterExample} from './RNTesterList.ios';
|
||||
import type {PassProps} from './RNTesterStatePersister';
|
||||
import type {TextStyleProp, ViewStyleProp} from 'StyleSheet';
|
||||
import type {ViewStyleProp} from 'StyleSheet';
|
||||
|
||||
type Props = {
|
||||
onNavigate: Function,
|
||||
@@ -33,8 +31,6 @@ type Props = {
|
||||
ComponentExamples: Array<RNTesterExample>,
|
||||
APIExamples: Array<RNTesterExample>,
|
||||
},
|
||||
persister: PassProps<*>,
|
||||
searchTextInputStyle: TextStyleProp,
|
||||
style?: ?ViewStyleProp,
|
||||
};
|
||||
|
||||
@@ -74,55 +70,47 @@ const renderSectionHeader = ({section}) => (
|
||||
|
||||
class RNTesterExampleList extends React.Component<Props, $FlowFixMeState> {
|
||||
render() {
|
||||
const filterText = this.props.persister.state.filter;
|
||||
let filterRegex = /.*/;
|
||||
|
||||
try {
|
||||
filterRegex = new RegExp(String(filterText), 'i');
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Failed to create RegExp: %s\n%s',
|
||||
filterText,
|
||||
error.message,
|
||||
);
|
||||
}
|
||||
|
||||
const filter = example =>
|
||||
const filter = ({example, filterRegex}) =>
|
||||
/* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.68 was deployed. To see the error delete this
|
||||
* comment and run Flow. */
|
||||
this.props.disableSearch ||
|
||||
(filterRegex.test(example.module.title) &&
|
||||
(!Platform.isTV || example.supportsTVOS));
|
||||
* error found when Flow v0.68 was deployed. To see the error delete this
|
||||
* comment and run Flow. */
|
||||
filterRegex.test(example.module.title) &&
|
||||
(!Platform.isTV || example.supportsTVOS);
|
||||
|
||||
const sections = [
|
||||
{
|
||||
data: this.props.list.ComponentExamples.filter(filter),
|
||||
data: this.props.list.ComponentExamples,
|
||||
title: 'COMPONENTS',
|
||||
key: 'c',
|
||||
},
|
||||
{
|
||||
data: this.props.list.APIExamples.filter(filter),
|
||||
data: this.props.list.APIExamples,
|
||||
title: 'APIS',
|
||||
key: 'a',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<View style={[styles.listContainer, this.props.style]}>
|
||||
{this._renderTitleRow()}
|
||||
{this._renderTextInput()}
|
||||
<SectionList
|
||||
ItemSeparatorComponent={ItemSeparator}
|
||||
contentContainerStyle={{backgroundColor: 'white'}}
|
||||
style={styles.list}
|
||||
<RNTesterExampleFilter
|
||||
sections={sections}
|
||||
renderItem={this._renderItem}
|
||||
enableEmptySections={true}
|
||||
itemShouldUpdate={this._itemShouldUpdate}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
automaticallyAdjustContentInsets={false}
|
||||
keyboardDismissMode="on-drag"
|
||||
renderSectionHeader={renderSectionHeader}
|
||||
filter={filter}
|
||||
render={({filteredSections}) => (
|
||||
<SectionList
|
||||
ItemSeparatorComponent={ItemSeparator}
|
||||
contentContainerStyle={styles.sectionListContentContainer}
|
||||
style={styles.list}
|
||||
sections={filteredSections}
|
||||
renderItem={this._renderItem}
|
||||
enableEmptySections={true}
|
||||
itemShouldUpdate={this._itemShouldUpdate}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
automaticallyAdjustContentInsets={false}
|
||||
keyboardDismissMode="on-drag"
|
||||
renderSectionHeader={renderSectionHeader}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
@@ -164,32 +152,6 @@ class RNTesterExampleList extends React.Component<Props, $FlowFixMeState> {
|
||||
);
|
||||
}
|
||||
|
||||
_renderTextInput(): ?React.Element<any> {
|
||||
/* $FlowFixMe(>=0.68.0 site=react_native_fb) This comment suppresses an
|
||||
* error found when Flow v0.68 was deployed. To see the error delete this
|
||||
* comment and run Flow. */
|
||||
if (this.props.disableSearch) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View style={styles.searchRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
clearButtonMode="always"
|
||||
onChangeText={text => {
|
||||
this.props.persister.setState(() => ({filter: text}));
|
||||
}}
|
||||
placeholder="Search..."
|
||||
underlineColorAndroid="transparent"
|
||||
style={[styles.searchTextInput, this.props.searchTextInputStyle]}
|
||||
testID="explorer_search"
|
||||
value={this.props.persister.state.filter}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_handleRowPress(exampleKey: string): void {
|
||||
this.props.onNavigate(RNTesterActions.ExampleAction(exampleKey));
|
||||
}
|
||||
@@ -199,17 +161,6 @@ const ItemSeparator = ({highlighted}) => (
|
||||
<View style={highlighted ? styles.separatorHighlighted : styles.separator} />
|
||||
);
|
||||
|
||||
/* $FlowFixMe(>=0.85.0 site=react_native_fb) This comment suppresses an error
|
||||
* found when Flow v0.85 was deployed. To see the error, delete this comment
|
||||
* and run Flow. */
|
||||
RNTesterExampleList = RNTesterStatePersister.createContainer(
|
||||
RNTesterExampleList,
|
||||
{
|
||||
cacheKeySuffix: () => 'mainList',
|
||||
getInitialState: () => ({filter: ''}),
|
||||
},
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
listContainer: {
|
||||
flex: 1,
|
||||
@@ -238,6 +189,9 @@ const styles = StyleSheet.create({
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: 'rgb(217, 217, 217)',
|
||||
},
|
||||
sectionListContentContainer: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
rowTitleText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '500',
|
||||
@@ -247,19 +201,6 @@ const styles = StyleSheet.create({
|
||||
color: '#888888',
|
||||
lineHeight: 20,
|
||||
},
|
||||
searchRow: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 10,
|
||||
},
|
||||
searchTextInput: {
|
||||
backgroundColor: 'white',
|
||||
borderColor: '#cccccc',
|
||||
borderRadius: 3,
|
||||
borderWidth: 1,
|
||||
paddingLeft: 8,
|
||||
paddingVertical: 0,
|
||||
height: 35,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = RNTesterExampleList;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const ActivityIndicator = require('ActivityIndicator');
|
||||
const Platform = require('Platform');
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
@@ -155,7 +154,6 @@ if (Platform.OS === 'ios') {
|
||||
autoscrollToTopThreshold: 10,
|
||||
}}
|
||||
style={styles.scrollView}>
|
||||
<ActivityIndicator style={{height: 40}} />
|
||||
{this.state.items.map(item =>
|
||||
React.cloneElement(item, {key: item.props.msg}),
|
||||
)}
|
||||
@@ -168,7 +166,6 @@ if (Platform.OS === 'ios') {
|
||||
autoscrollToTopThreshold: 10,
|
||||
}}
|
||||
style={[styles.scrollView, styles.horizontalScrollView]}>
|
||||
<ActivityIndicator style={{width: 40}} />
|
||||
{this.state.items.map(item =>
|
||||
React.cloneElement(item, {key: item.props.msg, style: null}),
|
||||
)}
|
||||
|
||||
@@ -11,10 +11,37 @@
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {Switch, Text, View} = ReactNative;
|
||||
const {Switch, Text, View} = require('react-native');
|
||||
|
||||
class BasicSwitchExample extends React.Component<{}, $FlowFixMeState> {
|
||||
type OnOffIndicatorProps = $ReadOnly<{|on: boolean, testID: string|}>;
|
||||
function OnOffIndicator({on, testID}: OnOffIndicatorProps) {
|
||||
return <Text testID={testID}>{on ? 'On' : 'Off'}</Text>;
|
||||
}
|
||||
|
||||
type ExampleRowProps = $ReadOnly<{|children: React.Node|}>;
|
||||
function ExampleRow({children}: ExampleRowProps) {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 10,
|
||||
}}>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
type SimpleSwitchExampleState = $ReadOnly<{|
|
||||
trueSwitchIsOn: boolean,
|
||||
falseSwitchIsOn: boolean,
|
||||
|}>;
|
||||
|
||||
class BasicSwitchExample extends React.Component<
|
||||
{||},
|
||||
SimpleSwitchExampleState,
|
||||
> {
|
||||
state = {
|
||||
trueSwitchIsOn: true,
|
||||
falseSwitchIsOn: false,
|
||||
@@ -23,26 +50,72 @@ class BasicSwitchExample extends React.Component<{}, $FlowFixMeState> {
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Switch
|
||||
onValueChange={value => this.setState({falseSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.falseSwitchIsOn}
|
||||
/>
|
||||
<Switch
|
||||
onValueChange={value => this.setState({trueSwitchIsOn: value})}
|
||||
value={this.state.trueSwitchIsOn}
|
||||
/>
|
||||
<ExampleRow>
|
||||
<Switch
|
||||
testID="on-off-initial-off"
|
||||
onValueChange={value => this.setState({falseSwitchIsOn: value})}
|
||||
value={this.state.falseSwitchIsOn}
|
||||
/>
|
||||
<OnOffIndicator
|
||||
on={this.state.falseSwitchIsOn}
|
||||
testID="on-off-initial-off-indicator"
|
||||
/>
|
||||
</ExampleRow>
|
||||
<ExampleRow>
|
||||
<Switch
|
||||
testID="on-off-initial-on"
|
||||
onValueChange={value => this.setState({trueSwitchIsOn: value})}
|
||||
value={this.state.trueSwitchIsOn}
|
||||
/>
|
||||
<OnOffIndicator
|
||||
on={this.state.trueSwitchIsOn}
|
||||
testID="on-off-initial-on-indicator"
|
||||
/>
|
||||
</ExampleRow>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DisabledSwitchExample extends React.Component<{}> {
|
||||
class DisabledSwitchExample extends React.Component<
|
||||
{||},
|
||||
SimpleSwitchExampleState,
|
||||
> {
|
||||
state = {
|
||||
trueSwitchIsOn: true,
|
||||
falseSwitchIsOn: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Switch disabled={true} style={{marginBottom: 10}} value={true} />
|
||||
<Switch disabled={true} value={false} />
|
||||
<ExampleRow>
|
||||
<Switch
|
||||
testID="disabled-initial-off"
|
||||
disabled={true}
|
||||
onValueChange={value => this.setState({falseSwitchIsOn: value})}
|
||||
value={this.state.falseSwitchIsOn}
|
||||
/>
|
||||
|
||||
<OnOffIndicator
|
||||
on={this.state.falseSwitchIsOn}
|
||||
testID="disabled-initial-off-indicator"
|
||||
/>
|
||||
</ExampleRow>
|
||||
|
||||
<ExampleRow>
|
||||
<Switch
|
||||
testID="disabled-initial-on"
|
||||
disabled={true}
|
||||
onValueChange={value => this.setState({trueSwitchIsOn: value})}
|
||||
value={this.state.trueSwitchIsOn}
|
||||
/>
|
||||
|
||||
<OnOffIndicator
|
||||
on={this.state.trueSwitchIsOn}
|
||||
testID="disabled-initial-on-indicator"
|
||||
/>
|
||||
</ExampleRow>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,8 +48,7 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> {
|
||||
}
|
||||
onContentSizeChange={event =>
|
||||
this.updateText(
|
||||
'onContentSizeChange size: ' +
|
||||
JSON.stringify(event.nativeEvent.contentSize),
|
||||
'onContentSizeChange size: ' + event.nativeEvent.contentSize,
|
||||
)
|
||||
}
|
||||
onEndEditing={event =>
|
||||
@@ -254,10 +253,10 @@ class ToggleDefaultPaddingExample extends React.Component<
|
||||
}
|
||||
|
||||
type SelectionExampleState = {
|
||||
selection: $ReadOnly<{|
|
||||
selection: {
|
||||
start: number,
|
||||
end?: number,
|
||||
|}>,
|
||||
end: number,
|
||||
},
|
||||
value: string,
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const Button = require('Button');
|
||||
const InputAccessoryView = require('InputAccessoryView');
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {Text, TextInput, View, StyleSheet, Slider, Switch, Alert} = ReactNative;
|
||||
const {Text, TextInput, View, StyleSheet, Slider, Switch} = ReactNative;
|
||||
|
||||
class WithLabel extends React.Component<$FlowFixMeProps> {
|
||||
render() {
|
||||
@@ -71,7 +71,7 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> {
|
||||
'onSelectionChange range: ' +
|
||||
event.nativeEvent.selection.start +
|
||||
',' +
|
||||
(event.nativeEvent.selection.end || ''),
|
||||
event.nativeEvent.selection.end,
|
||||
)
|
||||
}
|
||||
onKeyPress={event => {
|
||||
@@ -348,10 +348,10 @@ class BlurOnSubmitExample extends React.Component<{}> {
|
||||
}
|
||||
|
||||
type SelectionExampleState = {
|
||||
selection: $ReadOnly<{|
|
||||
selection: {|
|
||||
start: number,
|
||||
end?: number,
|
||||
|}>,
|
||||
|},
|
||||
value: string,
|
||||
};
|
||||
|
||||
@@ -862,9 +862,7 @@ exports.examples = [
|
||||
returnKeyType="next"
|
||||
blurOnSubmit={true}
|
||||
multiline={true}
|
||||
onSubmitEditing={event =>
|
||||
Alert.alert('Alert', event.nativeEvent.text)
|
||||
}
|
||||
onSubmitEditing={event => alert(event.nativeEvent.text)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -45,30 +45,7 @@ exports.examples = [
|
||||
'background color change as well with the activeOpacity and ' +
|
||||
'underlayColor props.',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.row}>
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={() => console.log('stock THW image - highlight')}>
|
||||
<Image source={heartImage} style={styles.image} />
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
activeOpacity={1}
|
||||
tvParallaxProperties={{
|
||||
pressMagnification: 1.3,
|
||||
pressDuration: 0.6,
|
||||
}}
|
||||
underlayColor="rgb(210, 230, 255)"
|
||||
onPress={() => console.log('custom THW text - highlight')}>
|
||||
<View style={styles.wrapperCustom}>
|
||||
<Text style={styles.text}>Tap Here For Custom Highlight!</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
return <TouchableHighlightBox />;
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -157,6 +134,57 @@ exports.examples = [
|
||||
},
|
||||
];
|
||||
|
||||
class TouchableHighlightBox extends React.Component<{}, $FlowFixMeState> {
|
||||
state = {
|
||||
timesPressed: 0,
|
||||
};
|
||||
|
||||
touchableOnPress = () => {
|
||||
this.setState({
|
||||
timesPressed: this.state.timesPressed + 1,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
let textLog = '';
|
||||
if (this.state.timesPressed > 1) {
|
||||
textLog = this.state.timesPressed + 'x TouchableHighlight onPress';
|
||||
} else if (this.state.timesPressed > 0) {
|
||||
textLog = 'TouchableHighlight onPress';
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.row}>
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
testID="touchable_highlight_image_button"
|
||||
onPress={this.touchableOnPress}>
|
||||
<Image source={heartImage} style={styles.image} />
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
testID="touchable_highlight_text_button"
|
||||
activeOpacity={1}
|
||||
tvParallaxProperties={{
|
||||
pressMagnification: 1.3,
|
||||
pressDuration: 0.6,
|
||||
}}
|
||||
underlayColor="rgb(210, 230, 255)"
|
||||
onPress={this.touchableOnPress}>
|
||||
<View style={styles.wrapperCustom}>
|
||||
<Text style={styles.text}>Tap Here For Custom Highlight!</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
<View style={styles.logBox}>
|
||||
<Text testID="touchable_highlight_console">{textLog}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TouchableWithoutFeedbackBox extends React.Component<{}, $FlowFixMeState> {
|
||||
state = {
|
||||
timesPressed: 0,
|
||||
@@ -178,13 +206,15 @@ class TouchableWithoutFeedbackBox extends React.Component<{}, $FlowFixMeState> {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<TouchableWithoutFeedback onPress={this.textOnPress}>
|
||||
<TouchableWithoutFeedback
|
||||
onPress={this.textOnPress}
|
||||
testID="touchable_without_feedback_button">
|
||||
<View style={styles.wrapperCustom}>
|
||||
<Text style={styles.text}>Tap Here For No Feedback!</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
<View style={styles.logBox}>
|
||||
<Text>{textLog}</Text>
|
||||
<Text testID="touchable_without_feedback_console">{textLog}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -212,11 +242,14 @@ class TextOnPressBox extends React.Component<{}, $FlowFixMeState> {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text style={styles.textBlock} onPress={this.textOnPress}>
|
||||
<Text
|
||||
style={styles.textBlock}
|
||||
testID="tappable_text"
|
||||
onPress={this.textOnPress}>
|
||||
Text has built-in onPress handling
|
||||
</Text>
|
||||
<View style={styles.logBox}>
|
||||
<Text>{textLog}</Text>
|
||||
<Text testID="tappable_text_console">{textLog}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {Text, View, TouchableOpacity, Alert} = ReactNative;
|
||||
const {Text, View, TouchableOpacity} = ReactNative;
|
||||
|
||||
class TransparentHitTestExample extends React.Component<{}> {
|
||||
render() {
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<TouchableOpacity onPress={() => Alert.alert('Alert', 'Hi!')}>
|
||||
<TouchableOpacity onPress={() => alert('Hi!')}>
|
||||
<Text>HELLO!</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class XHRExampleFetch extends React.Component<any, any> {
|
||||
this.responseHeaders = null;
|
||||
}
|
||||
|
||||
submit(uri: string) {
|
||||
submit(uri: String) {
|
||||
fetch(uri)
|
||||
.then(response => {
|
||||
this.responseURL = response.url;
|
||||
|
||||
@@ -35,7 +35,7 @@ server.on('connection', ws => {
|
||||
console.log('Received message:', message);
|
||||
console.log('Cookie:', ws.upgradeReq.headers.cookie);
|
||||
if (respondWithBinary) {
|
||||
message = Buffer.from(message);
|
||||
message = new Buffer(message);
|
||||
}
|
||||
if (message === 'getImage') {
|
||||
message = fs.readFileSync(path.resolve(__dirname, 'flux@3x.png'));
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
---
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: true
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: WebKit
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ]
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*\.h(pp)?>'
|
||||
Priority: 1
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
@@ -12,6 +12,7 @@ NSString *const RCTErrorDomain = @"RCTErrorDomain";
|
||||
NSString *const RCTJSStackTraceKey = @"RCTJSStackTraceKey";
|
||||
NSString *const RCTJSRawStackTraceKey = @"RCTJSRawStackTraceKey";
|
||||
NSString *const RCTFatalExceptionName = @"RCTFatalException";
|
||||
NSString *const RCTUntruncatedMessageKey = @"RCTUntruncatedMessageKey";
|
||||
|
||||
static NSString *const RCTAssertFunctionStack = @"RCTAssertFunctionStack";
|
||||
|
||||
@@ -128,8 +129,20 @@ void RCTFatal(NSError *error)
|
||||
@try {
|
||||
#endif
|
||||
NSString *name = [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, error.localizedDescription];
|
||||
NSString *message = RCTFormatError(error.localizedDescription, error.userInfo[RCTJSStackTraceKey], 75);
|
||||
@throw [[NSException alloc] initWithName:name reason:message userInfo:nil];
|
||||
|
||||
// Truncate the localized description to 175 characters to avoid wild screen overflows
|
||||
NSString *message = RCTFormatError(error.localizedDescription, error.userInfo[RCTJSStackTraceKey], 175);
|
||||
|
||||
// Attach an untruncated copy of the description to the userInfo, in case it is needed
|
||||
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
|
||||
[userInfo setObject:RCTFormatError(error.localizedDescription, error.userInfo[RCTJSStackTraceKey], -1)
|
||||
forKey:RCTUntruncatedMessageKey];
|
||||
|
||||
// Expected resulting exception information:
|
||||
// name: RCTFatalException: <underlying error description>
|
||||
// reason: <underlying error description plus JS stack trace, truncated to 175 characters>
|
||||
// userInfo: <underlying error userinfo, plus untruncated description plus JS stack trace>
|
||||
@throw [[NSException alloc] initWithName:name reason:message userInfo:userInfo];
|
||||
#if DEBUG
|
||||
} @catch (NSException *e) {}
|
||||
#endif
|
||||
|
||||