Compare commits

...
157 Commits
Author SHA1 Message Date
Eric Vicenti ce0ad9f712 0.5.0 2015-06-05 15:35:40 -07:00
Christopher Chedeau 4673dca0b0 Merge pull request #1375 from vjeux/Updates_Fri_22_May
Updates fri 22 may
2015-05-22 10:09:08 -07:00
Christopher Chedeau 800c62bb8b Updates from Fri 22 May 2015-05-22 09:59:17 -07:00
Amjad Masad eec67aff4d [react-packager] Update worker-farm to get custom error props
Summary:
@public
In my previous worker-farm update, the implementation wasn't complete.
Errors only passed the "data" property. This fixes the problem by passing all custom
props.

Test Plan:
1. `./Libraries/FBReactKit/runJestTests.sh`
2. `./Libraries/FBReactKit/runJestTests.sh PackagerIntegration`
2015-05-22 08:51:11 -08:00
Nick Lockwood fe4b4c2d83 Optimised blending for translucent images with opaque background color + fixed cropping for images in cover/contain mode.
Summary:
@public

Our background color propagation mechanism is designed to make rendering of translucent content more efficient by pre-blending against an opaque background. Currently this only works for text however, because images are not composited into their background even if the background color is opaque.

This diff precomposites network images with their background color when the background is opaque, allowing them to take advantage of this performance optimization.

I've also added some logic to correctly crop the downloaded image when the resizeMode is "cover" or "contain" - previously it was only correct for "stretch".

Before:{F22437859}
After:{F22437862}

Test Plan: Run the UIExplorer "<ListView> - Paging" example with "color blended layers" enabled and observe that the images appear in green now, instead of red as they did before.
2015-05-22 07:19:06 -08:00
James Ide 7f51f9c8a9 [Navigator] Support the ref prop on scene roots
Summary:
Navigator overrides the `ref` prop of scene components so that it can call `onItemRef` and do internal bookkeeping. With callback refs, we can additionally call the original value of the `ref` prop as long as it's a function (that is, string refs are not supported). Note that the `ref` prop is moved to `reactElement.ref` out of `reactElement.props.ref`, which is why this diff accesses `child.ref`.

This diff adds support for callback refs and warns helpfully if a string ref was provided. It should be completely backwards compatible since scenes couldn't have been relying on the `ref` prop before.

cc @ericvicenti

Closes https://github.com/facebook/react-native/pull/1361
Github Author: James Ide <ide@jameside.com>

@public

Test Plan:
 Write a renderScene implementation that puts a callback ref on the root component:
```js
renderScene() {
  return <View ref={component => console.log('yes! this is called')} />;
}
```
2015-05-21 11:01:09 -08:00
Andy Street c6670658f4 [react_native] JS files from D2087892: [react_native] Implement setInterval in JS 2015-05-21 04:24:04 -08:00
Alexsander Akers d20a6e9d2d Merge pull request #1353 from a2/Update_Wed_20_May
Updates from Wed 20 May
2015-05-21 10:34:10 +01:00
Hedger Wang b46c94aaf9 Unbreak RN JS server for Android. 2015-05-20 18:38:34 -08:00
Tadeu Zagallo 08844e3ddc [ReactNative] Add fps monitor
Summary:
@public

Add basic JS and UI thread FPS monitor

Test Plan: Launch the UIExplorer, open the Dev Menu with cmd+D, and select `Show FPS Monitor`
2015-05-20 18:26:36 -08:00
Joe Savona 1d5d01c3c9 InteractionManager: DEV warning for possibly unclosed handles 2015-05-20 16:54:03 -08:00
Amjad Masad 9a76f224af [react-packager] Add first class support to popular image formats
Summary:
@public
1. Default to first class support of popular image formats
2. Add tests to make sure we support other than png

Test Plan:
1. ./runJestTests.sh
2. Add test.png and test.jpg images in the Playground app dir
3. require both images and render then in the playground app
4. they render
2015-05-20 15:28:29 -08:00
Amjad Masad 8bb65215b1 [react-packager] Implement getJSModulePaths API 2015-05-20 13:38:46 -08:00
Nick Lockwood 0d227c0eb2 Eliminated redundant border drawing 2015-05-20 12:19:24 -08:00
Alex Kotliarskyi 1b2975803b [ReactNative] Cleanup _build_bundle script 2015-05-20 10:31:28 -08:00
Alexsander Akers 4cd5cad599 Updates from Wed 20 May 2015-05-20 18:04:26 +01:00
Georgiy Kassabli d211359aeb Added ability to set custom accessibility tap handler to React Native 2015-05-20 08:32:15 -08:00
Spencer Ahrens 32666f0aa2 [ReactNative] Add AppEventsTest 2015-05-20 00:31:50 -08:00
Eric Vicenti c1609bcab8 [ReactNative] Navigator fix for sceneStyle
Summary:
Fixes https://github.com/facebook/react-native/issues/1332

When the absolute left position is not set to zero on a provided sceneStyle, scene enabling is broken and no scene will be visible when it is pushed. This was broken recently when the scene disabling was modified to push the scenes offscreen.

Closes https://github.com/facebook/react-native/pull/1347
Github Author: Eric Vicenti <evv@fb.com>

@public

Test Plan:  Tested when pushing a scene Navigator in the UIExplorer example while sceneStyle is set on the Navigator
2015-05-19 18:54:15 -08:00
Eric Vicenti 97137e8bcc [ReactNative] Navigator clean scenes popped with gesture
Summary:
Fixes https://github.com/facebook/react-native/issues/1252

Scenes dismissed/popped via a gesture were not being removed. This is probably a regression from an earlier refactor.

Test plan: log statements after scene focusing now reports that `navigator.getCurrentRoutes().length` lowers after gesture. Tested on UIExplorer Navigator example
Closes https://github.com/facebook/react-native/pull/1346
Github Author: Eric Vicenti <evv@fb.com>

@public

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-19 18:45:42 -08:00
Spencer Ahrens 11b515b1b0 [ReactNative] clean lint in all of Libraries/ 2015-05-19 13:47:04 -08:00
Alex Akers a4f92ba3db [React Native] Add magic tap accessibility gesture 2015-05-19 06:28:01 -08:00
Spencer Ahrens 1c70f33511 [ReactNative] clean lint for Libraries/Components 2015-05-18 15:54:07 -08:00
Premasagar Rose 33ac55b2bd Fix typo in image documentation
Summary:
Closes https://github.com/facebook/react-native/pull/970
Github Author: Premasagar Rose <p@dharmafly.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-18 13:01:20 -08:00
Luke de27f1db54 fix exception when ES6 class with no propTypes defined before calling requireNativeComponent
Summary:
Closes https://github.com/facebook/react-native/pull/1260
Github Author: Luke <kejinlu@gmail.com>

Test Plan: Created `class Foo extends React.Component` and made sure error messages were good.
2015-05-18 11:47:42 -08:00
Spencer Ahrens a1193b7a93 Update CONTRIBUTING.md 2015-05-18 12:25:09 -07:00
Alex Kotliarskyi 214ae2062c Fix react-native-cli code formatting 2015-05-18 10:25:17 -07:00
Alexander Kotliarskyi f2b76566f3 Merge pull request #1293 from skv-headless/confirm-init-overwrite
Ask confirmation on init command
2015-05-18 10:24:19 -07:00
Alexsander Akers f2ffaed4ca Merge pull request #1327 from a2/Update_Mon_18_May
Updates from Mon 18 May
2015-05-18 16:47:09 +01:00
Andrei Coman 03905e69f4 [react_native] JS files from D2079609: [react_native] Use email type for login field 2015-05-18 07:36:39 -08:00
Georgiy Kassabli 6ef7eaf663 Added accessibility traits support to View class 2015-05-18 07:30:29 -08:00
Alexsander Akers 7219fcefc6 Updates from Mon 18 May 2015-05-18 16:29:47 +01:00
Tadeu Zagallo eedb880f6e [ReactNative] Bump package.json version to 0.4.4 2015-05-17 19:05:14 -08:00
Tadeu Zagallo a4e89d71a3 [ReactNative] Fix RCTBatchedBridge main thread invalidation
Summary:
D2052669 introduced a block for objects that had to be invalidated on the main
thread, but after the JS thread objects, but the block was being dispatched on
the JS thread.

@public

Test Plan:
I added `RCTAssertMainThread()` to the `mainThreadInvalidate` block, it was
crashing on reload, but now it should work as expected.
2015-05-17 18:27:20 -08:00
Brent Vatne 424d1318c8 [Docs] Linking Libraries fix site->side, prefer only to just 2015-05-17 18:41:40 -07:00
Amjad Masad 407d8d4cf6 [react-native] Update jest to get perf bugfix 2015-05-17 02:51:35 -08:00
Dmitry Soshnikov 545edba913 [jest] Update to v0.4.4 2015-05-17 00:20:42 -08:00
skv 5a83ffab94 ask confirmation on init command
if directory already exist
2015-05-16 22:23:19 +03:00
Christopher Chedeau d63eac4014 Merge pull request #1312 from vjeux/Updates_Sat_16_May
Updates sat 16 may
2015-05-16 10:14:17 -07:00
Christopher Chedeau 367638053a Updates from Sat 16 May 2015-05-16 10:07:17 -07:00
James Ide 08d30e751b [ActivityIndicator] Add the onLayout prop to the outer container view
Summary:
ActivityIndicator was forwarding all of its props except `style` to the inner native view. This meant that onLayout would report a zero-sized frame that was relative to the wrapper view instead of the parent of the ActivityIndicator.

This diff adds `onLayout` to the wrapper view instead of the native view.

In general, all components that forward props need to be audited in this manner.

Closes https://github.com/facebook/react-native/pull/1292
Github Author: James Ide <ide@jameside.com>

Test Plan: `<ActivityIndicator onLayout={...} />` reports the size of the spinner plus a position relative to its parent view.
2015-05-15 18:08:32 -08:00
Brent Vatne c668fd5be0 [ReactNative] Add "RCTNativeAppEventEmitter"
Summary:
As mentioned in #906, [in the docs it mentions sending native app events](http://facebook.github.io/react-native/docs/nativemodulesios.html#sending-events-to-javascript) eg: calendar event reminder received, through the `RCTNativeAppEventEmitter`, but the JS module for that is missing. This adds it - it's nothing more than an instance of `EventEmitter`, just like [RCTDeviceEventEmitter](https://github.com/facebook/react-native/blob/master/Libraries/Device/RCTDeviceEventEmitter.js).
Closes https://github.com/facebook/react-native/pull/918
Github Author: Brent Vatne <brent.vatne@madriska.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-15 16:57:18 -08:00
James Ide 5f841a950e [Setup] Remove AdSupport from the list of libraries linked by default
Summary:
Many apps don't need AdSupport, especially not when people are making a sample app to learn React. Apps that do want it can link it in like any other library.

Fixes #1303, see the discussion there.
Closes https://github.com/facebook/react-native/pull/1305
Github Author: James Ide <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-15 15:53:23 -08:00
Amjad Masad 64c0bb0bd4 [react-native] Fix source map issue with virtual modules 2015-05-15 15:49:11 -08:00
Christopher Chedeau 723e988416 [ReactNative] Redbox if JSC syntax errors 2015-05-15 15:33:17 -08:00
Christopher Chedeau 7a1c52c8e9 0.4.4 2015-05-15 15:59:55 -07:00
Christopher Chedeau 0fbe091304 Merge pull request #1301 from vjeux/Updates_Fri_15_May
Updates fri 15 may
2015-05-15 15:37:54 -07:00
Christopher Chedeau b5de997166 Updates from Fri 15 May 2015-05-15 15:23:28 -07:00
Amjad Masad d9b7e63e47 [react-native] Use trailing commas transform
Summary:
@public
Apparently trailing commas transform isn't exported by react-tools. We need to pull it out manually. This is not so clean but we're swtching to babel very shortly.

Test Plan:
* npm start
* write `foo(a,b,c,)` in some file
* request that file in the browser and make sure that trailing comma is gone
2015-05-15 14:11:55 -08:00
Zhao Han 40da7bb835 Add more documentation in ListViewDataSource
Summary:
ListViewDataSource's default data extractor can actually expect another data form:

`{ sectionID_1: [ <rowData1>, <rowData2>, ... ], ... }`
Closes https://github.com/facebook/react-native/pull/1285
Github Author: Zhao Han <cx.chenghai+github@gmail.com>

Test Plan: Changed the ListViewExample to make sure all three formats work.
2015-05-15 13:47:43 -08:00
James Ide d72045932e [TextInput] Add onLayout to TextInput, forwarding it to the native views
Summary:
`TextInput` does not automatically forward all props using the spread operator so we need to explicitly forward the `onLayout` prop.

Closes https://github.com/facebook/react-native/pull/1296
Github Author: James Ide <ide@jameside.com>

Test Plan:
 Mount a TextInput component with an `onLayout` prop and see that the callback handler is invoked with the TextInput's frame.
2015-05-15 11:52:23 -08:00
Nick Lockwood d27e6fa7f8 Fixed RCTWebSocket and chrome debugging in OSS 2015-05-15 11:37:07 -08:00
Christopher Chedeau 2d9990ca2a [ReactNative] Better error message when passing an Animated to a View 2015-05-15 11:01:46 -08:00
Spencer Ahrens 4771806c44 [ReactNative] Fix some mount callback issues 2015-05-15 10:59:09 -08:00
Christopher Chedeau e33fef8e42 Merge pull request #405 from JoeStanton/new-library-cmd
[CLI] New Library Generator
2015-05-15 10:58:40 -07:00
Joe Stanton 857c30b502 Stylistic cleanup 2015-05-15 17:08:21 +01:00
Joe Stanton 243ef68199 Update search paths to reflect new project structure 2015-05-15 14:10:06 +01:00
Joe Stanton ea8447e1c5 Upgrade sample to the new macros 2015-05-15 13:59:46 +01:00
Joe Stanton 0312c30a73 Duplicate the name validation for now 2015-05-15 09:21:38 +01:00
Joe Stanton 396439bf86 Added react-native new-library command 2015-05-15 09:17:27 +01:00
James Ide 80814f643f Merge pull request #1289 from umhan35/patch-4
Add SegmentedControlIOS documentation to website
2015-05-14 20:35:16 -07:00
Zhao Han 1c05aff424 Add SegmentedControlIOS documentation to website 2015-05-14 22:22:31 -05:00
James Ide 2497c02e38 [RCTBridge] Have RCTBridge.loading return RCTBatchedBridge.loading
Summary:
The parent RCTBridge no longer tracks the JS loading since that has been handed off to the RCTBatchedBridge. To make the `loading` property accurate again, just expose the batch bridge's loading property from the parent bridge (note: I didn't make it KVO-compliant).

Fixes #1199
Closes https://github.com/facebook/react-native/pull/1200
Github Author: James Ide <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-14 16:00:18 -08:00
Tadeu Zagallo e467fb7202 [ReactNative] Add console.profile hooks to systrace
Summary:
Add console.profile sync hooks compliant with the chrome API
https://developer.chrome.com/devtools/docs/console-api#consoleprofilelabel

@public

Test Plan:
Add a `console.profile()` and a `console.profileEnd()` in the JavaScript,
and record a systrace-like profile via DevMenu
2015-05-14 15:59:20 -08:00
Christopher Chedeau aa439b7e39 Merge pull request #1286 from hansonw/master
Fix jsdocs for multi-line ES6-style methods
2015-05-14 16:51:17 -07:00
Christopher Chedeau 623eb05bf6 0.4.3 2015-05-14 16:44:16 -07:00
Christopher Chedeau d2eaa51509 0.4.2 2015-05-14 16:42:26 -07:00
hansonw 97aad167a6 Fix jsdocs for multi-line ES6-style methods
Summary:
The function definition and body can be in different places for multi-line declarations, so the docblock might not get pulled in. None of the existing docs seem to be affected, but putting up the fix for posterity.

Test Plan:
I modified `AlertIOS.alert` (in Libraries/Utilties/AlertIOS.js) to actually have a docblock, and ran `website/publish.sh` (with the push bit commented out). The added doc doesn't get picked up with the current code, but it does with the fix.
2015-05-14 16:34:55 -07:00
Christopher Chedeau 1f8b97aeff Merge pull request #1283 from vjeux/Updates_Thu_14_May_3
Updates Thu 14 May
2015-05-14 15:39:25 -07:00
Christopher Chedeau da1aa962e2 Updates from Thu 14 May 2015-05-14 15:21:03 -07:00
Tadeu Zagallo 22fb03d7e0 [ReactNative] Fix UIExplorer missing reference to RCTWebSocket 2015-05-14 14:18:13 -08:00
Tadeu Zagallo 9c8e085677 [ReactNative] Fix Movies and SampleApp missing reference to RCTWebSocket 2015-05-14 14:15:23 -08:00
Georgiy Kassabli d2f79d835d Fixing misprint in RCText.m 2015-05-14 13:02:47 -08:00
Nick Lockwood 7c3070628a Fixed infinite #clowntown error loop 2015-05-14 12:19:15 -08:00
Christopher Chedeau b2d1d6f3e9 Merge pull request #440 from JoeStanton/init-to-nodejs
[CLI] Remove dependency on Ruby
2015-05-14 12:21:30 -07:00
Joe Stanton 04832e5aa4 Fixed stylistic issues 2015-05-14 20:19:29 +01:00
Christopher Chedeau 766983f69b [react native] Bump jest-cli version to 0.4.3 in RN packages 2015-05-14 10:32:44 -08:00
Yuta Okazaki 75ed1dd49e Fix typo of function name in ListView documentation
Summary:
When I read documents, I usually 'search within page' to see where they talk about specific things.
So I found this fix to be pretty useful. Hope it'll be merged!
Closes https://github.com/facebook/react-native/pull/1146
Github Author: Yuta Okazaki <s04155yo@gmail.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-14 09:52:19 -08:00
James Ide 4e412381f2 [TextView] Define missing properties and add getters
Summary:
Some of the RCTTextView properties weren't set up correctly which would cause bugs when you'd set a property and then unset it, trying to revert to the default. This requires reading the default value from the dummy view instance, but some of these properties didn't have getters which was causing issues.

Fixes #1174

Closes https://github.com/facebook/react-native/pull/1175
Github Author: James Ide <ide@jameside.com>

Test Plan:  Create a `<TextInput multiline={true}>` component. Give it a style with `color: 'blue'`, and then on the next render pass remove the style. No more red box.
2015-05-14 09:45:12 -08:00
Alex Akers e9db0338d2 [React Native] Enable accessibility on RCTText 2015-05-14 09:41:21 -08:00
Eric Sauter 711dd6602e Fix lint errors and warnings
Summary:
Fix the following problems resulting from running `npm run lint`:

```
Examples/Movies/SearchScreen.js
  118:4  error  'fetch' is not defined  no-undef
  177:4  error  'fetch' is not defined  no-undef

Examples/UIExplorer/MapViewExample.js
  32:1  warning  Missing semicolon  semi

Examples/UIExplorer/NavigatorIOSColorsExample.js
  48:26  warning  ['lightContent'] is better written in dot notation  dot-notation

Examples/UIExplorer/TabBarIOSExample.js
  81:16  warning  Trailing spaces not allowed  no-trailing-spaces

Examples/UIExplorer/TextInputExample.js
  390:7  warning  Missing semicolon  semi

✖ 6 problems
```
Closes https://github.com/facebook/react-native/pull/1254
Github Author: Eric Sauter <esauter@lgscout.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-14 09:39:52 -08:00
Harrison Harnisch babdc21614 WebSocket polyfill
Summary:
- Added as a library in /Libraries/WebSocket
- Drag and drop to add to project (similar to adding Geolocation polyfill)
- Exposed as `window.WebSocket` which conforms with https://developer.mozilla.org/en-US/docs/Web/API/WebSocket specs
Closes https://github.com/facebook/react-native/pull/890
Github Author: Harrison Harnisch <hharnisc@gmail.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-14 09:37:02 -08:00
James Ide 55e280d200 [UIExplorer] Fix app icon so it actually shows up on the home screen
Summary:
Generated icons of the proper sizes so they show up on the home screen. It's not beautiful since the images have a transparent background but this also makes build warnings go away.

Closes https://github.com/facebook/react-native/pull/1267
Github Author: James Ide <ide@jameside.com>

Test Plan:  Run app, see icon on simulator home screen
2015-05-14 09:16:15 -08:00
Joe Stanton 29325d7cb3 Move init into local-cli 2015-05-14 18:08:56 +01:00
Dave Sibiski f865da26ba [NavigatorIOS] Fixes #1268 - Bug causing the leftButtonIcon to not appear
Summary:
Closes https://github.com/facebook/react-native/pull/1269
Github Author: Dave Sibiski <dsibiski@gmail.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-14 09:01:57 -08:00
James Ide b1c93bb9fc [Haste] @provides -> @providesModule StaticRenderer
Summary:
Pretty sure this shouldn't be @provides
Closes https://github.com/facebook/react-native/pull/837
Github Author: James Ide <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-14 08:42:13 -08:00
Martin Konicek 661321fda7 [ReactNative] Remove ReactNativeComponentMixin 2015-05-14 08:17:20 -08:00
Joe Stanton 9caee3248b Linked with new local-cli, refactored 2015-05-14 16:11:05 +01:00
Joe Stanton 2e2e577a09 Require directly, don't spawn 2015-05-14 15:25:35 +01:00
Joe Stanton 132f8fa3ce 1-1 port of init script to Nodejs
This will remove the dependency on Ruby.
2015-05-14 15:23:25 +01:00
Alex Akers e84e5710e4 [React Native] Update podspec for 0.4.2 2015-05-14 04:10:47 -08:00
Spencer Ahrens 425711927a Merge pull request #1271 from ide/map-docs
Move requireNativeComponent call below the complete MapView definition
2015-05-13 21:13:19 -07:00
James Ide 69db752067 Move requireNativeComponent call below the complete MapView definition
requireNativeComponent should be called after the wrapper component is fully defined, including its static properties.
2015-05-13 21:05:50 -07:00
Christopher Chedeau ec6aebabff Merge pull request #1124 from enaqx/patch-1
Update .gitignore with *.log
2015-05-13 19:52:41 -07:00
Spencer Ahrens 6e179fb7cd [ReactNative] introduce mountSafeCallback
Summary:
`mountSafeCallback` simply wraps a callback in an `isMounted()` check to prevent crashes when old callbacks are called on unmounted components.

@public

Test Plan:
Added logging and made sure callbacks were getting called through
`mountSafeCallback` and that things worked (e.g. photo viewer rotation etc).
2015-05-13 18:36:53 -08:00
Christopher Chedeau 71ce49b7a5 Fix failing snapshot test 2015-05-13 19:04:50 -07:00
Amjad Masad a6b29a0b1a [react-packager] Update worker farm 2015-05-13 17:54:19 -08:00
Amjad Masad 9fde7d2828 [react-native] Make document.js into a polyfill. Fixes #1149
Summary:
@public
document shimming must run before anything else. However, we don't currently guarantee that. This moves the document shimming into `document.js` which is used as a polyfill.

Test Plan:
* start server
* go to playground app
* require `NativeModules` as the first thing
* open chrome debugger
* no error
2015-05-13 17:50:21 -08:00
Christopher Chedeau b63905f7f9 Merge pull request #1142 from frantic/init-in-existing-project
Warn if `init` is called from existing project
2015-05-13 18:13:33 -07:00
Christopher Chedeau ddde7e333c Actually submitting the right number. Sorry for the spam :( 2015-05-13 16:57:07 -07:00
Christopher Chedeau 50a58e108a Turns out, travis doesn't support 8.3, reverting to 8.1 :( 2015-05-13 16:50:13 -07:00
Christopher Chedeau 4b1f01ada2 Only use iphonesdk8.3 2015-05-13 16:43:31 -07:00
Christopher Chedeau fcf5cc3981 Add specific xcode sdk to travis.yml 2015-05-13 16:38:41 -07:00
Christopher Chedeau 1b99c9976a Update UIExplorerTests to iOS Simulator 8.3 and re-record failing tests 2015-05-13 16:32:31 -07:00
Amjad Masad 5429b5f9cc [react-packager] Use transformer name in cache name
Summary:
@public
Shouldn't confuse the cache from files transformed by different transformers. This takes into account the transformer in the cache hash name.

Test Plan:
* start server with --babel
* generate bundle
* start server with --jstransform
* generate bundle
* compare them and they're different
2015-05-13 14:49:28 -08:00
Christopher Chedeau fec81947bd Merge pull request #1264 from vjeux/Update_Wed_13_May
Update wed 13 may
2015-05-13 14:47:49 -07:00
Christopher Chedeau 8917f81cb5 Update flow config 2015-05-13 14:37:20 -07:00
Christopher Chedeau 5b01e41b24 Merge pull request #1097 from gabelevi/version
Specify Flow version in SampleApp .flowconfig
2015-05-13 14:11:03 -07:00
Gabe Levi bc4b118ede Urm actually update the correct file this time 2015-05-13 17:03:20 -04:00
Philipp von Weitershausen b47e89a397 Back out D2063283: [react-packager] Update worker farm 2015-05-13 12:41:47 -08:00
Gabe Levi 1e42fea0af Bump the react-native .flowconfig Flow version to v0.11.0 2015-05-13 13:38:54 -07:00
Gabe Levi aceaaa69eb [Flow] v0.11.0 cleaning - Part 15 (Libraries/FBReactKit/js) 2015-05-13 13:24:37 -07:00
Spencer Ahrens 81ad810186 [ReactNative] differentiate fatal and soft exceptions 2015-05-13 13:24:37 -07:00
James Ide 484f63b1db [Pods] Define a subspec for ART
Summary:
Adds a CocoaPods subspec for ART.

Closes https://github.com/facebook/react-native/pull/1208
Github Author: James Ide <ide@jameside.com>

Test Plan:  Pull in the subspec and run the VectorWidget example from react-art.
2015-05-13 13:24:37 -07:00
Spencer Ahrens 1497e42fc5 [ReactNative] Properly support overflow: 'visible' on ScrollView
Summary:
We need to unset `clipsToBounds` on both the wrapper and the inner custom
scroll view

@public

Test Plan:
`overflow: 'visible'` actually shows content outside the `ScrollView`
(e.g. for full-bleed horizontal scrollers/carousels).  It doesn't pick up
touches though, which is a wider issue.
2015-05-13 13:24:37 -07:00
Alex Akers 86709c15cb [React Native] Support variable corner radii on RCTView 2015-05-13 13:24:37 -07:00
James Ide f40a7b4609 [Bridge] Make RCTJavaScriptDidFailToLoadNotification match DidLoad notif
Summary:
Add the RCTBatchedBridge object to the notification's userInfo for consistency with RCTJavaScriptDidLoadNotification, and set the target object to `_parentBridge`.

cc @nicklockwood @tadeuzagallo
Closes https://github.com/facebook/react-native/pull/1243
Github Author: James Ide <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-13 13:24:37 -07:00
James Ide ba9ef00ab9 [RCTBridge] Clean up reload notification observer
Summary:
After the RCTBatchedBridge refactor, the `-[NSNotificationCenter addObserver]` and `[removeObserver]` calls got divided between RCTBridge and RCTBatchedBridge. This diff does two things:

 - Moved `removeObserver` out of RTCBatchedBridge and into `-[RCTBridge invalidate]`
 - Moved `addObserver` from `bindKeys` to `setUp`. This is so that `-[RCTBridge reload]` will re-add the observer after invalidating and removing the observer

cc @tadeuzagallo
Closes https://github.com/facebook/react-native/pull/1212
Github Author: James Ide <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-13 13:24:37 -07:00
Ben Alpert a0440daf98 [react-native] Codemod .getNodeHandle, .getNativeNode to React.findNodeHandle 2015-05-13 13:24:37 -07:00
Ben Alpert a2f73b4d77 [react-native] Add React.findNodeHandle 2015-05-13 13:24:37 -07:00
Logan Bernard 2ed2d20dfe FloatFromLeft animation
Summary:
float from left animation for Navigator.SceneConfigs

#1100
@ericvicenti
@ide
Closes https://github.com/facebook/react-native/pull/1249
Github Author: Logan Bernard <bernard.logan4@gmail.com>

@public

Test Plan: Video: https://drive.google.com/file/d/0B9HtmABaCcR0Zi1yNkl5UDhWbzg/view
2015-05-13 13:24:37 -07:00
Bill Fisher 89e26e92b6 [ReactNative] decompose transform matrix 2015-05-13 13:24:37 -07:00
James Ide 6a699302c8 [Navigator] Pass route into onItemRef
Summary:
The index alone isn't so useful; pass the route as well. (I am using this to implement componentWill/DidFocus in a library instead of onWill/DidFocus; #1153).

Closes https://github.com/facebook/react-native/pull/1154
Github Author: James Ide <ide@jameside.com>

@public

Test Plan:  Set up a navigator with a couple of scenes, and see that when onItemRef is called for each one, the route is passed in as the third argument.
2015-05-13 13:24:37 -07:00
Eric Vicenti 1a68585990 [ReactNative] Navigator fix rapid gesture breakage
Summary:
When gesturing rapidly between scenes, the navigator can get into an unresponsive state. A few minor fixes can avoid that case

@public

Test Plan: Rapid gestures on iOS device and simulator can no longer get into bad state
2015-05-13 13:24:36 -07:00
Gabe Levi 184bb1151a [Flow] v0.11.0 cleaning - Part 14 (react-native-github) 2015-05-13 13:24:36 -07:00
Amjad Masad 4a137aa840 [react-packager] Update worker farm
Summary:
@public
Adds a couple of things:
* `autoStart` option, which warms up the worker farm as opposed to spin up children on demand
* worker-farm now passes properties on errors from children to parent (for line/col number in errors without resorting to hacks)

Test Plan:
* Run the server with --reset-cache
* things work
2015-05-13 13:24:36 -07:00
Martin Konicek 92fc92835f [ReactNative] Resolve assets on Android 2015-05-13 13:24:36 -07:00
Krzysztof Magiera 369e30f685 [ReactNative] Rename files after ReactIOS codemod so that filename matches name exported with @providesModule. 2015-05-13 13:24:36 -07:00
Nick Lockwood 6c812c8124 Fixed layout bug 2015-05-13 13:24:36 -07:00
Tadeu Zagallo d230629e61 [ReactNative] Add test to check RootContentView and BatchedBridge are deallocated 2015-05-13 13:24:36 -07:00
Tadeu Zagallo 92d7324f15 [ReactNative] Fix RootContentView release when the top-level bridge is held
Summary:
The RCTRootView creates a underlying RCTRootContentView that was deallocated when
the bridge modules were deallocated. That doesn't work when the bridge is held.

@public

Test Plan:
Launch Groups, put a breakpoint on `-[RCTRootContentView dealloc]`, enter and
leave a group page. It should be called now.
2015-05-13 13:24:36 -07:00
Vladimir Kurchatkin a142ed50ff Add letterSpacing style property for Text
Summary:
Fixes #457
Closes https://github.com/facebook/react-native/pull/482
Github Author: Vladimir Kurchatkin <vladimir.kurchatkin@gmail.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
2015-05-13 13:24:36 -07:00
Eric Vicenti 02d875869a [ReactNative] Fix Navigator empty scene issue
Summary:
In some situations, when quickly swiping back to a scene we are transitioning from, the scene is blank/missing. This is fixed by adding a check for the active gesture when we hide the scenes.

@public

Test Plan: Can no longer reproduce on simulator when quickly swiping back to the scene we are transitioning from
2015-05-13 13:24:36 -07:00
Tadeu Zagallo ef339250b5 [ReactNative] Add prompt to AlertIOS
Summary:
Add `AlertIOS.prompt`

It's compatible with the js spec, with the exception that I had to add
a callback param since it's async. Also supports the same button configuration
as `AlertIOS.alert`.

@public

Test Plan:
I've updated the `AlertIOS` example on UIExplorer with every
valid combination of
parameters, so just going through it should be fine.
2015-05-13 13:24:36 -07:00
Nick Lockwood cfeae15c1f Fixed thread safety for RCTImageLoader 2015-05-13 13:24:36 -07:00
Nick Lockwood 6b2c88feec decode pathName when extracting from url 2015-05-13 13:24:36 -07:00
Ben Alpert f8b36491d7 [react-native] Fix spelling of "cancelled"
Summary:
Apparently British spelling is "cancelled", American is "canceled"? Picking "cancelled" for consistency with UIKit.

@public

Test Plan: landcastle
2015-05-13 13:24:36 -07:00
Nick Lockwood 5e160f168d Added support for local image to RCTImageLoader 2015-05-13 13:24:35 -07:00
Dmitry Soshnikov 792b2db23c [jest] Update to v0.4.2 2015-05-13 13:24:35 -07:00
Eric Vicenti aa19232609 [ReactNative] Fix case where scenes are not reset on gesture detaching
Summary:
Sometimes, when quicly backing out of a gesture, the scene isn't fully reset to the middle position and remains offset by a few pixels. This makes sure that never happens.

@public

Test Plan: Tested on iOS and I can no longer see the scenes stop when backing out of a gesture
2015-05-13 13:24:35 -07:00
Andrew Rasmussen 709aa5f259 Revert "[ReactNative] update Layout" 2015-05-13 13:24:35 -07:00
Eric Vicenti a852227279 [ReactNative] Improve Navigator start gesture logic
Summary:
Previously it was possible for a gesture to be granted initiated if the start direction is not respected before the gesture detection distance gets reached, if the gesture direction is met eventually. This change ensures the gesture gets started in the right direction, otherwise the gesture action will set the responder.

@public

Test Plan: Fixes left-right swiping issue in AdsManager when a vertical swipe is intended.
2015-05-13 13:24:35 -07:00
Krzysztof Magiera ff00e1496c [ReactNative] Rename ReactIOS JS module (and relatives) to ReactNative. 2015-05-13 13:24:35 -07:00
Christopher Chedeau 1db2f07192 Update jestSupport in preparation for upgrading jest to latest version 2015-05-13 13:23:43 -07:00
Eric Vicenti 4b5385b2f0 [ReactNative] Fix Navigator resetTo race condition
Summary:
SetState can be somewhat racy. By the time the route state finishes, another resetTo has already happened, so the origional route is no longer in the stack. Hence the redbox invariant "Calling pop to route for a route that doesn't exist!"

This could also be fixed in product code by not calling resetTo rapidly, but the navigator should be resilient to such shenanigans

@public

Test Plan: Cannot get AdsManager crash t7031976
2015-05-13 12:17:31 -08:00
James Ide 057f5ffc79 Merge pull request #1262 from umhan35/patch-2
Update link in Native UI Components (iOS) guide
2015-05-13 13:09:23 -07:00
Gabe Levi f0afbc237e Update the .flowconfig version to v0.11.0 2015-05-13 14:05:55 -04:00
Gabe Levi f619988476 Specify Flow version in SampleApp .flowconfig 2015-05-13 14:05:55 -04:00
Zhao Han 85a6734387 Update link in Native UI Components (iOS) guide
Update the event mapping link: update line number
2015-05-13 10:08:38 -05:00
Brent Vatne e0adedde78 Merge pull request #764 from Rudimental/patch-1
Fix grammar in EmbeddedApp.md
2015-05-11 14:02:51 -07:00
Brent Vatne 120c32c52c [Docs] Don't show copyright/flow on APIs without docblock 2015-05-10 10:17:21 -07:00
Brent Vatne 0206ab2bac Merge pull request #1225 from umhan35/patch-1
[Docs] Link to #props anchor instead of non-existent #proptypes
2015-05-10 09:41:48 -07:00
Zhao Han 38c5be59b8 Fix issues#1223 2015-05-09 19:05:33 -05:00
Alex Kotliarskyi 41612f37b0 0.4.2 2015-05-08 13:37:49 -07:00
Alex Kotliarskyi 4933034334 Warn if init is called from existing project 2015-05-04 12:19:48 -07:00
Nick Raienko aff1841b3d Update .gitignore with *.log
Add additional rule to exclude files like npm-debug.log.
2015-05-04 01:34:36 +03:00
David Rabkin 7c0a332b81 Fix grammar in EmbeddedApp.md 2015-04-08 16:28:29 -07:00
224 changed files with 6309 additions and 3161 deletions
+3 -1
View File
@@ -1,3 +1,5 @@
**/node_modules/**/.*js
# node_modules ignored by default
**/staticBundle.js
**/main.js
Libraries/vendor/**/*
+2 -1
View File
@@ -16,6 +16,7 @@
"document": false,
"escape": false,
"exports": false,
"fetch": false,
"global": false,
"jest": false,
"Map": true,
@@ -167,7 +168,7 @@
"no-underscore-dangle": 0, // disallow dangling underscores in identifiers
"no-wrap-func": 1, // disallow wrapping of non-IIFE statements in parens
"no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
"quotes": [1, "single"], // specify whether double or single quotes should be used
"quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used
"quote-props": 0, // require quotes around object literal property names (off by default)
"semi": 1, // require or disallow use of semicolons instead of ASI
"sort-vars": 0, // sort variables within the same declaration block (off by default)
+1 -1
View File
@@ -37,4 +37,4 @@ Examples/UIExplorer/ImageMocks.js
module.system=haste
[version]
0.10.0
0.11.0
+1
View File
@@ -27,3 +27,4 @@ project.xcworkspace
# Node
node_modules
*.log
+2 -2
View File
@@ -19,8 +19,8 @@ The core team will be monitoring for pull requests. When we get one, we'll run s
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests!
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes.
5. Make sure your code lints - we've done our best to make sure these rules match our internal linting guidelines.
4. Ensure tests pass on Travis.
5. Make sure your code lints (`node linter.js <files touched>`).
6. If you haven't already, complete the CLA.
### Contributor License Agreement ("CLA")
+1 -1
View File
@@ -150,7 +150,7 @@ class Game2048 extends React.Component {
startX: number;
startY: number;
constructor(props) {
constructor(props: {}) {
super(props);
this.state = {
board: new GameBoard(),
@@ -7,10 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */; };
008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 008F07F21AC5B25A0029DE68 /* main.jsbundle */; };
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
@@ -18,6 +16,7 @@
00E356F31AD99517003FC87E /* SampleAppTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* SampleAppTests.m */; };
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
@@ -27,13 +26,6 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
remoteInfo = RCTWebSocketDebugger;
};
00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
@@ -41,13 +33,6 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTActionSheet;
};
00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
remoteInfo = RCTAdSupport;
};
00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -90,6 +75,13 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTSettings;
};
139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
@@ -114,10 +106,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = ../../Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = "<group>"; };
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = iOS/main.jsbundle; sourceTree = "<group>"; };
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
@@ -126,6 +116,7 @@
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* SampleAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAppTests.m; sourceTree = "<group>"; };
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = iOS/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = "<group>"; };
@@ -151,30 +142,21 @@
buildActionMask = 2147483647;
files = (
146834051AC3E58100842450 /* libReact.a in Frameworks */,
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */,
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */,
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
00481BDC1AC0C7FA00671115 /* Products */ = {
isa = PBXGroup;
children = (
00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */,
);
name = Products;
sourceTree = "<group>";
};
00C302A81ABCB8CE00DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
@@ -183,14 +165,6 @@
name = Products;
sourceTree = "<group>";
};
00C302B01ABCB8E700DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */,
);
name = Products;
sourceTree = "<group>";
};
00C302B61ABCB90400DB3ED1 /* Products */ = {
isa = PBXGroup;
children = (
@@ -248,6 +222,14 @@
name = Products;
sourceTree = "<group>";
};
139FDEE71B06529A00C62182 /* Products */ = {
isa = PBXGroup;
children = (
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* SampleApp */ = {
isa = PBXGroup;
children = (
@@ -283,7 +265,6 @@
children = (
146833FF1AC3E56700842450 /* React.xcodeproj */,
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */,
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
@@ -291,7 +272,7 @@
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */,
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@@ -394,10 +375,6 @@
ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
},
{
ProductGroup = 00C302B01ABCB8E700DB3ED1 /* Products */;
ProjectRef = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */;
},
{
ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
@@ -427,8 +404,8 @@
ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
},
{
ProductGroup = 00481BDC1AC0C7FA00671115 /* Products */;
ProjectRef = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */;
ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 146834001AC3E56700842450 /* Products */;
@@ -444,13 +421,6 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocketDebugger.a;
remoteRef = 00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -458,13 +428,6 @@
remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAdSupport.a;
remoteRef = 00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -500,6 +463,13 @@
remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
146834041AC3E56700842450 /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
+3
View File
@@ -31,3 +31,6 @@ node_modules/react-native/Libraries/react-native/react-native-interface.js
[options]
module.system=haste
[version]
0.11.0
+90 -1
View File
@@ -95,9 +95,98 @@ exports.examples = [{
</TouchableHighlight>
</View>
);
},
}
},
{
title: 'Prompt',
render(): React.Component {
return <PromptExample />
}
}];
class PromptExample extends React.Component {
constructor(props) {
super(props);
this.promptResponse = this.promptResponse.bind(this);
this.state = {
promptValue: undefined,
};
this.title = 'Type a value';
this.defaultValue = 'Default value';
this.buttons = [{
text: 'Custom cancel',
}, {
text: 'Custom OK',
onPress: this.promptResponse
}];
}
render() {
return (
<View>
<Text style={{marginBottom: 10}}>
<Text style={{fontWeight: 'bold'}}>Prompt value:</Text> {this.state.promptValue}
</Text>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.promptResponse)}>
<View style={styles.button}>
<Text>
prompt with title & callback
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.buttons)}>
<View style={styles.button}>
<Text>
prompt with title & custom buttons
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.defaultValue, this.promptResponse)}>
<View style={styles.button}>
<Text>
prompt with title, default value & callback
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={this.prompt.bind(this, this.title, this.defaultValue, this.buttons)}>
<View style={styles.button}>
<Text>
prompt with title, default value & custom buttons
</Text>
</View>
</TouchableHighlight>
</View>
);
}
prompt() {
// Flow's apply support is broken: #7035621
((AlertIOS.prompt: any).apply: any)(AlertIOS, arguments);
}
promptResponse(promptValue) {
this.setState({ promptValue });
}
}
var styles = StyleSheet.create({
wrapper: {
borderRadius: 5,
+19
View File
@@ -68,6 +68,18 @@ var styles = StyleSheet.create({
borderLeftWidth: 40,
borderLeftColor: 'blue',
},
border6: {
borderTopWidth: 10,
borderTopColor: 'red',
borderRightWidth: 20,
borderRightColor: 'yellow',
borderBottomWidth: 30,
borderBottomColor: 'green',
borderLeftWidth: 40,
borderLeftColor: 'blue',
borderTopLeftRadius: 100,
},
});
exports.title = 'Border';
@@ -115,4 +127,11 @@ exports.examples = [
return <View style={[styles.box, styles.border5]} />;
}
},
{
title: 'Custom Borders',
description: 'border*Width & border*Color',
render() {
return <View style={[styles.box, styles.border6]} />;
}
},
];
+29
View File
@@ -0,0 +1,29 @@
/**
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
* Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @providesModule ExampleTypes
* @flow
*/
export type Example = {
title: string,
render: () => ?ReactElement<any, any, any>,
description?: string,
};
export type ExampleModule = {
title: string;
description: string;
examples: Array<Example>;
external?: bool;
};
+2 -2
View File
@@ -29,7 +29,7 @@ var regionText = {
longitude: '0',
latitudeDelta: '0',
longitudeDelta: '0',
}
};
var MapRegionInput = React.createClass({
@@ -168,7 +168,7 @@ var MapViewExample = React.createClass({
/>
<MapRegionInput
onChange={this._onRegionInputChanged}
region={this.state.mapRegionInput}
region={this.state.mapRegionInput || undefined}
/>
</View>
);
@@ -45,7 +45,7 @@ var NavigatorIOSColors = React.createClass({
render: function() {
// Set StatusBar with light contents to get better contrast
StatusBarIOS.setStyle(StatusBarIOS.Style['lightContent']);
StatusBarIOS.setStyle(StatusBarIOS.Style.lightContent);
return (
<NavigatorIOS
+7 -1
View File
@@ -181,7 +181,13 @@ var BoxOnlyExample = React.createClass({
}
});
var exampleClasses = [
type ExampleClass = {
Component: ReactClass<any, any, any>,
title: string,
description: string,
};
var exampleClasses: Array<ExampleClass> = [
{
Component: NoneExample,
title: '`none`',
+1 -1
View File
@@ -78,7 +78,7 @@ var TabBarExample = React.createClass({
this.setState({
selectedTab: 'greenTab',
presses: this.state.presses + 1
});
});
}}>
{this._renderContent('#21551C', 'Green Tab')}
</TabBarIOS.Item>
+20
View File
@@ -218,6 +218,26 @@ exports.examples = [
</View>
);
},
}, {
title: 'Letter Spacing',
render: function() {
return (
<View>
<Text style={{letterSpacing: 0}}>
letterSpacing = 0
</Text>
<Text style={{letterSpacing: 2, marginTop: 5}}>
letterSpacing = 2
</Text>
<Text style={{letterSpacing: 9, marginTop: 5}}>
letterSpacing = 9
</Text>
<Text style={{letterSpacing: -1, marginTop: 5}}>
letterSpacing = -1
</Text>
</View>
);
},
}, {
title: 'Spaces',
render: function() {
+1 -1
View File
@@ -387,7 +387,7 @@ exports.examples = [
<View style={styles.multilineChild}/>
</TextInput>
</View>
)
);
}
}
];
@@ -8,12 +8,13 @@
/* Begin PBXBuildFile section */
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 004D28A21AAF61C70097A701 /* UIExplorerTests.m */; };
00D2771A1AB8C3E100DC1E48 /* libRCTWebSocketDebugger.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D277131AB8C2C700DC1E48 /* libRCTWebSocketDebugger.a */; };
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
134180011AA9153C003F314A /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1344545A1AAFCAAE003F0779 /* libRCTAdSupport.a */; };
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1353F5451B0E64F9009B4FAC /* ClippingTests.m */; };
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDED91B0651EA00C62182 /* libRCTWebSocket.a */; };
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
@@ -34,13 +35,6 @@
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
remoteInfo = UIExplorer;
};
00D277121AB8C2C700DC1E48 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
remoteInfo = RCTWebSocketDebugger;
};
13417FE71AA91428003F314A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
@@ -76,6 +70,13 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTGeolocation;
};
139FDED81B0651EA00C62182 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
147CED4A1AB34F8C00DA3E4C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */;
@@ -124,12 +125,13 @@
004D289E1AAF61C70097A701 /* UIExplorerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
004D28A11AAF61C70097A701 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
004D28A21AAF61C70097A701 /* UIExplorerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIExplorerTests.m; sourceTree = "<group>"; };
00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = ../../Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = "<group>"; };
13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = ../../Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = "<group>"; };
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
1353F5451B0E64F9009B4FAC /* ClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClippingTests.m; sourceTree = "<group>"; };
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = UIExplorer/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = UIExplorer/AppDelegate.m; sourceTree = "<group>"; };
@@ -157,18 +159,18 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */,
14AADF051AC3DBB1002390C9 /* libReact.a in Frameworks */,
00D2771A1AB8C3E100DC1E48 /* libRCTWebSocketDebugger.a in Frameworks */,
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */,
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */,
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */,
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */,
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */,
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */,
134180011AA9153C003F314A /* libRCTText.a in Frameworks */,
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */,
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */,
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */,
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */,
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */,
134180011AA9153C003F314A /* libRCTText.a in Frameworks */,
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
139FDEDB1B0651FB00C62182 /* libRCTWebSocket.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -179,6 +181,7 @@
isa = PBXGroup;
children = (
004D28A21AAF61C70097A701 /* UIExplorerTests.m */,
1353F5451B0E64F9009B4FAC /* ClippingTests.m */,
004D28A01AAF61C70097A701 /* Supporting Files */,
);
path = UIExplorerTests;
@@ -192,14 +195,6 @@
name = "Supporting Files";
sourceTree = "<group>";
};
00D2770F1AB8C2C700DC1E48 /* Products */ = {
isa = PBXGroup;
children = (
00D277131AB8C2C700DC1E48 /* libRCTWebSocketDebugger.a */,
);
name = Products;
sourceTree = "<group>";
};
1316A21D1AA397F400C0188E /* Libraries */ = {
isa = PBXGroup;
children = (
@@ -213,8 +208,8 @@
13CC9D481AEED2B90020D1C2 /* RCTSettings.xcodeproj */,
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */,
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */,
00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */,
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */,
139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@@ -259,6 +254,14 @@
name = Products;
sourceTree = "<group>";
};
139FDECB1B0651EA00C62182 /* Products */ = {
isa = PBXGroup;
children = (
139FDED91B0651EA00C62182 /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* UIExplorer */ = {
isa = PBXGroup;
children = (
@@ -447,8 +450,8 @@
ProjectRef = D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */;
},
{
ProductGroup = 00D2770F1AB8C2C700DC1E48 /* Products */;
ProjectRef = 00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */;
ProductGroup = 139FDECB1B0651EA00C62182 /* Products */;
ProjectRef = 139FDECA1B0651EA00C62182 /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 14AADF001AC3DB95002390C9 /* Products */;
@@ -464,13 +467,6 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
00D277131AB8C2C700DC1E48 /* libRCTWebSocketDebugger.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocketDebugger.a;
remoteRef = 00D277121AB8C2C700DC1E48 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
13417FE81AA91428003F314A /* libRCTImage.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -506,6 +502,13 @@
remoteRef = 134A8A241AACED6A00945AAE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139FDED91B0651EA00C62182 /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 139FDED81B0651EA00C62182 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -575,6 +578,7 @@
buildActionMask = 2147483647;
files = (
004D28A31AAF61C70097A701 /* UIExplorerTests.m in Sources */,
1353F5461B0E64F9009B4FAC /* ClippingTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3,37 +3,37 @@
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "uie_icon@2x.png",
"filename" : "Icon-Small@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "uie_icon@2x-1.png",
"filename" : "Icon-Small@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "uie_icon@2x-2.png",
"filename" : "Icon-40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "uie_icon@2x-3.png",
"filename" : "Icon-40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "uie_icon@2x-5.png",
"filename" : "Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "uie_icon@2x-4.png",
"filename" : "Icon-60@3x.png",
"scale" : "3x"
}
],
@@ -41,4 +41,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

+4 -3
View File
@@ -69,9 +69,10 @@ var styles = StyleSheet.create({
overflow: 'hidden',
},
titleContainer: {
borderWidth: 0.5,
borderRadius: 2.5,
borderColor: '#d6d7da',
borderBottomWidth: 0.5,
borderTopLeftRadius: 3,
borderTopRightRadius: 2.5,
borderBottomColor: '#d6d7da',
backgroundColor: '#f6f7f8',
paddingHorizontal: 10,
paddingVertical: 5,
+16 -6
View File
@@ -30,6 +30,8 @@ var {
var { TestModule } = React.addons;
var Settings = require('Settings');
import type { Example, ExampleModule } from 'ExampleTypes';
var createExamplePage = require('./createExamplePage');
var COMPONENTS = [
@@ -107,9 +109,17 @@ COMPONENTS.concat(APIS).forEach((Example) => {
}
});
class UIExplorerList extends React.Component {
type Props = {
navigator: Array<{title: string, component: ReactClass<any,any,any>}>,
onExternalExampleRequested: Function,
};
constructor(props) {
class UIExplorerList extends React.Component {
props: Props;
constructor(props: Props) {
super(props);
this.state = {
dataSource: ds.cloneWithRowsAndSections({
@@ -149,7 +159,7 @@ class UIExplorerList extends React.Component {
);
}
_renderSectionHeader(data, section) {
_renderSectionHeader(data: any, section: string) {
return (
<View style={styles.sectionHeader}>
<Text style={styles.sectionHeaderTitle}>
@@ -159,7 +169,7 @@ class UIExplorerList extends React.Component {
);
}
_renderRow(example, i) {
_renderRow(example: ExampleModule, i: number) {
return (
<View key={i}>
<TouchableHighlight onPress={() => this._onPressRow(example)}>
@@ -177,7 +187,7 @@ class UIExplorerList extends React.Component {
);
}
_search(text) {
_search(text: mixed) {
var regex = new RegExp(text, 'i');
var filter = (component) => regex.test(component.title);
@@ -191,7 +201,7 @@ class UIExplorerList extends React.Component {
Settings.set({searchText: text});
}
_onPressRow(example) {
_onPressRow(example: ExampleModule) {
if (example.external) {
this.props.onExternalExampleRequested(example);
return;
@@ -0,0 +1,127 @@
/**
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
* Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIView.h>
#import <XCTest/XCTest.h>
extern CGRect RCTClipRect(CGSize contentSize, CGFloat contentScale,
CGSize targetSize, CGFloat targetScale,
UIViewContentMode resizeMode);
#define RCTAssertEqualPoints(a, b) { \
XCTAssertEqual(a.x, b.x); \
XCTAssertEqual(a.y, b.y); \
}
#define RCTAssertEqualSizes(a, b) { \
XCTAssertEqual(a.width, b.width); \
XCTAssertEqual(a.height, b.height); \
}
#define RCTAssertEqualRects(a, b) { \
RCTAssertEqualPoints(a.origin, b.origin); \
RCTAssertEqualSizes(a.size, b.size); \
}
@interface ClippingTests : XCTestCase
@end
@implementation ClippingTests
- (void)testLandscapeSourceLandscapeTarget
{
CGSize content = {1000, 100};
CGSize target = {100, 20};
{
CGRect expected = {CGPointZero, {100, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {CGPointZero, {100, 10}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {{-50, 0}, {200, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
- (void)testPortraitSourceLandscapeTarget
{
CGSize content = {10, 100};
CGSize target = {100, 20};
{
CGRect expected = {CGPointZero, {10, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {CGPointZero, {2, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {{0, -49}, {10, 100}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
- (void)testPortraitSourcePortraitTarget
{
CGSize content = {10, 100};
CGSize target = {20, 50};
{
CGRect expected = {CGPointZero, {10, 50}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {CGPointZero, {5, 50}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {{0, -37.5}, {10, 100}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
- (void)testScaling
{
CGSize content = {2, 2};
CGSize target = {3, 3};
CGRect expected = {CGPointZero, {3, 3}};
CGRect result = RCTClipRect(content, 2, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
@end
Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 140 KiB

@@ -88,35 +88,19 @@
XCTAssertTrue(foundElement, @"Cound't find element with '<View>' text in %d seconds", TIMEOUT_SECONDS);
}
- (void)testViewExampleSnapshot
{
[_runner runTest:_cmd module:@"ViewExample"];
#define RCT_SNAPSHOT_TEST(name, reRecord) \
- (void)test##name##Snapshot \
{ \
_runner.recordMode |= reRecord; \
[_runner runTest:_cmd module:@#name]; \
}
- (void)testLayoutExampleSnapshot
{
[_runner runTest:_cmd module:@"LayoutExample"];
}
- (void)testTextExampleSnapshot
{
[_runner runTest:_cmd module:@"TextExample"];
}
- (void)testSwitchExampleSnapshot
{
[_runner runTest:_cmd module:@"SwitchExample"];
}
- (void)testSliderExampleSnapshot
{
[_runner runTest:_cmd module:@"SliderExample"];
}
- (void)testTabBarExampleSnapshot
{
[_runner runTest:_cmd module:@"TabBarExample"];
}
RCT_SNAPSHOT_TEST(ViewExample, NO)
RCT_SNAPSHOT_TEST(LayoutExample, NO)
RCT_SNAPSHOT_TEST(TextExample, NO)
RCT_SNAPSHOT_TEST(SwitchExample, NO)
RCT_SNAPSHOT_TEST(SliderExample, NO)
RCT_SNAPSHOT_TEST(TabBarExample, NO)
// Make sure this test runs last
- (void)testZZZ_NotInRecordMode
+9 -18
View File
@@ -17,22 +17,13 @@
'use strict';
var React = require('react-native');
var ReactIOS = require('ReactIOS');
var ReactNative = require('ReactNative');
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var invariant = require('invariant');
class Example extends React.Component {
title: string;
description: string;
}
type ExampleModule = {
title: string;
description: string;
examples: Array<Example>;
};
import type { Example, ExampleModule } from 'ExampleTypes';
var createExamplePage = function(title: ?string, exampleModule: ExampleModule)
: ReactClass<any, any, any> {
@@ -44,20 +35,20 @@ var createExamplePage = function(title: ?string, exampleModule: ExampleModule)
description: exampleModule.description,
},
getBlock: function(example, i) {
getBlock: function(example: Example, i) {
// Hack warning: This is a hack because the www UI explorer requires
// renderComponent to be called.
var originalRender = React.render;
var originalRenderComponent = React.renderComponent;
var originalIOSRender = ReactIOS.render;
var originalIOSRenderComponent = ReactIOS.renderComponent;
var originalIOSRender = ReactNative.render;
var originalIOSRenderComponent = ReactNative.renderComponent;
var renderedComponent;
// TODO remove typecasts when Flow bug #6560135 is fixed
// and workaround is removed from react-native.js
(React: Object).render =
(React: Object).renderComponent =
(ReactIOS: Object).render =
(ReactIOS: Object).renderComponent =
(ReactNative: Object).render =
(ReactNative: Object).renderComponent =
function(element, container) {
renderedComponent = element;
};
@@ -67,8 +58,8 @@ var createExamplePage = function(title: ?string, exampleModule: ExampleModule)
}
(React: Object).render = originalRender;
(React: Object).renderComponent = originalRenderComponent;
(ReactIOS: Object).render = originalIOSRender;
(ReactIOS: Object).renderComponent = originalIOSRenderComponent;
(ReactNative: Object).render = originalIOSRender;
(ReactNative: Object).renderComponent = originalIOSRenderComponent;
return (
<UIExplorerBlock
key={i}
+62
View File
@@ -0,0 +1,62 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule AppEventsTest
* @flow
*/
'use strict';
var React = require('react-native');
var {
NativeAppEventEmitter,
NativeModules,
StyleSheet,
Text,
View,
} = React;
var TestModule = NativeModules.TestModule || NativeModules.SnapshotTestManager;
var deepDiffer = require('deepDiffer');
var TEST_PAYLOAD = {foo: 'bar'};
var AppEventsTest = React.createClass({
getInitialState: function() {
return {sent: 'none', received: 'none'};
},
componentDidMount: function() {
NativeAppEventEmitter.addListener('testEvent', this.receiveEvent);
var event = {data: TEST_PAYLOAD, ts: Date.now()};
TestModule.sendAppEvent('testEvent', event);
this.setState({sent: event});
},
receiveEvent: function(event: any) {
if (deepDiffer(event.data, TEST_PAYLOAD)) {
throw new Error('Received wrong event: ' + JSON.stringify(event));
}
var elapsed = (Date.now() - event.ts) + 'ms';
this.setState({received: event, elapsed}, TestModule.markTestCompleted);
},
render: function() {
return (
<View style={styles.container}>
<Text>
{JSON.stringify(this.state, null, ' ')}
</Text>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
margin: 40,
},
});
module.exports = AppEventsTest;
+1
View File
@@ -26,6 +26,7 @@ var TESTS = [
require('./TimersTest'),
require('./AsyncStorageTest'),
require('./LayoutEventsTest'),
require('./AppEventsTest'),
require('./SimpleSnapshotTest'),
];
@@ -76,6 +76,11 @@
[_runner runTest:_cmd module:@"LayoutEventsTest"];
}
- (void)testAppEvents
{
[_runner runTest:_cmd module:@"AppEventsTest"];
}
#pragma mark Snapshot Tests
- (void)testSimpleSnapshot
+1 -2
View File
@@ -8,8 +8,7 @@
*
* @providesModule ARTSerializablePath
*/
"use strict";
'use strict';
// TODO: Move this into an ART mode called "serialized" or something
@@ -6,19 +6,18 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactIOSART
* @providesModule ReactNativeART
*/
"use strict";
'use strict';
var Color = require('art/core/color');
var Path = require('ARTSerializablePath');
var Transform = require('art/core/transform');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var merge = require('merge');
// Diff Helpers
@@ -64,7 +63,7 @@ function fontAndLinesDiffer(a, b) {
// Native Attributes
var SurfaceViewAttributes = merge(ReactIOSViewAttributes.UIView, {
var SurfaceViewAttributes = merge(ReactNativeViewAttributes.UIView, {
// This should contain pixel information such as width, height and
// resolution to know what kind of buffer needs to be allocated.
// Currently we rely on UIViews and style to figure that out.
@@ -100,22 +99,22 @@ var TextAttributes = merge(RenderableAttributes, {
// Native Components
var NativeSurfaceView = createReactIOSNativeComponentClass({
var NativeSurfaceView = createReactNativeComponentClass({
validAttributes: SurfaceViewAttributes,
uiViewClassName: 'ARTSurfaceView',
});
var NativeGroup = createReactIOSNativeComponentClass({
var NativeGroup = createReactNativeComponentClass({
validAttributes: GroupAttributes,
uiViewClassName: 'ARTGroup',
});
var NativeShape = createReactIOSNativeComponentClass({
var NativeShape = createReactNativeComponentClass({
validAttributes: ShapeAttributes,
uiViewClassName: 'ARTShape',
});
var NativeText = createReactIOSNativeComponentClass({
var NativeText = createReactNativeComponentClass({
validAttributes: TextAttributes,
uiViewClassName: 'ARTText',
});
+2 -1
View File
@@ -12,6 +12,7 @@
'use strict';
var RCTAnimationManager = require('NativeModules').AnimationExperimentalManager;
var React = require('React');
var AnimationUtils = require('AnimationUtils');
type EasingFunction = (t: number) => number;
@@ -47,7 +48,7 @@ var AnimationExperimental = {
},
callback?: ?(finished: bool) => void
): number {
var nodeHandle = anim.node.getNodeHandle();
var nodeHandle = React.findNodeHandle(anim.node);
var easingSample = AnimationUtils.evaluateEasingFunction(
anim.duration,
anim.easing
+3 -2
View File
@@ -12,6 +12,7 @@
'use strict';
var POPAnimationOrNull = require('POPAnimation');
var React = require('React');
if (!POPAnimationOrNull) {
// POP animation isn't available in the OSS fork - this is a temporary
@@ -83,7 +84,7 @@ var POPAnimationMixin = {
'Invalid refKey ' + refKey + ' for anim:\n' + JSON.stringify(anim) +
'\nvalid refs: ' + JSON.stringify(Object.keys(this.refs))
);
var refNodeHandle = this.refs[refKey].getNodeHandle();
var refNodeHandle = React.findNodeHandle(this.refs[refKey]);
this.startAnimationWithNodeHandle(refNodeHandle, animID, doneCallback);
},
@@ -192,7 +193,7 @@ var POPAnimationMixin = {
*/
stopAnimations: function(refKey: string) {
invariant(this.refs[refKey], 'invalid ref');
this.stopNodeHandleAnimations(this.refs[refKey].getNodeHandle());
this.stopNodeHandleAnimations(React.findNodeHandle(this.refs[refKey]));
},
/**
@@ -15,7 +15,9 @@ var RCTPOPAnimationManager = require('NativeModules').POPAnimationManager;
if (!RCTPOPAnimationManager) {
// POP animation isn't available in the OSS fork - this is a temporary
// workaround to enable its availability to be determined at runtime.
module.exports = (null: ?Object);
// For Flow let's pretend like we always export POPAnimation
// so all our users don't need to do null checks
module.exports = ((null: any): typeof POPAnimation);
} else {
var ReactPropTypes = require('ReactPropTypes');
@@ -11,7 +11,7 @@
*/
'use strict';
var ReactIOSEventEmitter = require('ReactIOSEventEmitter');
var ReactNativeEventEmitter = require('ReactNativeEventEmitter');
// Completely locally implemented - no native hooks.
module.exports = ReactIOSEventEmitter;
module.exports = ReactNativeEventEmitter;
+2
View File
@@ -92,6 +92,8 @@ var getPhotosReturnChecker = createStrictShapeTypeChecker({
});
class CameraRoll {
static GroupTypesOptions: Array<string>;
/**
* Saves the image with tag `tag` to the camera roll.
*
@@ -12,7 +12,6 @@
'use strict';
var NativeMethodsMixin = require('NativeMethodsMixin');
var NativeModules = require('NativeModules');
var PropTypes = require('ReactPropTypes');
var React = require('React');
var StyleSheet = require('StyleSheet');
@@ -53,6 +52,12 @@ var ActivityIndicatorIOS = React.createClass({
'small',
'large',
]),
/**
* Invoked on mount and layout changes with
*
* {nativeEvent: { layout: {x, y, width, height}}}.
*/
onLayout: PropTypes.func,
},
getDefaultProps: function(): DefaultProps {
@@ -65,10 +70,12 @@ var ActivityIndicatorIOS = React.createClass({
},
render: function() {
var {style, ...props} = this.props;
var {onLayout, style, ...props} = this.props;
var sizeStyle = (this.props.size === 'large') ? styles.sizeLarge : styles.sizeSmall;
return (
<View style={[styles.container, sizeStyle, style]}>
<View
onLayout={onLayout}
style={[styles.container, sizeStyle, style]}>
<RCTActivityIndicatorView {...props} />
</View>
);
+4 -4
View File
@@ -15,10 +15,10 @@ var EdgeInsetsPropType = require('EdgeInsetsPropType');
var NativeMethodsMixin = require('NativeMethodsMixin');
var Platform = require('Platform');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var View = require('View');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var deepDiffer = require('deepDiffer');
var insetsDiffer = require('insetsDiffer');
var merge = require('merge');
@@ -163,9 +163,9 @@ var MapView = React.createClass({
});
if (Platform.OS === 'android') {
var RCTMap = createReactIOSNativeComponentClass({
var RCTMap = createReactNativeComponentClass({
validAttributes: merge(
ReactIOSViewAttributes.UIView, {
ReactNativeViewAttributes.UIView, {
showsUserLocation: true,
zoomEnabled: true,
rotateEnabled: true,
@@ -14,14 +14,14 @@
var EventEmitter = require('EventEmitter');
var Image = require('Image');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var RCTNavigatorManager = require('NativeModules').NavigatorManager;
var StyleSheet = require('StyleSheet');
var StaticContainer = require('StaticContainer.react');
var View = require('View');
var createReactIOSNativeComponentClass =
require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass =
require('createReactNativeComponentClass');
var invariant = require('invariant');
var logError = require('logError');
var merge = require('merge');
@@ -35,14 +35,14 @@ function getuid() {
return __uid++;
}
var RCTNavigator = createReactIOSNativeComponentClass({
validAttributes: merge(ReactIOSViewAttributes.UIView, {
var RCTNavigator = createReactNativeComponentClass({
validAttributes: merge(ReactNativeViewAttributes.UIView, {
requestedTopOfStack: true
}),
uiViewClassName: 'RCTNavigator',
});
var RCTNavigatorItem = createReactIOSNativeComponentClass({
var RCTNavigatorItem = createReactNativeComponentClass({
validAttributes: {
// TODO: Remove or fix the attributes that are not fully functional.
// NavigatorIOS does not use them all, because some are problematic
@@ -67,7 +67,7 @@ var RCTNavigatorItem = createReactIOSNativeComponentClass({
var NavigatorTransitionerIOS = React.createClass({
requestSchedulingNavigation: function(cb) {
RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
(this: any).getNodeHandle(),
React.findNodeHandle(this),
logError,
cb
);
+6 -5
View File
@@ -13,6 +13,7 @@
var NativeModules = require('NativeModules');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var React = require('React');
var Subscribable = require('Subscribable');
var TextInputState = require('TextInputState');
@@ -182,7 +183,7 @@ var ScrollResponderMixin = {
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
if (!this.props.keyboardShouldPersistTaps &&
currentlyFocusedTextInput != null &&
e.target != currentlyFocusedTextInput) {
e.target !== currentlyFocusedTextInput) {
return true;
}
return this.scrollResponderIsAnimating();
@@ -243,7 +244,7 @@ var ScrollResponderMixin = {
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
if (!this.props.keyboardShouldPersistTaps &&
currentlyFocusedTextInput != null &&
e.target != currentlyFocusedTextInput &&
e.target !== currentlyFocusedTextInput &&
!this.state.observedScrollSinceBecomingResponder &&
!this.state.becameResponderWhileAnimating) {
this.props.onScrollResponderKeyboardDismissed &&
@@ -350,7 +351,7 @@ var ScrollResponderMixin = {
* can also be used to quickly scroll to any element we want to focus
*/
scrollResponderScrollTo: function(offsetX: number, offsetY: number) {
RCTUIManagerDeprecated.scrollTo(this.getNodeHandle(), offsetX, offsetY);
RCTUIManagerDeprecated.scrollTo(React.findNodeHandle(this), offsetX, offsetY);
},
/**
@@ -358,7 +359,7 @@ var ScrollResponderMixin = {
* @param {object} rect Should have shape {x, y, width, height}
*/
scrollResponderZoomTo: function(rect: { x: number; y: number; width: number; height: number; }) {
RCTUIManagerDeprecated.zoomToRect(this.getNodeHandle(), rect);
RCTUIManagerDeprecated.zoomToRect(React.findNodeHandle(this), rect);
},
/**
@@ -376,7 +377,7 @@ var ScrollResponderMixin = {
this.preventNegativeScrollOffset = !!preventNegativeScrollOffset;
RCTUIManager.measureLayout(
nodeHandle,
this.getNodeHandle(),
React.findNodeHandle(this),
this.scrollResponderTextInputFocusError,
this.scrollResponderInputMeasureAndScrollToKeyboard
);
@@ -17,7 +17,7 @@ var PointPropType = require('PointPropType');
var RCTScrollView = require('NativeModules').UIManager.RCTScrollView;
var RCTScrollViewConsts = RCTScrollView.Constants;
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var RCTUIManager = require('NativeModules').UIManager;
var ScrollResponder = require('ScrollResponder');
var StyleSheet = require('StyleSheet');
@@ -25,7 +25,7 @@ var StyleSheetPropType = require('StyleSheetPropType');
var View = require('View');
var ViewStylePropTypes = require('ViewStylePropTypes');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var deepDiffer = require('deepDiffer');
var flattenStyle = require('flattenStyle');
var insetsDiffer = require('insetsDiffer');
@@ -207,19 +207,19 @@ var ScrollView = React.createClass({
},
getInnerViewNode: function(): any {
return this.refs[INNERVIEW].getNodeHandle();
return React.findNodeHandle(this.refs[INNERVIEW]);
},
scrollTo: function(destY?: number, destX?: number) {
if (Platform.OS === 'android') {
RCTUIManager.dispatchViewManagerCommand(
this.getNodeHandle(),
React.findNodeHandle(this),
RCTUIManager.RCTScrollView.Commands.scrollTo,
[destX || 0, destY || 0]
);
} else {
RCTUIManager.scrollTo(
this.getNodeHandle(),
React.findNodeHandle(this),
destX || 0,
destY || 0
);
@@ -228,7 +228,7 @@ var ScrollView = React.createClass({
scrollWithoutAnimationTo: function(destY?: number, destX?: number) {
RCTUIManager.scrollWithoutAnimationTo(
this.getNodeHandle(),
React.findNodeHandle(this),
destX || 0,
destY || 0
);
@@ -343,7 +343,7 @@ var styles = StyleSheet.create({
});
var validAttributes = {
...ReactIOSViewAttributes.UIView,
...ReactNativeViewAttributes.UIView,
alwaysBounceHorizontal: true,
alwaysBounceVertical: true,
automaticallyAdjustContentInsets: true,
@@ -370,11 +370,11 @@ var validAttributes = {
};
if (Platform.OS === 'android') {
var AndroidScrollView = createReactIOSNativeComponentClass({
var AndroidScrollView = createReactNativeComponentClass({
validAttributes: validAttributes,
uiViewClassName: 'RCTScrollView',
});
var AndroidHorizontalScrollView = createReactIOSNativeComponentClass({
var AndroidHorizontalScrollView = createReactNativeComponentClass({
validAttributes: validAttributes,
uiViewClassName: 'AndroidHorizontalScrollView',
});
+1 -1
View File
@@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @provides StaticRenderer
* @providesModule StaticRenderer
* @flow
*/
'use strict';
+1 -1
View File
@@ -11,7 +11,7 @@
*/
'use strict';
var EventEmitter = require('EventEmitter');
import type EventEmitter from 'EventEmitter';
/**
* Subscribable provides a mixin for safely subscribing a component to an
+16 -9
View File
@@ -19,14 +19,14 @@ var Platform = require('Platform');
var PropTypes = require('ReactPropTypes');
var React = require('React');
var ReactChildren = require('ReactChildren');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var StyleSheet = require('StyleSheet');
var Text = require('Text');
var TextInputState = require('TextInputState');
var TimerMixin = require('react-timer-mixin');
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var emptyFunction = require('emptyFunction');
var invariant = require('invariant');
var merge = require('merge');
@@ -35,7 +35,7 @@ var autoCapitalizeConsts = RCTUIManager.UIText.AutocapitalizationType;
var keyboardTypeConsts = RCTUIManager.UIKeyboardType;
var returnKeyTypeConsts = RCTUIManager.UIReturnKeyType;
var RCTTextViewAttributes = merge(ReactIOSViewAttributes.UIView, {
var RCTTextViewAttributes = merge(ReactNativeViewAttributes.UIView, {
autoCorrect: true,
autoCapitalize: true,
clearTextOnFocus: true,
@@ -179,12 +179,12 @@ var TextInput = React.createClass({
'number-pad',
'phone-pad',
'name-phone-pad',
'email-address',
'decimal-pad',
'twitter',
'web-search',
// Cross-platform
'numeric',
'email-address',
]),
/**
* Determines how the return key should look.
@@ -232,6 +232,10 @@ var TextInput = React.createClass({
* Callback that is called when the text input's submit button is pressed.
*/
onSubmitEditing: PropTypes.func,
/**
* Invoked on mount and layout changes with {x, y, width, height}.
*/
onLayout: PropTypes.func,
/**
* If true, the text input obscures the text entered so that sensitive text
* like passwords stay secure. Default value is false.
@@ -305,7 +309,7 @@ var TextInput = React.createClass({
isFocused: function(): boolean {
return TextInputState.currentlyFocusedField() ===
this.refs.input.getNativeNode();
React.findNodeHandle(this.refs.input);
},
getDefaultProps: function(): DefaultProps {
@@ -446,6 +450,7 @@ var TextInput = React.createClass({
onEndEditing={this.props.onEndEditing}
onSubmitEditing={this.props.onSubmitEditing}
onSelectionChangeShouldSetResponder={() => true}
onLayout={this.props.onLayout}
placeholder={this.props.placeholder}
placeholderTextColor={this.props.placeholderTextColor}
text={this.state.bufferedValue}
@@ -495,6 +500,7 @@ var TextInput = React.createClass({
onSelectionChange={this._onSelectionChange}
onTextInput={this._onTextInput}
onSelectionChangeShouldSetResponder={emptyFunction.thatReturnsTrue}
onLayout={this.props.onLayout}
placeholder={this.props.placeholder}
placeholderTextColor={this.props.placeholderTextColor}
text={this.state.bufferedValue}
@@ -530,6 +536,7 @@ var TextInput = React.createClass({
onChange={this._onChange}
onEndEditing={this.props.onEndEditing}
onSubmitEditing={this.props.onSubmitEditing}
onLayout={this.props.onLayout}
password={this.props.password || this.props.secureTextEntry}
placeholder={this.props.placeholder}
text={this.state.bufferedValue}
@@ -582,7 +589,7 @@ var TextInput = React.createClass({
var counter = event.nativeEvent.eventCounter;
if (counter > this.state.mostRecentEventCounter) {
this.setState({mostRecentEventCounter: counter});
}
}
},
});
@@ -592,17 +599,17 @@ var styles = StyleSheet.create({
},
});
var RCTTextView = createReactIOSNativeComponentClass({
var RCTTextView = createReactNativeComponentClass({
validAttributes: RCTTextViewAttributes,
uiViewClassName: 'RCTTextView',
});
var RCTTextField = createReactIOSNativeComponentClass({
var RCTTextField = createReactNativeComponentClass({
validAttributes: RCTTextFieldAttributes,
uiViewClassName: 'RCTTextField',
});
var AndroidTextInput = createReactIOSNativeComponentClass({
var AndroidTextInput = createReactNativeComponentClass({
validAttributes: AndroidTextInputAttributes,
uiViewClassName: 'AndroidTextInput',
});
@@ -21,22 +21,22 @@ var TextInputState = {
/**
* Internal state
*/
_currentlyFocusedID: (null: ?string),
_currentlyFocusedID: (null: ?number),
/**
* Returns the ID of the currently focused text field, if one exists
* If no text field is focused it returns null
*/
currentlyFocusedField: function(): ?string {
currentlyFocusedField: function(): ?number {
return this._currentlyFocusedID;
},
/**
* @param {string} TextInputID id of the text field to focus
* @param {number} TextInputID id of the text field to focus
* Focuses the specified text field
* noop if the text field was already focused
*/
focusTextInput: function(textFieldID: string) {
focusTextInput: function(textFieldID: ?number) {
if (this._currentlyFocusedID !== textFieldID && textFieldID !== null) {
this._currentlyFocusedID = textFieldID;
RCTUIManager.focus(textFieldID);
@@ -44,11 +44,11 @@ var TextInputState = {
},
/**
* @param {string} textFieldID id of the text field to focus
* @param {number} textFieldID id of the text field to focus
* Unfocuses the specified text field
* noop if it wasn't focused
*/
blurTextInput: function(textFieldID: string) {
blurTextInput: function(textFieldID: ?number) {
if (this._currentlyFocusedID === textFieldID && textFieldID !== null) {
this._currentlyFocusedID = null;
RCTUIManager.blur(textFieldID);
@@ -14,7 +14,7 @@
var NativeMethodsMixin = require('NativeMethodsMixin');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var StyleSheet = require('StyleSheet');
var TimerMixin = require('react-timer-mixin');
var Touchable = require('Touchable');
@@ -120,7 +120,7 @@ var TouchableHighlight = React.createClass({
viewConfig: {
uiViewClassName: 'RCTView',
validAttributes: ReactIOSViewAttributes.RCTView
validAttributes: ReactNativeViewAttributes.RCTView
},
/**
+51 -8
View File
@@ -15,15 +15,35 @@ var NativeMethodsMixin = require('NativeMethodsMixin');
var PropTypes = require('ReactPropTypes');
var RCTUIManager = require('NativeModules').UIManager;
var React = require('React');
var ReactIOSStyleAttributes = require('ReactIOSStyleAttributes');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var StyleSheetPropType = require('StyleSheetPropType');
var ViewStylePropTypes = require('ViewStylePropTypes');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var stylePropType = StyleSheetPropType(ViewStylePropTypes);
var AccessibilityTraits = [
'none',
'button',
'link',
'header',
'search',
'image',
'selected',
'plays',
'key',
'text',
'summary',
'disabled',
'frequentUpdates',
'startsMedia',
'adjustable',
'allowsDirectInteraction',
'pageTurn',
];
/**
* The most fundamental component for building UI, `View` is a
* container that supports layout with flexbox, style, some touch handling, and
@@ -53,7 +73,7 @@ var View = React.createClass({
*/
viewConfig: {
uiViewClassName: 'RCTView',
validAttributes: ReactIOSViewAttributes.RCTView
validAttributes: ReactNativeViewAttributes.RCTView
},
propTypes: {
@@ -70,6 +90,27 @@ var View = React.createClass({
*/
accessibilityLabel: PropTypes.string,
/**
* Provides additional traits to screen reader. By default no traits are
* provided unless specified otherwise in element
*/
accessibilityTraits: PropTypes.oneOfType([
PropTypes.oneOf(AccessibilityTraits),
PropTypes.arrayOf(PropTypes.oneOf(AccessibilityTraits)),
]),
/**
* When `accessible` is true, the system will try to invoke this function
* when the user performs accessibility tap gesture.
*/
onAcccessibilityTap: PropTypes.func,
/**
* When `accessible` is true, the system will invoke this function when the
* user performs the magic tap gesture.
*/
onMagicTap: PropTypes.func,
/**
* Used to locate this view in end-to-end tests.
*/
@@ -91,7 +132,9 @@ var View = React.createClass({
onStartShouldSetResponderCapture: PropTypes.func,
/**
* Invoked on mount and layout changes with {x, y, width, height}.
* Invoked on mount and layout changes with
*
* {nativeEvent: { layout: {x, y, width, height}}}.
*/
onLayout: PropTypes.func,
@@ -163,8 +206,8 @@ var View = React.createClass({
},
});
var RCTView = createReactIOSNativeComponentClass({
validAttributes: ReactIOSViewAttributes.RCTView,
var RCTView = createReactNativeComponentClass({
validAttributes: ReactNativeViewAttributes.RCTView,
uiViewClassName: 'RCTView',
});
RCTView.propTypes = View.propTypes;
@@ -172,7 +215,7 @@ if (__DEV__) {
var viewConfig = RCTUIManager.viewConfigs && RCTUIManager.viewConfigs.RCTView || {};
for (var prop in viewConfig.nativeProps) {
var viewAny: any = View; // Appease flow
if (!viewAny.propTypes[prop] && !ReactIOSStyleAttributes[prop]) {
if (!viewAny.propTypes[prop] && !ReactNativeStyleAttributes[prop]) {
throw new Error(
'View is missing propType for native prop `' + prop + '`'
);
@@ -28,6 +28,10 @@ var ViewStylePropTypes = {
borderBottomColor: ReactPropTypes.string,
borderLeftColor: ReactPropTypes.string,
borderRadius: ReactPropTypes.number,
borderTopLeftRadius: ReactPropTypes.number,
borderTopRightRadius: ReactPropTypes.number,
borderBottomLeftRadius: ReactPropTypes.number,
borderBottomRightRadius: ReactPropTypes.number,
opacity: ReactPropTypes.number,
overflow: ReactPropTypes.oneOf(['visible', 'hidden']),
shadowColor: ReactPropTypes.string,
@@ -12,11 +12,11 @@
var EdgeInsetsPropType = require('EdgeInsetsPropType');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var StyleSheet = require('StyleSheet');
var View = require('View');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var keyMirror = require('keyMirror');
var merge = require('merge');
@@ -75,7 +75,7 @@ var WebView = React.createClass({
errorEvent.code,
errorEvent.description);
} else if (this.state.viewState !== WebViewState.IDLE) {
console.error("RCTWebView invalid state encountered: " + this.state.loading);
console.error('RCTWebView invalid state encountered: ' + this.state.loading);
}
var webViewStyles = [styles.container, this.props.style];
@@ -143,7 +143,7 @@ var WebView = React.createClass({
},
getWebWiewHandle: function() {
return this.refs[RCT_WEBVIEW_REF].getNodeHandle();
return React.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
},
onLoadingStart: function(event) {
@@ -152,7 +152,7 @@ var WebView = React.createClass({
onLoadingError: function(event) {
event.persist(); // persist this event because we need to store it
console.error("encountered an error loading page", event.nativeEvent);
console.error('Encountered an error loading page', event.nativeEvent);
this.setState({
lastErrorEvent: event.nativeEvent,
@@ -168,8 +168,8 @@ var WebView = React.createClass({
},
});
var RCTWebView = createReactIOSNativeComponentClass({
validAttributes: merge(ReactIOSViewAttributes.UIView, {
var RCTWebView = createReactNativeComponentClass({
validAttributes: merge(ReactNativeViewAttributes.UIView, {
url: true,
javaScriptEnabledAndroid: true,
}),
+2 -3
View File
@@ -14,7 +14,6 @@
var ActivityIndicatorIOS = require('ActivityIndicatorIOS');
var EdgeInsetsPropType = require('EdgeInsetsPropType');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var StyleSheet = require('StyleSheet');
var Text = require('Text');
var View = require('View');
@@ -189,7 +188,7 @@ var WebView = React.createClass({
},
getWebWiewHandle: function(): any {
return this.refs[RCT_WEBVIEW_REF].getNodeHandle();
return React.findNodeHandle(this.refs[RCT_WEBVIEW_REF]);
},
onLoadingStart: function(event: Event) {
@@ -198,7 +197,7 @@ var WebView = React.createClass({
onLoadingError: function(event: Event) {
event.persist(); // persist this event because we need to store it
console.error("encountered an error loading page", event.nativeEvent);
console.error('Encountered an error loading page', event.nativeEvent);
this.setState({
lastErrorEvent: event.nativeEvent,
@@ -87,7 +87,7 @@ var SCROLLVIEW_REF = 'listviewscroll';
* smoothly while dynamically loading potentially very large (or conceptually
* infinite) data sets:
*
* * Only re-render changed rows - the hasRowChanged function provided to the
* * Only re-render changed rows - the rowHasChanged function provided to the
* data source tells the ListView if it needs to re-render a row because the
* source data has changed - see ListViewDataSource for more details.
*
@@ -346,12 +346,12 @@ var ListView = React.createClass({
_measureAndUpdateScrollProps: function() {
RCTUIManager.measureLayout(
this.refs[SCROLLVIEW_REF].getInnerViewNode(),
this.refs[SCROLLVIEW_REF].getNodeHandle(),
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
logError,
this._setScrollContentHeight
);
RCTUIManager.measureLayoutRelativeToParent(
this.refs[SCROLLVIEW_REF].getNodeHandle(),
React.findNodeHandle(this.refs[SCROLLVIEW_REF]),
logError,
this._setScrollVisibleHeight
);
@@ -103,6 +103,10 @@ class ListViewDataSource {
*
* or
*
* { sectionID_1: [ <rowData1>, <rowData2>, ... ], ... }
*
* or
*
* [ [ <rowData1>, <rowData2>, ... ], ... ]
*
* The constructor takes in a params argument that can contain any of the
@@ -24,6 +24,7 @@
*
* @providesModule Navigator
*/
/* eslint-disable no-extra-boolean-cast*/
'use strict';
var AnimationsDebugModule = require('NativeModules').AnimationsDebugModule;
@@ -48,8 +49,6 @@ var clamp = require('clamp');
var flattenStyle = require('flattenStyle');
var getNavigatorContext = require('getNavigatorContext');
var invariant = require('invariant');
var keyMirror = require('keyMirror');
var merge = require('merge');
var rebound = require('rebound');
var PropTypes = React.PropTypes;
@@ -253,7 +252,7 @@ var Navigator = React.createClass({
onDidFocus: PropTypes.func,
/**
* Will be called with (ref, indexInStack) when the scene ref changes
* Will be called with (ref, indexInStack, route) when the scene ref changes
*/
onItemRef: PropTypes.func,
@@ -582,7 +581,7 @@ var Navigator = React.createClass({
* This happens at the end of a transition started by transitionTo, and when the spring catches up to a pending gesture
*/
_completeTransition: function() {
if (this.spring.getCurrentValue() !== 1) {
if (this.spring.getCurrentValue() !== 1 && this.spring.getCurrentValue() !== 0) {
// The spring has finished catching up to a gesture in progress. Remove the pending progress
// and we will be in a normal activeGesture state
if (this.state.pendingGestureProgress) {
@@ -659,11 +658,17 @@ var Navigator = React.createClass({
},
/**
* Hides scenes that we are not currently on or transitioning from
* Hides all scenes that we are not currently on, gesturing to, or transitioning from
*/
_hideScenes: function() {
var gesturingToIndex = null;
if (this.state.activeGesture) {
gesturingToIndex = this.state.presentedIndex + this._deltaForGestureAction(this.state.activeGesture);
}
for (var i = 0; i < this.state.routeStack.length; i++) {
if (i === this.state.presentedIndex || i === this.state.transitionFromIndex) {
if (i === this.state.presentedIndex ||
i === this.state.transitionFromIndex ||
i === gesturingToIndex) {
continue;
}
this._disableScene(i);
@@ -683,7 +688,7 @@ var Navigator = React.createClass({
*/
_enableScene: function(sceneIndex) {
// First, determine what the defined styles are for scenes in this navigator
var sceneStyle = flattenStyle(this.props.sceneStyle);
var sceneStyle = flattenStyle([styles.baseScene, this.props.sceneStyle]);
// Then restore the left value for this scene
var enabledSceneNativeProps = {
left: sceneStyle.left,
@@ -734,10 +739,13 @@ var Navigator = React.createClass({
viewAtIndex.setNativeProps({renderToHardwareTextureAndroid: shouldRenderToHardwareTexture});
},
_handleTouchStart: function() {
this._eligibleGestures = GESTURE_ACTIONS;
},
_handleMoveShouldSetPanResponder: function(e, gestureState) {
var currentRoute = this.state.routeStack[this.state.presentedIndex];
var sceneConfig = this.state.sceneConfigStack[this.state.presentedIndex];
this._expectingGestureGrant = this._matchGestureAction(sceneConfig.gestures, gestureState);
this._expectingGestureGrant = this._matchGestureAction(this._eligibleGestures, sceneConfig.gestures, gestureState);
return !! this._expectingGestureGrant;
},
@@ -819,7 +827,16 @@ var Navigator = React.createClass({
}
} else {
// The gesture has enough velocity to complete, so we transition to the gesture's destination
this._transitionTo(destIndex, transitionVelocity);
this._transitionTo(
destIndex,
transitionVelocity,
null,
() => {
if (releaseGestureAction === 'pop') {
this._cleanScenesPastIndex(destIndex);
}
}
);
}
this._detachGesture();
},
@@ -855,7 +872,7 @@ var Navigator = React.createClass({
var gesture = sceneConfig.gestures[this.state.activeGesture];
return this._moveAttachedGesture(gesture, gestureState);
}
var matchedGesture = this._matchGestureAction(sceneConfig.gestures, gestureState);
var matchedGesture = this._matchGestureAction(GESTURE_ACTIONS, sceneConfig.gestures, gestureState);
if (matchedGesture) {
this._attachGesture(matchedGesture);
}
@@ -870,8 +887,13 @@ var Navigator = React.createClass({
var nextProgress = (distance - gestureDetectMovement) /
(gesture.fullDistance - gestureDetectMovement);
if (nextProgress < 0 && gesture.isDetachable) {
var gesturingToIndex = this.state.presentedIndex + this._deltaForGestureAction(this.state.activeGesture);
this._transitionBetween(this.state.presentedIndex, gesturingToIndex, 0);
this._detachGesture();
this.spring.setCurrentValue(0);
if (this.state.pendingGestureProgress != null) {
this.spring.setCurrentValue(0);
}
return;
}
if (this._doesGestureOverswipe(this.state.activeGesture)) {
var frictionConstant = gesture.overswipe.frictionConstant;
@@ -889,12 +911,12 @@ var Navigator = React.createClass({
}
},
_matchGestureAction: function(gestures, gestureState) {
_matchGestureAction: function(eligibleGestures, gestures, gestureState) {
if (!gestures) {
return null;
}
var matchedGesture = null;
GESTURE_ACTIONS.some((gestureName) => {
eligibleGestures.some((gestureName, gestureIndex) => {
var gesture = gestures[gestureName];
if (!gesture) {
return;
@@ -920,12 +942,19 @@ var Navigator = React.createClass({
}
var moveStartedInRegion = gesture.edgeHitWidth == null ||
currentLoc < edgeHitWidth;
var moveTravelledFarEnough =
travelDist >= gesture.gestureDetectMovement &&
travelDist > oppositeAxisTravelDist * gesture.directionRatio;
if (moveStartedInRegion && moveTravelledFarEnough) {
if (!moveStartedInRegion) {
return false;
}
var moveTravelledFarEnough = travelDist >= gesture.gestureDetectMovement;
if (!moveTravelledFarEnough) {
return false;
}
var directionIsCorrect = Math.abs(travelDist) > Math.abs(oppositeAxisTravelDist) * gesture.directionRatio;
if (directionIsCorrect) {
matchedGesture = gestureName;
return true;
} else {
this._eligibleGestures = this._eligibleGestures.slice().splice(gestureIndex, 1);
}
});
return matchedGesture;
@@ -1151,7 +1180,11 @@ var Navigator = React.createClass({
resetTo: function(route) {
invariant(!!route, 'Must supply route to push');
this.replaceAtIndex(route, 0, () => {
this.popToRoute(route);
// Do not use popToRoute here, because race conditions could prevent the
// route from existing at this time. Instead, just go to index 0
if (this.state.presentedIndex > 0) {
this._popN(this.state.presentedIndex);
}
});
},
@@ -1159,13 +1192,13 @@ var Navigator = React.createClass({
return this.state.routeStack;
},
_handleItemRef: function(itemId, ref) {
_handleItemRef: function(itemId, route, ref) {
this._itemRefs[itemId] = ref;
var itemIndex = this.state.idStack.indexOf(itemId);
if (itemIndex === -1) {
return;
}
this.props.onItemRef && this.props.onItemRef(ref, itemIndex);
this.props.onItemRef && this.props.onItemRef(ref, itemIndex, route);
},
_cleanScenesPastIndex: function(index) {
@@ -1202,6 +1235,7 @@ var Navigator = React.createClass({
<View
style={styles.transitioner}
{...this.panGesture.panHandlers}
onTouchStart={this._handleTouchStart}
onResponderTerminationRequest={
this._handleResponderTerminationRequest
}>
@@ -1264,6 +1298,14 @@ var Navigator = React.createClass({
if (i !== this.state.presentedIndex) {
disabledSceneStyle = styles.disabledScene;
}
var originalRef = child.ref;
if (originalRef != null && typeof originalRef !== 'function') {
console.warn(
'String refs are not supported for navigator scenes. Use a callback ' +
'ref instead. Ignoring ref: ' + originalRef
);
originalRef = null;
}
return (
<View
key={this.state.idStack[i]}
@@ -1273,7 +1315,12 @@ var Navigator = React.createClass({
}}
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
{React.cloneElement(child, {
ref: this._handleItemRef.bind(null, this.state.idStack[i]),
ref: component => {
this._handleItemRef(this.state.idStack[i], route, component);
if (originalRef) {
originalRef(component);
}
}
})}
</View>
);
@@ -101,6 +101,18 @@ var FadeToTheLeft = {
},
};
var FadeToTheRight = {
...FadeToTheLeft,
transformTranslate: {
from: {x: 0, y: 0, z: 0},
to: {x: Math.round(SCREEN_WIDTH * 0.3), y: 0, z: 0},
},
translateX: {
from: 0,
to: Math.round(SCREEN_WIDTH * 0.3),
}
};
var FadeIn = {
opacity: {
from: 0,
@@ -187,6 +199,27 @@ var FromTheRight = {
},
};
var FromTheLeft = {
...FromTheRight,
transformTranslate: {
from: {x: -SCREEN_WIDTH, y: 0, z: 0},
to: {x: 0, y: 0, z: 0},
min: 0,
max: 1,
type: 'linear',
extrapolate: true,
round: PixelRatio.get(),
},
translateX: {
from: -SCREEN_WIDTH,
to: 0,
min: 0,
max: 1,
type: 'linear',
extrapolate: true,
round: PixelRatio.get(),
},
};
var ToTheBack = {
// Rotate *requires* you to break out each individual component of
@@ -374,6 +407,13 @@ var NavigatorSceneConfigs = {
...BaseConfig,
// We will want to customize this soon
},
FloatFromLeft: {
...BaseConfig,
animationInterpolators: {
into: buildStyleInterpolator(FromTheLeft),
out: buildStyleInterpolator(FadeToTheRight),
},
},
FloatFromBottom: {
...BaseConfig,
gestures: {
+1
View File
@@ -12,6 +12,7 @@
* @providesModule fetch
* @nolint
*/
/* eslint-disable */
'use strict';
var self = {};
+1 -1
View File
@@ -120,6 +120,6 @@ var Geolocation = {
subscriptions = [];
}
}
}
};
module.exports = Geolocation;
+9 -3
View File
@@ -18,7 +18,7 @@ var NativeMethodsMixin = require('NativeMethodsMixin');
var NativeModules = require('NativeModules');
var PropTypes = require('ReactPropTypes');
var React = require('React');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var StyleSheet = require('StyleSheet');
var StyleSheetPropType = require('StyleSheetPropType');
@@ -60,7 +60,7 @@ var Image = React.createClass({
/**
* `uri` is a string representing the resource identifier for the image, which
* could be an http address, a local file path, or the name of a static image
* resource (which should be wrapped in the `required('image!name')` function).
* resource (which should be wrapped in the `require('image!name')` function).
*/
source: PropTypes.shape({
uri: PropTypes.string,
@@ -99,6 +99,12 @@ var Image = React.createClass({
* testing scripts.
*/
testID: PropTypes.string,
/**
* Invoked on mount and layout changes with
*
* {nativeEvent: { layout: {x, y, width, height}}}.
*/
onLayout: PropTypes.func,
},
statics: {
@@ -113,7 +119,7 @@ var Image = React.createClass({
*/
viewConfig: {
uiViewClassName: 'UIView',
validAttributes: ReactIOSViewAttributes.UIView
validAttributes: ReactNativeViewAttributes.UIView
},
render: function() {
+2
View File
@@ -33,6 +33,8 @@ typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
- (id)downloadImageForURL:(NSURL *)url
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(UIViewContentMode)resizeMode
backgroundColor:(UIColor *)backgroundColor
block:(RCTImageDownloadBlock)block;
/**
+119 -18
View File
@@ -10,6 +10,7 @@
#import "RCTImageDownloader.h"
#import "RCTCache.h"
#import "RCTLog.h"
#import "RCTUtils.h"
typedef void (^RCTCachedDataDownloadBlock)(BOOL cached, NSData *data, NSError *error);
@@ -121,34 +122,134 @@ static NSString *RCTCacheKeyForURL(NSURL *url)
}];
}
- (id)downloadImageForURL:(NSURL *)url size:(CGSize)size
scale:(CGFloat)scale block:(RCTImageDownloadBlock)block
/**
* Returns the optimal context size for an image drawn using the clip rect
* returned by RCTClipRect.
*/
CGSize RCTTargetSizeForClipRect(CGRect);
CGSize RCTTargetSizeForClipRect(CGRect clipRect)
{
return (CGSize){
clipRect.size.width + clipRect.origin.x * 2,
clipRect.size.height + clipRect.origin.y * 2
};
}
/**
* This function takes an input content size & scale (typically from an image),
* a target size & scale that it will be drawn into (typically a CGContext) and
* then calculates the optimal rectangle to draw the image into so that it will
* be sized and positioned correctly if drawn using the specified content mode.
*/
CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
CGRect RCTClipRect(CGSize sourceSize, CGFloat sourceScale,
CGSize destSize, CGFloat destScale,
UIViewContentMode resizeMode)
{
// Precompensate for scale
CGFloat scale = sourceScale / destScale;
sourceSize.width *= scale;
sourceSize.height *= scale;
// Calculate aspect ratios if needed (don't bother is resizeMode == stretch)
CGFloat aspect = 0.0, targetAspect = 0.0;
if (resizeMode != UIViewContentModeScaleToFill) {
aspect = sourceSize.width / sourceSize.height;
targetAspect = destSize.width / destSize.height;
if (aspect == targetAspect) {
resizeMode = UIViewContentModeScaleToFill;
}
}
switch (resizeMode) {
case UIViewContentModeScaleToFill: // stretch
sourceSize.width = MIN(destSize.width, sourceSize.width);
sourceSize.height = MIN(destSize.height, sourceSize.height);
return (CGRect){CGPointZero, sourceSize};
case UIViewContentModeScaleAspectFit: // contain
if (targetAspect <= aspect) { // target is taller than content
sourceSize.width = destSize.width = MIN(sourceSize.width, destSize.width);
sourceSize.height = sourceSize.width / aspect;
} else { // target is wider than content
sourceSize.height = destSize.height = MIN(sourceSize.height, destSize.height);
sourceSize.width = sourceSize.height * aspect;
}
return (CGRect){CGPointZero, sourceSize};
case UIViewContentModeScaleAspectFill: // cover
if (targetAspect <= aspect) { // target is taller than content
sourceSize.height = destSize.height = MIN(sourceSize.height, destSize.height);
sourceSize.width = sourceSize.height * aspect;
destSize.width = destSize.height * targetAspect;
return (CGRect){{(destSize.width - sourceSize.width) / 2, 0}, sourceSize};
} else { // target is wider than content
sourceSize.width = destSize.width = MIN(sourceSize.width, destSize.width);
sourceSize.height = sourceSize.width / aspect;
destSize.height = destSize.width / targetAspect;
return (CGRect){{0, (destSize.height - sourceSize.height) / 2}, sourceSize};
}
default:
RCTLogError(@"A resizeMode value of %zd is not supported", resizeMode);
return (CGRect){CGPointZero, destSize};
}
}
- (id)downloadImageForURL:(NSURL *)url
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(UIViewContentMode)resizeMode
backgroundColor:(UIColor *)backgroundColor
block:(RCTImageDownloadBlock)block
{
return [self downloadDataForURL:url block:^(NSData *data, NSError *error) {
if (!data || error) {
block(nil, error);
return;
}
if (CGSizeEqualToSize(size, CGSizeZero)) {
// Target size wasn't available yet, so abort image drawing
block(nil, nil);
return;
}
UIImage *image = [UIImage imageWithData:data scale:scale];
if (image) {
// Resize (TODO: should we take aspect ratio into account?)
CGSize imageSize = size;
if (CGSizeEqualToSize(imageSize, CGSizeZero)) {
imageSize = image.size;
} else {
imageSize = (CGSize){
MIN(size.width, image.size.width),
MIN(size.height, image.size.height)
};
}
// Get scale and size
CGFloat destScale = scale ?: RCTScreenScale();
CGRect imageRect = RCTClipRect(image.size, image.scale, size, destScale, resizeMode);
CGSize destSize = RCTTargetSizeForClipRect(imageRect);
// Rescale image if required size is smaller
CGFloat imageScale = scale;
if (imageScale == 0 || imageScale < image.scale) {
imageScale = image.scale;
// Opacity optimizations
UIColor *blendColor = nil;
BOOL opaque = !RCTImageHasAlpha(image.CGImage);
if (!opaque && backgroundColor) {
CGFloat alpha;
[backgroundColor getRed:NULL green:NULL blue:NULL alpha:&alpha];
if (alpha > 0.999) { // no benefit to blending if background is translucent
opaque = YES;
blendColor = backgroundColor;
}
}
// Decompress image at required size
UIGraphicsBeginImageContextWithOptions(imageSize, NO, imageScale);
[image drawInRect:(CGRect){{0, 0}, imageSize}];
UIGraphicsBeginImageContextWithOptions(destSize, opaque, destScale);
if (blendColor) {
[blendColor setFill];
UIRectFill((CGRect){CGPointZero, destSize});
}
[image drawInRect:imageRect];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
+7 -1
View File
@@ -15,6 +15,12 @@
@interface RCTImageLoader : NSObject
+ (ALAssetsLibrary *)assetsLibrary;
+ (void)loadImageWithTag:(NSString *)tag callback:(void (^)(NSError *error, UIImage *image))callback;
/**
* Can be called from any thread.
* Will always call callback on main thread.
*/
+ (void)loadImageWithTag:(NSString *)tag
callback:(void (^)(NSError *error, id /* UIImage or CAAnimation */ image))callback;
@end
+48 -20
View File
@@ -16,6 +16,7 @@
#import <UIKit/UIKit.h>
#import "RCTConvert.h"
#import "RCTGIFImage.h"
#import "RCTImageDownloader.h"
#import "RCTLog.h"
@@ -25,20 +26,29 @@ static dispatch_queue_t RCTImageLoaderQueue(void)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("com.facebook.rctImageLoader", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
});
return queue;
}
NSError *errorWithMessage(NSString *message)
static NSError *RCTErrorWithMessage(NSString *message)
{
NSDictionary *errorInfo = @{NSLocalizedDescriptionKey: message};
NSError *error = [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo];
return error;
}
static void RCTDispatchCallbackOnMainQueue(void (^callback)(NSError *, id), NSError *error, UIImage *image)
{
if ([NSThread isMainThread]) {
callback(error, image);
} else {
dispatch_async(dispatch_get_main_queue(), ^{
callback(error, image);
});
}
}
@implementation RCTImageLoader
+ (ALAssetsLibrary *)assetsLibrary
@@ -51,7 +61,11 @@ NSError *errorWithMessage(NSString *message)
return assetsLibrary;
}
+ (void)loadImageWithTag:(NSString *)imageTag callback:(void (^)(NSError *error, UIImage *image))callback
/**
* Can be called from any thread.
* Will always call callback on main thread.
*/
+ (void)loadImageWithTag:(NSString *)imageTag callback:(void (^)(NSError *error, id image))callback
{
if ([imageTag hasPrefix:@"assets-library"]) {
[[RCTImageLoader assetsLibrary] assetForURL:[NSURL URLWithString:imageTag] resultBlock:^(ALAsset *asset) {
@@ -67,18 +81,18 @@ NSError *errorWithMessage(NSString *message)
ALAssetRepresentation *representation = [asset defaultRepresentation];
ALAssetOrientation orientation = [representation orientation];
UIImage *image = [UIImage imageWithCGImage:[representation fullResolutionImage] scale:1.0f orientation:(UIImageOrientation)orientation];
callback(nil, image);
RCTDispatchCallbackOnMainQueue(callback, nil, image);
}
});
} else {
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@ with no error message.", imageTag];
NSError *error = errorWithMessage(errorText);
callback(error, nil);
NSError *error = RCTErrorWithMessage(errorText);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
}
} failureBlock:^(NSError *loadError) {
NSString *errorText = [NSString stringWithFormat:@"Failed to load asset at URL %@.\niOS Error: %@", imageTag, loadError];
NSError *error = errorWithMessage(errorText);
callback(error, nil);
NSError *error = RCTErrorWithMessage(errorText);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
}];
} else if ([imageTag hasPrefix:@"ph://"]) {
// Using PhotoKit for iOS 8+
@@ -89,19 +103,19 @@ NSError *errorWithMessage(NSString *message)
PHFetchResult *results = [PHAsset fetchAssetsWithLocalIdentifiers:@[phAssetID] options:nil];
if (results.count == 0) {
NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", phAssetID];
NSError *error = errorWithMessage(errorText);
callback(error, nil);
NSError *error = RCTErrorWithMessage(errorText);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
return;
}
PHAsset *asset = [results firstObject];
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage *result, NSDictionary *info) {
if (result) {
callback(nil, result);
RCTDispatchCallbackOnMainQueue(callback, nil, result);
} else {
NSString *errorText = [NSString stringWithFormat:@"Failed to load PHAsset with local identifier %@ with no error message.", phAssetID];
NSError *error = errorWithMessage(errorText);
callback(error, nil);
NSError *error = RCTErrorWithMessage(errorText);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
return;
}
}];
@@ -109,20 +123,34 @@ NSError *errorWithMessage(NSString *message)
NSURL *url = [NSURL URLWithString:imageTag];
if (!url) {
NSString *errorMessage = [NSString stringWithFormat:@"Invalid URL: %@", imageTag];
callback(errorWithMessage(errorMessage), nil);
RCTDispatchCallbackOnMainQueue(callback, RCTErrorWithMessage(errorMessage), nil);
return;
}
[[RCTImageDownloader sharedInstance] downloadDataForURL:url block:^(NSData *data, NSError *error) {
if (error) {
callback(error, nil);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
} else {
callback(nil, [UIImage imageWithData:data]);
RCTDispatchCallbackOnMainQueue(callback, nil, [UIImage imageWithData:data]);
}
}];
} else if ([[imageTag lowercaseString] hasSuffix:@".gif"]) {
id image = RCTGIFImageWithFileURL([RCTConvert NSURL:imageTag]);
if (image) {
RCTDispatchCallbackOnMainQueue(callback, nil, image);
} else {
NSString *errorMessage = [NSString stringWithFormat:@"Unable to load GIF image: %@", imageTag];
NSError *error = RCTErrorWithMessage(errorMessage);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
}
} else {
NSString *errorMessage = [NSString stringWithFormat:@"Unrecognized tag protocol: %@", imageTag];
NSError *error = errorWithMessage(errorMessage);
callback(error, nil);
UIImage *image = [RCTConvert UIImage:imageTag];
if (image) {
RCTDispatchCallbackOnMainQueue(callback, nil, image);
} else {
NSString *errorMessage = [NSString stringWithFormat:@"Unrecognized tag protocol: %@", imageTag];
NSError *error = RCTErrorWithMessage(errorMessage);
RCTDispatchCallbackOnMainQueue(callback, error, nil);
}
}
}
+43 -9
View File
@@ -13,6 +13,7 @@
#import "RCTGIFImage.h"
#import "RCTImageDownloader.h"
#import "RCTUtils.h"
#import "UIView+React.h"
@implementation RCTNetworkImageView
{
@@ -26,8 +27,7 @@
- (instancetype)initWithFrame:(CGRect)frame imageDownloader:(RCTImageDownloader *)imageDownloader
{
self = [super initWithFrame:frame];
if (self) {
if ((self = [super initWithFrame:frame])) {
_deferSentinel = 0;
_imageDownloader = imageDownloader;
self.userInteractionEnabled = NO;
@@ -37,20 +37,44 @@
- (NSURL *)imageURL
{
// We clear our backing layer's imageURL when we are not in a window for a while,
// We clear our imageURL when we are not in a window for a while,
// to make sure we don't consume network resources while offscreen.
// However we don't want to expose this hackery externally.
return _deferred ? _deferredImageURL : _imageURL;
}
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
super.backgroundColor = backgroundColor;
[self _updateImage];
}
- (void)reactSetFrame:(CGRect)frame
{
[super reactSetFrame:frame];
[self _updateImage];
}
- (void)_updateImage
{
[self setImageURL:_imageURL resetToDefaultImageWhileLoading:NO];
}
- (void)setImageURL:(NSURL *)imageURL resetToDefaultImageWhileLoading:(BOOL)reset
{
if (![_imageURL isEqual:imageURL] && _downloadToken) {
[_imageDownloader cancelDownload:_downloadToken];
_downloadToken = nil;
}
_imageURL = imageURL;
if (_deferred) {
_deferredImageURL = imageURL;
} else {
if (_downloadToken) {
[_imageDownloader cancelDownload:_downloadToken];
_downloadToken = nil;
if (!imageURL) {
self.layer.contents = nil;
return;
}
if (reset) {
self.layer.contentsScale = _defaultImage.scale;
@@ -62,25 +86,35 @@
_downloadToken = [_imageDownloader downloadDataForURL:imageURL block:^(NSData *data, NSError *error) {
if (data) {
dispatch_async(dispatch_get_main_queue(), ^{
if (imageURL != self.imageURL) {
// Image has changed
return;
}
CAKeyframeAnimation *animation = RCTGIFImageWithData(data);
self.layer.contentsScale = 1.0;
self.layer.minificationFilter = kCAFilterLinear;
self.layer.magnificationFilter = kCAFilterLinear;
[self.layer addAnimation:animation forKey:@"contents"];
});
} else if (error) {
RCTLogWarn(@"Unable to download image data. Error: %@", error);
}
// TODO: handle errors
}];
} else {
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() block:^(UIImage *image, NSError *error) {
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() resizeMode:self.contentMode backgroundColor:self.backgroundColor block:^(UIImage *image, NSError *error) {
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (imageURL != self.imageURL) {
// Image has changed
return;
}
[self.layer removeAnimationForKey:@"contents"];
self.layer.contentsScale = image.scale;
self.layer.contents = (__bridge id)image.CGImage;
});
} else if (error) {
RCTLogWarn(@"Unable to download image. Error: %@", error);
}
// TODO: handle errors
}];
}
}
+10 -2
View File
@@ -33,9 +33,11 @@ RCT_CUSTOM_VIEW_PROPERTY(src, NSURL, RCTStaticImage)
if ([[[json description] pathExtension] caseInsensitiveCompare:@"gif"] == NSOrderedSame) {
[view.layer addAnimation:RCTGIFImageWithFileURL([RCTConvert NSURL:json]) forKey:@"contents"];
} else {
[view.layer removeAnimationForKey:@"contents"];
view.image = [RCTConvert UIImage:json];
}
} else {
[view.layer removeAnimationForKey:@"contents"];
view.image = defaultView.image;
}
}
@@ -52,13 +54,19 @@ RCT_CUSTOM_VIEW_PROPERTY(tintColor, UIColor, RCTStaticImage)
RCT_CUSTOM_VIEW_PROPERTY(imageTag, NSString, RCTStaticImage)
{
if (json) {
[RCTImageLoader loadImageWithTag:[RCTConvert NSString:json] callback:^(NSError *error, UIImage *image) {
[RCTImageLoader loadImageWithTag:[RCTConvert NSString:json] callback:^(NSError *error, id image) {
if (error) {
RCTLogWarn(@"%@", error.localizedDescription);
}
view.image = image;
if ([image isKindOfClass:[CAAnimation class]]) {
[view.layer addAnimation:image forKey:@"contents"];
} else {
[view.layer removeAnimationForKey:@"contents"];
view.image = image;
}
}];
} else {
[view.layer removeAnimationForKey:@"contents"];
view.image = defaultView.image;
}
}
@@ -12,9 +12,10 @@ jest
.dontMock('AssetRegistry')
.dontMock('../resolveAssetSource');
var resolveAssetSource;
var SourceCode;
var AssetRegistry;
var Platform;
var SourceCode;
var resolveAssetSource;
function expectResolvesAsset(input, expectedSource) {
var assetId = AssetRegistry.registerAsset(input);
@@ -24,8 +25,9 @@ function expectResolvesAsset(input, expectedSource) {
describe('resolveAssetSource', () => {
beforeEach(() => {
jest.resetModuleRegistry();
SourceCode = require('NativeModules').SourceCode;
AssetRegistry = require('AssetRegistry');
Platform = require('Platform');
SourceCode = require('NativeModules').SourceCode;
resolveAssetSource = require('../resolveAssetSource');
});
@@ -59,7 +61,7 @@ describe('resolveAssetSource', () => {
expect(resolveAssetSource('nonsense')).toBe(null);
});
describe('bundle was loaded from network', () => {
describe('bundle was loaded from network (DEV)', () => {
beforeEach(() => {
SourceCode.scriptURL = 'http://10.0.0.1:8081/main.bundle';
});
@@ -104,9 +106,21 @@ describe('resolveAssetSource', () => {
});
describe('bundle was loaded from file', () => {
describe('bundle was loaded from file (PROD) on iOS', () => {
var originalDevMode;
var originalPlatform;
beforeEach(() => {
SourceCode.scriptURL = 'file:///Path/To/Simulator/main.bundle';
originalDevMode = __DEV__;
originalPlatform = Platform.OS;
__DEV__ = false;
Platform.OS = 'ios';
});
afterEach(() => {
__DEV__ = originalDevMode;
Platform.OS = originalPlatform;
});
it('uses pre-packed image', () => {
@@ -129,6 +143,43 @@ describe('resolveAssetSource', () => {
});
});
describe('bundle was loaded from file (PROD) on Android', () => {
var originalDevMode;
var originalPlatform;
beforeEach(() => {
SourceCode.scriptURL = 'file:///Path/To/Simulator/main.bundle';
originalDevMode = __DEV__;
originalPlatform = Platform.OS;
__DEV__ = false;
Platform.OS = 'android';
});
afterEach(() => {
__DEV__ = originalDevMode;
Platform.OS = originalPlatform;
});
it('uses pre-packed image', () => {
expectResolvesAsset({
__packager_asset: true,
fileSystemLocation: '/root/app/module/a',
httpServerLocation: '/assets/AwesomeModule/Subdir',
width: 100,
height: 200,
scales: [1],
hash: '5b6f00f',
name: '!@Logo#1_€', // Invalid chars shouldn't get passed to native
type: 'png',
}, {
isStatic: true,
width: 100,
height: 200,
uri: 'assets_awesomemodule_subdir_logo1_',
});
});
});
});
describe('resolveAssetSource.pickScale', () => {
+63 -17
View File
@@ -7,22 +7,31 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule resolveAssetSource
*
* Resolves an asset into a `source` for `Image`.
*/
'use strict';
var AssetRegistry = require('AssetRegistry');
var PixelRatio = require('PixelRatio');
var Platform = require('Platform');
var SourceCode = require('NativeModules').SourceCode;
var _serverURL;
function getServerURL() {
function getDevServerURL() {
if (!__DEV__) {
// In prod we want assets to be loaded from the archive
return null;
}
if (_serverURL === undefined) {
var scriptURL = SourceCode.scriptURL;
var match = scriptURL && scriptURL.match(/^https?:\/\/.*?\//);
if (match) {
// Bundle was loaded from network
_serverURL = match[0];
} else {
// Bundle was loaded from file
_serverURL = null;
}
}
@@ -30,6 +39,55 @@ function getServerURL() {
return _serverURL;
}
/**
* Returns the path at which the asset can be found in the archive
*/
function getPathInArchive(asset) {
if (Platform.OS === 'android') {
var assetDir = getBasePath(asset);
// E.g. 'assets_awesomemodule_icon'
// The Android resource system picks the correct scale.
return (assetDir + '/' + asset.name)
.toLowerCase()
.replace(/\//g, '_') // Encode folder structure in file name
.replace(/([^a-z0-9_])/g, ''); // Remove illegal chars
} else {
// E.g. 'assets/AwesomeModule/icon@2x.png'
return getScaledAssetPath(asset);
}
}
/**
* Returns an absolute URL which can be used to fetch the asset
* from the devserver
*/
function getPathOnDevserver(devServerUrl, asset) {
return devServerUrl + getScaledAssetPath(asset) + '?hash=' + asset.hash;
}
/**
* Returns a path like 'assets/AwesomeModule'
*/
function getBasePath(asset) {
// TODO(frantic): currently httpServerLocation is used both as
// path in http URL and path within IPA. Should we have zipArchiveLocation?
var path = asset.httpServerLocation;
if (path[0] === '/') {
path = path.substr(1);
}
return path;
}
/**
* Returns a path like 'assets/AwesomeModule/icon@2x.png'
*/
function getScaledAssetPath(asset) {
var scale = pickScale(asset.scales, PixelRatio.get());
var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x';
var assetDir = getBasePath(asset);
return assetDir + '/' + asset.name + scaleSuffix + '.' + asset.type;
}
function pickScale(scales, deviceScale) {
// Packager guarantees that `scales` array is sorted
for (var i = 0; i < scales.length; i++) {
@@ -58,31 +116,19 @@ function resolveAssetSource(source) {
}
function assetToImageSource(asset) {
// TODO(frantic): currently httpServerLocation is used both as
// path in http URL and path within IPA. Should we have zipArchiveLocation?
var path = asset.httpServerLocation;
if (path[0] === '/') {
path = path.substr(1);
}
var scale = pickScale(asset.scales, PixelRatio.get());
var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x';
var fileName = asset.name + scaleSuffix + '.' + asset.type;
var serverURL = getServerURL();
if (serverURL) {
var devServerURL = getDevServerURL();
if (devServerURL) {
return {
width: asset.width,
height: asset.height,
uri: serverURL + path + '/' + fileName +
'?hash=' + asset.hash,
uri: getPathOnDevserver(devServerURL, asset),
isStatic: false,
};
} else {
return {
width: asset.width,
height: asset.height,
uri: path + '/' + fileName,
uri: getPathInArchive(asset),
isStatic: true,
};
}
+32 -2
View File
@@ -19,6 +19,13 @@ var invariant = require('invariant');
var keyMirror = require('keyMirror');
var setImmediate = require('setImmediate');
type Handle = number;
/**
* Maximum time a handle can be open before warning in DEV.
*/
var DEV_TIMEOUT = 2000;
var _emitter = new EventEmitter();
var _interactionSet = new Set();
var _addInteractionSet = new Set();
@@ -83,17 +90,25 @@ var InteractionManager = {
/**
* Notify manager that an interaction has started.
*/
createInteractionHandle(): number {
createInteractionHandle(): Handle {
scheduleUpdate();
var handle = ++_inc;
_addInteractionSet.add(handle);
if (__DEV__) {
// Capture the stack trace of what created the handle.
var error = new Error(
'InteractionManager: interaction handle not cleared within ' +
DEV_TIMEOUT + ' ms.'
);
setDevTimeoutHandle(handle, error, DEV_TIMEOUT);
}
return handle;
},
/**
* Notify manager that an interaction has completed.
*/
clearInteractionHandle(handle: number) {
clearInteractionHandle(handle: Handle) {
invariant(
!!handle,
'Must provide a handle to clear.'
@@ -151,4 +166,19 @@ function processUpdate() {
_deleteInteractionSet.clear();
}
/**
* Wait until `timeout` has passed and warn if the handle has not been cleared.
*/
function setDevTimeoutHandle(
handle: Handle,
error: Error,
timeout: number
): void {
setTimeout(() => {
if (_interactionSet.has(handle)) {
console.warn(error.message + '\n' + error.stack);
}
}, timeout);
}
module.exports = InteractionManager;
@@ -25,26 +25,39 @@ type Exception = {
message: string;
}
function reportException(e: Exception, stack?: any) {
function reportException(e: Exception, isFatal: bool, stack?: any) {
if (RCTExceptionsManager) {
if (!stack) {
stack = parseErrorStack(e);
}
RCTExceptionsManager.reportUnhandledException(e.message, stack);
if (!RCTExceptionsManager.reportFatalException ||
!RCTExceptionsManager.reportSoftException) {
// Backwards compatibility - no differentiation
// TODO(#7049989): deprecate reportUnhandledException on Android
RCTExceptionsManager.reportUnhandledException(e.message, stack);
} else {
if (isFatal) {
RCTExceptionsManager.reportFatalException(e.message, stack);
} else {
RCTExceptionsManager.reportSoftException(e.message, stack);
}
}
if (__DEV__) {
(sourceMapPromise = sourceMapPromise || loadSourceMap())
.then(map => {
var prettyStack = parseErrorStack(e, map);
RCTExceptionsManager.updateExceptionMessage(e.message, prettyStack);
})
.then(null, error => {
console.error('#CLOWNTOWN (error while displaying error): ' + error.message);
.catch(error => {
// This can happen in a variety of normal situations, such as
// Network module not being available, or when running locally
console.warn('Unable to load source map: ' + error.message);
});
}
}
}
function handleException(e: Exception) {
function handleException(e: Exception, isFatal: boolean) {
var stack = parseErrorStack(e);
var msg =
'Error: ' + e.message +
@@ -57,7 +70,7 @@ function handleException(e: Exception) {
} else {
console.error(msg);
}
reportException(e, stack);
reportException(e, isFatal, stack);
}
/**
@@ -78,7 +91,7 @@ function installConsoleErrorReporter() {
var str = Array.prototype.map.call(arguments, stringifySafe).join(', ');
var error: any = new Error('console.error: ' + str);
error.framesToPop = 1;
reportException(error);
reportException(error, /* isFatal */ false);
};
if (console.reportErrorsAsExceptions === undefined) {
console.reportErrorsAsExceptions = true; // Individual apps can disable this
@@ -33,53 +33,20 @@ if (typeof window === 'undefined') {
window = GLOBAL;
}
/**
* The document must be shimmed before anything else that might define the
* `ExecutionEnvironment` module (which checks for `document.createElement`).
*/
function setupDocumentShim() {
// The browser defines Text and Image globals by default. If you forget to
// require them, then the error message is very confusing.
function getInvalidGlobalUseError(name) {
return new Error(
'You are trying to render the global ' + name + ' variable as a ' +
'React element. You probably forgot to require ' + name + '.'
);
}
GLOBAL.Text = {
get defaultProps() {
throw getInvalidGlobalUseError('Text');
}
};
GLOBAL.Image = {
get defaultProps() {
throw getInvalidGlobalUseError('Image');
}
};
// Force `ExecutionEnvironment.canUseDOM` to be false.
if (GLOBAL.document) {
GLOBAL.document.createElement = null;
}
// There is no DOM so MutationObserver doesn't make sense. It is used
// as feature detection in Bluebird Promise implementation
GLOBAL.MutationObserver = undefined;
}
function handleErrorWithRedBox(e) {
function handleErrorWithRedBox(e, isFatal) {
try {
require('ExceptionsManager').handleException(e);
require('ExceptionsManager').handleException(e, isFatal);
} catch(ee) {
console.log('Failed to print error: ', ee.message);
}
}
function setupRedBoxErrorHandler() {
function setUpRedBoxErrorHandler() {
var ErrorUtils = require('ErrorUtils');
ErrorUtils.setGlobalHandler(handleErrorWithRedBox);
}
function setupRedBoxConsoleErrorHandler() {
function setUpRedBoxConsoleErrorHandler() {
// ExceptionsManager transitively requires Promise so we install it after
var ExceptionsManager = require('ExceptionsManager');
var Platform = require('Platform');
@@ -96,7 +63,7 @@ function setupRedBoxConsoleErrorHandler() {
* implement our own custom timing bridge that should be immune to
* unexplainably dropped timing signals.
*/
function setupTimers() {
function setUpTimers() {
var JSTimers = require('JSTimers');
GLOBAL.setTimeout = JSTimers.setTimeout;
GLOBAL.setInterval = JSTimers.setInterval;
@@ -111,7 +78,7 @@ function setupTimers() {
};
}
function setupAlert() {
function setUpAlert() {
var RCTAlertManager = require('NativeModules').AlertManager;
if (!GLOBAL.alert) {
GLOBAL.alert = function(text) {
@@ -125,13 +92,13 @@ function setupAlert() {
}
}
function setupPromise() {
function setUpPromise() {
// The native Promise implementation throws the following error:
// ERROR: Event loop not supported.
GLOBAL.Promise = require('Promise');
}
function setupXHR() {
function setUpXHR() {
// The native XMLHttpRequest in Chrome dev tools is CORS aware and won't
// let you fetch anything from the internet
GLOBAL.XMLHttpRequest = require('XMLHttpRequest');
@@ -143,16 +110,26 @@ function setupXHR() {
GLOBAL.Response = fetchPolyfill.Response;
}
function setupGeolocation() {
function setUpGeolocation() {
GLOBAL.navigator = GLOBAL.navigator || {};
GLOBAL.navigator.geolocation = require('Geolocation');
}
setupDocumentShim();
setupRedBoxErrorHandler();
setupTimers();
setupAlert();
setupPromise();
setupXHR();
setupRedBoxConsoleErrorHandler();
setupGeolocation();
function setUpWebSockets() {
GLOBAL.WebSocket = require('WebSocket');
}
function setupProfile() {
console.profile = console.profile || GLOBAL.consoleProfile || function () {};
console.profileEnd = console.profileEnd || GLOBAL.consoleProfileEnd || function () {};
}
setUpRedBoxErrorHandler();
setUpTimers();
setUpAlert();
setUpPromise();
setUpXHR();
setUpRedBoxConsoleErrorHandler();
setUpGeolocation();
setUpWebSockets();
setupProfile();
@@ -18,6 +18,7 @@
* and wrapping resulting file into `wrapper` function.
*
*/
/*eslint-disable */
var scope = {};
wrapper.call(scope);
@@ -13,10 +13,13 @@
'use strict';
var Promise = require('Promise');
var RCTSourceCode = require('NativeModules').SourceCode;
var NativeModules = require('NativeModules');
var SourceMapConsumer = require('SourceMap').SourceMapConsumer;
var SourceMapURL = require('./source-map-url');
var RCTSourceCode = NativeModules.SourceCode;
var RCTDataManager = NativeModules.DataManager;
function loadSourceMap(): Promise {
return fetchSourceMap()
.then(map => new SourceMapConsumer(map));
@@ -31,17 +34,31 @@ function fetchSourceMap(): Promise {
return Promise.reject(new Error('RCTSourceCode module is not available'));
}
if (!RCTDataManager) {
// Used internally by fetch
return Promise.reject(new Error('RCTDataManager module is not available'));
}
return new Promise(RCTSourceCode.getScriptText)
.then(extractSourceMapURL)
.then((url) => {
if (url === null) {
return Promise.reject(new Error('No source map URL found. May be running from bundled file.'));
}
return Promise.resolve(url);
})
.then(fetch)
.then(response => response.text())
}
function extractSourceMapURL({url, text, fullSourceMappingURL}): string {
function extractSourceMapURL({url, text, fullSourceMappingURL}): ?string {
if (fullSourceMappingURL) {
return fullSourceMappingURL;
}
var mapURL = SourceMapURL.getFrom(text);
if (!mapURL) {
return null;
}
var baseURL = url.match(/(.+:\/\/.*?)\//)[1];
return baseURL + mapURL;
}
@@ -11,6 +11,7 @@
*
* @nolint
*/
/* eslint-disable */
(function() {
var define = null; // Hack to make it work with our packager
@@ -43,7 +43,6 @@ var JSTimers = {
var newID = JSTimersExecution.GUID++;
var freeIndex = JSTimers._getFreeIndex();
JSTimersExecution.timerIDs[freeIndex] = newID;
JSTimersExecution.callbacks[freeIndex] = func;
JSTimersExecution.callbacks[freeIndex] = function() {
return func.apply(undefined, args);
};
@@ -60,12 +59,15 @@ var JSTimers = {
var newID = JSTimersExecution.GUID++;
var freeIndex = JSTimers._getFreeIndex();
JSTimersExecution.timerIDs[freeIndex] = newID;
JSTimersExecution.callbacks[freeIndex] = func;
JSTimersExecution.callbacks[freeIndex] = function() {
return func.apply(undefined, args);
var startTime = Date.now();
var ret = func.apply(undefined, args);
var endTime = Date.now();
RCTTiming.createTimer(newID, Math.max(0, duration - (endTime - startTime)), endTime, false);
return ret;
};
JSTimersExecution.types[freeIndex] = JSTimersExecution.Type.setInterval;
RCTTiming.createTimer(newID, duration, Date.now(), /** recurring */ true);
RCTTiming.createTimer(newID, duration, Date.now(), /** recurring */ false);
return newID;
},
@@ -77,7 +79,6 @@ var JSTimers = {
var newID = JSTimersExecution.GUID++;
var freeIndex = JSTimers._getFreeIndex();
JSTimersExecution.timerIDs[freeIndex] = newID;
JSTimersExecution.callbacks[freeIndex] = func;
JSTimersExecution.callbacks[freeIndex] = function() {
return func.apply(undefined, args);
};
@@ -0,0 +1,34 @@
/* eslint global-strict: 0 */
(function(GLOBAL) {
/**
* The document must be shimmed before anything else that might define the
* `ExecutionEnvironment` module (which checks for `document.createElement`).
*/
// The browser defines Text and Image globals by default. If you forget to
// require them, then the error message is very confusing.
function getInvalidGlobalUseError(name) {
return new Error(
'You are trying to render the global ' + name + ' variable as a ' +
'React element. You probably forgot to require ' + name + '.'
);
}
GLOBAL.Text = {
get defaultProps() {
throw getInvalidGlobalUseError('Text');
}
};
GLOBAL.Image = {
get defaultProps() {
throw getInvalidGlobalUseError('Image');
}
};
// Force `ExecutionEnvironment.canUseDOM` to be false.
if (GLOBAL.document) {
GLOBAL.document.createElement = null;
}
// There is no DOM so MutationObserver doesn't make sense. It is used
// as feature detection in Bluebird Promise implementation
GLOBAL.MutationObserver = undefined;
})(this);
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule RCTNativeAppEventEmitter
* @flow
*/
'use strict';
var EventEmitter = require('EventEmitter');
var RCTNativeAppEventEmitter = new EventEmitter();
module.exports = RCTNativeAppEventEmitter;
+5 -5
View File
@@ -15,13 +15,13 @@
var NativeMethodsMixin = require('NativeMethodsMixin');
var React = require('React');
var ReactChildren = require('ReactChildren');
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var RCTPickerIOSConsts = require('NativeModules').UIManager.RCTPicker.Constants;
var StyleSheet = require('StyleSheet');
var View = require('View');
var createReactIOSNativeComponentClass =
require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass =
require('createReactNativeComponentClass');
var merge = require('merge');
var PICKER = 'picker';
@@ -112,12 +112,12 @@ var styles = StyleSheet.create({
},
});
var rkPickerIOSAttributes = merge(ReactIOSViewAttributes.UIView, {
var rkPickerIOSAttributes = merge(ReactNativeViewAttributes.UIView, {
items: true,
selectedIndex: true,
});
var RCTPickerIOS = createReactIOSNativeComponentClass({
var RCTPickerIOS = createReactNativeComponentClass({
validAttributes: rkPickerIOSAttributes,
uiViewClassName: 'RCTPicker',
});
@@ -11,7 +11,6 @@
*/
'use strict';
var NativeModules = require('NativeModules');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var RCTPushNotificationManager = require('NativeModules').PushNotificationManager;
var invariant = require('invariant');
+6
View File
@@ -11,6 +11,7 @@
#import "FBSnapshotTestController.h"
#import "RCTAssert.h"
#import "RCTEventDispatcher.h"
#import "RCTLog.h"
#import "RCTUIManager.h"
@@ -63,4 +64,9 @@ RCT_EXPORT_METHOD(markTestCompleted)
}];
}
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(id)body)
{
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
}
@end
@@ -1,132 +0,0 @@
//
// Copyright 2012 Square Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import <Foundation/Foundation.h>
#import <Security/SecCertificate.h>
typedef enum {
SR_CONNECTING = 0,
SR_OPEN = 1,
SR_CLOSING = 2,
SR_CLOSED = 3,
} SRReadyState;
typedef enum SRStatusCode : NSInteger {
SRStatusCodeNormal = 1000,
SRStatusCodeGoingAway = 1001,
SRStatusCodeProtocolError = 1002,
SRStatusCodeUnhandledType = 1003,
// 1004 reserved.
SRStatusNoStatusReceived = 1005,
// 1004-1006 reserved.
SRStatusCodeInvalidUTF8 = 1007,
SRStatusCodePolicyViolated = 1008,
SRStatusCodeMessageTooBig = 1009,
} SRStatusCode;
@class SRWebSocket;
extern NSString *const SRWebSocketErrorDomain;
extern NSString *const SRHTTPResponseErrorKey;
#pragma mark - SRWebSocketDelegate
@protocol SRWebSocketDelegate;
#pragma mark - SRWebSocket
@interface SRWebSocket : NSObject <NSStreamDelegate>
@property (nonatomic, weak) id <SRWebSocketDelegate> delegate;
@property (nonatomic, readonly) SRReadyState readyState;
@property (nonatomic, readonly, retain) NSURL *url;
// This returns the negotiated protocol.
// It will be nil until after the handshake completes.
@property (nonatomic, readonly, copy) NSString *protocol;
// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol.
- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols;
- (id)initWithURLRequest:(NSURLRequest *)request;
// Some helper constructors.
- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols;
- (id)initWithURL:(NSURL *)url;
// Delegate queue will be dispatch_main_queue by default.
// You cannot set both OperationQueue and dispatch_queue.
- (void)setDelegateOperationQueue:(NSOperationQueue*) queue;
- (void)setDelegateDispatchQueue:(dispatch_queue_t) queue;
// By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes.
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
// SRWebSockets are intended for one-time-use only. Open should be called once and only once.
- (void)open;
- (void)close;
- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason;
// Send a UTF8 String or Data.
- (void)send:(id)data;
// Send Data (can be nil) in a ping message.
- (void)sendPing:(NSData *)data;
@end
#pragma mark - SRWebSocketDelegate
@protocol SRWebSocketDelegate <NSObject>
// message will either be an NSString if the server is using text
// or NSData if the server is using binary.
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
@optional
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload;
@end
#pragma mark - NSURLRequest (CertificateAdditions)
@interface NSURLRequest (CertificateAdditions)
@property (nonatomic, retain, readonly) NSArray *SR_SSLPinnedCertificates;
@end
#pragma mark - NSMutableURLRequest (CertificateAdditions)
@interface NSMutableURLRequest (CertificateAdditions)
@property (nonatomic, retain) NSArray *SR_SSLPinnedCertificates;
@end
#pragma mark - NSRunLoop (SRWebSocket)
@interface NSRunLoop (SRWebSocket)
+ (NSRunLoop *)SR_networkRunLoop;
@end
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -11,7 +11,7 @@
*/
'use strict';
var ReactIOSTagHandles = require('ReactIOSTagHandles');
var ReactNativeTagHandles = require('ReactNativeTagHandles');
var RCTUIManager = require('NativeModules').UIManager;
type OnSuccessCallback = (
@@ -52,10 +52,9 @@ var queryLayoutByID = function(
): void {
// Native bridge doesn't *yet* surface errors.
RCTUIManager.measure(
ReactIOSTagHandles.rootNodeIDToTag[rootNodeID],
ReactNativeTagHandles.rootNodeIDToTag[rootNodeID],
onSuccess
);
};
module.exports = queryLayoutByID;
@@ -9,8 +9,7 @@
* @providesModule IOSNativeBridgeEventPlugin
* @flow
*/
"use strict";
'use strict';
var EventPropagators = require('EventPropagators');
var NativeModules = require('NativeModules');
@@ -33,7 +32,7 @@ for (var bubblingTypeName in customBubblingEventTypes) {
for (var directTypeName in customDirectEventTypes) {
warning(
!customBubblingEventTypes[directTypeName],
"Event cannot be both direct and bubbling: %s",
'Event cannot be both direct and bubbling: %s',
directTypeName
);
allTypesByEventName[directTypeName] = customDirectEventTypes[directTypeName];
@@ -76,4 +75,3 @@ var IOSNativeBridgeEventPlugin = {
};
module.exports = IOSNativeBridgeEventPlugin;
+30 -9
View File
@@ -16,6 +16,7 @@ var RCTPOPAnimationManager = NativeModules.POPAnimationManager;
var RCTUIManager = NativeModules.UIManager;
var TextInputState = require('TextInputState');
var findNodeHandle = require('findNodeHandle');
var flattenStyle = require('flattenStyle');
var invariant = require('invariant');
var mergeFast = require('mergeFast');
@@ -51,16 +52,23 @@ var animationIDInvariant = function(
var NativeMethodsMixin = {
addAnimation: function(anim: number, callback?: (finished: bool) => void) {
animationIDInvariant('addAnimation', anim);
RCTPOPAnimationManager.addAnimation(this.getNodeHandle(), anim, callback);
RCTPOPAnimationManager.addAnimation(
findNodeHandle(this),
anim,
mountSafeCallback(this, callback)
);
},
removeAnimation: function(anim: number) {
animationIDInvariant('removeAnimation', anim);
RCTPOPAnimationManager.removeAnimation(this.getNodeHandle(), anim);
RCTPOPAnimationManager.removeAnimation(findNodeHandle(this), anim);
},
measure: function(callback: MeasureOnSuccessCallback) {
RCTUIManager.measure(this.getNodeHandle(), callback);
RCTUIManager.measure(
findNodeHandle(this),
mountSafeCallback(this, callback)
);
},
measureLayout: function(
@@ -69,10 +77,10 @@ var NativeMethodsMixin = {
onFail: () => void /* currently unused */
) {
RCTUIManager.measureLayout(
this.getNodeHandle(),
findNodeHandle(this),
relativeToNativeNode,
onFail,
onSuccess
mountSafeCallback(this, onFail),
mountSafeCallback(this, onSuccess)
);
},
@@ -106,18 +114,18 @@ var NativeMethodsMixin = {
}
RCTUIManager.updateView(
this.getNodeHandle(),
findNodeHandle(this),
this.viewConfig.uiViewClassName,
props
);
},
focus: function() {
TextInputState.focusTextInput(this.getNodeHandle());
TextInputState.focusTextInput(findNodeHandle(this));
},
blur: function() {
TextInputState.blurTextInput(this.getNodeHandle());
TextInputState.blurTextInput(findNodeHandle(this));
}
};
@@ -152,4 +160,17 @@ if (__DEV__) {
};
}
/**
* In the future, we should cleanup callbacks by cancelling them instead of
* using this.
*/
var mountSafeCallback = function(context: ReactComponent, callback: ?Function): any {
return function() {
if (!callback || (context.isMounted && !context.isMounted())) {
return;
}
return callback.apply(context, arguments);
};
};
module.exports = NativeMethodsMixin;
@@ -1,79 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactIOSComponentMixin
* @flow
*/
'use strict';
var ReactIOSTagHandles = require('ReactIOSTagHandles');
var ReactInstanceMap = require('ReactInstanceMap');
/**
* ReactNative vs ReactWeb
* -----------------------
* React treats some pieces of data opaquely. This means that the information
* is first class (it can be passed around), but cannot be inspected. This
* allows us to build infrastructure that reasons about resources, without
* making assumptions about the nature of those resources, and this allows that
* infra to be shared across multiple platforms, where the resources are very
* different. General infra (such as `ReactMultiChild`) reasons opaquely about
* the data, but platform specific code (such as `ReactIOSNativeComponent`) can
* make assumptions about the data.
*
*
* `rootNodeID`, uniquely identifies a position in the generated native view
* tree. Many layers of composite components (created with `React.createClass`)
* can all share the same `rootNodeID`.
*
* `nodeHandle`: A sufficiently unambiguous way to refer to a lower level
* resource (dom node, native view etc). The `rootNodeID` is sufficient for web
* `nodeHandle`s, because the position in a tree is always enough to uniquely
* identify a DOM node (we never have nodes in some bank outside of the
* document). The same would be true for `ReactNative`, but we must maintain a
* mapping that we can send efficiently serializable
* strings across native boundaries.
*
* Opaque name TodaysWebReact FutureWebWorkerReact ReactNative
* ----------------------------------------------------------------------------
* nodeHandle N/A rootNodeID tag
*
*
* `mountImage`: A way to represent the potential to create lower level
* resources whos `nodeHandle` can be discovered immediately by knowing the
* `rootNodeID`. Today's web React represents this with `innerHTML` annotated
* with DOM ids that match the `rootNodeID`.
*
* Opaque name TodaysWebReact FutureWebWorkerReact ReactNative
* ----------------------------------------------------------------------------
* mountImage innerHTML innerHTML {rootNodeID, tag}
*
*/
var ReactIOSComponentMixin = {
/**
* This has no particular meaning in ReactIOS. If this were in the DOM, this
* would return the DOM node. There should be nothing that invokes this
* method. Any current callers of this are mistaken - they should be invoking
* `getNodeHandle`.
*/
getNativeNode: function() {
// TODO (balpert): Wrap iOS native components in a composite wrapper, then
// ReactInstanceMap.get here will always succeed
return ReactIOSTagHandles.rootNodeIDToTag[
(ReactInstanceMap.get(this) || this)._rootNodeID
];
},
getNodeHandle: function() {
return ReactIOSTagHandles.rootNodeIDToTag[
(ReactInstanceMap.get(this) || this)._rootNodeID
];
}
};
module.exports = ReactIOSComponentMixin;
+2 -2
View File
@@ -14,7 +14,7 @@
var RCTUIManager = require('NativeModules').UIManager;
var UnimplementedView = require('UnimplementedView');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var createReactNativeComponentClass = require('createReactNativeComponentClass');
var deepDiffer = require('deepDiffer');
var insetsDiffer = require('insetsDiffer');
var pointsDiffer = require('pointsDiffer');
@@ -59,7 +59,7 @@ function requireNativeComponent(
if (__DEV__) {
wrapperComponent && verifyPropTypes(wrapperComponent, viewConfig);
}
return createReactIOSNativeComponentClass(viewConfig);
return createReactNativeComponentClass(viewConfig);
}
var TypeToDifferMap = {
+11 -4
View File
@@ -11,7 +11,7 @@
*/
'use strict';
var ReactIOSStyleAttributes = require('ReactIOSStyleAttributes');
var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
var View = require('View');
function verifyPropTypes(
@@ -22,16 +22,23 @@ function verifyPropTypes(
if (!viewConfig) {
return; // This happens for UnimplementedView.
}
var componentName = component.name || component.displayName;
if (!component.propTypes) {
throw new Error(
'`' + componentName + '` has no propTypes defined`'
);
}
var nativeProps = viewConfig.nativeProps;
for (var prop in nativeProps) {
if (!component.propTypes[prop] &&
!View.propTypes[prop] &&
!ReactIOSStyleAttributes[prop] &&
!ReactNativeStyleAttributes[prop] &&
(!nativePropsToIgnore || !nativePropsToIgnore[prop])) {
throw new Error(
'`' + component.displayName + '` has no propType for native prop `' +
'`' + componentName + '` has no propType for native prop `' +
viewConfig.uiViewClassName + '.' + prop + '` of native type `' +
nativeProps[prop].type + '`'
nativeProps[prop] + '`'
);
}
}

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