Compare commits

...
299 Commits
Author SHA1 Message Date
James Ide 56563f13b3 [0.11.4] Add iOS stubs for Android modules 2015-09-28 12:21:57 -07:00
James Ide 0a08879d70 [Android/iOS] Add .iOS.js stubs for Android components 2015-09-28 12:20:28 -07:00
James Ide b890969b1e [0.11.3] Add Android exports 2015-09-28 05:02:28 -07:00
James Ide 3bc5b180b1 [Android] Export Android-specific modules 2015-09-28 05:01:55 -07:00
James Ide 5fbe29903b [0.11.2] displayName fixes + Android bundled 2015-09-24 11:44:24 -07:00
Martin Konicek 7cc3ba99e0 Add Android code to the 0.11-stable branch.
Cherry-picked https://github.com/facebook/react-native/commit/42eb5464fd8a65ed84b799de5d4dc225349449be
2015-09-24 13:55:23 +01:00
James Ide 77167b02ee [0.11.1]
- Added react.displayName to the packager.
2015-09-22 15:42:55 -07:00
James Ide aed1c76576 [Packager] Bump the cache breakers for the react.displayName transform 2015-09-22 15:42:28 -07:00
Ben Alpert 8187e9153c [ReactNative] Enable displayName transformer in open source 2015-09-22 15:41:54 -07:00
Martin Konicek c98a6fbde1 [0.11] Bump pod version 2015-09-15 21:24:16 +01:00
James Ide e1032e1d09 [0.11.0] 2015-09-14 18:23:33 -07:00
Amjad Masad 0c2f3fe145 Refactor DependencyResolver into request/response
Reviewed By: @martinbigio

Differential Revision: D2425842

Conflicts:
	packager/react-packager/src/Bundler/index.js
	packager/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js
2015-09-11 18:11:58 -07:00
Amjad Masad 329f059ba9 [react-packager] Support platform extensions in image requires
Summary:
We don't currently support platform extensions in asset modules.
This adds supports for it:

```
require('./a.png');
```

Will require 'a.ios.png' if it exists and 'a.png' if it doesn't.
2015-09-11 18:01:53 -07:00
James Ide 2d8ec5eca7 [npm] Update to stacktrace-parser@0.1.3 and ws@0.8.0 to satisfy io.js 3 / Node 4
Summary:
The previous version of stacktrace-parser 0.1.2 had an line in its package.json file that required Node <= 2.x. That line was removed, so it no longer warns on io.js 3.x or Node 4.x.

Similarly, ws 0.8.0 was published with support for the new V8, so it compiles with io.js 3.x and therefore should work with Node 4.x.

Updated the Travis file as well to run on io.js 3.x.

Fixes #2258, #2455

Closes https://github.com/facebook/react-native/pull/2398
Github Author: James Ide <ide@jameside.com>
2015-09-08 13:30:57 -07:00
Martin Konicek 6edb671e2d 0.11.0-rc 2015-08-26 17:28:18 +01:00
Martin Konicek 6d78b75a10 Update CONTRIBUTING.md 2015-08-26 17:04:53 +01:00
Martin Konicek a0c3b426de Update react-native-cli/CONTRIBUTING.md 2015-08-26 16:35:03 +01:00
Martin Konicek 9576657b57 Update react-native-cli/CONTRIBUTING.md 2015-08-26 16:04:48 +01:00
Martin Konicek dd9bbb4bca Update react-native-cli/CONTRIBUTING.md 2015-08-26 16:02:43 +01:00
Martin Konicek 57adecc36e Merge pull request #2443 from mkonicek/Updates_Wed_26_Aug
Updates from Wed 26 Aug
2015-08-26 14:23:12 +01:00
Martin Konicek 5526533f51 Updates from Wed 26 Aug 2015-08-26 14:04:01 +01:00
Felix Oghină 626f828d54 [reactnative] remove platform option from oss packager 2015-08-26 04:49:41 -08:00
Andrei Coman a8f11d7115 [ReactNative] Add TouchableNativeFeedback to OSS 2015-08-26 01:31:52 -08:00
Amjad Masad 074069e465 [react-packager] Cleanup socket interface code 2015-08-25 17:36:08 -08:00
Amjad Masad 2b7dd4650f [react-native] bump create server timeout 2015-08-25 17:13:13 -08:00
Andy Street 162d12cfa4 [ReactNative][SyncDiff] Allow renderToHardwareTextureAndroid to be used outside of setNativeProps 2015-08-25 16:55:51 -08:00
Andy Street 504fa60168 [ReactNative][SyncDiff] AutoSync 2015-08-25 14:54:10 -08:00
Martin Konicek 0203f87ea3 Add chalk mock 2015-08-25 22:02:19 +01:00
Martin Konicek 2f6e7336cb Merge pull request #2435 from mkonicek/Updates_Tue_25_Aug_trois
Updates from Tuesday 25 August

JS test failure fix will follow.
2015-08-25 19:58:36 +01:00
Martin Konicek 19f922aa80 [cli] Fix iOS app template 2015-08-25 19:25:17 +01:00
Martin Konicek 480b5c9e2e [website] Fix website generation 2015-08-25 19:23:41 +01:00
Martin Konicek da7ac11c53 Updates from Tue 25 Aug 2015-08-25 19:21:59 +01:00
Martin Konicek 4f87ec5ce7 [ReactNative] Unbreak OSS packager JS tests 2015-08-25 10:18:39 -08:00
Natansh Verma 8d65367fbc Revert "[packager] Unbreak Bundler test" 2015-08-25 09:53:45 -08:00
Amjad Masad 54026024cc [react-packager] Expose a socket interface
Summary:
Buck (our build system) currently starts multiple packager instances for each target and may build multiple targets in parallel. This means we're paying startup costs and are duplicating the work. This enables us to start one instance of the packager and connect to it via socket to do all the work that needs to be done.

The way this is structured:

1. SocketServer: A server that listens on a socket path that is generated based on the server options
2. SocketClient: Interfaces with the server and exposes the operations that we support as methods
3. SocketInterface: Integration point and responsible for forking off the server
2015-08-25 09:37:08 -08:00
Alexey Lang 2d2252cd50 Use native initialAppState to init app_state for AppStateIOS. 2015-08-25 09:32:28 -08:00
Martin Konicek 245a5b8e8c [packager] Unbreak Bundler test 2015-08-25 09:24:42 -08:00
Matt Mahoney 36c1064033 [rn] Pass props when creating a view in RCTViewManager 2015-08-25 08:08:17 -08:00
Krzysztof Magiera 27a67c2434 [ReactNative] Respect --assets-dest in "download from server" mode 2015-08-25 07:22:05 -08:00
Martin Konicek 5f8c0613fe [ReactNative] Temporarily disable flow in TabBarItemIOS 2015-08-25 07:16:35 -08:00
Nick Lockwood 8497b5a66f Fixed tab bar snapshot test 2015-08-25 06:36:43 -08:00
Nick Lockwood 65a3c07cfe Fixed tab bar icon scale
Summary:
TabBarItemIOS supports setting the scale for base64-encoded images using an optional scale parameter, however this was broken due to the JS code only passing the uri, not the whole source object, to the native side.

(See: https://github.com/facebook/react-native/issues/2413)
2015-08-25 05:26:14 -08:00
Pieter De Baets 371aeceb72 Small perf improvement to RCTPerfStats and RCTBridgeModuleNameForClass 2015-08-25 04:48:39 -08:00
Nick Lockwood 072390ec5c Fixed SampleAppTests 2015-08-25 04:41:12 -08:00
Alex Akers 9aefd6bd6e Add keyboard-observing notifications 2015-08-25 03:49:13 -08:00
Tadeu Zagallo fe0143eb20 [ReactNative] Update JS profiler to be compatible with Android
Summary:
Use nativeTraceBeginSection and nativeTraceEndSection with a more dynamic signature
to be compatible with Android.
2015-08-25 02:25:29 -08:00
Nick Lockwood 4382c0e8f4 Fixed redbox rotation
Summary:
Added autoresizing constraints to the redbox layout so that it resizes correctly when the screen is rotated.
2015-08-25 02:20:26 -08:00
Nick Lockwood 88e0bbc469 Ran Convert > To Modern Objective C Syntax 2015-08-25 01:08:49 -08:00
Jing Chen a57353b2b4 [react-native] Make flow warn on timeout instead of redbox 2015-08-24 19:51:14 -08:00
Ben Alpert 75df3b537a Don't report failures to npm
Summary:
This suppresses this output from npm:

```
npm ERR! Failed at the react-native@0.9.0 start script './packager/packager.sh'.
npm ERR! This is most likely a problem with the react-native package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     ./packager/packager.sh
npm ERR! You can get their info via:
npm ERR!     npm owner ls react-native
```

We don't seem to have any automated scripts that rely on the exit code of npm start (or even call it at all).
Closes https://github.com/facebook/react-native/pull/2415
Github Author: Ben Alpert <balpert@fb.com>
2015-08-24 19:32:27 -08:00
Martín Bigio 9ba4697f02 [react-packager] Fix OSS tests 2015-08-24 18:49:05 -08:00
Amjad Masad a008704b51 [react-packager] Add bser to be used in a socket server implementation 2015-08-24 17:04:32 -08:00
Amjad Masad eb248e0b58 [react-packager] Implement transformer progress bar
Summary:
The transform step in currently the longest one in the bundling process. This adds a progress bar to track the transform progress.

{F23096660}
2015-08-24 16:09:34 -08:00
Amjad Masad 8c5626cd87 [react-packager] check in the progress module 2015-08-24 16:09:33 -08:00
Justin Spahr-Summers 94671df753 [JSCLegacyProfiler] Use generic iOS SDK instead of pinning to 8.3
Summary:
The path to the iOS 8.3 SDK does not exist when only Xcode 6.4 is installed. This uses a more general folder name, which (at least) the 8.4 SDK symlinks to.

I haven't verified this on Xcode 6.3, so I'd appreciate it if someone could confirm that this path exists there too! :)
2015-08-24 13:42:34 -08:00
Martin Konicek bb708769d4 [ReactNative] Fix sample apps 2015-08-24 11:48:10 -08:00
Andrei Coman ed0ca71be0 [SyncDiff] [react_native] Revamp text input example for oss 2015-08-22 14:23:30 -08:00
Andrei Coman 127b3292c1 [SyncDiff] [react_native] Add more oss examples 2015-08-22 03:34:33 -08:00
Andrei Coman 8cc7f7f99a [SyncDiff] [react_native] Add toolbar example to oss 2015-08-22 02:14:38 -08:00
Tim Yung af8a6a44b2 RN: Expose React.unstable_batchedUpdates
Summary:
Per @spicyj in facebook/relay#127, this exposes `unstable_batchedUpdates` in React Native the same way it is exposed in `ReactDOM`.
2015-08-21 15:24:56 -08:00
Christopher Chedeau 4b420cc095 Merge pull request #2399 from ide/nvm
[Travis] Put $PWD in front of nvm  (fixes npm install)
2015-08-21 14:58:19 -07:00
Andrei Coman 52abc759ff [SyncDiff] [react_native] Add TextExample to UIExplorer 2015-08-21 14:34:46 -07:00
Christopher Chedeau f3a165db4f [Logs] Name fs step
Summary:
There are two fs steps and it wasn't clear why. This now puts the right label:

```
[9:38:25 PM] <START> Building in-memory fs for JavaScript
[9:38:27 PM] <END>   Building in-memory fs for JavaScript (2030ms)
[9:38:27 PM] <START> Building in-memory fs for Assets
[9:38:27 PM] <END>   Building in-memory fs for Assets (615ms)
```
2015-08-21 14:29:05 -07:00
Pieter De Baets eab390aecb Cleanup bridge init, measure native module init time 2015-08-21 12:32:25 -07:00
James Ide f8f68176d5 [Travis] Put $PWD in front of nvm (fixes npm install)
There was a problem where NVM_DIR wasn't correctly configured, which meant that `npm install` was using whatever version of Node was on the system (0.12 in this case) despite having run `nvm use iojs-v2`. Fixing up NVM_DIR fixes the `npm install` errors and builds the native npm packages for the right version of Node.
2015-08-21 11:37:11 -07:00
Alex Kotliarskyi 8d07df4a22 [ReactNative] Unbreak debugger 2015-08-21 11:20:17 -07:00
Alexey Lang 3643c127a8 Fix fuzziness images in UIExplorer <Image> sample. 2015-08-21 10:58:47 -07:00
Martin Bigio 677f96c60e [react-packager] unbreak tests 2015-08-21 09:38:37 -07:00
Martín Bigio 320a9207f4 [react-packager] Avoid referring Module like objects in BundlesLayout
Summary:
The `BundlesLayout` will be used as a persistent index. As such, it would be easier to avoid having dependencies to `Module`, `Package`, `Asset`, etc. We're not using that information for now and if we happen to need to use it we could always fetch it using the `ModuleCache`.
2015-08-21 08:13:58 -07:00
Martin Konicek 934e7b9afd [ReactNative][oss] Make package.json in consistent with github 2015-08-21 08:09:21 -07:00
Martín Bigio d2f82b1dfd [react-packager] Move async dependencies to System.import
Summary:
We've decided to move the syntax for asynchronously requiring async dependencies. The new syntax works better with promises and therefore withe async/await as well. The new syntax looks like this: `System.import('moduleA').then(moduleA => {...});` or if you're using async/await you could simply do:
  let moduleA = await System.import('moduleA');
  new moduleA().someFunction();

If you need to require multiple dependencies just do:
  Promise
    .all([System.import('moduleA'), System.import('moduleB')])
    .then((moduleA, moduleB) => {...})

or the equivalent using async/await
2015-08-21 07:56:19 -07:00
Dorota Kapturkiewicz f128269da7 [ReactNative] make radiobutton work with accessibility 2015-08-21 07:23:04 -07:00
Nick Lockwood c27e5198e2 Add doc comment for mainScrollView 2015-08-21 04:00:03 -07:00
Bill Fisher debca6d24f [ReactNative] Pass events through to touchable handlers
Summary:
We want to be able to access the touch data within our components' event handlers, so we need to thread the event object all the way through to them.
2015-08-21 03:03:32 -07:00
Nick Lockwood 2cd02d94ff Converted RCTRedBox to a bridge module 2015-08-21 02:53:55 -07:00
Harrison Harnisch 46c6cde947 UI CPU and memory utilization graphs in Chrome debugging mode
Summary:
Chrome debugging UI is currently only showing connection state and logs in the console, leaving room for plenty of interesting information.

I've pushed the UI (using the same convention set by FPS -- UI/JS) CPU and memory utilization data over the debug Websocket and tapped into the existing stream of JS calls that get ran in V8.

The number of JS calls in a time interval is counted for all sub calls in a batch
https://github.com/hharnisc/react-native/blob/master/packager/debugger.html#L150

The last 5 batches of JS calls are displayed in a list format.

<img width="951" alt="screen shot 2015-07-19 at 7 34 00 pm" src="https://cloud.githubusercontent.com/assets/1388079/8769257/edc42f70-2e4d-11e5-8813-e86ef530a446.png">

Charts are created with [Chart.JS](https://github.com/nnnick/Chart.js) (MIT licensed).
Closes https://github.com/facebook/react-native/pull/2050
Github Author: Harrison Harnisch <hharnisc@gmail.com>
2015-08-21 02:11:45 -07:00
Amjad Masad 6debfce374 [react-native] Update graceful-fs and use it in _build_bundle.js 2015-08-20 23:58:51 -07:00
Eric Vicenti 6f17dba39b [ReactNative] Remove POPAnimation
Summary:
Thanks to @vjeux' work on Animated, we have transitioned away from POPAnimation entirely
2015-08-20 22:24:28 -07:00
Emily Janzer 4b28a847e6 [android] fix crash if breadcrumb refs don't exist 2015-08-20 19:08:16 -07:00
Amjad Masad 3bfa90e433 [react-packager] Fix error in template string and bump timeout
Summary:
Fix error in the template string (no plus, thinks it's a function).
And bump the timeout to 30 seconds because a file is taking more than 10 seconds `js/RKJSModules/Libraries/FBComponents/FBFed/FeedStoryFragments.js`
2015-08-20 15:29:38 -07:00
Christopher Chedeau febc03a38b [Logs] Don't print flow error twice
Summary:
Flow errors are already throwing an exception in js, no need to also console.error in the packager
2015-08-20 14:05:47 -07:00
Andy Street a0168a8c62 [ReactNative] [SyncDiff] Create new non-coalesceable event for when native should take the responder lock 2015-08-20 13:56:23 -07:00
Martín Bigio c1f90c1ecf [react-packager] Integration test for runServerHere.sh 2015-08-20 12:00:06 -07:00
Spencer Ahrens 5f91d404e1 [RN] Fix Animated tests 2015-08-20 10:28:49 -07:00
Martín Bigio 5de0796126 [react-packager] Introduce bundle IDs and keep track of parent/child
Summary:
Since JS doesn't have the guarantee that once a bundle is loaded it will stay in memory (and this is something we actually don't want to enforce to keep memmory usage low), we need to keep track of parent/child relationships on the packager to pass it down to native. As part of this diff, we also introduced an ID for each bundle. The ID for a child bundle is shynthetized as the bundleID of the parent module + an index which gets incremented every time a new bundle is created. For instance given this tree:

       a,b
    c       f
  d   e       g

the ID for `d` will be `bundle.0.1.2`, the one for e will be `bundle.0.1.3` and the one for `g` will be `bundle.0.5.6`. This information will be useful to figure out which bundles need to be loaded when a `require.ensure` is re-written.
2015-08-20 10:19:09 -07:00
Dorota Kapturkiewicz ed9b8c8b3b [ReactNative] Disable accessibility of RootView when dialog appears. Apply it for AdsManager. 2015-08-20 10:16:13 -07:00
Christopher Chedeau 1ca1a44a07 [Logs] Remove already registered warning 2015-08-20 09:46:10 -07:00
Dorota Kapturkiewicz b888e8db40 [ReactNative] make sending accessibility events from JS possible and fix dialog 2015-08-20 08:41:22 -07:00
Martin Konicek 0b5952a454 [ReactNative][oss] Open source NetworkingModule 2015-08-20 07:19:34 -07:00
Alexsander Akers ee82a195f7 Set padding on ModalFullscreenView to offset status bar frame 2015-08-20 07:10:34 -07:00
Tadeu Zagallo 81fdf3e532 [ReactNative] Change RCTProfile API to be compatible with systrace 2015-08-20 00:47:23 -07:00
Christopher Chedeau 16ddb1962a [ReactNative] Remove warning for <Image source={require('./image.jpg')} />
Summary:
require('./image.jpg') returns a number and therefore the propType is wrong. Adding it to the propType to fix the warning and dealing with flow which is completely broken for this.
2015-08-19 22:53:25 -07:00
Spencer Ahrens 059e605e49 [RN] Mark some internal animated stuff as protected 2015-08-19 21:16:38 -07:00
Christopher Chedeau cf617640f3 [OpenSource] Fix 2048
Summary:
There were two issues:
(1) it was using /Users/sahrens as a path
(2) needed to remove RCTAnimationExperimental which doesn't exist anymore and add RCTWebSocket
2015-08-19 20:23:20 -07:00
Christopher Chedeau dd7945ae37 [OpenSource] Fix TicTacToe
Summary:
Needed to link RCTWebSocketManager to the project as instructed by the following issue:
https://github.com/facebook/react-native/issues/2256
2015-08-19 20:05:13 -07:00
Jing Chen cc96962e3d [react-native] Revert D2346396 to bring back JS stack traces 2015-08-19 18:07:15 -07:00
Amjad Masad ec82ffa52b [react-packger] Add a timeout on transform jobs
Summary:
There's been a case where Babel can hang indefinitely on a file parse/transform. Possibly related to https://github.com/babel/babel/issues/2211

This adds a timeout to transform jobs and throws an error informing the user of the offending file. The timeout interval defaults to 10 seconds, but can be changed via an option.
2015-08-19 17:42:28 -07:00
Alex Kotliarskyi c5c25c15ea [RN] Show only file name in RedBox 2015-08-19 17:35:25 -07:00
Amjad Masad 24689006ab [react-packager] Remove unnecessary 'chalk' module mock 2015-08-19 17:28:18 -07:00
Amjad Masad e76e60f88d [react-packager] Make the fs mock async 2015-08-19 17:17:15 -07:00
Ben Alpert 5a2d2007a4 [React Native] Fix infinite loop in css-layout
Summary:
Manual pick of https://github.com/facebook/css-layout/commit/9001a3d2 since we're still lagging behind the upstream. Fixes #1378.
2015-08-19 16:39:35 -07:00
Martin Bigio d9bd445940 Unbreak Catalyst 2015-08-19 16:25:14 -07:00
Amjad Masad b4100b8332 [react-packager] Wait for haste map before accepting any requests
Summary:
D2319999 introduced a regression where we stopped waiting for the "build haste map" step to finish before we accept any requests. This makes sure that we block on that.

Need to unbreak with this, but will follow up with a test to catch this in the future.
2015-08-19 16:17:37 -07:00
Tim Yung 966a3bbc66 RN: Style Tweaks to Chrome Debugger UI 2015-08-19 16:00:03 -07:00
Abhishek Sood 5fc2d67ee5 Revert "@build-break" 2015-08-19 15:21:16 -07:00
Abhishek Sood d64ac20119 Revert "[ReactNative] Open source NetworkingModule" 2015-08-19 15:20:09 -07:00
Ben Alpert 0f3ea9fb8c [ReactNative] Fix switching to null event listener 2015-08-19 15:02:25 -07:00
Martín Bigio f4c7bb1103 [react-packager] Fix bug on Bundles Layout algorithm
Summary:
The layout algorithm wasn't getting deep into the sync dependencies recursively to async dependencies.
2015-08-19 14:20:38 -07:00
Abhishek Sood 1aa29ceaf2 @build-break 2015-08-19 14:12:22 -07:00
Martin Konicek 9c32a7a940 [ReactNative] Prepare for putting RN Android OSS files in 2015-08-19 12:13:56 -07:00
Martin Konicek ade571065e [ReactNative] Open source NetworkingModule 2015-08-19 11:47:10 -07:00
Martin Konicek 3d0cd480d2 [ReactNative] Naming: RCTSwitch -> AndroidSwitch 2015-08-19 10:28:28 -07:00
James Ide deaef94471 [Podspec] Remove AnimationExperimental subspec and fix Image subspec
Summary:
AnimationExperimental is gone; remove it. The Image subspec now depends on the networking code, so we have to pull in those files. These changes were necessary to publish 0.10.0-rc to CocoaPods, so would be convenient to get them into master for 0.11.

Fixes #2354
Closes https://github.com/facebook/react-native/pull/2341
Github Author: James Ide <ide@jameside.com>
2015-08-19 09:59:49 -07:00
Nick Lockwood 26c4be62c8 Fixed test flakiness due to a race condition with RCTRedBox
Summary:
The test runner relied on checking the current error message in the RCTRedbox, which is a singleton (yay, shared mutable state!). This lead to some tests that worked individually but failed when run together due to error messages in RCTRedBox left over from previous tests.

I've replaced the call to -[RCTRedBox currentErrorMessage] by injecting a custom logging function to intercept the errors at source, which is a much more reliable solution.
2015-08-19 03:41:31 -07:00
Alex Kotliarskyi b18d73b568 [RN] Unbreak packager 2015-08-18 18:29:32 -07:00
Martín Bigio 291c8ff9ec [react-packager] Modernize Activity to ES6 2015-08-18 15:25:18 -07:00
Martín Bigio 51596f8674 [react-packager] Modernize AssetServer to ES6 2015-08-18 14:38:40 -07:00
Christopher Chedeau ede5fa7b39 Merge pull request #2374 from foghina/cli_contributing
[cli] add docs on how to contribute to the CLI
2015-08-18 11:22:08 -07:00
Krzysztof Magiera 67746fea2f [ReactNative] Use FbHttp for handling http requests from React Native. 2015-08-18 09:12:40 -07:00
Felix Oghină 621a2c486f [cli] add docs on how to contribute to the CLI 2015-08-18 15:56:26 +01:00
Nick Lockwood 76a9baaf2f Fixed bug where method calls containing struct arguments would fail silently
Summary:
The arg block for handling structs did not return a value, which was being intepreted as failure. This diff returns YES for success, and also adds an error log for this case so future regressions won't fail silently.
2015-08-18 07:35:26 -07:00
Felix Oghină e0e6fbfa8c Merge pull request #2373 from foghina/fix_e2e
[e2e] fix e2e tests
2015-08-18 12:10:54 +01:00
Felix Oghină 3b7bffa2a1 [e2e] fix e2e tests
* use new _flowconfig in generator template
* increase sinopia max_body_size
* remove breaking `cd` command from e2e-test.sh
2015-08-18 11:51:03 +01:00
Natthu Bharambe a4e64196bc Update GLOBAL.process instead of over-writing during initialization. 2015-08-17 16:47:10 -07:00
Ben Alpert 65692b7235 [ReactNative] Don't redbox for React warnings when not using Chrome executor 2015-08-17 16:02:10 -07:00
Nick Lockwood 8d1e02b8bd Convert alloc/init to new to please linter 2015-08-17 08:46:00 -07:00
Dorota Kapturkiewicz 869ff92dbc [ReactNative] add importantForAccessibility to accessibility sample app 2015-08-17 07:17:44 -07:00
Mike Armstrong bce7b9c638 generalise handling of uniforms and samplers 2015-08-17 07:13:17 -07:00
Pieter De Baets 65713992c4 Let native modules know when root views get added and removed 2015-08-17 07:12:06 -07:00
James Ide 12d5f0d6f4 [Views] Change rasterization scale to the main screen's scale
Summary:
`view.screen` can be nil if the view has not yet been added to the view hierarchy (e.g. new view), so we should use `[UIScreen mainScreen]` instead.

In the future, if we need to support multiple screens, one possible fix is to set the rasterization scale in didMoveToWindow/Superview. For now we have just one screen, though.
Closes https://github.com/facebook/react-native/pull/2334
Github Author: James Ide <ide@jameside.com>
2015-08-17 06:54:55 -07:00
Felix Oghină f0dd9fb358 Merge pull request #2298 from foghina/yo
[cli] convert project generation to use yeoman
2015-08-17 13:51:24 +01:00
Pieter De Baets 261f9434e5 Avoid dispatch_async in RCTRootView when bridge has already started
Summary:
There's no good reason for initialProperties to be mutable after the RCTRootView has been created. Passing it in through the constructor means we can skip one dispatch_async.
2015-08-17 05:34:25 -07:00
Ludo Fardel 8460db57bc Make flow check async 2015-08-17 03:13:16 -07:00
Amjad Masad ca38908423 [react-packager] In production resolve __DEV__ to NODE_ENV === 'development' 2015-08-15 17:07:41 -07:00
Amjad Masad 3388d8fe79 [reat-packager] Switch platform resolution based on query param
Summary:
Currently the platform selection is controlled by the blacklist. However, since we want to use the same server instance for cross-platform development, we need this to be controlled per request.

One outstanding issue, is that the DependencyGraph class wasn't designed that way and it doesn't have a per-request state. This means that with the current design race conditions is possible. If we got a request for a different platfrom while processing the previous request, we may change the outcome of the previous request.

To fix this a larger refactor is needed. I'll follow up a diff to do that.

Finally, so I don't break the universe like last time, I'll leave it up to the RN guys to update the call sites.
2015-08-15 13:28:18 -07:00
Amjad Masad 9eb5151bd2 [react-native] Set NODE_ENV and use node-env-inline plugin
Summary:
This sets NODE_ENV based on the value of the `dev` option when bundling the apps. This would then be inlined by the node-env-inline babel plugin. And finally -- if unreachable -- will be dead-code-eliminated by uglify.

This is not used in development because we set NODE_ENV to the value of __DEV__, which can be switched via a query param. However, the plugin has minimal overhead and to avoid complexity in the transformers I just enabled it by default.
2015-08-15 13:25:09 -07:00
Amjad Masad 9d96d00163 [react-native] Check in babel-plugin to inline __DEV__
Summary:
This plugin resolves __DEV__ to the value of `NODE_ENV === 'development'`. This can then be evaluated and dead code can be removed by uglifyjs.
2015-08-15 13:17:48 -07:00
James Ide 758ec76cb6 Merge pull request #2340 from chentsulin/patch-1
Add npm version badge
2015-08-14 20:55:09 -07:00
C. T. Lin 05b17a811e Add npm version badge 2015-08-15 11:42:33 +08:00
Christoph Pojer 5786a05e9e Merge pull request #2339 from ide/jest
[jest] Update jest-cli version to 0.5
2015-08-14 16:13:33 -07:00
Alex Kotliarskyi 324d154cf7 [ReactNative] Add ability to listen for Packager events 2015-08-14 14:28:45 -08:00
James Ide 5153ce0a03 [jest] Update jest-cli version to 0.5
npm install will get a little nicer since it can read from npm instead of always having to redownload from github.
2015-08-14 14:49:37 -07:00
Martín Bigio 3be2b1d966 [react-packager] Modernize Server to ES6 2015-08-14 12:34:23 -08:00
Martín Bigio 0623371814 [react-packager] Cache in which bundle is each module
Summary:
Not that at the moment a module can be present in multiple bundles, so the new API will return only one of them. In the near future we'll impose the invariant that a module can only be present in a single bundle so this API will return the exact bundle in which it is.
2015-08-14 12:30:30 -08:00
Martín Bigio 76e37c4423 [react-packager] Modernize Server-test by using ES6 features 2015-08-14 12:23:02 -08:00
Amjad Masad 8bd1cb8cce [react-native] Add babel-plugin-node-env-inline plugin
Summary:
Check in the `process.env.NODE_ENV` inline plugin. This will be used in conjuction with uglifyjs to eliminate dead code resulting from environment checks.
2015-08-14 10:46:05 -08:00
Alexsander Akers 91c8362176 Rename RCTReachability to RCTNetInfo 2015-08-14 08:20:01 -08:00
Nick Lockwood decf35c271 Fixed log prefixes to provide more context for prop binding errors 2015-08-14 08:01:34 -08:00
Nick Lockwood 3f5fcadbd5 Fix null values in network requests 2015-08-14 05:16:02 -08:00
Alexsander Akers 96277ca3f5 Add HSL/HSLA support 2015-08-14 04:48:20 -08:00
Alexsander Akers 0f14933948 Enable transparent modal presentation with <Modal />
Summary:
Enable transparent modal backgrounds using `UIModalPresentationCustom` modal presentation style.
2015-08-14 04:47:12 -08:00
Alexsander Akers dc01ecbc98 Remove now useless comment 2015-08-14 04:46:26 -08:00
Alex Akers 5c0805b071 Fix failing UIExplorer test (after isValid removal) 2015-08-14 04:27:27 -08:00
Dorota Kapturkiewicz a2c51b3b28 [ReactNative] expose importantForAccessibility to JS 2015-08-14 03:28:22 -08:00
Andrei Coman e9735556f6 [ReactNative] Sync [react_native] Fix keyboard behavior for android 2015-08-14 02:58:37 -08:00
Pieter De Baets fa07736ee1 Remove isValid from RCTInvalidating
Summary:
We only actually use it on RCTBridge and RCTJavaScriptExecutor, so add it to these interfaces explicitly
2015-08-14 01:57:18 -08:00
Zack Gomez f5d68f6ecb [ReactNative] Fix pixel rounding
Summary:
Too many rounds, we only want/need one.
2015-08-13 18:04:49 -08:00
Amjad Masad bc28a35bda [react-packager] Use module objects across the codebase (rid of getPlainObject etc)
Summary:
Instead of using plain objects and having to convert to and from them we just use the `Module` class across the codebase.
This seems cleaner and can enforce the type as opposed to fuzzy objects.
2015-08-13 15:52:31 -08:00
Amjad Masad 7bfc1baf7f [react-packager] Upgrade uglifyjs for Max call stack bug
Summary:
We're hitting an issue with large code size and `Maximum call stack size exceeded` error. https://github.com/mishoo/UglifyJS2/issues/414
We're seeing on inconsistently failing on landcastle.
2015-08-13 14:35:13 -08:00
Amjad Masad abce124198 [react-packager] Remove horribly outdated example_project
Summary:
Removes some old unused code.
2015-08-13 13:02:52 -08:00
Martín Bigio 5cad2e9370 [react-packager] Introduce Bundler
Summary:
Introduce a Bundler capable of generating the layout of modules for a given entry point. The current algorithm is the most trivial we could come up with: (1)it puts all the sync dependencies into the same bundle and (2) each group of async  dependencies with all their dependencies into a separate bundle. For async dependencies we do this recursivelly, meaning that async dependencies could have async dependencies which will end up on separate bundles as well.

The output of of the layout is an array of bundles. Each bundle is just an array for now with the dependencies in the order the requires where processed. Using this information we should be able to generate the actual bundles by using the `/path/to/entry/point.bundle` endpoint. We might change the structure of this json in the future, for instance to account for parent/child bundles relationships.

The next step will be to improve this algorithm to avoid repeating quite a bit dependencies across bundles.
2015-08-13 12:57:55 -08:00
Pieter De Baets c084793e91 Fix ModalFullScreenView's window not dismissing after being removed 2015-08-13 08:55:40 -08:00
Martino Luca 41a88c3eb1 Fixing typos in imports 2015-08-13 08:36:06 -08:00
Alex Akers f552495e7f Fix NavigatorIOS freeze when pushing before initialization completes
Summary:
This freezes the app in the UIExplorer because we try to push a new view controller onto the screen before the navigator finishes loading. This was exacerbated by @tadeuzagallo's diff that made the loading even faster. Hehe
2015-08-13 08:24:24 -08:00
Nick Lockwood 7232b1bbc7 Fixed image clipping / resizing logic 2015-08-13 08:13:55 -08:00
Alex Akers 672b77f355 Perform clip update on RCTScrollView in increments of 50 pt
Summary:
This diff removes calls to `-updateClippedSubviews` by only re-clipping when the scroll view moves by a certain number of pixels.

leeway = 50pt => 46.9% of calls removed
leeway = 10pt => 13.2% " " "
2015-08-13 07:56:41 -08:00
Tadeu Zagallo c9f5d229db Merge pull request #2323 from tadeuzagallo/Updates_Thu_13_Aug
Updates thu 13 aug
2015-08-13 14:50:09 +01:00
Tadeu Zagallo 12492d8d94 [ReactNative][Travis] Attempt to fix tests 2015-08-13 14:39:01 +01:00
Tadeu Zagallo b9dc29bcb3 [ReactNative] Fix SampleApp xcodeproj configuration
Summary:
Make SampleApp scheme shared.
2015-08-13 05:29:28 -08:00
Tadeu Zagallo eeb0adca43 [ReactNative][Website] Move bluebird to depencies instead of devDependencies 2015-08-13 14:10:56 +01:00
Tadeu Zagallo 28fb229266 [ReactNative] Fix e2e tests 2015-08-13 13:50:04 +01:00
Tadeu Zagallo 4daca092d2 [ReactNative][Website] Fix tests 2015-08-13 13:31:50 +01:00
Nick Lockwood 0487c55c25 Removed unnecessary overhead in RCTConvert functions 2015-08-13 04:08:17 -08:00
Nick Lockwood 1d072076db Reduce +[UIImage imageNamed:] overhead 2015-08-13 03:33:04 -08:00
Amjad Masad 7750db05e6 [react-packager] Set a lifetime on workers to avoid memory leaks 2015-08-12 19:26:26 -08:00
James Ide 08d1bc8c9f [TextInput] Fix multiline TextInput so text and cursor stay in bounds
Summary:
With a multiline TextInput, the text is initially rendered correctly but once you try to edit it, the cursor slides off the top of the view and out of its bounds. Also if the TextInput is scrollable, you can scroll the text out of the bounds of the view, which looks buggy unless you clip the overflow. This occurs because the top content inset is applied to the RCTTextView instead of the UITextView's text container.

This diff fixes both bugs by applying the vertical insets to the UITextView's textContainerInset instead of the RCTTextView's frame (which is a wrapper around a real UITextView).

The left inset is still applied to the frame because there is a bug with the text rendering when the left textContainerInset is negative: the initial text doesn't show up until you focus the text view. The bug doesn't occur when setting the right textContainerInset, so I apply this workaround to only the left inset.

Closes https://github.com/facebook/react-native/pull/2297
Github Author: James Ide <ide@jameside.com>
2015-08-12 14:50:42 -08:00
Martín Bigio cfcf604b3d [react-packager] Introduce require.ensure
Summary:
This is the first step to add support for splitting the JS bundle into multiple ones. This diff adds support for keeping track of the async dependencies each module has. To do so we introduce the following syntax:

  require.ensure(['dep1', 'dep2, ..., 'depN'], callback);

Where the callback function is asynchronously invoked once all the indicated modules are loaded.

Internally, the packager keeps track of every set of async dependencies a module has. So for instance if a module looks like this:
  require.ensure(['dep1'], () => {...});
  require.ensure(['dep2'], () => {...});

the `Module` object will keep track of each set of dependencies separately (because we might want to put them on separate bundles).
2015-08-12 12:23:42 -08:00
Amjad Masad 309326db2e [react-packager] Rename 'Package' to 'Bundle'
Summary:
The word Package is overloaded, it may mean npm package, or may mean a collection of bundles. Neither is what we mean. We mean `bundle`.

This renames it and modernize some of the Bundler code.
2015-08-12 12:09:01 -08:00
Martin Konicek c483db1b88 [ReactNative] Open source ProgressBarAndroid, remove example from the RN launcher 2015-08-12 12:02:17 -08:00
James Ide abdd0e09b3 [npm] Upgrade to stacktrace-parser 0.1.2, which supports io.js
Summary:
stacktrace-parser used to list only Node 0.10 under its list of supported engines. This new version includes Node 1.x and 2.x (i.e. io.js) as well, which addresses the warning during `npm install`.

There's no problem with using the older version of stacktrace-parser; this just clears the warning.

Closes https://github.com/facebook/react-native/pull/1738
Github Author: James Ide <ide@jameside.com>
2015-08-12 11:12:59 -08:00
Nick Lockwood a86e6b76fb Fixed fuzzer app and ensured that React does not crash when fuzzed 2015-08-12 06:14:36 -08:00
Felix Oghină f83675d191 [cli] convert project generation to use yeoman 2015-08-12 12:04:27 +01:00
Nick Lockwood 39230000de Fix ReactART 2015-08-11 22:44:45 -08:00
Alex Kotliarskyi 1e1efce69b Add .watchmanconfig
Summary:
This file tells watchman to watch this folder if "root_restrict_files"
is turned on.

Fixes #2042
Closes https://github.com/facebook/react-native/pull/2263
Github Author: Alex Kotliarskyi <alex.frantic@gmail.com>
2015-08-11 16:39:49 -08:00
Martín Bigio 70624dc347 [react-packager] Fix Cache-test 2015-08-11 11:27:15 -08:00
Chace Liang eb402d8c7d [e2e] Fix TouchableHighlight in e2e test 2015-08-11 10:53:50 -08:00
Christopher Chedeau 5ebe0ed717 Bust jest caching and fix tests 2015-08-11 11:02:19 -07:00
Nick Lockwood a5e9f83a0a Implemented lazy parsing of method signatures to improve TTI 2015-08-11 08:49:13 -08:00
Adam Roth 57a6a02dff [CameraRoll] Image orientation fix for #1845
Summary:
PR for #1845

Use ALAssetOrientationUp for image orientation.

Originally committed at https://github.com/facebook/react-native/commit/b34a85f4da87c62656ca9d29c5085a46e768d147
Closes https://github.com/facebook/react-native/pull/2214
Github Author: Adam Roth <adamjroth@gmail.com>
2015-08-11 08:44:57 -08:00
Christopher Chedeau 0d636a017d Updates from Tue 11 Aug 2015-08-11 08:42:07 -07:00
Nick Lockwood 4d817245f7 Fix crash when using alert() polyfill due to null callback 2015-08-11 07:31:19 -08:00
Tadeu Zagallo e2d9ddce4c [ReactNative] Fix cast warning in RCTProfile
Summary:
Buck is more strict than our current xcodeproj configuration is keeps warning
about this implicit cast, it's quite annoying.
2015-08-11 06:49:39 -08:00
Nick Lockwood 48af214216 Simplified event registration
Summary:
Our events all follow a common pattern, so there's no good reason why the configuration should be so verbose. This diff eliminates that redundancy, and gives us the freedom to simplify the underlying mechanism in future without further churning the call sites.
2015-08-11 06:41:04 -08:00
Yusef Napora 2fe1ac2a83 [Image] Fix invalid CGContext when one dimension of destination Image size == 0
Summary:
Addresses #1534

When an image has a known width, but a height of 0 (which can happen if `flex: 1` is set on the `Image` element), `RCTDownloadManager` attempts to scale it to an invalid size, which results in a `NULL` `CGContextRef` and some scary warnings from UIKit:

```
 <Error>: CGContextTranslateCTM: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
```

This adds a check for zero width or height to the `RCTClipRect` function.  If either dimension is zero, it is calculated based on the aspect ratio of the source image.  This ensures that we don't try to create an invalid `CGContextRef`, and that images with an unknown dimension are still scaled, blended, etc.
Closes https://github.com/facebook/react-native/pull/2278
Github Author: Yusef Napora <yusef@napora.org>
2015-08-11 06:30:34 -08:00
Tom Hastjarjanto 2424a215e0 [Image] Fix default Image functionality
Summary:
In the latest 0.9.0-rc of React Native, the default image won't load due to a typo and a missing condition in `setImage`. This PR contains fixes for both of them.
Closes https://github.com/facebook/react-native/pull/2269
Github Author: Tom Hastjarjanto <tom@intellicode.nl>
2015-08-11 05:19:04 -08:00
Nick Lockwood f5d8e4d6e0 Fixed a strongSelf that was accidentally marked as __weak 2015-08-11 04:46:56 -08:00
Nick Lockwood 68f1a223fb Fixed bug when updaing props for RCTNetworkImageView 2015-08-11 04:19:28 -08:00
Evan Solomon 51ccdfa36a [Babel] Upgrade babel and regenerator to the latest version
Summary:
See https://github.com/babel/babel/commit/c0fd4c1f9e0b18231f585c4fa793e4cb0e01aed1
Closes https://github.com/facebook/react-native/pull/1753
Github Author: Evan Solomon <evan@evanalyze.com>

@allow-crlf-text
2015-08-10 20:37:39 -08:00
Dave Sibiski e163df3567 Adds process.env.NODE_ENV polyfill
Summary:
There are many libraries that use `NODE_ENV` to check whether the code is running in
"production" mode or not. This allows those library authors to not have to add conditionals
for React Native.

One such library is Redux: https://github.com/gaearon/react-redux/pull/40

Thanks to @brentvatne for providing the solution via this tweet (via his phone in the airport 😉): https://twitter.com/notbrent/status/630440250951749632

/cc @vjeux @gaearon @zpao @amasad
Closes https://github.com/facebook/react-native/pull/2279
Github Author: Dave Sibiski <dsibiski@gmail.com>
2015-08-10 19:51:05 -08:00
Martín Bigio a303a42e28 [react-packager] Add more granular Activity logging 2015-08-10 16:25:04 -08:00
Martín Bigio 2afeb8fbe6 [react-packager] Promote Cache to top level
Summary:
The cache is only used for JSTransformer at the moment. We're doing IO and some computation to get each module's name, whether is a haste or node module and it's dependencies. This work happens on startup so by caching this value we shouldbe able to reduce the start up time. Lets promote the Cache to the Packager level to be able to use it by any of the components of the packager. For now, on this diff we'll start using it to cache the mentioned fields.

Also we had to introduce the concept of fields in the cache as manually merging the date we had for each path is not possible as we're using promisses all around. With the new API, each field is a promise.

@amasad and I did some manual testing to measure the impact of this change and looks like it's saves 1 second when building the haste map (which represents 50% of the time). Overall this reduces 1 second of start up time which was currently about 8s on my mac book pro.
2015-08-10 16:25:03 -08:00
Christopher Chedeau 56059e92df Merge pull request #2288 from ide/iojs-docs
[docs] remove instructions to install node/io.js with brew
2015-08-10 15:46:36 -07:00
Nick Lockwood 5d20b9065d Fix RKHTTPRequestHandler crash 2015-08-10 13:46:47 -08:00
James Ide fd4e75644f [docs] remove instructions to install node/io.js with brew
nvm is way better than homebrew for managing node installations:

 - can install multiple versions
 - can choose which version of node to install
 - easy to clean up under ~/.nvm
 - there are still some rough edges with /usr/local on El Cap -- nvm avoids those altogether
2015-08-10 14:31:48 -07:00
Nick Lockwood 6e2e02ab08 Merge pull request #2281 from jacob-israel-turner/patch-2
Grammar
2015-08-10 22:00:03 +01:00
Nick Tuckett f309540f69 [react_native] JS files from D2327386: Simplified unimplemented SliderIOS on Android 2015-08-10 08:33:39 -08:00
Nick Lockwood b489c9aa43 Fixed perf issue due to use of regex in +[RCTConvert NSURL:] 2015-08-10 07:13:36 -08:00
Jacob Turner 5b5cadeb30 Grammar 2015-08-10 14:34:27 +01:00
Dorota Kapturkiewicz 59b974eafb [ReactNative] make AdsManager floater and TouchableHighlight accessible 2015-08-10 04:41:09 -08:00
Christopher Chedeau 50d5f86bf8 Merge pull request #2273 from vjeux/fix_az
[Website] Fix a-z order in props
2015-08-08 10:28:39 -07:00
Christopher Chedeau c1a0a72275 [Website] Fix a-z order in props 2015-08-08 10:28:05 -07:00
Nick Lockwood 94caefa9c2 Converted RCTDevLoadingView to a module and fixed url display when using delegate 2015-08-08 03:31:49 -08:00
Nick Lockwood b82ac9bf07 Reverted to pre-init of queues to fix UIExplorer tests. 2015-08-08 01:47:43 -08:00
Alex Kotliarskyi e21fb91786 [ReactNative] Show banner promoting DevTools
Summary:
When React DevTools is not installed, React prints a tiny warning to the console.
However, in debugger.html we have a lot of free space we could use to promote
React DevTools more actively.
2015-08-07 15:23:22 -08:00
Philipp von Weitershausen 0f5190e9f3 [React Native] Provide a way to get a list of registered apps in AppRegistry 2015-08-07 11:05:25 -08:00
Tadeu Zagallo 331e4a96e9 [ReactNative] Preload ModuleData queue
Summary:
The module's methodQueue wasn't being created when accessing the modules directly
on the bridge, without going through JS. Preload the queue for now to fix internal
breakages, but I'll figure out a better way to keep it lazy afterwards.
2015-08-07 11:05:09 -08:00
Ben Alpert 2d66e10ec4 [ReactNative] Delay sending touches to JS until dependent (native) gesture recognizers fail
Summary:
Previously, JS touches were being interpreted simultaneously with native gesture recognizers.
2015-08-07 10:56:26 -08:00
Alexander Kotliarskyi 3aec8ee72d Merge pull request #2267 from frantic/hide-npm-output
Hide npm output when doing react-native init
2015-08-07 11:37:49 -07:00
Felix Oghină 205a2c0bfc [react_native] JS files from D2318945: Implement a slider for React Native Android 2015-08-07 10:15:52 -08:00
Alex Kotliarskyi 2ddf3d942d Hide npm output when doing react-native init 2015-08-07 10:59:59 -07:00
Christopher Chedeau a91f44d7fd Merge pull request #2264 from vjeux/platform_props
[Website] Platform-specific props
2015-08-07 10:39:04 -07:00
Christopher Chedeau 6e9ceaa348 [Website] Platform-specific props
We are annotating platform-specific props with a special @platform tag in the docblocks. This pull request adds a little [ios] tag before the name and sorts the props such as generic ones are before platform-specific ones.
2015-08-07 10:31:07 -07:00
Tadeu Zagallo 6cd0709bc0 [ReactNative] Parellelise bridge startup
Summary:
Parallelise the bridge startup so we don't keep waiting for the source to load.
2015-08-07 06:48:30 -08:00
Nick Lockwood 3cef3010e6 Fix RCTAssert logic 2015-08-07 06:11:49 -08:00
Andy Street 1d452f3e4d [ReactNative] Remove testID from root view 2015-08-07 05:23:40 -08:00
Tj c933087567 CMD+R should post a refresh notification.
Summary:
For the sake of consistency, `cmd+r` should just post a refresh notification. This way other tools can also observe and react to the refresh without ugly hacks.
Closes https://github.com/facebook/react-native/pull/2175
Github Author: Tj <tfallon@mail.depaul.edu>
2015-08-07 04:39:21 -08:00
Vladislav Alexeev 9edad17a15 Use Dynamic Text Size Multipliers from Wilde in ReactNative Module 2015-08-07 03:18:20 -08:00
Nick Lockwood ffa7dbcbf1 Fixed onLayout redbox issue 2015-08-07 02:58:48 -08:00
Jason Zhekov a8211e32d2 Fix typo
Summary:
Closes https://github.com/facebook/react-native/pull/2055
Github Author: Jason Zhekov <jasssonpet@gmail.com>
2015-08-06 20:22:24 -08:00
Nick Lockwood deba13f698 Refactor RCTUIManager
Summary:
Moved the view creation & property binding logic out of RCTUIManager into a separate RCTComponentData class - this follows the pattern used with the bridge.

I've also updated the property  binding to use pre-allocated blocks for setting the values, which is more efficient than the previous system that re-contructed the selectors each time it was called. This should improve view update performance significantly.
2015-08-06 15:49:35 -08:00
James Ide 3309f6da80 Merge pull request #2252 from ide/iojs-docs
[Docs] Update setup instructions to install io.js 2.x instead of latest
2015-08-06 14:24:15 -07:00
James Ide 554f23276b [Docs] Update setup instructions to install io.js 2.x instead of latest
The ws module has not been updated to work with 3.x quite yet.
2015-08-06 14:22:45 -07:00
Martín Bigio aefdf82cdc [JSAppServer] Don't keep track of not found packages 2015-08-06 11:34:56 -08:00
Andrei Coman 327f84b967 [ReactNative] Sync [react_native] Implement TextInput editable 2015-08-06 11:07:06 -08:00
Tadeu Zagallo 48548fedbf [ReactNative] Fix RCTTextField crash on iOS7
Summary:
RCTTextField was its own delegate, that was causing a stall on the main thread,
see more here:
http://stackoverflow.com/questions/19758025/uitextfield-delegate-jumping-to-100-cpu-usage-and-crashing-upon-using-keyboard
2015-08-06 09:56:17 -08:00
Andrei Coman 0d981c06de [ReactNative] Sync [react_native] Text Input missing letters fix 2015-08-06 04:59:09 -08:00
Hedger Wang 8463625bd9 [Navigation]: Add a method to map the stack routes to an array.
Summary:
Add a method to map the stack routes to an array.
2015-08-06 02:01:59 -08:00
Thomas Aylott a6ff11f1d2 [react-packager] Fixes stack traces
Summary:
TransformErrors weren't showing stack traces, making it hard to debug problems in transformer code.
2015-08-05 12:46:30 -08:00
James Ide d4eac3ddca [RFC][Rendering] Add shouldRasterizeIOS to View components
Summary:
Exposes the `shouldRasterize` property. Fixes #1986.
Closes https://github.com/facebook/react-native/pull/2226
Github Author: James Ide <ide@jameside.com>
2015-08-04 15:37:38 -08:00
Tj d8f43105ed [ListView] Fix RCTScrollView stickyHeader touch passing.
Summary:
Point must be converted to the stickyHeader's coordinate space and then passed to the stickyHeaders hitTest:withEvent: method in order to be correctly routed to any subviews of the stickyHeader.

This resolves this [issue](https://github.com/facebook/react-native/issues/2075).
Closes https://github.com/facebook/react-native/pull/2224
Github Author: Tj <tfallon@Tjs-MBP.local>
2015-08-04 17:10:19 -08:00
Nick Lockwood f165bbaf4e Use +[RCTConvert NSURL:] everywhere instead of +[NSURL URLWithString:]
Summary:
RCTConvert's URL: method gracefully handles unescaped urls, local file urls, urls containing unicode, etc. URLWithString doesn't.
2015-08-04 16:26:16 -08:00
Hedger Wang 222594cb44 [Navigator] A method subtract to compute the diff between stack mutation.
Summary:
When mutation of a stack happens, we'd like to compute the diff of the stacks (before and after) so that
we can know which routes are removed in the new stack.

This diff adds a new method `substract` which does what we need.
2015-08-04 16:16:17 -08:00
Nick Lockwood 274769fd8c Added Unicode URL test 2015-08-04 15:37:05 -08:00
Nick Lockwood 9f81d6726c Merge pull request #2227 from harrykiselev/patch-1
Fix link to Apple Developer account registration.
2015-08-04 22:16:26 +01:00
Harry V. Kiselev 01deb0b03d Fix link to Apple Developer account registration. 2015-08-05 00:07:42 +03:00
Brent Vatne 257bbb5255 [Docs] Add newsletter to top-level header 2015-08-04 13:47:52 -07:00
Alex Akers bb883bfb61 Update offscreen image fix with window checking
Summary:
2015-08-04 08:05:12 -08:00
James Ide eab7b00cee [JSContext] Define ContextExecutor.setContextName for debugging
Summary:
Add a method that lets JS set the name of the JSContext for debugging purposes. I check `JSGlobalContextSetName` since it is not available on iOS 7.

Closes https://github.com/facebook/react-native/pull/2144
Github Author: James Ide <ide@jameside.com>
2015-08-04 06:08:14 -08:00
James Ide 47e1d1aef8 [Async] Enable async/await and update UIExplorer and tests
Summary:
- Enables async/await in .babelrc and transformer.js
- Adds regenerator to package.json. Users still need to explicitly require the regenerator runtime -- this is so that you only pay for what you use.
- Update AsyncStorage examples in UIExplorer to use async/await
- Update promise tests in UIExplorer to use async/await in addition to the promise API

Closes https://github.com/facebook/react-native/pull/1765
Github Author: James Ide <ide@jameside.com>
2015-08-04 05:35:13 -08:00
Amjad Masad 18452940f0 [react-packager] Add support for platform in the resolver
Summary:
Teach the resolver about platform-based resolution. The platform extension is inferred from the entry point.
It works for haste modules, as well as node-based resolution.
2015-08-03 18:29:20 -08:00
Christopher Chedeau afdeefc864 [Animated] Remove rebound dependency
Summary:
We already reimplement the spring computation, we were only using rebound for the tension/friction conversion. Turns out that it is quite small so we can just embed it. I'm doing this as I'm preparing for doing a web version of the feature and I'm trying to minimize the number of dependencies.

https://github.com/facebook/rebound-js/blob/master/rebound.js#L932
2015-08-03 15:24:40 -08:00
Nick Lockwood 6a4b83c16f Fixed retain cycle that caused RCTModuleMethods to leak
Summary:
Some of the log statements inside argument blocks in RCTModuleMethod were directly accessing ivars, thereby causing a retain cycle that retained the class. I've fixed this by making the access explicit via weakSelf.
2015-08-03 08:46:52 -08:00
Martin Konicek c63992437b [ReactNative] LayoutAnimation docs
Summary:
Improve https://facebook.github.io/react-native/docs/layoutanimation.html
2015-08-03 07:52:31 -08:00
=?UTF-8?q?=E9=9A=90=E9=A3=8E?= 44ce9194a2 Profiling will not work if the bundleURL has no port.
Summary:
If the bundleURL has no port(default 80) , the profile request URL will be `<scheme>://<host>:<null>/profile`, that will not work. So we should decide if the port exsits first.
Closes https://github.com/facebook/react-native/pull/2131
Github Author: =?UTF-8?q?=E9=9A=90=E9=A3=8E?= <yinfeng.fcx@alibaba-inc.com>
2015-08-03 07:51:33 -08:00
Alex Akers 3e21f39a77 Remove rendered RCTText contents when moving offscreen
Summary:
When an `RCTText` instance moves offscreen (possibly due to parent clipping), we unset the layer's contents until it comes onscreen again.
2015-08-03 05:43:16 -08:00
Alex Akers e9f69bc2e4 Reorganize SampleApp
Summary:
2015-08-03 03:32:03 -08:00
Dorota Kapturkiewicz e3ed572c01 [ReactNative] accessibility test app 2015-08-03 01:42:35 -08:00
Brent Vatne e2a2472af4 Merge pull request #2194 from ide/animation-docs
[Docs] Remove sections on AnimationExperimental and Pop
2015-08-02 16:16:13 -07:00
Brent Vatne 5222be0edf [Docs] Fix typo in docs index 2015-08-02 16:14:50 -07:00
James Ide 0b5e229ed2 Merge pull request #2205 from muan/title
[Docs] Add dynamic page title
2015-08-02 15:04:03 -07:00
Mu-An Chiou 129d1548a8 Add dynamic page title
Currently all the pages have the same title, making it hard to
tell which page is while when user has multiple tabs opened.
This adds 'title' to Site so a page title can be passed in and
prepended to the default title
2015-08-02 22:07:53 +08:00
James Ide bc56eb1439 Merge pull request #2201 from threepointone/patch-1
doc typo
2015-08-01 12:34:42 -07:00
Sunil Pai 5a918227f2 doc typo
match member names
2015-08-01 23:43:29 +05:30
Nick Lockwood 95d1fd142e Fixed null argument errors for timers and layout animations 2015-08-01 06:40:27 -08:00
Philipp von Weitershausen 3e79838a31 [React Native] sync JS for D2287297 2015-07-31 21:31:46 -08:00
Kevin Gozali ee8b50c955 [ReactNative] fix up XMLHttpRequest failures 2015-07-31 21:31:45 -08:00
James Ide 4a93d23af2 [Docs] Remove sections on AnimationExperimental and Pop
AnimationExperimental has been removed and Pop has been superseded by Animated.
2015-07-31 17:17:22 -07:00
Philipp von Weitershausen d858d0c4e0 [ReactNative][Android] JS for D2294884: Allow XHR to send native files, as HTTP body or via multipart FormData 2015-07-31 15:50:49 -08:00
Brent Vatne f41663a2df [WebView] Replace RKWebView with RCTWebView in log message
Summary:
Easy merge, just a small change in log message
Closes https://github.com/facebook/react-native/pull/2061
Github Author: Brent Vatne <brentvatne@gmail.com>
2015-07-31 13:49:14 -08:00
Nick Lockwood 1fb26d4319 Cleanup 2015-07-31 11:33:22 -08:00
Krzysztof Magiera b807c51bbe [ReactNative] Fix TextInput Focus issue 2015-07-31 11:03:41 -08:00
Vladislav Alexeev 53fb5b6cee Dynamic Text Sizes for Text component
Summary:
Dynamic Text Sizes for Text component.
Text gains new prop - allowFontScaling (false by default).
There is also AccessibilityManager module that allows you to tune multipliers per each content size category.
2015-07-31 07:42:41 -08:00
Nick Lockwood 407eb4ce85 NSNumber arguments must now be nonnull
Summary:
The bridge implementation on React Android does not currently support boxed numeric/boolean types (the equivalent of NSNumber arguments on iOS), nor does Java support Objective-C's nil messaging system that transparently casts nil to zero, false, etc for primitive types.

To avoid platform incompatibilities, we now treat all primitive arguments as non-nullable rather than silently converting NSNull -> nil -> 0/false.

We also now enforce that NSNumber * objects must be explicitly marked as `nonnull` (this restriction may be lifted in future if/when Android supports boxed numbers).

Other object types are still assumed to be nullable unless specifically annotated with `nonnull`.
2015-07-31 06:57:08 -08:00
Eric Vicenti 41dd6fe6ea [ReactNative][Navigator] Fix disabled scene height change
Summary:
Disabling the scene this way would make the scene height go to zero and mess up the scroll position. By setting the bottom to the same distance, the view does not get resized and the scroll position is preserved through a scene disable cycle.
2015-07-30 12:58:45 -08:00
Alex Akers f2b3057a7c Fix border width precedence issue 2015-07-30 06:18:17 -08:00
Felix Oghina 90b80e375c [reactnative] add launchAndroidPackager.command 2015-07-30 03:35:29 -08:00
Tadeu Zagallo cf22111cee [ReactNative] Prevent RCTDevLoadingView from creating UIWindow on unit tests
Summary:
`RCTDevLoadingView` was being created from a constructor function and creating
a `UIWindow` when the bridge started loading. The `UIWindow` was crashing on
the unit tests since there's no host app.
2015-07-30 03:10:53 -08:00
Dorota Kapturkiewicz 8a272bc873 [ReactNative] implement accessibilityLiveRegion and accessibilityComponentType 2015-07-30 01:40:37 -08:00
Gabe Levi d8a13ec3d5 [Flow] Deploy v0.14.0 2015-07-29 20:29:44 -08:00
Philipp von Weitershausen 4bfeeaa90d [ReactNative] Improve Flow definitions and code comments in XHR FormData polyfill 2015-07-29 20:03:57 -08:00
Zack Gomez 60c8abcc70 Revert "[ReactNative] revert "prevent ScrollView content offset from changing during layout"" 2015-07-29 17:23:18 -08:00
Hedger Wang 4b16e4d550 [Navigator]: Add a method keyOf to NavigationRouteStack.
Summary:
# Summary

Add a method `keyOf` to NavigationRouteStack.

The method `keyOf` returns a key that is associated with the route.
The a route is added to a stack, the stack creats an unique key for it and
will keep the key for the route until the route is rmeoved from the stack.

The stack also passes the keys to its derived stack (the new stack created by the
mutation API such as `push`, `pop`...etc).

The key for the route persists until the initial stack and its derived stack no longer
contains this route.

# Why Do We Need This?

Navigator has needs to use an unique key to manage the scenes rendered.
The problem is that `route` itself isn't a very reliable thing to be used as the key.

Consider this example:

```
// `scene_1` animates into the viewport.
navigator.push('scene_1');

setTimeout(() => {
 // `scene_1` animates off the viewport.
 navigator.pop();
}, 100);

setTimeout(() => {
 // Should we bring in a new scene or bring back the one that was previously popped?
 navigator.push('scene_1');
}, 200);

```

Because we currently use `route` itself as a key for the scene, we'd have to block a route
until its scene is completely off the components tree even the route itself is no longer
in the stack otherwise we'd see strange animation of jumping scenes.

# What's Next

We're hoping that we can build pure reactive view for NavigationRouteStack easily.
The naive implementation of  NavigationRouteStackView may look like this:

```
class NavigationRouteStackView {
  constructor() {
    this.state = {
      staleScenes: {},
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.stack !== this.props.stack) {
      var stale;
      var staleScenes = {...this.state.staleScenes};
      this.props.stack.forEach((route, index, key) => {
        if (nextProps.stack.keyOf(route) !== key) {
          stale = true;
          staleScenes[key] = {route, index, key, stale};
        }
      });
      if (stale) {
        this.setState({
          staleScenes,
        });
      }
    }
  }

  render() {
    var scenes = [];

    this.props.stack.forEach((route, index, key) => {
      scenes.push({route, index, key});
    });

    Object.keys(this.state.staleScenes).forEach(key => {
      scenes.push(this.state.staleScenes[key]);
    });

    scenes.sort(stableSortByIndex);

    return <View>{scenes.map(renderScene)}</View>;
  }
}

```
2015-07-29 16:55:21 -08:00
Philipp von Weitershausen 37636fc59a [React Native] open source ImageEditingManager native module 2015-07-29 15:57:48 -08:00
Hedger Wang 809a2dc1d6 [Navigator: Prevent user from over-popping the routes.
Summary:
If user taps the back button quickly, the app crashes becuase "pop"
internally only checks `this.state.presentedIndex` which does not
always update when transtion happens.

This diff addresses this issue.
2015-07-29 11:42:34 -08:00
Jing Chen 8416691719 [events] Move start point of EventsDashboard to work with early boot 2015-07-29 10:47:13 -08:00
Pieter De Baets d6de865236 Cleanup AppRegistry types
Summary:
Found some missing/wrong types when playing around with the AppRegistry for routing work in the main app.
2015-07-29 09:55:24 -08:00
Dorota Kapturkiewicz e073fdc4c7 [ReactNative] add accessibilityComponentType 2015-07-29 09:20:23 -08:00
Felix Oghina dfa43f0ce5 [react_native] JS files from D2282690: make back button work in launcher app 2015-07-29 06:35:46 -08:00
Nick Lockwood 95b9dd3a88 Added support for method argument nullability
Summary:
This diff adds support for enforcing nullability in the arguments for exported methods.

We previously supported use of the nullable/nonnull attributes on method arguments, but didn't do anything to ensure that they were respected.

Now, if an argument is marked as nonnull, and a null value is sent for that argument, it will display a redbox.

In future, nonnull will be assumed by default, but for now we assume that un-annotated arguments can be null (to avoid breaking existing code).
2015-07-29 05:50:27 -08:00
Ben Alpert e0ea046092 [ReactNative] Fix ResponderEventPlugin after React upgrade 2015-07-29 02:47:55 -08:00
Kevin Gozali 87ce2d635b [ReactNative] revert "prevent ScrollView content offset from changing during layout" 2015-07-28 19:39:56 -08:00
Kevin Gozali f1b22e87f1 [madman] version mobile configs disk caching 2015-07-28 18:11:34 -08:00
Tadeu Zagallo 127f7095dc [ReactNative] Add RCTBridgeDelegate
Summary:
Add a new bridge delegate protocol to allow a more flexible bridge configuration.

For now it just support the pre-existent configurations + providing the JavaScript
source to the bridge, that should allow pre-loading sources.
2015-07-28 15:57:02 -08:00
Zack Gomez 068f396c9b [ReactNative] prevent ScrollView content offset from changing during layout
Summary:
-[UIScrollView setFrame:] changes the content offset, which we want to do manually.  Preserve the old offset during layout.
2015-07-28 14:36:27 -08:00
Nick Lockwood b812b0ee2e Added unit tests for RCTModuleMethod parsing, and fixed some edge cases 2015-07-28 13:07:52 -08:00
Alex Kotliarskyi e964e741ef [RN] Add loading view for development mode
Summary:
It's very useful to know where the app is being loaded from and
can help debug various issues.
2015-07-28 11:17:06 -08:00
Alex Akers 7d19ff3dcb Add <Modal /> component
Summary:
Create Modal component that can be used to present content modally.
2015-07-28 07:21:50 -08:00
Tadeu Zagallo f53c95c743 [ReactNative] Proxy bundleURL on RCTBatchedBridge
Summary:
Fixes #2126

`RCTBatchedBridge` didn't implement `bundleURL`, that was available on the public
bridge interface, so it'd always be `nil`, and setting it would just be ignored.
2015-07-28 05:59:45 -08:00
Nick Lockwood 1d852624fd Refactored RCTImageDownloader to use RCTNetworking instead of a separate download system 2015-07-27 13:47:52 -08:00
955 changed files with 59402 additions and 8284 deletions
+5 -6
View File
@@ -10,11 +10,8 @@
# Ignore react-tools where there are overlaps, but don't ignore anything that
# react-native relies on
.*/node_modules/react-tools/src/React.js
.*/node_modules/react-tools/src/renderers/shared/reconciler/ReactInstanceHandles.js
.*/node_modules/react-tools/src/renderers/shared/event/EventPropagators.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderSyntheticEvent.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderTouchHistoryStore.js
.*/node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js
# Ignore commoner tests
@@ -38,13 +35,15 @@ Examples/UIExplorer/ImageMocks.js
[options]
module.system=haste
munge_underscores=true
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-4]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-4]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version]
0.13.1
0.14.0
+6
View File
@@ -25,6 +25,12 @@ project.xcworkspace
# OS X
.DS_Store
# Android/IJ
.idea
.gradle
local.properties
*.iml
# Node
node_modules
*.log
+4 -5
View File
@@ -11,19 +11,18 @@ before_install:
- brew update
install:
- brew reinstall xctool nvm
- rm -Rf `node -p "require('os').tmpDir()"`/jest_preprocess_cache
- npm install -g flow-bin@`node -p "require('fs').readFileSync('.flowconfig', 'utf8').split('[version]')[1].trim()"`
- mkdir -p .nvm
- cp $(brew --prefix nvm)/nvm-exec .nvm/
- export NVM_DIR=.nvm
- export NVM_DIR="$PWD/.nvm"
- source $(brew --prefix nvm)/nvm.sh
- nvm install iojs-v2
- nvm use iojs-v2
- npm config set spin=false
- npm install
script:
- |
nvm use iojs-v2
if [ "$TEST_TYPE" = objc ]
then
@@ -38,7 +37,7 @@ script:
then
cd website
npm install
$(which npm) install
./setup.sh
if [ "$TRAVIS_PULL_REQUEST" = false ] && [ "$TRAVIS_BRANCH" = master ]; then
# Automatically publish the website
+19 -25
View File
@@ -12,7 +12,7 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1461632C1AC3E22900C2F5AD /* libReact.a */; };
58C1E40E1ACF54E9006D1A47 /* libRCTAnimationExperimental.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C1E40B1ACF54B4006D1A47 /* libRCTAnimationExperimental.a */; };
5F82F1781B85785200FAE87E /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F82F1771B85784500FAE87E /* libRCTWebSocket.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
/* End PBXBuildFile section */
@@ -24,12 +24,12 @@
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
58C1E40A1ACF54B4006D1A47 /* PBXContainerItemProxy */ = {
5F82F1761B85784500FAE87E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */;
containerPortal = 5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTAnimationExperimental;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
@@ -41,7 +41,6 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimationExperimental.xcodeproj; path = ../../Libraries/Animation/RCTAnimationExperimental.xcodeproj; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* 2048.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = 2048.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = 2048/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = 2048/AppDelegate.m; sourceTree = "<group>"; };
@@ -50,6 +49,7 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = 2048/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = 2048/main.m; sourceTree = "<group>"; };
146163271AC3E22900C2F5AD /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -58,8 +58,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5F82F1781B85785200FAE87E /* libRCTWebSocket.a in Frameworks */,
1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */,
58C1E40E1ACF54E9006D1A47 /* libRCTAnimationExperimental.a in Frameworks */,
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -88,10 +88,10 @@
name = Products;
sourceTree = "<group>";
};
58C1E4071ACF54B4006D1A47 /* Products */ = {
5F82F1731B85784500FAE87E /* Products */ = {
isa = PBXGroup;
children = (
58C1E40B1ACF54B4006D1A47 /* libRCTAnimationExperimental.a */,
5F82F1771B85784500FAE87E /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
@@ -99,9 +99,9 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */,
146163271AC3E22900C2F5AD /* React.xcodeproj */,
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@@ -174,14 +174,14 @@
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 58C1E4071ACF54B4006D1A47 /* Products */;
ProjectRef = 13ACB66C1AC2113500FF4204 /* RCTAnimationExperimental.xcodeproj */;
},
{
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
},
{
ProductGroup = 5F82F1731B85784500FAE87E /* Products */;
ProjectRef = 5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 146163281AC3E22900C2F5AD /* Products */;
ProjectRef = 146163271AC3E22900C2F5AD /* React.xcodeproj */;
@@ -202,11 +202,11 @@
remoteRef = 1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
58C1E40B1ACF54B4006D1A47 /* libRCTAnimationExperimental.a */ = {
5F82F1771B85784500FAE87E /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTAnimationExperimental.a;
remoteRef = 58C1E40A1ACF54B4006D1A47 /* PBXContainerItemProxy */;
path = libRCTWebSocket.a;
remoteRef = 5F82F1761B85784500FAE87E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
@@ -266,10 +266,7 @@
);
INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/sahrens/src/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Animation/build/Debug-iphoneos",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = 2048;
@@ -287,10 +284,7 @@
);
INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/sahrens/src/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Animation/build/Debug-iphoneos",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = 2048;
+1
View File
@@ -52,6 +52,7 @@
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"Game2048"
initialProperties:nil
launchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+3 -2
View File
@@ -37,14 +37,14 @@
* on the same Wi-Fi network.
*/
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle"];
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/Movies/MoviesApp.ios.includeRequire.runModule.bundle"];
/**
* OPTION 2
* Load from pre-bundled file on disk. To re-generate the static bundle, `cd`
* to your Xcode project folder in the terminal, and run
*
* $ curl 'http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle' -o main.jsbundle
* $ curl 'http://localhost:8081/Examples/Movies/MoviesApp.ios.includeRequire.runModule.bundle' -o main.jsbundle
*
* then add the `main.jsbundle` file to your project and uncomment this line:
*/
@@ -53,6 +53,7 @@
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"MoviesApp"
initialProperties:nil
launchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+94
View File
@@ -0,0 +1,94 @@
/**
* 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 MoviesApp
* @flow
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
BackAndroid,
Navigator,
StyleSheet,
ToolbarAndroid,
View,
} = React;
var MovieScreen = require('./MovieScreen');
var SearchScreen = require('./SearchScreen');
var _navigator;
BackAndroid.addEventListener('hardwareBackPress', () => {
if (_navigator && _navigator.getCurrentRoutes().length > 1) {
_navigator.pop();
return true;
}
return false;
});
var RouteMapper = function(route, navigationOperations, onComponentRef) {
_navigator = navigationOperations;
if (route.name === 'search') {
return (
<SearchScreen navigator={navigationOperations} />
);
} else if (route.name === 'movie') {
return (
<View style={{flex: 1}}>
<ToolbarAndroid
actions={[]}
navIcon={require('image!android_back_white')}
onIconClicked={navigationOperations.pop}
style={styles.toolbar}
titleColor="white"
title={route.movie.title} />
<MovieScreen
style={{flex: 1}}
navigator={navigationOperations}
movie={route.movie}
/>
</View>
);
}
};
var MoviesApp = React.createClass({
render: function() {
var initialRoute = {name: 'search'};
return (
<Navigator
style={styles.container}
initialRoute={initialRoute}
configureScene={() => Navigator.SceneConfigs.FadeAndroid}
renderScene={RouteMapper}
/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
toolbar: {
backgroundColor: '#a9a9a9',
height: 56,
},
});
AppRegistry.registerComponent('MoviesApp', () => MoviesApp);
module.exports = MoviesApp;
+104
View File
@@ -0,0 +1,104 @@
/**
* 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 SearchBar
* @flow
*/
'use strict';
var React = require('react-native');
var {
Image,
Platform,
ProgressBarAndroid,
TextInput,
StyleSheet,
TouchableNativeFeedback,
View,
} = React;
var IS_RIPPLE_EFFECT_SUPPORTED = Platform.Version >= 21;
var SearchBar = React.createClass({
render: function() {
var loadingView;
if (this.props.isLoading) {
loadingView = (
<ProgressBarAndroid
styleAttr="Large"
style={styles.spinner}
/>
);
} else {
loadingView = <View style={styles.spinner} />;
}
var background = IS_RIPPLE_EFFECT_SUPPORTED ?
TouchableNativeFeedback.SelectableBackgroundBorderless() :
TouchableNativeFeedback.SelectableBackground();
return (
<View style={styles.searchBar}>
<TouchableNativeFeedback
background={background}
onPress={() => this.refs.input && this.refs.input.focus()}>
<View>
<Image
source={require('image!android_search_white')}
style={styles.icon}
/>
</View>
</TouchableNativeFeedback>
<TextInput
ref="input"
autoCapitalize="none"
autoCorrect={false}
autoFocus={true}
onChange={this.props.onSearchChange}
placeholder="Search a movie..."
placeholderTextColor="rgba(255, 255, 255, 0.5)"
onFocus={this.props.onFocus}
style={styles.searchBarInput}
/>
{loadingView}
</View>
);
}
});
var styles = StyleSheet.create({
searchBar: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#a9a9a9',
height: 56,
},
searchBarInput: {
flex: 1,
fontSize: 20,
fontWeight: 'bold',
color: 'white',
height: 50,
padding: 0,
backgroundColor: 'transparent'
},
spinner: {
width: 30,
height: 30,
},
icon: {
width: 24,
height: 24,
marginHorizontal: 8,
},
});
module.exports = SearchBar;
+35
View File
@@ -0,0 +1,35 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.facebook.react.movies"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
// Depend on pre-built React Native
compile 'com.facebook.react:react-native:0.11.+'
// Depend on React Native source.
// This is useful for testing your changes when working on React Native.
// compile project(':ReactAndroid')
}
+17
View File
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,21 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.react.movies">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@drawable/rotten_tomatoes_icon"
android:theme="@style/AppTheme">
<activity
android:name=".MoviesActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
@@ -0,0 +1,89 @@
/**
* 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.
*/
package com.facebook.react.movies;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;
public class MoviesActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("MoviesApp.android.bundle")
.setJSMainModuleName("Examples/Movies/MoviesApp.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(true)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
((ReactRootView) findViewById(R.id.react_root_view))
.startReactApplication(mReactInstanceManager, "MoviesApp", null);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this);
}
}
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@@ -0,0 +1,12 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MoviesApp">
<com.facebook.react.ReactRootView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/react_root_view"/>
</RelativeLayout>
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">MoviesApp</string>
</resources>
@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
+5 -6
View File
@@ -10,11 +10,8 @@
# Ignore react-tools where there are overlaps, but don't ignore anything that
# react-native relies on
.*/node_modules/react-tools/src/React.js
.*/node_modules/react-tools/src/renderers/shared/reconciler/ReactInstanceHandles.js
.*/node_modules/react-tools/src/renderers/shared/event/EventPropagators.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderSyntheticEvent.js
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderTouchHistoryStore.js
.*/node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js
@@ -35,13 +32,15 @@ node_modules/react-native/Libraries/react-native/react-native-interface.js
[options]
module.system=haste
munge_underscores=true
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-3]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-4]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-4]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
[version]
0.13.1
0.14.0
+1
View File
@@ -0,0 +1 @@
{}
@@ -0,0 +1,35 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.facebook.react.sample"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.0'
// Depend on pre-built React Native
compile 'com.facebook.react:react-native:0.11.+'
// Depend on React Native source.
// This is useful for testing your changes when working on React Native.
// compile project(':ReactAndroid')
}
+17
View File
@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
@@ -0,0 +1,21 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.react.sample">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
@@ -0,0 +1,88 @@
/**
* 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.
*/
package com.facebook.react.sample;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactInstanceManager mReactInstanceManager;
private ReactRootView mReactRootView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SoLoader.init(this, false);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("Examples/SampleApp/index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(
mReactInstanceManager,
"SampleApp",
null);
setContentView(mReactRootView);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this);
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">SampleApp</string>
</resources>
@@ -0,0 +1,8 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
@@ -106,27 +106,27 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
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>"; };
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>"; };
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../../Libraries/ActionSheetIOS/RCTActionSheet.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>"; };
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
00E356EE1AD99517003FC87E /* SampleAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
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>"; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = iOS/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = "<group>"; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../../React/React.xcodeproj; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -233,15 +233,15 @@
13B07FAE1A68108700A75B9A /* SampleApp */ = {
isa = PBXGroup;
children = (
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FB71A68108700A75B9A /* main.m */,
);
name = SampleApp;
path = SampleApp;
sourceTree = "<group>";
};
146834001AC3E56700842450 /* Products */ = {
@@ -289,8 +289,8 @@
isa = PBXGroup;
children = (
13B07FAE1A68108700A75B9A /* SampleApp */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* SampleAppTests */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
);
indentWidth = 2;
@@ -548,7 +548,6 @@
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
path = iOS;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
@@ -566,6 +565,11 @@
"DEBUG=1",
"$(inherited)",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../../React/**",
);
INFOPLIST_FILE = SampleAppTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -583,6 +587,11 @@
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../../React/**",
);
INFOPLIST_FILE = SampleAppTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@@ -598,9 +607,9 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
"$(SRCROOT)/../../../React/**",
);
INFOPLIST_FILE = "iOS/Info.plist";
INFOPLIST_FILE = "$(SRCROOT)/SampleApp/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = SampleApp;
@@ -614,9 +623,9 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
"$(SRCROOT)/../../../React/**",
);
INFOPLIST_FILE = "iOS/Info.plist";
INFOPLIST_FILE = "$(SRCROOT)/SampleApp/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = SampleApp;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "0630"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -0,0 +1,61 @@
/**
* 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.
*/
#import "AppDelegate.h"
#import "RCTRootView.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
/**
* Loading JavaScript code - uncomment the one you want.
*
* OPTION 1
* Load from development server. Start the server from the repository root:
*
* $ npm start
*
* To run on device, change `localhost` to the IP address of your computer
* (you can get this by typing `ifconfig` into the terminal and selecting the
* `inet` value under `en0:`) and make sure your computer and iOS device are
* on the same Wi-Fi network.
*/
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/SampleApp/index.ios.bundle"];
/**
* OPTION 2
* Load from pre-bundled file on disk. To re-generate the static bundle
* from the root of your project directory, run
*
* $ react-native bundle --minify
*
* see http://facebook.github.io/react-native/docs/runningondevice.html
*/
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"SampleApp"
initialProperties:nil
launchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6751" systemVersion="14C1510" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6736"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
@@ -10,8 +10,7 @@
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "RCTAssert.h"
#import "RCTRedBox.h"
#import "RCTLog.h"
#import "RCTRootView.h"
#define TIMEOUT_SECONDS 240
@@ -23,7 +22,6 @@
@implementation SampleAppTests
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
{
if (test(view)) {
@@ -37,18 +35,23 @@
return NO;
}
- (void)testRendersWelcomeScreen {
- (void)testRendersWelcomeScreen
{
UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
BOOL foundElement = NO;
NSString *redboxError = nil;
__block NSString *redboxError = nil;
RCTSetLogFunction(^(RCTLogLevel level, NSString *fileName, NSNumber *lineNumber, NSString *message) {
if (level >= RCTLogLevelError) {
redboxError = message;
}
});
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
redboxError = [[RCTRedBox sharedInstance] currentErrorMessage];
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
return YES;
@@ -57,6 +60,8 @@
}];
}
RCTSetLogFunction(RCTDefaultLogFunction);
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
}
+52
View File
@@ -0,0 +1,52 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
} = React;
var SampleApp = React.createClass({
render: function() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
Shake or press menu button for dev menu
</Text>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);
@@ -14,6 +14,7 @@
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
144C5F691AC3E5E300B004E7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 144C5F681AC3E5D800B004E7 /* libReact.a */; };
58C572511AA6229D00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5724D1AA6224400CDF9C8 /* libRCTText.a */; };
5FF8942E1B85571A007731BE /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FF8942D1B8556F8007731BE /* libRCTWebSocket.a */; };
832044981B492C2500E297FC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832044951B492C1E00E297FC /* libRCTSettings.a */; };
/* End PBXBuildFile section */
@@ -39,6 +40,13 @@
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
5FF8942C1B8556F8007731BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5FF894281B8556F8007731BE /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
832044941B492C1E00E297FC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8320448F1B492C1E00E297FC /* RCTSettings.xcodeproj */;
@@ -59,6 +67,7 @@
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = TicTacToe/main.m; sourceTree = "<group>"; };
144C5F631AC3E5D800B004E7 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
5FF894281B8556F8007731BE /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
8320448F1B492C1E00E297FC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -67,6 +76,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5FF8942E1B85571A007731BE /* libRCTWebSocket.a in Frameworks */,
144C5F691AC3E5E300B004E7 /* libReact.a in Frameworks */,
1341803E1AA91802003F314A /* libRCTImage.a in Frameworks */,
58C572511AA6229D00CDF9C8 /* libRCTText.a in Frameworks */,
@@ -109,6 +119,7 @@
58C572071AA6126D00CDF9C8 /* Libraries */ = {
isa = PBXGroup;
children = (
5FF894281B8556F8007731BE /* RCTWebSocket.xcodeproj */,
144C5F631AC3E5D800B004E7 /* React.xcodeproj */,
134180381AA917ED003F314A /* RCTImage.xcodeproj */,
8320448F1B492C1E00E297FC /* RCTSettings.xcodeproj */,
@@ -125,6 +136,14 @@
name = Products;
sourceTree = "<group>";
};
5FF894291B8556F8007731BE /* Products */ = {
isa = PBXGroup;
children = (
5FF8942D1B8556F8007731BE /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
832044901B492C1E00E297FC /* Products */ = {
isa = PBXGroup;
children = (
@@ -205,6 +224,10 @@
ProductGroup = 58C572481AA6224300CDF9C8 /* Products */;
ProjectRef = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */;
},
{
ProductGroup = 5FF894291B8556F8007731BE /* Products */;
ProjectRef = 5FF894281B8556F8007731BE /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 144C5F641AC3E5D800B004E7 /* Products */;
ProjectRef = 144C5F631AC3E5D800B004E7 /* React.xcodeproj */;
@@ -239,6 +262,13 @@
remoteRef = 58C5724C1AA6224400CDF9C8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
5FF8942D1B8556F8007731BE /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 5FF8942C1B8556F8007731BE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
832044951B492C1E00E297FC /* libRCTSettings.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -52,6 +52,7 @@
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"TicTacToeApp"
initialProperties:nil
launchOptions:launchOptions];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
@@ -0,0 +1,213 @@
/**
* 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.
*
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
Text,
View,
ToastAndroid,
TouchableWithoutFeedback,
} = React;
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var importantForAccessibilityValues = ['auto', 'yes', 'no', 'no-hide-descendants'];
var AccessibilityAndroidExample = React.createClass({
statics: {
title: 'Accessibility',
description: 'Examples of using Accessibility API.',
},
getInitialState: function() {
return {
count: 0,
backgroundImportantForAcc: 0,
forgroundImportantForAcc: 0,
};
},
_addOne: function() {
this.setState({
count: ++this.state.count,
});
},
_changeBackgroundImportantForAcc: function() {
this.setState({
backgroundImportantForAcc: (this.state.backgroundImportantForAcc + 1) % 4,
});
},
_changeForgroundImportantForAcc: function() {
this.setState({
forgroundImportantForAcc: (this.state.forgroundImportantForAcc + 1) % 4,
});
},
render: function() {
return (
<UIExplorerPage title={'Accessibility'}>
<UIExplorerBlock title="Nonaccessible view with TextViews">
<View>
<Text style={{color: 'green',}}>
This is
</Text>
<Text style={{color: 'blue'}}>
nontouchable normal view.
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Accessible view with TextViews wihout label">
<View accessible={true}>
<Text style={{color: 'green',}}>
This is
</Text>
<Text style={{color: 'blue'}}>
nontouchable accessible view without label.
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Accessible view with TextViews with label">
<View accessible={true}
accessibilityLabel="I have label, so I read it instead of embedded text.">
<Text style={{color: 'green',}}>
This is
</Text>
<Text style={{color: 'blue'}}>
nontouchable accessible view with label.
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Touchable with component type = button">
<TouchableWithoutFeedback
onPress={() => ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT)}
accessibilityComponentType="button">
<View style={styles.embedded}>
<Text>Click me</Text>
<Text>Or not</Text>
</View>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="LiveRegion">
<TouchableWithoutFeedback onPress={this._addOne}>
<View style={styles.embedded}>
<Text>Click me</Text>
</View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
Clicked {this.state.count} times
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Overlapping views and importantForAccessibility property">
<View style={styles.container}>
<View
style={{
position: 'absolute',
left: 10,
top: 10,
right: 10,
height: 100,
backgroundColor: 'green'}}
accessible={true}
accessibilityLabel="First layout"
importantForAccessibility={
importantForAccessibilityValues[this.state.backgroundImportantForAcc]}>
<View accessible={true}>
<Text style={{fontSize: 25}}>
Hello
</Text>
</View>
</View>
<View
style={{
position: 'absolute',
left: 10,
top: 25,
right: 10,
height: 110,
backgroundColor: 'yellow', opacity: 0.5}}
accessible={true}
accessibilityLabel="Second layout"
importantForAccessibility={
importantForAccessibilityValues[this.state.forgroundImportantForAcc]}>
<View accessible={true}>
<Text style={{fontSize: 20}}>
world
</Text>
</View>
</View>
</View>
<TouchableWithoutFeedback onPress={this._changeBackgroundImportantForAcc}>
<View style={styles.embedded}>
<Text>
Change importantForAccessibility for background layout.
</Text>
</View>
</TouchableWithoutFeedback>
<View accessible={true}>
<Text>
Background layout importantForAccessibility
</Text>
<Text>
{importantForAccessibilityValues[this.state.backgroundImportantForAcc]}
</Text>
</View>
<TouchableWithoutFeedback onPress={this._changeForgroundImportantForAcc}>
<View style={styles.embedded}>
<Text>
Change importantForAccessibility for forground layout.
</Text>
</View>
</TouchableWithoutFeedback>
<View accessible={true}>
<Text>
Forground layout importantForAccessibility
</Text>
<Text>
{importantForAccessibilityValues[this.state.forgroundImportantForAcc]}
</Text>
</View>
</UIExplorerBlock>
</UIExplorerPage>
);
},
});
var styles = StyleSheet.create({
embedded: {
backgroundColor: 'yellow',
padding:10,
},
container: {
flex: 1,
backgroundColor: 'white',
padding: 10,
height:150,
},
});
module.exports = AccessibilityAndroidExample;
@@ -0,0 +1,256 @@
/**
* 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.
*
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
Text,
View,
TouchableWithoutFeedback,
} = React;
var ToastAndroid = require('ToastAndroid');
var AccessibilityInfo = require('AccessibilityInfo');
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var importantForAccessibilityValues = ['auto', 'yes', 'no', 'no-hide-descendants'];
var AccessibilityAndroidExample = React.createClass({
statics: {
title: 'Accessibility',
description: 'Examples of using Accessibility API.',
},
getInitialState: function() {
return {
count: 0,
talkbackEnabled: false,
backgroundImportantForAcc: 0,
forgroundImportantForAcc: 0,
};
},
componentDidMount: function() {
AccessibilityInfo.addEventListener(
'change',
this._handleTouchExplorationChange
);
AccessibilityInfo.fetch().done((enabled) => {
this.setState({
count: this.state.count,
talkbackEnabled: enabled}); }
);
},
componentWillUnmount: function() {
AccessibilityInfo.removeEventListener(
'change',
this._handleTouchExplorationChange
);
},
_handleTouchExplorationChange: function(isEnabled) {
this.setState({
count: this.state.count,
talkbackEnabled: isEnabled,
});
},
_showAccessibilityToast: function() {
var text = 'TouchExploration is ' + (this.state.talkbackEnabled ? 'enabled' : 'disabled');
ToastAndroid.show(text, ToastAndroid.SHORT);
},
_addOne: function() {
this.setState({
count: ++this.state.count,
talkbackEnabled: this.state.talkbackEnabled,
});
},
_changeBackgroundImportantForAcc: function() {
this.setState({
backgroundImportantForAcc: (this.state.backgroundImportantForAcc + 1) % 4,
});
},
_changeForgroundImportantForAcc: function() {
this.setState({
forgroundImportantForAcc: (this.state.forgroundImportantForAcc + 1) % 4,
});
},
render: function() {
return (
<UIExplorerPage title={'Accessibility'}>
<UIExplorerBlock title="Nonaccessible view with TextViews">
<View>
<Text style={{color: 'green',}}>
This is
</Text>
<Text style={{color: 'blue'}}>
nontouchable normal view.
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Accessible view with TextViews wihout label">
<View accessible={true}>
<Text style={{color: 'green',}}>
This is
</Text>
<Text style={{color: 'blue'}}>
nontouchable accessible view without label.
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Accessible view with TextViews with label">
<View accessible={true}
accessibilityLabel="I have label, so I read it instead of embedded text.">
<Text style={{color: 'green',}}>
This is
</Text>
<Text style={{color: 'blue'}}>
nontouchable accessible view with label.
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Touchable with component type = button">
<TouchableWithoutFeedback
onPress={() => ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT)}>
<View style={styles.embedded} accessibilityComponentType="button">
<Text>Click me</Text>
<Text>Or not</Text>
</View>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="LiveRegion">
<TouchableWithoutFeedback onPress={this._addOne}>
<View style={styles.embedded} accessibilityComponentType="button">
<Text>Click me</Text>
</View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
Clicked {this.state.count} times
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Check if TouchExploration is enabled">
<TouchableWithoutFeedback onPress={this._showAccessibilityToast}>
<View style={styles.embedded}>
<Text>
Click to check TouchExploration
</Text>
</View>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="Overlapping views and importantForAccessibility property">
<View style={styles.container}>
<View
style={{
position: 'absolute',
left: 10,
top: 10,
right: 10,
height: 100,
backgroundColor: 'green'}}
accessible={true}
accessibilityLabel="First layout"
importantForAccessibility={
importantForAccessibilityValues[this.state.backgroundImportantForAcc]}>
<View accessible={true}>
<Text style={{fontSize: 25}}>
Hello
</Text>
</View>
</View>
<View
style={{
position: 'absolute',
left: 10,
top: 25,
right: 10,
height: 110,
backgroundColor: 'yellow', opacity: 0.5}}
accessible={true}
accessibilityLabel="Second layout"
importantForAccessibility={
importantForAccessibilityValues[this.state.forgroundImportantForAcc]}>
<View accessible={true}>
<Text style={{fontSize: 20}}>
world
</Text>
</View>
</View>
</View>
<TouchableWithoutFeedback onPress={this._changeBackgroundImportantForAcc}>
<View style={styles.embedded}>
<Text>
Change importantForAccessibility for background layout.
</Text>
</View>
</TouchableWithoutFeedback>
<View accessible={true}>
<Text>
Background layout importantForAccessibility
</Text>
<Text>
{importantForAccessibilityValues[this.state.backgroundImportantForAcc]}
</Text>
</View>
<TouchableWithoutFeedback onPress={this._changeForgroundImportantForAcc}>
<View style={styles.embedded}>
<Text>
Change importantForAccessibility for forground layout.
</Text>
</View>
</TouchableWithoutFeedback>
<View accessible={true}>
<Text>
Forground layout importantForAccessibility
</Text>
<Text>
{importantForAccessibilityValues[this.state.forgroundImportantForAcc]}
</Text>
</View>
</UIExplorerBlock>
</UIExplorerPage>
);
},
});
var styles = StyleSheet.create({
embedded: {
backgroundColor: 'yellow',
padding:10,
},
container: {
flex: 1,
backgroundColor: 'white',
padding: 10,
height:150,
},
});
module.exports = AccessibilityAndroidExample;
@@ -38,9 +38,11 @@ class Circle extends React.Component {
super();
this._onLongPress = this._onLongPress.bind(this);
this._toggleIsActive = this._toggleIsActive.bind(this);
this.state = {isActive: false};
this.state.pan = new Animated.ValueXY(); // Vectors reduce boilerplate. (step1: uncomment)
this.state.pop = new Animated.Value(0); // Initial value. (step2a: uncomment)
this.state = {
isActive: false,
pan: new Animated.ValueXY(), // Vectors reduce boilerplate. (step1: uncomment)
pop: new Animated.Value(0), // Initial value. (step2a: uncomment)
};
}
_onLongPress(): void {
+30 -21
View File
@@ -29,18 +29,23 @@ var COLORS = ['red', 'orange', 'yellow', 'green', 'blue'];
var BasicStorageExample = React.createClass({
componentDidMount() {
AsyncStorage.getItem(STORAGE_KEY)
.then((value) => {
if (value !== null){
this.setState({selectedValue: value});
this._appendMessage('Recovered selection from disk: ' + value);
} else {
this._appendMessage('Initialized with no selection on disk.');
}
})
.catch((error) => this._appendMessage('AsyncStorage error: ' + error.message))
.done();
this._loadInitialState().done();
},
async _loadInitialState() {
try {
var value = await AsyncStorage.getItem(STORAGE_KEY);
if (value !== null){
this.setState({selectedValue: value});
this._appendMessage('Recovered selection from disk: ' + value);
} else {
this._appendMessage('Initialized with no selection on disk.');
}
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
getInitialState() {
return {
selectedValue: COLORS[0],
@@ -80,19 +85,23 @@ var BasicStorageExample = React.createClass({
);
},
_onValueChange(selectedValue) {
async _onValueChange(selectedValue) {
this.setState({selectedValue});
AsyncStorage.setItem(STORAGE_KEY, selectedValue)
.then(() => this._appendMessage('Saved selection to disk: ' + selectedValue))
.catch((error) => this._appendMessage('AsyncStorage error: ' + error.message))
.done();
try {
await AsyncStorage.setItem(STORAGE_KEY, selectedValue);
this._appendMessage('Saved selection to disk: ' + selectedValue);
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
_removeStorage() {
AsyncStorage.removeItem(STORAGE_KEY)
.then(() => this._appendMessage('Selection removed from disk.'))
.catch((error) => { this._appendMessage('AsyncStorage error: ' + error.message) })
.done();
async _removeStorage() {
try {
await AsyncStorage.removeItem(STORAGE_KEY);
this._appendMessage('Selection removed from disk.');
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
_appendMessage(message) {
+305
View File
@@ -0,0 +1,305 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
CameraRoll,
Image,
NativeModules,
ScrollView,
StyleSheet,
Text,
TouchableHighlight,
View,
} = React;
var ImageEditingManager = NativeModules.ImageEditingManager;
var RCTScrollViewConsts = NativeModules.UIManager.RCTScrollView.Constants;
var PAGE_SIZE = 20;
type ImageOffset = {
x: number;
y: number;
};
type ImageSize = {
width: number;
height: number;
};
type TransformData = {
offset: ImageOffset;
size: ImageSize;
}
class SquareImageCropper extends React.Component {
_isMounted: boolean;
_transformData: TransformData;
constructor(props) {
super(props);
this._isMounted = true;
this.state = {
randomPhoto: null,
measuredSize: null,
croppedImageURI: null,
cropError: null,
};
this._fetchRandomPhoto();
}
_fetchRandomPhoto() {
CameraRoll.getPhotos(
{first: PAGE_SIZE},
(data) => {
if (!this._isMounted) {
return;
}
var edges = data.edges;
var edge = edges[Math.floor(Math.random() * edges.length)];
var randomPhoto = edge && edge.node && edge.node.image;
if (randomPhoto) {
this.setState({randomPhoto});
}
},
(error) => undefined
);
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
if (!this.state.measuredSize) {
return (
<View
style={styles.container}
onLayout={(event) => {
var measuredWidth = event.nativeEvent.layout.width;
if (!measuredWidth) {
return;
}
this.setState({
measuredSize: {width: measuredWidth, height: measuredWidth},
});
}}
/>
);
}
if (!this.state.croppedImageURI) {
return this._renderImageCropper();
}
return this._renderCroppedImage();
}
_renderImageCropper() {
if (!this.state.randomPhoto) {
return (
<View style={styles.container} />
);
}
var error = null;
if (this.state.cropError) {
error = (
<Text>{this.state.cropError.message}</Text>
);
}
return (
<View style={styles.container}>
<Text>Drag the image within the square to crop:</Text>
<ImageCropper
image={this.state.randomPhoto}
size={this.state.measuredSize}
style={[styles.imageCropper, this.state.measuredSize]}
onTransformDataChange={(data) => this._transformData = data}
/>
<TouchableHighlight
style={styles.cropButtonTouchable}
onPress={this._crop.bind(this)}>
<View style={styles.cropButton}>
<Text style={styles.cropButtonLabel}>
Crop
</Text>
</View>
</TouchableHighlight>
{error}
</View>
);
}
_renderCroppedImage() {
return (
<View style={styles.container}>
<Text>Here is the cropped image:</Text>
<Image
source={{uri: this.state.croppedImageURI}}
style={[styles.imageCropper, this.state.measuredSize]}
/>
<TouchableHighlight
style={styles.cropButtonTouchable}
onPress={this._reset.bind(this)}>
<View style={styles.cropButton}>
<Text style={styles.cropButtonLabel}>
Try again
</Text>
</View>
</TouchableHighlight>
</View>
);
}
_crop() {
ImageEditingManager.cropImage(
this.state.randomPhoto.uri,
this._transformData,
(croppedImageURI) => this.setState({croppedImageURI}),
(cropError) => this.setState({cropError})
);
}
_reset() {
this.setState({
randomPhoto: null,
croppedImageURI: null,
cropError: null,
});
this._fetchRandomPhoto();
}
}
class ImageCropper extends React.Component {
_scaledImageSize: ImageSize;
_contentOffset: ImageOffset;
componentWillMount() {
// Scale an image to the minimum size that is large enough to completely
// fill the crop box.
var widthRatio = this.props.image.width / this.props.size.width;
var heightRatio = this.props.image.height / this.props.size.height;
if (widthRatio < heightRatio) {
this._scaledImageSize = {
width: this.props.size.width,
height: this.props.image.height / widthRatio,
};
} else {
this._scaledImageSize = {
width: this.props.image.width / heightRatio,
height: this.props.size.height,
};
}
this._contentOffset = {
x: (this._scaledImageSize.width - this.props.size.width) / 2,
y: (this._scaledImageSize.height - this.props.size.height) / 2,
};
this._updateTransformData(
this._contentOffset,
this._scaledImageSize,
this.props.size
);
}
_onScroll(event) {
this._updateTransformData(
event.nativeEvent.contentOffset,
event.nativeEvent.contentSize,
event.nativeEvent.layoutMeasurement
);
}
_updateTransformData(offset, scaledImageSize, croppedImageSize) {
var offsetRatioX = offset.x / scaledImageSize.width;
var offsetRatioY = offset.y / scaledImageSize.height;
var sizeRatioX = croppedImageSize.width / scaledImageSize.width;
var sizeRatioY = croppedImageSize.height / scaledImageSize.height;
this.props.onTransformDataChange && this.props.onTransformDataChange({
offset: {
x: this.props.image.width * offsetRatioX,
y: this.props.image.height * offsetRatioY,
},
size: {
width: this.props.image.width * sizeRatioX,
height: this.props.image.height * sizeRatioY,
},
});
}
render() {
var decelerationRate =
RCTScrollViewConsts && RCTScrollViewConsts.DecelerationRate ?
RCTScrollViewConsts.DecelerationRate.Fast :
0;
return (
<ScrollView
alwaysBounceVertical={true}
automaticallyAdjustContentInsets={false}
contentOffset={this._contentOffset}
decelerationRate={decelerationRate}
horizontal={true}
maximumZoomScale={3.0}
onMomentumScrollEnd={this._onScroll.bind(this)}
onScrollEndDrag={this._onScroll.bind(this)}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
style={this.props.style}
scrollEventThrottle={16}>
<Image source={this.props.image} style={this._scaledImageSize} />
</ScrollView>
);
}
}
exports.framework = 'React';
exports.title = 'ImageEditingManager';
exports.description = 'Cropping and scaling with ImageEditingManager';
exports.examples = [{
title: 'Image Cropping',
render() {
return <SquareImageCropper/>;
}
}];
var styles = StyleSheet.create({
container: {
flex: 1,
alignSelf: 'stretch',
},
imageCropper: {
alignSelf: 'center',
marginTop: 12,
},
cropButtonTouchable: {
alignSelf: 'center',
marginTop: 12,
},
cropButton: {
padding: 12,
backgroundColor: 'blue',
borderRadius: 4,
},
cropButtonLabel: {
color: 'white',
fontSize: 16,
fontWeight: '500',
},
});
+1 -1
View File
@@ -340,7 +340,7 @@ exports.examples = [
];
var fullImage = {uri: 'http://facebook.github.io/react/img/logo_og.png'};
var smallImage = {uri: 'http://facebook.github.io/react/img/logo_small.png'};
var smallImage = {uri: 'http://facebook.github.io/react/img/logo_small_2x.png'};
var styles = StyleSheet.create({
base: {
+10 -10
View File
@@ -15,37 +15,37 @@
*/
'use strict';
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare module 'image!story-background' {
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare var uri: string;
declare var isStatic: boolean;
}
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare module 'image!uie_comment_highlighted' {
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare var uri: string;
declare var isStatic: boolean;
}
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare module 'image!uie_comment_normal' {
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare var uri: string;
declare var isStatic: boolean;
}
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare module 'image!uie_thumb_normal' {
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare var uri: string;
declare var isStatic: boolean;
}
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare module 'image!uie_thumb_selected' {
/* $FlowIssue #7387208 - There's a flow bug preventing this type from flowing
* into a proptype shape */
declare var uri: string;
declare var isStatic: boolean;
}
+3 -4
View File
@@ -49,8 +49,7 @@ var LayoutEventExample = React.createClass({
() => {
console.log('layout animation done.');
this.addWrapText();
},
(error) => { throw new Error(JSON.stringify(error)); }
}
);
this.setState({
viewStyle: {
@@ -139,11 +138,11 @@ var styles = StyleSheet.create({
},
});
exports.title = 'onLayout';
exports.title = 'Layout Events';
exports.description = 'Layout events can be used to measure view size and position.';
exports.examples = [
{
title: 'onLayout',
title: 'LayoutEventExample',
render: function(): ReactElement {
return <LayoutEventExample />;
},
+172
View File
@@ -0,0 +1,172 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
Modal,
StyleSheet,
SwitchIOS,
Text,
TouchableHighlight,
View,
} = React;
exports.displayName = (undefined: ?string);
exports.framework = 'React';
exports.title = '<Modal>';
exports.description = 'Component for presenting modal views.';
var Button = React.createClass({
getInitialState() {
return {
active: false,
};
},
_onHighlight() {
this.setState({active: true});
},
_onUnhighlight() {
this.setState({active: false});
},
render() {
var colorStyle = {
color: this.state.active ? '#fff' : '#000',
};
return (
<TouchableHighlight
onHideUnderlay={this._onUnhighlight}
onPress={this.props.onPress}
onShowUnderlay={this._onHighlight}
style={[styles.button, this.props.style]}
underlayColor="#a9d9d4">
<Text style={[styles.buttonText, colorStyle]}>{this.props.children}</Text>
</TouchableHighlight>
);
}
});
var ModalExample = React.createClass({
getInitialState() {
return {
animated: true,
modalVisible: false,
transparent: false,
};
},
_setModalVisible(visible) {
this.setState({modalVisible: visible});
},
_toggleAnimated() {
this.setState({animated: !this.state.animated});
},
_toggleTransparent() {
this.setState({transparent: !this.state.transparent});
},
render() {
var modalBackgroundStyle = {
backgroundColor: this.state.transparent ? 'rgba(0, 0, 0, 0.5)' : '#f5fcff',
};
var innerContainerTransparentStyle = this.state.transparent
? {backgroundColor: '#fff', padding: 20}
: null;
return (
<View>
<Modal
animated={this.state.animated}
transparent={this.state.transparent}
visible={this.state.modalVisible}>
<View style={[styles.container, modalBackgroundStyle]}>
<View style={[styles.innerContainer, innerContainerTransparentStyle]}>
<Text>This modal was presented {this.state.animated ? 'with' : 'without'} animation.</Text>
<Button
onPress={this._setModalVisible.bind(this, false)}
style={styles.modalButton}>
Close
</Button>
</View>
</View>
</Modal>
<View style={styles.row}>
<Text style={styles.rowTitle}>Animated</Text>
<SwitchIOS value={this.state.animated} onValueChange={this._toggleAnimated} />
</View>
<View style={styles.row}>
<Text style={styles.rowTitle}>Transparent</Text>
<SwitchIOS value={this.state.transparent} onValueChange={this._toggleTransparent} />
</View>
<Button onPress={this._setModalVisible.bind(this, true)}>
Present
</Button>
</View>
);
},
});
exports.examples = [
{
title: 'Modal Presentation',
description: 'Modals can be presented with or without animation',
render: () => <ModalExample />,
},
];
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
},
innerContainer: {
borderRadius: 10,
},
row: {
alignItems: 'center',
flex: 1,
flexDirection: 'row',
marginBottom: 20,
},
rowTitle: {
flex: 1,
fontWeight: 'bold',
},
button: {
borderRadius: 5,
flex: 1,
height: 44,
justifyContent: 'center',
overflow: 'hidden',
},
buttonText: {
fontSize: 18,
margin: 5,
textAlign: 'center',
},
modalButton: {
marginTop: 10,
},
});
@@ -0,0 +1,62 @@
/**
* 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.
*
* @flow
*/
'use strict';
var ProgressBar = require('ProgressBarAndroid');
var React = require('React');
var UIExplorerBlock = require('UIExplorerBlock');
var UIExplorerPage = require('UIExplorerPage');
var ProgressBarAndroidExample = React.createClass({
statics: {
title: '<ProgressBarAndroid>',
description: 'Visual indicator of progress of some operation. ' +
'Shows either a cyclic animation or a horizontal bar.',
},
render: function() {
return (
<UIExplorerPage title="ProgressBar Examples">
<UIExplorerBlock title="Default ProgressBar">
<ProgressBar />
</UIExplorerBlock>
<UIExplorerBlock title="Small ProgressBar">
<ProgressBar styleAttr="Small" />
</UIExplorerBlock>
<UIExplorerBlock title="Large ProgressBar">
<ProgressBar styleAttr="Large" />
</UIExplorerBlock>
<UIExplorerBlock title="Inverse ProgressBar">
<ProgressBar styleAttr="Inverse" />
</UIExplorerBlock>
<UIExplorerBlock title="Small Inverse ProgressBar">
<ProgressBar styleAttr="SmallInverse" />
</UIExplorerBlock>
<UIExplorerBlock title="Large Inverse ProgressBar">
<ProgressBar styleAttr="LargeInverse" />
</UIExplorerBlock>
</UIExplorerPage>
);
},
});
module.exports = ProgressBarAndroidExample;
@@ -0,0 +1,83 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
ScrollView,
StyleSheet,
Text,
TouchableOpacity
} = React;
var NUM_ITEMS = 20;
var ScrollViewSimpleExample = React.createClass({
statics: {
title: '<ScrollView>',
description: 'Component that enables scrolling through child components.'
},
makeItems: function(nItems: number, styles): Array<any> {
var items = [];
for (var i = 0; i < nItems; i++) {
items[i] = (
<TouchableOpacity key={i} style={styles}>
<Text>{'Item ' + i}</Text>
</TouchableOpacity>
);
}
return items;
},
render: function() {
// One of the items is a horizontal scroll view
var items = this.makeItems(NUM_ITEMS, styles.itemWrapper);
items[4] = (
<ScrollView key={'scrollView'} horizontal={true}>
{this.makeItems(NUM_ITEMS, [styles.itemWrapper, styles.horizontalItemWrapper])}
</ScrollView>
);
var verticalScrollView = (
<ScrollView style={styles.verticalScrollView}>
{items}
</ScrollView>
);
return verticalScrollView;
}
});
var styles = StyleSheet.create({
verticalScrollView: {
margin: 10,
},
itemWrapper: {
backgroundColor: '#dddddd',
alignItems: 'center',
borderRadius: 5,
borderWidth: 5,
borderColor: '#a52a2a',
padding: 30,
margin: 5,
},
horizontalItemWrapper: {
padding: 50
}
});
module.exports = ScrollViewSimpleExample;
@@ -0,0 +1,80 @@
/**
* 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.
*/
'use strict';
var React = require('React');
var SwitchAndroid = require('SwitchAndroid');
var Text = require('Text');
var UIExplorerBlock = require('UIExplorerBlock');
var UIExplorerPage = require('UIExplorerPage');
var SwitchAndroidExample = React.createClass({
statics: {
title: '<SwitchAndroid>',
description: 'Standard Android two-state toggle component'
},
getInitialState : function() {
return {
trueSwitchIsOn: true,
falseSwitchIsOn: false,
colorTrueSwitchIsOn: true,
colorFalseSwitchIsOn: false,
eventSwitchIsOn: false,
};
},
render: function() {
return (
<UIExplorerPage title="<SwitchAndroid>">
<UIExplorerBlock title="Switches can be set to true or false">
<SwitchAndroid
onValueChange={(value) => this.setState({falseSwitchIsOn: value})}
style={{marginBottom: 10}}
value={this.state.falseSwitchIsOn} />
<SwitchAndroid
onValueChange={(value) => this.setState({trueSwitchIsOn: value})}
value={this.state.trueSwitchIsOn} />
</UIExplorerBlock>
<UIExplorerBlock title="Switches can be disabled">
<SwitchAndroid
disabled={true}
style={{marginBottom: 10}}
value={true} />
<SwitchAndroid
disabled={true}
value={false} />
</UIExplorerBlock>
<UIExplorerBlock title="Change events can be detected">
<SwitchAndroid
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
style={{marginBottom: 10}}
value={this.state.eventSwitchIsOn} />
<SwitchAndroid
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
style={{marginBottom: 10}}
value={this.state.eventSwitchIsOn} />
<Text>{this.state.eventSwitchIsOn ? "On" : "Off"}</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Switches are controlled components">
<SwitchAndroid />
<SwitchAndroid value={true} />
</UIExplorerBlock>
</UIExplorerPage>
);
}
});
module.exports = SwitchAndroidExample;
+3
View File
@@ -23,6 +23,8 @@ var {
View,
} = React;
var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
var TabBarExample = React.createClass({
statics: {
title: '<TabBarIOS>',
@@ -55,6 +57,7 @@ var TabBarExample = React.createClass({
barTintColor="darkslateblue">
<TabBarIOS.Item
title="Blue Tab"
icon={{uri: base64Icon, scale: 3}}
selected={this.state.selectedTab === 'blueTab'}
onPress={() => {
this.setState({
+349
View File
@@ -0,0 +1,349 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
Text,
View,
} = React;
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var Entity = React.createClass({
render: function() {
return (
<Text style={{fontWeight: 'bold', color: '#527fe4'}}>
{this.props.children}
</Text>
);
}
});
var AttributeToggler = React.createClass({
getInitialState: function() {
return {fontWeight: 'bold', fontSize: 15};
},
toggleWeight: function() {
this.setState({
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold'
});
},
increaseSize: function() {
this.setState({
fontSize: this.state.fontSize + 1
});
},
render: function() {
var curStyle = {fontWeight: this.state.fontWeight, fontSize: this.state.fontSize};
return (
<View>
<Text style={curStyle}>
Tap the controls below to change attributes.
</Text>
<Text>
<Text>See how it will even work on <Text style={curStyle}>this nested text</Text></Text>
</Text>
<Text>
<Text onPress={this.toggleWeight}>Toggle Weight</Text>
{' (with highlight onPress)'}
</Text>
<Text onPress={this.increaseSize} suppressHighlighting={true}>
Increase Size (suppressHighlighting true)
</Text>
</View>
);
}
});
var TextExample = React.createClass({
statics: {
title: '<Text>',
description: 'Base component for rendering styled text.',
},
render: function() {
return (
<UIExplorerPage title="<Text>">
<UIExplorerBlock title="Wrap">
<Text>
The text should wrap if it goes on multiple lines.
See, this is going to the next line.
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Padding">
<Text style={{padding: 10}}>
This text is indented by 10px padding on all sides.
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Font Family">
<Text style={{fontFamily: 'sans-serif'}}>
Sans-Serif
</Text>
<Text style={{fontFamily: 'sans-serif', fontWeight: 'bold'}}>
Sans-Serif Bold
</Text>
<Text style={{fontFamily: 'serif'}}>
Serif
</Text>
<Text style={{fontFamily: 'serif', fontWeight: 'bold'}}>
Serif Bold
</Text>
<Text style={{fontFamily: 'monospace'}}>
Monospace
</Text>
<Text style={{fontFamily: 'monospace', fontWeight: 'bold'}}>
Monospace Bold (After 5.0)
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Android Material Design fonts">
<View style={{flexDirection: 'row', alignItems: 'flex-start'}}>
<View style={{flex: 1}}>
<Text style={{fontFamily: 'sans-serif'}}>
Roboto Regular
</Text>
<Text style={{fontFamily: 'sans-serif', fontStyle: 'italic'}}>
Roboto Italic
</Text>
<Text style={{fontFamily: 'sans-serif', fontWeight: 'bold'}}>
Roboto Bold
</Text>
<Text style={{fontFamily: 'sans-serif', fontStyle: 'italic', fontWeight: 'bold'}}>
Roboto Bold Italic
</Text>
<Text style={{fontFamily: 'sans-serif-light'}}>
Roboto Light
</Text>
<Text style={{fontFamily: 'sans-serif-light', fontStyle: 'italic'}}>
Roboto Light Italic
</Text>
<Text style={{fontFamily: 'sans-serif-thin'}}>
Roboto Thin (After 4.2)
</Text>
<Text style={{fontFamily: 'sans-serif-thin', fontStyle: 'italic'}}>
Roboto Thin Italic (After 4.2)
</Text>
<Text style={{fontFamily: 'sans-serif-condensed'}}>
Roboto Condensed
</Text>
<Text style={{fontFamily: 'sans-serif-condensed', fontStyle: 'italic'}}>
Roboto Condensed Italic
</Text>
<Text style={{fontFamily: 'sans-serif-condensed', fontWeight: 'bold'}}>
Roboto Condensed Bold
</Text>
<Text style={{
fontFamily: 'sans-serif-condensed',
fontStyle: 'italic',
fontWeight: 'bold'}}>
Roboto Condensed Bold Italic
</Text>
<Text style={{fontFamily: 'sans-serif-medium'}}>
Roboto Medium (After 5.0)
</Text>
<Text style={{fontFamily: 'sans-serif-medium', fontStyle: 'italic'}}>
Roboto Medium Italic (After 5.0)
</Text>
</View>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Font Size">
<Text style={{fontSize: 23}}>
Size 23
</Text>
<Text style={{fontSize: 8}}>
Size 8
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Color">
<Text style={{color: 'red'}}>
Red color
</Text>
<Text style={{color: 'blue'}}>
Blue color
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Font Weight">
<Text style={{fontWeight: 'bold'}}>
Move fast and be bold
</Text>
<Text style={{fontWeight: 'normal'}}>
Move fast and be bold
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Font Style">
<Text style={{fontStyle: 'italic'}}>
Move fast and be bold
</Text>
<Text style={{fontStyle: 'normal'}}>
Move fast and be bold
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Font Style and Weight">
<Text style={{fontStyle: 'italic', fontWeight: 'bold'}}>
Move fast and be bold
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Nested">
<Text onPress={() => console.log('1st')}>
(Normal text,
<Text style={{fontWeight: 'bold'}} onPress={() => console.log('2nd')}>
(and bold
<Text style={{fontStyle: 'italic', fontSize: 11, color: '#527fe4'}} onPress={() => console.log('3rd')}>
(and tiny bold italic blue
<Text style={{fontWeight: 'normal', fontStyle: 'normal'}} onPress={() => console.log('4th')}>
(and tiny normal blue)
</Text>
)
</Text>
)
</Text>
)
</Text>
<Text style={{fontFamily: 'serif'}} onPress={() => console.log('1st')}>
(Serif
<Text style={{fontStyle: 'italic', fontWeight: 'bold'}} onPress={() => console.log('2nd')}>
(Serif Bold Italic
<Text
style={{fontFamily: 'monospace', fontStyle: 'normal', fontWeight: 'normal'}}
onPress={() => console.log('3rd')}>
(Monospace Normal
<Text
style={{fontFamily: 'sans-serif', fontWeight: 'bold'}}
onPress={() => console.log('4th')}>
(Sans-Serif Bold
<Text style={{fontWeight: 'normal'}} onPress={() => console.log('5th')}>
(and Sans-Serif Normal)
</Text>
)
</Text>
)
</Text>
)
</Text>
)
</Text>
<Text style={{fontSize: 12}}>
<Entity>Entity Name</Entity>
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Text Align">
<Text>
auto (default) - english LTR
</Text>
<Text>
أحب اللغة العربية auto (default) - arabic RTL
</Text>
<Text style={{textAlign: 'left'}}>
left left left left left left left left left left left left left left left
</Text>
<Text style={{textAlign: 'center'}}>
center center center center center center center center center center center
</Text>
<Text style={{textAlign: 'right'}}>
right right right right right right right right right right right right right
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Unicode">
<View style={{flex: 1}}>
<View style={{flexDirection: 'row'}}>
<Text style={{backgroundColor: 'red'}}>
星际争霸是世界上最好的游戏
</Text>
</View>
<View style={{flex: 1}}>
<Text style={{backgroundColor: 'red'}}>
星际争霸是世界上最好的游戏
</Text>
</View>
<View style={{flex: 1, alignItems: 'center'}}>
<Text style={{backgroundColor: 'red'}}>
星际争霸是世界上最好的游戏
</Text>
</View>
<View style={{flex: 1}}>
<Text style={{backgroundColor: 'red'}}>
星际争霸是世界上最好的游戏星际争霸是世界上最好的游戏星际争霸是世界上最好的游戏星际争霸是世界上最好的游戏
</Text>
</View>
</View>
</UIExplorerBlock>
<UIExplorerBlock title="Spaces">
<Text>
A {'generated'} {' '} {'string'} and some &nbsp;&nbsp;&nbsp; spaces
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Line Height">
<Text style={{lineHeight: 35}}>
Holisticly formulate inexpensive ideas before best-of-breed benefits. <Text style={{fontSize: 20}}>Continually</Text> expedite magnetic potentialities rather than client-focused interfaces.
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Empty Text">
<Text />
</UIExplorerBlock>
<UIExplorerBlock title="Toggling Attributes">
<AttributeToggler />
</UIExplorerBlock>
<UIExplorerBlock title="backgroundColor attribute">
<Text style={{backgroundColor: '#ffaaaa'}}>
Red background,
<Text style={{backgroundColor: '#aaaaff'}}>
{' '}blue background,
<Text>
{' '}inherited blue background,
<Text style={{backgroundColor: '#aaffaa'}}>
{' '}nested green background.
</Text>
</Text>
</Text>
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="containerBackgroundColor attribute">
<View style={{flexDirection: 'row', height: 85}}>
<View style={{backgroundColor: '#ffaaaa', width: 150}} />
<View style={{backgroundColor: '#aaaaff', width: 150}} />
</View>
<Text style={[styles.backgroundColorText, {top: -80}]}>
Default containerBackgroundColor (inherited) + backgroundColor wash
</Text>
<Text style={[styles.backgroundColorText, {top: -70, backgroundColor: 'transparent'}]}>
{"containerBackgroundColor: 'transparent' + backgroundColor wash"}
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="numberOfLines attribute">
<Text numberOfLines={1}>
Maximum of one line no matter now much I write here. If I keep writing it{"'"}ll just truncate after one line
</Text>
<Text numberOfLines={2} style={{marginTop: 20}}>
Maximum of two lines no matter now much I write here. If I keep writing it{"'"}ll just truncate after two lines
</Text>
<Text style={{marginTop: 20}}>
No maximum lines specified no matter now much I write here. If I keep writing it{"'"}ll just keep going and going
</Text>
</UIExplorerBlock>
</UIExplorerPage>
);
}
});
var styles = StyleSheet.create({
backgroundColorText: {
left: 5,
backgroundColor: 'rgba(100, 100, 100, 0.3)'
},
});
module.exports = TextExample;
+19
View File
@@ -378,6 +378,25 @@ exports.examples = [
</View>
);
},
}, {
title: 'allowFontScaling attribute',
render: function() {
return (
<View>
<Text>
By default, text will respect Text Size accessibility setting on iOS.
It means that all font sizes will be increased or descreased depending on the value of Text Size setting in
{" "}<Text style={{fontWeight: 'bold'}}>Settings.app - Display & Brightness - Text Size</Text>
</Text>
<Text style={{marginTop: 10}}>
You can disable scaling for your Text component by passing {"\""}allowFontScaling={"{"}false{"}\""} prop.
</Text>
<Text allowFontScaling={false} style={{marginTop: 20}}>
This text will not scale.
</Text>
</View>
);
},
}];
var styles = StyleSheet.create({
@@ -0,0 +1,316 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
Text,
TextInput,
View,
StyleSheet,
} = React;
var TextEventsExample = React.createClass({
getInitialState: function() {
return {
curText: '<No Event>',
prevText: '<No Event>',
prev2Text: '<No Event>',
};
},
updateText: function(text) {
this.setState((state) => {
return {
curText: text,
prevText: state.curText,
prev2Text: state.prevText,
};
});
},
render: function() {
return (
<View>
<TextInput
autoCapitalize="none"
placeholder="Enter text to see events"
autoCorrect={false}
onFocus={() => this.updateText('onFocus')}
onBlur={() => this.updateText('onBlur')}
onChange={(event) => this.updateText(
'onChange text: ' + event.nativeEvent.text
)}
onEndEditing={(event) => this.updateText(
'onEndEditing text: ' + event.nativeEvent.text
)}
onSubmitEditing={(event) => this.updateText(
'onSubmitEditing text: ' + event.nativeEvent.text
)}
style={styles.singleLine}
/>
<Text style={styles.eventLabel}>
{this.state.curText}{'\n'}
(prev: {this.state.prevText}){'\n'}
(prev2: {this.state.prev2Text})
</Text>
</View>
);
}
});
class RewriteExample extends React.Component {
constructor(props) {
super(props);
this.state = {text: ''};
}
render() {
return (
<TextInput
onChangeText={(text) => {
text = text.replace(/ /g, '_');
this.setState({text});
}}
style={styles.singleLine}
value={this.state.text}
/>
);
}
}
var styles = StyleSheet.create({
multiline: {
height: 60,
fontSize: 16,
padding: 4,
marginBottom: 10,
},
eventLabel: {
margin: 3,
fontSize: 12,
},
singleLine: {
fontSize: 16,
padding: 4,
},
singleLineWithHeightTextInput: {
height: 30,
},
});
exports.title = '<TextInput>';
exports.description = 'Single and multi-line text inputs.';
exports.examples = [
{
title: 'Auto-focus',
render: function() {
return <TextInput autoFocus={true} style={styles.singleLine} />;
}
},
{
title: "Live Re-Write (<sp> -> '_')",
render: function() {
return <RewriteExample />;
}
},
{
title: 'Auto-capitalize',
render: function() {
var autoCapitalizeTypes = [
'none',
'sentences',
'words',
'characters',
];
var examples = autoCapitalizeTypes.map((type) => {
return (
<TextInput
autoCapitalize={type}
placeholder={'autoCapitalize: ' + type}
style={styles.singleLine}
/>
);
});
return <View>{examples}</View>;
}
},
{
title: 'Auto-correct',
render: function() {
return (
<View>
<TextInput
autoCorrect={true}
placeholder="This has autoCorrect"
style={styles.singleLine}
/>
<TextInput
autoCorrect={false}
placeholder="This does not have autoCorrect"
style={styles.singleLine}
/>
</View>
);
}
},
{
title: 'Keyboard types',
render: function() {
var keyboardTypes = [
'default',
'email-address',
'numeric',
];
var examples = keyboardTypes.map((type) => {
return (
<TextInput
keyboardType={type}
placeholder={'keyboardType: ' + type}
style={styles.singleLine}
/>
);
});
return <View>{examples}</View>;
}
},
{
title: 'Event handling',
render: function(): ReactElement { return <TextEventsExample />; },
},
{
title: 'Colors and text inputs',
render: function() {
return (
<View>
<TextInput
style={[styles.singleLine]}
defaultValue="Default color text"
/>
<TextInput
style={[styles.singleLine, {color: 'green'}]}
defaultValue="Green Text"
/>
<TextInput
placeholder="Default placeholder text color"
style={styles.singleLine}
/>
<TextInput
placeholder="Red placeholder text color"
placeholderTextColor="red"
style={styles.singleLine}
/>
<TextInput
placeholder="Default underline color"
style={styles.singleLine}
/>
<TextInput
placeholder="Blue underline color"
style={styles.singleLine}
underlineColorAndroid="blue"
/>
</View>
);
}
},
{
title: 'Text input, themes and heights',
render: function() {
return (
<TextInput
placeholder="If you set height, beware of padding set from themes"
style={[styles.singleLineWithHeightTextInput]}
/>
);
}
},
{
title: 'Passwords',
render: function() {
return (
<TextInput
defaultValue="iloveturtles"
password={true}
style={styles.singleLine}
/>
);
}
},
{
title: 'Editable',
render: function() {
return (
<TextInput
defaultValue="Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^"
editable={false}
style={styles.singleLine}
/>
);
}
},
{
title: 'Multiline',
render: function() {
return (
<View>
<TextInput
autoCorrect={true}
placeholder="multiline, aligned top-left"
placeholderTextColor="red"
multiline={true}
textAlign="start"
textAlignVertical="top"
style={styles.multiline}
/>
<TextInput
autoCorrect={true}
placeholder="multiline, aligned center"
placeholderTextColor="green"
multiline={true}
textAlign="center"
textAlignVertical="center"
style={[styles.multiline]}
/>
<TextInput
autoCorrect={true}
multiline={true}
textAlign="end"
textAlignVertical="bottom"
style={[styles.multiline, {color: 'blue'}]}>
<Text style={styles.multiline}>multiline with children, aligned bottom-right</Text>
</TextInput>
</View>
);
}
},
{
title: 'Fixed number of lines',
platform: 'android',
render: function() {
return (
<View>
<TextInput numberOfLines={2}
multiline={true}
placeholder="Two line input"
/>
<TextInput numberOfLines={5}
multiline={true}
placeholder="Five line input"
/>
</View>
);
}
},
];
@@ -0,0 +1,68 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
Text,
ToastAndroid,
TouchableWithoutFeedback
} = React;
var UIExplorerBlock = require('UIExplorerBlock');
var UIExplorerPage = require('UIExplorerPage');
var ToastExample = React.createClass({
statics: {
title: 'Toast Example',
description: 'Toast Example',
},
getInitialState: function() {
return {};
},
render: function() {
return (
<UIExplorerPage title="ToastAndroid">
<UIExplorerBlock title="Simple toast">
<TouchableWithoutFeedback
onPress={() =>
ToastAndroid.show('This is a toast with short duration', ToastAndroid.SHORT)}>
<Text style={styles.text}>Click me.</Text>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="Toast with long duration">
<TouchableWithoutFeedback
onPress={() =>
ToastAndroid.show('This is a toast with long duration', ToastAndroid.LONG)}>
<Text style={styles.text}>Click me too.</Text>
</TouchableWithoutFeedback>
</UIExplorerBlock>
</UIExplorerPage>
);
},
});
var styles = StyleSheet.create({
text: {
color: 'black',
},
});
module.exports = ToastExample;
@@ -0,0 +1,119 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
Text,
View,
} = React;
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var SwitchAndroid = require('SwitchAndroid');
var ToolbarAndroid = require('ToolbarAndroid');
var ToolbarAndroidExample = React.createClass({
statics: {
title: '<ToolbarAndroid>',
description: 'Examples of using the Android toolbar.'
},
getInitialState: function() {
return {
actionText: 'Example app with toolbar component',
toolbarSwitch: false,
colorProps: {
titleColor: '#3b5998',
subtitleColor: '#6a7180',
},
};
},
render: function() {
return (
<UIExplorerPage title="<ToolbarAndroid>">
<UIExplorerBlock title="Toolbar with title/subtitle and actions">
<ToolbarAndroid
actions={toolbarActions}
navIcon={require('image!ic_menu_black_24dp')}
onActionSelected={this._onActionSelected}
onIconClicked={() => this.setState({actionText: 'Icon clicked'})}
style={styles.toolbar}
subtitle={this.state.actionText}
title="Toolbar" />
<Text>{this.state.actionText}</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Toolbar with logo & custom title view (a View with Switch+Text)">
<ToolbarAndroid
logo={require('image!launcher_icon')}
style={styles.toolbar}>
<View style={{height: 56, flexDirection: 'row', alignItems: 'center'}}>
<SwitchAndroid
value={this.state.toolbarSwitch}
onValueChange={(value) => this.setState({'toolbarSwitch': value})} />
<Text>{'\'Tis but a switch'}</Text>
</View>
</ToolbarAndroid>
</UIExplorerBlock>
<UIExplorerBlock title="Toolbar with no icon">
<ToolbarAndroid
actions={toolbarActions}
style={styles.toolbar}
subtitle="There be no icon here" />
</UIExplorerBlock>
<UIExplorerBlock title="Toolbar with navIcon & logo, no title">
<ToolbarAndroid
actions={toolbarActions}
logo={require('image!launcher_icon')}
navIcon={require('image!ic_menu_black_24dp')}
style={styles.toolbar} />
</UIExplorerBlock>
<UIExplorerBlock title="Toolbar with custom title colors">
<ToolbarAndroid
navIcon={require('image!ic_menu_black_24dp')}
onIconClicked={() => this.setState({colorProps: {}})}
title="Wow, such toolbar"
style={styles.toolbar}
subtitle="Much native"
{...this.state.colorProps} />
<Text>
Touch the icon to reset the custom colors to the default (theme-provided) ones.
</Text>
</UIExplorerBlock>
</UIExplorerPage>
);
},
_onActionSelected: function(position) {
this.setState({
actionText: 'Selected ' + toolbarActions[position].title,
});
},
});
var toolbarActions = [
{title: 'Create', icon: require('image!ic_create_black_48dp'), show: 'always'},
{title: 'Filter'},
{title: 'Settings', icon: require('image!ic_settings_black_48dp'), show: 'always'},
];
var styles = StyleSheet.create({
toolbar: {
backgroundColor: '#e9eaed',
height: 56,
},
});
module.exports = ToolbarAndroidExample;
+1
View File
@@ -27,6 +27,7 @@ var {
} = React;
exports.displayName = (undefined: ?string);
exports.description = 'Touchable and onPress examples';
exports.title = '<Touchable*> and onPress';
exports.examples = [
{
@@ -15,15 +15,17 @@
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
138D6A171B53CD440074A87E /* RCTCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A151B53CD440074A87E /* RCTCacheTests.m */; };
138D6A181B53CD440074A87E /* RCTShadowViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 138D6A161B53CD440074A87E /* RCTShadowViewTests.m */; };
1393D0381B68CD1300E1B601 /* RCTModuleMethodTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1393D0371B68CD1300E1B601 /* RCTModuleMethodTests.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 */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
13DB03481B5D2ED500C27245 /* RCTJSONTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DB03471B5D2ED500C27245 /* RCTJSONTests.m */; };
13DF61B61B67A45000EDB188 /* RCTMethodArgumentTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DF61B51B67A45000EDB188 /* RCTMethodArgumentTests.m */; };
141FC1211B222EBB004D5FFB /* IntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 141FC1201B222EBB004D5FFB /* IntegrationTests.m */; };
143BC5A11B21E45C00462512 /* UIExplorerSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */; };
144D21241B2204C5006DB32B /* RCTClipRectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTClipRectTests.m */; };
144D21241B2204C5006DB32B /* RCTImageUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTImageUtilTests.m */; };
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */; };
1497CFAD1B21F5E400C1F8F2 /* RCTBridgeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */; };
@@ -52,6 +54,7 @@
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
83A936C81B7E0F08005B9C36 /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83A936C71B7E0F08005B9C36 /* RCTConvert_UIColorTests.m */; };
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
/* End PBXBuildFile section */
@@ -166,6 +169,7 @@
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
138D6A151B53CD440074A87E /* RCTCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTCacheTests.m; sourceTree = "<group>"; };
138D6A161B53CD440074A87E /* RCTShadowViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTShadowViewTests.m; sourceTree = "<group>"; };
1393D0371B68CD1300E1B601 /* RCTModuleMethodTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTModuleMethodTests.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>"; };
@@ -176,6 +180,7 @@
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = UIExplorer/main.m; sourceTree = "<group>"; };
13CC9D481AEED2B90020D1C2 /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
13DB03471B5D2ED500C27245 /* RCTJSONTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJSONTests.m; sourceTree = "<group>"; };
13DF61B51B67A45000EDB188 /* RCTMethodArgumentTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTMethodArgumentTests.m; sourceTree = "<group>"; };
141FC1201B222EBB004D5FFB /* IntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IntegrationTests.m; sourceTree = "<group>"; };
143BC57E1B21E18100462512 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
143BC5811B21E18100462512 /* testLayoutExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testLayoutExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
@@ -187,7 +192,7 @@
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
143BC5981B21E3E100462512 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerSnapshotTests.m; sourceTree = "<group>"; };
144D21231B2204C5006DB32B /* RCTClipRectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTClipRectTests.m; sourceTree = "<group>"; };
144D21231B2204C5006DB32B /* RCTImageUtilTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageUtilTests.m; sourceTree = "<group>"; };
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAllocationTests.m; sourceTree = "<group>"; };
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBridgeTests.m; sourceTree = "<group>"; };
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTContextExecutorTests.m; sourceTree = "<group>"; };
@@ -212,6 +217,7 @@
357858F81B28D2C400341EDB /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTUIManagerScenarioTests.m; sourceTree = "<group>"; };
83A936C71B7E0F08005B9C36 /* RCTConvert_UIColorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert_UIColorTests.m; sourceTree = "<group>"; };
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -353,13 +359,16 @@
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */,
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */,
138D6A151B53CD440074A87E /* RCTCacheTests.m */,
144D21231B2204C5006DB32B /* RCTClipRectTests.m */,
1497CFA61B21F5E400C1F8F2 /* RCTContextExecutorTests.m */,
1497CFA71B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m */,
83A936C71B7E0F08005B9C36 /* RCTConvert_UIColorTests.m */,
1497CFA81B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m */,
1497CFA91B21F5E400C1F8F2 /* RCTEventDispatcherTests.m */,
1300627E1B59179B0043FE5A /* RCTGzipTests.m */,
144D21231B2204C5006DB32B /* RCTImageUtilTests.m */,
13DB03471B5D2ED500C27245 /* RCTJSONTests.m */,
13DF61B51B67A45000EDB188 /* RCTMethodArgumentTests.m */,
1393D0371B68CD1300E1B601 /* RCTModuleMethodTests.m */,
138D6A161B53CD440074A87E /* RCTShadowViewTests.m */,
1497CFAA1B21F5E400C1F8F2 /* RCTSparseArrayTests.m */,
1497CFAB1B21F5E400C1F8F2 /* RCTUIManagerTests.m */,
@@ -787,7 +796,8 @@
buildActionMask = 2147483647;
files = (
1497CFB01B21F5E400C1F8F2 /* RCTConvert_UIFontTests.m in Sources */,
144D21241B2204C5006DB32B /* RCTClipRectTests.m in Sources */,
144D21241B2204C5006DB32B /* RCTImageUtilTests.m in Sources */,
1393D0381B68CD1300E1B601 /* RCTModuleMethodTests.m in Sources */,
1497CFB21B21F5E400C1F8F2 /* RCTSparseArrayTests.m in Sources */,
1300627F1B59179B0043FE5A /* RCTGzipTests.m in Sources */,
1497CFAF1B21F5E400C1F8F2 /* RCTConvert_NSURLTests.m in Sources */,
@@ -798,6 +808,8 @@
138D6A171B53CD440074A87E /* RCTCacheTests.m in Sources */,
13DB03481B5D2ED500C27245 /* RCTJSONTests.m in Sources */,
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */,
83A936C81B7E0F08005B9C36 /* RCTConvert_UIColorTests.m in Sources */,
13DF61B61B67A45000EDB188 /* RCTMethodArgumentTests.m in Sources */,
138D6A181B53CD440074A87E /* RCTShadowViewTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
+58 -37
View File
@@ -14,56 +14,77 @@
#import "AppDelegate.h"
#import "RCTBridge.h"
#import "RCTJavaScriptLoader.h"
#import "RCTRootView.h"
@interface AppDelegate() <RCTBridgeDelegate>
@end
@implementation AppDelegate
- (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self
launchOptions:launchOptions];
/**
* Loading JavaScript code - uncomment the one you want.
*
* OPTION 1
* Load from development server. Start the server from the repository root:
*
* $ npm start
*
* To run on device, change `localhost` to the IP address of your computer
* (you can get this by typing `ifconfig` into the terminal and selecting the
* `inet` value under `en0:`) and make sure your computer and iOS device are
* on the same Wi-Fi network.
*/
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.ios.includeRequire.runModule.bundle?dev=true"];
/**
* OPTION 2
* Load from pre-bundled file on disk. To re-generate the static bundle, `cd`
* to your Xcode project folder and run
*
* $ curl 'http://localhost:8081/Examples/UIExplorer/UIExplorerApp.ios.includeRequire.runModule.bundle' -o main.jsbundle
*
* then add the `main.jsbundle` file to your project and uncomment this line:
*/
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#if RUNNING_ON_CI
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"UIExplorerApp"
launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"UIExplorerApp"
initialProperties:nil];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [[UIViewController alloc] init];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge
{
NSURL *sourceURL;
/**
* Loading JavaScript code - uncomment the one you want.
*
* OPTION 1
* Load from development server. Start the server from the repository root:
*
* $ npm start
*
* To run on device, change `localhost` to the IP address of your computer
* (you can get this by typing `ifconfig` into the terminal and selecting the
* `inet` value under `en0:`) and make sure your computer and iOS device are
* on the same Wi-Fi network.
*/
sourceURL = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.ios.includeRequire.runModule.bundle?dev=true"];
/**
* OPTION 2
* Load from pre-bundled file on disk. To re-generate the static bundle, `cd`
* to your Xcode project folder and run
*
* $ curl 'http://localhost:8081/Examples/UIExplorer/UIExplorerApp.ios.includeRequire.runModule.bundle' -o main.jsbundle
*
* then add the `main.jsbundle` file to your project and uncomment this line:
*/
// sourceURL = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#if RUNNING_ON_CI
sourceURL = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
return sourceURL;
}
- (void)loadSourceForBridge:(RCTBridge *)bridge
withBlock:(RCTSourceLoadBlock)loadCallback
{
[RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge]
onComplete:loadCallback];
}
@end
+30 -23
View File
@@ -18,34 +18,42 @@
var React = require('react-native');
var {
AppRegistry,
BackAndroid,
Dimensions,
DrawerLayoutAndroid,
StyleSheet,
ToolbarAndroid,
View,
} = React;
var UIExplorerList = require('./UIExplorerList');
// TODO: these should be exposed by the 'react-native' module.
var DrawerLayoutAndroid = require('DrawerLayoutAndroid');
var ToolbarAndroid = require('ToolbarAndroid');
var UIExplorerList = require('./UIExplorerList.android');
var DRAWER_WIDTH_LEFT = 56;
var UIExplorerApp = React.createClass({
getInitialState: function() {
return {
example: {
title: 'UIExplorer',
component: this._renderHome(),
},
example: this._getUIExplorerHome(),
};
},
_getUIExplorerHome: function() {
return {
title: 'UIExplorer',
component: this._renderHome(),
};
},
componentWillMount: function() {
BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress);
},
render: function() {
return (
<DrawerLayoutAndroid
drawerPosition={DrawerLayoutAndroid.positions.Left}
drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT}
keyboardDismissMode="on-drag"
ref={(drawer) => { this.drawer = drawer; }}
renderNavigationView={this._renderNavigationView}>
{this._renderNavigation()}
@@ -64,14 +72,11 @@ var UIExplorerApp = React.createClass({
onSelectExample: function(example) {
this.drawer.closeDrawer();
if (example.title === 'UIExplorer') {
example.component = this._renderHome();
if (example.title === this._getUIExplorerHome().title) {
example = this._getUIExplorerHome();
}
this.setState({
example: {
title: example.title,
component: example.component,
},
example: example,
});
},
@@ -105,16 +110,16 @@ var UIExplorerApp = React.createClass({
);
},
_handleBackButtonPress: function() {
if (this.state.example.title !== this._getUIExplorerHome().title) {
this.onSelectExample(this._getUIExplorerHome());
return true;
}
return false;
},
});
var styles = StyleSheet.create({
messageText: {
fontSize: 17,
fontWeight: '500',
padding: 15,
marginTop: 50,
marginLeft: 15,
},
container: {
flex: 1,
},
@@ -124,4 +129,6 @@ var styles = StyleSheet.create({
},
});
AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);
module.exports = UIExplorerApp;
@@ -26,11 +26,11 @@
- (void)setUp
{
#if __LP64__
RCTAssert(false, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)");
RCTAssert(NO, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)");
#endif
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion);
NSOperatingSystemVersion version = [NSProcessInfo processInfo].operatingSystemVersion;
RCTAssert(version.majorVersion == 8 || version.minorVersion >= 3, @"Tests should be run on iOS 8.3+, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion);
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerIntegrationTests/js/IntegrationTestsApp", nil);
}
@@ -45,12 +45,12 @@
{
[super setUp];
_uiManager = [[RCTUIManager alloc] init];
_uiManager = [RCTUIManager new];
// Register 20 views to use in the tests
for (NSInteger i = 1; i <= 20; i++) {
UIView *registeredView = [[UIView alloc] init];
[registeredView setReactTag:@(i)];
UIView *registeredView = [UIView new];
registeredView.reactTag = @(i);
_uiManager.viewRegistry[i] = registeredView;
}
}
@@ -92,7 +92,7 @@
NSArray *removeAtIndices = @[@0, @4, @8, @12, @16];
for (NSNumber *index in removeAtIndices) {
NSNumber *reactTag = @([index integerValue] + 2);
NSNumber *reactTag = @(index.integerValue + 2);
[removedViews addObject:_uiManager.viewRegistry[reactTag]];
}
for (NSInteger i = 2; i < 20; i++) {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

@@ -32,11 +32,12 @@
- (void)setUp
{
#ifdef __LP64__
RCTAssert(!__LP64__, @"Snapshot tests should be run on 32-bit device simulators (e.g. iPhone 5)");
#if __LP64__
RCTAssert(NO, @"Tests should be run on 32-bit device simulators (e.g. iPhone 5)");
#endif
NSString *version = [[UIDevice currentDevice] systemVersion];
RCTAssert([version isEqualToString:@"8.3"], @"Snapshot tests should be run on iOS 8.3, found %@", version);
NSOperatingSystemVersion version = [NSProcessInfo processInfo].operatingSystemVersion;
RCTAssert(version.majorVersion == 8 || version.minorVersion >= 3, @"Snapshot tests should be run on iOS 8.3+, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion);
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp.ios", nil);
_runner.recordMode = NO;
}
@@ -10,6 +10,8 @@
*/
'use strict';
require('regenerator/runtime');
var React = require('react-native');
var {
@@ -51,8 +51,7 @@ var LayoutEventsTest = React.createClass({
() => {
debug('layout animation done.');
this.checkLayout(this.addWrapText);
},
(error) => { throw new Error(JSON.stringify(error)); }
}
);
this.setState({viewStyle: {margin: 60}});
},
@@ -17,13 +17,18 @@ var PromiseTest = React.createClass({
shouldResolve: false,
shouldReject: false,
shouldSucceedAsync: false,
shouldThrowAsync: false,
componentDidMount() {
Promise.all([
this.testShouldResolve(),
this.testShouldReject(),
this.testShouldSucceedAsync(),
this.testShouldThrowAsync(),
]).then(() => RCTTestModule.markTestPassed(
this.shouldResolve && this.shouldReject
this.shouldResolve && this.shouldReject &&
this.shouldSucceedAsync && this.shouldThrowAsync
));
},
@@ -41,6 +46,24 @@ var PromiseTest = React.createClass({
.catch(() => this.shouldReject = true);
},
async testShouldSucceedAsync() {
try {
await RCTTestModule.shouldResolve();
this.shouldSucceedAsync = true;
} catch (e) {
this.shouldSucceedAsync = false;
}
},
async testShouldThrowAsync() {
try {
await RCTTestModule.shouldReject();
this.shouldThrowAsync = false;
} catch (e) {
this.shouldThrowAsync = true;
}
},
render() {
return <React.View />;
}
@@ -0,0 +1,99 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
View,
} = React;
var UIExplorerListBase = require('./UIExplorerListBase');
var COMPONENTS = [
require('./ImageExample'),
require('./ProgressBarAndroidExample'),
require('./ScrollViewSimpleExample'),
require('./SwitchAndroidExample'),
require('./TextExample.android'),
require('./TextInputExample.android'),
require('./ToolbarAndroidExample'),
require('./TouchableExample'),
require('./ViewExample'),
];
var APIS = [
require('./AccessibilityAndroidExample.android'),
require('./BorderExample'),
require('./LayoutEventsExample'),
require('./LayoutExample'),
require('./PanResponderExample'),
require('./PointerEventsExample'),
require('./TimerExample'),
require('./ToastAndroidExample.android'),
require('./XHRExample'),
];
type Props = {
onSelectExample: Function,
isInDrawer: bool,
};
class UIExplorerList extends React.Component {
props: Props;
render() {
return (
<UIExplorerListBase
components={COMPONENTS}
apis={APIS}
searchText=""
renderAdditionalView={this.renderAdditionalView.bind(this)}
onPressRow={this.onPressRow.bind(this)}
/>
);
}
renderAdditionalView(renderRow, renderTextInput): React.Component {
if (this.props.isInDrawer) {
var homePage = renderRow({
title: 'UIExplorer',
description: 'List of examples',
}, -1);
return (
<View>
{homePage}
</View>
);
}
return renderTextInput(styles.searchTextInput);
}
onPressRow(example: any) {
var Component = UIExplorerListBase.makeRenderable(example);
this.props.onSelectExample({
title: Component.title,
component: Component,
});
}
}
var styles = StyleSheet.create({
searchTextInput: {
padding: 2,
},
});
module.exports = UIExplorerList;
+4 -29
View File
@@ -37,6 +37,7 @@ var COMPONENTS = [
require('./ListViewGridLayoutExample'),
require('./ListViewPagingExample'),
require('./MapViewExample'),
require('./ModalExample'),
require('./Navigator/NavigatorExample'),
require('./NavigatorIOSColorsExample'),
require('./NavigatorIOSExample'),
@@ -48,7 +49,7 @@ var COMPONENTS = [
require('./SwitchIOSExample'),
require('./TabBarIOSExample'),
require('./TextExample.ios'),
require('./TextInputExample'),
require('./TextInputExample.ios'),
require('./TouchableExample'),
require('./ViewExample'),
require('./WebViewExample'),
@@ -73,7 +74,8 @@ var APIS = [
require('./StatusBarIOSExample'),
require('./TimerExample'),
require('./VibrationIOSExample'),
require('./XHRExample'),
require('./XHRExample.ios'),
require('./ImageEditingExample'),
];
// Register suitable examples for snapshot tests
@@ -121,32 +123,6 @@ class UIExplorerList extends React.Component {
);
}
componentDidMount() {
var wasUIExplorer = false;
var didOpenExample = false;
this.props.navigator.navigationContext.addListener('didfocus', (event) => {
var isUIExplorer = event.data.route.title === 'UIExplorer';
if (!didOpenExample && isUIExplorer) {
didOpenExample = true;
var visibleExampleTitle = Settings.get('visibleExample');
if (visibleExampleTitle) {
var predicate = (example) => example.title === visibleExampleTitle;
var foundExample = APIS.find(predicate) || COMPONENTS.find(predicate);
if (foundExample) {
setTimeout(() => this._openExample(foundExample), 100);
}
} else if (!wasUIExplorer && isUIExplorer) {
Settings.set({visibleExample: null});
}
}
wasUIExplorer = isUIExplorer;
});
}
renderAdditionalView(renderRow: Function, renderTextInput: Function): React.Component {
return renderTextInput(styles.searchTextInput);
}
@@ -169,7 +145,6 @@ class UIExplorerList extends React.Component {
}
onPressRow(example: any) {
Settings.set({visibleExample: example.title});
this._openExample(example);
}
}
-344
View File
@@ -1,344 +0,0 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
ListView,
PixelRatio,
Platform,
Settings,
StyleSheet,
Text,
TextInput,
TouchableHighlight,
View,
} = React;
var { TestModule } = React.addons;
import type { ExampleModule } from 'ExampleTypes';
import type { NavigationContext } from 'NavigationContext';
var createExamplePage = require('./createExamplePage');
var COMMON_COMPONENTS = [
require('./ImageExample'),
require('./LayoutEventsExample'),
require('./ListViewExample'),
require('./ListViewGridLayoutExample'),
require('./ListViewPagingExample'),
require('./MapViewExample'),
require('./Navigator/NavigatorExample'),
require('./ScrollViewExample'),
require('./TextInputExample'),
require('./TouchableExample'),
require('./ViewExample'),
require('./WebViewExample'),
];
var COMMON_APIS = [
require('./AnimationExample/AnExApp'),
require('./GeolocationExample'),
require('./LayoutExample'),
require('./PanResponderExample'),
require('./PointerEventsExample'),
];
if (Platform.OS === 'ios') {
var COMPONENTS = COMMON_COMPONENTS.concat([
require('./ActivityIndicatorIOSExample'),
require('./DatePickerIOSExample'),
require('./NavigatorIOSColorsExample'),
require('./NavigatorIOSExample'),
require('./PickerIOSExample'),
require('./ProgressViewIOSExample'),
require('./SegmentedControlIOSExample'),
require('./SliderIOSExample'),
require('./SwitchIOSExample'),
require('./TabBarIOSExample'),
require('./TextExample.ios'),
]);
var APIS = COMMON_APIS.concat([
require('./AccessibilityIOSExample'),
require('./ActionSheetIOSExample'),
require('./AdSupportIOSExample'),
require('./AlertIOSExample'),
require('./AppStateIOSExample'),
require('./AsyncStorageExample'),
require('./TransformExample'),
require('./BorderExample'),
require('./CameraRollExample.ios'),
require('./NetInfoExample'),
require('./PushNotificationIOSExample'),
require('./StatusBarIOSExample'),
require('./TimerExample'),
require('./VibrationIOSExample'),
require('./XHRExample'),
]);
} else if (Platform.OS === 'android') {
var COMPONENTS = COMMON_COMPONENTS.concat([
]);
var APIS = COMMON_APIS.concat([
]);
}
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
});
function makeRenderable(example: any): ReactClass<any, any, any> {
return example.examples ?
createExamplePage(null, example) :
example;
}
// Register suitable examples for snapshot tests
COMPONENTS.concat(APIS).forEach((Example) => {
if (Example.displayName) {
var Snapshotter = React.createClass({
componentDidMount: function() {
// View is still blank after first RAF :\
global.requestAnimationFrame(() =>
global.requestAnimationFrame(() => TestModule.verifySnapshot(
TestModule.markTestPassed
)
));
},
render: function() {
var Renderable = makeRenderable(Example);
return <Renderable />;
},
});
AppRegistry.registerComponent(Example.displayName, () => Snapshotter);
}
});
type Props = {
navigator: {
navigationContext: NavigationContext,
push: (route: {title: string, component: ReactClass<any,any,any>}) => void,
},
onExternalExampleRequested: Function,
onSelectExample: Function,
isInDrawer: bool,
};
class UIExplorerList extends React.Component {
props: Props;
constructor(props: Props) {
super(props);
this.state = {
dataSource: ds.cloneWithRowsAndSections({
components: COMPONENTS,
apis: APIS,
}),
searchText: Platform.OS === 'ios' ? Settings.get('searchText') : '',
};
}
componentWillMount() {
this.props.navigator.navigationContext.addListener('didfocus', function(event) {
if (event.data.route.title === 'UIExplorer') {
Settings.set({visibleExample: null});
}
});
}
componentDidMount() {
this._search(this.state.searchText);
}
render() {
if (Platform.OS === 'ios' ||
(Platform.OS === 'android' && !this.props.isInDrawer)) {
var platformTextInputStyle =
Platform.OS === 'ios' ? styles.searchTextInputIOS :
Platform.OS === 'android' ? styles.searchTextInputAndroid : {};
var textInput = (
<View style={styles.searchRow}>
<TextInput
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
onChangeText={this._search.bind(this)}
placeholder="Search..."
style={[styles.searchTextInput, platformTextInputStyle]}
testID="explorer_search"
value={this.state.searchText}
/>
</View>);
}
var homePage;
if (Platform.OS === 'android' && this.props.isInDrawer) {
homePage = this._renderRow({
title: 'UIExplorer',
description: 'List of examples',
}, -1);
}
return (
<View style={styles.listContainer}>
{textInput}
{homePage}
<ListView
style={styles.list}
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
renderSectionHeader={this._renderSectionHeader}
keyboardShouldPersistTaps={true}
automaticallyAdjustContentInsets={false}
keyboardDismissMode="on-drag"
/>
</View>
);
}
_renderSectionHeader(data: any, section: string) {
return (
<View style={styles.sectionHeader}>
<Text style={styles.sectionHeaderTitle}>
{section.toUpperCase()}
</Text>
</View>
);
}
_renderRow(example: any, i: number) {
return (
<View key={i}>
<TouchableHighlight onPress={() => this._onPressRow(example)}>
<View style={styles.row}>
<Text style={styles.rowTitleText}>
{example.title}
</Text>
<Text style={styles.rowDetailText}>
{example.description}
</Text>
</View>
</TouchableHighlight>
<View style={styles.separator} />
</View>
);
}
_search(text: mixed) {
var regex = new RegExp(text, 'i');
var filter = (component) => regex.test(component.title);
this.setState({
dataSource: ds.cloneWithRowsAndSections({
components: COMPONENTS.filter(filter),
apis: APIS.filter(filter),
}),
searchText: text,
});
Settings.set({searchText: text});
}
_openExample(example: any) {
if (example.external) {
this.props.onExternalExampleRequested(example);
return;
}
var Component = makeRenderable(example);
if (Platform.OS === 'ios') {
this.props.navigator.push({
title: Component.title,
component: Component,
});
} else if (Platform.OS === 'android') {
this.props.onSelectExample({
title: Component.title,
component: Component,
});
}
}
_onPressRow(example: any) {
Settings.set({visibleExample: example.title});
this._openExample(example);
}
}
var styles = StyleSheet.create({
listContainer: {
flex: 1,
},
list: {
backgroundColor: '#eeeeee',
},
sectionHeader: {
padding: 5,
},
group: {
backgroundColor: 'white',
},
sectionHeaderTitle: {
fontWeight: '500',
fontSize: 11,
},
row: {
backgroundColor: 'white',
justifyContent: 'center',
paddingHorizontal: 15,
paddingVertical: 8,
},
separator: {
height: 1 / PixelRatio.get(),
backgroundColor: '#bbbbbb',
marginLeft: 15,
},
rowTitleText: {
fontSize: 17,
fontWeight: '500',
},
rowDetailText: {
fontSize: 15,
color: '#888888',
lineHeight: 20,
},
searchRow: {
backgroundColor: '#eeeeee',
paddingTop: 75,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 10,
},
searchTextInput: {
backgroundColor: 'white',
borderColor: '#cccccc',
borderRadius: 3,
borderWidth: 1,
paddingLeft: 8,
},
searchTextInputIOS: {
height: 30,
},
searchTextInputAndroid: {
padding: 2,
},
});
module.exports = UIExplorerList;
@@ -17,6 +17,7 @@
#import "RCTBridge.h"
#import "RCTContextExecutor.h"
#import "RCTModuleMethod.h"
#import "RCTRootView.h"
#define RUN_RUNLOOP_WHILE(CONDITION) \
@@ -41,15 +42,16 @@ _Pragma("clang diagnostic pop")
@end
@interface AllocationTestModule : NSObject<RCTBridgeModule, RCTInvalidating>
@property (nonatomic, assign, getter=isValid) BOOL valid;
@end
@implementation AllocationTestModule
RCT_EXPORT_MODULE();
@synthesize valid = _valid;
- (id)init
- (instancetype)init
{
if ((self = [super init])) {
_valid = YES;
@@ -62,6 +64,11 @@ RCT_EXPORT_MODULE();
_valid = NO;
}
RCT_EXPORT_METHOD(test:(__unused NSString *)a
:(__unused NSNumber *)b
:(__unused RCTResponseSenderBlock)c
:(__unused RCTResponseErrorBlock)d) {}
@end
@interface RCTAllocationTests : XCTestCase
@@ -75,6 +82,7 @@ RCT_EXPORT_MODULE();
@autoreleasepool {
RCTRootView *view = [[RCTRootView alloc] initWithBundleURL:nil
moduleName:@""
initialProperties:nil
launchOptions:nil];
weakBridge = view.bridge;
XCTAssertNotNil(weakBridge, @"RCTBridge should have been created");
@@ -86,7 +94,7 @@ RCT_EXPORT_MODULE();
- (void)testModulesAreInvalidated
{
AllocationTestModule *module = [[AllocationTestModule alloc] init];
AllocationTestModule *module = [AllocationTestModule new];
@autoreleasepool {
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
moduleProvider:^{
@@ -97,10 +105,6 @@ RCT_EXPORT_MODULE();
(void)bridge;
}
/**
* Sleep on the main thread to allow js thread deallocations then run the runloop
* to allow the module to be deallocated on the main thread
*/
RUN_RUNLOOP_WHILE(module.isValid)
XCTAssertFalse(module.isValid, @"AllocationTestModule should have been invalidated by the bridge");
}
@@ -109,7 +113,7 @@ RCT_EXPORT_MODULE();
{
__weak AllocationTestModule *weakModule;
@autoreleasepool {
AllocationTestModule *module = [[AllocationTestModule alloc] init];
AllocationTestModule *module = [AllocationTestModule new];
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
moduleProvider:^{
return @[module];
@@ -124,6 +128,19 @@ RCT_EXPORT_MODULE();
XCTAssertNil(weakModule, @"AllocationTestModule should have been deallocated");
}
- (void)testModuleMethodsAreDeallocated
{
__weak RCTModuleMethod *weakMethod;
@autoreleasepool {
__autoreleasing RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:@"test:(NSString *)a :(nonnull NSNumber *)b :(RCTResponseSenderBlock)c :(RCTResponseErrorBlock)d" JSMethodName:@"" moduleClass:[AllocationTestModule class]];
weakMethod = method;
XCTAssertNotNil(method, @"RCTModuleMethod should have been created");
}
RUN_RUNLOOP_WHILE(weakMethod)
XCTAssertNil(weakMethod, @"RCTModuleMethod should have been deallocated");
}
- (void)testJavaScriptExecutorIsDeallocated
{
__weak id<RCTJavaScriptExecutor> weakExecutor;
@@ -162,15 +179,15 @@ RCT_EXPORT_MODULE();
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:nil
moduleProvider:nil
launchOptions:nil];
__weak id rootContentView;
__weak UIView *rootContentView;
@autoreleasepool {
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@""];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"" initialProperties:nil];
RUN_RUNLOOP_WHILE(!(rootContentView = [rootView valueForKey:@"contentView"]))
XCTAssertTrue([rootContentView isValid], @"RCTContentView should be valid");
XCTAssertTrue(rootContentView.userInteractionEnabled, @"RCTContentView should be valid");
(void)rootView;
}
XCTAssertFalse([rootContentView isValid], @"RCTContentView should have been invalidated");
XCTAssertFalse(rootContentView.userInteractionEnabled, @"RCTContentView should have been invalidated");
}
- (void)testUnderlyingBridgeIsDeallocated
@@ -120,10 +120,22 @@ RCT_EXPORT_MODULE(TestModule)
[_bridge invalidate];
}
#define RUN_RUNLOOP_WHILE(CONDITION) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
NSDate *timeout = [[NSDate date] dateByAddingTimeInterval:0.1]; \
while ((CONDITION) && [timeout timeIntervalSinceNow] > 0) { \
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeout]; \
} \
_Pragma("clang diagnostic pop")
- (void)testHookRegistration
{
TestExecutor *executor = [_bridge.batchedBridge valueForKey:@"_javaScriptExecutor"];
NSString *injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"];
NSString *injectedStuff;
RUN_RUNLOOP_WHILE(!(injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"]));
NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL);
NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"];
NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"];
@@ -142,7 +154,10 @@ RCT_EXPORT_MODULE(TestModule)
- (void)testCallNativeMethod
{
TestExecutor *executor = [_bridge.batchedBridge valueForKey:@"_javaScriptExecutor"];
NSString *injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"];
NSString *injectedStuff;
RUN_RUNLOOP_WHILE(!(injectedStuff = executor.injectedStuff[@"__fbBatchedBridgeConfig"]));
NSDictionary *moduleConfig = RCTJSONParse(injectedStuff, NULL);
NSDictionary *remoteModuleConfig = moduleConfig[@"remoteModuleConfig"];
NSDictionary *testModuleConfig = remoteModuleConfig[@"TestModule"];
@@ -170,7 +185,7 @@ RCT_EXPORT_MODULE(TestModule)
}
RCT_EXPORT_METHOD(testMethod:(NSInteger)integer
number:(NSNumber *)number
number:(nonnull NSNumber *)number
string:(NSString *)string
dictionary:(NSDictionary *)dict
callback:(RCTResponseSenderBlock)callback)
@@ -37,7 +37,7 @@
- (void)setUp
{
self.cache = [[RCTCache alloc] init];
self.cache = [RCTCache new];
self.cache.countLimit = 3;
self.cache.totalCostLimit = 100;
}
@@ -33,7 +33,7 @@
- (void)setUp
{
[super setUp];
_executor = [[RCTContextExecutor alloc] init];
_executor = [RCTContextExecutor new];
[_executor setUp];
}
@@ -129,7 +129,7 @@ static uint64_t _get_time_nanoseconds(void)
";
[_executor executeApplicationScript:script sourceURL:[NSURL URLWithString:@"http://localhost:8081/"] onComplete:^(__unused NSError *error) {
NSMutableArray *params = [[NSMutableArray alloc] init];
NSMutableArray *params = [NSMutableArray new];
id data = @1;
for (int i = 0; i < 4; i++) {
double samples[runs / frequency];
@@ -26,8 +26,7 @@
#define TEST_URL(name, _input, _expectedURL) \
- (void)test_##name { \
NSURL *result = [RCTConvert NSURL:_input]; \
NSURL *expected = (_expectedURL) ? [NSURL URLWithString:_expectedURL ?: @""] : nil; \
XCTAssertEqualObjects(result.absoluteURL, expected); \
XCTAssertEqualObjects(result.absoluteString, _expectedURL); \
} \
#define TEST_PATH(name, _input, _expectedPath) \
@@ -52,7 +51,9 @@ TEST_BUNDLE_PATH(imageAt2XPath, @"images/foo@2x.jpg", @"images/foo@2x.jpg")
TEST_BUNDLE_PATH(imageFile, @"foo.jpg", @"foo.jpg")
// User documents
TEST_PATH(documentsFolder, @"~/Documents", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject])
TEST_PATH(documentsFolder, @"~/Documents",
[NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES) firstObject])
// Remote files
TEST_URL(fullURL, @"http://example.com/blah/hello.jsbundle", @"http://example.com/blah/hello.jsbundle")
@@ -61,6 +62,13 @@ TEST_URL(urlWithEncodedSpaces, @"http://example.com/blah%20blah/foo", @"http://e
TEST_URL(imageURL, @"http://example.com/foo@2x.jpg", @"http://example.com/foo@2x.jpg")
TEST_URL(imageURLWithSpaces, @"http://example.com/blah foo@2x.jpg", @"http://example.com/blah%20foo@2x.jpg")
// Unicode
TEST_URL(unicodeURL,
@"https://ru.wikipedia.org/wiki/\u0417\u0430\u0433\u043B\u0430\u0432"
"\u043D\u0430\u044F_\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430",
@"https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2"
"%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0")
// Data URLs
- (void)testDataURL
{
@@ -0,0 +1,79 @@
/**
* 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 <XCTest/XCTest.h>
#import "RCTConvert.h"
@interface RCTConvert_UIColorTests : XCTestCase
@end
@implementation RCTConvert_UIColorTests
#define XCTAssertEqualColors(color1, color2) do { \
CGFloat r1, g1, b1, a1; \
CGFloat r2, g2, b2, a2; \
XCTAssertTrue([(color1) getRed:&r1 green:&g1 blue:&b1 alpha:&a1] && \
[(color2) getRed:&r2 green:&g2 blue:&b2 alpha:&a2] && \
r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2, \
@"rgba(%d, %d, %d, %.3f) != rgba(%d, %d, %d, %.3f)", \
(int)(r1 * 255), (int)(g1 * 255), (int)(b1 * 255), a1, \
(int)(r2 * 255), (int)(g2 * 255), (int)(b2 * 255), a2 \
); \
} while (0)
- (void)testHex3
{
UIColor *color = [RCTConvert UIColor:@"#333"];
UIColor *expected = [UIColor colorWithWhite:0.2 alpha:1.0];
XCTAssertEqualColors(color, expected);
}
- (void)testHex6
{
UIColor *color = [RCTConvert UIColor:@"#666"];
UIColor *expected = [UIColor colorWithWhite:0.4 alpha:1.0];
XCTAssertEqualColors(color, expected);
}
- (void)testRGB
{
UIColor *color = [RCTConvert UIColor:@"rgb(51, 102, 153)"];
UIColor *expected = [UIColor colorWithRed:0.2 green:0.4 blue:0.6 alpha:1.0];
XCTAssertEqualColors(color, expected);
}
- (void)testRGBA
{
UIColor *color = [RCTConvert UIColor:@"rgba(51, 102, 153, 0.5)"];
UIColor *expected = [UIColor colorWithRed:0.2 green:0.4 blue:0.6 alpha:0.5];
XCTAssertEqualColors(color, expected);
}
- (void)testHSL
{
UIColor *color = [RCTConvert UIColor:@"hsl(30, 50%, 50%)"];
UIColor *expected = [UIColor colorWithHue:30.0 / 360.0 saturation:0.5 brightness:0.5 alpha:1.0];
XCTAssertEqualColors(color, expected);
}
- (void)testHSLA
{
UIColor *color = [RCTConvert UIColor:@"hsla(30, 50%, 50%, 0.5)"];
UIColor *expected = [UIColor colorWithHue:30.0 / 360.0 saturation:0.5 brightness:0.5 alpha:0.5];
XCTAssertEqualColors(color, expected);
}
@end
@@ -162,8 +162,8 @@
- (void)testFamilyStyleAndWeight
{
{
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-UltraLightItalic" size:14];
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic", @"fontWeight": @"100"}];
UIFont *expected = [UIFont fontWithName:@"HelveticaNeue-LightItalic" size:14];
UIFont *result = [RCTConvert UIFont:@{@"fontFamily": @"Helvetica Neue", @"fontStyle": @"italic", @"fontWeight": @"300"}];
RCTAssertEqualFonts(expected, result);
}
{
@@ -61,10 +61,10 @@
[super setUp];
_bridge = [OCMockObject mockForClass:[RCTBridge class]];
_eventDispatcher = [[RCTEventDispatcher alloc] init];
_eventDispatcher = [RCTEventDispatcher new];
((id<RCTBridgeModule>)_eventDispatcher).bridge = _bridge;
_eventName = @"sampleEvent";
_eventName = RCTNormalizeInputEventName(@"sampleEvent");
_body = @{ @"foo": @"bar" };
_testEvent = [[RCTTestEvent alloc] initWithViewTag:nil
eventName:_eventName
@@ -125,7 +125,7 @@
- (void)testDifferentEventTypesDontCoalesce
{
NSString *firstEventName = @"firstEvent";
NSString *firstEventName = RCTNormalizeInputEventName(@"firstEvent");
RCTTestEvent *firstEvent = [[RCTTestEvent alloc] initWithViewTag:nil
eventName:firstEventName
body:_body];
@@ -67,7 +67,7 @@ extern BOOL RCTIsGzippedData(NSData *data);
@"headers": @{@"Content-Encoding": @"gzip"},
};
RCTNetworking *networker = [[RCTNetworking alloc] init];
RCTNetworking *networker = [RCTNetworking new];
__block NSURLRequest *request = nil;
[networker buildRequest:query completionBlock:^(NSURLRequest *_request) {
request = _request;
@@ -33,11 +33,11 @@ RCTAssertEqualPoints(a.origin, b.origin); \
RCTAssertEqualSizes(a.size, b.size); \
}
@interface RCTClipRectTests : XCTestCase
@interface RCTImageUtilTests : XCTestCase
@end
@implementation RCTClipRectTests
@implementation RCTImageUtilTests
- (void)testLandscapeSourceLandscapeTarget
{
@@ -46,19 +46,19 @@ RCTAssertEqualSizes(a.size, b.size); \
{
CGRect expected = {CGPointZero, {100, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {CGPointZero, {100, 10}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleAspectFit);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {{-50, 0}, {200, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
@@ -69,20 +69,20 @@ RCTAssertEqualSizes(a.size, b.size); \
CGSize target = {100, 20};
{
CGRect expected = {CGPointZero, {10, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
CGRect expected = {CGPointZero, {100, 20}};
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {CGPointZero, {2, 20}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleAspectFit);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {{0, -49}, {10, 100}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
CGRect expected = {{0, -490}, {100, 1000}};
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
@@ -93,20 +93,20 @@ RCTAssertEqualSizes(a.size, b.size); \
CGSize target = {20, 50};
{
CGRect expected = {CGPointZero, {10, 50}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleToFill);
CGRect expected = {CGPointZero, {20, 50}};
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {CGPointZero, {5, 50}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFit);
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleAspectFit);
RCTAssertEqualRects(expected, result);
}
{
CGRect expected = {{0, -37.5}, {10, 100}};
CGRect result = RCTClipRect(content, 2, target, 2, UIViewContentModeScaleAspectFill);
CGRect expected = {{0, -75}, {20, 200}};
CGRect result = RCTTargetRect(content, target, 2, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
@@ -117,8 +117,8 @@ RCTAssertEqualSizes(a.size, b.size); \
CGSize target = {20, 50};
{
CGRect expected = {{0, -38}, {10, 100}};
CGRect result = RCTClipRect(content, 1, target, 1, UIViewContentModeScaleAspectFill);
CGRect expected = {{0, -75}, {20, 200}};
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleAspectFill);
RCTAssertEqualRects(expected, result);
}
}
@@ -129,7 +129,7 @@ RCTAssertEqualSizes(a.size, b.size); \
CGSize target = {3, 3};
CGRect expected = {CGPointZero, {3, 3}};
CGRect result = RCTClipRect(content, 2, target, 1, UIViewContentModeScaleToFill);
CGRect result = RCTTargetRect(content, target, 1, UIViewContentModeScaleToFill);
RCTAssertEqualRects(expected, result);
}
@@ -0,0 +1,144 @@
/**
* 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 <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "RCTModuleMethod.h"
@interface RCTMethodArgumentTests : XCTestCase
@end
@implementation RCTMethodArgumentTests
extern void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **argTypes);
- (void)testOneArgument
{
NSArray *arguments;
NSString *methodName = @"foo:(NSInteger)foo";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:");
XCTAssertEqual(arguments.count, (NSUInteger)1);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
}
- (void)testTwoArguments
{
NSArray *arguments;
NSString *methodName = @"foo:(NSInteger)foo bar:(BOOL)bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
}
- (void)testSpaces
{
NSArray *arguments;
NSString *methodName = @"foo : (NSInteger)foo bar : (BOOL) bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
}
- (void)testNewlines
{
NSArray *arguments;
NSString *methodName = @"foo : (NSInteger)foo\nbar : (BOOL) bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
}
- (void)testUnnamedArgs
{
NSArray *arguments;
NSString *methodName = @"foo:(NSInteger)foo:(BOOL)bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo::");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSInteger");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
}
- (void)testUntypedUnnamedArgs
{
NSArray *arguments;
NSString *methodName = @"foo:foo:bar:bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:::");
XCTAssertEqual(arguments.count, (NSUInteger)3);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"id");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"id");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[2]).type, @"id");
}
- (void)testAttributes
{
NSArray *arguments;
NSString *methodName = @"foo:(__attribute__((nonnull)) NSString *)foo bar:(__unused BOOL)bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
}
- (void)testNullability
{
NSArray *arguments;
NSString *methodName = @"foo:(nullable NSString *)foo bar:(nonnull NSNumber *)bar baz:(id)baz";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:baz:");
XCTAssertEqual(arguments.count, (NSUInteger)3);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"NSNumber");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[2]).type, @"id");
XCTAssertEqual(((RCTMethodArgument *)arguments[0]).nullability, RCTNullable);
XCTAssertEqual(((RCTMethodArgument *)arguments[1]).nullability, RCTNonnullable);
XCTAssertEqual(((RCTMethodArgument *)arguments[2]).nullability, RCTNullabilityUnspecified);
}
- (void)testSemicolonStripping
{
NSArray *arguments;
NSString *methodName = @"foo:(NSString *)foo bar:(BOOL)bar;";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"BOOL");
}
- (void)testUnused
{
NSArray *arguments;
NSString *methodName = @"foo:(__unused NSString *)foo bar:(NSNumber *)bar";
RCTParseObjCMethodName(&methodName, &arguments);
XCTAssertEqualObjects(methodName, @"foo:bar:");
XCTAssertEqual(arguments.count, (NSUInteger)2);
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[0]).type, @"NSString");
XCTAssertEqualObjects(((RCTMethodArgument *)arguments[1]).type, @"NSNumber");
XCTAssertTrue(((RCTMethodArgument *)arguments[0]).unused);
XCTAssertFalse(((RCTMethodArgument *)arguments[1]).unused);
}
@end
@@ -0,0 +1,124 @@
/**
* 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 <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "RCTBridgeModule.h"
#import "RCTModuleMethod.h"
#import "RCTLog.h"
static BOOL RCTLogsError(void (^block)(void))
{
__block BOOL loggedError = NO;
RCTPerformBlockWithLogFunction(block, ^(RCTLogLevel level,
__unused NSString *fileName,
__unused NSNumber *lineNumber,
__unused NSString *message) {
loggedError = (level == RCTLogLevelError);
});
return loggedError;
}
@interface RCTModuleMethodTests : XCTestCase <RCTBridgeModule>
@end
@implementation RCTModuleMethodTests
{
CGRect _s;
}
+ (NSString *)moduleName { return nil; }
- (void)doFooWithBar:(__unused NSString *)bar { }
- (void)testNonnull
{
NSString *methodName = @"doFooWithBar:(nonnull NSString *)bar";
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
XCTAssertFalse(RCTLogsError(^{
[method invokeWithBridge:nil module:self arguments:@[@"Hello World"]];
}));
XCTAssertTrue(RCTLogsError(^{
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
}));
}
- (void)doFooWithNumber:(__unused NSNumber *)n { }
- (void)doFooWithDouble:(__unused double)n { }
- (void)doFooWithInteger:(__unused NSInteger)n { }
- (void)doFooWithCGRect:(CGRect)s { _s = s; }
- (void)testNumbersNonnull
{
{
// Specifying an NSNumber param without nonnull isn't allowed
XCTAssertTrue(RCTLogsError(^{
NSString *methodName = @"doFooWithNumber:(NSNumber *)n";
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
// Invoke method to trigger parsing
[method invokeWithBridge:nil module:self arguments:@[@1]];
}));
}
{
NSString *methodName = @"doFooWithNumber:(nonnull NSNumber *)n";
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
XCTAssertTrue(RCTLogsError(^{
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
}));
}
{
NSString *methodName = @"doFooWithDouble:(double)n";
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
XCTAssertTrue(RCTLogsError(^{
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
}));
}
{
NSString *methodName = @"doFooWithInteger:(NSInteger)n";
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
XCTAssertTrue(RCTLogsError(^{
[method invokeWithBridge:nil module:self arguments:@[[NSNull null]]];
}));
}
}
- (void)testStructArgument
{
NSString *methodName = @"doFooWithCGRect:(CGRect)s";
RCTModuleMethod *method = [[RCTModuleMethod alloc] initWithObjCMethodName:methodName
JSMethodName:nil
moduleClass:[self class]];
CGRect r = CGRectMake(10, 20, 30, 40);
[method invokeWithBridge:nil module:self arguments:@[@[@10, @20, @30, @40]]];
XCTAssertTrue(CGRectEqualToRect(r, _s));
}
@end
@@ -99,7 +99,7 @@
- (RCTShadowView *)_shadowViewWithStyle:(void(^)(css_style_t *style))styleBlock
{
RCTShadowView *shadowView = [[RCTShadowView alloc] init];
RCTShadowView *shadowView = [RCTShadowView new];
css_style_t style = shadowView.cssNode->style;
styleBlock(&style);
@@ -25,13 +25,13 @@
- (void)testDictionary
{
NSObject<RCTViewNodeProtocol> *myView = [[UIView alloc] init];
id<RCTComponent> myView = [UIView new];
myView.reactTag = @4;
NSObject<RCTViewNodeProtocol> *myOtherView = [[UIView alloc] init];
id<RCTComponent> myOtherView = [UIView new];
myOtherView.reactTag = @5;
RCTSparseArray *registry = [[RCTSparseArray alloc] init];
RCTSparseArray *registry = [RCTSparseArray new];
XCTAssertNil(registry[@4], @"how did you have a view when none are registered?");
XCTAssertNil(registry[@5], @"how did you have a view when none are registered?");
@@ -44,12 +44,12 @@
{
[super setUp];
_uiManager = [[RCTUIManager alloc] init];
_uiManager = [RCTUIManager new];
// Register 20 views to use in the tests
for (NSInteger i = 1; i <= 20; i++) {
UIView *registeredView = [[UIView alloc] init];
[registeredView setReactTag:@(i)];
UIView *registeredView = [UIView new];
registeredView.reactTag = @(i);
_uiManager.viewRegistry[i] = registeredView;
}
}
@@ -91,7 +91,7 @@
NSArray *removeAtIndices = @[@0, @4, @8, @12, @16];
for (NSNumber *index in removeAtIndices) {
NSNumber *reactTag = @([index integerValue] + 2);
NSNumber *reactTag = @(index.integerValue + 2);
[removedViews addObject:_uiManager.viewRegistry[reactTag]];
}
for (NSInteger i = 2; i < 20; i++) {
+326
View File
@@ -0,0 +1,326 @@
/**
* 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.
*
* @flow
*/
'use strict';
var React = require('react-native');
var {
PixelRatio,
StyleSheet,
Text,
TextInput,
TouchableHighlight,
View,
} = React;
// TODO t7093728 This is a simlified XHRExample.ios.js.
// Once we have Camera roll, Toast, Intent (for opening URLs)
// we should make this consistent with iOS.
class Downloader extends React.Component {
xhr: XMLHttpRequest;
cancelled: boolean;
constructor(props) {
super(props);
this.cancelled = false;
this.state = {
status: '',
contentSize: 1,
downloaded: 0,
};
}
download() {
this.xhr && this.xhr.abort();
var xhr = this.xhr || new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === xhr.HEADERS_RECEIVED) {
var contentSize = parseInt(xhr.getResponseHeader('Content-Length'), 10);
this.setState({
contentSize: contentSize,
downloaded: 0,
});
} else if (xhr.readyState === xhr.LOADING) {
this.setState({
downloaded: xhr.responseText.length,
});
console.log(xhr.responseText.length);
} else if (xhr.readyState === xhr.DONE) {
if (this.cancelled) {
this.cancelled = false;
return;
}
if (xhr.status === 200) {
this.setState({
status: 'Download complete!',
});
} else if (xhr.status !== 0) {
this.setState({
status: 'Error: Server returned HTTP status of ' + xhr.status + ' ' + xhr.responseText,
});
} else {
this.setState({
status: 'Error: ' + xhr.responseText,
});
}
}
};
xhr.open('GET', 'http://www.gutenberg.org/cache/epub/100/pg100.txt');
xhr.send();
this.xhr = xhr;
this.setState({status: 'Downloading...'});
}
componentWillUnmount() {
this.cancelled = true;
this.xhr && this.xhr.abort();
}
render() {
var button = this.state.status === 'Downloading...' ? (
<View style={styles.wrapper}>
<View style={styles.button}>
<Text>...</Text>
</View>
</View>
) : (
<TouchableHighlight
style={styles.wrapper}
onPress={this.download.bind(this)}>
<View style={styles.button}>
<Text>Download 5MB Text File</Text>
</View>
</TouchableHighlight>
);
return (
<View>
{button}
<Text>{this.state.status}</Text>
</View>
);
}
}
class FormUploader extends React.Component {
_isMounted: boolean;
_addTextParam: () => void;
_upload: () => void;
constructor(props) {
super(props);
this.state = {
isUploading: false,
uploadProgress: null,
textParams: [],
};
this._isMounted = true;
this._addTextParam = this._addTextParam.bind(this);
this._upload = this._upload.bind(this);
}
_addTextParam() {
var textParams = this.state.textParams;
textParams.push({name: '', value: ''});
this.setState({textParams});
}
componentWillUnmount() {
this._isMounted = false;
}
_onTextParamNameChange(index, text) {
var textParams = this.state.textParams;
textParams[index].name = text;
this.setState({textParams});
}
_onTextParamValueChange(index, text) {
var textParams = this.state.textParams;
textParams[index].value = text;
this.setState({textParams});
}
_upload() {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://posttestserver.com/post.php');
xhr.onload = () => {
this.setState({isUploading: false});
if (xhr.status !== 200) {
console.log(
'Upload failed',
'Expected HTTP 200 OK response, got ' + xhr.status
);
return;
}
if (!xhr.responseText) {
console.log(
'Upload failed',
'No response payload.'
);
return;
}
var index = xhr.responseText.indexOf('http://www.posttestserver.com/');
if (index === -1) {
console.log(
'Upload failed',
'Invalid response payload.'
);
return;
}
var url = xhr.responseText.slice(index).split('\n')[0];
console.log('Upload successful: ' + url);
};
var formdata = new FormData();
this.state.textParams.forEach(
(param) => formdata.append(param.name, param.value)
);
if (xhr.upload) {
xhr.upload.onprogress = (event) => {
console.log('upload onprogress', event);
if (event.lengthComputable) {
this.setState({uploadProgress: event.loaded / event.total});
}
};
}
xhr.send(formdata);
this.setState({isUploading: true});
}
render() {
var textItems = this.state.textParams.map((item, index) => (
<View style={styles.paramRow}>
<TextInput
autoCapitalize="none"
autoCorrect={false}
onChangeText={this._onTextParamNameChange.bind(this, index)}
placeholder="name..."
style={styles.textInput}
/>
<Text style={styles.equalSign}>=</Text>
<TextInput
autoCapitalize="none"
autoCorrect={false}
onChangeText={this._onTextParamValueChange.bind(this, index)}
placeholder="value..."
style={styles.textInput}
/>
</View>
));
var uploadButtonLabel = this.state.isUploading ? 'Uploading...' : 'Upload';
var uploadProgress = this.state.uploadProgress;
if (uploadProgress !== null) {
uploadButtonLabel += ' ' + Math.round(uploadProgress * 100) + '%';
}
var uploadButton = (
<View style={styles.uploadButtonBox}>
<Text style={styles.uploadButtonLabel}>{uploadButtonLabel}</Text>
</View>
);
if (!this.state.isUploading) {
uploadButton = (
<TouchableHighlight onPress={this._upload}>
{uploadButton}
</TouchableHighlight>
);
}
return (
<View>
{textItems}
<View>
<Text
style={[styles.textButton, styles.addTextParamButton]}
onPress={this._addTextParam}>
Add a text param
</Text>
</View>
<View style={styles.uploadButton}>
{uploadButton}
</View>
</View>
);
}
}
exports.framework = 'React';
exports.title = 'XMLHttpRequest';
exports.description = 'XMLHttpRequest';
exports.examples = [{
title: 'File Download',
render() {
return <Downloader/>;
}
}, {
title: 'multipart/form-data Upload',
render() {
return <FormUploader/>;
}
}];
var styles = StyleSheet.create({
wrapper: {
borderRadius: 5,
marginBottom: 5,
},
button: {
backgroundColor: '#eeeeee',
padding: 8,
},
paramRow: {
flexDirection: 'row',
paddingVertical: 8,
alignItems: 'center',
borderBottomWidth: 1 / PixelRatio.get(),
borderBottomColor: 'grey',
},
textButton: {
color: 'blue',
},
addTextParamButton: {
marginTop: 8,
},
textInput: {
flex: 1,
borderRadius: 3,
borderColor: 'grey',
borderWidth: 1,
height: 30,
paddingLeft: 8,
},
equalSign: {
paddingHorizontal: 4,
},
uploadButton: {
marginTop: 16,
},
uploadButtonBox: {
flex: 1,
paddingVertical: 12,
alignItems: 'center',
backgroundColor: 'blue',
borderRadius: 4,
},
uploadButtonLabel: {
color: 'white',
fontSize: 16,
fontWeight: '500',
},
});
@@ -144,7 +144,6 @@ class FormUploader extends React.Component {
CameraRoll.getPhotos(
{first: PAGE_SIZE},
(data) => {
console.log('isMounted', this._isMounted);
if (!this._isMounted) {
return;
}

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