diff --git a/.circleci/config.yml b/.circleci/config.yml index 1b28b421da2391..682a6732414fe8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -585,31 +585,44 @@ jobs: - checkout - run: *setup-artifacts - - restore-cache: *restore-yarn-cache + - restore-cache: *restore-cache-analysis - run: *yarn + - run: + name: Analyze Shell Scripts + command: | + echo -e "\\x1B[36mInstalling additional dependencies\\x1B[0m" + sudo apt-get install -y shellcheck + yarn add @octokit/rest@15.10.0 + echo -e "\\x1B[36mAnalyzing shell scripts\\x1B[0m"; \ + GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" \ + GITHUB_OWNER="$CIRCLE_PROJECT_USERNAME" \ + GITHUB_REPO="$CIRCLE_PROJECT_REPONAME" \ + GITHUB_PR_NUMBER="$CIRCLE_PR_NUMBER" \ + ./scripts/circleci/analyze_scripts.sh + when: always + - run: name: Analyze Code command: | - if [ -n "$CIRCLE_PR_NUMBER" ]; then - echo -e "\\x1B[36mInstalling additional dependencies\\x1B[0m"; yarn add @octokit/rest@15.10.0 - echo -e "\\x1B[36mAnalyzing code\\x1B[0m"; GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" ./scripts/circleci/analyze_code.sh - else - echo "Skipping code analysis." - fi + echo -e "\\x1B[36mInstalling additional dependencies\\x1B[0m"; yarn add @octokit/rest@15.10.0 + echo -e "\\x1B[36mAnalyzing code\\x1B[0m"; \ + GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" \ + GITHUB_OWNER="$CIRCLE_PROJECT_USERNAME" \ + GITHUB_REPO="$CIRCLE_PROJECT_REPONAME" \ + GITHUB_PR_NUMBER="$CIRCLE_PR_NUMBER" \ + ./scripts/circleci/analyze_code.sh when: always - - restore-cache: *restore-cache-analysis - run: name: Analyze Pull Request command: | - if [ -n "$CIRCLE_PR_NUMBER" ]; then - cd bots - yarn install --non-interactive --cache-folder ~/.cache/yarn - DANGER_GITHUB_API_TOKEN="$PUBLIC_PULLBOT_GITHUB_TOKEN_A""$PUBLIC_PULLBOT_GITHUB_TOKEN_B" yarn danger - else - echo "Skipping pull request analysis." - fi + echo -e "\\x1B[36mInstalling additional dependencies\\x1B[0m" + cd bots + yarn install --non-interactive --cache-folder ~/.cache/yarn + echo -e "\\x1B[36mAnalyzing pull request\\x1B[0m"; \ + DANGER_GITHUB_API_TOKEN="$PUBLIC_PULLBOT_GITHUB_TOKEN_A""$PUBLIC_PULLBOT_GITHUB_TOKEN_B" \ + yarn danger when: always - save-cache: *save-cache-analysis @@ -716,13 +729,9 @@ workflows: # only act on version tags tags: only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ - requires: - - analyze - - test_detox_end_to_end - - test_javascript - - test_objc - - test_android - # Run code checks + # Run code checks on PRs from forks - analyze_pr: - filters: *filter-ignore-master-stable + filters: + branches: + only: /^pull\/.*$/ diff --git a/.editorconfig b/.editorconfig index 4cde30709106fc..dadac3a2b6d50b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -12,3 +12,6 @@ indent_size = 2 [*.gradle] indent_size = 4 + +[BUCK] +indent_size = 4 diff --git a/.flowconfig b/.flowconfig index 2907e44c8edd28..60467473a1255a 100644 --- a/.flowconfig +++ b/.flowconfig @@ -100,4 +100,4 @@ untyped-import untyped-type-import [version] -^0.81.0 +^0.82.0 diff --git a/.flowconfig.android b/.flowconfig.android index a32f8678bff233..99eff7c0cf95b5 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -100,4 +100,4 @@ untyped-import untyped-type-import [version] -^0.81.0 +^0.82.0 diff --git a/ContainerShip/scripts/run-android-docker-instrumentation-tests.sh b/ContainerShip/scripts/run-android-docker-instrumentation-tests.sh index ed7183dec9d5fc..e2c320d7e61afe 100644 --- a/ContainerShip/scripts/run-android-docker-instrumentation-tests.sh +++ b/ContainerShip/scripts/run-android-docker-instrumentation-tests.sh @@ -6,7 +6,7 @@ mount -o remount,exec /dev/shm AVD_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1) # create virtual device -echo no | android create avd -n $AVD_UUID -f -t android-19 --abi default/armeabi-v7a +echo no | android create avd -n "$AVD_UUID" -f -t android-19 --abi default/armeabi-v7a # emulator setup emulator64-arm -avd $AVD_UUID -no-skin -no-audio -no-window -no-boot-anim & @@ -28,8 +28,9 @@ watchman shutdown-server node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js # build test APK +# shellcheck disable=SC1091 source ./scripts/android-setup.sh && NO_BUCKD=1 retry3 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1 # run installed apk with tests -node ./ContainerShip/scripts/run-android-ci-instrumentation-tests.js $* +node ./ContainerShip/scripts/run-android-ci-instrumentation-tests.js "$*" exit $? diff --git a/ContainerShip/scripts/run-android-docker-unit-tests.sh b/ContainerShip/scripts/run-android-docker-unit-tests.sh index 5a58bb352e5421..1a422c25bf1b17 100644 --- a/ContainerShip/scripts/run-android-docker-unit-tests.sh +++ b/ContainerShip/scripts/run-android-docker-unit-tests.sh @@ -9,4 +9,4 @@ mount -o remount,exec /dev/shm set -x # run unit tests -buck test ReactAndroid/src/test/... --config build.threads=$UNIT_TESTS_BUILD_THREADS +buck test ReactAndroid/src/test/... --config build.threads="$UNIT_TESTS_BUILD_THREADS" diff --git a/ContainerShip/scripts/run-ci-e2e-tests.sh b/ContainerShip/scripts/run-ci-e2e-tests.sh index 73296e5325c622..be916439735dfd 100755 --- a/ContainerShip/scripts/run-ci-e2e-tests.sh +++ b/ContainerShip/scripts/run-ci-e2e-tests.sh @@ -128,6 +128,7 @@ function e2e_suite() { emulator64-arm -avd "$AVD_UUID" -no-skin -no-audio -no-window -no-boot-anim & bootanim="" + # shellcheck disable=SC2076 until [[ "$bootanim" =~ "stopped" ]]; do sleep 5 bootanim=$(adb -e shell getprop init.svc.bootanim 2>&1) @@ -210,15 +211,15 @@ function e2e_suite() { fi # kill packager process - if kill -0 $SERVER_PID; then + if kill -0 "$SERVER_PID"; then echo "Killing packager $SERVER_PID" - kill -9 $SERVER_PID + kill -9 "$SERVER_PID" fi # kill appium process - if kill -0 $APPIUM_PID; then + if kill -0 "$APPIUM_PID"; then echo "Killing appium $APPIUM_PID" - kill -9 $APPIUM_PID + kill -9 "$APPIUM_PID" fi fi diff --git a/ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh b/ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh index 5a9a976a97da4e..72b011ca9c3c8b 100755 --- a/ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh +++ b/ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh @@ -1,5 +1,5 @@ #!/bin/bash - +# shellcheck disable=SC1117 # Python script to run instrumentation tests, copied from https://github.com/circleci/circle-dummy-android # Example: ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests com.facebook.react.tests.ReactPickerTestCase # @@ -9,7 +9,7 @@ export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH" adb logcat -c # run tests and check output -python - $1 $2 << END +python - "$1" "$2" << END import re import subprocess as sp @@ -24,7 +24,7 @@ test_class = None if len(sys.argv) > 2: test_class = sys.argv[2] - + def update(): # prevent CircleCI from killing the process for inactivity while not done: @@ -38,10 +38,10 @@ t.start() def run(): sp.Popen(['adb', 'wait-for-device']).communicate() if (test_class != None): - p = sp.Popen('adb shell am instrument -w -e class %s %s/android.support.test.runner.AndroidJUnitRunner' + p = sp.Popen('adb shell am instrument -w -e class %s %s/android.support.test.runner.AndroidJUnitRunner' % (test_class, test_app), shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE) else : - p = sp.Popen('adb shell am instrument -w %s/android.support.test.runner.AndroidJUnitRunner' + p = sp.Popen('adb shell am instrument -w %s/android.support.test.runner.AndroidJUnitRunner' % (test_app), shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE) return p.communicate() diff --git a/IntegrationTests/IntegrationTestHarnessTest.js b/IntegrationTests/IntegrationTestHarnessTest.js index 0489a0ae41972d..e1469dda1b418a 100644 --- a/IntegrationTests/IntegrationTestHarnessTest.js +++ b/IntegrationTests/IntegrationTestHarnessTest.js @@ -10,28 +10,22 @@ 'use strict'; -/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error - * found when Flow v0.54 was deployed. To see the error delete this comment and - * run Flow. */ const requestAnimationFrame = require('fbjs/lib/requestAnimationFrame'); const React = require('react'); -const PropTypes = require('prop-types'); const ReactNative = require('react-native'); const {Text, View} = ReactNative; const {TestModule} = ReactNative.NativeModules; -class IntegrationTestHarnessTest extends React.Component< - { - shouldThrow?: boolean, - waitOneFrame?: boolean, - }, - $FlowFixMeState, -> { - static propTypes = { - shouldThrow: PropTypes.bool, - waitOneFrame: PropTypes.bool, - }; +type Props = $ReadOnly<{| + shouldThrow?: boolean, + waitOneFrame?: boolean, +|}>; + +type State = {| + done: boolean, +|}; +class IntegrationTestHarnessTest extends React.Component { state = { done: false, }; diff --git a/IntegrationTests/ReactContentSizeUpdateTest.js b/IntegrationTests/ReactContentSizeUpdateTest.js index fbec33a76a63b9..8aea15c2b6b38e 100644 --- a/IntegrationTests/ReactContentSizeUpdateTest.js +++ b/IntegrationTests/ReactContentSizeUpdateTest.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; @@ -13,12 +14,11 @@ const React = require('react'); const createReactClass = require('create-react-class'); const ReactNative = require('react-native'); const RCTNativeAppEventEmitter = require('RCTNativeAppEventEmitter'); -const Subscribable = require('Subscribable'); -const TimerMixin = require('react-timer-mixin'); const {View} = ReactNative; const {TestModule} = ReactNative.NativeModules; +import type EmitterSubscription from 'EmitterSubscription'; const reactViewWidth = 101; const reactViewHeight = 102; @@ -27,11 +27,11 @@ const newReactViewHeight = 202; const ReactContentSizeUpdateTest = createReactClass({ displayName: 'ReactContentSizeUpdateTest', - mixins: [Subscribable.Mixin, TimerMixin], + _timeoutID: (null: ?TimeoutID), + _subscription: (null: ?EmitterSubscription), UNSAFE_componentWillMount: function() { - this.addListenerOn( - RCTNativeAppEventEmitter, + this._subscription = RCTNativeAppEventEmitter.addListener( 'rootViewDidChangeIntrinsicSize', this.rootViewDidChangeIntrinsicSize, ); @@ -52,11 +52,21 @@ const ReactContentSizeUpdateTest = createReactClass({ }, componentDidMount: function() { - this.setTimeout(() => { + this._timeoutID = setTimeout(() => { this.updateViewSize(); }, 1000); }, + componentWillUnmount: function() { + if (this._timeoutID != null) { + clearTimeout(this._timeoutID); + } + + if (this._subscription != null) { + this._subscription.remove(); + } + }, + rootViewDidChangeIntrinsicSize: function(intrinsicSize) { if ( intrinsicSize.height === newReactViewHeight && diff --git a/IntegrationTests/SizeFlexibilityUpdateTest.js b/IntegrationTests/SizeFlexibilityUpdateTest.js index 4fcd833b43a677..9220a479a8dac9 100644 --- a/IntegrationTests/SizeFlexibilityUpdateTest.js +++ b/IntegrationTests/SizeFlexibilityUpdateTest.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ 'use strict'; @@ -13,10 +14,10 @@ const React = require('react'); const createReactClass = require('create-react-class'); const ReactNative = require('react-native'); const RCTNativeAppEventEmitter = require('RCTNativeAppEventEmitter'); -const Subscribable = require('Subscribable'); const {View} = ReactNative; const {TestModule} = ReactNative.NativeModules; +import type EmitterSubscription from 'EmitterSubscription'; const reactViewWidth = 111; const reactViewHeight = 222; @@ -25,16 +26,21 @@ let finalState = false; const SizeFlexibilityUpdateTest = createReactClass({ displayName: 'SizeFlexibilityUpdateTest', - mixins: [Subscribable.Mixin], + _subscription: (null: ?EmitterSubscription), UNSAFE_componentWillMount: function() { - this.addListenerOn( - RCTNativeAppEventEmitter, + this._subscription = RCTNativeAppEventEmitter.addListener( 'rootViewDidChangeIntrinsicSize', this.rootViewDidChangeIntrinsicSize, ); }, + componentWillUnmount: function() { + if (this._subscription != null) { + this._subscription.remove(); + } + }, + markPassed: function() { TestModule.markTestPassed(true); finalState = true; diff --git a/Libraries/Animated/release/package.json b/Libraries/Animated/release/package.json index 49f6a2081ffd14..4873f784a5ffad 100644 --- a/Libraries/Animated/release/package.json +++ b/Libraries/Animated/release/package.json @@ -10,7 +10,7 @@ "license": "MIT", "main": "Animated.js", "dependencies": { - "fbjs": "0.8.17" + "fbjs": "^1.0.0" }, "scripts": { "build": "gulp" diff --git a/Libraries/Animated/src/__tests__/Animated-test.js b/Libraries/Animated/src/__tests__/Animated-test.js index 96b41083d5537c..930d8a020f2bff 100644 --- a/Libraries/Animated/src/__tests__/Animated-test.js +++ b/Libraries/Animated/src/__tests__/Animated-test.js @@ -134,7 +134,9 @@ describe('Animated tests', () => { expect(callback).toBeCalled(); }); - it('send toValue when an underdamped spring stops', () => { + // This test is flaky and we are asking open source to fix it + // https://github.com/facebook/react-native/issues/21517 + it.skip('send toValue when an underdamped spring stops', () => { const anim = new Animated.Value(0); const listener = jest.fn(); anim.addListener(listener); diff --git a/Libraries/Animated/src/createAnimatedComponent.js b/Libraries/Animated/src/createAnimatedComponent.js index fb66023217f2bf..d705d6eebaa8be 100644 --- a/Libraries/Animated/src/createAnimatedComponent.js +++ b/Libraries/Animated/src/createAnimatedComponent.js @@ -12,7 +12,7 @@ const {AnimatedEvent} = require('./AnimatedEvent'); const AnimatedProps = require('./nodes/AnimatedProps'); const React = require('React'); -const ViewStylePropTypes = require('ViewStylePropTypes'); +const DeprecatedViewStylePropTypes = require('DeprecatedViewStylePropTypes'); const invariant = require('fbjs/lib/invariant'); @@ -184,7 +184,7 @@ function createAnimatedComponent(Component: any): any { return; } - for (const key in ViewStylePropTypes) { + for (const key in DeprecatedViewStylePropTypes) { if (!propTypes[key] && props[key] !== undefined) { console.warn( 'You are setting the style `{ ' + diff --git a/Libraries/Components/Button.js b/Libraries/Components/Button.js index 2466bda614196c..93ee79035915f6 100644 --- a/Libraries/Components/Button.js +++ b/Libraries/Components/Button.js @@ -150,21 +150,21 @@ const styles = StyleSheet.create({ borderRadius: 2, }, }), - text: Platform.select({ - ios: { - // iOS blue from https://developer.apple.com/ios/human-interface-guidelines/visual-design/color/ - color: '#007AFF', - textAlign: 'center', - padding: 8, - fontSize: 18, - }, - android: { - color: 'white', - textAlign: 'center', - padding: 8, - fontWeight: '500', - }, - }), + text: { + textAlign: 'center', + padding: 8, + ...Platform.select({ + ios: { + // iOS blue from https://developer.apple.com/ios/human-interface-guidelines/visual-design/color/ + color: '#007AFF', + fontSize: 18, + }, + android: { + color: 'white', + fontWeight: '500', + }, + }), + }, buttonDisabled: Platform.select({ ios: {}, android: { diff --git a/Libraries/Components/ScrollResponder.js b/Libraries/Components/ScrollResponder.js index dc55a741009a72..42079dec32abfa 100644 --- a/Libraries/Components/ScrollResponder.js +++ b/Libraries/Components/ScrollResponder.js @@ -14,7 +14,6 @@ const Dimensions = require('Dimensions'); const FrameRateLogger = require('FrameRateLogger'); const Keyboard = require('Keyboard'); const ReactNative = require('ReactNative'); -const Subscribable = require('Subscribable'); const TextInputState = require('TextInputState'); const UIManager = require('UIManager'); @@ -25,6 +24,8 @@ const warning = require('fbjs/lib/warning'); const {ScrollViewManager} = require('NativeModules'); +import type EmitterSubscription from 'EmitterSubscription'; + /** * Mixin that can be integrated in order to handle scrolling that plays well * with `ResponderEventPlugin`. Integrate with your platform specific scroll @@ -115,7 +116,10 @@ type State = { type Event = Object; const ScrollResponderMixin = { - mixins: [Subscribable.Mixin], + _subscriptionKeyboardWillShow: (null: ?EmitterSubscription), + _subscriptionKeyboardWillHide: (null: ?EmitterSubscription), + _subscriptionKeyboardDidShow: (null: ?EmitterSubscription), + _subscriptionKeyboardDidHide: (null: ?EmitterSubscription), scrollResponderMixinGetInitialState: function(): State { return { isTouching: false, @@ -602,28 +606,39 @@ const ScrollResponderMixin = { this.keyboardWillOpenTo = null; this.additionalScrollOffset = 0; - this.addListenerOn( - Keyboard, + this._subscriptionKeyboardWillShow = Keyboard.addListener( 'keyboardWillShow', this.scrollResponderKeyboardWillShow, ); - this.addListenerOn( - Keyboard, + this._subscriptionKeyboardWillHide = Keyboard.addListener( 'keyboardWillHide', this.scrollResponderKeyboardWillHide, ); - this.addListenerOn( - Keyboard, + this._subscriptionKeyboardDidShow = Keyboard.addListener( 'keyboardDidShow', this.scrollResponderKeyboardDidShow, ); - this.addListenerOn( - Keyboard, + this._subscriptionKeyboardDidHide = Keyboard.addListener( 'keyboardDidHide', this.scrollResponderKeyboardDidHide, ); }, + componentWillUnmount: function() { + if (this._subscriptionKeyboardWillShow != null) { + this._subscriptionKeyboardWillShow.remove(); + } + if (this._subscriptionKeyboardWillHide != null) { + this._subscriptionKeyboardWillHide.remove(); + } + if (this._subscriptionKeyboardDidShow != null) { + this._subscriptionKeyboardDidShow.remove(); + } + if (this._subscriptionKeyboardDidHide != null) { + this._subscriptionKeyboardDidHide.remove(); + } + }, + /** * Warning, this may be called several times for a single keyboard opening. * It's best to store the information in this method and then take any action diff --git a/Libraries/Components/Slider/Slider.js b/Libraries/Components/Slider/Slider.js index 7b7cfb3e71d739..fdde5f17ea6eec 100644 --- a/Libraries/Components/Slider/Slider.js +++ b/Libraries/Components/Slider/Slider.js @@ -66,7 +66,7 @@ type Props = $ReadOnly<{| /** * Used to style and layout the `Slider`. See `StyleSheet.js` and - * `ViewStylePropTypes.js` for more info. + * `DeprecatedViewStylePropTypes.js` for more info. */ style?: ?ViewStyleProp, diff --git a/Libraries/Components/Switch/Switch.js b/Libraries/Components/Switch/Switch.js index 6622d44fa405f1..80fe6306d7228c 100644 --- a/Libraries/Components/Switch/Switch.js +++ b/Libraries/Components/Switch/Switch.js @@ -109,7 +109,7 @@ class Switch extends React.Component { _thumbColor = thumbTintColor; if (__DEV__) { console.warn( - 'Switch: `thumbTintColor` is deprecated, use `_thumbColor` instead.', + 'Switch: `thumbTintColor` is deprecated, use `thumbColor` instead.', ); } } diff --git a/Libraries/Components/TextInput/InputAccessoryView.js b/Libraries/Components/TextInput/InputAccessoryView.js index 7bd7f7d04d6955..2e7f906096c3b0 100644 --- a/Libraries/Components/TextInput/InputAccessoryView.js +++ b/Libraries/Components/TextInput/InputAccessoryView.js @@ -10,7 +10,6 @@ 'use strict'; const DeprecatedColorPropType = require('DeprecatedColorPropType'); -const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes'); const Platform = require('Platform'); const React = require('React'); const StyleSheet = require('StyleSheet'); @@ -19,6 +18,8 @@ const requireNativeComponent = require('requireNativeComponent'); const RCTInputAccessoryView = requireNativeComponent('RCTInputAccessoryView'); +import type {ViewStyleProp} from 'StyleSheet'; + /** * Note: iOS only * @@ -77,16 +78,16 @@ const RCTInputAccessoryView = requireNativeComponent('RCTInputAccessoryView'); * For an example, look at InputAccessoryViewExample.js in RNTester. */ -type Props = { +type Props = $ReadOnly<{| +children: React.Node, /** * An ID which is used to associate this `InputAccessoryView` to * specified TextInput(s). */ - nativeID?: string, - style?: DeprecatedViewPropTypes.style, - backgroundColor?: DeprecatedColorPropType, -}; + nativeID?: ?string, + style?: ?ViewStyleProp, + backgroundColor?: ?DeprecatedColorPropType, +|}>; class InputAccessoryView extends React.Component { render(): React.Node { diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 274833a44b0258..cd71083cc08ebf 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -22,7 +22,6 @@ const StyleSheet = require('StyleSheet'); const Text = require('Text'); const TextAncestor = require('TextAncestor'); const TextInputState = require('TextInputState'); -const TimerMixin = require('react-timer-mixin'); const TouchableWithoutFeedback = require('TouchableWithoutFeedback'); const UIManager = require('UIManager'); @@ -803,7 +802,7 @@ const TextInput = createReactClass({ * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We * make `this` look like an actual native component class. */ - mixins: [NativeMethodsMixin, TimerMixin], + mixins: [NativeMethodsMixin], /** * Returns `true` if the input is currently focused; `false` otherwise. @@ -819,6 +818,7 @@ const TextInput = createReactClass({ _focusSubscription: (undefined: ?Function), _lastNativeText: (undefined: ?string), _lastNativeSelection: (undefined: ?Selection), + _rafId: (null: ?AnimationFrameID), componentDidMount: function() { this._lastNativeText = this.props.value; @@ -833,7 +833,7 @@ const TextInput = createReactClass({ 'focus', el => { if (this === el) { - this.requestAnimationFrame(this.focus); + this._rafId = requestAnimationFrame(this.focus); } else if (this.isFocused()) { this.blur(); } @@ -844,7 +844,7 @@ const TextInput = createReactClass({ } } else { if (this.props.autoFocus) { - this.requestAnimationFrame(this.focus); + this._rafId = requestAnimationFrame(this.focus); } } }, @@ -858,6 +858,9 @@ const TextInput = createReactClass({ if (tag != null) { TextInputState.unregisterInput(tag); } + if (this._rafId != null) { + cancelAnimationFrame(this._rafId); + } }, contextTypes: { diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index 205f227596fc32..9d153a586a52d6 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -15,7 +15,6 @@ const Easing = require('Easing'); const NativeMethodsMixin = require('NativeMethodsMixin'); const React = require('React'); const PropTypes = require('prop-types'); -const TimerMixin = require('react-timer-mixin'); const Touchable = require('Touchable'); const TouchableWithoutFeedback = require('TouchableWithoutFeedback'); @@ -132,7 +131,7 @@ type Props = $ReadOnly<{| */ const TouchableOpacity = ((createReactClass({ displayName: 'TouchableOpacity', - mixins: [TimerMixin, Touchable.Mixin, NativeMethodsMixin], + mixins: [Touchable.Mixin, NativeMethodsMixin], propTypes: { ...TouchableWithoutFeedback.propTypes, diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index 0b1dc3843c65a7..50e98e504667f6 100755 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -13,7 +13,6 @@ const DeprecatedEdgeInsetsPropType = require('DeprecatedEdgeInsetsPropType'); const React = require('React'); const PropTypes = require('prop-types'); -const TimerMixin = require('react-timer-mixin'); const Touchable = require('Touchable'); const View = require('View'); @@ -21,19 +20,19 @@ const createReactClass = require('create-react-class'); const ensurePositiveDelayProps = require('ensurePositiveDelayProps'); const { - AccessibilityComponentTypes, - AccessibilityRoles, - AccessibilityStates, - AccessibilityTraits, -} = require('ViewAccessibility'); + DeprecatedAccessibilityComponentTypes, + DeprecatedAccessibilityRoles, + DeprecatedAccessibilityStates, + DeprecatedAccessibilityTraits, +} = require('DeprecatedViewAccessibility'); import type {PressEvent} from 'CoreEventTypes'; import type {EdgeInsetsProp} from 'EdgeInsetsPropType'; import type { AccessibilityComponentType, AccessibilityRole, - AccessibilityStates as AccessibilityStatesFlow, - AccessibilityTraits as AccessibilityTraitsFlow, + AccessibilityStates, + AccessibilityTraits, } from 'ViewAccessibility'; const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; @@ -50,8 +49,8 @@ export type Props = $ReadOnly<{| accessibilityHint?: ?Stringish, accessibilityIgnoresInvertColors?: ?boolean, accessibilityRole?: ?AccessibilityRole, - accessibilityStates?: ?AccessibilityStatesFlow, - accessibilityTraits?: ?AccessibilityTraitsFlow, + accessibilityStates?: ?AccessibilityStates, + accessibilityTraits?: ?AccessibilityTraits, children?: ?React.Node, delayLongPress?: ?number, delayPressIn?: ?number, @@ -59,6 +58,8 @@ export type Props = $ReadOnly<{| disabled?: ?boolean, hitSlop?: ?EdgeInsetsProp, nativeID?: ?string, + onBlur?: ?Function, + onFocus?: ?Function, onLayout?: ?Function, onLongPress?: ?Function, onPress?: ?Function, @@ -78,20 +79,22 @@ export type Props = $ReadOnly<{| */ const TouchableWithoutFeedback = ((createReactClass({ displayName: 'TouchableWithoutFeedback', - mixins: [TimerMixin, Touchable.Mixin], + mixins: [Touchable.Mixin], propTypes: { accessible: PropTypes.bool, accessibilityLabel: PropTypes.node, accessibilityHint: PropTypes.string, - accessibilityComponentType: PropTypes.oneOf(AccessibilityComponentTypes), - accessibilityRole: PropTypes.oneOf(AccessibilityRoles), + accessibilityComponentType: PropTypes.oneOf( + DeprecatedAccessibilityComponentTypes, + ), + accessibilityRole: PropTypes.oneOf(DeprecatedAccessibilityRoles), accessibilityStates: PropTypes.arrayOf( - PropTypes.oneOf(AccessibilityStates), + PropTypes.oneOf(DeprecatedAccessibilityStates), ), accessibilityTraits: PropTypes.oneOfType([ - PropTypes.oneOf(AccessibilityTraits), - PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)), + PropTypes.oneOf(DeprecatedAccessibilityTraits), + PropTypes.arrayOf(PropTypes.oneOf(DeprecatedAccessibilityTraits)), ]), /** * When `accessible` is true (which is the default) this may be called when diff --git a/Libraries/Components/View/ReactNativeStyleAttributes.js b/Libraries/Components/View/ReactNativeStyleAttributes.js index 93ea3a35bc83c6..240e6a4f0a4e4a 100644 --- a/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -4,29 +4,29 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @format + * @format strict-local * @flow */ 'use strict'; -const ImageStylePropTypes = require('ImageStylePropTypes'); +const DeprecatedImageStylePropTypes = require('DeprecatedImageStylePropTypes'); const TextStylePropTypes = require('TextStylePropTypes'); -const ViewStylePropTypes = require('ViewStylePropTypes'); +const DeprecatedViewStylePropTypes = require('DeprecatedViewStylePropTypes'); -/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error - * found when Flow v0.54 was deployed. To see the error delete this comment and - * run Flow. */ -const keyMirror = require('fbjs/lib/keyMirror'); const processColor = require('processColor'); const processTransform = require('processTransform'); const sizesDiffer = require('sizesDiffer'); -const ReactNativeStyleAttributes = { - ...keyMirror(ViewStylePropTypes), - ...keyMirror(TextStylePropTypes), - ...keyMirror(ImageStylePropTypes), -}; +const ReactNativeStyleAttributes = {}; + +for (const attributeName of Object.keys({ + ...DeprecatedViewStylePropTypes, + ...TextStylePropTypes, + ...DeprecatedImageStylePropTypes, +})) { + ReactNativeStyleAttributes[attributeName] = true; +} ReactNativeStyleAttributes.transform = {process: processTransform}; ReactNativeStyleAttributes.shadowOffset = {diff: sizesDiffer}; diff --git a/Libraries/Components/View/ReactNativeViewAttributes.js b/Libraries/Components/View/ReactNativeViewAttributes.js index c1639e13631691..5b4ab1c6c2c5fa 100644 --- a/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/Libraries/Components/View/ReactNativeViewAttributes.js @@ -4,8 +4,8 @@ * 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 - * @flow strict */ 'use strict'; diff --git a/Libraries/Components/View/ViewAccessibility.js b/Libraries/Components/View/ViewAccessibility.js index 55acba53ac9477..ed7eb4d68e50b8 100644 --- a/Libraries/Components/View/ViewAccessibility.js +++ b/Libraries/Components/View/ViewAccessibility.js @@ -39,6 +39,7 @@ export type AccessibilityComponentType = | 'radiobutton_checked' | 'radiobutton_unchecked'; +// This must be kept in sync with the AccessibilityRolesMask in RCTViewManager.m export type AccessibilityRole = | 'none' | 'button' @@ -52,48 +53,5 @@ export type AccessibilityRole = | 'header' | 'summary'; +// This must be kept in sync with the AccessibilityStatesMask in RCTViewManager.m export type AccessibilityStates = $ReadOnlyArray<'disabled' | 'selected'>; - -module.exports = { - AccessibilityTraits: [ - 'none', - 'button', - 'link', - 'header', - 'search', - 'image', - 'selected', - 'plays', - 'key', - 'text', - 'summary', - 'disabled', - 'frequentUpdates', - 'startsMedia', - 'adjustable', - 'allowsDirectInteraction', - 'pageTurn', - ], - AccessibilityComponentTypes: [ - 'none', - 'button', - 'radiobutton_checked', - 'radiobutton_unchecked', - ], - // This must be kept in sync with the AccessibilityRolesMask in RCTViewManager.m - AccessibilityRoles: [ - 'none', - 'button', - 'link', - 'search', - 'image', - 'keyboardkey', - 'text', - 'adjustable', - 'imagebutton', - 'header', - 'summary', - ], - // This must be kept in sync with the AccessibilityStatesMask in RCTViewManager.m - AccessibilityStates: ['selected', 'disabled'], -}; diff --git a/Libraries/Core/InitializeCore.js b/Libraries/Core/InitializeCore.js index 5fcceab22909fb..c55163981c8e4b 100644 --- a/Libraries/Core/InitializeCore.js +++ b/Libraries/Core/InitializeCore.js @@ -91,9 +91,6 @@ polyfillGlobal('regeneratorRuntime', () => { // The require just sets up the global, so make sure when we first // invoke it the global does not exist delete global.regeneratorRuntime; - /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an - * error found when Flow v0.54 was deployed. To see the error delete this - * comment and run Flow. */ require('regenerator-runtime/runtime'); return global.regeneratorRuntime; }); @@ -214,9 +211,6 @@ if (__DEV__) { // Set up inspector const JSInspector = require('JSInspector'); - /* $FlowFixMe(>=0.56.0 site=react_native_fb,react_native_oss) This comment - * suppresses an error found when Flow v0.56 was deployed. To see the error - * delete this comment and run Flow. */ JSInspector.registerAgent(require('NetworkAgent')); } } diff --git a/Libraries/DeprecatedPropTypes/DeprecatedImagePropType.js b/Libraries/DeprecatedPropTypes/DeprecatedImagePropType.js new file mode 100644 index 00000000000000..6b8c16b579d23e --- /dev/null +++ b/Libraries/DeprecatedPropTypes/DeprecatedImagePropType.js @@ -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. + * + * @flow + * @format + */ + +'use strict'; + +const DeprecatedEdgeInsetsPropType = require('DeprecatedEdgeInsetsPropType'); +const DeprecatedImageSourcePropType = require('DeprecatedImageSourcePropType'); +const DeprecatedImageStylePropTypes = require('DeprecatedImageStylePropTypes'); +const DeprecatedStyleSheetPropType = require('DeprecatedStyleSheetPropType'); +const PropTypes = require('prop-types'); + +module.exports = { + style: DeprecatedStyleSheetPropType(DeprecatedImageStylePropTypes), + source: DeprecatedImageSourcePropType, + defaultSource: PropTypes.oneOfType([ + PropTypes.shape({ + uri: PropTypes.string, + width: PropTypes.number, + height: PropTypes.number, + scale: PropTypes.number, + }), + PropTypes.number, + ]), + + accessible: PropTypes.bool, + + accessibilityLabel: PropTypes.node, + + blurRadius: PropTypes.number, + + capInsets: DeprecatedEdgeInsetsPropType, + + resizeMethod: PropTypes.oneOf(['auto', 'resize', 'scale']), + + resizeMode: PropTypes.oneOf([ + 'cover', + 'contain', + 'stretch', + 'repeat', + 'center', + ]), + + testID: PropTypes.string, + + onLayout: PropTypes.func, + + onLoadStart: PropTypes.func, + + onProgress: PropTypes.func, + + onError: PropTypes.func, + + onPartialLoad: PropTypes.func, + + onLoad: PropTypes.func, + + onLoadEnd: PropTypes.func, +}; diff --git a/Libraries/DeprecatedPropTypes/DeprecatedImageSourcePropType.js b/Libraries/DeprecatedPropTypes/DeprecatedImageSourcePropType.js new file mode 100644 index 00000000000000..0670023ae73ba2 --- /dev/null +++ b/Libraries/DeprecatedPropTypes/DeprecatedImageSourcePropType.js @@ -0,0 +1,39 @@ +/** + * 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. + * + * @no-flow + * @format + */ +'use strict'; + +const PropTypes = require('prop-types'); + +const ImageURISourcePropType = PropTypes.shape({ + uri: PropTypes.string, + bundle: PropTypes.string, + method: PropTypes.string, + headers: PropTypes.objectOf(PropTypes.string), + body: PropTypes.string, + cache: PropTypes.oneOf([ + 'default', + 'reload', + 'force-cache', + 'only-if-cached', + ]), + width: PropTypes.number, + height: PropTypes.number, + scale: PropTypes.number, +}); + +const ImageSourcePropType = PropTypes.oneOfType([ + ImageURISourcePropType, + // Opaque type returned by require('./image.jpg') + PropTypes.number, + // Multiple sources + PropTypes.arrayOf(ImageURISourcePropType), +]); + +module.exports = ImageSourcePropType; diff --git a/Libraries/Image/ImageStylePropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedImageStylePropTypes.js similarity index 90% rename from Libraries/Image/ImageStylePropTypes.js rename to Libraries/DeprecatedPropTypes/DeprecatedImageStylePropTypes.js index 20088ace1abfb7..3fbed21da30fe0 100644 --- a/Libraries/Image/ImageStylePropTypes.js +++ b/Libraries/DeprecatedPropTypes/DeprecatedImageStylePropTypes.js @@ -10,17 +10,22 @@ 'use strict'; const DeprecatedColorPropType = require('DeprecatedColorPropType'); -const ImageResizeMode = require('ImageResizeMode'); -const LayoutPropTypes = require('LayoutPropTypes'); +const DeprecatedLayoutPropTypes = require('DeprecatedLayoutPropTypes'); const ReactPropTypes = require('prop-types'); const DeprecatedShadowPropTypesIOS = require('DeprecatedShadowPropTypesIOS'); const DeprecatedTransformPropTypes = require('DeprecatedTransformPropTypes'); const ImageStylePropTypes = { - ...LayoutPropTypes, + ...DeprecatedLayoutPropTypes, ...DeprecatedShadowPropTypesIOS, ...DeprecatedTransformPropTypes, - resizeMode: ReactPropTypes.oneOf(Object.keys(ImageResizeMode)), + resizeMode: ReactPropTypes.oneOf([ + 'center', + 'contain', + 'cover', + 'repeat', + 'stretch', + ]), backfaceVisibility: ReactPropTypes.oneOf(['visible', 'hidden']), backgroundColor: DeprecatedColorPropType, borderColor: DeprecatedColorPropType, diff --git a/Libraries/DeprecatedPropTypes/DeprecatedLayoutPropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedLayoutPropTypes.js new file mode 100644 index 00000000000000..0ebccaa8d07083 --- /dev/null +++ b/Libraries/DeprecatedPropTypes/DeprecatedLayoutPropTypes.js @@ -0,0 +1,190 @@ +/** + * 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 + */ + +'use strict'; + +const ReactPropTypes = require('prop-types'); + +const LayoutPropTypes = { + display: ReactPropTypes.oneOf(['none', 'flex']), + width: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + height: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + start: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + end: ReactPropTypes.oneOfType([ReactPropTypes.number, ReactPropTypes.string]), + top: ReactPropTypes.oneOfType([ReactPropTypes.number, ReactPropTypes.string]), + left: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + right: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + bottom: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + minWidth: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + maxWidth: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + minHeight: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + maxHeight: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + margin: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginVertical: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginHorizontal: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginTop: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginBottom: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginLeft: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginRight: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginStart: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + marginEnd: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + padding: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingVertical: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingHorizontal: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingTop: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingBottom: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingLeft: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingRight: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingStart: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + paddingEnd: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + borderWidth: ReactPropTypes.number, + borderTopWidth: ReactPropTypes.number, + borderStartWidth: ReactPropTypes.number, + borderEndWidth: ReactPropTypes.number, + borderRightWidth: ReactPropTypes.number, + borderBottomWidth: ReactPropTypes.number, + borderLeftWidth: ReactPropTypes.number, + position: ReactPropTypes.oneOf(['absolute', 'relative']), + flexDirection: ReactPropTypes.oneOf([ + 'row', + 'row-reverse', + 'column', + 'column-reverse', + ]), + flexWrap: ReactPropTypes.oneOf(['wrap', 'nowrap', 'wrap-reverse']), + justifyContent: ReactPropTypes.oneOf([ + 'flex-start', + 'flex-end', + 'center', + 'space-between', + 'space-around', + 'space-evenly', + ]), + alignItems: ReactPropTypes.oneOf([ + 'flex-start', + 'flex-end', + 'center', + 'stretch', + 'baseline', + ]), + alignSelf: ReactPropTypes.oneOf([ + 'auto', + 'flex-start', + 'flex-end', + 'center', + 'stretch', + 'baseline', + ]), + alignContent: ReactPropTypes.oneOf([ + 'flex-start', + 'flex-end', + 'center', + 'stretch', + 'space-between', + 'space-around', + ]), + overflow: ReactPropTypes.oneOf(['visible', 'hidden', 'scroll']), + flex: ReactPropTypes.number, + flexGrow: ReactPropTypes.number, + flexShrink: ReactPropTypes.number, + flexBasis: ReactPropTypes.oneOfType([ + ReactPropTypes.number, + ReactPropTypes.string, + ]), + aspectRatio: ReactPropTypes.number, + zIndex: ReactPropTypes.number, + direction: ReactPropTypes.oneOf(['inherit', 'ltr', 'rtl']), +}; + +module.exports = LayoutPropTypes; diff --git a/Libraries/DeprecatedPropTypes/DeprecatedTextPropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedTextPropTypes.js new file mode 100644 index 00000000000000..1723bb56cb6cdd --- /dev/null +++ b/Libraries/DeprecatedPropTypes/DeprecatedTextPropTypes.js @@ -0,0 +1,41 @@ +/** + * 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 DeprecatedColorPropType = require('DeprecatedColorPropType'); +const DeprecatedEdgeInsetsPropType = require('DeprecatedEdgeInsetsPropType'); +const DeprecatedStyleSheetPropType = require('DeprecatedStyleSheetPropType'); +const PropTypes = require('prop-types'); +const TextStylePropTypes = require('TextStylePropTypes'); + +const stylePropType = DeprecatedStyleSheetPropType(TextStylePropTypes); + +module.exports = { + ellipsizeMode: PropTypes.oneOf(['head', 'middle', 'tail', 'clip']), + numberOfLines: PropTypes.number, + textBreakStrategy: PropTypes.oneOf(['simple', 'highQuality', 'balanced']), + onLayout: PropTypes.func, + onPress: PropTypes.func, + onLongPress: PropTypes.func, + pressRetentionOffset: DeprecatedEdgeInsetsPropType, + selectable: PropTypes.bool, + selectionColor: DeprecatedColorPropType, + suppressHighlighting: PropTypes.bool, + style: stylePropType, + testID: PropTypes.string, + nativeID: PropTypes.string, + allowFontScaling: PropTypes.bool, + maxFontSizeMultiplier: PropTypes.number, + accessible: PropTypes.bool, + adjustsFontSizeToFit: PropTypes.bool, + minimumFontScale: PropTypes.number, + disabled: PropTypes.bool, +}; diff --git a/Libraries/DeprecatedPropTypes/DeprecatedViewAccessibility.js b/Libraries/DeprecatedPropTypes/DeprecatedViewAccessibility.js new file mode 100644 index 00000000000000..890dd49f0f8672 --- /dev/null +++ b/Libraries/DeprecatedPropTypes/DeprecatedViewAccessibility.js @@ -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. + * + * @format + * @flow strict + */ + +'use strict'; + +module.exports = { + DeprecatedAccessibilityTraits: [ + 'none', + 'button', + 'link', + 'header', + 'search', + 'image', + 'selected', + 'plays', + 'key', + 'text', + 'summary', + 'disabled', + 'frequentUpdates', + 'startsMedia', + 'adjustable', + 'allowsDirectInteraction', + 'pageTurn', + ], + DeprecatedAccessibilityComponentTypes: [ + 'none', + 'button', + 'radiobutton_checked', + 'radiobutton_unchecked', + ], + // This must be kept in sync with the AccessibilityRolesMask in RCTViewManager.m + DeprecatedAccessibilityRoles: [ + 'none', + 'button', + 'link', + 'search', + 'image', + 'keyboardkey', + 'text', + 'adjustable', + 'imagebutton', + 'header', + 'summary', + ], + // This must be kept in sync with the AccessibilityStatesMask in RCTViewManager.m + DeprecatedAccessibilityStates: ['selected', 'disabled'], +}; diff --git a/Libraries/DeprecatedPropTypes/DeprecatedViewPropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedViewPropTypes.js index 9bbb30c3ffdbc8..0d5b0746c4a3d8 100644 --- a/Libraries/DeprecatedPropTypes/DeprecatedViewPropTypes.js +++ b/Libraries/DeprecatedPropTypes/DeprecatedViewPropTypes.js @@ -14,16 +14,18 @@ const DeprecatedEdgeInsetsPropType = require('DeprecatedEdgeInsetsPropType'); const PlatformViewPropTypes = require('PlatformViewPropTypes'); const PropTypes = require('prop-types'); const DeprecatedStyleSheetPropType = require('DeprecatedStyleSheetPropType'); -const ViewStylePropTypes = require('ViewStylePropTypes'); +const DeprecatedViewStylePropTypes = require('DeprecatedViewStylePropTypes'); const { - AccessibilityComponentTypes, - AccessibilityTraits, - AccessibilityRoles, - AccessibilityStates, -} = require('ViewAccessibility'); + DeprecatedAccessibilityComponentTypes, + DeprecatedAccessibilityTraits, + DeprecatedAccessibilityRoles, + DeprecatedAccessibilityStates, +} = require('DeprecatedViewAccessibility'); -const stylePropType = DeprecatedStyleSheetPropType(ViewStylePropTypes); +const stylePropType = DeprecatedStyleSheetPropType( + DeprecatedViewStylePropTypes, +); module.exports = { /** @@ -75,17 +77,21 @@ module.exports = { * * See http://facebook.github.io/react-native/docs/view.html#accessibilitycomponenttype */ - accessibilityComponentType: PropTypes.oneOf(AccessibilityComponentTypes), + accessibilityComponentType: PropTypes.oneOf( + DeprecatedAccessibilityComponentTypes, + ), /** * Indicates to accessibility services to treat UI component like a specific role. */ - accessibilityRole: PropTypes.oneOf(AccessibilityRoles), + accessibilityRole: PropTypes.oneOf(DeprecatedAccessibilityRoles), /** * Indicates to accessibility services that UI Component is in a specific State. */ - accessibilityStates: PropTypes.arrayOf(PropTypes.oneOf(AccessibilityStates)), + accessibilityStates: PropTypes.arrayOf( + PropTypes.oneOf(DeprecatedAccessibilityStates), + ), /** * Indicates to accessibility services whether the user should be notified * when this view changes. Works for Android API >= 19 only. @@ -123,8 +129,8 @@ module.exports = { * See http://facebook.github.io/react-native/docs/view.html#accessibilitytraits */ accessibilityTraits: PropTypes.oneOfType([ - PropTypes.oneOf(AccessibilityTraits), - PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)), + PropTypes.oneOf(DeprecatedAccessibilityTraits), + PropTypes.arrayOf(PropTypes.oneOf(DeprecatedAccessibilityTraits)), ]), /** diff --git a/Libraries/Components/View/ViewStylePropTypes.js b/Libraries/DeprecatedPropTypes/DeprecatedViewStylePropTypes.js similarity index 92% rename from Libraries/Components/View/ViewStylePropTypes.js rename to Libraries/DeprecatedPropTypes/DeprecatedViewStylePropTypes.js index 486d7426e582c4..546da9cee33e8d 100644 --- a/Libraries/Components/View/ViewStylePropTypes.js +++ b/Libraries/DeprecatedPropTypes/DeprecatedViewStylePropTypes.js @@ -11,7 +11,7 @@ 'use strict'; const DeprecatedColorPropType = require('DeprecatedColorPropType'); -const LayoutPropTypes = require('LayoutPropTypes'); +const DeprecatedLayoutPropTypes = require('DeprecatedLayoutPropTypes'); const ReactPropTypes = require('prop-types'); const DeprecatedShadowPropTypesIOS = require('DeprecatedShadowPropTypesIOS'); const DeprecatedTransformPropTypes = require('DeprecatedTransformPropTypes'); @@ -19,8 +19,8 @@ const DeprecatedTransformPropTypes = require('DeprecatedTransformPropTypes'); /** * Warning: Some of these properties may not be supported in all releases. */ -const ViewStylePropTypes = { - ...LayoutPropTypes, +const DeprecatedViewStylePropTypes = { + ...DeprecatedLayoutPropTypes, ...DeprecatedShadowPropTypesIOS, ...DeprecatedTransformPropTypes, backfaceVisibility: ReactPropTypes.oneOf(['visible', 'hidden']), @@ -58,4 +58,4 @@ const ViewStylePropTypes = { elevation: ReactPropTypes.number, }; -module.exports = ViewStylePropTypes; +module.exports = DeprecatedViewStylePropTypes; diff --git a/Libraries/Experimental/Incremental.js b/Libraries/Experimental/Incremental.js index bf1438d71afe1c..b20fb543e947c5 100644 --- a/Libraries/Experimental/Incremental.js +++ b/Libraries/Experimental/Incremental.js @@ -90,7 +90,7 @@ export type Props = { * Tags instances and associated tasks for easier debugging. */ name: string, - children?: any, + children: React.Node, }; type DefaultProps = { name: string, diff --git a/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js b/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js index c2790f848a5979..cf54d9d502f7f8 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableFlatList.js @@ -17,23 +17,31 @@ const React = require('React'); const SwipeableRow = require('SwipeableRow'); const FlatList = require('FlatList'); +// TODO: Make this $ReadOnly and Exact. Will require doing the same to the props in +// Libraries/Lists/* type SwipableListProps = { /** * To alert the user that swiping is possible, the first row can bounce * on component mount. */ bounceFirstRowOnMount: boolean, - // Maximum distance to open to after a swipe + + /** + * Maximum distance to open to after a swipe + */ maxSwipeDistance: number | (Object => number), - // Callback method to render the view that will be unveiled on swipe + + /** + * Callback method to render the view that will be unveiled on swipe + */ renderQuickActions: renderItemType, }; type Props = SwipableListProps & FlatListProps; -type State = { +type State = {| openRowKey: ?string, -}; +|}; /** * A container component that renders multiple SwipeableRow's in a FlatList @@ -53,29 +61,9 @@ type State = { */ class SwipeableFlatList extends React.Component, State> { - props: Props; - state: State; - _flatListRef: ?FlatList = null; _shouldBounceFirstRowOnMount: boolean = false; - static propTypes = { - ...FlatList.propTypes, - - /** - * To alert the user that swiping is possible, the first row can bounce - * on component mount. - */ - bounceFirstRowOnMount: PropTypes.bool.isRequired, - - // Maximum distance to open to after a swipe - maxSwipeDistance: PropTypes.oneOfType([PropTypes.number, PropTypes.func]) - .isRequired, - - // Callback method to render the view that will be unveiled on swipe - renderQuickActions: PropTypes.func.isRequired, - }; - static defaultProps = { ...FlatList.defaultProps, bounceFirstRowOnMount: true, diff --git a/Libraries/Experimental/SwipeableRow/SwipeableQuickActionButton.js b/Libraries/Experimental/SwipeableRow/SwipeableQuickActionButton.js index 9c99418df13eed..82e1f7a0ae5e47 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableQuickActionButton.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableQuickActionButton.js @@ -27,12 +27,21 @@ import type {ImageSource} from 'ImageSource'; class SwipeableQuickActionButton extends React.Component<{ accessibilityLabel?: string, imageSource?: ?(ImageSource | number), + /* $FlowFixMe(>=0.82.0 site=react_native_fb) This comment suppresses an error + * found when Flow v0.82 was deployed. To see the error delete this comment + * and run Flow. */ imageStyle?: ?DeprecatedViewPropTypes.style, mainView?: ?React.Node, onPress?: Function, + /* $FlowFixMe(>=0.82.0 site=react_native_fb) This comment suppresses an error + * found when Flow v0.82 was deployed. To see the error delete this comment + * and run Flow. */ style?: ?DeprecatedViewPropTypes.style, testID?: string, text?: ?(string | Object | Array), + /* $FlowFixMe(>=0.82.0 site=react_native_fb) This comment suppresses an error + * found when Flow v0.82 was deployed. To see the error delete this comment + * and run Flow. */ textStyle?: ?DeprecatedViewPropTypes.style, }> { render(): React.Node { diff --git a/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js b/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js index 4d2a43825f3b36..c97f77648af76f 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableQuickActions.js @@ -10,11 +10,17 @@ 'use strict'; -const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes'); const React = require('React'); const StyleSheet = require('StyleSheet'); const View = require('View'); +import type {ViewStyleProp} from 'StyleSheet'; + +type Props = $ReadOnly<{| + style?: ?ViewStyleProp, + children: React.Node, +|}>; + /** * A thin wrapper around standard quick action buttons that can, if the user * chooses, be used with SwipeableListView. Sample usage is as follows, in the @@ -25,13 +31,8 @@ const View = require('View'); * * */ -class SwipeableQuickActions extends React.Component<{style?: $FlowFixMe}> { - static propTypes = { - style: DeprecatedViewPropTypes.style, - }; - +class SwipeableQuickActions extends React.Component { render(): React.Node { - // $FlowFixMe found when converting React.createClass to ES6 const children = this.props.children; let buttons = []; @@ -40,8 +41,7 @@ class SwipeableQuickActions extends React.Component<{style?: $FlowFixMe}> { for (let i = 0; i < children.length; i++) { buttons.push(children[i]); - // $FlowFixMe found when converting React.createClass to ES6 - if (i < this.props.children.length - 1) { + if (i < children.length - 1) { // Not last button buttons.push(); } diff --git a/Libraries/Experimental/SwipeableRow/SwipeableRow.js b/Libraries/Experimental/SwipeableRow/SwipeableRow.js index fb9cc1df409090..5e9e796cdcdb79 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableRow.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableRow.js @@ -16,10 +16,6 @@ const PanResponder = require('PanResponder'); const React = require('React'); const PropTypes = require('prop-types'); const StyleSheet = require('StyleSheet'); -/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error - * found when Flow v0.54 was deployed. To see the error delete this comment and - * run Flow. */ -const TimerMixin = require('react-timer-mixin'); const View = require('View'); const createReactClass = require('create-react-class'); @@ -85,8 +81,7 @@ const SwipeableRow = createReactClass({ displayName: 'SwipeableRow', _panResponder: {}, _previousLeft: CLOSED_LEFT_POSITION, - - mixins: [TimerMixin], + _timeoutID: (null: ?TimeoutID), propTypes: { children: PropTypes.any, @@ -157,7 +152,7 @@ const SwipeableRow = createReactClass({ * Do the on mount bounce after a delay because if we animate when other * components are loading, the animation will be laggy */ - this.setTimeout(() => { + this._timeoutID = setTimeout(() => { this._animateBounceBack(ON_MOUNT_BOUNCE_DURATION); }, ON_MOUNT_BOUNCE_DELAY); } @@ -173,6 +168,12 @@ const SwipeableRow = createReactClass({ } }, + componentWillUnmount() { + if (this._timeoutID != null) { + clearTimeout(this._timeoutID); + } + }, + render(): React.Element { // The view hidden behind the main view let slideOutView; diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index e81db678bdafad..3eda5a7c52d2ec 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -10,15 +10,15 @@ 'use strict'; +const DeprecatedImageStylePropTypes = require('DeprecatedImageStylePropTypes'); +const DeprecatedStyleSheetPropType = require('DeprecatedStyleSheetPropType'); const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes'); -const ImageStylePropTypes = require('ImageStylePropTypes'); +const ImageViewNativeComponent = require('ImageViewNativeComponent'); const NativeModules = require('NativeModules'); const PropTypes = require('prop-types'); const React = require('React'); const ReactNative = require('ReactNative'); const StyleSheet = require('StyleSheet'); -const DeprecatedStyleSheetPropType = require('DeprecatedStyleSheetPropType'); -const ImageViewNativeComponent = require('ImageViewNativeComponent'); const TextAncestor = require('TextAncestor'); const flattenStyle = require('flattenStyle'); @@ -38,7 +38,7 @@ function generateRequestId() { const ImageProps = { ...DeprecatedViewPropTypes, - style: DeprecatedStyleSheetPropType(ImageStylePropTypes), + style: DeprecatedStyleSheetPropType(DeprecatedImageStylePropTypes), /** * See https://facebook.github.io/react-native/docs/image.html#source */ diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index 07e34b92251262..29532dea908e89 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -9,7 +9,7 @@ */ 'use strict'; -const ImageProps = require('ImageProps'); +const DeprecatedImagePropType = require('DeprecatedImagePropType'); const NativeModules = require('NativeModules'); const React = require('React'); const ReactNative = require('ReactNative'); @@ -58,7 +58,7 @@ declare class ImageComponentType extends ReactNative.NativeComponent< static prefetch: typeof prefetch; static queryCache: typeof queryCache; static resolveAssetSource: typeof resolveAssetSource; - static propTypes: typeof ImageProps; + static propTypes: typeof DeprecatedImagePropType; } /** @@ -154,7 +154,7 @@ Image.queryCache = queryCache; */ Image.resolveAssetSource = resolveAssetSource; -Image.propTypes = ImageProps; +Image.propTypes = DeprecatedImagePropType; const styles = StyleSheet.create({ base: { diff --git a/Libraries/Image/ImageProps.js b/Libraries/Image/ImageProps.js index 71396abd43c5c6..9dcf083be07841 100644 --- a/Libraries/Image/ImageProps.js +++ b/Libraries/Image/ImageProps.js @@ -10,18 +10,12 @@ 'use strict'; -const DeprecatedEdgeInsetsPropType = require('DeprecatedEdgeInsetsPropType'); -const ImageSourcePropType = require('ImageSourcePropType'); -const ImageStylePropTypes = require('ImageStylePropTypes'); -const PropTypes = require('prop-types'); -const DeprecatedStyleSheetPropType = require('DeprecatedStyleSheetPropType'); - -import type {DimensionValue} from 'StyleSheetTypes'; -import type {ViewProps} from 'ViewPropTypes'; -import type {ImageSource} from 'ImageSource'; +import type {SyntheticEvent, LayoutEvent} from 'CoreEventTypes'; import type {EdgeInsetsProp} from 'EdgeInsetsPropType'; -import type {SyntheticEvent} from 'CoreEventTypes'; +import type {ImageSource} from 'ImageSource'; import type {ViewStyleProp, ImageStyleProp} from 'StyleSheet'; +import type {DimensionValue} from 'StyleSheetTypes'; +import type {ViewProps} from 'ViewPropTypes'; type OnLoadEvent = SyntheticEvent< $ReadOnly<{| @@ -37,8 +31,23 @@ type OnLoadEvent = SyntheticEvent< >; type IOSImageProps = $ReadOnly<{| + /** + * A static image to display while loading the image source. + * + * See https://facebook.github.io/react-native/docs/image.html#defaultsource + */ defaultSource?: ?ImageSource, + /** + * Invoked when a partial load of the image is complete. + * + * See https://facebook.github.io/react-native/docs/image.html#onpartialload + */ onPartialLoad?: ?() => void, + /** + * Invoked on download progress with `{nativeEvent: {loaded, total}}`. + * + * See https://facebook.github.io/react-native/docs/image.html#onprogress + */ onProgress?: ?( event: SyntheticEvent<$ReadOnly<{|loaded: number, total: number|}>>, ) => void, @@ -54,139 +63,108 @@ export type ImageProps = {| ...$Diff>, ...IOSImageProps, ...AndroidImageProps, - blurRadius?: ?number, - capInsets?: ?EdgeInsetsProp, - - onError?: ?(event: SyntheticEvent<$ReadOnly<{||}>>) => void, - onLoad?: ?(event: OnLoadEvent) => void, - onLoadEnd?: ?() => void, - onLoadStart?: ?() => void, - resizeMethod?: ?('auto' | 'resize' | 'scale'), - source?: ?ImageSource, - style?: ?ImageStyleProp, - // Can be set via props or style, for now - height?: ?DimensionValue, - width?: ?DimensionValue, - resizeMode?: ?('cover' | 'contain' | 'stretch' | 'repeat' | 'center'), - - src?: empty, - children?: empty, -|}; - -module.exports = { - /** - * See https://facebook.github.io/react-native/docs/image.html#style - */ - style: DeprecatedStyleSheetPropType(ImageStylePropTypes), - /** - * The image source (either a remote URL or a local file resource). - * - * See https://facebook.github.io/react-native/docs/image.html#source - */ - source: ImageSourcePropType, - /** - * A static image to display while loading the image source. - * - * See https://facebook.github.io/react-native/docs/image.html#defaultsource - */ - defaultSource: PropTypes.oneOfType([ - PropTypes.shape({ - uri: PropTypes.string, - width: PropTypes.number, - height: PropTypes.number, - scale: PropTypes.number, - }), - PropTypes.number, - ]), /** * When true, indicates the image is an accessibility element. * * See https://facebook.github.io/react-native/docs/image.html#accessible */ - accessible: PropTypes.bool, + accessible?: ?boolean, + /** * The text that's read by the screen reader when the user interacts with * the image. * * See https://facebook.github.io/react-native/docs/image.html#accessibilitylabel */ - accessibilityLabel: PropTypes.node, + accessibilityLabel?: ?Stringish, + /** * blurRadius: the blur radius of the blur filter added to the image * * See https://facebook.github.io/react-native/docs/image.html#blurradius */ - blurRadius: PropTypes.number, + blurRadius?: ?number, + /** * See https://facebook.github.io/react-native/docs/image.html#capinsets */ - capInsets: DeprecatedEdgeInsetsPropType, + capInsets?: ?EdgeInsetsProp, + /** - * See https://facebook.github.io/react-native/docs/image.html#resizemethod + * Invoked on load error with `{nativeEvent: {error}}`. + * + * See https://facebook.github.io/react-native/docs/image.html#onerror */ - resizeMethod: PropTypes.oneOf(['auto', 'resize', 'scale']), + onError?: ?(event: SyntheticEvent<$ReadOnly<{||}>>) => void, + /** - * Determines how to resize the image when the frame doesn't match the raw - * image dimensions. + * Invoked on mount and layout changes with + * `{nativeEvent: {layout: {x, y, width, height}}}`. * - * See https://facebook.github.io/react-native/docs/image.html#resizemode + * See https://facebook.github.io/react-native/docs/image.html#onlayout */ - resizeMode: PropTypes.oneOf([ - 'cover', - 'contain', - 'stretch', - 'repeat', - 'center', - ]), + + onLayout?: ?(event: LayoutEvent) => mixed, + /** - * A unique identifier for this element to be used in UI Automation - * testing scripts. + * Invoked when load completes successfully. * - * See https://facebook.github.io/react-native/docs/image.html#testid + * See https://facebook.github.io/react-native/docs/image.html#onload */ - testID: PropTypes.string, + onLoad?: ?(event: OnLoadEvent) => void, + /** - * Invoked on mount and layout changes with - * `{nativeEvent: {layout: {x, y, width, height}}}`. + * Invoked when load either succeeds or fails. * - * See https://facebook.github.io/react-native/docs/image.html#onlayout + * See https://facebook.github.io/react-native/docs/image.html#onloadend */ - onLayout: PropTypes.func, + onLoadEnd?: ?() => void, + /** * Invoked on load start. * * See https://facebook.github.io/react-native/docs/image.html#onloadstart */ - onLoadStart: PropTypes.func, + onLoadStart?: ?() => void, + /** - * Invoked on download progress with `{nativeEvent: {loaded, total}}`. - * - * See https://facebook.github.io/react-native/docs/image.html#onprogress + * See https://facebook.github.io/react-native/docs/image.html#resizemethod */ - onProgress: PropTypes.func, + resizeMethod?: ?('auto' | 'resize' | 'scale'), + /** - * Invoked on load error with `{nativeEvent: {error}}`. + * The image source (either a remote URL or a local file resource). * - * See https://facebook.github.io/react-native/docs/image.html#onerror + * See https://facebook.github.io/react-native/docs/image.html#source */ - onError: PropTypes.func, + source?: ?ImageSource, + /** - * Invoked when a partial load of the image is complete. - * - * See https://facebook.github.io/react-native/docs/image.html#onpartialload + * See https://facebook.github.io/react-native/docs/image.html#style */ - onPartialLoad: PropTypes.func, + style?: ?ImageStyleProp, + + // Can be set via props or style, for now + height?: ?DimensionValue, + width?: ?DimensionValue, + /** - * Invoked when load completes successfully. + * Determines how to resize the image when the frame doesn't match the raw + * image dimensions. * - * See https://facebook.github.io/react-native/docs/image.html#onload + * See https://facebook.github.io/react-native/docs/image.html#resizemode */ - onLoad: PropTypes.func, + resizeMode?: ?('cover' | 'contain' | 'stretch' | 'repeat' | 'center'), + /** - * Invoked when load either succeeds or fails. + * A unique identifier for this element to be used in UI Automation + * testing scripts. * - * See https://facebook.github.io/react-native/docs/image.html#onloadend + * See https://facebook.github.io/react-native/docs/image.html#testid */ - onLoadEnd: PropTypes.func, -}; + testID?: ?string, + + src?: empty, + children?: empty, +|}; diff --git a/Libraries/Image/ImageResizeMode.js b/Libraries/Image/ImageResizeMode.js index b3f3b087887df2..1dad3309b1588d 100644 --- a/Libraries/Image/ImageResizeMode.js +++ b/Libraries/Image/ImageResizeMode.js @@ -4,49 +4,33 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow + * @flow strict * @format */ -'use strict'; -/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error - * found when Flow v0.54 was deployed. To see the error delete this comment and - * run Flow. */ -const keyMirror = require('fbjs/lib/keyMirror'); +'use strict'; /** - * ImageResizeMode - Enum for different image resizing modes, set via - * `resizeMode` style property on `` components. + * ImageResizeMode defines valid values for different image resizing modes set + * via the `resizeMode` style property on ``. */ -const ImageResizeMode = keyMirror({ - /** - * contain - The image will be resized such that it will be completely - * visible, contained within the frame of the View. - */ - contain: null, - /** - * cover - The image will be resized such that the entire area of the view - * is covered by the image, potentially clipping parts of the image. - */ - cover: null, - /** - * stretch - The image will be stretched to fill the entire frame of the - * view without clipping. This may change the aspect ratio of the image, - * distorting it. - */ - stretch: null, - /** - * center - The image will be scaled down such that it is completely visible, - * if bigger than the area of the view. - * The image will not be scaled up. - */ - center: null, +export type ImageResizeMode = + // Resize by scaling down such that it is completely visible, if bigger than + // the area of the view. The image will not be scaled up. + | 'center' + + // Resize such that it will be completely visible, contained within the frame + // of the View. + | 'contain' + + // Resize such that the entire area of the view is covered by the image, + // potentially clipping parts of the image. + | 'cover' - /** - * repeat - The image will be repeated to cover the frame of the View. The - * image will keep it's size and aspect ratio. - */ - repeat: null, -}); + // Resize by repeating to cover the frame of the View. The image will keep its + // size and aspect ratio. + | 'repeat' -module.exports = ImageResizeMode; + // Resize by stretching it to fill the entire frame of the view without + // clipping. This may change the aspect ratio of the image, distorting it. + | 'stretch'; diff --git a/Libraries/Image/ImageSource.js b/Libraries/Image/ImageSource.js index 9cb9fceed082e3..0e03dc78c0f5d1 100644 --- a/Libraries/Image/ImageSource.js +++ b/Libraries/Image/ImageSource.js @@ -15,14 +15,72 @@ // instances of classes like FBIcon. // https://fburl.com/8lynhvtw export type ImageURISource = $ReadOnly<{ + /** + * `uri` is a string representing the resource identifier for the image, which + * could be an http address, a local file path, or the name of a static image + * resource (which should be wrapped in the `require('./path/to/image.png')` + * function). + */ uri?: ?string, + + /** + * `bundle` is the iOS asset bundle which the image is included in. This + * will default to [NSBundle mainBundle] if not set. + * @platform ios + */ bundle?: ?string, + + /** + * `method` is the HTTP Method to use. Defaults to GET if not specified. + */ method?: ?string, + + /** + * `headers` is an object representing the HTTP headers to send along with the + * request for a remote image. + */ headers?: ?Object, + + /** + * `body` is the HTTP body to send with the request. This must be a valid + * UTF-8 string, and will be sent exactly as specified, with no + * additional encoding (e.g. URL-escaping or base64) applied. + */ body?: ?string, + + /** + * `cache` determines how the requests handles potentially cached + * responses. + * + * - `default`: Use the native platforms default strategy. `useProtocolCachePolicy` on iOS. + * + * - `reload`: The data for the URL will be loaded from the originating source. + * No existing cache data should be used to satisfy a URL load request. + * + * - `force-cache`: The existing cached data will be used to satisfy the request, + * regardless of its age or expiration date. If there is no existing data in the cache + * corresponding the request, the data is loaded from the originating source. + * + * - `only-if-cached`: The existing cache data will be used to satisfy a request, regardless of + * its age or expiration date. If there is no existing data in the cache corresponding + * to a URL load request, no attempt is made to load the data from the originating source, + * and the load is considered to have failed. + * + * @platform ios + */ cache?: ?('default' | 'reload' | 'force-cache' | 'only-if-cached'), + + /** + * `width` and `height` can be specified if known at build time, in which case + * these will be used to set the default `` component dimensions. + */ width?: ?number, height?: ?number, + + /** + * `scale` is used to indicate the scale factor of the image. Defaults to 1.0 if + * unspecified, meaning that one image pixel equates to one display point / DIP. + */ scale?: ?number, }>; diff --git a/Libraries/Image/ImageSourcePropType.js b/Libraries/Image/ImageSourcePropType.js deleted file mode 100644 index 0665c2e108b3fa..00000000000000 --- a/Libraries/Image/ImageSourcePropType.js +++ /dev/null @@ -1,90 +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. - * - * @no-flow - * @format - */ -'use strict'; - -const PropTypes = require('prop-types'); - -const ImageURISourcePropType = PropTypes.shape({ - /** - * `uri` is a string representing the resource identifier for the image, which - * could be an http address, a local file path, or the name of a static image - * resource (which should be wrapped in the `require('./path/to/image.png')` - * function). - */ - uri: PropTypes.string, - /** - * `bundle` is the iOS asset bundle which the image is included in. This - * will default to [NSBundle mainBundle] if not set. - * @platform ios - */ - bundle: PropTypes.string, - /** - * `method` is the HTTP Method to use. Defaults to GET if not specified. - */ - method: PropTypes.string, - /** - * `headers` is an object representing the HTTP headers to send along with the - * request for a remote image. - */ - headers: PropTypes.objectOf(PropTypes.string), - /** - * `body` is the HTTP body to send with the request. This must be a valid - * UTF-8 string, and will be sent exactly as specified, with no - * additional encoding (e.g. URL-escaping or base64) applied. - */ - body: PropTypes.string, - /** - * `cache` determines how the requests handles potentially cached - * responses. - * - * - `default`: Use the native platforms default strategy. `useProtocolCachePolicy` on iOS. - * - * - `reload`: The data for the URL will be loaded from the originating source. - * No existing cache data should be used to satisfy a URL load request. - * - * - `force-cache`: The existing cached data will be used to satisfy the request, - * regardless of its age or expiration date. If there is no existing data in the cache - * corresponding the request, the data is loaded from the originating source. - * - * - `only-if-cached`: The existing cache data will be used to satisfy a request, regardless of - * its age or expiration date. If there is no existing data in the cache corresponding - * to a URL load request, no attempt is made to load the data from the originating source, - * and the load is considered to have failed. - * - * @platform ios - */ - cache: PropTypes.oneOf([ - 'default', - 'reload', - 'force-cache', - 'only-if-cached', - ]), - /** - * `width` and `height` can be specified if known at build time, in which case - * these will be used to set the default `` component dimensions. - */ - width: PropTypes.number, - height: PropTypes.number, - /** - * `scale` is used to indicate the scale factor of the image. Defaults to 1.0 if - * unspecified, meaning that one image pixel equates to one display point / DIP. - */ - scale: PropTypes.number, -}); - -const ImageSourcePropType = PropTypes.oneOfType([ - ImageURISourcePropType, - // Opaque type returned by require('./image.jpg') - PropTypes.number, - // Multiple sources - PropTypes.arrayOf(ImageURISourcePropType), -]); - -module.exports = ImageSourcePropType; diff --git a/Libraries/Inspector/ElementProperties.js b/Libraries/Inspector/ElementProperties.js index 4c83062874bd13..9b6c222ed5babd 100644 --- a/Libraries/Inspector/ElementProperties.js +++ b/Libraries/Inspector/ElementProperties.js @@ -26,7 +26,7 @@ const openFileInEditor = require('openFileInEditor'); import type {ViewStyleProp} from 'StyleSheet'; type Props = $ReadOnly<{| - hierarchy: Array<$FlowFixMe>, + hierarchy: Array<{|name: string|}>, style?: ?ViewStyleProp, source?: ?{ fileName?: string, diff --git a/Libraries/Inspector/InspectorPanel.js b/Libraries/Inspector/InspectorPanel.js index 9e309bacc0d457..42c191d7ed530c 100644 --- a/Libraries/Inspector/InspectorPanel.js +++ b/Libraries/Inspector/InspectorPanel.js @@ -14,14 +14,43 @@ const ElementProperties = require('ElementProperties'); const NetworkOverlay = require('NetworkOverlay'); const PerformanceOverlay = require('PerformanceOverlay'); const React = require('React'); -const PropTypes = require('prop-types'); const ScrollView = require('ScrollView'); const StyleSheet = require('StyleSheet'); const Text = require('Text'); const TouchableHighlight = require('TouchableHighlight'); const View = require('View'); -class InspectorPanel extends React.Component<$FlowFixMeProps> { +import type {ViewStyleProp} from 'StyleSheet'; + +type Props = $ReadOnly<{| + devtoolsIsOpen: boolean, + inspecting: boolean, + setInspecting: (val: boolean) => void, + perfing: boolean, + setPerfing: (val: boolean) => void, + touchTargeting: boolean, + setTouchTargeting: (val: boolean) => void, + networking: boolean, + setNetworking: (val: boolean) => void, + hierarchy?: ?Array<{|name: string|}>, + selection?: ?number, + setSelection: number => mixed, + inspected?: ?$ReadOnly<{| + style?: ?ViewStyleProp, + frame?: ?$ReadOnly<{| + top?: ?number, + left?: ?number, + width?: ?number, + height: ?number, + |}>, + source?: ?{| + fileName?: string, + lineNumber?: number, + |}, + |}>, +|}>; + +class InspectorPanel extends React.Component { renderWaiting() { if (this.props.inspecting) { return ( @@ -40,6 +69,7 @@ class InspectorPanel extends React.Component<$FlowFixMeProps> { style={this.props.inspected.style} frame={this.props.inspected.frame} source={this.props.inspected.source} + // $FlowFixMe: Hierarchy should be non-nullable hierarchy={this.props.hierarchy} selection={this.props.selection} setSelection={this.props.setSelection} @@ -57,22 +87,22 @@ class InspectorPanel extends React.Component<$FlowFixMeProps> { {!this.props.devtoolsIsOpen && contents} -