Compare commits

...
Author SHA1 Message Date
Eloy Durán b9944e54ae [0.62.2] Bump version numbers 2020-04-08 19:01:02 +02:00
Bruno BarbieriandEloy Durán f89c5098be Make Vibration.vibrate compatible with TurboModules (#27951)
Summary:
This PR fixes a compatibility issue with the Vibration module and TurboModules.
The TurboModules spec doesn't allow nullable arguments of type Number, causing the following problem:

![IMG_3758](https://user-images.githubusercontent.com/1247834/73803879-10be6f80-4790-11ea-92d4-a008f0007681.PNG)

[iOS] [Fixed] - Make Vibration library compatible with TurboModules.
Pull Request resolved: https://github.com/facebook/react-native/pull/27951

Test Plan:
Just submitted a PR to my own app to fix the issue [here](https://github.com/rainbow-me/rainbow/pull/340)

The problem should be reproducible on RNTester due to this line: https://github.com/facebook/react-native/blob/91f139b94118fe8db29728ea8ad855fc4a13f743/RNTester/js/examples/Vibration/VibrationExample.js#L66  and should be working on this branch.

Reviewed By: TheSavior

Differential Revision: D19761064

Pulled By: hramos

fbshipit-source-id: 84f6b62a2734cc09d450e906b5866d4e9ce61124
2020-04-08 16:24:23 +02:00
Javier CuevasandEloy Durán 8858d879eb Exclude all FlipperKit transitive dependencies from iOS Release builds (#28504)
Summary:
The `:configuration` option from `pod` only affects the specified pod and not its dependencies [1]. Therefore in order to avoid all transitive dependencies being linked in the resulting Release IPA we need to list them in the `Podfile`.

Note that this will still build Flipper's pods when doing a Release, but it won't link it in the resulting IPA.

[1] https://guides.cocoapods.org/syntax/podfile.html#pod

Fixes https://github.com/react-native-community/upgrade-support/issues/28
Related https://github.com/CocoaPods/CocoaPods/issues/9658

* [iOS] [Fixed] - Exclude Flipper from iOS Release builds
Pull Request resolved: https://github.com/facebook/react-native/pull/28504

Test Plan:
Create a new React Native 0.62 project, run `pod install`, then diff:
```
ProjectName/ios/Pods/Target Support Files/Pods-ProjectName/Pods-ProjectName.debug.xcconfig`
```
and
```
ProjectName/ios/Pods/Target Support Files/Pods-ProjectName/Pods-ProjectName.relaese.xcconfig
```

![image](https://user-images.githubusercontent.com/855995/78337679-a3fa0280-7591-11ea-8142-6f82cbc6be58.png)

Reviewed By: passy

Differential Revision: D20894406

Pulled By: priteshrnandgaonkar

fbshipit-source-id: 680780f0f5a85fd8423b85a271a499bd12f06d00
2020-04-08 16:11:25 +02:00
Eli WhiteandEloy Durán 4fd9c9d544 Fix Appearance module when using Chrome Debugger
Summary:
The appearance module uses sync native module methods which doesn't work with the chrome debugger. This broke in 0.62: https://github.com/facebook/react-native/issues/26705

This fix makes the appearance module return 'light' when using the chrome debugger.

Changelog: [Fixed] Appearance `getColorScheme` no longer breaks the debugger

Reviewed By: yungsters

Differential Revision: D20879779

fbshipit-source-id: ad49c66226096433bc9f270e004ad4a6f54fa8c2
2020-04-08 15:47:34 +02:00
Eli WhiteandEloy Durán 6e530d9aed Move DebugEnvironment helper to open source
Summary:
This is an internal only module that we use to detect whether we are in async debugging mode.

Changelog: [Internal]

Reviewed By: yungsters

Differential Revision: D20879780

fbshipit-source-id: 5915f4e1c54a3fda0cf607c77f463120264fdbc4
2020-04-08 15:47:27 +02:00
Hein RutjesandEloy Durán 6b6877d5b5 Fix crash when enabling Performance Monitor on iOS 13.4 (#28512)
Summary:
This PR fixes a crash when opening the Performance Monitor on iOS 13.4.
Detailed info: https://github.com/facebook/react-native/issues/28414

## Changelog

`[iOS] [Fixed] - Fix crash when enabling Performance Monitor on iOS 13.4`

## How

This PR prevents the JavaScriptCore option from being set altogether.
This ensures that the performance monitor keeps working, but on iOS 13.4 and higher, it will no longer crash trying to show the GC usage.
Pull Request resolved: https://github.com/facebook/react-native/pull/28512

Test Plan:
Tested on iOS 13.4 (simulator):

![image](https://user-images.githubusercontent.com/6184593/77903803-c6370c00-7283-11ea-8b71-b6b6546c82f6.png)

Tested on iOS 13.1 (simulator)

![image](https://user-images.githubusercontent.com/6184593/77903499-41e48900-7283-11ea-9d14-83f67a3b7b77.png)

- Verified that the `setOption` was called, but the Performance Monitor didn't show any GC usage regardless.
- Identical PR https://github.com/expo/react-native/pull/21 has been shipped and tested in Expo Client 37

Fixes https://github.com/facebook/react-native/issues/28414

Reviewed By: PeteTheHeat

Differential Revision: D20851131

Pulled By: TheSavior

fbshipit-source-id: ff96301036e8487db59f95947bbe6841fe230e1e
2020-04-08 15:47:19 +02:00
Sergio EstevaoandEloy Durán 9a00cecae4 Fix mock for TextInput (#28332)
Summary:
This PR adds the `isFocused` method to the mock of the TextInput component. My understanding some of the latest changes on the TextInput to make it use a forwardRef change the way this method is mock giving an error when trying to use in on a mock.
The change suggested here fixes the issue.

## Changelog

[JavaScript] [Fixed] - Fix the mock for TextInput to support the `isFocused` method
Pull Request resolved: https://github.com/facebook/react-native/pull/28332

Reviewed By: cpojer

Differential Revision: D20538044

Pulled By: TheSavior

fbshipit-source-id: be734af105ab62ffdf9ed4017bd70845e207f8cd
2020-04-08 15:45:12 +02:00
Eloy DuránandGitHub 8e705b71e2 Merge pull request #28520 from thymikee/fix/flow-types
[General] [Fixed] Flow errors from YellowBox and BubblingEventHandler
2020-04-07 11:58:19 +02:00
Michał Pierzchała a049130f34 [General] [Fixed] Flow errors from YellowBox and BubblingEventHandler 2020-04-03 22:40:03 +02:00
Eloy Durán 25011a6d09 [0.62.1] Bump version numbers 2020-04-03 17:09:15 +02:00
Eloy Durán 2b434af178 [Internal] [Changed] - Update lockfiles. 2020-04-03 16:16:57 +02:00
Eloy Durán 4067f903be Seed ssh known hosts with github's public key (#28370)
Summary:
The [previous attempt](https://github.com/facebook/react-native/pull/28304) to fix the publish step failed, so now reverting to manually configuring things. This PR adds an entry to SSH’s `known_hosts` file using github.com’s public key that I have verified as per [these instructions](https://serverfault.com/a/807363):

```
~/C/R/react-native [master] » nmap github.com --script ssh-hostkey
Nmap scan report for github.com (140.82.118.4)
rDNS record for 140.82.118.4: lb-140-82-118-4-ams.github.com
PORT     STATE SERVICE
22/tcp   open  ssh
| ssh-hostkey:
|   1024 ad:1c:08:a4:40:e3:6f:9c:f5:66:26:5d:4b:33:5d:8c (DSA)
|_  2048 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48 (RSA)
```

These fingerprints line up with [the ones posted by GitHub](https://help.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints), so my setup should be good and can be trusted to grab the public key from the right host:

```
~/C/R/react-native [master] » ssh-keyscan -t rsa -H github.com
|1|If6MU203eXTaaWL678YEfWkVMrw=|kqLeIAyTy8pzpj8x8Ae4Fr8Mtlc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
```

[Internal] [Fixed] - Make automated publishing of packages from CI work again
Pull Request resolved: https://github.com/facebook/react-native/pull/28370

Test Plan: I used the command being added in this PR in [a failed CI job](https://app.circleci.com/pipelines/github/facebook/react-native/4104/workflows/916127cb-177f-4583-9f90-cae5318041d8/jobs/140810). When I invoked the publish script manually I was not greeted by the blocking prompt and the package was successfully published: https://www.npmjs.com/package/react-native/v/0.0.0-56cf99a96

Reviewed By: cpojer

Differential Revision: D20601527

Pulled By: hramos

fbshipit-source-id: b1a4405228408cfc4a1b3b44ab88c79522af3a66
2020-04-03 16:00:18 +02:00
Eloy Durán eac56b9749 [General] [Fixed] - Bump CLI to 4.5.1 to improve DX 2020-04-03 15:46:14 +02:00
grabbouandEloy Durán 27a3248a3b [iOS] [Fixed] - Revert [previous incomplete fix](https://github.com/facebook/react-native/commit/bd2b7d6c0366b5f19de56b71cb706a0af4b0be43) for [an issue](https://github.com/facebook/react-native/issues/26473) with Modal’s onDismiss prop.
This reverts commit bd2b7d6c03.
2020-04-03 15:35:42 +02:00
Jesse KatsumataandEloy Durán 8ba46aa86c chore: update url of warning message from deprecated imports (#28452)
Summary:
Some of the repository name of Lean Core(https://github.com/facebook/react-native/issues/23313) libraries has been renamed.
This PR updates the warning message to display the updated url.

[General] [Changed] - Update warning message of deprecated imports
Pull Request resolved: https://github.com/facebook/react-native/pull/28452

Test Plan: updated URL can be accessed.

Reviewed By: cpojer

Differential Revision: D20745184

Pulled By: TheSavior

fbshipit-source-id: 2c3ed6a000b45022ca6c4862305aa567c4d18b2e
2020-04-03 15:33:59 +02:00
Martin SherburnandEloy Durán d7d4fae101 Fix issue with onEndReached
Summary:
onEndReached can be triggered twice when more items are added to the end of the list. This change makes it so that a second call to onEndReached won't happen until the user scrolls down to the new end of the list.

Changelog:

[General] [Fixed] - Fix double call to onEndReached in VirtualizedList

Reviewed By: sahrens

Differential Revision: D20066740

fbshipit-source-id: 129d7ae6bfd241eeea18fe0bb12b82be67735874
2020-04-03 15:30:34 +02:00
Janic DuplessisandEloy Durán 7efc77985a Add new DoNotStrip class to proguard config (#27934)
Summary:
JNI now comes from https://github.com/facebookincubator/fbjni and it uses a different DoNotStrip class (https://github.com/facebookincubator/fbjni/blob/master/java/com/facebook/jni/annotations/DoNotStrip.java) so we need to include it in the proguard config.

## Changelog

[Android] [Fixed] - Add new DoNotStrip class to proguard config
Pull Request resolved: https://github.com/facebook/react-native/pull/27934

Test Plan: Test that it fixes a crash related to missing NativeRunnable class in release builds.

Differential Revision: D19690580

Pulled By: cpojer

fbshipit-source-id: cb4e2eaae35fb3a9d68f04c57cc973914207be73
2020-04-03 15:30:14 +02:00
Mo GorhomandEloy Durán cad697d8b4 Dark mode support for RCTPerfMonitor (#28130)
Summary:
Hi There 👋,

While I'm developing on iOS with dark appearance enabled, i notice that `Pref Monitor` view doesn't support dark mode yet, so here is the PR to fix it :)

## Changelog

[iOS] [Fixed] - Fix Pref Monitor in dark appearance
Pull Request resolved: https://github.com/facebook/react-native/pull/28130

Test Plan:
Run any React Native app on iOS > Turn on dark appearance
### Before
![Before](https://user-images.githubusercontent.com/4061838/74872974-8b75b600-535e-11ea-8550-763a598547ec.png)
### After
![After](https://user-images.githubusercontent.com/4061838/74872978-8ca6e300-535e-11ea-9862-4d3014e849f7.png)

Reviewed By: RSNara

Differential Revision: D20080019

Pulled By: PeteTheHeat

fbshipit-source-id: 9365daa3f7193a11760bc1372b8de2c3896def5c
2020-04-03 15:29:43 +02:00
EmilioandEloy Durán 30aad14e77 tapping on iOS status bar should scroll inverted ScrollViews to their top (#27574)
Summary:
React Native ScrollViews are flipped upside down when the prop inverted is set to true. This is the root of a bug: tapping on the status bar in iOS should scroll the Flatlist up to the top but currently it does to the bottom.

The solution proposed is to detect natively if the ScrollView is inverted, on such case, prevent it from scrolling it to the beginning of the ScrollView (as a non-inverted ScrollView would do) and force a scroll to the end of it.

I've been careful enough not to force the scroll if the user explicitly selected not to do it or if it's happening in a nested ScrollView, as it is the default behaviour in iOS.

Fixes https://github.com/facebook/react-native/issues/21126

## Changelog

[iOS] [Fixed] - Inverted ScrollViews scroll to their bottom when the status bar is pressed
Pull Request resolved: https://github.com/facebook/react-native/pull/27574

Test Plan:
- on iOS, add a ScrollView and put enough content to overflow the screen size so it can be scrolled
- add the prop `inverted={true}` to the ScrollView
- go to the screen the Scrollview is in and press the status bar
- it should scroll to top (previously it scrolled to the bottom)

![v](https://user-images.githubusercontent.com/807710/71188640-a0ac6680-2281-11ea-91a7-d1e46aba8b14.gif)

Differential Revision: D19185270

Pulled By: hramos

fbshipit-source-id: 5445093ff38f4ba4082f1d883d8ed087e9565eaf
2020-04-03 15:28:42 +02:00
RickyandGitHub 227aa96bb2 Fix YellowBox in 0.62 (#28457) 2020-03-31 07:46:07 +01:00
Eloy Durán 9101eaf121 [0.62.0] Bump version numbers 2020-03-26 18:03:15 +01:00
Tim Yungandgrabbou 1f8b698013 Pressability: Fix Missing onLongPress Gestures
Summary:
The current implementation of `Pressability` has a bug related to `onLongPress`.

When a user starts a press gesture, we keep track of the activation position (occurs after waiting `delayPressIn` milliseconds). If the touch moves away from that position by more than 10dp, we rule out the long press gesture. This means no matter how long you hold down the press, even if you move it back to within 10dp, we will not fire `onLongPress`.

However, there is currently a bug where we never reset the cached activation position. This means that after the first press gesture, all subsequent long press gestures must start within 10dp of that first press gesture. This leads to seemingly intermittent missing long press gestures.

This fixes the bug by ensuring that whenever a press gestures is terminated (either via a cancel or release), we reset the activation position.

Changelog:
[General][Fixed] - Fixed Pressability to properly fire `onLongPress`.

Reviewed By: TheSavior

Differential Revision: D20410075

fbshipit-source-id: e4727b7a9585ce3ea39481fc13e56b6b91740c8c
2020-03-18 16:54:46 +01:00
Michel WeststrateandEloy Durán f6a8452e76 Bump FlipperKit version on iOS to be compatible with react-native-flipper (#28277)
Summary:
This pull request re-applies https://github.com/facebook/react-native/pull/28225, thereby reverting https://github.com/facebook/react-native/commit/4bb17944f18e8ecd20633e49ff143f23210cd976, this time bumping to FlipperKit 0.33.1 which is again compatible with iOS 9 (thanks to https://github.com/facebook/flipper/pull/874)

This is the iOS counterpart of https://github.com/facebook/react-native/pull/28275

[iOS] [Changed] - Upgrade Flipper dependency to 0.33.1
Pull Request resolved: https://github.com/facebook/react-native/pull/28277

Test Plan:
* Bumped the version in our Flipper / RN integration test app first, that runs on 0.62-rc.5, verified everything still works there.
* CI

![Screen Shot 2020-03-10 at 12 12 46](https://user-images.githubusercontent.com/1820292/76311312-94f09f00-62c8-11ea-81db-ced6d16e096b.png)

Reviewed By: mweststrate

Differential Revision: D20369106

Pulled By: TheSavior

fbshipit-source-id: dfeb0446e7f29684a266eca5d0e29ac42cef2ef3
2020-03-11 20:06:55 +01:00
Pascal HartigandEloy Durán e8a368c9a0 Upgrade Flipper Android to 0.33.1 (#28275)
Summary:
Upgrades Flipper to 0.33.1 for both the Android template and RNTester.

## Changelog

[Android] [Changed] - Upgrade Flipper dependency to 0.33.1
Pull Request resolved: https://github.com/facebook/react-native/pull/28275

Test Plan: Still trying to figure out how to get my Gradle setup working again. Until then, CI.

Reviewed By: cpojer, mweststrate

Differential Revision: D20369480

Pulled By: TheSavior

fbshipit-source-id: 048c944819168a352214349f6a83407a587479c9
2020-03-11 20:04:28 +01:00
Eloy Durán 83aff2c32f [0.62.0-rc.5] Bump version numbers 2020-03-07 16:01:54 +01:00
Joshua GrossandEloy Durán e41e146baa Fix toggling between hidden and visible password
Summary:
A previous PR broke toggling between visible and non-visible password (basically once a password field was made visible, future updates to the keyboardType were effectively ignored, so the password would always be visible).

Original PR: https://github.com/facebook/react-native/pull/27523

Changelog: [Internal]

Reviewed By: mdvacca, rodrigos-facebook

Differential Revision: D19527245

fbshipit-source-id: a5ab343c8a0c6a608171dbfa5afc7536ff241826
2020-03-07 09:04:31 +01:00
Eloy Durán ba3815feae [0.62.0-rc.4] Bump version numbers 2020-03-06 19:48:13 +01:00
Eloy Durán 4bb17944f1 Revert "Bump FlipperKit version on iOS to be compatible with react-native-fli… (#28225)"
This reverts commit ada73a3549.
2020-03-06 17:27:55 +01:00
Michel WeststrateandEloy Durán ada73a3549 Bump FlipperKit version on iOS to be compatible with react-native-fli… (#28225)
Summary:
This diff updated FlipperKit to be compatible with the latest react-native-flipper version.

(nothing changes compared to what is already in the changelog for RN 0.62.0)

[iOS][Fixed] - Upgraded FlipperKit to 0.32.2 to ensure compatibility with latest `react-native-flipper`
Pull Request resolved: https://github.com/facebook/react-native/pull/28225

Test Plan:
Tested by upgrading the ReactNativeFlipperExample (https://github.com/facebook/flipper/tree/master/react-native/ReactNativeFlipperExample) to RN 0.62.0-rc.3 and verified the example plugin works. (In D20221558)

![Screen Shot 2020-03-04 at 11 26 52](https://user-images.githubusercontent.com/1820292/75875163-18167e80-5e0b-11ea-8a7d-504bb27757db.png)

Reviewed By: priteshrnandgaonkar

Differential Revision: D20249666

Pulled By: mweststrate

fbshipit-source-id: 71a61c4249f8b767c7767d5c6133436c9bc9cf26
2020-03-05 15:02:53 +01:00
Pavlos VinieratosandEloy Durán 4efa3baf0c Add xcscheme files back in the template (#28198)
Summary:
Adding `xcscheme` files for iOS template back in. They were removed in https://github.com/facebook/react-native/issues/26471 after https://github.com/facebook/react-native/issues/25451. We have reverted the change on `.gitignore`, as this directory is supposed to be in git, but we didn't revert the removed files. Now they are back as well.

You can also see here that the two files are still missing, they got removed on rc.0 and are still missing on rc.3.
https://react-native-community.github.io/upgrade-helper/?from=0.61.5&to=0.62.0-rc.3

## Changelog

[iOS] [Changed] - Add `xcscheme` files for iOS template back in.
Pull Request resolved: https://github.com/facebook/react-native/pull/28198

Test Plan: `init` a nre project, and check if the files are there or not. The paths are `ios/MyApp.xcodeproj/xcshareddata/xcschemes/MyApp.xcscheme` and `ios/MyApp.xcodeproj/xcshareddata/xcschemes/MyApp-tvOS.xcscheme`

Reviewed By: cpojer

Differential Revision: D20179447

Pulled By: TheSavior

fbshipit-source-id: b0f08c0f32d6bb7630179bc2fe46d9ac10f6c1d7
2020-03-05 12:15:10 +01:00
Will HolenandEloy Durán 409551ccd2 Try the debug executor before the release executor
Summary:
We are currently unintentionally including both libhermes-executor-release.so
and libhermes-executor-debug.so in all OSS RN builds.

RN tries both in turn, but since they both exist and the release executor is compatible
with the debug build, we always get the release executor without debug functionality.

While we sort this out, switch the load order. Since the debug executor is not compatible
with the release build, so it'll fail to load and try the next one.

ChangeLog: [Android] Fix Hermes debugger being disabled by default

Reviewed By: mhorowitz

Differential Revision: D20163828

fbshipit-source-id: ee4d87f40e42a7c8eedfdb7e1fc17eb3e5966ba5
2020-03-05 12:14:59 +01:00
Marc HorowitzandEloy Durán e16c5cb4bf If JSC fails to load when starting RN, expose that error to the caller
Summary:
See the comments for more info.

Changelog: [Android] [Changed] - Improve exception message when JSC loading fails

Reviewed By: tmikov

Differential Revision: D19917034

fbshipit-source-id: d846f542c31e9c94edcee240c2935d77d48d1f2a
2020-03-05 12:14:51 +01:00
David VaccaandEloy Durán 0b6cd69dd4 Return null when requesting constants for nonexistent View Managers in RN Android
Summary:
This diff changes the behavior of UIImplementation.resolveViewManager() to return null instead of throwing an exception when trying to find an unexistent viewManager during the computation of constants for view Managers.

The C++/JS code manages exceptions and null results when a view manager doesn't exists, this diff simplifies the way this method operates.

changeLog: [internal]

Reviewed By: rickhanlonii

Differential Revision: D19624423

fbshipit-source-id: df31dcfae9a588bf325b61d529cec6ead59fb19d
2020-03-05 12:14:41 +01:00
Jason SafaiyehandEloy Durán d22cc4f2bd Fix setting keyboardType from breaking autoCapitalize (#27523)
Summary:
Fix for https://github.com/facebook/react-native/issues/27510.

Setting the `InputType.TYPE_CLASS_TEXT` flag when `keyboardType` is null or default breaks autoCapitalize. Handle the case when `keyboardType` is null, default, or invalid type.

## Changelog

[Android] [Fixed] - Fix setting keyboardType from breaking autoCapitalize
Pull Request resolved: https://github.com/facebook/react-native/pull/27523

Test Plan:
Added keyboardType prop to RNTester as so
```
<TextInput autoCapitalize="words" keyboardType="default" style={styles.default} />
```
![fixedKeyboardType](https://user-images.githubusercontent.com/8675043/70872892-c96dec80-1f5f-11ea-8e33-714a67eff581.gif)

Reviewed By: makovkastar

Differential Revision: D19132261

Pulled By: JoshuaGross

fbshipit-source-id: be66f0317ed305425ebcff32046ad4bff06d367f
2020-03-05 12:14:25 +01:00
Eloy Durán dfa8fed64b [0.62.0-rc.3] Bump version numbers 2020-02-25 20:55:05 +01:00
Eloy Durán be5088401f [package] Bump CLI to ^4.2.x 2020-02-25 20:53:28 +01:00
Eloy Durán 26e7d6a062 [package] Bump CLI to ^4.1.x to fix run-android 2020-02-25 18:12:37 +01:00
Jason SafaiyehandEloy Durán ebb629d056 Resolve localization warnings (#28046)
Summary:
Resolve Xcode localization warnings in template

## Changelog

[iOS] [Fixed] - Resolve localization warnings
Pull Request resolved: https://github.com/facebook/react-native/pull/28046

Test Plan: Create a fresh template app, localization warnings should not happen.

Differential Revision: D19873686

Pulled By: hramos

fbshipit-source-id: 5db0e7da1048899c4049fe991bc354a6798dfb06
2020-02-25 15:56:51 +01:00
Will HolenandEloy Durán 2799d677ca @allow-large-files Upgrade Hermes dependency to 0.4.0
Summary:
Use the latest published release of hermes-engine.

Changelog: [Android] [Changed] - Upgraded to Hermes 0.4.0

Reviewed By: mhorowitz

Differential Revision: D19866355

fbshipit-source-id: be2bed957bc034d3e6107804229abc2d83e40d40
2020-02-25 15:56:38 +01:00
Jason SafaiyehandEloy Durán 76604e7c5c Resolve React-RCTText Xcode warning (#28054)
Summary:
Resolve React-RCTText warning: `'UIKeyboardTypeASCIICapableNumberPad' is only available on iOS 10.0 or newer`

## Changelog

[iOS] [Fixed] - Resolve React-RCTText Xcode warning
Pull Request resolved: https://github.com/facebook/react-native/pull/28054

Test Plan: Build template, React-RCTText should no longer throw a warning.

Differential Revision: D19887063

Pulled By: hramos

fbshipit-source-id: 3437ee993babd7cdaec259af24526e197acb64bb
2020-02-25 15:56:23 +01:00
Valentin SherginandEloy Durán 8aeb5dc7ad Revert D19235758: Implement onRequestClose for iOS 13+ modals
Differential Revision:
D19235758

Original commit changeset: c0f1d946c77c

fbshipit-source-id: c4a9d7876aa8d07ff5b8419f097b02e9c28e2880
2020-02-25 15:56:13 +01:00
Janic DuplessisandEloy Durán 360b53d77f Implement TextInput autoFocus natively on iOS (#27803)
Summary:
This implement the autoFocus functionality natively instead of calling the focus method from JS on mount. This is needed to properly fix the issue described in https://github.com/facebook/react-native/issues/27217, where when using native navigation (UINavigationController) text input focus needs to happen in the same frame transition starts or it leads to an animation bug in UIKit.

My previous attempt fixed the problem only partially and the bug could still happen since there is no guaranty code executed in useEffect will end up in the same frame as the native view being created and attached.

To fix this I added an autoFocus prop to the native component on iOS and in didAttachToWindow we focus the input if it is set. This makes sure the focus is set in the same frame as the view hierarchy containing the input is created.

## Changelog

[iOS] [Fixed] - Add native support for TextInput autoFocus on iOS
Pull Request resolved: https://github.com/facebook/react-native/pull/27803

Test Plan:
- Tested that the UI glitch when transitionning to a screen with an input with autofocus no longer happens in my app.
- Tested that autofocus still works in RNTester
- Made sure that onFocus does get called and TextInputState is updated properly

Differential Revision: D19673369

Pulled By: TheSavior

fbshipit-source-id: 14d8486ac635901622ca667c0e61c75fb446e493
2020-02-25 15:56:02 +01:00
Jesse KatsumataandEloy Durán ebfd1bdf6e fix: resolve Require Cycle warning (#27851)
Summary:
When I was testing React Native 0.62-rc.1, I noticed that console was showing a warning for Require Cycle as shown in image below

![Screen Shot 2020-01-24 at 12 22 38](https://user-images.githubusercontent.com/6936373/73042467-998dff00-3ea4-11ea-911c-955d55fd0743.png)

This is because ScrollResponder was importing `ScrollView` to get the `typeof ScrollView`.
I've made an export for ScrollView type in `ScrollView` so that Require cycle warning will not show up.

## Changelog

[General] [Fixed] - Remove Require cycle warning.
Pull Request resolved: https://github.com/facebook/react-native/pull/27851

Differential Revision: D19577644

Pulled By: cpojer

fbshipit-source-id: 257b9421a91244d69394375102cfbe683326bba2
2020-02-25 15:55:48 +01:00
Pavlos VinieratosandEloy Durán b0eddefcbb remove xcshareddata from gitignore (#27563)
Summary:
Files that are inside `xcshareddata` are meant to be "shared", and that means committed to git. These files are for example `ios/RnDiffApp.xcodeproj/xcshareddata/xcschemes/RnDiffApp.xcscheme`, and if ignored that means they are removed from the repo or are missing when cloning. These should be present. They are the shared schemes so Xcode knows what and how to build, on everyone's machine.

I noticed it being there in a new project on 0.62.0-rc.0.

## Changelog

[iOS] [Changed] - Remove the xcshareddata from .gitignore
Pull Request resolved: https://github.com/facebook/react-native/pull/27563

Differential Revision: D19166364

Pulled By: TheSavior

fbshipit-source-id: 0377dc5b08ba04d121f9ed5e4027942a7a9f463f
2020-02-25 15:55:33 +01:00
Rick Hanlon 9bf0d7f509 LogBox - Revert back to RedBox window strategy
Summary: This diff reverts the iOS LogBox module back to the UIWindow strategy used by Redbox.

Reviewed By: sammy-SC

Differential Revision: D19941390

fbshipit-source-id: 4aea09137ea9e8bfc166a733272647a79102bf35
2020-02-19 12:11:43 +00:00
Rick Hanlon 90e21dfd65 LogBox - Move images to files
Summary:
Moves the LogBox images from base64 data to files since base64 is not supported everywhere.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D19879323

fbshipit-source-id: 2dc03eebfc712ed863ed76322e133fcad5b00bb4
2020-02-19 12:08:55 +00:00
Eloy Durán c5ecc6ffff [0.62.0-rc.2] Bump version numbers 2020-02-13 17:47:01 +01:00
Eloy Durán cef001713f [Template] Upgrade metro babel preset
Related to 41f4efb364
2020-02-13 16:43:59 +01:00
Jason SafaiyehandEloy Durán 572f710492 Resolve React-cxxreact warnings (#28047)
Summary:
Resolve Xcode warnings from React-cxxreact.

## Changelog

[iOS] [Fixed] - Resolve Xcode warnings from React-cxxreact.
Pull Request resolved: https://github.com/facebook/react-native/pull/28047

Test Plan: React-cxxreact should no longer throw `... creates a copy from type...` warnings

Differential Revision: D19874043

Pulled By: hramos

fbshipit-source-id: 15a4a810adee268e6ede459d6d4917ccfa83c157
2020-02-13 16:19:33 +01:00
Janic DuplessisandEloy Durán 474861f4e7 Implement adjustsFontSizeToFit on Android (#26389)
Summary:
This adds support for `adjustsFontSizeToFit` and `minimumFontScale` on Android. The implementation tries to match closely the behaviour on iOS (hardcoded 4px min size for example). It uses a simpler linear algorithm for now, opened to improving it now if it is a deal breaker or in a follow up.

See https://twitter.com/janicduplessis/status/1171147709979516929 for a more detailed thread about the implementation

## Changelog

[Android] [Added] - Implement `adjustsFontSizeToFit` on Android
Pull Request resolved: https://github.com/facebook/react-native/pull/26389

Test Plan: Tested by adding the existing `adjustsFontSizeToFit` example from the iOS text page to android. Also added a case for limiting size by using `maxHeight` instead of `numberOfLines`.

Reviewed By: mdvacca

Differential Revision: D17285473

Pulled By: JoshuaGross

fbshipit-source-id: 43dbdb05e2d6418e9a390d11f921518bfa58e697
2020-02-13 16:19:14 +01:00
Michał PierzchałaandEloy Durán 048b537800 - Bump CLI to ^4.0.0 (#27976)
Summary:
Upgrading CLI to latest. This diff is intended to be cherry-picked to 0.62.

cc grabbou kelset

[Internal] [Changed] - Bump CLI to ^4.0.0
Pull Request resolved: https://github.com/facebook/react-native/pull/27976

Test Plan: None

Differential Revision: D19769017

Pulled By: cpojer

fbshipit-source-id: c3f5cd8afc0bc26372ee9f9e9dbaf4e68cdec216
2020-02-13 16:18:57 +01:00
Rick HanlonandEloy Durán 2a50905c0b Upgrade metro
Summary:
Upgrades metro so OSS gets code frames in LogBox.

Changelog: [Internal]

Reviewed By: cpojer

Differential Revision: D19621775

fbshipit-source-id: 02ee45e7282a5fd98e3365292d9221afa637dfeb
2020-02-13 16:17:54 +01:00
Jesse KatsumataandEloy Durán 14398752e3 chore: add eslint back to template (#27983)
Summary:
This PR is part of https://github.com/react-native-community/releases/issues/157#issuecomment-582504146
Adding eslint back to the template package.json

[Internal] [Fixed] - Add eslint back in template
Pull Request resolved: https://github.com/facebook/react-native/pull/27983

Test Plan:
(edited)
- npx react-native init RN062 --version 0.62.0-rc.1
- yarn add -d eslint
- add npm script for lint
- yarn lint

Differential Revision: D19784567

Pulled By: TheSavior

fbshipit-source-id: 9ce24c0b674c2b1ea9fee3ed5614e8922f992f72
2020-02-13 16:16:59 +01:00
Jorge BernalandEloy Durán 6d00239e49 Implement onRequestClose for iOS 13+ modals (#27618)
Summary:
Starting on iOS 13, a View Controller presented modally will have a "bottom sheet" style unless it's explicitly presented full screen.

Before this, modals on iOS were only being dismissed programatically by setting `visible={false}`. However, now that the dismissal can happen on the OS side, we need a callback to be able to update the state.

This PR reuses the `onRequestClose` prop already available for tvOS and Android, and makes it work on iOS for this use case.

Should fix https://github.com/facebook/react-native/issues/26892

## Changelog

[iOS] [Added] - Add support for onRequestClose prop to Modal on iOS 13+
Pull Request resolved: https://github.com/facebook/react-native/pull/27618

Test Plan:
I tested this using the RNTester app with the Modal example:

1. Select any presentation style other than the full screen ones
2. Tap Present and the modal is presented
3. Swipe down on the presented modal until dismissed
4. Tap Present again and a second modal should be presented

![Screen Recording 2019-12-26 at 14 05 33](https://user-images.githubusercontent.com/8739/71477208-0ac88c80-27e9-11ea-9342-8631426a9b80.gif)

Differential Revision: D19235758

Pulled By: shergin

fbshipit-source-id: c0f1d946c77ce8d1baab209eaef7eb64697851df
2020-02-13 16:08:41 +01:00
Panagiotis VekrisandEloy Durán cae662bfea Remove types-first from flowconfig template
Summary:
Removing the experimental types-first flag from RN templates, until these are properly documented in the docs. See https://github.com/facebook/flow/issues/8279 for context.

Changelog: [Internal]

Reviewed By: jbrown215

Differential Revision: D19728257

fbshipit-source-id: 8f7473b9c8383bd1eef76b5733ff3a26e2e554fc
2020-02-13 16:08:33 +01:00
Matt ChowningandEloy Durán 77305cadf0 Allow overriding EditText construction in ReactTextInputShadowNode (#27782)
Summary:
This PR makes it possible for subclasses of `ReactTextInputShadowNode` to control the construction of the "dummy" `EditText` instance that `ReactTextInputShadowNode` internally uses to determine the expected height of the view. This PR does not change the default behavior, it just opens up that default to being overriden.

This is useful in the case of custom views that have different behavior from a "default" `EditText` instance (`new EditText(context)`). For example, it might have a different style applied.

As a side benefit, this change also makes it easy to have subclasses not apply the default theme, which can allow the custom view to avoid a longstanding crash issue (https://github.com/facebook/react-native/issues/17530).

## Changelog

[Android] [Added] - Allow overriding `EditText` construction in `ReactTextInputShadowNode`
Pull Request resolved: https://github.com/facebook/react-native/pull/27782

Test Plan: All tests pass.

Reviewed By: mdvacca

Differential Revision: D19450593

Pulled By: JoshuaGross

fbshipit-source-id: 8d2ce6117246fc3e2108623312b38583af5722b3
2020-02-13 16:08:23 +01:00
Peter ArganyandEloy Durán 925330bb83 Fix animations in OSS debug builds by modifying Platform.isTesting() behaviour
Summary:
In D14244606 I "fixed" `Platform.isTesting()` in JS. By fixed, I made it return true when running SSTs.

People in OSS complained about this in discord and [github](https://github.com/facebook/react-native/issues/27010). The problem is that this call returns true whenever an RN project references Detox in the build.gradle file. In practice, this has been really annoying, because it has disabled animations in debug builds, due to D13811035.

The fix is to be more specific, and look for the exact screenshot test activity. I haven't explicitly verified this doesn't trigger from Detox, but it shouldn't. I'll coordinate on the github issue to verify.

Changelog: [Android][Fixed] Fix animations in OSS debug builds by modifying `Platform.isTesting()` behaviour

Reviewed By: TheSavior

Differential Revision: D19384098

fbshipit-source-id: 22c885219f2c00f5dcc3b930b068bfd2ad7e4b8e
2020-02-13 16:08:14 +01:00
Jason SafaiyehandEloy Durán d68013dd71 Make addCookies method public. (#27512)
Summary:
react-native-cookie-store wants the ability to set custom cookies on Android. We use ForwardingCookieHandler to mange the cookies. Exposing the `addCookies` method will allow the module to provide the same functionality on Android.

https://github.com/safaiyeh/react-native-cookie-store/issues/1

## Changelog

[Android] [Changed] - Expose addCookies method
Pull Request resolved: https://github.com/facebook/react-native/pull/27512

Test Plan: N/A

Differential Revision: D19236309

Pulled By: cpojer

fbshipit-source-id: bf1a0730165456c34c5bf432ac370176a881cbcf
2020-02-13 16:08:00 +01:00
Andy MatuschakandEloy Durán 80f5b6c110 Enabling RCTWebSocket on UIKitForMac (macOS Catalyst) (#27469)
Summary:
In https://github.com/facebook/react-native/issues/25427, radex added initial support for running React Native projects on macOS via Catalyst. However, `RCTWebSocket` was disabled for that target because of some compilation issues. This meant that running projects via a connection to the packager wasn't possible: no live reload, and projects must be run in "Release" mode. It also meant making manual changes to Xcode projects deploying to macOS and scattering a number of conditional checks throughout the codebase.

In this change, I've implemented support for `RCTWebSocket` on the macOS target and re-enabled the affected features. Live reload and the inspector now work for macOS targets. Manual modifications of Xcode build settings are no longer necessary for react-native projects running on macOS.

![Screen Shot 2019-12-10 at 8 36 38 AM](https://user-images.githubusercontent.com/2771/70549905-ce7b0800-1b29-11ea-85c6-07bf09811ae2.png)

### Limitations

There's no binding which displays the developer menu (since there's no shake event on macOS). We'll probably want to add one, perhaps to the menu bar.

I've chosen not to commit the modifications to RNTester which enable macOS support, since that would imply more "official" support for this target than I suspect you all would like to convey. I'm happy to add those chunks if it would be helpful.

## Changelog

[iOS] [Added] - Added web socket support for macOS (Catalyst), enabling debug builds and live reload
Pull Request resolved: https://github.com/facebook/react-native/pull/27469

Test Plan:
* Open RNTester/RNTester.xcodeproj with Xcode 11.2.1, run it like a normal iOS app -- make sure it compiles and runs correctly (no regression)
* Select "My Mac" as device target, and run. You may need to configure a valid development team to make signing work.
* RNTester should run fine with no additional configuration. Modify a file in RNTester, note that live reload is now working.
* Test the developer inspector. To display the developer menu, you'll need to manually show it; here's an example diff which does that:
```
 diff --git a/RNTester/js/RNTesterApp.ios.js b/RNTester/js/RNTesterApp.ios.js
index 8245a68d12..a447ad3b1b 100644
 --- a/RNTester/js/RNTesterApp.ios.js
+++ b/RNTester/js/RNTesterApp.ios.js
@@ -19,6 +19,8 @@ const React = require('react');
 const SnapshotViewIOS = require('./examples/Snapshot/SnapshotViewIOS.ios');
 const URIActionMap = require('./utils/URIActionMap');

+import NativeDevMenu from '../../Libraries/NativeModules/specs/NativeDevMenu';
+
 const {
   AppRegistry,
   AsyncStorage,
@@ -143,6 +145,7 @@ class RNTesterApp extends React.Component<Props, RNTesterNavigationState> {

   UNSAFE_componentWillMount() {
     BackHandler.addEventListener('hardwareBackPress', this._handleBack);
+    NativeDevMenu.show();
   }

   componentDidMount() {
```

Reviewed By: sammy-SC

Differential Revision: D18945861

Pulled By: hramos

fbshipit-source-id: edcf02c5803742c89a845a3e5d72bc7dacae839f
2020-02-13 16:07:37 +01:00
Eloy Durán 99ef72cad7 Add androidx.swiperefreshlayout to template build.gradle
Same as 2c89e51507, but for template.

Changelog: [Android] [Fixed] Template instacrash from missing androidx dependency
2020-02-13 16:00:05 +01:00
Eloy Durán b4d1fcfb2f Smoothen Flipper iOS integration (#28044)
Summary:
Addresses my feedback [here](https://github.com/facebook/react-native/issues/27565#issuecomment-580950480), [here](https://github.com/facebook/react-native/issues/27565#issuecomment-582490074), and [here](https://github.com/facebook/react-native/issues/27565#issuecomment-585456768).

## Changelog

[iOS] [Changed] - Updated Flipper iOS integration to be included by default in the `Debug` configuration
Pull Request resolved: https://github.com/facebook/react-native/pull/28044

Test Plan:
Manually tested that a new application from this template still works and that the Flipper integration works.

<img width="912" alt="Screenshot 2020-02-13 at 02 09 42" src="https://user-images.githubusercontent.com/2320/74391951-eb6fd800-4e05-11ea-9fde-7e0eb42c1ec4.png">

Differential Revision: D19871482

Pulled By: TheSavior

fbshipit-source-id: a805808fdd0c2dfdfe47dd59ffee02c81f3fdfa7
2020-02-13 14:47:47 +01:00
Pritesh NandgaonkarandEloy Durán 13cefd396c @allow-large-files [Flipper][RN] Integrated Flipper in RNTester application
Summary:
Changelog: [iOS] [Fixed]

Integrated Flipper in RNTester application and made sure that flipper connects with RNTester application

allow-large-files

Reviewed By: rickhanlonii

Differential Revision: D19813213

fbshipit-source-id: f0c7a5a42ffaccd488582b0f42ce37aea946c636
2020-02-13 14:33:47 +01:00
Pascal HartigandRick Hanlon e7bfa1fc2e Upgrade Flipper version (#27837)
Summary:
Depends on https://github.com/facebook/react-native/issues/27833.

Updates the Flipper version to the most recent release.

## Changelog

[Android] [Changed] - Upgrade Flipper version in default template
Pull Request resolved: https://github.com/facebook/react-native/pull/27837

Test Plan:
This is a bit annoying, but I can't test this against the 0.62-rc.0 version. I tried patching it by running `react-native init --version 0.62.0-rc.0  testproj`, which would fail because of a missing androidx dep. After adding `implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'` to the deps, that was fixed but now after updating, `libfbjni.so` is missing because my PR https://github.com/facebook/react-native/issues/27729 isn't part of the RN dependency yet.

Given that this mirrors the RNTester app, I'm pretty confident that the change here is otherwise correct and will work on top of master with the most recent template changes.

Differential Revision: D19619365

Pulled By: passy

fbshipit-source-id: 5723bd105ab3ab86b7f00e1a26e29e1e9dc58290
2020-02-05 14:10:50 +00:00
Eloy Durán 6a10d5dfd3 Remove FB copyright notices from iOS template (#27725)
Summary:
Files that are to be part of the user’s project shouldn’t have FB copyright notices.

There’s [one notice left](https://github.com/facebook/react-native/blob/66601e755fcad10698e61d20878d52194ad0e90c/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java#L2) in the `android` template, which is in a file that doesn’t seem to be intended to be changed by the user and so that seems fine to me.

[iOS] [Removed] - Remove copyright notices from iOS application template
Pull Request resolved: https://github.com/facebook/react-native/pull/27725

Test Plan:
```bash
npx react-native init TestTemplateUpdates --template ~/Code/ReactNative/react-native
cd ios
xcodebuild -workspace TestTemplateUpdates.xcworkspace \
  -scheme TestTemplateUpdates \
  -destination 'platform=iOS Simulator,OS=latest,name=iPhone 8' build
[…]
** BUILD SUCCEEDED **
```

Differential Revision: D19343386

Pulled By: TheSavior

fbshipit-source-id: a78be5e5d2fdc2477adedb51d6bb3ff19845b75f
2020-02-05 14:54:03 +01:00
Eloy Durán 60da5071a6 Make C++ requirement opt-in (#27730)
Summary:
When building as a framework these headers get automatically added to the framework umbrella header for React-Core. Instead of converting all the React sources to ObjC++ files and still forcing external users that build native source (and link against a framework build) to also compile as ObjC++, this makes the attribution related methods that were added in https://github.com/facebook/react-native/commit/fdcdca4 opt-in to ObjC++ builds.

This is also the reason for the current failure of the CI `test_ios_frameworks` run.

I’m unsure if this change really warrants an entry in the CHANGELOG, as it’s more of an amendment of the (afaik) unreleased [change](https://github.com/facebook/react-native/commit/fdcdca4).

[iOS] [Fixed] - Make framework builds work again by making `RCTImageLoader` C++ requirement opt-in
Pull Request resolved: https://github.com/facebook/react-native/pull/27730

Test Plan:
I tested static and dynamic (framework) builds and ran the test suite.

This change should make the `test_ios_frameworks` CI run _build_ again, ~~but it may still fail overall as in my local testing one of the tests leads to a segfault (which I will try to address separately)~~.

Reviewed By: PeteTheHeat

Differential Revision: D19348846

Pulled By: fkgozali

fbshipit-source-id: 8a74e6f7ad3ddce2cf10b080b9a5d7b399bd5fc0
2020-02-05 14:54:03 +01:00
Eloy Durán e3218a0d96 Remove empty Swift file for Flipper (#27922)
Summary:
Related to https://github.com/facebook/react-native/issues/27426 & https://github.com/facebook/react-native/issues/27565.

The wish to not include an empty Swift file to trigger the correct Xcode settings was voiced in https://github.com/facebook/react-native/issues/27426 & https://github.com/facebook/react-native/issues/27565.

[iOS] [Fixed] - Remove need for Swift file in the user’s project in order to use Flipper
Pull Request resolved: https://github.com/facebook/react-native/pull/27922

Test Plan:
An application created with the template, like so:

```bash
react-native init --template=~/Code/React/react-native TestFlipper
```

…will successfully build, launch, and have Flipper connect.

Differential Revision: D19690592

Pulled By: cpojer

fbshipit-source-id: ee696e0d747d6338534b0c2d62029e64ece02cd3
2020-02-05 14:54:03 +01:00
Rick Hanlon 2c89e51507 Add androidx.swiperefreshlayout to RNTester build.gradle
Summary:
Suggested fix from passy

Changelog: [General] [Fixed] RNTester instacrash from missing androidx dependency

Reviewed By: passy

Differential Revision: D19741935

fbshipit-source-id: 62e02169a92b7418471d2228a3d75ffffbe7a6a6
2020-02-05 13:27:30 +00:00
Pascal HartigandRick Hanlon 6f00f5f6b8 Remove NativeRunnableDeprecated (#27529)
Summary:
The class was deprecated in 2016 and is blocking an upgrade to fbjni
which no longer supports the `Countable` class this extends.

Changelog:
[Android] [Removed] - NativeRunnableDeprecated
Pull Request resolved: https://github.com/facebook/react-native/pull/27529

Test Plan: No references to it in this codebase.

Reviewed By: mdvacca

Differential Revision: D19087074

Pulled By: passy

fbshipit-source-id: a4ee73be7c13cedf1d86d2643f8e788ad4a2e31f
2020-02-05 11:33:06 +00:00
Jason SafaiyehandRick Hanlon 05f5cb534f initalizeFlipper should be set in template app by default (#27569)
Summary:
Issue: https://github.com/facebook/react-native/issues/27565

initalizeFlipper should be set in template app by default.

## Changelog

[iOS] [Changed] - Added Flipper to template app
[Android] [Changed] - Added Flipper to template app
Pull Request resolved: https://github.com/facebook/react-native/pull/27569

Test Plan:
Connect Flipper to the iOS application
Connect Flipper to the Android application

Reviewed By: passy

Differential Revision: D19344704

Pulled By: rickhanlonii

fbshipit-source-id: ca126fd2caab13751ddc2ce6d195bd0c644c704e
2020-02-05 11:04:26 +00:00
Jason SafaiyehandRick Hanlon 79e38e7d8e Integrate Flipper in RNTester on Android (#27631)
Summary:
0.62 Flipper Support items: https://github.com/facebook/react-native/issues/27565
Made RNTester's Android Flipper implementation consistent with the template.
~~Added Flipper to the iOS build.~~
<img width="1259" alt="Screen Shot 2019-12-28 at 7 06 42 PM" src="https://user-images.githubusercontent.com/8675043/71551835-37290800-29a5-11ea-9eac-b119a69a68c1.png">

## Changelog

[Internal] [Added] - RNTester Android Fipper updates
Pull Request resolved: https://github.com/facebook/react-native/pull/27631

Test Plan: Run RNTester and see if it connects to Flipper.

Reviewed By: rickhanlonii

Differential Revision: D19345093

Pulled By: passy

fbshipit-source-id: 6957c1ca3f4a5bb7f0e581c5daf8ddeac5d87eea
2020-02-05 11:04:03 +00:00
Pascal HartigandRick Hanlon b86f16aa4e Use new Flipper SDK (#27833)
Summary:
The FBJNI compat issue is gone so this is working now. �

Still a bit ugly to set up, but that's on our ToDo. Next: Template.

## Changelog

[Android] [Fixed] - Use modern Flipper SDK version for RNTester
Pull Request resolved: https://github.com/facebook/react-native/pull/27833

Test Plan:
```
./gradlew :RNTester:android:app:installHermesDebug
```

![Screenshot 2020-01-22 at 09 30 22](https://user-images.githubusercontent.com/9906/72883088-9c012500-3cfb-11ea-9997-b38831196259.png)

Reviewed By: cpojer

Differential Revision: D19513412

Pulled By: passy

fbshipit-source-id: af118bd364ab316732e2a1e657fa1b682bf7da59
2020-02-05 11:03:42 +00:00
Pascal HartigandRick Hanlon 4d9385d531 Fix BUCK build (#27826)
Summary:
This fixes a build failure with buck introduced with https://github.com/facebook/react-native/issues/27729. The internal and external buck overlays diverged in how fbjni was imported. The Buck re-export here ensures that the targets resolve both internall and externally.

## Changelog

[Android] [Fixed] - RNTester Buck Build
Pull Request resolved: https://github.com/facebook/react-native/pull/27826

Test Plan:
buck fetch rntester
buck build rntester

Reviewed By: jknoxville

Differential Revision: D19496769

Pulled By: passy

fbshipit-source-id: d699a5f64f691ed375cfc7a9d6a5a6f6e36ba283
2020-02-05 11:03:23 +00:00
Pascal HartigandRick Hanlon 8c11d3ffce Migrate to FBJNI (#27729)
Summary:
This is an incomplete effort to migrate from libfb to libfbjni. This is needed to restore the compatibility with Flipper and other FB Android projects that make use of FBJNI. Effectively, the outcome is that `fbjni` no longer has a checked-in copy here, but instead relies on the public artifacts published at github.com/facebookincubator/fbjni that can be deduplicated at build-time.

**A non-exhaustive list of tasks:**

* [X] Gradle builds the SDK and RNTester for Android.
* [X] Buck build for rntester works in OSS.
* [ ] Move from `java-only` release to full `fbjni` release. This requires finding a solution for stripping out `.so` files that the old `Android.mk` insists on including in the final artifacts and will clash with the full distribution.
* [ ] Import this and fix potential internal build issues.
* [ ] Verify that the changes made to the Hermes integration don't have any unintended consequences.

## Changelog

[Android] [Changed] - Migrated from libfb to libfbjni for JNI calls
Pull Request resolved: https://github.com/facebook/react-native/pull/27729

Test Plan:
- CI is already passing again for Gradle and Buck in OSS.
- After applying the following patch, RNTester builds and works with the latest Flipper SDK:

```
 diff --git a/RNTester/android/app/build.gradle b/RNTester/android/app/build.gradle
index b8a6437d7..eac942104 100644
 --- a/RNTester/android/app/build.gradle
+++ b/RNTester/android/app/build.gradle
@@ -170,10 +170,19 @@ dependencies {
     debugImplementation files(hermesPath + "hermes-debug.aar")
     releaseImplementation files(hermesPath + "hermes-release.aar")

-    debugImplementation("com.facebook.flipper:flipper:0.23.4") {
+    debugImplementation("com.facebook.flipper🐬+") {
         exclude group:'com.facebook.yoga'
-        exclude group:'com.facebook.flipper', module: 'fbjni'
-        exclude group:'com.facebook.litho', module: 'litho-annotations'
+        exclude group:'com.facebook.fbjni'
+    }
+
+    debugImplementation("com.facebook.flipper:flipper-network-plugin:+") {
+        exclude group:'com.facebook.yoga'
+        exclude group:'com.facebook.fbjni'
+    }
+
+    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:+") {
+        exclude group:'com.facebook.yoga'
+        exclude group:'com.facebook.fbjni'
     }

     if (useIntlJsc) {
```

Reviewed By: mdvacca

Differential Revision: D19345270

Pulled By: passy

fbshipit-source-id: 33811e7f97f44f2ec5999e1c35339909dc4fd3b1
2020-02-05 11:02:13 +00:00
Pascal HartigandRick Hanlon 89eb287be1 clang-format cpp
Summary:
Ran `arc f` against some CPP files to be modified with the next diff
to reduce the churn on it.

## Changelog

[Android] [Changed] - Formatted cpp/h code with clang-format

Reviewed By: javache

Differential Revision: D19371785

fbshipit-source-id: b7f7b92c4cb9ec7f8da728bb577db29cf11fbb39
2020-02-05 11:01:55 +00:00
Pascal HartigandRick Hanlon 3c3b4cf575 Fix RNTester integration with Flipper (#27482)
Summary:
There was a reflective call to a non-existent class. It did, however,
exist in the template, so I copied it over from there and updated
the references accordingly.
Pull Request resolved: https://github.com/facebook/react-native/pull/27482

Test Plan:
Built it and ran it. Works again with the latest Flipper desktop app.

![Screenshot 2019-12-11 16 02 40](https://user-images.githubusercontent.com/9906/70637975-02405580-1c30-11ea-9fec-23860c59cdb6.png)

Reviewed By: rickhanlonii

Differential Revision: D18933530

Pulled By: passy

fbshipit-source-id: 4515d7baaad9a9fff9a4b66e1cbf8a75889e6e45
2020-01-29 11:10:11 +00:00
brotskyandRick Hanlon 8f954b3659 Edits to flipper pods comments (#27485)
Summary:
grammar edits

## Changelog

[Internal] [Fixed] - Edits to flipper pods comments
Pull Request resolved: https://github.com/facebook/react-native/pull/27485

Differential Revision: D18962196

Pulled By: hramos

fbshipit-source-id: d8eb8b852130b9ceee8ab9b668f94d9d4d11a217
2020-01-29 11:07:39 +00:00
Lorenzo Sciandra 2bf7f1046d [0.62.0-rc.1] Bump version numbers 2020-01-21 08:27:36 +00:00
Rick Hanlon 5b4816741b LogBox - Double sync rendering timeout
Summary:
On slower devices , 0.5s is not fast enough and we frequently render a black screen. Let's bump the sync rendering timeout to 1s.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D19282619

fbshipit-source-id: 0d9ae60f4869b0de7c4523c2cb33fbbf320c6438
2020-01-07 06:55:57 -05:00
sunnylqmandRick Hanlon 39e5a83062 Fix android modal not disappear when reload (#27542)
Summary:
Fixes https://github.com/facebook/react-native/issues/17986

See above issue

After apply this change:
![ezgif-4-45d9add85b74](https://user-images.githubusercontent.com/615282/70987576-2520ad00-20fb-11ea-9b90-c9a7839824a5.gif)

## Changelog

[Android] [Fixed] - Fix android modal not disappear when reload
Pull Request resolved: https://github.com/facebook/react-native/pull/27542

Test Plan: Open a modal and do a refresh to see whether it disappears

Differential Revision: D19178803

Pulled By: mdvacca

fbshipit-source-id: 61894927fc481650804b2196df06a80c16b64e6c
2019-12-20 09:47:45 -05:00
Rick Hanlon fe348ab53d LogBox fixes for OSS
Summary:
This diff fixes two issues with LogBox in OSS.

Changelog: [Internal]

Reviewed By: mmmulani

Differential Revision: D19165696

fbshipit-source-id: 4dd9c480ea3d2b205f8e65cb32203949b1e32e8a
2019-12-19 07:32:26 -05:00
Rick Hanlon 0fd83e4786 LogBox - lazily initialize on iOS, use sync APIs
Summary:
Update LogBox on iOS to lazily initialize, using a synchronous RCTSurface, behind RCTSharedApplication checks.

This results in faster of LogBox, without keeping around a long lived window in the background, and only used when LogBox is used.

On Android, we still start the react app in the background but we create a dialog when it's shown and then destroy it when it's hidden. Once we have the sync APIs on android we can update it to use the same strategy.

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D18925538

fbshipit-source-id: 1a72c39aa0fc26c8ba657d36c7fa7bc0ae777eb9
2019-12-19 07:30:59 -05:00
Kevin GozaliandRick Hanlon e97baa6066 LogBox iOS: don't initialize logbox window if redbox flag is disabled
Summary:
If redbox flag is disabled, don't initialize LogBox window even if the native module exists. This makes the module noop.

Changelog: [Internal]

Reviewed By: shergin

Differential Revision: D18927309

fbshipit-source-id: 3dc6c08ed537925594cabf77d1142568d47132e9
2019-12-19 07:30:59 -05:00
Rick Hanlon 76557f00d7 Add WarningFilter handling for YellowBox
Summary:
This diff backports warning filter handling to yellow box. I also backported the skipped warning handling so that ignored patterns do not log to the console, same as LogBox.

Changelog: [Internal]

Reviewed By: gaearon

Differential Revision: D18573288

fbshipit-source-id: 5bf8e86f754adc808313d7ed02f98daaf65de98c
2019-12-19 07:30:59 -05:00
Rick Hanlon 4693170d63 Hotfix - register null logbox outside of dev
Summary:
Outside of __DEV__ the app may still try to use LogBox. We're going to fix that but until we do, if it tries to use LogBox outside of dev render null.

Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D18932666

fbshipit-source-id: ef0f2542a295dc9332cae8b77faed78f8be350fe
2019-12-19 07:30:59 -05:00
Rick Hanlon 51dcb0195b Disable LogBox if native module is not available
Summary: Changelog: [Internal]

Reviewed By: mmmulani

Differential Revision: D18920345

fbshipit-source-id: e5213dc9c3a1aa775138e71a8040a3472e9bbd67
2019-12-19 07:30:59 -05:00
Lorenzo Sciandra 203f3e3399 [0.62.0-rc.0] Bump version numbers 2019-12-18 15:36:07 +00:00
Spencer AhrensandHéctor Ramos e7c289b56e emit Dimensions change enent when app goes split screen
Summary:
Fixes https://github.com/facebook/react-native/issues/26830 by removing version gating around `RCTUserInterfaceStyleDidChangeNotification` sent by `RCTRootView` and observing that notif for `Dimensions` changes.

Also centralizes `RCTUserInterfaceStyleDidChangeNotification` constant definition in new `RCTConstants` file.

Changelog:
[iOS] [Fixed] - `Dimensions` module now updates on initial split screen

Reviewed By: sammy-SC

Differential Revision: D18931098

fbshipit-source-id: e9784be3f544f3b10360fbc2d6ad0324273b1a8f
2019-12-11 14:05:45 -08:00
Rick Hanlon 3cfbae6540 Fix logs stuck in pending symbolocated state
Summary:
This diff fixes an issue where symbolicated logs were getting stuck in a "pending" state if the timeout occurred before symbolication finished.

Changelog: [Internal]

Reviewed By: sahrens

Differential Revision: D18894154

fbshipit-source-id: ed225962468f67aef40e430aa798f8d426d31027
2019-12-10 19:53:38 +00:00
Rick Hanlon 3fd98d95ef RN DevX] LogBox - Handle tapping component stacks if possible
Summary:
This diff adds handling for tapping to open components in component stacks, whenever they're available.

Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D18882338

fbshipit-source-id: 574bff1c41c952c33e647cb142d278ace60b4631
2019-12-10 19:53:29 +00:00
Rick Hanlon c194ed2dbb Add unstable_enableLogBox
Summary:
This diff adds a new `unstable_enableLogBox` function to opt-into the new LogBox experience. If LogBox is not enabled early enough, we show an error with instructions.

With this, LogBox can be enabled with:

```
require('react-native').unstable_enableLogBox();
```

Changelog: [General] [Adds] unstable_enableLogBox

Reviewed By: zackargyle, rubennorte

Differential Revision: D18808940

fbshipit-source-id: 4b0234ddc4d1646515bf63110d5b02133780512e
2019-12-10 19:53:18 +00:00
Rick Hanlon 93bbab3878 LogBox - Update to use it's own root for the inspector
Summary:
Apologies for the large diff, it was difficult to break down.

This diff is a major refactor of LogBox that:
- Separates LogBoxNotification and LogBoxInspector
- Moves them each to their own container
- Updates AppContainer to only render the notification
- Updates the native logbox root to render the inspector
- Adds withSubscription HOC to manage subscribing to LogBoxData
- Simplifies LogBox to export an object instead of a component

Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D18750011

fbshipit-source-id: 639885d29e55e125892d1c2b6bbf2826f27d78db
2019-12-10 19:53:09 +00:00
Rick Hanlon 1a305fd79b Add NativeLogBox module on Android
Summary:
This diff adds a NativeLogBox module implementation on Android to manage rendering LogBox the way we render RedBox, except rendering a React Native component instead of a native view.

The strategy here is:
- initialize: will create a React rootview and render it.
- show: will add the rootview to a dialog and display the dialog.
- hide: will remove the rootview from it's parent, dismiss the dialog, and release the reference to the activity to prevent leaks.

Most of this is copied from the way RedBox works, the difference here is that we eagerly initialize the rootview with the `initialize` function so that it's warm by the time the dialog needs to render.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D18768517

fbshipit-source-id: 2510d6c186ccf73153ef9372c736c9e0c71bbc7d
2019-12-10 19:52:58 +00:00
Rick Hanlon 45a43241cd Add NativeLogBox module on iOS
Summary:
This diff adds a NativeLogBox module implementation on iOS to manage rendering LogBox the way we render RedBox, except rendering a React Native component instead of a native view.

The strategy here is:
- initialize: will create a hidden window (the way redbox does) and render the LogBox to it
- show: will show the window
- hide: will hide the window

Most of this is copied from the way RedBox works, the difference here is that we eagerly initialize the window with the `initialize` function so that it's warm by the time LogBox needs to render.

Changelog: [Internal]

Reviewed By: RSNara

Differential Revision: D18750008

fbshipit-source-id: 013e55ded55c8572bb08e0219ff4cd0060ebe0da
2019-12-10 19:52:44 +00:00
Rick Hanlon 041c392ec9 Register LogBox by default in dev
Summary:
This diff stubs out registering LogBox as a renderable component. In later diffs, we'll render this component on the native side.

Changelog: [Internal]

Reviewed By: motiz88

Differential Revision: D18750005

fbshipit-source-id: 4db082ca2104731641d2d10de1ba83a318ab44fb
2019-12-10 19:52:23 +00:00
312 changed files with 5657 additions and 11142 deletions
+1
View File
@@ -8,6 +8,7 @@
[maven_repositories]
central = https://repo1.maven.org/maven2
google = https://maven.google.com/
jcenter = https://jcenter.bintray.com/
[alias]
rntester = //RNTester/android/app:app
+6 -2
View File
@@ -568,11 +568,15 @@ jobs:
# -------------------------
# JOBS: Releases
# -------------------------
# Publishes new version onto npm
# Only works on stable branches when a properly tagged commit is pushed
# Publishes a new version onto npm
publish_npm_package:
executor: reactnativeandroid
steps:
- run:
name: Add github.com to SSH known hosts
command: |
mkdir -p ~/.ssh
echo '|1|If6MU203eXTaaWL678YEfWkVMrw=|kqLeIAyTy8pzpj8x8Ae4Fr8Mtlc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
- restore_cache_checkout:
checkout_type: android
- run_yarn
+5 -5
View File
@@ -18,13 +18,13 @@ const ReactNative = require('../Renderer/shims/ReactNative');
const TextInputState = require('./TextInput/TextInputState');
const UIManager = require('../ReactNative/UIManager');
const Platform = require('../Utilities/Platform');
const ScrollView = require('./ScrollView/ScrollView');
import Commands from './ScrollView/ScrollViewCommands';
const invariant = require('invariant');
const performanceNow = require('fbjs/lib/performanceNow');
import type {PressEvent, ScrollEvent} from '../Types/CoreEventTypes';
import typeof ScrollView from './ScrollView/ScrollView';
import type {Props as ScrollViewProps} from './ScrollView/ScrollView';
import type {KeyboardEvent} from './Keyboard/Keyboard';
import type EmitterSubscription from '../vendor/emitter/EmitterSubscription';
@@ -468,7 +468,7 @@ const ScrollResponderMixin = {
({x, y, animated} = x || {});
}
const that: React.ElementRef<typeof ScrollView> = (this: any);
const that: React.ElementRef<ScrollView> = (this: any);
invariant(
that.getNativeScrollRef != null,
'Expected scrollTo to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native',
@@ -492,7 +492,7 @@ const ScrollResponderMixin = {
// Default to true
const animated = (options && options.animated) !== false;
const that: React.ElementRef<typeof ScrollView> = (this: any);
const that: React.ElementRef<ScrollView> = (this: any);
invariant(
that.getNativeScrollRef != null,
'Expected scrollToEnd to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native',
@@ -531,7 +531,7 @@ const ScrollResponderMixin = {
);
}
const that: React.ElementRef<typeof ScrollView> = this;
const that: React.ElementRef<ScrollView> = this;
invariant(
that.getNativeScrollRef != null,
'Expected zoomToRect to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native',
@@ -547,7 +547,7 @@ const ScrollResponderMixin = {
* Displays the scroll indicators momentarily.
*/
scrollResponderFlashScrollIndicators: function() {
const that: React.ElementRef<typeof ScrollView> = (this: any);
const that: React.ElementRef<ScrollView> = (this: any);
invariant(
that.getNativeScrollRef != null,
'Expected flashScrollIndicators to be called on a scrollViewRef. If this exception occurs it is likely a bug in React Native',
+1 -1
View File
@@ -83,7 +83,7 @@ function reportException(e: ExtendedError, isFatal: boolean) {
e.jsEngine == null ? message : `${message}, js engine: ${e.jsEngine}`;
const isHandledByLogBox =
e.forceRedbox !== true && global.__reactExperimentalLogBox;
e.forceRedbox !== true && global.__unstable_isLogBoxEnabled === true;
const data = preprocessException({
message,
+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,
patch: 0,
minor: 62,
patch: 2,
prerelease: null,
};
@@ -1671,6 +1671,33 @@ namespace facebook {
}
} // namespace react
} // namespace facebook
namespace facebook {
namespace react {
static facebook::jsi::Value __hostFunction_NativeLogBoxSpecJSI_show(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "show", @selector(show), args, count);
}
static facebook::jsi::Value __hostFunction_NativeLogBoxSpecJSI_hide(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "hide", @selector(hide), args, count);
}
NativeLogBoxSpecJSI::NativeLogBoxSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<CallInvoker> jsInvoker)
: ObjCTurboModule("LogBox", instance, jsInvoker) {
methodMap_["show"] = MethodMetadata {0, __hostFunction_NativeLogBoxSpecJSI_show};
methodMap_["hide"] = MethodMetadata {0, __hostFunction_NativeLogBoxSpecJSI_hide};
}
} // namespace react
@@ -1771,6 +1771,25 @@ namespace facebook {
};
} // namespace react
} // namespace facebook
@protocol NativeLogBoxSpec <RCTBridgeModule, RCTTurboModule>
- (void)show;
- (void)hide;
@end
namespace facebook {
namespace react {
/**
* ObjC++ class for module 'LogBox'
*/
class JSI_EXPORT NativeLogBoxSpecJSI : public ObjCTurboModule {
public:
NativeLogBoxSpecJSI(id<RCTTurboModule> instance, std::shared_ptr<CallInvoker> jsInvoker);
};
} // namespace react
} // namespace facebook
@protocol NativeModalManagerSpec <RCTBridgeModule, RCTTurboModule>
- (void)addListener:(NSString *)eventName;
@@ -2766,7 +2785,7 @@ namespace facebook {
} // namespace facebook
@protocol NativeVibrationSpec <RCTBridgeModule, RCTTurboModule>
- (void)vibrate:(NSNumber *)pattern;
- (void)vibrate:(double)pattern;
- (void)vibrateByPattern:(NSArray *)pattern
repeat:(double)repeat;
- (void)cancel;
@@ -12,6 +12,8 @@
@protocol RCTImageLoaderWithAttributionProtocol<RCTImageLoaderProtocol>
// TODO (T61325135): Remove C++ checks
#ifdef __cplusplus
/**
* Same as the variant in RCTImageURLLoaderProtocol, but allows passing attribution
* information that each image URL loader can process.
@@ -25,5 +27,6 @@
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
#endif
@end
@@ -7,6 +7,8 @@
#import <React/RCTImageURLLoader.h>
// TODO (T61325135): Remove C++ checks
#ifdef __cplusplus
namespace facebook {
namespace react {
@@ -17,6 +19,7 @@ struct ImageURLLoaderAttribution {
} // namespace react
} // namespace facebook
#endif
/**
* Same as the RCTImageURLLoader interface, but allows passing in optional `attribution` information.
@@ -24,6 +27,8 @@ struct ImageURLLoaderAttribution {
*/
@protocol RCTImageURLLoaderWithAttribution <RCTImageURLLoader>
// TODO (T61325135): Remove C++ checks
#ifdef __cplusplus
/**
* Same as the RCTImageURLLoader variant above, but allows optional `attribution` information.
*/
@@ -35,5 +40,6 @@ struct ImageURLLoaderAttribution {
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;
#endif
@end
+10 -11
View File
@@ -1169,8 +1169,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
componentDidUpdate(prevProps: Props) {
const {data, extraData} = this.props;
if (data !== prevProps.data || extraData !== prevProps.extraData) {
this._hasDataChangedSinceEndReached = true;
// clear the viewableIndices cache to also trigger
// the onViewableItemsChanged callback with the new data
this._viewabilityTuples.forEach(tuple => {
@@ -1199,7 +1197,6 @@ class VirtualizedList extends React.PureComponent<Props, State> {
_fillRateHelper: FillRateHelper;
_frames = {};
_footerLength = 0;
_hasDataChangedSinceEndReached = true;
_hasDoneInitialScroll = false;
_hasInteracted = false;
_hasMore = false;
@@ -1491,20 +1488,22 @@ class VirtualizedList extends React.PureComponent<Props, State> {
} = this.props;
const {contentLength, visibleLength, offset} = this._scrollMetrics;
const distanceFromEnd = contentLength - visibleLength - offset;
const threshold = onEndReachedThreshold
? onEndReachedThreshold * visibleLength
: 0;
if (
onEndReached &&
this.state.last === getItemCount(data) - 1 &&
/* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.63 was deployed. To see the error delete this
* comment and run Flow. */
distanceFromEnd < onEndReachedThreshold * visibleLength &&
(this._hasDataChangedSinceEndReached ||
this._scrollMetrics.contentLength !== this._sentEndForContentLength)
distanceFromEnd < threshold &&
this._scrollMetrics.contentLength !== this._sentEndForContentLength
) {
// Only call onEndReached once for a given dataset + content length.
this._hasDataChangedSinceEndReached = false;
// Only call onEndReached once for a given content length
this._sentEndForContentLength = this._scrollMetrics.contentLength;
onEndReached({distanceFromEnd});
} else if (distanceFromEnd > threshold) {
// If the user scrolls away from the end and back again cause
// an onEndReached to be triggered again
this._sentEndForContentLength = 0;
}
}
+133 -25
View File
@@ -10,6 +10,7 @@
('use strict');
import * as React from 'react';
import LogBoxLog from './LogBoxLog';
import {parseLogBoxException} from './parseLogBoxLog';
import type {LogLevel} from './LogBoxLog';
@@ -21,7 +22,7 @@ import type {
} from './parseLogBoxLog';
import parseErrorStack from '../../Core/Devtools/parseErrorStack';
import type {ExtendedError} from '../../Core/Devtools/parseErrorStack';
import NativeLogBox from '../../NativeModules/specs/NativeLogBox';
export type LogBoxLogs = Set<LogBoxLog>;
export type LogData = $ReadOnly<{|
level: LogLevel,
@@ -73,7 +74,7 @@ let warningFilter: WarningFilter = function(format) {
return {
finalFormat: format,
forceDialogImmediately: false,
suppressDialog_LEGACY: false,
suppressDialog_LEGACY: true,
suppressCompletely: false,
monitorEvent: 'unknown',
monitorListVersion: 0,
@@ -85,20 +86,6 @@ const LOGBOX_ERROR_MESSAGE =
'An error was thrown when attempting to render log messages via LogBox.';
function getNextState() {
const logArray = Array.from(logs);
let index = logArray.length - 1;
while (index >= 0) {
// The latest syntax error is selected and displayed before all other logs.
if (logArray[index].level === 'syntax') {
return {
logs,
isDisabled: _isDisabled,
selectedLogIndex: index,
};
}
index -= 1;
}
return {
logs,
isDisabled: _isDisabled,
@@ -174,9 +161,10 @@ function appendNewLog(newLog) {
let addPendingLog = () => {
logs.add(newLog);
if (_selectedIndex <= 0) {
_selectedIndex = logs.size - 1;
setSelectedLog(logs.size - 1);
} else {
handleUpdate();
}
handleUpdate();
addPendingLog = null;
};
@@ -190,8 +178,14 @@ function appendNewLog(newLog) {
if (addPendingLog && status !== 'PENDING') {
addPendingLog();
clearTimeout(optimisticTimeout);
} else if (status !== 'PENDING') {
// The log has already been added but we need to trigger a render.
handleUpdate();
}
});
} else if (newLog.level === 'syntax') {
logs.add(newLog);
setSelectedLog(logs.size - 1);
} else {
logs.add(newLog);
handleUpdate();
@@ -255,21 +249,42 @@ export function symbolicateLogLazy(log: LogBoxLog) {
export function clear(): void {
if (logs.size > 0) {
logs = new Set();
_selectedIndex = -1;
handleUpdate();
setSelectedLog(-1);
}
}
export function setSelectedLog(index: number): void {
_selectedIndex = index;
export function setSelectedLog(proposedNewIndex: number): void {
const oldIndex = _selectedIndex;
let newIndex = proposedNewIndex;
const logArray = Array.from(logs);
let index = logArray.length - 1;
while (index >= 0) {
// The latest syntax error is selected and displayed before all other logs.
if (logArray[index].level === 'syntax') {
newIndex = index;
break;
}
index -= 1;
}
_selectedIndex = newIndex;
handleUpdate();
if (NativeLogBox) {
setTimeout(() => {
if (oldIndex < 0 && newIndex >= 0) {
NativeLogBox.show();
} else if (oldIndex >= 0 && newIndex < 0) {
NativeLogBox.hide();
}
}, 0);
}
}
export function clearWarnings(): void {
const newLogs = Array.from(logs).filter(log => log.level !== 'warn');
if (newLogs.length !== logs.size) {
logs = new Set(newLogs);
_selectedIndex = -1;
setSelectedLog(-1);
handleUpdate();
}
}
@@ -280,8 +295,7 @@ export function clearErrors(): void {
);
if (newLogs.length !== logs.size) {
logs = new Set(newLogs);
_selectedIndex = -1;
handleUpdate();
setSelectedLog(-1);
}
}
@@ -369,3 +383,97 @@ export function observe(observer: Observer): Subscription {
},
};
}
type Props = $ReadOnly<{||}>;
type State = $ReadOnly<{|
logs: LogBoxLogs,
isDisabled: boolean,
hasError: boolean,
selectedLogIndex: number,
|}>;
type SubscribedComponent = React.AbstractComponent<
$ReadOnly<{|
logs: $ReadOnlyArray<LogBoxLog>,
isDisabled: boolean,
selectedLogIndex: number,
|}>,
>;
export function withSubscription(
WrappedComponent: SubscribedComponent,
): React.AbstractComponent<{||}> {
class LogBoxStateSubscription extends React.Component<Props, State> {
static getDerivedStateFromError() {
return {hasError: true};
}
componentDidCatch(err: Error, errorInfo: {componentStack: string, ...}) {
reportLogBoxError(err, errorInfo.componentStack);
}
_subscription: ?Subscription;
state = {
logs: new Set(),
isDisabled: false,
hasError: false,
selectedLogIndex: -1,
};
render(): React.Node {
if (this.state.hasError) {
// This happens when the component failed to render, in which case we delegate to the native redbox.
// We can't show anyback fallback UI here, because the error may be with <View> or <Text>.
return null;
}
return (
<WrappedComponent
logs={Array.from(this.state.logs)}
isDisabled={this.state.isDisabled}
selectedLogIndex={this.state.selectedLogIndex}
/>
);
}
componentDidMount(): void {
this._subscription = observe(data => {
this.setState(data);
});
}
componentWillUnmount(): void {
if (this._subscription != null) {
this._subscription.unsubscribe();
}
}
_handleDismiss = (): void => {
// Here we handle the cases when the log is dismissed and it
// was either the last log, or when the current index
// is now outside the bounds of the log array.
const {selectedLogIndex, logs: stateLogs} = this.state;
const logsArray = Array.from(stateLogs);
if (selectedLogIndex != null) {
if (logsArray.length - 1 <= 0) {
setSelectedLog(-1);
} else if (selectedLogIndex >= logsArray.length - 1) {
setSelectedLog(selectedLogIndex - 1);
}
dismiss(logsArray[selectedLogIndex]);
}
};
_handleMinimize = (): void => {
setSelectedLog(-1);
};
_handleSetSelectedLog = (index: number): void => {
setSelectedLog(index);
};
}
return LogBoxStateSubscription;
}
@@ -25,7 +25,13 @@ function getLogBoxLog() {
message: {content: '...', substitutions: []},
stack: createStack(['A', 'B', 'C']),
category: 'Message category...',
componentStack: [{component: 'LogBoxLog', location: 'LogBoxLog.js:1'}],
componentStack: [
{
content: 'LogBoxLog',
fileName: 'LogBoxLog.js',
location: {column: -1, row: 1},
},
],
codeFrame: {
fileName: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js',
location: {row: 199, column: 0},
@@ -69,7 +75,11 @@ describe('LogBoxLog', () => {
expect(log.stack).toEqual(createStack(['A', 'B', 'C']));
expect(log.category).toEqual('Message category...');
expect(log.componentStack).toEqual([
{component: 'LogBoxLog', location: 'LogBoxLog.js:1'},
{
content: 'LogBoxLog',
fileName: 'LogBoxLog.js',
location: {column: -1, row: 1},
},
]);
expect(log.codeFrame).toEqual({
fileName: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js',
@@ -117,8 +117,16 @@ describe('parseLogBoxLog', () => {
]),
).toEqual({
componentStack: [
{component: 'MyComponent', location: 'filename.js:1'},
{component: 'MyOtherComponent', location: 'filename2.js:1'},
{
content: 'MyComponent',
fileName: 'filename.js',
location: {column: -1, row: 1},
},
{
content: 'MyOtherComponent',
fileName: 'filename2.js',
location: {column: -1, row: 1},
},
],
category:
'Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?%s',
@@ -143,8 +151,16 @@ describe('parseLogBoxLog', () => {
]),
).toEqual({
componentStack: [
{component: 'MyComponent', location: 'filename.js:1'},
{component: 'MyOtherComponent', location: 'filename2.js:1'},
{
content: 'MyComponent',
fileName: 'filename.js',
location: {column: -1, row: 1},
},
{
content: 'MyOtherComponent',
fileName: 'filename2.js',
location: {column: -1, row: 1},
},
],
category: 'Some kind of message',
message: {
@@ -164,8 +180,16 @@ describe('parseLogBoxLog', () => {
]),
).toEqual({
componentStack: [
{component: 'MyComponent', location: 'filename.js:1'},
{component: 'MyOtherComponent', location: 'filename2.js:1'},
{
content: 'MyComponent',
fileName: 'filename.js',
location: {column: -1, row: 1},
},
{
content: 'MyOtherComponent',
fileName: 'filename2.js',
location: {column: -1, row: 1},
},
],
category:
'Some kind of message Some other kind of message Some third kind of message',
@@ -418,12 +442,14 @@ Please follow the instructions at: fburl.com/rn-remote-assets`,
},
componentStack: [
{
component: 'MyComponent',
location: 'filename.js:1',
content: 'MyComponent',
fileName: 'filename.js',
location: {column: -1, row: 1},
},
{
component: 'MyOtherComponent',
location: 'filename2.js:1',
content: 'MyOtherComponent',
fileName: 'filename2.js',
location: {column: -1, row: 1},
},
],
stack: [
+12 -10
View File
@@ -42,12 +42,7 @@ export type Message = $ReadOnly<{|
>,
|}>;
export type ComponentStack = $ReadOnlyArray<
$ReadOnly<{|
component: string,
location: string,
|}>,
>;
export type ComponentStack = $ReadOnlyArray<CodeFrame>;
const SUBSTITUTION = UTFSequence.BOM + '%s';
@@ -127,6 +122,7 @@ export function parseCategory(
},
};
}
export function parseComponentStack(message: string): ComponentStack {
return message
.split(/\n {4}in /g)
@@ -134,11 +130,17 @@ export function parseComponentStack(message: string): ComponentStack {
if (!s) {
return null;
}
let [component, location] = s.split(/ \(at /);
if (!location) {
[component, location] = s.split(/ \(/);
const match = s.match(/(.*) \(at (.*\.js):([\d]+)\)/);
if (!match) {
return null;
}
return {component, location: location && location.replace(')', '')};
let [content, fileName, row] = match.slice(1);
return {
content,
fileName,
location: {column: -1, row: parseInt(row, 10)},
};
})
.filter(Boolean);
}
+28 -98
View File
@@ -10,26 +10,14 @@
'use strict';
import * as React from 'react';
import Platform from '../Utilities/Platform';
import RCTLog from '../Utilities/RCTLog';
import LogBoxContainer from './UI/LogBoxContainer';
import * as LogBoxData from './Data/LogBoxData';
import {parseLogBoxLog} from './Data/parseLogBoxLog';
import type {LogBoxLogs, Subscription, IgnorePattern} from './Data/LogBoxData';
import type {IgnorePattern} from './Data/LogBoxData';
import LogBoxLog from './Data/LogBoxLog';
type Props = $ReadOnly<{||}>;
type State = {|
logs: LogBoxLogs,
isDisabled: boolean,
hasError: boolean,
selectedLogIndex: number,
|};
let LogBoxComponent;
let LogBox;
/**
* LogBox displays logs in the app.
@@ -48,25 +36,26 @@ if (__DEV__) {
warnImpl(...args);
};
LogBoxComponent = class LogBox extends React.Component<Props, State> {
static getDerivedStateFromError() {
return {hasError: true};
}
componentDidCatch(err, errorInfo) {
LogBoxData.reportLogBoxError(err, errorInfo.componentStack);
}
LogBox = {
// TODO: deprecated, replace with ignoreLogs
static ignoreWarnings(patterns: $ReadOnlyArray<IgnorePattern>): void {
ignoreWarnings: (patterns: $ReadOnlyArray<IgnorePattern>): void => {
LogBox.ignoreLogs(patterns);
}
},
static ignoreLogs(patterns: $ReadOnlyArray<IgnorePattern>): void {
ignoreLogs: (patterns: $ReadOnlyArray<IgnorePattern>): void => {
LogBoxData.addIgnorePatterns(patterns);
}
},
uninstall: (): void => {
errorImpl = error;
warnImpl = warn;
delete (console: any).disableLogBox;
},
install: (): void => {
// Trigger lazy initialization of module.
require('../NativeModules/specs/NativeLogBox');
static install(): void {
errorImpl = function(...args) {
registerError(...args);
};
@@ -92,62 +81,7 @@ if (__DEV__) {
RCTLog.setWarningHandler((...args) => {
registerWarning(...args);
});
}
static uninstall(): void {
errorImpl = error;
warnImpl = warn;
delete (console: any).disableLogBox;
}
_subscription: ?Subscription;
state = {
logs: new Set(),
isDisabled: false,
hasError: false,
selectedLogIndex: -1,
};
render(): React.Node {
if (this.state.hasError) {
// This happens when the component failed to render, in which case we delegate to the native redbox.
// We can't show anyback fallback UI here, because the error may be with <View> or <Text>.
return null;
}
return this.state.logs == null ? null : (
<LogBoxContainer
onDismiss={this._handleDismiss}
onDismissWarns={LogBoxData.clearWarnings}
onDismissErrors={LogBoxData.clearErrors}
logs={this.state.logs}
isDisabled={this.state.isDisabled}
selectedLogIndex={this.state.selectedLogIndex}
setSelectedLog={this._handleSetSelectedLog}
/>
);
}
componentDidMount(): void {
this._subscription = LogBoxData.observe(data => {
this.setState(data);
});
}
componentWillUnmount(): void {
if (this._subscription != null) {
this._subscription.unsubscribe();
}
}
_handleDismiss(log: LogBoxLog): void {
LogBoxData.dismiss(log);
}
_handleSetSelectedLog(index: number): void {
LogBoxData.setSelectedLog(index);
}
},
};
const isRCTLogAdviceWarning = (...args) => {
@@ -227,31 +161,27 @@ if (__DEV__) {
}
};
} else {
LogBoxComponent = class extends React.Component<Props, State> {
LogBox = {
// TODO: deprecated, replace with ignoreLogs
static ignoreWarnings(patterns: $ReadOnlyArray<IgnorePattern>): void {
ignoreWarnings: (patterns: $ReadOnlyArray<IgnorePattern>): void => {
// Do nothing.
}
},
static ignoreLogs(patterns: $ReadOnlyArray<IgnorePattern>): void {
ignoreLogs: (patterns: $ReadOnlyArray<IgnorePattern>): void => {
// Do nothing.
}
},
static install(): void {
install: (): void => {
// Do nothing.
}
},
static uninstall(): void {
uninstall: (): void => {
// Do nothing.
}
render(): React.Node {
return null;
}
},
};
}
module.exports = (LogBoxComponent: Class<React.Component<Props, State>> & {
module.exports = (LogBox: {
// TODO: deprecated, replace with ignoreLogs
ignoreWarnings($ReadOnlyArray<IgnorePattern>): void,
ignoreLogs($ReadOnlyArray<IgnorePattern>): void,
@@ -0,0 +1,68 @@
/**
* 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';
import * as React from 'react';
import {View, StyleSheet} from 'react-native';
import * as LogBoxData from './Data/LogBoxData';
import LogBoxInspector from './UI/LogBoxInspector';
import type LogBoxLog from './Data/LogBoxLog';
type Props = $ReadOnly<{|
logs: $ReadOnlyArray<LogBoxLog>,
selectedLogIndex: number,
isDisabled?: ?boolean,
|}>;
export class _LogBoxInspectorContainer extends React.Component<Props> {
render(): React.Node {
return (
<View style={StyleSheet.absoluteFill}>
<LogBoxInspector
onDismiss={this._handleDismiss}
onMinimize={this._handleMinimize}
onChangeSelectedIndex={this._handleSetSelectedLog}
logs={this.props.logs}
selectedIndex={this.props.selectedLogIndex}
/>
</View>
);
}
_handleDismiss = (): void => {
// Here we handle the cases when the log is dismissed and it
// was either the last log, or when the current index
// is now outside the bounds of the log array.
const {selectedLogIndex, logs} = this.props;
const logsArray = Array.from(logs);
if (selectedLogIndex != null) {
if (logsArray.length - 1 <= 0) {
LogBoxData.setSelectedLog(-1);
} else if (selectedLogIndex >= logsArray.length - 1) {
LogBoxData.setSelectedLog(selectedLogIndex - 1);
}
LogBoxData.dismiss(logsArray[selectedLogIndex]);
}
};
_handleMinimize = (): void => {
LogBoxData.setSelectedLog(-1);
};
_handleSetSelectedLog = (index: number): void => {
LogBoxData.setSelectedLog(index);
};
}
export default (LogBoxData.withSubscription(
_LogBoxInspectorContainer,
): React.AbstractComponent<{||}>);
@@ -11,46 +11,31 @@
'use strict';
import * as React from 'react';
import SafeAreaView from '../../Components/SafeAreaView/SafeAreaView';
import StyleSheet from '../../StyleSheet/StyleSheet';
import View from '../../Components/View/View';
import LogBoxInspector from './LogBoxInspector';
import LogBoxLog from '../Data/LogBoxLog';
import LogBoxLogNotification from './LogBoxLogNotification';
import type {LogBoxLogs} from '../Data/LogBoxData';
import StyleSheet from '../StyleSheet/StyleSheet';
import View from '../Components/View/View';
import * as LogBoxData from './Data/LogBoxData';
import LogBoxLog from './Data/LogBoxLog';
import LogBoxLogNotification from './UI/LogBoxNotification';
type Props = $ReadOnly<{|
onDismiss: (log: LogBoxLog) => void,
onDismissWarns: () => void,
onDismissErrors: () => void,
setSelectedLog: number => void,
logs: LogBoxLogs,
logs: $ReadOnlyArray<LogBoxLog>,
selectedLogIndex: number,
isDisabled?: ?boolean,
|}>;
function LogBoxContainer(props: Props): React.Node {
const {selectedLogIndex, setSelectedLog} = props;
export function _LogBoxNotificationContainer(props: Props): React.Node {
const {logs} = props;
const logs = Array.from(props.logs);
const onDismissWarns = () => {
LogBoxData.clearWarnings();
};
const onDismissErrors = () => {
LogBoxData.clearErrors();
};
function handleInspectorDismiss() {
// Here we handle the cases when the log is dismissed and it
// was either the last log, or when the current index
// is now outside the bounds of the log array.
if (selectedLogIndex != null) {
if (logs.length - 1 <= 0) {
setSelectedLog(-1);
} else if (selectedLogIndex >= logs.length - 1) {
setSelectedLog(selectedLogIndex - 1);
}
props.onDismiss(logs[selectedLogIndex]);
}
}
function handleInspectorMinimize() {
setSelectedLog(-1);
}
const setSelectedLog = (index: number): void => {
LogBoxData.setSelectedLog(index);
};
function openLog(log: LogBoxLog) {
let index = logs.length - 1;
@@ -62,20 +47,6 @@ function LogBoxContainer(props: Props): React.Node {
setSelectedLog(index);
}
if (selectedLogIndex > -1) {
return (
<View style={StyleSheet.absoluteFill}>
<LogBoxInspector
onDismiss={handleInspectorDismiss}
onMinimize={handleInspectorMinimize}
onChangeSelectedIndex={setSelectedLog}
logs={logs}
selectedIndex={selectedLogIndex}
/>
</View>
);
}
if (logs.length === 0 || props.isDisabled === true) {
return null;
}
@@ -93,7 +64,7 @@ function LogBoxContainer(props: Props): React.Node {
level="warn"
totalLogCount={warnings.length}
onPressOpen={() => openLog(warnings[warnings.length - 1])}
onPressDismiss={props.onDismissWarns}
onPressDismiss={onDismissWarns}
/>
</View>
)}
@@ -104,7 +75,7 @@ function LogBoxContainer(props: Props): React.Node {
level="error"
totalLogCount={errors.length}
onPressOpen={() => openLog(errors[errors.length - 1])}
onPressDismiss={props.onDismissErrors}
onPressDismiss={onDismissErrors}
/>
</View>
)}
@@ -126,4 +97,6 @@ const styles = StyleSheet.create({
},
});
export default LogBoxContainer;
export default (LogBoxData.withSubscription(
_LogBoxNotificationContainer,
): React.AbstractComponent<{||}>);
-65
View File
@@ -1,65 +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 strict-local
* @format
*/
'use strict';
import PixelRatio from '../../Utilities/PixelRatio';
const scale = PixelRatio.get();
/**
* We use inline images for LogBox in order to avoid display latency due to
* resource contention with symbolicating stack traces.
*
* The following steps were used to create these:
*
* 1. Download SVG files from: https://feathericons.com
* 2. Rasterize SVG files to PNG files at 16dp, 36dp, and 48dp.
* 3. Convert to Base64: https://www.google.com/search?q=base64+image+encoder
*
* @see https://github.com/feathericons/feather
* @copyright 2013-2017 Cole Bemis
* @license MIT
*/
const LogBoxImageSource = {
alertTriangle: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB60lEQVRoge2Z3W3DIBSFj9oFPAIjZARGyAiMkBHuJh4hI2QEj5AR3Me+tQ91JALHmD8bKvmTkCr5Auc6/kzUACcnRXzuvL4GoAB8Afjeea9qXADcAfw4475c65orgBl++NeYl5ouUQiHt5tQTRJuwB6b5zLY49QVGn7I0bo+kuv60IQbuHf5CWCIqOkCgX93maia1MkRAUMo+OI+AvUPp7a50EzcUCBF6psJrUkYiZgnZJ7eId8mMeIyhpW5hyLw72LKCXsl86VqwgAKceKapW5e/nZpJnSsuHaTM7muyDq7C63JprJS69YxhNTpSlkpKeLGNHCo0EJChcSNaQA4SGiFtBMXJFSI3YVOPXFB6kMoUl9NaE0Wl4h5KQ0AOwqde+KmNrCL0EKCxJ64qQ0AlYVWSBfXZusgW6Oa0Dni2hiEv0qsoci+yUJrsoikLlKAkP11ygK54taiSOgb/O5b/DMqS+gBZeLWJlnoEX7XwQkBDPIktlEkz7hWrEmxZG4M5L9GXYTk0qxwcopKxa3VABN6cosM/C5LxTUof4ReMKHf1nRlaSnuGsGM7kfU4w8RF5Bz4aNlokLe/HQ/ngl9/Qih4L9k3h4hA1+S3odxu3Q77Hl4r1Hg75n6D01M2Difbp02Mi3ZTk5OLH4BUyEtOlDYuK0AAAAASUVORK5CYII='
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABVklEQVRYheWX4U3DMBBGH4gBMoJHyAgeoSNkAxjBG5QNOkJHCGzQDcoGZQP4gY3Oqe1cEscS4pNOqs9Jvqvv6ZrCf9fDhnutD4A3H810Br4mcW5l7hLmIdze5mZi+OJD5syeBYzC6CjyR5Ef9zI/CJMb0Im9zufC/qG2eQdchcGQuGYQ+9dJgZvl0B2xbJGrZW6IIevFXp9YVwcyB540syJfFcgSeJb0cVcDcg68XAFQCUhH+ShLBcBGIA158LQFqIB8zBRwEp9fgctcxQld/L2pZxZVAk/KkucjaDGQmoknrz35KEE2sABIRxm8tVIBaZgHb61UQOYmXk7aFgQVJ6QWPCnLAriYAVILnpTxD7yh/9EZiIEE4m+y29uMkGy1nQ6i9wYFRB5PwKdYP/v1msmnUe89gn695bG0iqjdXeMiRu9599csvGKZ0jlu0Ac/7d2rxX9Q37HW6QfX/ZguAAAAAElFTkSuQmCC'
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAvUlEQVQ4jbWT4Q3CIBCFP40DdANxg24gIzhKuwEjuIFxAkcwTtARGicoG+iPXlMCB8UfvoQc4e7ePV4A/ogWuMlqc0W7AsEo0QMNcPplugMmwMia5KwKWkNIuIkHq3wLXGQ/Sq4IC3wkLpOfmZyKeEpIEKsDYB8VN0Afkfpg30uNiycbdKcNqXEOxdBEWoEAoqta8uZ0iqqkxwGDUrSFAXAHZpOWd/+ubD5Kz335Cx1wZna4Bh54AddauVl8ARfCLO9Xq7xGAAAAAElFTkSuQmCC'): string),
check: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAqElEQVRoge3YTQ7CIBRF4bPUu/8JS6gTSaqilh95vuR+CaO2cGgYNAUzMzOzFgHlPhRaMkDAcRoltKaTeIxPtQHxGn+Q5AgJx8cQjo8hHB9DOP76Yiu/RcTmN18WLiQCjs3zBkYXVGOeLWd+xcIr5pgyEzDz7FIjISPP/FRPUM+9W4nvYVfuCSXeB3669ldEOzRFfCUSx1cicXwlEsdXIvEPKDMzM7PMbtugw3XTpNA2AAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAf0lEQVRYhe2UvQ2AIBQGL3EBR3AESkv3bxxFN8DmWUgwvkI+En1X0cBd+IMg+DuDyDMCs413kfMiX4EMbD3l8oCaPIU85B4mYLEF5XJscrYFPRGvb/sZ4IlocubJGdH0wj1FSG77XYT0qdUi5O+8jOjyyZQRUnkZ0UUeBMF3OQC/0VsyGlxligAAAABJRU5ErkJggg=='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASElEQVQ4jWNgGJHAgIGBIYESze8ZGBjWU6L5PAMDgwBNNCdAFZJt83qoQmRDSHK2AFQhzBCy/IxsCNkBJsDAwLAfiknWPBIBAETPFeuA4fr6AAAAAElFTkSuQmCC'): string),
chevronLeft: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAgElEQVRoge3YMQ6DQBAEwRYvnf8nPAECbAnkyATsrt0lXUyPdAE6kCRJ/yXA+jopLbkhwHY6a2nNl8I1ftSA8Bm/MeQKBeNrBONrBONrBONrhMHxcPwOlMUvT32oszD8CoEj+giO6CE4oofgiB7Cj44Y86zyFoYPgOFPi5Ik6WwHji+QVIOyhqgAAAAASUVORK5CYII='
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAaUlEQVRYhe3WsQ2AMAwAwRcs5LEYg3HpYANoQKKgcEEUI/6adM5LbgySfmZsNDeACdiApdEfaQGswH6+Xd1jugc9xYQxxhjz9RhaxwxvDuul3MrAqDyjsozKKnWgXUqdsJcAZgqsTFJ5B7gjUNw0n0HHAAAAAElFTkSuQmCC'
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARklEQVQ4jWNgGPKAmUh1AQwMDBIMDAwPyLEkgYGB4T/UELI1J9BdcwCxmpnIMZ1YkECsK+hmCNZoZCHCgAUMDAwfoHg4AgDJuQ/bcLyV+QAAAABJRU5ErkJggg=='): string),
chevronRight: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAeElEQVRoge3YMQ6AIBQE0Ykn3fs3HEEbC6MdFp+v8xJaspNQAZIkqbcA4zwpXTJpAPvlpHTNhHtAu4jwDDCiQjBiDcGINQQj1hCMWEN4Boy3l25vL/iL0PgJBcfXCI6vERxfIzi+Rmg8Hj7wrdL+Yys0/1qUJEmzDvSAkFQ8EOdJAAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAZElEQVRYhe3WsQmAQAxA0Y8ulLEcw3HtdANtBNvzCJjD/5pUgQ9pApJ+Zu7YCWABDmDLzemzA+c94+MW4AkqExUY1caoVka1GibqlSm7qJJSJzPGGGMylYqBgi9sACtFYiQN7wKC6VDcJ7tlpQAAAABJRU5ErkJggg=='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAANUlEQVQ4jWNgGLbAgYGBIYASAwIYGBj+MzAwJFBiSMLQMISJEpMptp2mmimORgcGChPSEAIAHGENPH8gqdYAAAAASUVORK5CYII='): string),
// TOOO: properly scale
close: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAAXNSR0IArs4c6QAAAPJJREFUSA3FllEOAiEMRIm3888/7x+vodEOWsPWLk4rIElDgOk8YBdCKaUcJS6vOEk9usBT/cGqjbvUiKvEWWJUgRc81R/gDXAk1MLgXYFYcjuLEVAPBsb7k+0J0B8ttBct7Mwg7BFOaODp3ExiJqeZ6/NosD/SzzAlM0aMRv2oumfYG6PM90Se8U3ECL1BRpzdDd+DToMpGVC7KkDRhzGqHCjVH0RLt9SDTftpPBguBPT3xlIfgTFkNBQ8YhTRuvCMQSanwtOJkh3ODSc4+0N70EIHYru+ei1/ROHpNuMi9lb68S7VQ223Kdu20Apc+tR/AAbAEIZxSf3+AAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAAXNSR0IArs4c6QAAAPJJREFUSA3FllEOAiEMRIm3888/7x+vodEOWsPWLk4rIElDgOk8YBdCKaUcJS6vOEk9usBT/cGqjbvUiKvEWWJUgRc81R/gDXAk1MLgXYFYcjuLEVAPBsb7k+0J0B8ttBct7Mwg7BFOaODp3ExiJqeZ6/NosD/SzzAlM0aMRv2oumfYG6PM90Se8U3ECL1BRpzdDd+DToMpGVC7KkDRhzGqHCjVH0RLt9SDTftpPBguBPT3xlIfgTFkNBQ8YhTRuvCMQSanwtOJkh3ODSc4+0N70EIHYru+ei1/ROHpNuMi9lb68S7VQ223Kdu20Apc+tR/AAbAEIZxSf3+AAAAAElFTkSuQmCC'
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAAAXNSR0IArs4c6QAAAPJJREFUSA3FllEOAiEMRIm3888/7x+vodEOWsPWLk4rIElDgOk8YBdCKaUcJS6vOEk9usBT/cGqjbvUiKvEWWJUgRc81R/gDXAk1MLgXYFYcjuLEVAPBsb7k+0J0B8ttBct7Mwg7BFOaODp3ExiJqeZ6/NosD/SzzAlM0aMRv2oumfYG6PM90Se8U3ECL1BRpzdDd+DToMpGVC7KkDRhzGqHCjVH0RLt9SDTftpPBguBPT3xlIfgTFkNBQ8YhTRuvCMQSanwtOJkh3ODSc4+0N70EIHYru+ei1/ROHpNuMi9lb68S7VQ223Kdu20Apc+tR/AAbAEIZxSf3+AAAAAElFTkSuQmCC'): string),
loader: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABXElEQVRoge2a3W3DMAyEr+0CHkGjaISOcKN4k6zQETpCR+gGzgbpQ10kcamIpKQ6avQBBPxg3pHwL2UDg/8LASxrcNdKnCwATmssrUyeWgnju/DmXs8tRP+Sh2kgAJga1rFlWj2rcMD5YqQh77QJLbzIORjyRIJQCJW5ngYo5AVlrsgkCGqbsDbAhFfxqZsSZibP0oDXQ43HQPsg82i7sBoR+VcJq2YxKcPo0IoJLRZXmYGC6ezQmQUdVqhPBVH/CNBTSMkLVlzjA8Bbocb7GoPBoADi+umZilYzbrG/JrnljOvy734iu4To/BQaDB6Rl4LciPPF9Lmjhgvi+s7w6tCIGw3WKS0P8fvWNjt0ZkGHFeq7CQXTbkZKGg2JOxrqPUZ3s6ziNdju38IjS/dLi0EQpDLX2gDQYHEX6Hx5/YcA+6H0NgAYPnCMj3x7Mxq4wTGx3Q1E578aDDR8AX0mOGD6BEN/AAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABN0lEQVRYhe2WzU3EMBCFP34KyJEjJaQDXAIlJJ24BSow2wEdhHSwJSwd7JHbcmC0mOxMnDiWDIInWbHkN29exo4n8IvRAEFGU8OAA04yulyR60Jm7msbyIZloAMGwBfI4UWrWxM08LW/weC4iOMNTog4g0awKjBG827GxBwC3996NHizAifsSrTRmlsZm23CT9adktyXSq6ZUPdxgiXnZzW8CLcLuC3lvqA/gCt5NtjlPQL7TP0Wu1HtRRu4PO3T4TKTz2kG+AG9IN6CR/Su9iojBw69egfghWgL/pGCp+JFVPUqTjWjlsuqeAo1o6rt2C8QcNiV0UxoHPMieojmz0CfMKyhl1hN84xbI3gnz5Ftp7kH3iT5LsFdDUf6pzSJ6r2glIFDbuDNhqRH4I7Pvv4EvG/QqocP2Jh/xzzX/zUAAAAASUVORK5CYII='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAsklEQVQ4jaWTYRHCMAyFP7gJmIQ6oChgEpBQKXMwC3MADpAAEiphDuBHC4QuDRu8u9ylyWtem7Rgw2X7GT1wsghb4beAVzhtsfYyJgs44AoEQzBkjrMId1HkKPwyZ6oMSnxYsnk1NqT7yMo34Fzhd9meGJvs7Hh3NhqCLXDI/rT0lKsR+KOJgc9RdaRRarkZvELogYsi8HqxjUhGYE+aQg1jzketwFTZXHbbEpjB8eU7PwAbLiJz46707gAAAABJRU5ErkJggg=='): string),
};
export default LogBoxImageSource;
Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

+12 -12
View File
@@ -14,7 +14,7 @@ import LogBoxInspectorCodeFrame from './LogBoxInspectorCodeFrame';
import * as React from 'react';
import ScrollView from '../../Components/ScrollView/ScrollView';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Modal from '../../Modal/Modal';
import View from '../../Components/View/View';
import * as LogBoxData from '../Data/LogBoxData';
import Keyboard from '../../Components/Keyboard/Keyboard';
import LogBoxInspectorFooter from './LogBoxInspectorFooter';
@@ -23,8 +23,7 @@ import LogBoxInspectorReactFrames from './LogBoxInspectorReactFrames';
import LogBoxInspectorStackFrames from './LogBoxInspectorStackFrames';
import LogBoxInspectorHeader from './LogBoxInspectorHeader';
import * as LogBoxStyle from './LogBoxStyle';
import type LogBoxLog, {LogLevel} from '../Data/LogBoxLog';
import LogBoxLog, {type LogLevel} from '../Data/LogBoxLog';
type Props = $ReadOnly<{|
onDismiss: () => void,
@@ -37,10 +36,12 @@ type Props = $ReadOnly<{|
function LogBoxInspector(props: Props): React.Node {
const {logs, selectedIndex} = props;
let log = logs[selectedIndex];
const log = logs[selectedIndex];
React.useEffect(() => {
LogBoxData.symbolicateLogNow(log);
if (log) {
LogBoxData.symbolicateLogNow(log);
}
}, [log]);
React.useEffect(() => {
@@ -68,12 +69,7 @@ function LogBoxInspector(props: Props): React.Node {
}
return (
<Modal
animationType="none"
visible
statusBarTranslucent
supportedOrientations={['portrait']}
presentationStyle="overFullScreen">
<View style={styles.root}>
<LogBoxInspectorHeader
onSelectIndex={props.onChangeSelectedIndex}
selectedIndex={selectedIndex}
@@ -86,7 +82,7 @@ function LogBoxInspector(props: Props): React.Node {
onMinimize={props.onMinimize}
level={log.level}
/>
</Modal>
</View>
);
}
@@ -143,6 +139,10 @@ function LogBoxInspectorBody(props) {
}
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: LogBoxStyle.getTextColor(),
},
scrollBody: {
backgroundColor: LogBoxStyle.getBackgroundColor(0.9),
flex: 1,
+4 -2
View File
@@ -101,9 +101,11 @@ const styles = StyleSheet.create({
syntaxErrorText: {
textAlign: 'center',
width: '100%',
height: 48,
fontSize: 14,
paddingTop: 15,
paddingBottom: 15,
lineHeight: 20,
paddingTop: 20,
paddingBottom: 50,
fontStyle: 'italic',
color: LogBoxStyle.getTextColor(0.6),
},
+8 -10
View File
@@ -17,7 +17,6 @@ import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import View from '../../Components/View/View';
import StatusBar from '../../Components/StatusBar/StatusBar';
import LogBoxImageSource from './LogBoxImageSource';
import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';
import type {LogLevel} from '../Data/LogBoxLog';
@@ -54,7 +53,7 @@ function LogBoxInspectorHeader(props: Props): React.Node {
<LogBoxInspectorHeaderButton
disabled={props.total <= 1}
level={props.level}
image={LogBoxImageSource.chevronLeft}
image={require('./LogBoxImages/chevron-left.png')}
onPress={() => props.onSelectIndex(prevIndex)}
/>
<View style={styles.title}>
@@ -63,7 +62,7 @@ function LogBoxInspectorHeader(props: Props): React.Node {
<LogBoxInspectorHeaderButton
disabled={props.total <= 1}
level={props.level}
image={LogBoxImageSource.chevronRight}
image={require('./LogBoxImages/chevron-right.png')}
onPress={() => props.onSelectIndex(nextIndex)}
/>
</View>
@@ -94,7 +93,7 @@ const backgroundForLevel = (level: LogLevel) =>
function LogBoxInspectorHeaderButton(
props: $ReadOnly<{|
disabled: boolean,
image: string,
image: number,
level: LogLevel,
onPress?: ?() => void,
|}>,
@@ -105,10 +104,7 @@ function LogBoxInspectorHeaderButton(
onPress={props.disabled ? null : props.onPress}
style={headerStyles.button}>
{props.disabled ? null : (
<Image
source={{height: 16, uri: props.image, width: 16}}
style={headerStyles.buttonImage}
/>
<Image source={props.image} style={headerStyles.buttonImage} />
)}
</LogBoxButton>
);
@@ -126,7 +122,9 @@ const headerStyles = StyleSheet.create({
borderRadius: 3,
},
buttonImage: {
tintColor: LogBoxStyle.getBackgroundColor(1),
height: 14,
width: 8,
tintColor: LogBoxStyle.getTextColor(),
},
});
@@ -156,7 +154,7 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
titleText: {
color: LogBoxStyle.getBackgroundColor(1),
color: LogBoxStyle.getTextColor(),
fontSize: 16,
fontWeight: '600',
includeFontPadding: false,
@@ -18,12 +18,37 @@ import View from '../../Components/View/View';
import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';
import LogBoxInspectorSection from './LogBoxInspectorSection';
import openFileInEditor from '../../Core/Devtools/openFileInEditor';
import type LogBoxLog from '../Data/LogBoxLog';
type Props = $ReadOnly<{|
log: LogBoxLog,
|}>;
const BEFORE_SLASH_RE = /^(.*)[\\/]/;
// Taken from React https://github.com/facebook/react/blob/206d61f72214e8ae5b935f0bf8628491cb7f0797/packages/react-devtools-shared/src/backend/describeComponentFrame.js#L27-L41
function getPrettyFileName(path) {
let fileName = path.replace(BEFORE_SLASH_RE, '');
// In DEV, include code for a common special case:
// prefer "folder/index.js" instead of just "index.js".
if (/^index\./.test(fileName)) {
const match = path.match(BEFORE_SLASH_RE);
if (match) {
const pathBeforeSlash = match[1];
if (pathBeforeSlash) {
const folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, '');
// Note the below string contains a zero width space after the "/" character.
// This is to prevent browsers like Chrome from formatting the file name as a link.
// (Since this is a source link, it would not work to open the source file anyway.)
fileName = folderName + '/' + fileName;
}
}
}
return fileName;
}
function LogBoxInspectorReactFrames(props: Props): React.Node {
const [collapsed, setCollapsed] = React.useState(true);
if (props.log.componentStack == null || props.log.componentStack.length < 1) {
@@ -39,6 +64,10 @@ function LogBoxInspectorReactFrames(props: Props): React.Node {
}
function getCollapseMessage() {
if (props.log.componentStack.length <= 3) {
return;
}
const count = props.log.componentStack.length - 3;
if (collapsed) {
return `See ${count} more components`;
@@ -53,15 +82,34 @@ function LogBoxInspectorReactFrames(props: Props): React.Node {
<View
// Unfortunately we don't have a unique identifier for stack traces.
key={index}
style={componentStyles.frame}>
<View style={componentStyles.component}>
<Text style={componentStyles.frameName}>
<Text style={componentStyles.bracket}>{'<'}</Text>
{frame.component}
<Text style={componentStyles.bracket}>{' />'}</Text>
style={componentStyles.frameContainer}>
<LogBoxButton
backgroundColor={{
default: 'transparent',
pressed: LogBoxStyle.getBackgroundColor(1),
}}
onPress={
// Older versions of DevTools do not provide full path.
// This will not work on Windows, remove check once the
// DevTools return the full file path.
frame.fileName.startsWith('/')
? () =>
openFileInEditor(frame.fileName, frame.location?.row ?? 1)
: null
}
style={componentStyles.frame}>
<View style={componentStyles.component}>
<Text style={componentStyles.frameName}>
<Text style={componentStyles.bracket}>{'<'}</Text>
{frame.content}
<Text style={componentStyles.bracket}>{' />'}</Text>
</Text>
</View>
<Text style={componentStyles.frameLocation}>
{getPrettyFileName(frame.fileName)}
{frame.location ? `:${frame.location.row}` : ''}
</Text>
</View>
<Text style={componentStyles.frameLocation}>{frame.location}</Text>
</LogBoxButton>
</View>
))}
<View style={componentStyles.collapseContainer}>
@@ -96,9 +144,15 @@ const componentStyles = StyleSheet.create({
paddingVertical: 5,
paddingHorizontal: 10,
},
frameContainer: {
flexDirection: 'row',
paddingHorizontal: 15,
},
frame: {
paddingHorizontal: 25,
flex: 1,
paddingVertical: 4,
paddingHorizontal: 10,
borderRadius: 5,
},
component: {
flexDirection: 'row',
@@ -15,7 +15,6 @@ import Easing from '../../Animated/src/Easing';
import * as React from 'react';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import LogBoxImageSource from './LogBoxImageSource';
import LogBoxButton from './LogBoxButton';
import * as LogBoxStyle from './LogBoxStyle';
@@ -74,11 +73,11 @@ function LogBoxInspectorSourceMapStatus(props: Props): React.Node {
let color;
switch (props.status) {
case 'FAILED':
image = LogBoxImageSource.alertTriangle;
image = require('./LogBoxImages/alert-triangle.png');
color = LogBoxStyle.getErrorColor(1);
break;
case 'PENDING':
image = LogBoxImageSource.loader;
image = require('./LogBoxImages/loader.png');
color = LogBoxStyle.getWarningColor(1);
break;
}
@@ -97,7 +96,7 @@ function LogBoxInspectorSourceMapStatus(props: Props): React.Node {
onPress={props.onPress}
style={styles.root}>
<Animated.Image
source={{height: 16, uri: image, width: 16}}
source={image}
style={[
styles.image,
{tintColor: color},
@@ -120,6 +119,8 @@ const styles = StyleSheet.create({
paddingHorizontal: 8,
},
image: {
height: 14,
width: 16,
marginEnd: 4,
tintColor: LogBoxStyle.getTextColor(0.4),
},
@@ -12,7 +12,6 @@
import * as React from 'react';
import Image from '../../Image/Image';
import LogBoxImageSource from './LogBoxImageSource';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import View from '../../Components/View/View';
@@ -102,11 +101,7 @@ function DismissButton(props) {
onPress={props.onPress}
style={dismissStyles.press}>
<Image
source={{
width: 8,
height: 8,
uri: LogBoxImageSource.close,
}}
source={require('./LogBoxImages/close.png')}
style={dismissStyles.image}
/>
</LogBoxButton>
@@ -188,6 +183,8 @@ const dismissStyles = StyleSheet.create({
justifyContent: 'center',
},
image: {
height: 8,
width: 8,
tintColor: LogBoxStyle.getBackgroundColor(1),
},
});
@@ -1,254 +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
* @emails oncall+react_native
* @flow strict-local
*/
'use strict';
const React = require('react');
const LogBoxContainer = require('../LogBoxContainer').default;
const LogBoxLog = require('../../Data/LogBoxLog').default;
const render = require('../../../../jest/renderer');
describe('LogBoxContainer', () => {
it('should render null with no logs', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={-1}
logs={new Set()}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render null with no selected log and disabled', () => {
const output = render.shallowRender(
<LogBoxContainer
isDisabled
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={-1}
logs={
new Set([
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render the latest warning notification', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={-1}
logs={
new Set([
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render the latest error notification', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={-1}
logs={
new Set([
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render both an error and warning notification', () => {
const output = render.shallowRender(
<LogBoxContainer
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={-1}
logs={
new Set([
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render selected fatal error even when disabled', () => {
const output = render.shallowRender(
<LogBoxContainer
isDisabled
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={0}
logs={
new Set([
new LogBoxLog({
level: 'fatal',
isComponentError: false,
message: {
content: 'Should be selected',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render selected syntax error even when disabled', () => {
const output = render.shallowRender(
<LogBoxContainer
isDisabled
onDismiss={() => {}}
onDismissWarns={() => {}}
onDismissErrors={() => {}}
setSelectedLog={() => {}}
selectedLogIndex={0}
logs={
new Set([
new LogBoxLog({
level: 'syntax',
isComponentError: false,
message: {
content: 'Should be selected',
substitutions: [],
},
stack: [],
category: 'Some kind of syntax error message',
componentStack: [],
codeFrame: {
fileName:
'/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js',
location: {row: 199, column: 0},
content: ` 197 | });
198 |
> 199 | export default CrashReactApp;
| ^
200 |`,
},
}),
])
}
/>,
);
expect(output).toMatchSnapshot();
});
});
@@ -40,7 +40,7 @@ describe('LogBoxInspectorReactFrames', () => {
expect(output).toMatchSnapshot();
});
it('should render componentStack frames', () => {
it('should render componentStack frames without full path pressable', () => {
const output = render.shallowRender(
<LogBoxInspectorReactFrames
log={
@@ -55,8 +55,129 @@ describe('LogBoxInspectorReactFrames', () => {
category: 'Some kind of message',
componentStack: [
{
component: 'MyComponent',
location: 'MyComponentFile.js:1',
content: 'MyComponent',
fileName: 'MyComponentFile.js',
location: {
row: 1,
column: -1,
},
},
],
})
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render componentStack frames with full path pressable', () => {
const output = render.shallowRender(
<LogBoxInspectorReactFrames
log={
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [
{
content: 'MyComponent',
fileName: '/path/to/MyComponentFile.js',
location: {
row: 1,
column: -1,
},
},
],
})
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render componentStack frames with parent folder of index.js', () => {
const output = render.shallowRender(
<LogBoxInspectorReactFrames
log={
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [
{
content: 'MyComponent',
fileName: '/path/to/index.js',
location: {
row: 1,
column: -1,
},
},
],
})
}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render componentStack frames with more than 3 stacks', () => {
const output = render.shallowRender(
<LogBoxInspectorReactFrames
log={
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [
{
content: 'MyComponent',
fileName: '/path/to/index.js',
location: {
row: 1,
column: -1,
},
},
{
content: 'MyComponent2',
fileName: '/path/to/index2.js',
location: {
row: 1,
column: -1,
},
},
{
content: 'MyComponent3',
fileName: '/path/to/index3.js',
location: {
row: 1,
column: -1,
},
},
{
content: 'MyComponent4',
fileName: '/path/to/index4.js',
location: {
row: 1,
column: -1,
},
},
],
})
@@ -12,7 +12,7 @@
'use strict';
const React = require('react');
const LogBoxLogNotification = require('../LogBoxLogNotification').default;
const LogBoxNotification = require('../LogBoxNotification').default;
const LogBoxLog = require('../../Data/LogBoxLog').default;
const render = require('../../../../jest/renderer');
@@ -28,10 +28,10 @@ const log = new LogBoxLog({
componentStack: [],
});
describe('LogBoxLogNotification', () => {
describe('LogBoxNotification', () => {
it('should render log', () => {
const output = render.shallowRender(
<LogBoxLogNotification
<LogBoxNotification
log={log}
totalLogCount={1}
level="warn"
@@ -1,17 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxContainer should render fatal with selectedIndex 2 1`] = `
<Component
animationType="none"
hardwareAccelerated={false}
presentationStyle="overFullScreen"
statusBarTranslucent={true}
supportedOrientations={
Array [
"portrait",
]
<View
style={
Object {
"backgroundColor": "rgba(255, 255, 255, 1)",
"flex": 1,
}
}
visible={true}
>
<LogBoxInspectorHeader
level="fatal"
@@ -47,23 +43,19 @@ exports[`LogBoxContainer should render fatal with selectedIndex 2 1`] = `
onDismiss={[Function]}
onMinimize={[Function]}
/>
</Component>
</View>
`;
exports[`LogBoxContainer should render null with no logs 1`] = `null`;
exports[`LogBoxContainer should render warning with selectedIndex 0 1`] = `
<Component
animationType="none"
hardwareAccelerated={false}
presentationStyle="overFullScreen"
statusBarTranslucent={true}
supportedOrientations={
Array [
"portrait",
]
<View
style={
Object {
"backgroundColor": "rgba(255, 255, 255, 1)",
"flex": 1,
}
}
visible={true}
>
<LogBoxInspectorHeader
level="warn"
@@ -99,5 +91,5 @@ exports[`LogBoxContainer should render warning with selectedIndex 0 1`] = `
onDismiss={[Function]}
onMinimize={[Function]}
/>
</Component>
</View>
`;
@@ -29,8 +29,10 @@ exports[`LogBoxInspectorFooter should render no buttons and a message for syntax
"color": "rgba(255, 255, 255, 0.6)",
"fontSize": 14,
"fontStyle": "italic",
"paddingBottom": 15,
"paddingTop": 15,
"height": 48,
"lineHeight": 20,
"paddingBottom": 50,
"paddingTop": 20,
"textAlign": "center",
"width": "100%",
}
@@ -23,7 +23,11 @@ exports[`LogBoxInspectorHeader should render both buttons for two total 1`] = `
>
<LogBoxInspectorHeaderButton
disabled={false}
image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAaUlEQVRYhe3WsQ2AMAwAwRcs5LEYg3HpYANoQKKgcEEUI/6adM5LbgySfmZsNDeACdiApdEfaQGswH6+Xd1jugc9xYQxxhjz9RhaxwxvDuul3MrAqDyjsozKKnWgXUqdsJcAZgqsTFJ5B7gjUNw0n0HHAAAAAElFTkSuQmCC"
image={
Object {
"testUri": "../Libraries/LogBox/UI/LogBoxImages/chevron-left.png",
}
}
level="warn"
onPress={[Function]}
/>
@@ -39,7 +43,7 @@ exports[`LogBoxInspectorHeader should render both buttons for two total 1`] = `
<Text
style={
Object {
"color": "rgba(51, 51, 51, 1)",
"color": "rgba(255, 255, 255, 1)",
"fontSize": 16,
"fontWeight": "600",
"includeFontPadding": false,
@@ -52,7 +56,11 @@ exports[`LogBoxInspectorHeader should render both buttons for two total 1`] = `
</View>
<LogBoxInspectorHeaderButton
disabled={false}
image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAZElEQVRYhe3WsQmAQAxA0Y8ulLEcw3HtdANtBNvzCJjD/5pUgQ9pApJ+Zu7YCWABDmDLzemzA+c94+MW4AkqExUY1caoVka1GibqlSm7qJJSJzPGGGMylYqBgi9sACtFYiQN7wKC6VDcJ7tlpQAAAABJRU5ErkJggg=="
image={
Object {
"testUri": "../Libraries/LogBox/UI/LogBoxImages/chevron-right.png",
}
}
level="warn"
onPress={[Function]}
/>
@@ -83,7 +91,11 @@ exports[`LogBoxInspectorHeader should render no buttons for one total 1`] = `
>
<LogBoxInspectorHeaderButton
disabled={true}
image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAaUlEQVRYhe3WsQ2AMAwAwRcs5LEYg3HpYANoQKKgcEEUI/6adM5LbgySfmZsNDeACdiApdEfaQGswH6+Xd1jugc9xYQxxhjz9RhaxwxvDuul3MrAqDyjsozKKnWgXUqdsJcAZgqsTFJ5B7gjUNw0n0HHAAAAAElFTkSuQmCC"
image={
Object {
"testUri": "../Libraries/LogBox/UI/LogBoxImages/chevron-left.png",
}
}
level="warn"
onPress={[Function]}
/>
@@ -99,7 +111,7 @@ exports[`LogBoxInspectorHeader should render no buttons for one total 1`] = `
<Text
style={
Object {
"color": "rgba(51, 51, 51, 1)",
"color": "rgba(255, 255, 255, 1)",
"fontSize": 16,
"fontWeight": "600",
"includeFontPadding": false,
@@ -112,7 +124,11 @@ exports[`LogBoxInspectorHeader should render no buttons for one total 1`] = `
</View>
<LogBoxInspectorHeaderButton
disabled={true}
image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAZElEQVRYhe3WsQmAQAxA0Y8ulLEcw3HtdANtBNvzCJjD/5pUgQ9pApJ+Zu7YCWABDmDLzemzA+c94+MW4AkqExUY1caoVka1GibqlSm7qJJSJzPGGGMylYqBgi9sACtFYiQN7wKC6VDcJ7tlpQAAAABJRU5ErkJggg=="
image={
Object {
"testUri": "../Libraries/LogBox/UI/LogBoxImages/chevron-right.png",
}
}
level="warn"
onPress={[Function]}
/>
@@ -153,7 +169,7 @@ exports[`LogBoxInspectorHeader should render syntax error header 1`] = `
<Text
style={
Object {
"color": "rgba(51, 51, 51, 1)",
"color": "rgba(255, 255, 255, 1)",
"fontSize": 16,
"fontWeight": "600",
"includeFontPadding": false,
@@ -191,7 +207,11 @@ exports[`LogBoxInspectorHeader should render two buttons for three or more total
>
<LogBoxInspectorHeaderButton
disabled={true}
image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAaUlEQVRYhe3WsQ2AMAwAwRcs5LEYg3HpYANoQKKgcEEUI/6adM5LbgySfmZsNDeACdiApdEfaQGswH6+Xd1jugc9xYQxxhjz9RhaxwxvDuul3MrAqDyjsozKKnWgXUqdsJcAZgqsTFJ5B7gjUNw0n0HHAAAAAElFTkSuQmCC"
image={
Object {
"testUri": "../Libraries/LogBox/UI/LogBoxImages/chevron-left.png",
}
}
level="warn"
onPress={[Function]}
/>
@@ -207,7 +227,7 @@ exports[`LogBoxInspectorHeader should render two buttons for three or more total
<Text
style={
Object {
"color": "rgba(51, 51, 51, 1)",
"color": "rgba(255, 255, 255, 1)",
"fontSize": 16,
"fontWeight": "600",
"includeFontPadding": false,
@@ -220,7 +240,11 @@ exports[`LogBoxInspectorHeader should render two buttons for three or more total
</View>
<LogBoxInspectorHeaderButton
disabled={true}
image="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAZElEQVRYhe3WsQmAQAxA0Y8ulLEcw3HtdANtBNvzCJjD/5pUgQ9pApJ+Zu7YCWABDmDLzemzA+c94+MW4AkqExUY1caoVka1GibqlSm7qJJSJzPGGGMylYqBgi9sACtFYiQN7wKC6VDcJ7tlpQAAAABJRU5ErkJggg=="
image={
Object {
"testUri": "../Libraries/LogBox/UI/LogBoxImages/chevron-right.png",
}
}
level="warn"
onPress={[Function]}
/>
@@ -1,81 +1,420 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxInspectorReactFrames should render componentStack frames 1`] = `
exports[`LogBoxInspectorReactFrames should render componentStack frames with full path pressable 1`] = `
<LogBoxInspectorSection
heading="Component Stack"
>
<View
style={
Object {
"paddingHorizontal": 25,
"paddingVertical": 4,
"flexDirection": "row",
"paddingHorizontal": 15,
}
}
>
<View
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"flexDirection": "row",
"paddingRight": 10,
"borderRadius": 5,
"flex": 1,
"paddingHorizontal": 10,
"paddingVertical": 4,
}
}
>
<Text
<View
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"includeFontPadding": false,
"lineHeight": 18,
"flexDirection": "row",
"paddingRight": 10,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
&lt;
</Text>
MyComponent
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
}
>
/&gt;
>
&lt;
</Text>
MyComponent
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
/&gt;
</Text>
</Text>
</View>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
}
}
>
MyComponentFile.js
:1
</Text>
</View>
<Text
</LogBoxButton>
</View>
<View
style={
Object {
"flexDirection": "row",
"marginLeft": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
"borderRadius": 5,
}
}
>
MyComponentFile.js:1
</Text>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"lineHeight": 20,
"marginTop": 0,
"paddingHorizontal": 10,
"paddingVertical": 5,
}
}
/>
</LogBoxButton>
</View>
</LogBoxInspectorSection>
`;
exports[`LogBoxInspectorReactFrames should render componentStack frames with more than 3 stacks 1`] = `
<LogBoxInspectorSection
heading="Component Stack"
>
<View
style={
Object {
"flexDirection": "row",
"paddingHorizontal": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
"flex": 1,
"paddingHorizontal": 10,
"paddingVertical": 4,
}
}
>
<View
style={
Object {
"flexDirection": "row",
"paddingRight": 10,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
&lt;
</Text>
MyComponent
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
/&gt;
</Text>
</Text>
</View>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
}
}
>
to/index.js
:1
</Text>
</LogBoxButton>
</View>
<View
style={
Object {
"flexDirection": "row",
"paddingHorizontal": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
"flex": 1,
"paddingHorizontal": 10,
"paddingVertical": 4,
}
}
>
<View
style={
Object {
"flexDirection": "row",
"paddingRight": 10,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
&lt;
</Text>
MyComponent2
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
/&gt;
</Text>
</Text>
</View>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
}
}
>
index2.js
:1
</Text>
</LogBoxButton>
</View>
<View
style={
Object {
"flexDirection": "row",
"paddingHorizontal": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
"flex": 1,
"paddingHorizontal": 10,
"paddingVertical": 4,
}
}
>
<View
style={
Object {
"flexDirection": "row",
"paddingRight": 10,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
&lt;
</Text>
MyComponent3
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
/&gt;
</Text>
</Text>
</View>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
}
}
>
index3.js
:1
</Text>
</LogBoxButton>
</View>
<View
style={
@@ -112,11 +451,283 @@ exports[`LogBoxInspectorReactFrames should render componentStack frames 1`] = `
}
}
>
See -2 more components
See 1 more components
</Text>
</LogBoxButton>
</View>
</LogBoxInspectorSection>
`;
exports[`LogBoxInspectorReactFrames should render componentStack frames with parent folder of index.js 1`] = `
<LogBoxInspectorSection
heading="Component Stack"
>
<View
style={
Object {
"flexDirection": "row",
"paddingHorizontal": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
"flex": 1,
"paddingHorizontal": 10,
"paddingVertical": 4,
}
}
>
<View
style={
Object {
"flexDirection": "row",
"paddingRight": 10,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
&lt;
</Text>
MyComponent
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
/&gt;
</Text>
</Text>
</View>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
}
}
>
to/index.js
:1
</Text>
</LogBoxButton>
</View>
<View
style={
Object {
"flexDirection": "row",
"marginLeft": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"lineHeight": 20,
"marginTop": 0,
"paddingHorizontal": 10,
"paddingVertical": 5,
}
}
/>
</LogBoxButton>
</View>
</LogBoxInspectorSection>
`;
exports[`LogBoxInspectorReactFrames should render componentStack frames without full path pressable 1`] = `
<LogBoxInspectorSection
heading="Component Stack"
>
<View
style={
Object {
"flexDirection": "row",
"paddingHorizontal": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={null}
style={
Object {
"borderRadius": 5,
"flex": 1,
"paddingHorizontal": 10,
"paddingVertical": 4,
}
}
>
<View
style={
Object {
"flexDirection": "row",
"paddingRight": 10,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 1)",
"fontFamily": "Menlo",
"fontSize": 14,
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
&lt;
</Text>
MyComponent
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.4)",
"fontFamily": "Menlo",
"fontSize": 14,
"fontWeight": "500",
"includeFontPadding": false,
"lineHeight": 18,
}
}
>
/&gt;
</Text>
</Text>
</View>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"includeFontPadding": false,
"lineHeight": 16,
"paddingLeft": 10,
}
}
>
MyComponentFile.js
:1
</Text>
</LogBoxButton>
</View>
<View
style={
Object {
"flexDirection": "row",
"marginLeft": 15,
}
}
>
<LogBoxButton
backgroundColor={
Object {
"default": "transparent",
"pressed": "rgba(51, 51, 51, 1)",
}
}
onPress={[Function]}
style={
Object {
"borderRadius": 5,
}
}
>
<Text
style={
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontSize": 12,
"fontWeight": "300",
"lineHeight": 20,
"marginTop": 0,
"paddingHorizontal": 10,
"paddingVertical": 5,
}
}
/>
</LogBoxButton>
</View>
</LogBoxInspectorSection>
`;
exports[`LogBoxInspectorReactFrames should render null for no componentStack frames 1`] = `null`;
@@ -30,16 +30,16 @@ exports[`LogBoxInspectorSourceMapStatus should render for failed 1`] = `
<ForwardRef(AnimatedComponentWrapper)
source={
Object {
"height": 16,
"uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABVklEQVRYheWX4U3DMBBGH4gBMoJHyAgeoSNkAxjBG5QNOkJHCGzQDcoGZQP4gY3Oqe1cEscS4pNOqs9Jvqvv6ZrCf9fDhnutD4A3H810Br4mcW5l7hLmIdze5mZi+OJD5syeBYzC6CjyR5Ef9zI/CJMb0Im9zufC/qG2eQdchcGQuGYQ+9dJgZvl0B2xbJGrZW6IIevFXp9YVwcyB540syJfFcgSeJb0cVcDcg68XAFQCUhH+ShLBcBGIA158LQFqIB8zBRwEp9fgctcxQld/L2pZxZVAk/KkucjaDGQmoknrz35KEE2sABIRxm8tVIBaZgHb61UQOYmXk7aFgQVJ6QWPCnLAriYAVILnpTxD7yh/9EZiIEE4m+y29uMkGy1nQ6i9wYFRB5PwKdYP/v1msmnUe89gn695bG0iqjdXeMiRu9599csvGKZ0jlu0Ac/7d2rxX9Q37HW6QfX/ZguAAAAAElFTkSuQmCC",
"width": 16,
"testUri": "../Libraries/LogBox/UI/LogBoxImages/alert-triangle.png",
}
}
style={
Array [
Object {
"height": 14,
"marginEnd": 4,
"tintColor": "rgba(255, 255, 255, 0.4)",
"width": 16,
},
Object {
"tintColor": "rgba(243, 83, 105, 1)",
@@ -97,16 +97,16 @@ exports[`LogBoxInspectorSourceMapStatus should render for pending 1`] = `
<ForwardRef(AnimatedComponentWrapper)
source={
Object {
"height": 16,
"uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABN0lEQVRYhe2WzU3EMBCFP34KyJEjJaQDXAIlJJ24BSow2wEdhHSwJSwd7JHbcmC0mOxMnDiWDIInWbHkN29exo4n8IvRAEFGU8OAA04yulyR60Jm7msbyIZloAMGwBfI4UWrWxM08LW/weC4iOMNTog4g0awKjBG827GxBwC3996NHizAifsSrTRmlsZm23CT9adktyXSq6ZUPdxgiXnZzW8CLcLuC3lvqA/gCt5NtjlPQL7TP0Wu1HtRRu4PO3T4TKTz2kG+AG9IN6CR/Su9iojBw69egfghWgL/pGCp+JFVPUqTjWjlsuqeAo1o6rt2C8QcNiV0UxoHPMieojmz0CfMKyhl1hN84xbI3gnz5Ftp7kH3iT5LsFdDUf6pzSJ6r2glIFDbuDNhqRH4I7Pvv4EvG/QqocP2Jh/xzzX/zUAAAAASUVORK5CYII=",
"width": 16,
"testUri": "../Libraries/LogBox/UI/LogBoxImages/loader.png",
}
}
style={
Array [
Object {
"height": 14,
"marginEnd": 4,
"tintColor": "rgba(255, 255, 255, 0.4)",
"width": 16,
},
Object {
"tintColor": "rgba(250, 186, 48, 1)",
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxLogNotification should render log 1`] = `
exports[`LogBoxNotification should render log 1`] = `
<View
style={
Object {
@@ -0,0 +1,212 @@
/**
* 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 {
_LogBoxNotificationContainer: LogBoxNotificationContainer,
} = require('../LogBoxNotificationContainer');
const LogBoxLog = require('../Data/LogBoxLog').default;
const render = require('../../../jest/renderer');
describe('LogBoxNotificationContainer', () => {
it('should render null with no logs', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer selectedLogIndex={-1} logs={[]} />,
);
expect(output).toMatchSnapshot();
});
it('should render null with no selected log and disabled', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer
isDisabled
selectedLogIndex={-1}
logs={[
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render the latest warning notification', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer
selectedLogIndex={-1}
logs={[
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render the latest error notification', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer
selectedLogIndex={-1}
logs={[
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render both an error and warning notification', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer
selectedLogIndex={-1}
logs={[
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render selected fatal error even when disabled', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer
isDisabled
selectedLogIndex={0}
logs={[
new LogBoxLog({
level: 'fatal',
isComponentError: false,
message: {
content: 'Should be selected',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
it('should render selected syntax error even when disabled', () => {
const output = render.shallowRender(
<LogBoxNotificationContainer
isDisabled
selectedLogIndex={0}
logs={[
new LogBoxLog({
level: 'syntax',
isComponentError: false,
message: {
content: 'Should be selected',
substitutions: [],
},
stack: [],
category: 'Some kind of syntax error message',
componentStack: [],
codeFrame: {
fileName: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js',
location: {row: 199, column: 0},
content: ` 197 | });
198 |
> 199 | export default CrashReactApp;
| ^
200 |`,
},
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
});
@@ -0,0 +1,56 @@
/**
* 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 strict-local
*/
'use strict';
const React = require('react');
const {
_LogBoxInspectorContainer: LogBoxInspectorContainer,
} = require('../LogBoxInspectorContainer');
const LogBoxLog = require('../Data/LogBoxLog').default;
const render = require('../../../jest/renderer');
describe('LogBoxNotificationContainer', () => {
it('should render inspector with logs, even when disabled', () => {
const output = render.shallowRender(
<LogBoxInspectorContainer
isDisabled
selectedLogIndex={-1}
logs={[
new LogBoxLog({
level: 'warn',
isComponentError: false,
message: {
content: 'Some kind of message',
substitutions: [],
},
stack: [],
category: 'Some kind of message',
componentStack: [],
}),
new LogBoxLog({
level: 'error',
isComponentError: false,
message: {
content: 'Some kind of message (latest)',
substitutions: [],
},
stack: [],
category: 'Some kind of message (latest)',
componentStack: [],
}),
]}
/>,
);
expect(output).toMatchSnapshot();
});
});
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxContainer should render both an error and warning notification 1`] = `
exports[`LogBoxNotificationContainer should render both an error and warning notification 1`] = `
<View
style={
Object {
@@ -86,108 +86,15 @@ exports[`LogBoxContainer should render both an error and warning notification 1`
</View>
`;
exports[`LogBoxContainer should render null with no logs 1`] = `null`;
exports[`LogBoxNotificationContainer should render null with no logs 1`] = `null`;
exports[`LogBoxContainer should render null with no selected log and disabled 1`] = `null`;
exports[`LogBoxNotificationContainer should render null with no selected log and disabled 1`] = `null`;
exports[`LogBoxContainer should render selected fatal error even when disabled 1`] = `
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<LogBoxInspector
logs={
Array [
LogBoxLog {
"category": "Some kind of message",
"codeFrame": undefined,
"componentStack": Array [],
"count": 1,
"isComponentError": false,
"level": "fatal",
"message": Object {
"content": "Should be selected",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
]
}
onChangeSelectedIndex={[Function]}
onDismiss={[Function]}
onMinimize={[Function]}
selectedIndex={0}
/>
</View>
`;
exports[`LogBoxNotificationContainer should render selected fatal error even when disabled 1`] = `null`;
exports[`LogBoxContainer should render selected syntax error even when disabled 1`] = `
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<LogBoxInspector
logs={
Array [
LogBoxLog {
"category": "Some kind of syntax error message",
"codeFrame": Object {
"content": " 197 | });
198 |
> 199 | export default CrashReactApp;
| ^
200 |",
"fileName": "/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js",
"location": Object {
"column": 0,
"row": 199,
},
},
"componentStack": Array [],
"count": 1,
"isComponentError": false,
"level": "syntax",
"message": Object {
"content": "Should be selected",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
]
}
onChangeSelectedIndex={[Function]}
onDismiss={[Function]}
onMinimize={[Function]}
selectedIndex={0}
/>
</View>
`;
exports[`LogBoxNotificationContainer should render selected syntax error even when disabled 1`] = `null`;
exports[`LogBoxContainer should render the latest error notification 1`] = `
exports[`LogBoxNotificationContainer should render the latest error notification 1`] = `
<View
style={
Object {
@@ -237,7 +144,7 @@ exports[`LogBoxContainer should render the latest error notification 1`] = `
</View>
`;
exports[`LogBoxContainer should render the latest warning notification 1`] = `
exports[`LogBoxNotificationContainer should render the latest warning notification 1`] = `
<View
style={
Object {
@@ -0,0 +1,62 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxNotificationContainer should render inspector with logs, even when disabled 1`] = `
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<LogBoxInspector
logs={
Array [
LogBoxLog {
"category": "Some kind of message",
"codeFrame": undefined,
"componentStack": Array [],
"count": 1,
"isComponentError": false,
"level": "warn",
"message": Object {
"content": "Some kind of message",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
LogBoxLog {
"category": "Some kind of message (latest)",
"codeFrame": undefined,
"componentStack": Array [],
"count": 1,
"isComponentError": false,
"level": "error",
"message": Object {
"content": "Some kind of message (latest)",
"substitutions": Array [],
},
"stack": Array [],
"symbolicated": Object {
"error": null,
"stack": null,
"status": "NONE",
},
},
]
}
onChangeSelectedIndex={[Function]}
onDismiss={[Function]}
onMinimize={[Function]}
selectedIndex={-1}
/>
</View>
`;
+26 -4
View File
@@ -12,8 +12,11 @@
const AppContainer = require('../ReactNative/AppContainer');
const I18nManager = require('../ReactNative/I18nManager');
const PropTypes = require('prop-types');
const NativeEventEmitter = require('../EventEmitter/NativeEventEmitter');
import NativeModalManager from './NativeModalManager';
const Platform = require('../Utilities/Platform');
const React = require('react');
const PropTypes = require('prop-types');
const ScrollView = require('../Components/ScrollView/ScrollView');
const StyleSheet = require('../StyleSheet/StyleSheet');
const View = require('../Components/View/View');
@@ -22,6 +25,12 @@ import type {ViewProps} from '../Components/View/ViewPropTypes';
import type {DirectEventHandler} from '../Types/CodegenTypes';
import type EmitterSubscription from '../vendor/emitter/EmitterSubscription';
import RCTModalHostView from './RCTModalHostViewNativeComponent';
const ModalEventEmitter =
Platform.OS === 'ios' && NativeModalManager != null
? new NativeEventEmitter(NativeModalManager)
: null;
/**
* The Modal component is a simple way to present content above an enclosing view.
*
@@ -178,9 +187,22 @@ class Modal extends React.Component<Props> {
};
}
componentDidMount() {
if (ModalEventEmitter) {
this._eventSubscription = ModalEventEmitter.addListener(
'modalDismissed',
event => {
if (event.modalID === this._identifier && this.props.onDismiss) {
this.props.onDismiss();
}
},
);
}
}
componentWillUnmount() {
if (this.props.onDismiss != null) {
this.props.onDismiss();
if (this._eventSubscription) {
this._eventSubscription.remove();
}
}
@@ -229,7 +251,7 @@ class Modal extends React.Component<Props> {
}
const innerChildren = __DEV__ ? (
<AppContainer rootTag={this.context.rootTag} internal_excludeLogBox>
<AppContainer rootTag={this.context.rootTag}>
{this.props.children}
</AppContainer>
) : (
@@ -15,6 +15,7 @@ import type {HostComponent} from '../Renderer/shims/ReactNativeTypes';
import type {
WithDefault,
DirectEventHandler,
BubblingEventHandler,
Int32,
} from '../Types/CodegenTypes';
@@ -86,6 +87,14 @@ type NativeProps = $ReadOnly<{|
*/
onShow?: ?DirectEventHandler<null>,
/**
* The `onDismiss` prop allows passing a function that will be called once
* the modal has been dismissed.
*
* See https://facebook.github.io/react-native/docs/modal.html#ondismiss
*/
onDismiss?: ?BubblingEventHandler<null>,
/**
* Deprecated. Use the `animationType` prop instead.
*/
@@ -0,0 +1,21 @@
/**
* 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';
import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry';
export interface Spec extends TurboModule {
+show: () => void;
+hide: () => void;
}
export default (TurboModuleRegistry.get<Spec>('LogBox'): ?Spec);
+1
View File
@@ -602,6 +602,7 @@ export default class Pressability {
event: PressEvent,
): void {
if (isTerminalSignal(signal)) {
this._touchActivatePosition = null;
this._cancelLongPressDelayTimeout();
}
@@ -395,9 +395,97 @@ describe('Pressability', () => {
jest.advanceTimersByTime(1);
expect(config.onLongPress).toBeCalled();
});
});
// TODO: onLongPressShouldCancelPress tests
it('is called if touch moves within 10dp', () => {
mockUIManagerMeasure();
const {config, handlers} = createMockPressability();
handlers.onStartShouldSetResponder();
handlers.onResponderGrant(createMockPressEvent('onResponderGrant'));
handlers.onResponderMove(
createMockPressEvent({
registrationName: 'onResponderMove',
pageX: 0,
pageY: 0,
}),
);
jest.advanceTimersByTime(130);
handlers.onResponderMove(
// NOTE: Delta from (0, 0) is ~9.9 < 10.
createMockPressEvent({
registrationName: 'onResponderMove',
pageX: 7,
pageY: 7,
}),
);
jest.advanceTimersByTime(370);
expect(config.onLongPress).toBeCalled();
});
it('is not called if touch moves beyond 10dp', () => {
mockUIManagerMeasure();
const {config, handlers} = createMockPressability();
handlers.onStartShouldSetResponder();
handlers.onResponderGrant(createMockPressEvent('onResponderGrant'));
handlers.onResponderMove(
createMockPressEvent({
registrationName: 'onResponderMove',
pageX: 0,
pageY: 0,
}),
);
jest.advanceTimersByTime(130);
handlers.onResponderMove(
createMockPressEvent({
registrationName: 'onResponderMove',
// NOTE: Delta from (0, 0) is ~10.6 > 10.
pageX: 7,
pageY: 8,
}),
);
jest.advanceTimersByTime(370);
expect(config.onLongPress).not.toBeCalled();
});
it('is called independent of preceding long touch gesture', () => {
mockUIManagerMeasure();
const {config, handlers} = createMockPressability();
handlers.onStartShouldSetResponder();
handlers.onResponderGrant(createMockPressEvent('onResponderGrant'));
handlers.onResponderMove(
createMockPressEvent({
registrationName: 'onResponderMove',
pageX: 0,
pageY: 0,
}),
);
jest.advanceTimersByTime(500);
expect(config.onLongPress).toHaveBeenCalledTimes(1);
handlers.onResponderRelease(createMockPressEvent('onResponderRelease'));
// Subsequent long touch gesture should not carry over previous state.
handlers.onStartShouldSetResponder();
handlers.onResponderGrant(createMockPressEvent('onResponderGrant'));
handlers.onResponderMove(
// NOTE: Delta from (0, 0) is ~10.6 > 10, but should not matter.
createMockPressEvent({
registrationName: 'onResponderMove',
pageX: 7,
pageY: 8,
}),
);
jest.advanceTimersByTime(500);
expect(config.onLongPress).toHaveBeenCalledTimes(2);
});
});
describe('onPress', () => {
it('is called even when `measure` does not finish', () => {
@@ -26,7 +26,7 @@ static NSString *const kRemoteNotificationRegistrationFailed = @"RemoteNotificat
static NSString *const kErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS";
#if !TARGET_OS_TV && !TARGET_OS_UIKITFORMAC
#if !TARGET_OS_TV
@implementation RCTConvert (NSCalendarUnit)
RCT_ENUM_CONVERTER(NSCalendarUnit,
+11 -27
View File
@@ -94,16 +94,14 @@ class AppContainer extends React.Component<Props, State> {
}
render(): React.Node {
let logBox = null;
if (__DEV__ && !this.props.internal_excludeLogBox) {
if (!global.__RCTProfileIsProfiling) {
if (global.__reactExperimentalLogBox) {
const LogBox = require('../LogBox/LogBox');
logBox = <LogBox />;
} else {
const YellowBox = require('../YellowBox/YellowBox');
logBox = <YellowBox />;
}
let yellowBox = null;
if (__DEV__) {
if (
!global.__RCTProfileIsProfiling &&
!this.props.internal_excludeLogBox
) {
const YellowBox = require('../YellowBox/YellowBox');
yellowBox = <YellowBox />;
}
}
@@ -137,7 +135,7 @@ class AppContainer extends React.Component<Props, State> {
<View style={styles.appContainer} pointerEvents="box-none">
{!this.state.hasError && innerView}
{this.state.inspector}
{logBox}
{yellowBox}
</View>
</RootTagContext.Provider>
);
@@ -152,22 +150,8 @@ const styles = StyleSheet.create({
if (__DEV__) {
if (!global.__RCTProfileIsProfiling) {
if (global.__reactExperimentalLogBox) {
const LogBox = require('../LogBox/LogBox');
LogBox.install();
// TODO: (rickhanlonii) T57484314 Temporary hack to fix LogBox experiment but we need to
// either decide to provide an error boundary by default or move this to a separate root.
AppContainer.getDerivedStateFromError = function getDerivedStateFromError(
error,
state,
) {
return {...state, hasError: true};
};
} else {
const YellowBox = require('../YellowBox/YellowBox');
YellowBox.install();
}
const YellowBox = require('../YellowBox/YellowBox');
YellowBox.install();
}
}
+23 -7
View File
@@ -125,6 +125,7 @@ const AppRegistry = {
appParameters.fabric,
showArchitectureIndicator,
scopedPerformanceLogger,
appKey === 'LogBox',
);
},
};
@@ -180,13 +181,15 @@ const AppRegistry = {
* See http://facebook.github.io/react-native/docs/appregistry.html#runapplication
*/
runApplication(appKey: string, appParameters: any): void {
const msg =
'Running "' + appKey + '" with ' + JSON.stringify(appParameters);
infoLog(msg);
BugReporting.addSource(
'AppRegistry.runApplication' + runCount++,
() => msg,
);
if (appKey !== 'LogBox') {
const msg =
'Running "' + appKey + '" with ' + JSON.stringify(appParameters);
infoLog(msg);
BugReporting.addSource(
'AppRegistry.runApplication' + runCount++,
() => msg,
);
}
invariant(
runnables[appKey] && runnables[appKey].run,
`"${appKey}" has not been registered. This can happen if:\n` +
@@ -292,4 +295,17 @@ const AppRegistry = {
BatchedBridge.registerCallableModule('AppRegistry', AppRegistry);
if (__DEV__) {
const LogBoxInspector = require('../LogBox/LogBoxInspectorContainer').default;
AppRegistry.registerComponent('LogBox', () => LogBoxInspector);
} else {
AppRegistry.registerComponent(
'LogBox',
() =>
function NoOp() {
return null;
},
);
}
module.exports = AppRegistry;
+3 -1
View File
@@ -29,6 +29,7 @@ function renderApplication<Props: Object>(
fabric?: boolean,
showArchitectureIndicator?: boolean,
scopedPerformanceLogger?: IPerformanceLogger,
isLogBox?: boolean,
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
@@ -39,7 +40,8 @@ function renderApplication<Props: Object>(
rootTag={rootTag}
fabric={fabric}
showArchitectureIndicator={showArchitectureIndicator}
WrapperComponent={WrapperComponent}>
WrapperComponent={WrapperComponent}
internal_excludeLogBox={isLogBox}>
<RootComponent {...initialProps} rootTag={rootTag} />
</AppContainer>
</PerformanceLoggerContext.Provider>
@@ -40,6 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy, nullable) RCTDirectEventBlock onScroll;
@property (nonatomic, assign) NSInteger mostRecentEventCount;
@property (nonatomic, assign) BOOL autoFocus;
@property (nonatomic, assign) BOOL blurOnSubmit;
@property (nonatomic, assign) BOOL selectTextOnFocus;
@property (nonatomic, assign) BOOL clearTextOnFocus;
@@ -25,6 +25,7 @@
BOOL _hasInputAccesoryView;
NSString *_Nullable _predictedText;
NSInteger _nativeEventCount;
BOOL _didMoveToWindow;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
@@ -522,7 +523,13 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
- (void)didMoveToWindow
{
[self.backedTextInputView reactFocusIfNeeded];
if (self.autoFocus && !_didMoveToWindow) {
[self.backedTextInputView reactFocus];
} else {
[self.backedTextInputView reactFocusIfNeeded];
}
_didMoveToWindow = YES;
}
#pragma mark - Custom Input Accessory View
@@ -562,14 +569,25 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
// These keyboard types (all are number pads) don't have a "Done" button by default,
// so we create an `inputAccessoryView` with this button for them.
BOOL shouldHaveInputAccesoryView =
(
keyboardType == UIKeyboardTypeNumberPad ||
keyboardType == UIKeyboardTypePhonePad ||
keyboardType == UIKeyboardTypeDecimalPad ||
keyboardType == UIKeyboardTypeASCIICapableNumberPad
) &&
textInputView.returnKeyType == UIReturnKeyDone;
BOOL shouldHaveInputAccesoryView;
if (@available(iOS 10.0, *)) {
shouldHaveInputAccesoryView =
(
keyboardType == UIKeyboardTypeNumberPad ||
keyboardType == UIKeyboardTypePhonePad ||
keyboardType == UIKeyboardTypeDecimalPad ||
keyboardType == UIKeyboardTypeASCIICapableNumberPad
) &&
textInputView.returnKeyType == UIReturnKeyDone;
} else {
shouldHaveInputAccesoryView =
(
keyboardType == UIKeyboardTypeNumberPad ||
keyboardType == UIKeyboardTypePhonePad ||
keyboardType == UIKeyboardTypeDecimalPad
) &&
textInputView.returnKeyType == UIReturnKeyDone;
}
if (_hasInputAccesoryView == shouldHaveInputAccesoryView) {
return;
@@ -48,6 +48,7 @@ RCT_REMAP_VIEW_PROPERTY(caretHidden, backedTextInputView.caretHidden, BOOL)
RCT_REMAP_VIEW_PROPERTY(clearButtonMode, backedTextInputView.clearButtonMode, UITextFieldViewMode)
RCT_REMAP_VIEW_PROPERTY(scrollEnabled, backedTextInputView.scrollEnabled, BOOL)
RCT_REMAP_VIEW_PROPERTY(secureTextEntry, backedTextInputView.secureTextEntry, BOOL)
RCT_EXPORT_VIEW_PROPERTY(autoFocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(blurOnSubmit, BOOL)
RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL)
RCT_EXPORT_VIEW_PROPERTY(keyboardType, UIKeyboardType)
+9
View File
@@ -17,6 +17,7 @@ import NativeAppearance, {
type ColorSchemeName,
} from './NativeAppearance';
import invariant from 'invariant';
import {isAsyncDebugging} from './DebugEnvironment';
type AppearanceListener = (preferences: AppearancePreferences) => void;
const eventEmitter = new EventEmitter();
@@ -50,6 +51,14 @@ module.exports = {
* @returns {?ColorSchemeName} Value for the color scheme preference.
*/
getColorScheme(): ?ColorSchemeName {
if (__DEV__) {
if (isAsyncDebugging) {
// Hard code light theme when using the async debugger as
// sync calls aren't supported
return 'light';
}
}
// TODO: (hramos) T52919652 Use ?ColorSchemeName once codegen supports union
const nativeColorScheme: ?string =
NativeAppearance == null
+21
View File
@@ -0,0 +1,21 @@
/**
* 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 let isAsyncDebugging: boolean = false;
if (__DEV__) {
// These native interfaces don't exist in asynchronous debugging environments.
isAsyncDebugging =
!global.nativeExtensions &&
!global.nativeCallSyncHook &&
!global.RN$Bridgeless;
}
+1 -1
View File
@@ -15,7 +15,7 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
export interface Spec extends TurboModule {
+getConstants: () => {||};
+vibrate: (pattern?: ?number) => void;
+vibrate: (pattern: number) => void;
// Android only
+vibrateByPattern: (pattern: Array<number>, repeat: number) => void;
+1 -1
View File
@@ -25,7 +25,7 @@ RCT_EXPORT_MODULE()
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
RCT_EXPORT_METHOD(vibrate:(NSNumber *)pattern)
RCT_EXPORT_METHOD(vibrate:(double)pattern)
{
[self vibrate];
}
+5 -4
View File
@@ -22,6 +22,7 @@ const Platform = require('../Utilities/Platform');
let _vibrating: boolean = false;
let _id: number = 0; // _id is necessary to prevent race condition.
const _default_vibration_length = 400;
function vibrateByPattern(pattern: Array<number>, repeat: boolean = false) {
if (_vibrating) {
@@ -29,7 +30,7 @@ function vibrateByPattern(pattern: Array<number>, repeat: boolean = false) {
}
_vibrating = true;
if (pattern[0] === 0) {
NativeVibration.vibrate();
NativeVibration.vibrate(_default_vibration_length);
pattern = pattern.slice(1);
}
if (pattern.length === 0) {
@@ -48,7 +49,7 @@ function vibrateScheduler(
if (!_vibrating || id !== _id) {
return;
}
NativeVibration.vibrate();
NativeVibration.vibrate(_default_vibration_length);
if (nextIndex >= pattern.length) {
if (repeat) {
nextIndex = 0;
@@ -70,7 +71,7 @@ const Vibration = {
* See https://facebook.github.io/react-native/docs/vibration.html#vibrate
*/
vibrate: function(
pattern: number | Array<number> = 400,
pattern: number | Array<number> = _default_vibration_length,
repeat: boolean = false,
) {
if (Platform.OS === 'android') {
@@ -86,7 +87,7 @@ const Vibration = {
return;
}
if (typeof pattern === 'number') {
NativeVibration.vibrate();
NativeVibration.vibrate(pattern);
} else if (Array.isArray(pattern)) {
vibrateByPattern(pattern, repeat);
} else {
+6 -11
View File
@@ -14,12 +14,9 @@
// limitations under the License.
//
#if !TARGET_OS_UIKITFORMAC
#import <React/RCTSRWebSocket.h>
#import <Availability.h>
#import <Endian.h>
#import <Security/SecRandom.h>
@@ -580,7 +577,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
NSMutableData *mutablePayload = [[NSMutableData alloc] initWithLength:sizeof(uint16_t) + maxMsgSize];
NSData *payload = mutablePayload;
((uint16_t *)mutablePayload.mutableBytes)[0] = EndianU16_BtoN(code);
((uint16_t *)mutablePayload.mutableBytes)[0] = NSSwapBigShortToHost(code);
if (reason) {
NSRange remainingRange = {0};
@@ -749,7 +746,7 @@ static inline BOOL closeCodeIsValid(int closeCode)
return;
} else if (dataSize >= 2) {
[data getBytes:&closeCode length:sizeof(closeCode)];
_closeCode = EndianU16_BtoN(closeCode);
_closeCode = NSSwapBigShortToHost(closeCode);
if (!closeCodeIsValid(_closeCode)) {
[self _closeWithProtocolError:[NSString stringWithFormat:@"Cannot have close code of %d", _closeCode]];
return;
@@ -972,12 +969,12 @@ static const uint8_t RCTSRPayloadLenMask = 0x7F;
if (header.payload_length == 126) {
assert(mapped_size >= sizeof(uint16_t));
uint16_t newLen = EndianU16_BtoN(*(uint16_t *)(mapped_buffer));
uint16_t newLen = NSSwapBigShortToHost(*(uint16_t *)(mapped_buffer));
header.payload_length = newLen;
offset += sizeof(uint16_t);
} else if (header.payload_length == 127) {
assert(mapped_size >= sizeof(uint64_t));
header.payload_length = EndianU64_BtoN(*(uint64_t *)(mapped_buffer));
header.payload_length = NSSwapBigLongLongToHost(*(uint64_t *)(mapped_buffer));
offset += sizeof(uint64_t);
} else {
assert(header.payload_length < 126 && header.payload_length >= 0);
@@ -1264,11 +1261,11 @@ static const size_t RCTSRFrameHeaderOverhead = 32;
frame_buffer[1] |= payloadLength;
} else if (payloadLength <= UINT16_MAX) {
frame_buffer[1] |= 126;
*((uint16_t *)(frame_buffer + frame_buffer_size)) = EndianU16_BtoN((uint16_t)payloadLength);
*((uint16_t *)(frame_buffer + frame_buffer_size)) = NSSwapBigShortToHost((uint16_t)payloadLength);
frame_buffer_size += sizeof(uint16_t);
} else {
frame_buffer[1] |= 127;
*((uint64_t *)(frame_buffer + frame_buffer_size)) = EndianU64_BtoN((uint64_t)payloadLength);
*((uint64_t *)(frame_buffer + frame_buffer_size)) = NSSwapBigLongLongToHost((uint64_t)payloadLength);
frame_buffer_size += sizeof(uint64_t);
}
@@ -1637,5 +1634,3 @@ static NSRunLoop *networkRunLoop = nil;
}
@end
#endif
+26 -28
View File
@@ -12,8 +12,8 @@
const YellowBoxWarning = require('./YellowBoxWarning');
import type {Category} from './YellowBoxCategory';
import type {Category, Message} from './YellowBoxCategory';
import type {Stack} from './YellowBoxSymbolication';
export type Registry = Map<Category, $ReadOnlyArray<YellowBoxWarning>>;
export type Observer = (registry: Registry) => void;
@@ -32,25 +32,13 @@ let disabled = false;
let projection = new Map();
let updateTimeout = null;
function isWarningIgnored(warning: YellowBoxWarning): boolean {
for (const pattern of ignorePatterns) {
if (pattern instanceof RegExp && pattern.test(warning.message.content)) {
return true;
} else if (
typeof pattern === 'string' &&
warning.message.content.includes(pattern)
) {
return true;
}
}
return false;
}
function handleUpdate(): void {
projection = new Map();
if (!disabled) {
for (const [category, warnings] of registry) {
const filtered = warnings.filter(warning => !isWarningIgnored(warning));
const filtered = warnings.filter(
warning => !YellowBoxRegistry.isWarningIgnored(warning.message),
);
if (filtered.length > 0) {
projection.set(category, filtered);
}
@@ -67,18 +55,28 @@ function handleUpdate(): void {
}
const YellowBoxRegistry = {
add({
args,
}: $ReadOnly<{|
args: $ReadOnlyArray<mixed>,
|}>): void {
if (typeof args[0] === 'string' && args[0].startsWith('(ADVICE)')) {
return;
isWarningIgnored(message: Message): boolean {
for (const pattern of ignorePatterns) {
if (pattern instanceof RegExp && pattern.test(message.content)) {
return true;
} else if (
typeof pattern === 'string' &&
message.content.includes(pattern)
) {
return true;
}
}
const {category, message, stack} = YellowBoxWarning.parse({
args,
});
return false;
},
add({
category,
message,
stack,
}: $ReadOnly<{|
category: Category,
message: Message,
stack: Stack,
|}>): void {
let warnings = registry.get(category);
if (warnings == null) {
warnings = [];
@@ -11,6 +11,7 @@
'use strict';
const YellowBoxWarning = require('../YellowBoxWarning');
const YellowBoxCategory = require('../YellowBoxCategory');
const YellowBoxRegistry = require('../YellowBoxRegistry');
@@ -34,7 +35,7 @@ describe('YellowBoxRegistry', () => {
});
it('adds and deletes warnings', () => {
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
const {category: categoryA} = YellowBoxCategory.parse(['A']);
expect(registry().size).toBe(1);
@@ -46,9 +47,9 @@ describe('YellowBoxRegistry', () => {
});
it('clears all warnings', () => {
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add({args: ['B']});
YellowBoxRegistry.add({args: ['C']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['C']}));
expect(registry().size).toBe(3);
@@ -57,9 +58,9 @@ describe('YellowBoxRegistry', () => {
});
it('sorts warnings in chronological order', () => {
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add({args: ['B']});
YellowBoxRegistry.add({args: ['C']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['C']}));
const {category: categoryA} = YellowBoxCategory.parse(['A']);
const {category: categoryB} = YellowBoxCategory.parse(['B']);
@@ -71,7 +72,7 @@ describe('YellowBoxRegistry', () => {
categoryC,
]);
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
// Expect `A` to be hoisted to the end of the registry.
expect(Array.from(registry().keys())).toEqual([
@@ -82,9 +83,9 @@ describe('YellowBoxRegistry', () => {
});
it('ignores warnings matching patterns', () => {
YellowBoxRegistry.add({args: ['A!']});
YellowBoxRegistry.add({args: ['B?']});
YellowBoxRegistry.add({args: ['C!']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A!']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B?']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['C!']}));
expect(registry().size).toBe(3);
YellowBoxRegistry.addIgnorePatterns(['!']);
@@ -95,9 +96,9 @@ describe('YellowBoxRegistry', () => {
});
it('ignores warnings matching regexs or pattern', () => {
YellowBoxRegistry.add({args: ['There are 4 dogs']});
YellowBoxRegistry.add({args: ['There are 3 cats']});
YellowBoxRegistry.add({args: ['There are H cats']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['There are 4 dogs']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['There are 3 cats']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['There are H cats']}));
expect(registry().size).toBe(3);
YellowBoxRegistry.addIgnorePatterns(['dogs']);
@@ -111,9 +112,9 @@ describe('YellowBoxRegistry', () => {
});
it('ignores all warnings when disabled', () => {
YellowBoxRegistry.add({args: ['A!']});
YellowBoxRegistry.add({args: ['B?']});
YellowBoxRegistry.add({args: ['C!']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A!']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B?']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['C!']}));
expect(registry().size).toBe(3);
YellowBoxRegistry.setDisabled(true);
@@ -124,57 +125,54 @@ describe('YellowBoxRegistry', () => {
});
it('groups warnings by simple categories', () => {
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
expect(registry().size).toBe(1);
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
expect(registry().size).toBe(1);
YellowBoxRegistry.add({args: ['B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B']}));
expect(registry().size).toBe(2);
});
it('groups warnings by format string categories', () => {
YellowBoxRegistry.add({args: ['%s', 'A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['%s', 'A']}));
expect(registry().size).toBe(1);
YellowBoxRegistry.add({args: ['%s', 'B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['%s', 'B']}));
expect(registry().size).toBe(1);
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
expect(registry().size).toBe(2);
YellowBoxRegistry.add({args: ['B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B']}));
expect(registry().size).toBe(3);
});
it('groups warnings with consideration for arguments', () => {
YellowBoxRegistry.add({args: ['A', 'B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A', 'B']}));
expect(registry().size).toBe(1);
YellowBoxRegistry.add({args: ['A', 'B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A', 'B']}));
expect(registry().size).toBe(1);
YellowBoxRegistry.add({args: ['A', 'C']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A', 'C']}));
expect(registry().size).toBe(2);
YellowBoxRegistry.add({args: ['%s', 'A', 'A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['%s', 'A', 'A']}));
expect(registry().size).toBe(3);
YellowBoxRegistry.add({args: ['%s', 'B', 'A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['%s', 'B', 'A']}));
expect(registry().size).toBe(3);
YellowBoxRegistry.add({args: ['%s', 'B', 'B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['%s', 'B', 'B']}));
expect(registry().size).toBe(4);
});
it('ignores warnings starting with "(ADVICE)"', () => {
YellowBoxRegistry.add({args: ['(ADVICE) ...']});
expect(registry().size).toBe(0);
});
it('does not ignore warnings formatted to start with "(ADVICE)"', () => {
YellowBoxRegistry.add({args: ['%s ...', '(ADVICE)']});
YellowBoxRegistry.add(
YellowBoxWarning.parse({args: ['%s ...', '(ADVICE)']}),
);
expect(registry().size).toBe(1);
});
@@ -189,8 +187,8 @@ describe('YellowBoxRegistry', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add({args: ['B']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['B']}));
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
});
@@ -207,7 +205,7 @@ describe('YellowBoxRegistry', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
@@ -226,7 +224,7 @@ describe('YellowBoxRegistry', () => {
const {observer} = observe();
expect(observer.mock.calls.length).toBe(1);
YellowBoxRegistry.add({args: ['A']});
YellowBoxRegistry.add(YellowBoxWarning.parse({args: ['A']}));
jest.runAllImmediates();
expect(observer.mock.calls.length).toBe(2);
@@ -1,59 +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 strict-local
* @format
*/
'use strict';
const PixelRatio = require('../../Utilities/PixelRatio');
const scale = PixelRatio.get();
/**
* We use inline images for YellowBox in order to avoid display latency due to
* resource contention with symbolicating stack traces.
*
* The following steps were used to create these:
*
* 1. Download SVG files from: https://feathericons.com
* 2. Rasterize SVG files to PNG files at 16dp, 36dp, and 48dp.
* 3. Convert to Base64: https://www.google.com/search?q=base64+image+encoder
*
* @see https://github.com/feathericons/feather
* @copyright 2013-2017 Cole Bemis
* @license MIT
*/
const YellowBoxImageSource = {
alertTriangle: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB60lEQVRoge2Z3W3DIBSFj9oFPAIjZARGyAiMkBHuJh4hI2QEj5AR3Me+tQ91JALHmD8bKvmTkCr5Auc6/kzUACcnRXzuvL4GoAB8Afjeea9qXADcAfw4475c65orgBl++NeYl5ouUQiHt5tQTRJuwB6b5zLY49QVGn7I0bo+kuv60IQbuHf5CWCIqOkCgX93maia1MkRAUMo+OI+AvUPp7a50EzcUCBF6psJrUkYiZgnZJ7eId8mMeIyhpW5hyLw72LKCXsl86VqwgAKceKapW5e/nZpJnSsuHaTM7muyDq7C63JprJS69YxhNTpSlkpKeLGNHCo0EJChcSNaQA4SGiFtBMXJFSI3YVOPXFB6kMoUl9NaE0Wl4h5KQ0AOwqde+KmNrCL0EKCxJ64qQ0AlYVWSBfXZusgW6Oa0Dni2hiEv0qsoci+yUJrsoikLlKAkP11ygK54taiSOgb/O5b/DMqS+gBZeLWJlnoEX7XwQkBDPIktlEkz7hWrEmxZG4M5L9GXYTk0qxwcopKxa3VABN6cosM/C5LxTUof4ReMKHf1nRlaSnuGsGM7kfU4w8RF5Bz4aNlokLe/HQ/ngl9/Qih4L9k3h4hA1+S3odxu3Q77Hl4r1Hg75n6D01M2Difbp02Mi3ZTk5OLH4BUyEtOlDYuK0AAAAASUVORK5CYII='
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABVklEQVRYheWX4U3DMBBGH4gBMoJHyAgeoSNkAxjBG5QNOkJHCGzQDcoGZQP4gY3Oqe1cEscS4pNOqs9Jvqvv6ZrCf9fDhnutD4A3H810Br4mcW5l7hLmIdze5mZi+OJD5syeBYzC6CjyR5Ef9zI/CJMb0Im9zufC/qG2eQdchcGQuGYQ+9dJgZvl0B2xbJGrZW6IIevFXp9YVwcyB540syJfFcgSeJb0cVcDcg68XAFQCUhH+ShLBcBGIA158LQFqIB8zBRwEp9fgctcxQld/L2pZxZVAk/KkucjaDGQmoknrz35KEE2sABIRxm8tVIBaZgHb61UQOYmXk7aFgQVJ6QWPCnLAriYAVILnpTxD7yh/9EZiIEE4m+y29uMkGy1nQ6i9wYFRB5PwKdYP/v1msmnUe89gn695bG0iqjdXeMiRu9599csvGKZ0jlu0Ac/7d2rxX9Q37HW6QfX/ZguAAAAAElFTkSuQmCC'
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAvUlEQVQ4jbWT4Q3CIBCFP40DdANxg24gIzhKuwEjuIFxAkcwTtARGicoG+iPXlMCB8UfvoQc4e7ePV4A/ogWuMlqc0W7AsEo0QMNcPplugMmwMia5KwKWkNIuIkHq3wLXGQ/Sq4IC3wkLpOfmZyKeEpIEKsDYB8VN0Afkfpg30uNiycbdKcNqXEOxdBEWoEAoqta8uZ0iqqkxwGDUrSFAXAHZpOWd/+ubD5Kz335Cx1wZna4Bh54AddauVl8ARfCLO9Xq7xGAAAAAElFTkSuQmCC'): string),
check: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAqElEQVRoge3YTQ7CIBRF4bPUu/8JS6gTSaqilh95vuR+CaO2cGgYNAUzMzOzFgHlPhRaMkDAcRoltKaTeIxPtQHxGn+Q5AgJx8cQjo8hHB9DOP76Yiu/RcTmN18WLiQCjs3zBkYXVGOeLWd+xcIr5pgyEzDz7FIjISPP/FRPUM+9W4nvYVfuCSXeB3669ldEOzRFfCUSx1cicXwlEsdXIvEPKDMzM7PMbtugw3XTpNA2AAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAf0lEQVRYhe2UvQ2AIBQGL3EBR3AESkv3bxxFN8DmWUgwvkI+En1X0cBd+IMg+DuDyDMCs413kfMiX4EMbD3l8oCaPIU85B4mYLEF5XJscrYFPRGvb/sZ4IlocubJGdH0wj1FSG77XYT0qdUi5O+8jOjyyZQRUnkZ0UUeBMF3OQC/0VsyGlxligAAAABJRU5ErkJggg=='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASElEQVQ4jWNgGJHAgIGBIYESze8ZGBjWU6L5PAMDgwBNNCdAFZJt83qoQmRDSHK2AFQhzBCy/IxsCNkBJsDAwLAfiknWPBIBAETPFeuA4fr6AAAAAElFTkSuQmCC'): string),
chevronLeft: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAgElEQVRoge3YMQ6DQBAEwRYvnf8nPAECbAnkyATsrt0lXUyPdAE6kCRJ/yXA+jopLbkhwHY6a2nNl8I1ftSA8Bm/MeQKBeNrBONrBONrBONrhMHxcPwOlMUvT32oszD8CoEj+giO6CE4oofgiB7Cj44Y86zyFoYPgOFPi5Ik6WwHji+QVIOyhqgAAAAASUVORK5CYII='
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAaUlEQVRYhe3WsQ2AMAwAwRcs5LEYg3HpYANoQKKgcEEUI/6adM5LbgySfmZsNDeACdiApdEfaQGswH6+Xd1jugc9xYQxxhjz9RhaxwxvDuul3MrAqDyjsozKKnWgXUqdsJcAZgqsTFJ5B7gjUNw0n0HHAAAAAElFTkSuQmCC'
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARklEQVQ4jWNgGPKAmUh1AQwMDBIMDAwPyLEkgYGB4T/UELI1J9BdcwCxmpnIMZ1YkECsK+hmCNZoZCHCgAUMDAwfoHg4AgDJuQ/bcLyV+QAAAABJRU5ErkJggg=='): string),
chevronRight: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAeElEQVRoge3YMQ6AIBQE0Ykn3fs3HEEbC6MdFp+v8xJaspNQAZIkqbcA4zwpXTJpAPvlpHTNhHtAu4jwDDCiQjBiDcGINQQj1hCMWEN4Boy3l25vL/iL0PgJBcfXCI6vERxfIzi+Rmg8Hj7wrdL+Yys0/1qUJEmzDvSAkFQ8EOdJAAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAZElEQVRYhe3WsQmAQAxA0Y8ulLEcw3HtdANtBNvzCJjD/5pUgQ9pApJ+Zu7YCWABDmDLzemzA+c94+MW4AkqExUY1caoVka1GibqlSm7qJJSJzPGGGMylYqBgi9sACtFYiQN7wKC6VDcJ7tlpQAAAABJRU5ErkJggg=='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAANUlEQVQ4jWNgGLbAgYGBIYASAwIYGBj+MzAwJFBiSMLQMISJEpMptp2mmimORgcGChPSEAIAHGENPH8gqdYAAAAASUVORK5CYII='): string),
loader: ((scale > 2
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABXElEQVRoge2a3W3DMAyEr+0CHkGjaISOcKN4k6zQETpCR+gGzgbpQ10kcamIpKQ6avQBBPxg3pHwL2UDg/8LASxrcNdKnCwATmssrUyeWgnju/DmXs8tRP+Sh2kgAJga1rFlWj2rcMD5YqQh77QJLbzIORjyRIJQCJW5ngYo5AVlrsgkCGqbsDbAhFfxqZsSZibP0oDXQ43HQPsg82i7sBoR+VcJq2YxKcPo0IoJLRZXmYGC6ezQmQUdVqhPBVH/CNBTSMkLVlzjA8Bbocb7GoPBoADi+umZilYzbrG/JrnljOvy734iu4To/BQaDB6Rl4LciPPF9Lmjhgvi+s7w6tCIGw3WKS0P8fvWNjt0ZkGHFeq7CQXTbkZKGg2JOxrqPUZ3s6ziNdju38IjS/dLi0EQpDLX2gDQYHEX6Hx5/YcA+6H0NgAYPnCMj3x7Mxq4wTGx3Q1E578aDDR8AX0mOGD6BEN/AAAAAElFTkSuQmCC'
: scale > 1
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABN0lEQVRYhe2WzU3EMBCFP34KyJEjJaQDXAIlJJ24BSow2wEdhHSwJSwd7JHbcmC0mOxMnDiWDIInWbHkN29exo4n8IvRAEFGU8OAA04yulyR60Jm7msbyIZloAMGwBfI4UWrWxM08LW/weC4iOMNTog4g0awKjBG827GxBwC3996NHizAifsSrTRmlsZm23CT9adktyXSq6ZUPdxgiXnZzW8CLcLuC3lvqA/gCt5NtjlPQL7TP0Wu1HtRRu4PO3T4TKTz2kG+AG9IN6CR/Su9iojBw69egfghWgL/pGCp+JFVPUqTjWjlsuqeAo1o6rt2C8QcNiV0UxoHPMieojmz0CfMKyhl1hN84xbI3gnz5Ftp7kH3iT5LsFdDUf6pzSJ6r2glIFDbuDNhqRH4I7Pvv4EvG/QqocP2Jh/xzzX/zUAAAAASUVORK5CYII='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAsklEQVQ4jaWTYRHCMAyFP7gJmIQ6oChgEpBQKXMwC3MADpAAEiphDuBHC4QuDRu8u9ylyWtem7Rgw2X7GT1wsghb4beAVzhtsfYyJgs44AoEQzBkjrMId1HkKPwyZ6oMSnxYsnk1NqT7yMo34Fzhd9meGJvs7Hh3NhqCLXDI/rT0lKsR+KOJgc9RdaRRarkZvELogYsi8HqxjUhGYE+aQg1jzketwFTZXHbbEpjB8eU7PwAbLiJz46707gAAAABJRU5ErkJggg=='): string),
};
module.exports = YellowBoxImageSource;
@@ -17,7 +17,6 @@ const SafeAreaView = require('../../Components/SafeAreaView/SafeAreaView');
const StyleSheet = require('../../StyleSheet/StyleSheet');
const Text = require('../../Text/Text');
const View = require('../../Components/View/View');
const YellowBoxImageSource = require('./YellowBoxImageSource');
const YellowBoxPressable = require('./YellowBoxPressable');
const YellowBoxStyle = require('./YellowBoxStyle');
@@ -43,7 +42,7 @@ const YellowBoxInspectorHeader = (props: Props): React.Node => {
<View style={styles.header}>
<YellowBoxInspectorHeaderButton
disabled={props.warnings[prevIndex] == null}
image={YellowBoxImageSource.chevronLeft}
image={require('../../LogBox/UI/LogBoxImages/chevron-left.png')}
onPress={() => props.onSelectIndex(prevIndex)}
/>
<View style={styles.headerTitle}>
@@ -51,7 +50,7 @@ const YellowBoxInspectorHeader = (props: Props): React.Node => {
</View>
<YellowBoxInspectorHeaderButton
disabled={props.warnings[nextIndex] == null}
image={YellowBoxImageSource.chevronRight}
image={require('../../LogBox/UI/LogBoxImages/chevron-right.png')}
onPress={() => props.onSelectIndex(nextIndex)}
/>
</View>
@@ -62,7 +61,7 @@ const YellowBoxInspectorHeader = (props: Props): React.Node => {
const YellowBoxInspectorHeaderButton = (
props: $ReadOnly<{|
disabled: boolean,
image: string,
image: number,
onPress?: ?() => void,
|}>,
): React.Node => (
@@ -74,10 +73,7 @@ const YellowBoxInspectorHeaderButton = (
onPress={props.disabled ? null : props.onPress}
style={styles.headerButton}>
{props.disabled ? null : (
<Image
source={{height: 16, uri: props.image, width: 16}}
style={styles.headerButtonImage}
/>
<Image source={props.image} style={styles.headerButtonImage} />
)}
</YellowBoxPressable>
);
@@ -99,6 +95,8 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
headerButtonImage: {
height: 14,
width: 8,
tintColor: YellowBoxStyle.getTextColor(1),
},
headerTitle: {
@@ -15,7 +15,6 @@ const Easing = require('../../Animated/src/Easing');
const React = require('react');
const StyleSheet = require('../../StyleSheet/StyleSheet');
const Text = require('../../Text/Text');
const YellowBoxImageSource = require('./YellowBoxImageSource');
const YellowBoxPressable = require('./YellowBoxPressable');
const YellowBoxStyle = require('./YellowBoxStyle');
@@ -41,15 +40,13 @@ class YellowBoxInspectorSourceMapStatus extends React.Component<Props, State> {
render(): React.Node {
let image;
switch (this.props.status) {
case 'COMPLETE':
image = YellowBoxImageSource.check;
break;
case 'FAILED':
image = YellowBoxImageSource.alertTriangle;
image = require('../../LogBox/UI/LogBoxImages/alert-triangle.png');
break;
case 'PENDING':
image = YellowBoxImageSource.loader;
image = require('../../LogBox/UI/LogBoxImages/loader.png');
break;
}
@@ -66,7 +63,7 @@ class YellowBoxInspectorSourceMapStatus extends React.Component<Props, State> {
this.props.status === 'PENDING' ? styles.pending : null,
)}>
<Animated.Image
source={{height: 16, uri: image, width: 16}}
source={image}
style={StyleSheet.compose(
styles.image,
this.state.rotate == null
@@ -142,6 +139,8 @@ const styles = StyleSheet.create({
backgroundColor: YellowBoxStyle.getTextColor(0.6),
},
image: {
height: 14,
width: 16,
marginEnd: 4,
tintColor: YellowBoxStyle.getBackgroundColor(1),
},
+102 -44
View File
@@ -12,13 +12,12 @@
const React = require('react');
import type {Category} from './Data/YellowBoxCategory';
import type {
Registry,
Subscription,
IgnorePattern,
} from './Data/YellowBoxRegistry';
import type {Registry, IgnorePattern} from './Data/YellowBoxRegistry';
import YellowBoxWarning from './Data/YellowBoxWarning';
import * as LogBoxData from '../LogBox/Data/LogBoxData';
import NativeLogBox from '../NativeModules/specs/NativeLogBox';
type Props = $ReadOnly<{||}>;
type State = {|
registry: ?Registry,
@@ -47,14 +46,19 @@ let YellowBox;
if (__DEV__) {
const Platform = require('../Utilities/Platform');
const RCTLog = require('../Utilities/RCTLog');
const YellowBoxList = require('./UI/YellowBoxList');
const YellowBoxContainer = require('./YellowBoxContainer').default;
const LogBox = require('../LogBox/LogBox');
const YellowBoxRegistry = require('./Data/YellowBoxRegistry');
const LogBoxNotificationContainer = require('../LogBox/LogBoxNotificationContainer')
.default;
// YellowBox needs to insert itself early,
// in order to access the component stacks appended by React DevTools.
const {error, warn} = console;
let errorImpl = error;
let warnImpl = warn;
let _isLogBoxEnabled = false;
let _isInstalled = false;
(console: any).error = function(...args) {
errorImpl(...args);
};
@@ -70,16 +74,17 @@ if (__DEV__) {
}
static install(): void {
if (_isLogBoxEnabled) {
LogBox.install();
return;
}
_isInstalled = true;
errorImpl = function(...args) {
error.call(console, ...args);
// Show YellowBox for the `warning` module.
if (typeof args[0] === 'string' && args[0].startsWith('Warning: ')) {
registerWarning(...args);
}
registerError(...args);
};
warnImpl = function(...args) {
warn.call(console, ...args);
registerWarning(...args);
};
@@ -102,51 +107,95 @@ if (__DEV__) {
}
static uninstall(): void {
if (_isLogBoxEnabled) {
LogBox.uninstall();
return;
}
_isInstalled = false;
errorImpl = error;
warnImpl = warn;
delete (console: any).disableYellowBox;
}
_subscription: ?Subscription;
static __unstable_enableLogBox(): void {
if (NativeLogBox == null) {
// The native module is required to enable LogBox.
return;
}
state = {
registry: null,
};
if (_isInstalled) {
throw new Error(
'LogBox must be enabled before AppContainer is required so that it can properly wrap the console methods.\n\nPlease enable LogBox earlier in your app.\n\n',
);
}
_isLogBoxEnabled = true;
// TODO: Temporary hack to prevent cycles with the ExceptionManager.
global.__unstable_isLogBoxEnabled = true;
}
static __unstable_isLogBoxEnabled(): boolean {
return !!_isLogBoxEnabled;
}
render(): React.Node {
// TODO: Ignore warnings that fire when rendering `YellowBox` itself.
return this.state.registry == null ? null : (
<YellowBoxList
onDismiss={this._handleDismiss}
onDismissAll={this._handleDismissAll}
registry={this.state.registry}
/>
);
}
componentDidMount(): void {
this._subscription = YellowBoxRegistry.observe(registry => {
this.setState({registry});
});
}
componentWillUnmount(): void {
if (this._subscription != null) {
this._subscription.unsubscribe();
if (_isLogBoxEnabled) {
return <LogBoxNotificationContainer />;
}
}
_handleDismiss = (category: Category): void => {
YellowBoxRegistry.delete(category);
};
_handleDismissAll(): void {
YellowBoxRegistry.clear();
// TODO: Ignore warnings that fire when rendering `YellowBox` itself.
return <YellowBoxContainer />;
}
};
const registerWarning = (...args): void => {
YellowBoxRegistry.add({args});
if (typeof args[0] === 'string' && args[0].startsWith('(ADVICE)')) {
return;
}
const {category, message, stack} = YellowBoxWarning.parse({
args,
});
if (!YellowBoxRegistry.isWarningIgnored(message)) {
YellowBoxRegistry.add({category, message, stack});
warn.call(console, ...args);
}
};
const registerError = (...args): void => {
// Only show YellowBox for the `warning` module, otherwise pass through and skip.
if (typeof args[0] !== 'string' || !args[0].startsWith('Warning: ')) {
error.call(console, ...args);
return;
}
const format = args[0].replace('Warning: ', '');
const filterResult = LogBoxData.checkWarningFilter(format);
if (filterResult.suppressCompletely) {
return;
}
args[0] = filterResult.finalFormat;
const {category, message, stack} = YellowBoxWarning.parse({
args,
});
if (YellowBoxRegistry.isWarningIgnored(message)) {
return;
}
if (filterResult.forceDialogImmediately === true) {
// This will pop a redbox. Do not downgrade. These are real bugs with same severity as throws.
error.call(console, message.content);
} else {
// Unfortunately, we need to add the Warning: prefix back so we don't show a redbox later.
args[0] = `Warning: ${filterResult.finalFormat}`;
// Note: YellowBox has no concept of "soft errors" so we're showing YellowBox for those.
YellowBoxRegistry.add({category, message, stack});
error.call(console, ...args);
}
};
} else {
YellowBox = class extends React.Component<Props, State> {
@@ -162,6 +211,13 @@ if (__DEV__) {
// Do nothing.
}
static __unstable_enableLogBox(): void {
// Do nothing.
}
static __unstable_isLogBoxEnabled(): boolean {
return false;
}
render(): React.Node {
return null;
}
@@ -172,5 +228,7 @@ module.exports = (YellowBox: Class<React.Component<Props, State>> & {
ignoreWarnings($ReadOnlyArray<IgnorePattern>): void,
install(): void,
uninstall(): void,
__unstable_enableLogBox(): void,
__unstable_isLogBoxEnabled(): boolean,
...
});
+65
View File
@@ -0,0 +1,65 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
const React = require('react');
import type {Category} from './Data/YellowBoxCategory';
import type {Registry, Subscription} from './Data/YellowBoxRegistry';
type Props = $ReadOnly<{||}>;
type State = $ReadOnly<{|
registry: ?Registry,
|}>;
const YellowBoxList = require('./UI/YellowBoxList');
const YellowBoxRegistry = require('./Data/YellowBoxRegistry');
class YellowBoxContainer extends React.Component<Props, State> {
_subscription: ?Subscription;
state: State = {
registry: null,
};
render(): React.Node {
// TODO: Ignore warnings that fire when rendering `YellowBox` itself.
return this.state.registry == null ? null : (
<YellowBoxList
onDismiss={this._handleDismiss}
onDismissAll={this._handleDismissAll}
registry={this.state.registry}
/>
);
}
componentDidMount(): void {
this._subscription = YellowBoxRegistry.observe(registry => {
this.setState({registry});
});
}
componentWillUnmount(): void {
if (this._subscription != null) {
this._subscription.unsubscribe();
}
}
_handleDismiss = (category: Category): void => {
YellowBoxRegistry.delete(category);
};
_handleDismissAll(): void {
YellowBoxRegistry.clear();
}
}
export default YellowBoxContainer;
+202 -9
View File
@@ -11,20 +11,62 @@
'use strict';
const YellowBox = require('../YellowBox');
import * as React from 'react';
const YellowBoxRegistry = require('../Data/YellowBoxRegistry');
const LogBoxData = require('../../LogBox/Data/LogBoxData');
const render = require('../../../jest/renderer');
jest.mock('../../NativeModules/specs/NativeLogBox', () => true);
jest.mock('../../LogBox/LogBoxNotificationContainer', () => ({
__esModule: true,
default: 'LogBoxNotificationContainer',
}));
type Overrides = {|
forceDialogImmediately?: boolean,
suppressDialog_LEGACY?: boolean,
suppressCompletely?: boolean,
|};
const setFilter = (options?: Overrides) => {
LogBoxData.setWarningFilter(format => ({
finalFormat: format,
forceDialogImmediately: false,
suppressDialog_LEGACY: false,
suppressCompletely: false,
monitorEvent: null,
monitorListVersion: 0,
monitorSampleRate: 0,
...options,
}));
};
const install = () => {
const YellowBox = require('../YellowBox');
YellowBox.install();
};
const uninstall = () => {
const YellowBox = require('../YellowBox');
YellowBox.uninstall();
};
describe('YellowBox', () => {
const {error, warn} = console;
const mockError = jest.fn();
const mockWarn = jest.fn();
beforeEach(() => {
jest.resetModules();
(console: any).error = jest.fn();
(console: any).warn = jest.fn();
mockError.mockClear();
mockWarn.mockClear();
(console: any).error = mockError;
(console: any).warn = mockWarn;
});
afterEach(() => {
YellowBox.uninstall();
uninstall();
(console: any).error = error;
(console: any).warn = warn;
});
@@ -32,7 +74,7 @@ describe('YellowBox', () => {
it('can set `disableYellowBox` after installing', () => {
expect((console: any).disableYellowBox).toBe(undefined);
YellowBox.install();
install();
expect((console: any).disableYellowBox).toBe(false);
expect(YellowBoxRegistry.isDisabled()).toBe(false);
@@ -47,7 +89,7 @@ describe('YellowBox', () => {
expect((console: any).disableYellowBox).toBe(undefined);
(console: any).disableYellowBox = true;
YellowBox.install();
install();
expect((console: any).disableYellowBox).toBe(true);
expect(YellowBoxRegistry.isDisabled()).toBe(true);
@@ -56,22 +98,173 @@ describe('YellowBox', () => {
it('registers warnings', () => {
jest.mock('../Data/YellowBoxRegistry');
YellowBox.install();
install();
expect(YellowBoxRegistry.add).not.toBeCalled();
(console: any).warn('...');
expect(YellowBoxRegistry.add).toBeCalled();
expect(mockWarn).toBeCalledTimes(1);
expect(mockWarn).toBeCalledWith('...');
});
it('registers errors beginning with "Warning: "', () => {
it('registers errors', () => {
jest.mock('../Data/YellowBoxRegistry');
YellowBox.install();
install();
(console: any).error('...');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(mockError).toBeCalledTimes(1);
expect(mockError).toBeCalledWith('...');
});
it('skips ADVICE warnings', () => {
jest.mock('../Data/YellowBoxRegistry');
install();
(console: any).warn('(ADVICE) Ignore me');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(mockWarn).not.toBeCalled();
});
it('skips ignored warnings', () => {
jest.mock('../Data/YellowBoxRegistry');
install();
(YellowBoxRegistry: any).isWarningIgnored.mockReturnValue(true);
(console: any).warn('Ignore me');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(mockWarn).not.toBeCalled();
});
it('registers Warning module errors with default options to YellowBox', () => {
jest.mock('../Data/YellowBoxRegistry');
setFilter();
install();
(console: any).error('Warning: ...');
expect(YellowBoxRegistry.add).toBeCalled();
expect(mockError).toBeCalled();
expect(mockError).toBeCalledTimes(1);
expect(mockWarn).not.toBeCalled();
});
it('skips Warning module errors with forceDialogImmediately', () => {
jest.mock('../Data/YellowBoxRegistry');
setFilter({
suppressCompletely: true,
});
install();
(console: any).error('Warning: ...');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(mockError).not.toBeCalled();
expect(mockWarn).not.toBeCalled();
});
it('registers Warning errors with forceDialogImmediately as console.error (with interpolation)', () => {
jest.mock('../Data/YellowBoxRegistry');
setFilter({
forceDialogImmediately: true,
});
install();
(console: any).error('Warning: %s', 'Something');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(mockWarn).not.toBeCalled();
expect(mockError).toBeCalledTimes(1);
// We expect this to be the interpolated value because we don't do interpolation downstream.
// We also strip the "Warning" prefix, otherwise the redbox would be skipped downstream.
expect(mockError).toBeCalledWith('Something');
});
it('registers Warning errors with suppressDialog_LEGACY to YellowBox', () => {
jest.mock('../Data/YellowBoxRegistry');
setFilter({
suppressDialog_LEGACY: true,
});
install();
(console: any).error('Warning: Something');
expect(YellowBoxRegistry.add).toBeCalledTimes(1);
expect(mockWarn).not.toBeCalled();
expect(mockError).toBeCalledTimes(1);
// We cannot strip the "Warning" prefix or it would pop a redbox.
expect(mockError).toBeCalledWith('Warning: Something');
});
it('skips Warning errors sent to YellowBox but ignored by patterns', () => {
jest.mock('../Data/YellowBoxRegistry');
setFilter({
suppressDialog_LEGACY: true,
});
install();
(YellowBoxRegistry: any).isWarningIgnored.mockReturnValue(true);
(console: any).error('Warning: ...');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(mockWarn).not.toBeCalled();
expect(mockError).not.toBeCalled();
});
it('if LogBox is enabled, installs and uninstalls LogBox', () => {
jest.mock('../../LogBox/Data/LogBoxData');
jest.mock('../Data/YellowBoxRegistry');
const YellowBox = require('../YellowBox');
YellowBox.__unstable_enableLogBox();
install();
(console: any).warn('Some warning');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(LogBoxData.addLog).toBeCalled();
expect(require('../YellowBox').__unstable_isLogBoxEnabled()).toBe(true);
uninstall();
(LogBoxData.addLog: any).mockClear();
(console: any).warn('Some warning');
expect(YellowBoxRegistry.add).not.toBeCalled();
expect(LogBoxData.addLog).not.toBeCalled();
expect(YellowBox.__unstable_isLogBoxEnabled()).toBe(true);
});
it('throws if LogBox is enabled after YellowBox is installed', () => {
jest.mock('../Data/YellowBoxRegistry');
const YellowBox = require('../YellowBox');
install();
expect(() => YellowBox.__unstable_enableLogBox()).toThrow(
'LogBox must be enabled before AppContainer is required so that it can properly wrap the console methods.\n\nPlease enable LogBox earlier in your app.\n\n',
);
});
it('should render YellowBoxContainer by default', () => {
const YellowBox = require('../YellowBox');
const output = render.shallowRender(<YellowBox />);
expect(output).toMatchSnapshot();
});
it('should render LogBoxNotificationContainer when LogBox is enabled', () => {
const YellowBox = require('../YellowBox');
YellowBox.__unstable_enableLogBox();
const output = render.shallowRender(<YellowBox />);
expect(output).toMatchSnapshot();
});
});
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`YellowBox should render LogBoxNotificationContainer when LogBox is enabled 1`] = `<LogBoxNotificationContainer />`;
exports[`YellowBox should render YellowBoxContainer by default 1`] = `<YellowBoxContainer />`;
+49 -1
View File
@@ -17,15 +17,62 @@ def pods()
# Additional Pods which aren't included in the default Podfile
pod 'React-ART', :path => '../Libraries/ART'
pod 'React-RCTPushNotification', :path => '../Libraries/PushNotificationIOS'
pod 'Yoga',:path => '../ReactCommon/yoga', :modular_headers => true
# Additional Pods which are classed as unstable
#
# To use fabric: add `fabric_enabled` option to the use_react_native method above, like below
# use_react_native!(path: "..", fabric_enabled: true)
end
def flipper_pods()
flipperkit_version = '0.30.1'
pod 'FlipperKit', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/FlipperKitLayoutPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/SKIOSNetworkPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/FlipperKitUserDefaultsPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
pod 'FlipperKit/FlipperKitReactPlugin', '~>' + flipperkit_version, :configuration => 'Debug'
if ENV['USE_FRAMEWORKS'] == '1'
$static_framework = ['FlipperKit', 'Flipper', 'Flipper-Folly',
'CocoaAsyncSocket', 'ComponentKit', 'Flipper-DoubleConversion',
'Flipper-Glog', 'Flipper-PeerTalk', 'Flipper-RSocket',
'CocoaLibEvent', 'OpenSSL-Universal', 'boost-for-react-native']
pre_install do |installer|
Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
installer.pod_targets.each do |pod|
if $static_framework.include?(pod.name)
def pod.build_type;
Pod::Target::BuildType.static_library
end
end
end
end
end
end
# Post Install processing for Flipper
def flipper_post_install(installer)
file_name = Dir.glob("*.xcodeproj")[0]
app_project = Xcodeproj::Project.open(file_name)
app_project.native_targets.each do |target|
target.build_configurations.each do |config|
cflags = config.build_settings['OTHER_CFLAGS'] || '$(inherited) '
unless cflags.include? '-DFB_SONARKIT_ENABLED=1'
puts 'Adding -DFB_SONARKIT_ENABLED=1 in OTHER_CFLAGS...'
cflags << ' -DFB_SONARKIT_ENABLED=1 '
end
config.build_settings['OTHER_CFLAGS'] = cflags
end
app_project.save
end
installer.pods_project.save
end
target 'RNTester' do
pods()
flipper_pods()
end
target 'RNTesterUnitTests' do
@@ -39,6 +86,7 @@ target 'RNTesterIntegrationTests' do
end
post_install do |installer|
flipper_post_install(installer)
installer.pods_project.targets.each do |target|
puts target.name
end
+273 -199
View File
@@ -1,14 +1,60 @@
PODS:
- boost-for-react-native (1.63.0)
- CocoaAsyncSocket (7.6.3)
- CocoaLibEvent (1.0.0)
- DoubleConversion (1.1.6)
- FBLazyVector (1000.0.0)
- FBReactNativeSpec (1000.0.0):
- FBLazyVector (0.62.0)
- FBReactNativeSpec (0.62.0):
- Folly (= 2018.10.22.00)
- RCTRequired (= 1000.0.0)
- RCTTypeSafety (= 1000.0.0)
- React-Core (= 1000.0.0)
- React-jsi (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- RCTRequired (= 0.62.0)
- RCTTypeSafety (= 0.62.0)
- React-Core (= 0.62.0)
- React-jsi (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- Flipper (0.30.1):
- Flipper-Folly (~> 2.1)
- Flipper-RSocket (~> 1.0)
- Flipper-Folly (2.1.0):
- boost-for-react-native
- CocoaLibEvent (~> 1.0)
- DoubleConversion
- glog
- OpenSSL-Universal (= 1.0.2.19)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.0.0):
- Flipper-Folly (~> 2.0)
- FlipperKit (0.30.1):
- FlipperKit/Core (= 0.30.1)
- FlipperKit/Core (0.30.1):
- Flipper (~> 0.30.1)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- FlipperKit/CppBridge (0.30.1):
- Flipper (~> 0.30.1)
- FlipperKit/FBCxxFollyDynamicConvert (0.30.1):
- Flipper-Folly (~> 2.1)
- FlipperKit/FBDefines (0.30.1)
- FlipperKit/FKPortForwarding (0.30.1):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.30.1)
- FlipperKit/FlipperKitLayoutPlugin (0.30.1):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.30.1)
- FlipperKit/FlipperKitNetworkPlugin (0.30.1):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.30.1):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.30.1):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.30.1):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Folly (2018.10.22.00):
- boost-for-react-native
- DoubleConversion
@@ -19,269 +65,279 @@ PODS:
- DoubleConversion
- glog
- glog (0.3.5)
- RCTRequired (1000.0.0)
- RCTTypeSafety (1000.0.0):
- FBLazyVector (= 1000.0.0)
- OpenSSL-Universal (1.0.2.19):
- OpenSSL-Universal/Static (= 1.0.2.19)
- OpenSSL-Universal/Static (1.0.2.19)
- RCTRequired (0.62.0)
- RCTTypeSafety (0.62.0):
- FBLazyVector (= 0.62.0)
- Folly (= 2018.10.22.00)
- RCTRequired (= 1000.0.0)
- React-Core (= 1000.0.0)
- React (1000.0.0):
- React-Core (= 1000.0.0)
- React-Core/DevSupport (= 1000.0.0)
- React-Core/RCTWebSocket (= 1000.0.0)
- React-RCTActionSheet (= 1000.0.0)
- React-RCTAnimation (= 1000.0.0)
- React-RCTBlob (= 1000.0.0)
- React-RCTImage (= 1000.0.0)
- React-RCTLinking (= 1000.0.0)
- React-RCTNetwork (= 1000.0.0)
- React-RCTSettings (= 1000.0.0)
- React-RCTText (= 1000.0.0)
- React-RCTVibration (= 1000.0.0)
- React-ART (1000.0.0):
- React-Core/ARTHeaders (= 1000.0.0)
- React-Core (1000.0.0):
- RCTRequired (= 0.62.0)
- React-Core (= 0.62.0)
- React (0.62.0):
- React-Core (= 0.62.0)
- React-Core/DevSupport (= 0.62.0)
- React-Core/RCTWebSocket (= 0.62.0)
- React-RCTActionSheet (= 0.62.0)
- React-RCTAnimation (= 0.62.0)
- React-RCTBlob (= 0.62.0)
- React-RCTImage (= 0.62.0)
- React-RCTLinking (= 0.62.0)
- React-RCTNetwork (= 0.62.0)
- React-RCTSettings (= 0.62.0)
- React-RCTText (= 0.62.0)
- React-RCTVibration (= 0.62.0)
- React-ART (0.62.0):
- React-Core/ARTHeaders (= 0.62.0)
- React-Core (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 1000.0.0)
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-Core/Default (= 0.62.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/ARTHeaders (1000.0.0):
- React-Core/ARTHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/CoreModulesHeaders (1000.0.0):
- React-Core/CoreModulesHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/Default (1000.0.0):
- React-Core/Default (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/DevSupport (1000.0.0):
- React-Core/DevSupport (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 1000.0.0)
- React-Core/RCTWebSocket (= 1000.0.0)
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-jsinspector (= 1000.0.0)
- React-Core/Default (= 0.62.0)
- React-Core/RCTWebSocket (= 0.62.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- React-jsinspector (= 0.62.0)
- Yoga
- React-Core/RCTActionSheetHeaders (1000.0.0):
- React-Core/RCTActionSheetHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTAnimationHeaders (1000.0.0):
- React-Core/RCTAnimationHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTBlobHeaders (1000.0.0):
- React-Core/RCTBlobHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTImageHeaders (1000.0.0):
- React-Core/RCTImageHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTLinkingHeaders (1000.0.0):
- React-Core/RCTLinkingHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTNetworkHeaders (1000.0.0):
- React-Core/RCTNetworkHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTPushNotificationHeaders (1000.0.0):
- React-Core/RCTPushNotificationHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTSettingsHeaders (1000.0.0):
- React-Core/RCTSettingsHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTTextHeaders (1000.0.0):
- React-Core/RCTTextHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTVibrationHeaders (1000.0.0):
- React-Core/RCTVibrationHeaders (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-Core/RCTWebSocket (1000.0.0):
- React-Core/RCTWebSocket (0.62.0):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 1000.0.0)
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsiexecutor (= 1000.0.0)
- React-Core/Default (= 0.62.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsiexecutor (= 0.62.0)
- Yoga
- React-CoreModules (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- React-CoreModules (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 1000.0.0)
- React-Core/CoreModulesHeaders (= 1000.0.0)
- React-RCTImage (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-cxxreact (1000.0.0):
- RCTTypeSafety (= 0.62.0)
- React-Core/CoreModulesHeaders (= 0.62.0)
- React-RCTImage (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-cxxreact (0.62.0):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsinspector (= 1000.0.0)
- React-jsi (1000.0.0):
- React-jsinspector (= 0.62.0)
- React-jsi (0.62.0):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsi/Default (= 1000.0.0)
- React-jsi/Default (1000.0.0):
- React-jsi/Default (= 0.62.0)
- React-jsi/Default (0.62.0):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsiexecutor (1000.0.0):
- React-jsiexecutor (0.62.0):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-jsinspector (1000.0.0)
- React-RCTActionSheet (1000.0.0):
- React-Core/RCTActionSheetHeaders (= 1000.0.0)
- React-RCTAnimation (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- React-jsinspector (0.62.0)
- React-RCTActionSheet (0.62.0):
- React-Core/RCTActionSheetHeaders (= 0.62.0)
- React-RCTAnimation (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 1000.0.0)
- React-Core/RCTAnimationHeaders (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTBlob (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- RCTTypeSafety (= 0.62.0)
- React-Core/RCTAnimationHeaders (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTBlob (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- React-Core/RCTBlobHeaders (= 1000.0.0)
- React-Core/RCTWebSocket (= 1000.0.0)
- React-jsi (= 1000.0.0)
- React-RCTNetwork (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTImage (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- React-Core/RCTBlobHeaders (= 0.62.0)
- React-Core/RCTWebSocket (= 0.62.0)
- React-jsi (= 0.62.0)
- React-RCTNetwork (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTImage (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 1000.0.0)
- React-Core/RCTImageHeaders (= 1000.0.0)
- React-RCTNetwork (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTLinking (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- React-Core/RCTLinkingHeaders (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTNetwork (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- RCTTypeSafety (= 0.62.0)
- React-Core/RCTImageHeaders (= 0.62.0)
- React-RCTNetwork (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTLinking (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- React-Core/RCTLinkingHeaders (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTNetwork (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 1000.0.0)
- React-Core/RCTNetworkHeaders (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTPushNotification (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- RCTTypeSafety (= 1000.0.0)
- React-Core/RCTPushNotificationHeaders (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTSettings (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- RCTTypeSafety (= 0.62.0)
- React-Core/RCTNetworkHeaders (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTPushNotification (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- RCTTypeSafety (= 0.62.0)
- React-Core/RCTPushNotificationHeaders (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTSettings (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 1000.0.0)
- React-Core/RCTSettingsHeaders (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-RCTTest (1000.0.0):
- React-Core (= 1000.0.0)
- React-CoreModules (= 1000.0.0)
- React-RCTText (1000.0.0):
- React-Core/RCTTextHeaders (= 1000.0.0)
- React-RCTVibration (1000.0.0):
- FBReactNativeSpec (= 1000.0.0)
- RCTTypeSafety (= 0.62.0)
- React-Core/RCTSettingsHeaders (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- React-RCTTest (0.62.0):
- React-Core (= 0.62.0)
- React-CoreModules (= 0.62.0)
- React-RCTText (0.62.0):
- React-Core/RCTTextHeaders (= 0.62.0)
- React-RCTVibration (0.62.0):
- FBReactNativeSpec (= 0.62.0)
- Folly (= 2018.10.22.00)
- React-Core/RCTVibrationHeaders (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- ReactCommon/callinvoker (1000.0.0):
- React-Core/RCTVibrationHeaders (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- ReactCommon/callinvoker (0.62.0):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 1000.0.0)
- ReactCommon/turbomodule/core (1000.0.0):
- React-cxxreact (= 0.62.0)
- ReactCommon/turbomodule/core (0.62.0):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 1000.0.0)
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- ReactCommon/callinvoker (= 1000.0.0)
- ReactCommon/turbomodule/samples (1000.0.0):
- React-Core (= 0.62.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- ReactCommon/callinvoker (= 0.62.0)
- ReactCommon/turbomodule/samples (0.62.0):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 1000.0.0)
- React-cxxreact (= 1000.0.0)
- React-jsi (= 1000.0.0)
- ReactCommon/callinvoker (= 1000.0.0)
- ReactCommon/turbomodule/core (= 1000.0.0)
- React-Core (= 0.62.0)
- React-cxxreact (= 0.62.0)
- React-jsi (= 0.62.0)
- ReactCommon/callinvoker (= 0.62.0)
- ReactCommon/turbomodule/core (= 0.62.0)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
DEPENDENCIES:
- DoubleConversion (from `../third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../Libraries/FBReactNativeSpec`)
- FlipperKit (~> 0.30.1)
- FlipperKit/FlipperKitLayoutPlugin (~> 0.30.1)
- FlipperKit/FlipperKitReactPlugin (~> 0.30.1)
- FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.30.1)
- FlipperKit/SKIOSNetworkPlugin (~> 0.30.1)
- Folly (from `../third-party-podspecs/Folly.podspec`)
- glog (from `../third-party-podspecs/glog.podspec`)
- RCTRequired (from `../Libraries/RCTRequired`)
@@ -313,8 +369,17 @@ DEPENDENCIES:
- Yoga (from `../ReactCommon/yoga`)
SPEC REPOS:
trunk:
https://cdn.cocoapods.org/:
- boost-for-react-native
- CocoaAsyncSocket
- CocoaLibEvent
- Flipper
- Flipper-Folly
- Flipper-PeerTalk
- Flipper-RSocket
- FlipperKit
- OpenSSL-Universal
- YogaKit
EXTERNAL SOURCES:
DoubleConversion:
@@ -376,35 +441,44 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
CocoaAsyncSocket: eafaa68a7e0ec99ead0a7b35015e0bf25d2c8987
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: 34431b7e61740bed29b082ff81500b0ffafaffa0
FBReactNativeSpec: e9febd2d5cc091662f172724165922b2e28d10a3
FBLazyVector: 545eccf4f6ef2de8fd450fd8a1edb3f913c7371a
FBReactNativeSpec: 85c7f8347f4a6e911742228e89e245187afa298e
Flipper: d591b88245dc8c8147819aa249f911923c7417fc
Flipper-Folly: bcae82405dafd18ac9f8d9d4902fd1c2ef2a7e77
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 1260a31c05c238eabfa9bb8a64e3983049048371
FlipperKit: 3e13631bca7c5ec0dd54ee1d096f5e5d32a5d784
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
RCTRequired: 33f3b89d2d82ef01c02b9b4f8146c43762e509d8
RCTTypeSafety: 2b1cb2d92b779aa9a3522f67bd4f07e6b6d0797e
React: 28a654b69575941571c073a656bc06795825e7f7
React-ART: a5da06a892342d03896e0db45a7072525981f63c
React-Core: f8656b21cfe16b1fe276686f3b921bce0fa6de4d
React-CoreModules: 96b2f1e0b84493e6c1b7f3bb21357f24fdcfce2f
React-cxxreact: 7c4242192149ce0205b53efaa03e3bf86ba4337c
React-jsi: 98d1f9d8a79d2720ba6a44c2d928a77f315b7e4f
React-jsiexecutor: c0ab8c80a6e88380d63f583690a50d4a723b47b5
React-jsinspector: ea0a218071a11c3687cef2480580180caa6a64c0
React-RCTActionSheet: 090e7bd7c5774d919c47c4eeff78223a7fd8c19c
React-RCTAnimation: 891c2b3404c214dc19faee57b5f249da6deeb099
React-RCTBlob: 8df793b30385b7ffe7e6703651043bad369cd756
React-RCTImage: 3ee9a6cd02c7741ebe3a001d51a18c349019778f
React-RCTLinking: 7ccb8f6dcfd4b95b68a73119aca7bca9fa530b08
React-RCTNetwork: 565fa6cc6108db9210fe5774f04ce52edccbb8ed
React-RCTPushNotification: 494ccfc569e2a699c0cc1a816eaebf8197a2ebc8
React-RCTSettings: 8138286da8de74839cb436dd37704ed64d4bfe78
React-RCTTest: d148e0657ce77ffd43a10325c284f47f25fb0532
React-RCTText: 9078167d3bc011162326f2d8ef4dd580ec1eca17
React-RCTVibration: e3269787c533de8c4f54f489202d848fdef33e1d
ReactCommon: 9d212865526209dc2d01be40340c8d27b53e6bea
Yoga: d88d8b51ee5b247f43211e2edf272438df1b484f
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
RCTRequired: 0873f5bdb1762d2b9b1ae16a01c4f91d6ee3b6dd
RCTTypeSafety: a605e0cc0e4220f6e65896bd9e675073c2978f35
React: 8abf6bdd2b05538e9445f7bbda800df744068bfe
React-ART: 815f382e56c662740eeb48c296224f936d35dd21
React-Core: d6daa0d60a4180915e889a5e81f28522cb30359a
React-CoreModules: 9d5343b095a52e830954a1dd7ae1cb9321ceeddc
React-cxxreact: c108ca236585b9c802f1eeab11fed1a023faac3a
React-jsi: bc8166d6833cdcb0848c80710b26ce63fad2c099
React-jsiexecutor: 8bf0b2707f05865113415088c398a7f98c0cf546
React-jsinspector: 8e5913c4c6c54f0d3f9c9fc630c465a89cded65d
React-RCTActionSheet: 674afbc8b9c76e0a83520e0a51da29a70802c03f
React-RCTAnimation: f5f24330d09ee677fb49e0782f8321868f4df431
React-RCTBlob: b773ce6138ab0d172ebd8a455fd4efd200a92549
React-RCTImage: 8dbaa77916f9d21ff8faa0f3f5f06d4069c28e93
React-RCTLinking: 312a2b3511e2829e68c300c2cdcae4282fefc7ef
React-RCTNetwork: 4b87acf29c38b8819bea67dad3edeca7b9a20718
React-RCTPushNotification: 04424ad9d13ebac07ea14ae913df3d5b4edd3967
React-RCTSettings: be798c8b33392a90d9d551644610ffa349a89255
React-RCTTest: 9ceb703e7bf6f42d79dd51c01020bc5783baa371
React-RCTText: 91a0d0ae5434aa28fe0c89c03eb9d660ff53bd9b
React-RCTVibration: 0630aeb11e22f87c180ca9c0c3a0a0aba780cc62
ReactCommon: d22162ab8f1358c53dfcd0f9c4d82d38facdbc48
Yoga: 9db9ff2025ad21d1ac0a8b3c85d5ac4e7c29d525
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: 060903e270072f1e192b064848e6c34528af1c87
PODFILE CHECKSUM: 6c950c0173bc4754b0d9fa5aba9232943ac228b4
COCOAPODS: 1.8.4
+30
View File
@@ -33,6 +33,19 @@
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#endif
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitLayoutPlugin/SKDescriptorMapper.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#endif
#endif
#import <ReactCommon/RCTTurboModuleManager.h>
#import "RNTesterTurboModuleProvider.h"
@@ -83,6 +96,7 @@
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[self initializeFlipper:application];
return YES;
}
@@ -94,6 +108,22 @@
fallbackResource:nil];
}
- (void)initializeFlipper:(UIApplication *)application
{
#if DEBUG
#ifdef FB_SONARKIT_ENABLED
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application
withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
#endif
#endif
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
+55 -16
View File
@@ -13,11 +13,11 @@
27F441EC1BEBE5030039B79C /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; };
2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */; };
3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */; };
42C7FD8921D436BBA216216D /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EA4C77A9826FF02A56911142 /* libPods-RNTester.a */; };
442B673CCEF28320AE16877B /* libPods-RNTester.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3C8BDC1E54DFC8EB0F67828 /* libPods-RNTester.a */; };
5C60EB1C226440DB0018C04F /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C60EB1B226440DB0018C04F /* AppDelegate.mm */; };
5CB07C9B226467E60039471C /* RNTesterTurboModuleProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */; };
69B65AC442B001534251D909 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5BBFF3E3792E27C4FBA2CB43 /* libPods-RNTesterIntegrationTests.a */; };
C23B0809CAE8A115772B092E /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42A6C306038665FDDA3E54E2 /* libPods-RNTesterUnitTests.a */; };
AB71F075B51B1FA0C65DCF39 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2723489EF058D50FF7217FD9 /* libPods-RNTesterUnitTests.a */; };
CBC719CA19D2FD9247BD28F1 /* libPods-RNTesterIntegrationTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67373A0E14C242E758EE729F /* libPods-RNTesterIntegrationTests.a */; };
E7C1241A22BEC44B00DA25C0 /* RNTesterIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */; };
E7DB20D122B2BAA6005AC45F /* RCTBundleURLProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7DB20A922B2BAA3005AC45F /* RCTBundleURLProviderTests.m */; };
E7DB20D222B2BAA6005AC45F /* RCTModuleInitNotificationRaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7DB20AA22B2BAA3005AC45F /* RCTModuleInitNotificationRaceTests.m */; };
@@ -74,6 +74,7 @@
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RNTester/main.m; sourceTree = "<group>"; };
2723489EF058D50FF7217FD9 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
272E6B3B1BEA849E001FCF37 /* UpdatePropertiesExampleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UpdatePropertiesExampleView.h; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.h; sourceTree = "<group>"; };
272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UpdatePropertiesExampleView.m; path = RNTester/NativeExampleViews/UpdatePropertiesExampleView.m; sourceTree = "<group>"; };
27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlexibleSizeExampleView.m; path = RNTester/NativeExampleViews/FlexibleSizeExampleView.m; sourceTree = "<group>"; };
@@ -81,15 +82,15 @@
2DDEF00F1F84BF7B00DBDF73 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RNTester/Images.xcassets; sourceTree = "<group>"; };
34028D6B10F47E490042EB27 /* Pods-RNTesterUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.debug.xcconfig"; sourceTree = "<group>"; };
3D2AFAF41D646CF80089D1A3 /* legacy_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "legacy_image@2x.png"; path = "RNTester/legacy_image@2x.png"; sourceTree = "<group>"; };
42A6C306038665FDDA3E54E2 /* libPods-RNTesterUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
5BBFF3E3792E27C4FBA2CB43 /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
5BEC8567F3741044B6A5EFC5 /* Pods-RNTester.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNTester/Pods-RNTester.release.xcconfig"; sourceTree = "<group>"; };
5C60EB1B226440DB0018C04F /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = RNTester/AppDelegate.mm; sourceTree = "<group>"; };
5CB07C99226467E60039471C /* RNTesterTurboModuleProvider.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RNTesterTurboModuleProvider.mm; path = RNTester/RNTesterTurboModuleProvider.mm; sourceTree = "<group>"; };
5CB07C9A226467E60039471C /* RNTesterTurboModuleProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNTesterTurboModuleProvider.h; path = RNTester/RNTesterTurboModuleProvider.h; sourceTree = "<group>"; };
67373A0E14C242E758EE729F /* libPods-RNTesterIntegrationTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTesterIntegrationTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
7D51F73F0DA20287418D98BD /* Pods-RNTesterIntegrationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.release.xcconfig"; sourceTree = "<group>"; };
972A459EE6CF8CC63531A088 /* Pods-RNTesterIntegrationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterIntegrationTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterIntegrationTests/Pods-RNTesterIntegrationTests.debug.xcconfig"; sourceTree = "<group>"; };
98233960D1D6A1977D1C7EAF /* Pods-RNTester.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTester.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RNTester/Pods-RNTester.debug.xcconfig"; sourceTree = "<group>"; };
D3C8BDC1E54DFC8EB0F67828 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E771AEEA22B44E3100EA1189 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RNTester/Info.plist; sourceTree = "<group>"; };
E7C1241922BEC44B00DA25C0 /* RNTesterIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterIntegrationTests.m; sourceTree = "<group>"; };
E7DB209F22B2BA84005AC45F /* RNTesterUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNTesterUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -163,7 +164,6 @@
E7DB216122B2F3EC005AC45F /* RCTRootViewIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootViewIntegrationTests.m; sourceTree = "<group>"; };
E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
E9618482EC8608D4872A6E28 /* Pods-RNTesterUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNTesterUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RNTesterUnitTests/Pods-RNTesterUnitTests.release.xcconfig"; sourceTree = "<group>"; };
EA4C77A9826FF02A56911142 /* libPods-RNTester.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNTester.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -171,7 +171,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
42C7FD8921D436BBA216216D /* libPods-RNTester.a in Frameworks */,
442B673CCEF28320AE16877B /* libPods-RNTester.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -181,7 +181,7 @@
files = (
E7DB213122B2C649005AC45F /* JavaScriptCore.framework in Frameworks */,
E7DB213222B2C67D005AC45F /* libOCMock.a in Frameworks */,
C23B0809CAE8A115772B092E /* libPods-RNTesterUnitTests.a in Frameworks */,
AB71F075B51B1FA0C65DCF39 /* libPods-RNTesterUnitTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -191,7 +191,7 @@
files = (
E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */,
E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */,
69B65AC442B001534251D909 /* libPods-RNTesterIntegrationTests.a in Frameworks */,
CBC719CA19D2FD9247BD28F1 /* libPods-RNTesterIntegrationTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -261,9 +261,9 @@
E7DB211822B2BD53005AC45F /* libReact-RCTText.a */,
E7DB211A22B2BD53005AC45F /* libReact-RCTVibration.a */,
E7DB212222B2BD53005AC45F /* libyoga.a */,
EA4C77A9826FF02A56911142 /* libPods-RNTester.a */,
5BBFF3E3792E27C4FBA2CB43 /* libPods-RNTesterIntegrationTests.a */,
42A6C306038665FDDA3E54E2 /* libPods-RNTesterUnitTests.a */,
D3C8BDC1E54DFC8EB0F67828 /* libPods-RNTester.a */,
67373A0E14C242E758EE729F /* libPods-RNTesterIntegrationTests.a */,
2723489EF058D50FF7217FD9 /* libPods-RNTesterUnitTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -725,8 +725,20 @@
);
INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_CFLAGS = "$(inherited)";
LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
);
"LIBRARY_SEARCH_PATHS[arch=*]" = "$(inherited)";
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -779,8 +791,19 @@
);
INFOPLIST_FILE = "$(SRCROOT)/RNTester/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_CFLAGS = "$(inherited)";
LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift,
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
);
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -974,6 +997,10 @@
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.RNTesterUnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
@@ -1005,6 +1032,10 @@
"$(PROJECT_DIR)/RNTesterUnitTests",
);
MTL_FAST_MATH = YES;
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.RNTesterUnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
@@ -1037,6 +1068,10 @@
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.RNTesterIntegrationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
@@ -1066,6 +1101,10 @@
"@loader_path/Frameworks",
);
MTL_FAST_MATH = YES;
OTHER_CFLAGS = (
"$(inherited)",
"-DFB_SONARKIT_ENABLED=1",
);
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.RNTesterIntegrationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
+12 -4
View File
@@ -166,14 +166,22 @@ dependencies {
// Build React Native from source
implementation project(':ReactAndroid')
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
def hermesPath = '$projectDir/../../../../node_modules/hermes-engine/android/'
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
debugImplementation("com.facebook.flipper:flipper:0.23.4") {
exclude group:'com.facebook.yoga'
exclude group:'com.facebook.flipper', module: 'fbjni'
exclude group:'com.facebook.litho', module: 'litho-annotations'
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (useIntlJsc) {
+3
View File
@@ -7,3 +7,6 @@ MYAPP_RELEASE_KEY_PASSWORD=android
android.useAndroidX=true
android.enableJetifier=true
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.33.1
@@ -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.
*/
package com.facebook.react.uiapp;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new ReactFlipperPlugin());
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}
@@ -11,6 +11,7 @@ import android.app.Application;
import android.content.Context;
import com.facebook.react.BuildConfig;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
@@ -48,7 +49,8 @@ public class RNTesterApplication extends Application implements ReactApplication
public void onCreate() {
ReactFontManager.getInstance().addCustomFont(this, "Rubik", R.font.rubik);
super.onCreate();
initializeFlipper(this);
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
@Override
@@ -56,15 +58,25 @@ public class RNTesterApplication extends Application implements ReactApplication
return mReactNativeHost;
}
private static void initializeFlipper(Context context) {
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
Class<?> aClass = Class.forName("com.facebook.react.uiapp.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
@@ -16,7 +16,7 @@ const React = require('react');
const TextInlineView = require('../../components/TextInlineView');
const TextLegend = require('../../components/TextLegend');
const {StyleSheet, Text, View} = require('react-native');
const {LayoutAnimation, StyleSheet, Text, View} = require('react-native');
class Entity extends React.Component<{|children: React.Node|}> {
render() {
@@ -70,10 +70,137 @@ class AttributeToggler extends React.Component<{...}, $FlowFixMeState> {
}
}
type AdjustingFontSizeProps = $ReadOnly<{||}>;
type AdjustingFontSizeState = {|
dynamicText: string,
shouldRender: boolean,
|};
class AdjustingFontSize extends React.Component<
AdjustingFontSizeProps,
AdjustingFontSizeState,
> {
state = {
dynamicText: '',
shouldRender: true,
};
reset = () => {
LayoutAnimation.easeInEaseOut();
this.setState({
shouldRender: false,
});
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
dynamicText: '',
shouldRender: true,
});
}, 300);
};
addText = () => {
this.setState({
dynamicText:
this.state.dynamicText +
(Math.floor((Math.random() * 10) % 2) ? ' foo' : ' bar'),
});
};
removeText = () => {
this.setState({
dynamicText: this.state.dynamicText.slice(
0,
this.state.dynamicText.length - 4,
),
});
};
render() {
if (!this.state.shouldRender) {
return <View />;
}
return (
<View>
<Text
ellipsizeMode="tail"
numberOfLines={1}
style={{fontSize: 36, marginVertical: 6}}>
Truncated text is baaaaad.
</Text>
<Text
numberOfLines={1}
adjustsFontSizeToFit={true}
style={{fontSize: 40, marginVertical: 6}}>
Shrinking to fit available space is much better!
</Text>
<Text
adjustsFontSizeToFit={true}
numberOfLines={1}
style={{fontSize: 30, marginVertical: 6}}>
{'Add text to me to watch me shrink!' + ' ' + this.state.dynamicText}
</Text>
<Text
adjustsFontSizeToFit={true}
numberOfLines={4}
style={{fontSize: 20, marginVertical: 6}}>
{'Multiline text component shrinking is supported, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' +
' ' +
this.state.dynamicText}
</Text>
<Text
adjustsFontSizeToFit={true}
style={{fontSize: 20, marginVertical: 6, maxHeight: 50}}>
{'Text limited by height, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' +
' ' +
this.state.dynamicText}
</Text>
<Text
adjustsFontSizeToFit={true}
numberOfLines={1}
style={{marginVertical: 6}}>
<Text style={{fontSize: 14}}>
{'Differently sized nested elements will shrink together. '}
</Text>
<Text style={{fontSize: 20}}>
{'LARGE TEXT! ' + this.state.dynamicText}
</Text>
</Text>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-around',
marginTop: 5,
marginVertical: 6,
}}>
<Text style={{backgroundColor: '#ffaaaa'}} onPress={this.reset}>
Reset
</Text>
<Text style={{backgroundColor: '#aaaaff'}} onPress={this.removeText}>
Remove Text
</Text>
<Text style={{backgroundColor: '#aaffaa'}} onPress={this.addText}>
Add Text
</Text>
</View>
</View>
);
}
}
class TextExample extends React.Component<{...}> {
render(): React.Node {
return (
<RNTesterPage title="<Text>">
<RNTesterBlock title="Dynamic Font Size Adjustment">
<AdjustingFontSize />
</RNTesterBlock>
<RNTesterBlock title="Wrap">
<Text>
The text should wrap if it goes on multiple lines. See, this is
@@ -222,6 +222,14 @@ class AdjustingFontSize extends React.Component<
this.state.dynamicText}
</Text>
<Text
adjustsFontSizeToFit={true}
style={{fontSize: 20, marginVertical: 6, maxHeight: 50}}>
{'Text limited by height, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' +
' ' +
this.state.dynamicText}
</Text>
<Text
adjustsFontSizeToFit={true}
numberOfLines={1}
+1 -1
View File
@@ -305,7 +305,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
*/
- (void)reloadWithReason:(NSString *)reason
{
#if RCT_ENABLE_INSPECTOR && !TARGET_OS_UIKITFORMAC
#if RCT_ENABLE_INSPECTOR
// Disable debugger to resume the JsVM & avoid thread locks while reloading
[RCTInspectorDevServerHelper disableDebugger];
#endif
@@ -5,12 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#import <React/RCTDefines.h>
#include <fb/visibility.h>
namespace facebook {
namespace jni {
void FBEXPORT installTerminateHandler();
}};
RCT_EXTERN NSString *const RCTUserInterfaceStyleDidChangeNotification;
RCT_EXTERN NSString *const RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey;
+11
View File
@@ -0,0 +1,11 @@
/*
* 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.
*/
#import "RCTConstants.h"
NSString *const RCTUserInterfaceStyleDidChangeNotification = @"RCTUserInterfaceStyleDidChangeNotification";
NSString *const RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey = @"traitCollection";
+1 -1
View File
@@ -63,7 +63,7 @@
#endif
#ifndef ENABLE_PACKAGER_CONNECTION
#if RCT_DEV && (__has_include("RCTPackagerConnection.h") || __has_include(<React/RCTPackagerConnection.h>)) && !TARGET_OS_UIKITFORMAC
#if RCT_DEV && (__has_include("RCTPackagerConnection.h") || __has_include(<React/RCTPackagerConnection.h>))
#define ENABLE_PACKAGER_CONNECTION 1
#else
#define ENABLE_PACKAGER_CONNECTION 0
+6 -11
View File
@@ -14,6 +14,7 @@
#import "RCTAssert.h"
#import "RCTBridge.h"
#import "RCTBridge+Private.h"
#import "RCTConstants.h"
#import "RCTEventDispatcher.h"
#import "RCTKeyCommands.h"
#import "RCTLog.h"
@@ -33,7 +34,6 @@
#endif
NSString *const RCTContentDidAppearNotification = @"RCTContentDidAppearNotification";
static NSString *const RCTUserInterfaceStyleDidChangeNotification = @"RCTUserInterfaceStyleDidChangeNotification";
@interface RCTUIManager (RCTRootView)
@@ -367,21 +367,16 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
[self showLoadingView];
}
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
[super traitCollectionDidChange:previousTraitCollection];
if (@available(iOS 13.0, *)) {
if ([previousTraitCollection hasDifferentColorAppearanceComparedToTraitCollection:self.traitCollection]) {
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUserInterfaceStyleDidChangeNotification
object:self
userInfo:@{@"traitCollection": self.traitCollection}];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUserInterfaceStyleDidChangeNotification
object:self
userInfo:@{
RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey: self.traitCollection,
}];
}
#endif
- (void)dealloc
{
+5 -5
View File
@@ -21,11 +21,11 @@ NSDictionary* RCTGetReactNativeVersion(void)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^(void){
__rnVersion = @{
RCTVersionMajor: @(0),
RCTVersionMinor: @(0),
RCTVersionPatch: @(0),
RCTVersionPrerelease: [NSNull null],
};
RCTVersionMajor: @(0),
RCTVersionMinor: @(62),
RCTVersionPatch: @(2),
RCTVersionPrerelease: [NSNull null],
};
});
return __rnVersion;
}
@@ -7,14 +7,13 @@
#import "RCTSurfaceHostingView.h"
#import "RCTConstants.h"
#import "RCTDefines.h"
#import "RCTSurface.h"
#import "RCTSurfaceDelegate.h"
#import "RCTSurfaceView.h"
#import "RCTUtils.h"
static NSString *const RCTUserInterfaceStyleDidChangeNotification = @"RCTUserInterfaceStyleDidChangeNotification";
@interface RCTSurfaceHostingView ()
@property (nonatomic, assign) BOOL isActivityIndicatorViewVisible;
@@ -208,21 +207,15 @@ RCT_NOT_IMPLEMENTED(- (nullable instancetype)initWithCoder:(NSCoder *)coder)
#pragma mark - UITraitCollection updates
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
[super traitCollectionDidChange:previousTraitCollection];
if (@available(iOS 13.0, *)) {
if ([previousTraitCollection hasDifferentColorAppearanceComparedToTraitCollection:self.traitCollection]) {
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUserInterfaceStyleDidChangeNotification
object:self
userInfo:@{@"traitCollection": self.traitCollection}];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUserInterfaceStyleDidChangeNotification
object:self
userInfo:@{
RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey: self.traitCollection,
}];
}
#endif
#pragma mark - Private stuff
+3
View File
@@ -96,6 +96,9 @@ rn_apple_library(
) + react_module_plugin_providers(
name = "RedBox",
native_class_func = "RCTRedBoxCls",
) + react_module_plugin_providers(
name = "LogBox",
native_class_func = "RCTLogBoxCls",
) + react_module_plugin_providers(
name = "TVNavigationEventEmitter",
native_class_func = "RCTTVNavigationEventEmitterCls",
+1
View File
@@ -48,6 +48,7 @@ Class RCTPerfMonitorCls(void) __attribute__((used));
Class RCTDevMenuCls(void) __attribute__((used));
Class RCTDevSettingsCls(void) __attribute__((used));
Class RCTRedBoxCls(void) __attribute__((used));
Class RCTLogBoxCls(void) __attribute__((used));
Class RCTTVNavigationEventEmitterCls(void) __attribute__((used));
Class RCTWebSocketExecutorCls(void) __attribute__((used));
Class RCTWebSocketModuleCls(void) __attribute__((used));
+1
View File
@@ -37,6 +37,7 @@ Class RCTCoreModulesClassProvider(const char *name) {
{"DevMenu", RCTDevMenuCls},
{"DevSettings", RCTDevSettingsCls},
{"RedBox", RCTRedBoxCls},
{"LogBox", RCTLogBoxCls},
{"TVNavigationEventEmitter", RCTTVNavigationEventEmitterCls},
{"WebSocketExecutor", RCTWebSocketExecutorCls},
{"WebSocketModule", RCTWebSocketModuleCls},
-2
View File
@@ -12,7 +12,5 @@
RCT_EXTERN void RCTEnableAppearancePreference(BOOL enabled);
NSString *const RCTUserInterfaceStyleDidChangeNotification = @"RCTUserInterfaceStyleDidChangeNotification";
@interface RCTAppearance : RCTEventEmitter <RCTBridgeModule>
@end
+2 -1
View File
@@ -8,6 +8,7 @@
#import "RCTAppearance.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTConstants.h>
#import <React/RCTEventEmitter.h>
#import "CoreModulesPlugins.h"
@@ -86,7 +87,7 @@ RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getColorScheme)
NSDictionary *userInfo = [notification userInfo];
UITraitCollection *traitCollection = nil;
if (userInfo) {
traitCollection = userInfo[@"traitCollection"];
traitCollection = userInfo[RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey];
}
NSString *newColorScheme = RCTColorSchemePreference(traitCollection);
if (![_currentColorScheme isEqualToString:newColorScheme]) {
+1 -1
View File
@@ -262,7 +262,7 @@ RCT_EXPORT_MODULE()
if (devSettings.isNuclideDebuggingAvailable && !devSettings.isDebuggingRemotely) {
[items addObject:[RCTDevMenuItem buttonItemWithTitle:@"Debug with Nuclide"
handler:^{
#if RCT_ENABLE_INSPECTOR && !TARGET_OS_UIKITFORMAC
#if RCT_ENABLE_INSPECTOR
[RCTInspectorDevServerHelper
attachDebugger:@"ReactNative"
withBundleURL:bridge.bundleURL
+1 -1
View File
@@ -176,7 +176,7 @@ RCT_EXPORT_MODULE()
forMethod:@"reload"];
#endif
#if RCT_ENABLE_INSPECTOR && !TARGET_OS_UIKITFORMAC
#if RCT_ENABLE_INSPECTOR
// we need this dispatch back to the main thread because even though this
// is executed on the main thread, at this point the bridge is not yet
// finished with its initialisation. But it does finish by the time it
+10 -3
View File
@@ -10,6 +10,7 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTAccessibilityManager.h>
#import <React/RCTAssert.h>
#import <React/RCTConstants.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUIUtils.h>
#import <React/RCTUtils.h>
@@ -61,9 +62,15 @@ RCT_EXPORT_MODULE()
_currentInterfaceDimensions = RCTExportedDimensions(_bridge);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interfaceFrameDidChange)
name:UIApplicationDidBecomeActiveNotification
object:nil];
selector:@selector(interfaceFrameDidChange)
name:UIApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(interfaceFrameDidChange)
name:RCTUserInterfaceStyleDidChangeNotification
object:nil];
#endif
}
+21
View File
@@ -0,0 +1,21 @@
/*
* 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.
*/
#import <UIKit/UIKit.h>
#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTErrorCustomizer.h>
@class RCTJSStackFrame;
@interface RCTLogBox : NSObject <RCTBridgeModule>
- (void)show;
- (void)hide;
@end
+156
View File
@@ -0,0 +1,156 @@
/*
* 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.
*/
#import "RCTLogBox.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTRootView.h>
#import <React/RCTConvert.h>
#import <React/RCTDefines.h>
#import <React/RCTErrorInfo.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTJSStackFrame.h>
#import <React/RCTRedBoxSetEnabled.h>
#import <React/RCTReloadCommand.h>
#import <React/RCTRedBoxSetEnabled.h>
#import <React/RCTSurface.h>
#import <React/RCTUtils.h>
#import <objc/runtime.h>
#import "CoreModulesPlugins.h"
#if RCT_DEV_MENU
@class RCTLogBoxView;
@interface RCTLogBoxView : UIWindow
@end
@implementation RCTLogBoxView
{
RCTSurface *_surface;
}
- (instancetype)initWithFrame:(CGRect)frame bridge:(RCTBridge *)bridge
{
if ((self = [super initWithFrame:frame])) {
self.windowLevel = UIWindowLevelStatusBar - 1;
self.backgroundColor = [UIColor clearColor];
_surface = [[RCTSurface alloc] initWithBridge:bridge moduleName:@"LogBox" initialProperties:@{}];
[_surface start];
[_surface setSize:frame.size];
if (![_surface synchronouslyWaitForStage:RCTSurfaceStageSurfaceDidInitialMounting timeout:1]) {
RCTLogInfo(@"Failed to mount LogBox within 1s");
}
UIViewController *_rootViewController = [UIViewController new];
_rootViewController.view = (UIView *)_surface.view;
_rootViewController.view.backgroundColor = [UIColor clearColor];
_rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;
self.rootViewController = _rootViewController;
}
return self;
}
- (void)dealloc
{
[RCTSharedApplication().delegate.window makeKeyWindow];
}
- (void)show
{
[self becomeFirstResponder];
[self makeKeyAndVisible];
}
@end
@interface RCTLogBox () <NativeLogBoxSpec>
@end
@implementation RCTLogBox
{
RCTLogBoxView *_view;
}
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE()
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
RCT_EXPORT_METHOD(show)
{
if (RCTRedBoxGetEnabled()) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!self->_view) {
self->_view = [[RCTLogBoxView alloc] initWithFrame:[UIScreen mainScreen].bounds bridge: self->_bridge];
}
[self->_view show];
});
}
}
RCT_EXPORT_METHOD(hide)
{
if (RCTRedBoxGetEnabled()) {
dispatch_async(dispatch_get_main_queue(), ^{
self->_view = nil;
});
}
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
if (RCTRedBoxGetEnabled()) {
return std::make_shared<facebook::react::NativeLogBoxSpecJSI>(self, jsInvoker);
}
return nullptr;
}
@end
#else // Disabled
@interface RCTLogBox() <NativeLogBoxSpec>
@end
@implementation RCTLogBox
+ (NSString *)moduleName
{
return nil;
}
- (void)show {
// noop
}
- (void)hide {
// noop
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return std::make_shared<facebook::react::NativeLogBoxSpecJSI>(self, jsInvoker);
}
@end
#endif
Class RCTLogBoxCls(void) {
return RCTLogBox.class;
}
+16 -1
View File
@@ -44,6 +44,14 @@ static BOOL RCTJSCSetOption(const char *option)
static RCTJSCSetOptionType setOption;
static dispatch_once_t onceToken;
// As of iOS 13.4, it is no longer possible to change the JavaScriptCore
// options at runtime. The options are protected and will cause an
// exception when you try to change them after the VM has been initialized.
// https://github.com/facebook/react-native/issues/28414
if (@available(iOS 13.4, *)) {
return NO;
}
dispatch_once(&onceToken, ^{
/**
* JSC private C++ static method to toggle options at runtime
@@ -197,12 +205,19 @@ RCT_EXPORT_MODULE()
{
if (!_container) {
_container = [[UIView alloc] initWithFrame:CGRectMake(10, 25, 180, RCTPerfMonitorBarHeight)];
_container.backgroundColor = UIColor.whiteColor;
_container.layer.borderWidth = 2;
_container.layer.borderColor = [UIColor lightGrayColor].CGColor;
[_container addGestureRecognizer:self.gestureRecognizer];
[_container addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(tap)]];
_container.backgroundColor = [UIColor whiteColor];
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && defined(__IPHONE_13_0) && \
__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
if (@available(iOS 13.0, *)) {
_container.backgroundColor = [UIColor systemBackgroundColor];
}
#endif
}
return _container;
@@ -11,7 +11,7 @@
#import <React/RCTDefines.h>
#import <React/RCTInspectorPackagerConnection.h>
#if RCT_DEV && !TARGET_OS_UIKITFORMAC
#if RCT_DEV
@interface RCTInspectorDevServerHelper : NSObject
@@ -7,7 +7,7 @@
#import <React/RCTInspectorDevServerHelper.h>
#if RCT_DEV && !TARGET_OS_UIKITFORMAC
#if RCT_DEV
#import <React/RCTLog.h>
#import <UIKit/UIKit.h>

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