Compare commits

...
Author SHA1 Message Date
Mike Grabowski 60b3942389 [0.58.0-rc.3] Bump version numbers 2019-01-17 16:02:13 +01:00
Mike Grabowski 9151e0d400 Revert "[0.58.0-rc.3] Bump version numbers"
This reverts commit 22af50ad95.
2019-01-17 16:02:05 +01:00
Mike Grabowski 22af50ad95 [0.58.0-rc.3] Bump version numbers 2019-01-17 15:40:47 +01:00
gengjiawenandMike Grabowski 0244caf513 Fix ReactAndroid bundle issue (#22799)
Summary:
Related change: https://github.com/facebook/react-native/commit/0a293a014bc8ef11191829a79a7419a3fa448852.

Changelog:
----------

[Bugfix] [Android] - fix 64bit so bundle issue.
Pull Request resolved: https://github.com/facebook/react-native/pull/22799

Differential Revision: D13669711

Pulled By: hramos

fbshipit-source-id: 0234b4731db0c74c8e4b8b738a19ae971fadb702
2019-01-17 11:29:27 +01:00
Mike Grabowski fb4e4fd099 evert "Remove unused files and code for old JSC and gcc build (#23014)"
This reverts commit bbf439862c.
2019-01-17 10:53:19 +01:00
Mike Grabowski 4ff693b93b Re-trigger Android build 2019-01-16 20:31:06 +01:00
Kudo ChienandMike Grabowski bbf439862c Remove unused files and code for old JSC and gcc build (#23014)
Summary:
----------

1. Unused prebuilt old JSC for 64bits.
2. Folly patch for gcc build.
Pull Request resolved: https://github.com/facebook/react-native/pull/23014

Differential Revision: D13690139

Pulled By: cpojer

fbshipit-source-id: 64555f5b9a5fbd4156e42eeff13da721846c2521
2019-01-16 16:46:05 +01:00
Thibault MalbrancheandMike Grabowski 54e82a8c42 Added WebView deprecation warning (#22980)
Summary:
Changelog:
----------

Help reviewers and the release process by writing your own changelog entry. See http://facebook.github.io/react-native/docs/contributing#changelog for an example.

[General] [Deprecated] - Deprecation warning for WebView as it has been extracted from core.
Pull Request resolved: https://github.com/facebook/react-native/pull/22980

Differential Revision: D13664505

Pulled By: hramos

fbshipit-source-id: 0cfc06015e77c52bed9eeebd97c8cbca6eacd8ce
2019-01-16 16:44:00 +01:00
Monte ThakkarandMike Grabowski dbdb509f26 Updated RedBox screen (#22242)
Summary:
[Re: RedBox screen is a bit scary - Discussions and Proposals](https://github.com/react-native-community/discussions-and-proposals/issues/42)

Per hramos:
> The RedScreen was inspired by Ruby on Rails's error screen

> I do see the RedBox screen could be made less jarring while still successfully displaying all the information we need.

Hence jamonholmgren came up with the idea that only the header & footer of the RedBox screen could be red. This makes the content a bit more readable as well as makes the screen a little less intimidating.

Also frantic made the suggestion that since the bottom buttons are not as important, they don't need to stand out. Hence only the header of the RedBox screen which displays the error is made red.

Screenshots:
----------

<div style="flex-direction: row">
<img width="325" alt="orginal" src="https://user-images.githubusercontent.com/7840686/48322916-b4958b80-e5de-11e8-9276-33378d1b41c5.png">
<img width="320" alt="redbox_v2_ios" src="https://user-images.githubusercontent.com/7840686/48665300-cce32b80-ea60-11e8-8e8f-88f74bad30ca.png">

</div>

<div style="flex-direction: row">
<img width="300" alt="original_android" src="https://user-images.githubusercontent.com/7840686/48322958-d5f67780-e5de-11e8-891c-1b20bd00e67b.png">
<img width="300" alt="redbox_v2_android" src="https://user-images.githubusercontent.com/7840686/48665312-f13f0800-ea60-11e8-9fb6-47e03c809789.png">

</div>
Pull Request resolved: https://github.com/facebook/react-native/pull/22242

Reviewed By: hramos

Differential Revision: D13564287

Pulled By: cpojer

fbshipit-source-id: fcb6ba5e20d863f4b957d20f3787f5b7a365bfdb
2019-01-16 16:43:37 +01:00
DulmandakhandMike Grabowski 34a585e093 bump okhttp to 3.12.1 (#22877)
Summary:
Bump OkHTTP to 3.12.1.

Changelog:
----------
[Android] [Changed] - bump OkHTTP 3.12.1
Pull Request resolved: https://github.com/facebook/react-native/pull/22877

Differential Revision: D13639172

Pulled By: hramos

fbshipit-source-id: 780d10207877637592ea3eb25eff445bc2986f91
2019-01-16 16:43:10 +01:00
Edward KarunaandMike Grabowski 7546aeaf8d Copy bundled resources and js in Android App Bundle builds (#21738)
Summary:
Android App Bundle builds use the packageBundle and bundle tasks instead
of the package and assemble tasks the APK builds use. Because of this,
the resources and js bundles weren't getting copied into the final
artifact. In an App Bundle build, the merged assets must be present
during the buildPreBundle step in order to arrive in the App Bundle.
Pull Request resolved: https://github.com/facebook/react-native/pull/21738

Differential Revision: D13669288

Pulled By: cpojer

fbshipit-source-id: 0e985983f04504b69e447dbc1f3f34cf8f4eb927
2019-01-16 16:38:34 +01:00
Mike Grabowski d25e304bcc [0.58.0-rc.2] Bump version numbers 2019-01-03 23:19:14 +01:00
Mike Grabowski c162c89edf Attempt fixing Detox 2019-01-03 22:57:50 +01:00
Mike Grabowski 57c6403048 Trigger tests 2019-01-03 22:23:26 +01:00
Mike Grabowski c8b1bdb88e Fix missing header on single-example pages 2019-01-03 21:55:50 +01:00
Mike Grabowski c88a7ca24a Do not display filter when doing snapshot tests on iOS 2019-01-03 21:48:46 +01:00
Mike Grabowski e0093fc98d Revert "Update some snapshots, still need to run tvOS and iOS 10"
This reverts commit 19c3a08ca8.
2019-01-03 19:34:07 +01:00
Mike Grabowski 19c3a08ca8 Update some snapshots, still need to run tvOS and iOS 10 2019-01-03 19:33:05 +01:00
Mike Grabowski e29ca07749 Ignore a Flow error 2019-01-03 19:21:18 +01:00
Mike Grabowski 54cb03c8d6 Fix a ESLint error 2019-01-03 19:13:30 +01:00
Josh JusticeandMike Grabowski bd79303d5b Added filtering to RNTester example screens (#22777)
Summary:
This PR adds filtering functionality to individual example screens of RNTester. This is useful for Detox testing of RNTester, since Detox requires elements to be visible on the screen before they can be interacted with. Instead of needing to scroll an arbitrary amount, the test can enter the name of the example to be tested, just as is done on the main screen. This will lead to simpler and more reliable E2E tests for long example screens. This PR doesn't add any automated tests using the filter; those will be added in a separate PR.

This is implemented by extracting the existing filtering functionality out of `RNTesterExampleList` into a shared `RNTesterExampleFilter` component that can be used both within `RNTesterExampleList` (the main screen) and `RNTesterExampleContainer` (the example screen).

![simulator screen shot - iphone 8 - 2018-12-24 at 08 22 46](https://user-images.githubusercontent.com/15832198/50401564-4273a300-0755-11e9-9120-9bf8fbb70261.png)

![simulator screen shot - iphone 8 - 2018-12-24 at 08 22 51](https://user-images.githubusercontent.com/15832198/50401566-44d5fd00-0755-11e9-9637-6e5ddce1c476.png)

Changelog:
----------

[General] [Added] - Added filtering to RNTester example screens
Pull Request resolved: https://github.com/facebook/react-native/pull/22777

Reviewed By: TheSavior

Differential Revision: D13561744

Pulled By: rickhanlonii

fbshipit-source-id: cb120626a8e2b8440f88b871557c0b92fbef5edc
2019-01-03 18:58:05 +01:00
Josh JusticeandMike Grabowski 68f6325849 Fix failing Switch E2E tests (#22698)
Summary:
Switch E2E tests have been failing on master, although they pass locally.

Changelog:
----------

Help reviewers and the release process by writing your own changelog entry. See http://facebook.github.io/react-native/docs/contributing#changelog for an example.

[General] [Fixed] - Fix failing Switch E2E tests
Pull Request resolved: https://github.com/facebook/react-native/pull/22698

Differential Revision: D13511917

Pulled By: hramos

fbshipit-source-id: b2f5cac1927531a855699e34e1a37036773f0aad
2019-01-03 18:57:21 +01:00
Josh JusticeandMike Grabowski 1c22c10aa2 Remove persistence from RNTester app (#22596)
Summary:
Previously the RNTester app saved what screen you were on and what filter text was entered into the initial screen. This made e2e testing complex, as each test needed to manually restore the state to the home screen. If the state ever got out of sync with the test's expectations, it could lead to multiple failed tests.

There is still one specific component that uses persistence: `RNTesterSettingSwitchRow`. Persistence can be removed from this component next time tests for it are updated. As a result, `RNTesterStatePersister` is not yet entirely removed from the app.
Pull Request resolved: https://github.com/facebook/react-native/pull/22596

Differential Revision: D13413457

Pulled By: cpojer

fbshipit-source-id: 3faa26a94139397b4bce6b62ff43e9c2f870b145
2019-01-03 18:57:17 +01:00
Héctor RamosandMike Grabowski 1df4713e9a test_ios → : Update iOS Snapshots, remove tvOS tests, disable failing tests (#22720)
Summary:
The following tests are disabled in this PR:

- testTimersTest is failing due to undefined this.setTimeout, probably introduced back in 61346d3. Tracking a fix in https://github.com/facebook/react-native/issues/22695
- testTheTester_ExpectError is failing as RCTTestRunner is not properly passing through the error. Tracking a fix in https://github.com/facebook/react-native/issues/22697

I've added a comment regarding testWebSocketTest and how to ensure it passes locally.

This PR also fixes all remaining snapshot tests, which were failing due to the use of iPhone XS as a iOS Simulator on Circle CI. We are using iPhone 6s for SST internally, and this allows us to be consistent.
Pull Request resolved: https://github.com/facebook/react-native/pull/22720

Differential Revision: D13532788

Pulled By: hramos

fbshipit-source-id: 75681236032839bf88180611ee68826b53cc96eb
2018-12-24 13:45:34 +01:00
Radek CzemerysandMike Grabowski f09ab6df25 Remove ActivityIndicator from ScrollView snapshot tests (#22729)
Summary:
`ActivityIndicator` was not consistent when running snapshot tests so I removed it.

From diff:
![image](https://user-images.githubusercontent.com/7029942/50274094-9c662700-043c-11e9-9cac-ccc1b69695c1.png)

Changelog:
----------

[iOS] [FIXED] - Fixed ScrollViewExample snapshot tests
Pull Request resolved: https://github.com/facebook/react-native/pull/22729

Differential Revision: D13528756

Pulled By: hramos

fbshipit-source-id: 747d91ad6a8fb8f0aa8022496bd8855a90710142
2018-12-24 13:44:40 +01:00
Héctor RamosandMike Grabowski 94e7a10141 Update RNTester snapshots
Summary:
The iOS snapshots have been out of date for months, but the failure was not caught in open source's  `test_objc` job because `xcpretty` was swallowing the non-zero error code.

To fix this, I enabled recording mode in RNTesterSnapshotTests.m temporarily, and re-ran the tests in order to update the snapshots. I've also switched the test device used by Circle CI to iPhone 6s to be consistent with the snapshot tests that run internally at Facebook.

Integration tests are not fully fixed yet, but I can confirm the following tests are fixed by this diff:

```
-[RNTesterIntegrationTests testImageSnapshotTest]
-[RNTesterIntegrationTests testSimpleSnapshotTest]
-[RNTesterSnapshotTests testARTExample]
-[RNTesterSnapshotTests testLayoutExample]
-[RNTesterSnapshotTests testSliderExample]
-[RNTesterSnapshotTests testSwitchExample]
-[RNTesterSnapshotTests testTabBarExample]
-[RNTesterSnapshotTests testTextExample]
-[RNTesterSnapshotTests testViewExample]
```

I've also fixed a few shellcheck warnings in related scripts.

Reviewed By: fkgozali

Differential Revision: D13506865

fbshipit-source-id: dab985130c2ff3cb9dea19d1f87c8ee65d8c141e
2018-12-24 13:43:37 +01:00
Mike Grabowski be40199f13 §Revert "[0.58.0-rc.2] Bump version numbers"
This reverts commit 6ae2ebfcab.
2018-12-19 14:00:56 +01:00
Héctor RamosandMike Grabowski e4fffa281e Fix RNTesterUnitTests failure (#22658)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/22658

Add JavaScriptCore.framework to RNTester's RNTesterUnitTests target. This resolves the failure seen when running `scripts/objc-test-ios.sh test` seen in Circle CI.

 See D9875409 for a related diff (https://github.com/facebook/react-native/commit/78fcf7c5598ce7f5d0d62110eb34fe5a4b962e71 in open source).

Without this diff, `scripts/objc-test-ios.sh test` would fail with the following error (see Circle https://circleci.com/gh/facebook/react-native/63704):

```
�  ld: symbol(s) not found for architecture x86_64

�  clang: error: linker command failed with exit code 1 (use -v to see invocation)

Testing failed:
	"_JSObjectGetPrototype", referenced from:
	"_JSObjectSetPrototype", referenced from:
	"_JSPropertyNameAccumulatorAddName", referenced from:
	"_JSObjectCopyPropertyNames", referenced from:
	"_JSContextGetGlobalObject", referenced from:
	"_JSValueMakeString", referenced from:
	"_JSValueIsNumber", referenced from:
	"_JSClassCreate", referenced from:
	"_JSObjectGetPropertyAtIndex", referenced from:
	"_JSObjectMakeArray", referenced from:
	"_JSEvaluateScript", referenced from:
	"_JSValueIsUndefined", referenced from:
	"_JSPropertyNameArrayGetCount", referenced from:
	"_JSPropertyNameArrayGetNameAtIndex", referenced from:
	"_JSPropertyNameArrayRelease", referenced from:
	"_JSValueMakeUndefined", referenced from:
	"_JSValueMakeNull", referenced from:
	"_JSStringCreateWithUTF8CString", referenced from:
	"_JSObjectSetProperty", referenced from:
	"_JSObjectHasProperty", referenced from:
	"_kJSClassDefinitionEmpty", referenced from:
	"_JSObjectIsFunction", referenced from:
	"_JSValueIsBoolean", referenced from:
	"_JSValueIsInstanceOfConstructor", referenced from:
	"_JSValueIsObjectOfClass", referenced from:
	"_JSValueToNumber", referenced from:
	"_JSGlobalContextRelease", referenced from:
	"_JSValueToBoolean", referenced from:
	"_JSValueIsArray", referenced from:
	"_JSValueMakeNumber", referenced from:
	"_JSObjectSetPrivate", referenced from:
	"_JSValueIsNull", referenced from:
	"_JSObjectSetPropertyAtIndex", referenced from:
	"_JSValueIsObject", referenced from:
	"_JSValueMakeBoolean", referenced from:
	"_JSValueUnprotect", referenced from:
	"_JSValueToStringCopy", referenced from:
	"_JSObjectGetProperty", referenced from:
	"_JSValueToObject", referenced from:
	"_JSObjectGetPrivate", referenced from:
	"_JSStringRelease", referenced from:
	"_JSGlobalContextRetain", referenced from:
	"_JSStringIsEqual", referenced from:
	"_JSStringGetMaximumUTF8CStringSize", referenced from:
	"_JSObjectCallAsFunction", referenced from:
	"_JSStringGetUTF8CString", referenced from:
	"_JSValueProtect", referenced from:
	"_JSValueIsString", referenced from:
	"_JSStringRetain", referenced from:
	"_JSObjectMake", referenced from:
	"_JSGlobalContextCreateInGroup", referenced from:
	"_JSObjectCallAsConstructor", referenced from:
	Linker command failed with exit code 1 (use -v to see invocation)
	Testing cancelled because the build failed.
** TEST FAILED **
```

Reviewed By: fkgozali

Differential Revision: D13474936

fbshipit-source-id: b12ddd6dcb95a7a588463d74cc0798dd591bdd78
2018-12-19 10:59:22 +01:00
Mike Grabowski 6ae2ebfcab [0.58.0-rc.2] Bump version numbers 2018-12-18 19:35:57 +01:00
Héctor RamosandMike Grabowski b8c0d9d289 Bump RN OSS iOS tests to iOS SDK 12.1, Xcode 10.1
Summary:
Use Xcode 10.1 and iOS 12.1 SDK to run iOS tests on an iOS 12.1 iPhone XS Simulator, all of which are available on a default Xcode 10.1 install.

Note that we were previously running iOS tests using Xcode 10.1 and the 12.1 SDK in a separate `test_xcode10` workflow on Circle CI. This was in place to allow us to track Xcode 10 compatibility during the Xcode 10 beta. Now that Xcode 10 has been public for a while, we can drop the compatibility check and use Xcode 10 in our main iOS test workflow.

Reviewed By: TheSavior

Differential Revision: D13317891

fbshipit-source-id: 04c17bf3a2e9d3617f14a46b4ed30a5491a4f4a4
2018-12-18 19:34:40 +01:00
Mike Grabowski 7c04c09923 Revert "[0.58.0-rc.2] Bump version numbers"
This reverts commit 8c3111af31.
2018-12-18 19:32:08 +01:00
Mike Grabowski 8c3111af31 [0.58.0-rc.2] Bump version numbers 2018-12-18 14:48:35 +01:00
Mike Grabowski 26af339a47 Fix bad application of windows ci commit 2018-12-17 19:57:30 +01:00
Sunny LuoandMike Grabowski 76fc78e740 Use relative path for SCRIPTDIR (#22598)
Summary:
Fixes https://github.com/facebook/react-native/issues/22521

The current approach has an issue with white spaces when compiling in Xcode 10.1

![space](https://user-images.githubusercontent.com/615282/49782648-07836f80-fd52-11e8-952f-b93f8c593c60.png)

Change back to relative path fixes this issue
Pull Request resolved: https://github.com/facebook/react-native/pull/22598

Differential Revision: D13421446

Pulled By: hramos

fbshipit-source-id: 688157b2e951399059cb6c95e2a6ce8d176e9b9c
2018-12-17 19:55:28 +01:00
SalakarandMike Grabowski 1d949a12fa Allow 'userInfo' for native promise.reject + add native error stack support (#20940)
Summary:
As mentioned [here](https://github.com/react-native-community/react-native-releases/issues/34#issuecomment-417718601), Android is missing native Promise reject with a `userInfo` `WritableMap` support and also `nativeStack` support (which addresses `TODO(8850038)`). This PR adds Android support for both of these.

React Native on iOS ([here](https://github.com/facebook/react-native/blob/master/React/Base/RCTUtils.m#L433)) and Windows ([here](https://github.com/Microsoft/react-native-windows/pull/732)) already support this so this is a relatively minor addition to bring Android in line with the other platforms. (JS support is also [here](https://github.com/facebook/react-native/blob/master/Libraries/BatchedBridge/NativeModules.js#L145-L148))

Existing methods remain unchanged other than general cleanup of variable names (`e -> throwable`) and adding code comments/docs.

Additionally, the `ShareTestModule` implementation of Promise (SimplePromise) was updated to reflect these changes - other line changes in this file are from formatting in Android Studio - if this is an issue let me know.

 - Currently inconsistent with other platforms.
 - Blocking a couple of issues over at [invertase/react-native-firebase](https://github.com/invertase/react-native-firebase) - save for re-writing everything to Promise resolve only - which is no small change and isn't a great solution either.
Pull Request resolved: https://github.com/facebook/react-native/pull/20940

Differential Revision: D13412527

Pulled By: cpojer

fbshipit-source-id: 2ca6c5f3db9ff2c2986b02edda80bc73432f66d3
2018-12-17 19:55:10 +01:00
Salil ApteandMike Grabowski 8302e0cd8f Fixes animated gifs incorrectly looping/not stopping on last frame (#21999)
Summary:
Currently, if you load an animated gif using the standard `Image` component, it will not correctly respect the loop count property found in the Netscape App Extension block of the file. The issues are as follows:

1) If the App Extension isn't present, the animated gif loops indefinitely when it should not loop at all.
2) If the App Extension is present, the animated gif loops one less time than it should.

The other issue is that once the looping completes, the image doesn't pause at the last frame but instead, loops back to the beginning of the animation e.g. frame 1.

The fix does a few things:

1) If there is _no_ App Extension present, the image doesn't loop at all
2) If there _is_ an App Extension present, it loops the correct amount of times. For instance, if the loop count is 1, it means the gif should loop _once_ after it finishes playing, for a total of _two_ total loops.
3) Once the number of loops completes (assuming loop count isn't set to 0 which means infinite), the animation pauses on the last frame.
Pull Request resolved: https://github.com/facebook/react-native/pull/21999

Differential Revision: D13287005

Pulled By: hramos

fbshipit-source-id: f7210ad40e0e76c9ec454953b8a067569d3feaaa
2018-12-17 19:54:19 +01:00
Igor MandriginandMike Grabowski e3b7e81c8c Avoid using -[UITextView setAttributedString:] while user is typing (#19809)
Summary:
iOS-specific.
For languages with complex input (such as Japanese or Chinese), a user has to type multiple characters that are then merged into a single one.
If `-[UITextView setAttributedString:]` is used while the user is still typing, it resets the input and characters are not being treated as typed together.

This PR avoids calling this method if possible, replacing it by just copying the attributes if the string has not been changed. That preserves the state and user can continue to type Korean or Chinese characters.

Fixes #19339

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

<!--
  Required: Write your test plan here. If you changed any code, please provide us with
  clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
-->

Essentially, the steps to reproduce are described in [the issue](https://github.com/facebook/react-native/issues/19339):

1. Type some Korean characters in TextInput, such as "하늘" (buttons `ㅎ`,`ㅏ`,`ㄴ`,`ㅡ`,`ㄹ`).
2. Then move the cursor to the beginning of the text, type "파란" (buttons `ㅍ`,`ㅏ`,`ㄹ`,`ㅏ`,`ㄴ`) this time.

**Behaviour before this fix (broken)**
Actual text: `ㅍㅏㄹㅏㄴ하늘`.
Expected text: `파란하늘`.
Characters aren't combined properly.

![ezgif com-resize](https://user-images.githubusercontent.com/466427/41613572-4256dda8-73f6-11e8-99a9-0ab833202b95.gif)

**Behaviour after this fix (correct)**
Actual text: `파란하늘`.
Expected text: `파란하늘`.
Characters are combined, the same behaviour is in vanilla iOS `UITextView`.

![input-with-fix](https://user-images.githubusercontent.com/466427/41613526-1aae2284-73f6-11e8-87f2-c1cef51cd83a.gif)

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[IOS] [BUGFIX] [TextView] - Fix Korean/Chinese/Japanese input for multiline TextView on iOS.

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Pull Request resolved: https://github.com/facebook/react-native/pull/19809

Differential Revision: D13326614

Pulled By: shergin

fbshipit-source-id: 6a5cab3f7290f0f623a6f4c29353a573eb321b0b
2018-12-17 19:53:46 +01:00
Max ShermanandMike Grabowski 2472e65b62 Record thread cpu time for native modules thread
Summary: I want the same instrumentation we did for the JS thread for the NM thread.  This diff adds thread cpu time.

Reviewed By: alexeylang

Differential Revision: D13328876

fbshipit-source-id: 7b310956c52907ffbd881f864e1f8e774853d7f5
2018-12-17 19:53:32 +01:00
Ian ParkandMike Grabowski 7709285708 Fix bug in comparison logic of object property (#22348)
Summary:
`instance.hasOwnProperty` has potential danger because of some object could be eliminate own prototype chain. Update code be more reliable.

This PR is solution of #22308 issue. (Fixes #22308)
Pull Request resolved: https://github.com/facebook/react-native/pull/22348

Differential Revision: D13334882

Pulled By: cpojer

fbshipit-source-id: 9b9310a972e933af1962666d7b0c683ff43cc5b2
2018-12-17 19:53:24 +01:00
Zack SheppardandMike Grabowski e7a52675cb Extend reason message for RCTFatalException (#22532)
Summary:
Fixes #22530

As described in the issue, the previous behavior for the `RCTFatal` macro was to truncate the `reason` on the resulting `NSException` to 75 characters. This would ensure the reason would fit on a single line, but resulted in issues debugging errors that occurred in the wild, as many crash logging tools (like Sentry) discard the `name` value of the exception and use the `reason` as their primary identifier. At 75 characters, useful information like the location of the error would usually be truncated.

- [x] This extends the truncation threshold to 175 characters, which should be short enough to prevent full-screen-takeover length errors, but long enough to provide useful context to the error.
- [x] This adds a `userInfo` value to the resulting `NSException`. It copies over the `userInfo` from the `NSError` passed to the macro, and adds an "untruncated message" value that contains the untruncated version of the `NSException`'s reason.

[iOS] [Changed] - RCTFatalExceptions now include more information in their reason and a userInfo.

<!--

  CATEGORY may be:

  - [General]
  - [iOS]
  - [Android]

  TYPE may be:

  - [Added] for new features.
  - [Changed] for changes in existing functionality.
  - [Deprecated] for soon-to-be removed features.
  - [Removed] for now removed features.
  - [Fixed] for any bug fixes.
  - [Security] in case of vulnerabilities.

  For more detail, see https://keepachangelog.com/en/1.0.0/#how

  MESSAGE may answer "what and why" on a feature level. Use this to briefly tell React Native users about notable changes.

  EXAMPLES:

  [General] [Added] - Add snapToOffsets prop to ScrollView component
  [General] [Fixed] - Fix various issues in snapToInterval on ScrollView component
  [iOS] [Fixed] - Fix crash in RCTImagePicker

-->
Pull Request resolved: https://github.com/facebook/react-native/pull/22532

Differential Revision: D13373469

Pulled By: cpojer

fbshipit-source-id: ac140d14ce76e1664869437c2c178bdd65ab6e0e
2018-12-17 19:53:16 +01:00
Elliott SprehnandMike Grabowski 06dc51f8a9 Don't crash on second resolve or reject in PromiseImpl. (#20303)
Summary:
Promise semantics per JS should allow calling resolve or reject repeatedly without crashing. Only the first one should do anything, but others should be allowed. This change fixes the Java bridge for Android. A separate change is needed for iOS.

Issue #20262
Pull Request resolved: https://github.com/facebook/react-native/pull/20303

Differential Revision: D13396975

Pulled By: cpojer

fbshipit-source-id: 81f14f73654fa7c44e043f574a39fda481ace44b
2018-12-17 19:53:08 +01:00
Albert SunandMike Grabowski 319fa03125 Ensure RCTImageCache's DateFormatter is only allocated once
Summary: This change attempts to fix a crash within RCTImageCache's new dateWithHeaderString method. This is a speculative fix as there aren't any concrete repro steps.

Reviewed By: hramos

Differential Revision: D13278666

fbshipit-source-id: cdb69b1296c946d89e14c074329280994d87ddcd
2018-12-17 19:52:53 +01:00
David VaccaandMike Grabowski 3c454eef8f Fix NPE when opening Google Search Assist when a RN Dialog is displayed
Summary:
This fixes app crashes on opening android search assistant when a RN modal is visible. The root cause is that ViewGroup.dispatchProvideStructure() method uses the private variable 'mChildren' to access the children of a view group instead of the publicApi.

This fixes the top crash for the react_MarketplaceProductDetailsNonIPadRoute route.

This also fixes github issues:
https://github.com/facebook/react-native/issues/15932
https://github.com/facebook/react-native/issues/13201
https://github.com/facebook/react-native/issues/15440

that were closed without a fix

Reviewed By: PeteTheHeat

Differential Revision: D13375993

fbshipit-source-id: d603cb4ef65a423c63a6ef2b51235702c7dbffcb
2018-12-17 19:52:45 +01:00
David VaccaandMike Grabowski c43b7b93b2 fix possible NPE in StatusBarModule
Summary:
This diff fixes a NPE happening in StatusBarModule when the style passed by parameter is null.
Even if JS shoulnd't send a null value, this method should not crash with an NPE. I'm not changing behavior, only avoiding NPE when status is null

Reviewed By: RSNara

Differential Revision: D13287057

fbshipit-source-id: cc5ac4e97083d63f2bf65c03bac0dc9bce976423
2018-12-17 19:52:39 +01:00
Ivan FilenkoandMike Grabowski d8f28ceef8 Bump ws package to 1.1.5 due to vulnerability issues (#21769)
Summary:
Update `ws` package from 1.1.0 to 1.1.5 due to vulnerability issues.

Here is `npm audit` report:
```

                       === npm audit security report ===

┌──────────────────────────────────────────────────────────────────────────────┐
│                                Manual Review                                 │
│            Some vulnerabilities require your attention to resolve            │
│                                                                              │
│         Visit https://go.npm.me/audit-guide for additional guidance          │
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Denial of Service                                            │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ ws                                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >= 1.1.5 <2.0.0 || >=3.3.1                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ c635d8a886cde7688a0123f573cc5b1f0430780052ba848c8fa1dc8a4c3… │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ c635d8a886cde7688a0123f573cc5b1f0430780052ba848c8fa1dc8a4c3… │
│               │ > react-devtools-core > ws                                   │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/550                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
```
Pull Request resolved: https://github.com/facebook/react-native/pull/21769

Reviewed By: hramos

Differential Revision: D10379892

Pulled By: cpojer

fbshipit-source-id: 9d03f8231a90c5f55eb95ccac029aedd45a49a2d
2018-12-17 19:52:32 +01:00
Héctor RamosandMike Grabowski 370fde33da Propagate exit code in test_objc (#22562)
Summary:
Any failures in `test_objc` within the objc-test.sh script have been kept hidden as `xcpretty` was swallowing the exit code from xcodebuild.

Fixes the issue TheSavior brought up in #22470 where failing snapshot tests were not reflected on Circle.

Run on Circle CI and confirm `test_objc` fails (iOS tests *are* broken on master).
Pull Request resolved: https://github.com/facebook/react-native/pull/22562

Differential Revision: D13406987

Pulled By: hramos

fbshipit-source-id: 3f3da01ab4c0ad87077813b06d2fdf788f32f6b8
2018-12-17 19:52:11 +01:00
Eli WhiteandMike Grabowski 1b302b3f2a Add detox tests for Switch (#22470)
Summary:
Reorganized some of the switch examples to be more testable:

Before:
![simulator screen shot - iphone xs - 2018-12-01 at 02 27 47](https://user-images.githubusercontent.com/249164/49327066-bcc35580-f510-11e8-860d-fc07a574f80c.png)

After:
![simulator screen shot - iphone xs - 2018-12-01 at 02 27 06](https://user-images.githubusercontent.com/249164/49327068-bf25af80-f510-11e8-95c6-7aa4a9095b91.png)

Tests pass!

```
yarn build-ios-e2e && yarn test-ios-e2e
```
<img width="711" alt="screen shot 2018-12-01 at 2 20 33 am" src="https://user-images.githubusercontent.com/249164/49327070-c64cbd80-f510-11e8-8cad-84c3fe42941e.png">

Changelog:
----------
Help reviewers and the release process by writing your own changelog entry. When the change doesn't impact React Native developers, it may be ommitted from the changelog for brevity. See below for an example.

[Internal] [Added] - Detox tests for Switch
Pull Request resolved: https://github.com/facebook/react-native/pull/22470

Reviewed By: RSNara

Differential Revision: D13290329

Pulled By: TheSavior

fbshipit-source-id: 91c1b895dd5e1acc4330618e6d3165c7f9215997
2018-12-17 19:50:51 +01:00
Héctor RamosandMike Grabowski 808a156769 Merge appveyor.yml with .appveyor/config.yml (#22529)
Summary:
A recent PR was merged with changes to appveyor.yml, but that file recently moved to .appveyor/config.yml
Pull Request resolved: https://github.com/facebook/react-native/pull/22529

Differential Revision: D13342085

Pulled By: hramos

fbshipit-source-id: d243e233ef769ab279dacdd48444248fbdec9417
2018-12-17 19:49:21 +01:00
Rick HanlonandMike Grabowski d1e312d8ce Fix ActivityIndicator snapshot test, add toMatchShallowSnapshot
Summary:
This diff adds a custom matcher which will wrap a given component and shallow render it, snapshotting the result with the formatting users will see when they do the same.

I also update the ActivityIndicator test to use this new strategy, and add an additional check that the displayName is set.

For context see:
- https://github.com/facebook/react-native/pull/21950
- https://github.com/rajivshah3/rn-broken-snapshot/blob/broken-example/__tests__/App.spec.js#L3
- https://github.com/facebook/react-native/issues/21937

Reviewed By: TheSavior

Differential Revision: D13326689

fbshipit-source-id: 8ed2302a8aad12962fa2498a46d2502ccfb5c737
2018-12-17 19:48:38 +01:00
Lea BärtschiandMike Grabowski cd8051c939 Remove trailing slash from origin header if no port is specified (#22290)
Summary:
Fixes #16304

The standard format for origin HTTP headers does not allow a trailing slash. In order to not get warnings when connecting a websocket, I removed the trailing slash when generating the default origin HTTP header for the websocket connect request.

Release Notes:
----------
[Android] [Fixed] - Fixed default origin header for websocket connections to match the standard format (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) in WebSocketModule
Pull Request resolved: https://github.com/facebook/react-native/pull/22290

Differential Revision: D13374345

Pulled By: cpojer

fbshipit-source-id: 1173241f2b6912fd6df5e196053a950bb42ff01b
2018-12-17 19:48:29 +01:00
gengjiawenandMike Grabowski cb85396fab fix windows ci
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/22557

Differential Revision: D13381568

Pulled By: hramos

fbshipit-source-id: db2ca0615c4cde5b0a4ae8ae824a005bcc1e2a1c
2018-12-17 19:48:11 +01:00
Rick HanlonandMike Grabowski 00c7c5ade1 Add e2e tests, bug fixes for testIDs (#22537)
Summary:
This PR adds e2e tests for the Picker and DatePicker components.

While writing these tests, I also found and fixed two bugs where we wern't passing the `testID` down to the native components, so detox couldn't look them up. This confirms what was mentioned by rotemmiz [here](https://github.com/wix/Detox/issues/798#issuecomment-401412276)
Pull Request resolved: https://github.com/facebook/react-native/pull/22537

Reviewed By: cpojer

Differential Revision: D13371307

Pulled By: rickhanlonii

fbshipit-source-id: a4dfcdb5913645bceca0c7353328eeb9ad0f6558
2018-12-17 19:46:46 +01:00
Josh JusticeandMike Grabowski 1fdfed51c3 Detox debug build (#22572)
Summary:
Adds a Detox configuration and instructions for running the app in development mode in Detox. This speeds up developing tests, because changes to production code don't require a full rebuild.
Pull Request resolved: https://github.com/facebook/react-native/pull/22572

Differential Revision: D13396883

Pulled By: cpojer

fbshipit-source-id: 186cc8d75eccae411b602cb0f68f0e11856e0743
2018-12-17 19:46:43 +01:00
Josh JusticeandMike Grabowski 0189ea2c2b Add Touchable E2E tests (#22570)
Summary:
Adds some initial tests for Touchable*. It only tests the first screen worth of examples; in a separate PR I'll work on an alternate way to "scroll" to individual examples in tests, before I add tests for the rest of the Touchable examples.

On the live stream where I began writing these tests, I reorganized the "Touchable feedback examples" to the top of the list so it would be on-screen for testing. I didn't include this reorganization or test in this PR; that can be added in once the "alternative to scrolling" is added in, to avoid having to reorganize.

Changelog:
----------
[General] [Added] - Add E2E tests for Touchable
Pull Request resolved: https://github.com/facebook/react-native/pull/22570

Differential Revision: D13400348

Pulled By: TheSavior

fbshipit-source-id: 821af135296049090427a16472cc14dabeb10ab4
2018-12-17 19:46:18 +01:00
gengjiawenandMike Grabowski 860d01a2c4 Enable ci for windows (#22028)
Summary:
Enable ci for windows
appveyor pass.
https://github.com/facebook/react-native/pull/21835
 [GENERAL] [INTERNAL] [CI] - Enable ci for windows
Pull Request resolved: https://github.com/facebook/react-native/pull/22028

Differential Revision: D13318242

Pulled By: cpojer

fbshipit-source-id: be4b9b9fe6a4e21572f3d6c38b15a2acf8bb2662
2018-12-17 19:45:59 +01:00
DulmandakhandMike Grabowski 8e39451512 Bump Android SDK to 28, Build Tools to 28.0.2, Gradle to 4.7, Gradle Plugin to 3.2.0 (#21632)
Summary:
This PR is bumping compileSdkVersion to 28, buildToolsVersion to 28.0.2, Gradle to 4.7, Android Gradle plugin to 3.2.0.

Gradle 4.7 added support for Java 10 and 11.

allow-large-files

Release Notes:
--------------
[ANDROID] [ENHANCEMENT] [SDK] - bump to 28

Pull Request resolved: https://github.com/facebook/react-native/pull/21632

Reviewed By: mdvacca

Differential Revision: D13084836

Pulled By: hramos

fbshipit-source-id: e0f493881e80e87faf8c3ef1ac77044495966a49
2018-12-17 19:44:58 +01:00
Mike Grabowski c0bf7a128c [0.58.0-rc.1] Bump version numbers 2018-12-06 09:39:36 +01:00
Tim YungandMike Grabowski e54d1e27ea React sync for revisions 3ff2c7c...6bf5e85
Summary:
@public
This sync includes the following changes:
- **[6bf5e8598](https://github.com/facebook/react/commit/6bf5e8598)**: Fix scheduler setTimeout() re-entrancy check (#14384) //<Brian Vaughn>//
- **[7a48c900b](https://github.com/facebook/react/commit/7a48c900b)**: Prevent a v8 deopt when profiling (#14383) //<Brian Vaughn>//
- **[f00c2755b](https://github.com/facebook/react/commit/f00c2755b)**: Removed unnecessary externals from Jest bundles (#14372) //<Brian Vaughn>//
- **[52bea95cf](https://github.com/facebook/react/commit/52bea95cf)**: Fixed scheduler setTimeout fallback (#14358) //<Brian Vaughn>//
- **[1d25aa578](https://github.com/facebook/react/commit/1d25aa578)**: [Fizz] New Server Rendering Infra (#14144) //<Sebastian Markbåge>//
- **[f1bf28160](https://github.com/facebook/react/commit/f1bf28160)**: Fix bug in cloneHook (#14364) //<Imre Osswald>//
- **[16e120438](https://github.com/facebook/react/commit/16e120438)**: [Fire] Add initial build infrastructure (#14359) //<Dan Abramov>//
- **[d14ba87b1](https://github.com/facebook/react/commit/d14ba87b1)**: Validate propTypes for lazy() and memo() and warn about invalid patterns (#14298) //<Dan Abramov>//
- **[4f964f09c](https://github.com/facebook/react/commit/4f964f09c)**: Adding isMemo check to react-is package (#14313) //<Jinto Jose>//
- **[c2a2d8a53](https://github.com/facebook/react/commit/c2a2d8a53)**: Remove useMutationEffect (#14336) //<Sophie Alpert>//
- **[48f1e5b3c](https://github.com/facebook/react/commit/48f1e5b3c)**: Add a null type test for memo (#14325) //<chun shang>//
- **[f93f3402f](https://github.com/facebook/react/commit/f93f3402f)**: Make useEffect(async) warning more verbose (#14327) //<Dan Abramov>//
- **[ee3ef3a07](https://github.com/facebook/react/commit/ee3ef3a07)**: Fix regression: Errors not emitted in streams (#14314) //<Pelle Wessman>//
- **[33f6f5e53](https://github.com/facebook/react/commit/33f6f5e53)**: Remove usage of `fbjs/lib/invariant` in ReactNativeViewConfigRegistry. (#14330) //<Christoph Nakazawa>//
- **[686f1060a](https://github.com/facebook/react/commit/686f1060a)**: Publish a local release (canary or stable) to NPM (#14260) //<Brian Vaughn>//
- **[7475120ce](https://github.com/facebook/react/commit/7475120ce)**: Prevent deopts from modifying exports object in stable builds (#14309) //<Dan Abramov>//
- **[0c7189d92](https://github.com/facebook/react/commit/0c7189d92)**: Fix resolution of outer props with React.memo() (#14312) //<Dan Abramov>//
- **[14be29b2b](https://github.com/facebook/react/commit/14be29b2b)**: Add more test coverage for nested memo() (#14311) //<Dan Abramov>//
- **[dc0dd4bbf](https://github.com/facebook/react/commit/dc0dd4bbf)**: Use |0 to coerce to number (#14297) //<Dan Abramov>//
- **[dd8205cef](https://github.com/facebook/react/commit/dd8205cef)**: List ignored types instead of included types in the stack (#14308) //<Dan Abramov>//
- **[a9fdf8a32](https://github.com/facebook/react/commit/a9fdf8a32)**: Warn about reassigning this.props (#14277) //<Dan Abramov>//
- **[327cf0ee3](https://github.com/facebook/react/commit/327cf0ee3)**: Fix support for mixing react-dom/server@16.6 and react@<16.6 (#14291) //<Dan Abramov>//
- **[c954efa70](https://github.com/facebook/react/commit/c954efa70)**: Remove `import * as` pattern from the codebase (#14282) //<Sebastian Markbåge>//
- **[ccb14e270](https://github.com/facebook/react/commit/ccb14e270)**: Fix SSR useCallback in render phase (#14279) //<Dan Abramov>//
- **[0e9cb3f5d](https://github.com/facebook/react/commit/0e9cb3f5d)**: Clear fields on unmount of fiber to avoid memory leak (#14276) //<Dominic Gannaway>//
- **[592676503](https://github.com/facebook/react/commit/592676503)**: Revert "Clear memoizedState on unmount of fiber to avoid memory leak (#14218)" (#14275) //<Dominic Gannaway>//
- **[9b2fb24f9](https://github.com/facebook/react/commit/9b2fb24f9)**: Clear memoizedState on unmount of fiber to avoid memory leak (#14218) //<Dominic Gannaway>//
- **[a22fabc2a](https://github.com/facebook/react/commit/a22fabc2a)**: Reduce scheduler serialization overhead (#14249) //<Jason Miller>//
- **[21d5f7d32](https://github.com/facebook/react/commit/21d5f7d32)**: Wrap shorthand CSS property collision warning in feature flag (#14245) //<Andrew Clark>//
- **[8feeed10d](https://github.com/facebook/react/commit/8feeed10d)**: [scheduler] Remove window.postMessage fallback //<Andrew Clark>//
- **[5bce0ef10](https://github.com/facebook/react/commit/5bce0ef10)**: [scheduler] Post to MessageChannel instead of window (#14234) //<Andrew Clark>//
- **[f55795c8e](https://github.com/facebook/react/commit/f55795c8e)**: Add regression test for #14188 (#14197) //<Dan Abramov>//
- **[b98adb648](https://github.com/facebook/react/commit/b98adb648)**: Simplify CSS shorthand property warning (#14183) //<Sophie Alpert>//
- **[f8bfd5868](https://github.com/facebook/react/commit/f8bfd5868)**: fix typo //<Sebastian Markbage>//
- **[961eb65b4](https://github.com/facebook/react/commit/961eb65b4)**: Use unique thread ID for each partial render to access Context (#14182) //<Sebastian Markbåge>//
- **[1a6ab1e9b](https://github.com/facebook/react/commit/1a6ab1e9b)**: SimpleMemoComponent should warn if a ref is given (#14178) //<Sophie Alpert>//
- **[8ae867e6b](https://github.com/facebook/react/commit/8ae867e6b)**: Warn about conflicting style values during updates (#14181) //<Sophie Alpert>//
- **[d5e1bf07d](https://github.com/facebook/react/commit/d5e1bf07d)**: Renamed outdated schedule/tracing referecnes (#14177) //<Brian Vaughn>//
- **[2dd4ba11e](https://github.com/facebook/react/commit/2dd4ba11e)**: ESlint -> ESLint //<Andrew Clark>//
- **[9cc631a53](https://github.com/facebook/react/commit/9cc631a53)**: Don't run danger on bad build (#14143) //<Sophie Alpert>//
- **[1034e26fe](https://github.com/facebook/react/commit/1034e26fe)**: Fix typos (#14124) //<Heaven>//
- **[5618da49d](https://github.com/facebook/react/commit/5618da49d)**: Fix comment typo (#14156) //<Bartosz Gordon>//
- **[9fb919945](https://github.com/facebook/react/commit/9fb919945)**: Add global to ESLint plugin bundle config //<Andrew Clark>//
- **[c174f8592](https://github.com/facebook/react/commit/c174f8592)**: Add fb build of ESLint plugin (#14165) //<Andrew Clark>//
- **[02e4848e3](https://github.com/facebook/react/commit/02e4848e3)**: Improved suspense support in ReactDOMServer (#14161) //<Alex Taylor>//
- **[4b163fee1](https://github.com/facebook/react/commit/4b163fee1)**: Remove errant return assignment (#14164) //<Andrew Clark>//
- **[e58ecda9a](https://github.com/facebook/react/commit/e58ecda9a)**: Suspense fuzz tester (#14147) //<Andrew Clark>//
- **[7fd1661f8](https://github.com/facebook/react/commit/7fd1661f8)**:  Don't warn if an unmounted component is pinged (#14158) //<Andrew Clark>//
- **[f9e9913f0](https://github.com/facebook/react/commit/f9e9913f0)**: [Synchronous Suspense] Don't delete children of suspended component (#14157) //<Andrew Clark>//
- **[7c560131b](https://github.com/facebook/react/commit/7c560131b)**: Adding logger pri (#14155) //<Nathan Schloss>//
- **[3d8bda70e](https://github.com/facebook/react/commit/3d8bda70e)**: Refactor ESLint configuration to enable better IDE integration (#13914) //<Minh Nguyen>//
- **[051272f20](https://github.com/facebook/react/commit/051272f20)**: Use Entry in `yarn build ...` Instead of Label (#14148) //<Sebastian Markbåge>//

Release Notes:
[GENERAL] [FEATURE] [React] - React sync for revisions 3ff2c7c...6bf5e85

Reviewed By: bvaughn

Differential Revision: D13288288

fbshipit-source-id: 89a4837a9198c53fc79306933f589ef25d8bb4b6
2018-12-04 15:38:21 +01:00
Valentin SherginandMike Grabowski f6566c77b1 Summary:
Calling -[UIScrollView setContentOffset] with NaN values can cause a crash. That's not clear why exactly the computation returns NaN sometime, but the implemented sanitizing should help to detect this problem during development (and this also prevents the app from crashing).

See attached task for more details.

Reviewed By: fkgozali

Differential Revision: D13242729

fbshipit-source-id: 747bf1b42e02597e9f1300eee24547563ab29b27
2018-12-04 15:37:25 +01:00
Nicolas GallagherandMike Grabowski 747b5e47ef Fix text alpha bug
Summary: Set the default text radius to 0 so that text shadows aren't applied to every text node

Reviewed By: mdvacca

Differential Revision: D13027589

fbshipit-source-id: 4f7386059ac1654b8f77dddf9eb1b772f6049e23
2018-12-04 15:35:54 +01:00
Michael BlanchardandMike Grabowski 0b32a65bbd Fix: Add displayName to ActivityIndicator (#22417)
Summary:
Similar to #21950, this adds displayName to `ActivityIndicator`, so it displays the correct component name in snapshots instead of `Component`.

Fixes #21937 (a little bit more than it was already fixed).
Pull Request resolved: https://github.com/facebook/react-native/pull/22417

Differential Revision: D13205376

Pulled By: TheSavior

fbshipit-source-id: 21e71d4980d159a1f33d32d83346b48257ec21d4
2018-12-04 15:35:35 +01:00
Ramanpreet NaraandMike Grabowski 3fbefa8664 Revert D13105396
Summary: D13105396 broke a few things, so I'm reverting it. See: https://fburl.com/toehyir8

Reviewed By: sahrens, mmmulani

Differential Revision: D13220491

fbshipit-source-id: 35594099eea7f40d2fb948ae2010db4babb7093d
2018-12-04 15:35:21 +01:00
Radek CzemerysandMike Grabowski 19a7ecc837 Fix Xcode 10 builds (broken by folly upgrade) (#22394)
Summary:
[Folly upgrade](https://github.com/facebook/react-native/commit/a70625abd7bf4fba3dafb8a969a73854b7ddcd42) introduced changes that have to be applied to `Install Third Party` script in order to use `New build system` from Xcode 10. Unfortunately, this might happen again if someone changes folly. Also removes non-existent files from folly podspec.
Pull Request resolved: https://github.com/facebook/react-native/pull/22394

Differential Revision: D13192463

Pulled By: hramos

fbshipit-source-id: ea0eeb6e1e7f6d7dfcdb6d1dee28b1a640ee7097
2018-11-27 12:25:12 +01:00
Mike Grabowski 0c1c66e719 [0.58.0-rc.0] Bump version numbers 2018-11-22 18:30:52 +01:00
Mike Grabowski e71fb64ecd Apply same config for Android 2018-11-22 18:29:16 +01:00
Mike Grabowski 26bdd5ba4e Make Metro untyped instead of ignored to let Metro-config resolve type annotations 2018-11-22 18:25:47 +01:00
Mike Grabowski e0ea58ecbd Add missing Metro Config 2018-11-22 18:18:37 +01:00
Kudo ChienandMike Grabowski 64dd60fb7d Fix ReactAndroid build break. (#22377)
Summary:
During C++ build, we need the libjsc.so.
  But arm64-v8a and x86_64 libjsc.so are in different path and this error raised:

    Android NDK: ERROR:/home/circleci/react-native/ReactAndroid/build/third-party-ndk/jsc/Android.mk:jsc: LOCAL_SRC_FILES points to a missing file
    /opt/ndk/android-ndk-r17c/build/core/prebuilt-library.mk:45: *** Android NDK: Aborting    .  Stop.
    Android NDK: Check that /home/circleci/react-native/ReactAndroid/build/third-party-ndk/jsc/jni/arm64-v8a/libjsc.so exists  or that its path is correct

  The commit moves prebuilt libjsc.so into
  ReactAndroid/src/main/jni/third-party/jsc/jni and let ndkbuild script find the prebuilt libjsc.so.
  For AAR packaging, modify the jniLibs so that gradle android library plugin could find the prebuilt libjsc.so as well.
Pull Request resolved: https://github.com/facebook/react-native/pull/22377

Differential Revision: D13166556

Pulled By: hramos

fbshipit-source-id: 61daaede7defbc66491a3e2f20058e7d248ba13e
2018-11-22 17:55:40 +01:00
gengjiawenandMike Grabowski d4d457b4eb Fix jsc regression.Fixes #22274 (#22293)
Summary:
My silly mistake when tinkering with the jsc lib. Also you have this patch first https://github.com/facebook/react-native/pull/22295.
Kudo plz review.

![image](https://user-images.githubusercontent.com/3759816/48561684-758f6f00-e92b-11e8-905b-e394f72349f7.png)
Pull Request resolved: https://github.com/facebook/react-native/pull/22293

Differential Revision: D13153931

Pulled By: hramos

fbshipit-source-id: 8a6efa0cd8abbff359f082d5ea7713933b6e7ac6
2018-11-22 17:55:31 +01:00
Mike Grabowski b864e7e63e Revert "Merge branch 'master' into 0.58-stable"
This reverts commit 696bd89013, reversing
changes made to a525941ab6.
2018-11-22 17:53:44 +01:00
Mike Grabowski 696bd89013 Merge branch 'master' into 0.58-stable 2018-11-22 17:33:25 +01:00
Rafael OlezaandMike Grabowski a525941ab6 Bump metro@0.49.1
Summary: galavant-fistbump

Reviewed By: jeanlauliac

Differential Revision: D13027247

fbshipit-source-id: 3635527b6c745111b26d9f61666c30e696b04526
2018-11-13 23:52:11 +01:00
232 changed files with 3933 additions and 3737 deletions
+2 -2
View File
@@ -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 -1
View File
@@ -1,6 +1,6 @@
[android]
target = android-27
target = android-28
[download]
max_number_of_retries = 3
+21 -59
View File
@@ -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
+4 -4
View File
@@ -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/.*
+4 -4
View File
@@ -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/.*
+2 -2
View File
@@ -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;
+1 -41
View File
@@ -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}
+27 -31
View File
@@ -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),
/**
+38 -70
View File
@@ -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);
}
/**
+29 -93
View File
@@ -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,
|}>;
+17 -83
View File
@@ -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);
},
+4 -4
View File
@@ -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',
};
+14 -3
View File
@@ -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 {
+10 -10
View File
@@ -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);
};
+2 -2
View File
@@ -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
View File
@@ -1 +1 @@
3ff2c7ccd4d174786aed0f16cc0dd784816ae977
6bf5e859860938b8cb7153ee928c01ad45656969
File diff suppressed because it is too large Load Diff
+47 -51
View File
@@ -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) {
+51 -54
View File
@@ -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) {
File diff suppressed because it is too large Load Diff
@@ -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)
+1
View File
@@ -59,6 +59,7 @@ export type ReactContext<T> = {
_currentValue: T,
_currentValue2: T,
_threadCount: number,
// DEV only
_currentRenderer?: Object | null,
+1 -1
View File
@@ -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];
+12 -12
View File
@@ -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);
+2 -7
View File
@@ -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
+7 -7
View File
@@ -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,
/**
+2 -5
View File
@@ -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;
+2 -5
View File
@@ -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),
};
-165
View File
@@ -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};
+10
View File
@@ -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');
},
+1 -1
View File
@@ -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];
+2 -2
View File
@@ -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
+23
View File
@@ -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.
+3 -1
View File
@@ -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
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 KiB

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

+2 -2
View File
@@ -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"
+55
View File
@@ -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');
});
});
+30
View File
@@ -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();
});
});
+81
View File
@@ -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');
});
});
+72
View File
@@ -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');
});
});
+3 -7
View File
@@ -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}>
+4 -11
View File
@@ -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));
};
}
+8 -2
View File
@@ -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}
+2 -2
View File
@@ -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 => {
+2 -4
View File
@@ -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}
+1
View File
@@ -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')}>
+6 -12
View File
@@ -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>
);
}
+29 -1
View File
@@ -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>
);
}
+106
View File
@@ -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;
+30 -89
View File
@@ -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;
-3
View File
@@ -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}),
)}
+88 -15
View File
@@ -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>
);
}
+4 -5
View File
@@ -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,
};
+5 -7
View File
@@ -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>
);
+61 -28
View File
@@ -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>
);
+2 -2
View File
@@ -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>
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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'));
-87
View File
@@ -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
...
+15 -2
View File
@@ -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

Some files were not shown because too many files have changed in this diff Show More