Compare commits

..
14 Commits
Author SHA1 Message Date
Martin Konicek db3c3e460d [0.22.2] Bump version numbers 2016-03-21 22:00:57 +00:00
Martin Konicek 810a7a85ce Revert "added shrinkwrap to package"
This reverts commit cafbeb08fe.
2016-03-21 21:50:54 +00:00
Konstantin Raev e163e6d8b7 fixed podspec verison generation 2016-03-21 20:05:57 +00:00
Konstantin Raev 2360c99d99 Revert "Sync CSSLayout: Make 'stretch' aligned children fill cross-axis in containers of undefined size in the cross-axis"
Reason - to keep IOS and Android in sync
A new update will be coming to master branch

This reverts commit f538032888.
2016-03-21 11:56:26 +00:00
Martín Bigio 0f7e461820 inline __accept call so that sourcemaps work
Summary:Sourcemaps on HMR where a couple of line off. The problem is that since the `__accept` call doesn't go through the sourcemaps pipeline we need to make sure that call is a single-line one.

This was originally written in a single line but I incorrectly updated it on https://github.com/facebook/react-native/commit/436db67126f1e64d1889c2d084b77c98c8d63f8d. Would be great having test coverage for this.

Reviewed By: davidaurelio

Differential Revision: D3075164

fb-gh-sync-id: c77ea99f26bdd675f241c5d20a620eb4ddfbf701
shipit-source-id: c77ea99f26bdd675f241c5d20a620eb4ddfbf701
2016-03-21 11:56:05 +00:00
Konstantin Raev cafbeb08fe added shrinkwrap to package 2016-03-16 12:07:46 +00:00
Konstantin Raev 995aa485d2 revert committed version numbers, confusing for CI npm deployments 2016-03-16 10:56:12 +00:00
Konstantin Raev 09ef2b522b added deployment debugging inf 2016-03-15 18:18:45 +00:00
Konstantin Raev 1228321636 Npm publish
Summary:This work allows automated release deployment.

Previous semi-automation lived in release.sh and I split it into two pieces:
- test-manual-e2e.sh - that just tests that current commit is buildable and makes a quick e2e installation for manual testing
- publish-npm.js - that makes publish based on what current branch and tags are on commit that is tested/deployed by CI

This simplified `Releases.md` guide and requires you to just run
```
git checkout -b 0.22-stable
git tag v0.22.0-rc
git push origin 0.22-stable --tags
```
to have a successful npm release.
Closes https://github.com/facebook/react-native/pull/6453

Reviewed By: mkonicek

Differential Revision: D3047938

Pulled By: bestander

fb-gh-sync-id: dbebf4c3a0bc2c2a0ef75c54595ab5654f91b8ea
shipit-source-id: dbebf4c3a0bc2c2a0ef75c54595ab5654f91b8ea
2016-03-15 16:48:24 +00:00
Laurence Bortfeld 31c3b08a7b getCurrentConnectivity should resolve with object
Summary:`getCurrentConnectivity()` should resolve with object instead of array otherwise in `NetInfo.fetch().done(reach => console.log('Initial: ' + reach))` `reach` will be undefined (see https://github.com/l-urence/react-native/blob/master/Libraries/Network/NetInfo.js#L200).

cc satya164
Closes https://github.com/facebook/react-native/pull/6373

Differential Revision: D3032773

fb-gh-sync-id: edc545548d3c17387545b6c59894c27e4563cb18
shipit-source-id: edc545548d3c17387545b6c59894c27e4563cb18
2016-03-15 16:42:48 +00:00
Martín Bigio 25496d4d97 Unbreak HMR listener
Reviewed By: sam-swarr

Differential Revision: D3042801

fb-gh-sync-id: 2f06f2efbdf3d04ce4db0cf847ebe76d05fb109f
shipit-source-id: 2f06f2efbdf3d04ce4db0cf847ebe76d05fb109f
2016-03-15 16:42:37 +00:00
Dan Abramov 4113da70f0 Update hot reloading dependencies
Summary:These updates include important changes to correctness in the linked and underlying packages:

* https://github.com/gaearon/babel-plugin-react-transform/releases/tag/v2.0.1
* https://github.com/gaearon/babel-plugin-react-transform/releases/tag/v2.0.2
* https://github.com/gaearon/react-proxy/releases/tag/v1.1.3
* https://github.com/gaearon/react-proxy/releases/tag/v1.1.4
* etc

We need to include these if we want to ship hot reloading.

Create a new project with those versions of packages.

<img width="761" alt="screen shot 2016-03-06 at 18 49 20" src="https://cloud.githubusercontent.com/assets/810438/13556222/2d45ca62-e3cc-11e5-8a3f-a2346efe19dd.png">

Verify hot reloading still works.

![](http://cl.ly/2J150y0Y3E1z/download/Screen%20Recording%202016-03-06%20at%2018.48.gif)

martinbigio skevy

I wasn’t sure whether to touch the shrinkwrap.
Closes https://github.com/facebook/react-native/pull/6325

Reviewed By: yungsters

Differential Revision: D3019470

Pulled By: martinbigio

fb-gh-sync-id: 99bad390cd898f58aa7f74494066561a81eb40e6
shipit-source-id: 99bad390cd898f58aa7f74494066561a81eb40e6
2016-03-15 16:42:23 +00:00
Janic Duplessis c5feed4991 Update node-haste and replace fast-path with node-haste's version to fix Windows compatibility
Summary:This is the last bits needed to fix Windows compatibility on master, most of the work was done in node-haste.

**Test plan**
Run npm test
Run the packager using Windows and Mac

cc cpojer davidaurelio
Closes https://github.com/facebook/react-native/pull/6260

Reviewed By: dmmiller, bestander

Differential Revision: D3005397

Pulled By: davidaurelio

fb-gh-sync-id: e16847808ebfa8b234315b2093dba204c9c1e869
shipit-source-id: e16847808ebfa8b234315b2093dba204c9c1e869
2016-03-15 16:41:43 +00:00
Konstantin Raev 9ed661601b [0.22.0-rc] Bump version numbers 2016-03-08 20:07:23 +00:00
3152 changed files with 79486 additions and 220447 deletions
-1
View File
@@ -7,4 +7,3 @@
[alias]
movies = //Examples/Movies/android/app:app
uiexplorer = //Examples/UIExplorer/android/app:app
-3
View File
@@ -9,6 +9,3 @@ end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
[*.gradle]
indent_size = 4
+10 -14
View File
@@ -21,7 +21,6 @@
"__fbBatchedBridgeConfig": false,
"alert": false,
"cancelAnimationFrame": false,
"cancelIdleCallback": false,
"clearImmediate": true,
"clearInterval": false,
"clearTimeout": false,
@@ -41,7 +40,6 @@
"process": false,
"Promise": true,
"requestAnimationFrame": true,
"requestIdleCallback": true,
"require": false,
"Set": true,
"setImmediate": true,
@@ -61,7 +59,6 @@
"SyntheticEvent": false,
"$Either": false,
"$All": false,
"$ArrayBufferView": false,
"$Tuple": false,
"$Supertype": false,
"$Subtype": false,
@@ -79,7 +76,6 @@
"comma-dangle": 0, // disallow trailing commas in object literals
"no-cond-assign": 1, // disallow assignment in conditional expressions
"no-console": 0, // disallow use of console (off by default in the node environment)
"no-const-assign": 2, // disallow assignment to const-declared variables
"no-constant-condition": 0, // disallow use of constant expressions in conditions
"no-control-regex": 1, // disallow control characters in regular expressions
"no-debugger": 1, // disallow use of debugger
@@ -151,6 +147,11 @@
"wrap-iife": 0, // require immediate function invocation to be wrapped in parentheses (off by default)
"yoda": 1, // require or disallow Yoda conditions
// Strict Mode
// These rules relate to using strict mode.
"strict": [2, "global"], // require or disallow the "use strict" pragma in the global scope (off by default in the node environment)
// Variables
// These rules have to do with variable declarations.
@@ -223,24 +224,19 @@
"no-bitwise": 1, // disallow use of bitwise operators (off by default)
"no-plusplus": 0, // disallow use of unary operators, ++ and -- (off by default)
// React Plugin
// The following rules are made available via `eslint-plugin-react`.
"react/display-name": 0,
"react/jsx-boolean-value": 0,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-undef": 1,
"react/jsx-sort-props": 0,
"react/jsx-uses-react": 1,
"react/jsx-uses-react": 0,
"react/jsx-uses-vars": 1,
"react/no-did-mount-set-state": 1,
"react/no-did-update-set-state": 1,
"react/no-did-mount-set-state": [1, "allow-in-func"],
"react/no-did-update-set-state": [1, "allow-in-func"],
"react/no-multi-comp": 0,
"react/no-string-refs": 1,
"react/no-unknown-property": 0,
"react/prop-types": 0,
"react/react-in-jsx-scope": 1,
"react/react-in-jsx-scope": 0,
"react/self-closing-comp": 1,
"react/wrap-multilines": 0,
"react/wrap-multilines": 0
}
}
+43 -30
View File
@@ -1,57 +1,70 @@
[ignore]
; We fork some components by platform
.*/*[.]android.js
; Ignore templates for 'react-native init'
.*/local-cli/templates/.*
# We fork some components by platform.
.*/*.web.js
.*/*.android.js
; Ignore the website subdir
<PROJECT_ROOT>/website/.*
# Some modules have their own node_modules with overlap
.*/node_modules/node-haste/.*
; Ignore "BUCK" generated dirs
<PROJECT_ROOT>/\.buckd/
# Ugh
.*/node_modules/babel.*
.*/node_modules/babylon.*
.*/node_modules/invariant.*
; Ignore unexpected extra "@providesModule"
.*/node_modules/.*/node_modules/fbjs/.*
# Ignore react and fbjs where there are overlaps, but don't ignore
# anything that react-native relies on
.*/node_modules/fbjs/lib/Map.js
.*/node_modules/fbjs/lib/fetch.js
.*/node_modules/fbjs/lib/ExecutionEnvironment.js
.*/node_modules/fbjs/lib/ErrorUtils.js
; Ignore duplicate module providers
; For RN Apps installed via npm, "Libraries" folder is inside
; "node_modules/react-native" but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js
# Flow has a built-in definition for the 'react' module which we prefer to use
# over the currently-untyped source
.*/node_modules/react/react.js
.*/node_modules/react/lib/React.js
.*/node_modules/react/lib/ReactDOM.js
; Ignore duplicate ReactErrorUtils in react-dom/lib in React 16 alpha 4.
; TODO (bvaughn) Remove this once we've synced to React 16 alpha 5.
; For more info see https://phabricator.intern.facebook.com/D4747529#10
<PROJECT_ROOT>/node_modules/react-dom/lib/ReactErrorUtils.js
.*/__mocks__/.*
.*/__tests__/.*
.*/commoner/test/source/widget/share.js
# Ignore commoner tests
.*/node_modules/commoner/test/.*
# See https://github.com/facebook/flow/issues/442
.*/react-tools/node_modules/commoner/lib/reader.js
# Ignore jest
.*/node_modules/jest-cli/.*
# Ignore Website
.*/website/.*
[include]
[libs]
Libraries/react-native/react-native-interface.js
flow/
[options]
emoji=true
module.system=haste
experimental.strict_type_args=true
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
munge_underscores=true
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-1]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
unsafe.enable_getters_and_setters=true
[version]
^0.42.0
0.21.0
-29
View File
@@ -1,29 +0,0 @@
Please read the following carefully before opening a new issue.
Your issue may be closed if it does not provide the information required by this template.
We use GitHub Issues for tracking bugs in React Native.
- If you have a question, ask on Stack Overflow: http://stackoverflow.com/questions/tagged/react-native
- If you have a feature request, post it on Canny: https://react-native.canny.io/feature-requests
--- Delete everything above this line ---
### Description
Explain what you did, what you expected to happen, and what actually happens.
### Reproduction Steps and Sample Code
Try to reproduce your bug on https://sketch.expo.io/ and provide a link.
If you can't reproduce the bug on Sketch, provide a sample project. At the very least, provide an example of your code.
### Solution
What needs to be done to address this issue? Ideally, provide a pull request with a fix.
### Additional Information
* React Native version: [FILL THIS OUT: Be specific, filling out "latest" here is not enough.]
* Platform: [FILL THIS OUT: iOS, Android, or both?]
* Development Operating System: [FILL THIS OUT: Are you developing on MacOS, Linux, or Windows?]
* Dev tools: [FILL THIS OUT: Xcode or Android Studio version, iOS or Android SDK version, if applicable]
-32
View File
@@ -1,32 +0,0 @@
Thanks for submitting a PR! Please read these instructions carefully:
- [ ] Explain the **motivation** for making this change.
- [ ] Provide a **test plan** demonstrating that the code is solid.
- [ ] Match the **code formatting** of the rest of the codebase.
- [ ] Target the `master` branch, NOT a "stable" branch.
## Motivation (required)
What existing problem does the pull request solve?
## Test Plan (required)
A good test plan has the exact commands you ran and their output, provides screenshots or videos if the pull request changes UI or updates the website. See [What is a Test Plan?][1] to learn more.
If you have added code that should be tested, add tests.
## Next Steps
Sign the [CLA][2], if you haven't already.
Small pull requests are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
Make sure all **tests pass** on both [Travis][3] and [Circle CI][4]. PRs that break tests are unlikely to be merged.
For more info, see the ["Pull Requests"][5] section of our "Contributing" guidelines.
[1]: https://medium.com/@martinkonicek/what-is-a-test-plan-8bfc840ec171#.y9lcuqqi9
[2]: https://code.facebook.com/cla
[3]: https://travis-ci.org/facebook/react-native
[4]: http://circleci.com/gh/facebook/react-native
[5]: https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md#pull-requests
-11
View File
@@ -24,9 +24,6 @@ project.xcworkspace
# Gradle
/build/
/Examples/**/android/app/build/
/Examples/**/android/app/gradle/
/Examples/**/android/app/gradlew
/Examples/**/android/app/gradlew.bat
/ReactAndroid/build/
# Buck
@@ -34,7 +31,6 @@ project.xcworkspace
buck-out
/ReactAndroid/src/main/jni/prebuilt/lib/armeabi-v7a/
/ReactAndroid/src/main/jni/prebuilt/lib/x86/
/ReactAndroid/src/main/gen
# Android
.idea
@@ -50,10 +46,3 @@ node_modules
# OS X
.DS_Store
# Test generated files
/ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
*.js.meta
/coverage
/third-party
-3
View File
@@ -1,3 +0,0 @@
# rnpm
/local-cli/rnpm
/local-cli/server/middleware/heapCapture/bundle.js
+38 -30
View File
@@ -1,37 +1,52 @@
language: objective-c
osx_image: xcode8.2
osx_image: xcode7.2
cache:
directories:
- node_modules
- .nvm
install:
- mkdir -p /Users/travis/build/facebook/.nvm
- export NVM_DIR="/Users/travis/build/facebook/.nvm"
- brew install nvm
- brew reinstall nvm
- mkdir -p .nvm
- export NVM_DIR="$PWD/.nvm"
- source $(brew --prefix nvm)/nvm.sh
# TODO npm 2 started stalling on Travis, t11852928
# Use node 6 because that is what runs on land-blocking tests
- nvm install 6
- nvm install 5
- rm -Rf "${TMPDIR}/jest_preprocess_cache"
- wget https://github.com/yarnpkg/yarn/releases/download/v0.16.0/yarn-0.16.0.js
- export yarn="node $(pwd)/yarn-0.16.0.js"
- $yarn install
- npm config set spin=false
- npm config set progress=false
- npm install
script:
- if [[ "$TEST_TYPE" = objc-ios ]]; then travis_retry travis_wait ./scripts/objc-test-ios.sh test; fi
- if [[ "$TEST_TYPE" = objc-tvos ]]; then travis_retry travis_wait ./scripts/objc-test-tvos.sh; fi
- if [[ "$TEST_TYPE" = e2e-objc ]]; then node ./scripts/run-ci-e2e-tests.js --ios --js --retries 3; fi
- if [[ ( "$TEST_TYPE" = podspecs ) && ( "$TRAVIS_PULL_REQUEST" = "false" ) ]]; then gem install cocoapods && ./scripts/process-podspecs.sh; fi
- |
if [ "$TEST_TYPE" = objc ]
then
travis_retry ./scripts/objc-test.sh
matrix:
- fast_finish: true # Fail the whole build as soon as one test type fails. Should help with Travis capacity issues (very long queues).
elif [ "$TEST_TYPE" = js ]
then
npm install github@0.2.4
cat <(echo eslint; npm run lint --silent -- --format=json; echo flow; npm run flow --silent -- --json) | GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" node bots/code-analysis-bot.js
npm run flow && npm test
elif [ "$TEST_TYPE" = e2e-objc ]
then
travis_retry ./scripts/e2e-test.sh --ios
else
echo "Unknown test type: $TEST_TYPE"
exit 1
fi
# The order of these tests says which are more likely to run first and fail the whole build fast.
env:
- TEST_TYPE=objc-ios
- TEST_TYPE=podspecs
- TEST_TYPE=e2e-objc
- TEST_TYPE=objc-tvos
matrix:
- TEST_TYPE=objc
- TEST_TYPE=js
- TEST_TYPE=e2e-objc
branches:
only:
@@ -41,13 +56,6 @@ branches:
notifications:
email:
recipients:
- mkonicek@fb.com
- douglowder@mac.com # Doug Lowder built and maintains Apple TV specific code and wants to be notified about tvOS failures.
- eloy@artsy.net # Eloy Durán maintains the podspecs test and wants to be notified about failures.
on_failure: change
on_success: change
slack:
secure: oQL2C966v7/DtxNqfM7WowjY0R5mgLHR2qHkoucwK5iVrmaptnHr8fq01xlj7VT0kDwNLqT3n4+gtCviGw89lq71m3W76c8Pms/10jpjw+LwAfQPVizNw/Bx8MFNNmjDauK/auFxaybiLZupi7zd4xFGOZvScmFdfD4CAAp2OOA=
on_pull_requests: false
- bestander@gmail.com
on_failure: change
on_success: change
+10 -24
View File
@@ -14,30 +14,16 @@ We will do our best to keep `master` in good shape, with tests passing at all ti
The core team will be monitoring for pull requests. When we get one, we'll run some Facebook-specific integration tests on it first. From here, we'll need to get another person to sign off on the changes and then merge the pull request. For API changes we may need to fix internal uses, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
**Please submit your pull request on the `master` branch**. If the fix is critical and should be included in a stable branch please mention it and it will be cherry picked into it by a project maintainer.
*Before* submitting a pull request, please make sure the following is done…
1. Fork the repo and create your branch from `master`.
2. **Describe your test plan in your commit.**
- If you've added code that should be tested, add tests!
- If you've changed APIs, update the documentation.
- If you've updated the docs, verify the website locally and submit screenshots if applicable.
```
$ cd website
$ npm install && npm start
Open the following in your browser: http://localhost:8079/react-native/index.html
```
3. Add the copyright notice to the top of any new files you've added.
4. Ensure tests pass on Travis and Circle CI.
5. Make sure your code lints (`node linter.js <files touched>`).
6. If you haven't already, sign the [CLA](https://code.facebook.com/cla).
2. **Describe your test plan in your commit.** If you've added code that should be tested, add tests!
3. If you've changed APIs, update the documentation.
4. Add the copyright notice to the top of any new files you've added.
5. Ensure tests pass on Travis and Circle CI.
6. Make sure your code lints (`node linter.js <files touched>`).
7. Squash your commits (`git rebase -i`).
One intent alongside one commit makes it clearer for people to review and easier to understand your intention.
> **Note:** It is not necessary to keep clicking `Merge master to your branch` on the PR page. You would want to merge master if there are conflicts or tests are failing. The Facebook-GitHub-Bot ultimately squashes all commits to a single one before merging your PR.
8. If you haven't already, sign the [CLA](https://code.facebook.com/cla).
#### Copyright Notice for files
@@ -70,7 +56,7 @@ We are using GitHub Issues for our public bugs. We keep a close eye on this and
### Reporting New Issues
The best way to get your bug fixed is to provide a reduced test case. Please provide either a public repository with a runnable example or a [Sketch](https://sketch.expo.io/).
The best way to get your bug fixed is to provide a reduced test case. Please provide either a public repository with a runnable example or a [React Native Playground](https://rnplay.org/) snippet.
### Security Bugs
@@ -78,8 +64,8 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
## How to Get in Touch
* [Facebook](https://www.facebook.com/groups/react.native.community/)
* [Twitter](https://www.twitter.com/reactnative)
* [Facebook group](https://www.facebook.com/groups/react.native.community/)
* Reactiflux — [#react-native](http://join.reactiflux.com/)
## Style Guide
@@ -102,7 +88,7 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
#### JSX
* Prefer `"` over `'` for string literal props
* Prefer `'` over `"` for string literal props
* When wrapping opening tags over multiple lines, place one prop per line
* `{}` of props should hug their values (no spaces)
* Place the closing `>` of opening tags on the same line as the last prop
-55
View File
@@ -1,55 +0,0 @@
FROM containership/android-base:latest
# set default environment variables
ENV GRADLE_OPTS="-Dorg.gradle.jvmargs=\"-Xmx512m -XX:+HeapDumpOnOutOfMemoryError\""
ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF8"
ENV REACT_NATIVE_MAX_WORKERS=1
# add ReactAndroid directory
ADD .buckconfig /app/.buckconfig
ADD .buckjavaargs /app/.buckjavaargs
ADD ReactAndroid /app/ReactAndroid
ADD ReactCommon /app/ReactCommon
ADD keystores /app/keystores
# set workdir
WORKDIR /app
# run buck fetches
RUN buck fetch ReactAndroid/src/test/java/com/facebook/react/modules
RUN buck fetch ReactAndroid/src/main/java/com/facebook/react
RUN buck fetch ReactAndroid/src/main/java/com/facebook/react/shell
RUN buck fetch ReactAndroid/src/test/...
RUN buck fetch ReactAndroid/src/androidTest/...
# build app
RUN buck build ReactAndroid/src/main/java/com/facebook/react
RUN buck build ReactAndroid/src/main/java/com/facebook/react/shell
ADD gradle /app/gradle
ADD gradlew /app/gradlew
ADD settings.gradle /app/settings.gradle
ADD build.gradle /app/build.gradle
ADD react.gradle /app/react.gradle
# run gradle downloads
RUN ./gradlew :ReactAndroid:downloadBoost :ReactAndroid:downloadDoubleConversion :ReactAndroid:downloadFolly :ReactAndroid:downloadGlog :ReactAndroid:downloadJSCHeaders
# compile native libs with Gradle script, we need bridge for unit and integration tests
RUN ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1 -Pcom.android.build.threadPoolSize=1
# add all react-native code
ADD . /app
WORKDIR /app
# https://github.com/npm/npm/issues/13306
RUN cd $(npm root -g)/npm && npm install fs-extra && sed -i -e s/graceful-fs/fs-extra/ -e s/fs.rename/fs.move/ ./lib/utils/rename.js
# build node dependencies
RUN npm install
RUN npm install github@0.2.4
WORKDIR /app/website
RUN npm install
WORKDIR /app
-95
View File
@@ -1,95 +0,0 @@
FROM library/ubuntu:16.04
# set default build arguments
ARG ANDROID_VERSION=25.2.3
ARG BUCK_VERSION=f3452a6a7ab15a60e94c962e686293acbe677473
ARG NDK_VERSION=10e
ARG NODE_VERSION=6.2.0
ARG WATCHMAN_VERSION=4.7.0
# set default environment variables
ENV ADB_INSTALL_TIMEOUT=10
ENV PATH=${PATH}:/opt/buck/bin/
ENV ANDROID_HOME=/opt/android
ENV ANDROID_SDK_HOME=${ANDROID_HOME}
ENV PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
ENV ANDROID_NDK=/opt/ndk/android-ndk-r$NDK_VERSION
ENV PATH=${PATH}:${ANDROID_NDK}
# install system dependencies
RUN apt-get update && apt-get install ant autoconf automake curl g++ gcc git libqt5widgets5 lib32z1 lib32stdc++6 make maven npm openjdk-8* python-dev python3-dev qml-module-qtquick-controls qtdeclarative5-dev unzip -y
# configure npm
RUN npm config set spin=false
RUN npm config set progress=false
# install node
RUN npm install n -g
RUN n $NODE_VERSION
# download buck
RUN git clone https://github.com/facebook/buck.git /opt/buck
WORKDIR /opt/buck
RUN git checkout $BUCK_VERSION
# build buck
RUN ant
# download watchman
RUN git clone https://github.com/facebook/watchman.git /opt/watchman
WORKDIR /opt/watchman
RUN git checkout v$WATCHMAN_VERSION
# build watchman
RUN ./autogen.sh
RUN ./configure
RUN make
RUN make install
# download and unpack android
RUN mkdir /opt/android
WORKDIR /opt/android
RUN curl --silent https://dl.google.com/android/repository/tools_r$ANDROID_VERSION-linux.zip > android.zip
RUN unzip android.zip
RUN rm android.zip
# download and unpack NDK
RUN mkdir /opt/ndk
WORKDIR /opt/ndk
RUN curl --silent https://dl.google.com/android/repository/android-ndk-r$NDK_VERSION-linux-x86_64.zip > ndk.zip
RUN unzip ndk.zip
# cleanup NDK
RUN rm ndk.zip
# Add android SDK tools
# Android SDK Platform-tools, revision 25.0.4
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android SDK Platform-tools, revision 25.0.4" | awk '{ print $1 }' | sed 's/.$//')
# Android SDK Build-tools, revision 23.0.1
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android SDK Build-tools, revision 23.0.1" | awk '{ print $1 }' | sed 's/.$//')
# SDK Platform Android 6.0, API 23, revision 3
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "SDK Platform Android 6.0, API 23" | awk '{ print $1 }' | sed 's/.$//')
# SDK Platform Android 4.4.2, API 19, revision 4
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "SDK Platform Android 4.4.2, API 19, revision 4" | awk '{ print $1 }' | sed 's/.$//')
# ARM EABI v7a System Image, Android API 19, revision 5
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "ARM EABI v7a System Image, Android API 19, revision 5" | awk '{ print $1 }' | sed 's/.$//')
# Intel x86 Atom System Image, Android API 19, revision 5
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Intel x86 Atom System Image, Android API 19, revision 5" | awk '{ print $1 }' | sed 's/.$//')
# Google APIs, Android API 23, revision 1
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Google APIs, Android API 23, revision 1" | awk '{ print $1 }' | sed 's/.$//')
# Android Support Repository, revision 45
RUN echo "y" | android update sdk -u -a -t $(android list sdk -a | grep "Android Support Repository, revision 45" | awk '{ print $1 }' | sed 's/.$//')
# Link adb executable
RUN ln -s /opt/android/platform-tools/adb /usr/bin/adb
# clean up unnecessary directories
RUN rm -rf /opt/android/system-images/android-19/default/x86
-19
View File
@@ -1,19 +0,0 @@
FROM library/node:6.9.2
ENV YARN_VERSION=0.19.1
# install dependencies
RUN apt-get update && apt-get install ocaml libelf-dev -y
RUN npm install yarn@$YARN_VERSION -g
# add code
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN yarn install --ignore-engines
WORKDIR website
RUN yarn install --ignore-engines --ignore-platform
WORKDIR /app
@@ -1,161 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
/**
* This script runs instrumentation tests one by one with retries
* Instrumentation tests tend to be flaky, so rerunning them individually increases
* chances for success and reduces total average execution time.
*
* We assume that all instrumentation tests are flat in one folder
* Available arguments:
* --path - path to all .java files with tests
* --package - com.facebook.react.tests
* --retries [num] - how many times to retry possible flaky commands: npm install and running tests, default 1
*/
/*eslint-disable no-undef */
const argv = require('yargs').argv;
const async = require('async');
const child_process = require('child_process');
const fs = require('fs');
const path = require('path');
// Flaky tests ignored on Circle CI. They still run internally at fb.
const ignoredTests = [
'ReactScrollViewTestCase',
'ReactHorizontalScrollViewTestCase'
];
const colors = {
GREEN: '\x1b[32m',
RED: '\x1b[31m',
RESET: '\x1b[0m'
};
const test_opts = {
FILTER: new RegExp(argv.filter || '.*', 'i'),
PACKAGE: argv.package || 'com.facebook.react.tests',
PATH: argv.path || './ReactAndroid/src/androidTest/java/com/facebook/react/tests',
RETRIES: parseInt(argv.retries || 2, 10),
TEST_TIMEOUT: parseInt(argv['test-timeout'] || 1000 * 60 * 10),
OFFSET: argv.offset,
COUNT: argv.count
}
let max_test_class_length = Number.NEGATIVE_INFINITY;
let testClasses = fs.readdirSync(path.resolve(process.cwd(), test_opts.PATH))
.filter((file) => {
return file.endsWith('.java');
}).map((clazz) => {
return path.basename(clazz, '.java');
}).filter(className => {
return ignoredTests.indexOf(className) === -1;
}).map((clazz) => {
return test_opts.PACKAGE + '.' + clazz;
}).filter((clazz) => {
return test_opts.FILTER.test(clazz);
});
// only process subset of the tests at corresponding offset and count if args provided
if (test_opts.COUNT != null && test_opts.OFFSET != null) {
const testCount = testClasses.length;
const start = test_opts.COUNT * test_opts.OFFSET;
const end = start + test_opts.COUNT;
if (start >= testClasses.length) {
testClasses = [];
} else if (end >= testClasses.length) {
testClasses = testClasses.slice(start);
} else {
testClasses = testClasses.slice(start, end);
}
}
return async.mapSeries(testClasses, (clazz, callback) => {
if(clazz.length > max_test_class_length) {
max_test_class_length = clazz.length;
}
return async.retry(test_opts.RETRIES, (retryCb) => {
const test_process = child_process.spawn('./ContainerShip/scripts/run-instrumentation-tests-via-adb-shell.sh', [test_opts.PACKAGE, clazz], {
stdio: 'inherit'
})
const timeout = setTimeout(() => {
test_process.kill();
}, test_opts.TEST_TIMEOUT);
test_process.on('error', (err) => {
clearTimeout(timeout);
retryCb(err);
});
test_process.on('exit', (code) => {
clearTimeout(timeout);
if(code !== 0) {
return retryCb(new Error(`Process exited with code: ${code}`));
}
return retryCb();
});
}, (err) => {
return callback(null, {
name: clazz,
status: err ? 'failure' : 'success'
});
});
}, (err, results) => {
print_test_suite_results(results);
const failures = results.filter((test) => {
return test.status === 'failure';
});
return failures.length === 0 ? process.exit(0) : process.exit(1);
});
function print_test_suite_results(results) {
console.log('\n\nTest Suite Results:\n');
let color;
let failing_suites = 0;
let passing_suites = 0;
function pad_output(num_chars) {
let i = 0;
while(i < num_chars) {
process.stdout.write(' ');
i++;
}
}
results.forEach((test) => {
if(test.status === 'success') {
color = colors.GREEN;
passing_suites++;
} else if(test.status === 'failure') {
color = colors.RED;
failing_suites++;
}
process.stdout.write(color);
process.stdout.write(test.name);
pad_output((max_test_class_length - test.name.length) + 8);
process.stdout.write(test.status);
process.stdout.write(`${colors.RESET}\n`);
});
console.log(`\n${passing_suites} passing, ${failing_suites} failing!`);
}
@@ -1,35 +0,0 @@
#!/bin/bash
# for buck gen
mount -o remount,exec /dev/shm
AVD_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
# create virtual device
echo no | android create avd -n $AVD_UUID -f -t android-19 --abi default/armeabi-v7a
# emulator setup
emulator64-arm -avd $AVD_UUID -no-skin -no-audio -no-window -no-boot-anim &
bootanim=""
until [[ "$bootanim" =~ "stopped" ]]; do
sleep 5
bootanim=$(adb -e shell getprop init.svc.bootanim 2>&1)
echo "boot animation status=$bootanim"
done
set -x
# solve issue with max user watches limit
echo 65536 | tee -a /proc/sys/fs/inotify/max_user_watches
watchman shutdown-server
# integration tests
# build JS bundle for instrumentation tests
node local-cli/cli.js bundle --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
# build test APK
source ./scripts/circle-ci-android-setup.sh && NO_BUCKD=1 retry3 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1
# run installed apk with tests
node ./ContainerShip/scripts/run-android-ci-instrumentation-tests.js $*
exit $?
@@ -1,12 +0,0 @@
#!/bin/bash
# set default environment variables
UNIT_TESTS_BUILD_THREADS="${UNIT_TESTS_BUILD_THREADS:-1}"
# for buck gen
mount -o remount,exec /dev/shm
set -x
# run unit tests
buck test ReactAndroid/src/test/... --config build.threads=$UNIT_TESTS_BUILD_THREADS
-250
View File
@@ -1,250 +0,0 @@
#!/bin/bash
set -ex
# set default environment variables
ROOT=$(pwd)
SCRIPTS=$(pwd)/scripts
RUN_ANDROID=0
RUN_CLI_INSTALL=1
RUN_IOS=0
RUN_JS=0
RETRY_COUNT=${RETRY_COUNT:-1}
AVD_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
ANDROID_NPM_DEPS="appium@1.5.1 mocha@2.4.5 wd@0.3.11 colors@1.0.3 pretty-data2@0.40.1"
CLI_PACKAGE=$ROOT/react-native-cli/react-native-cli-*.tgz
PACKAGE=$ROOT/react-native-*.tgz
REACT_NATIVE_MAX_WORKERS=1
# retries command on failure
# $1 -- max attempts
# $2 -- command to run
function retry() {
local -r -i max_attempts="$1"; shift
local -r cmd="$@"
local -i attempt_num=1
until $cmd; do
if (( attempt_num == max_attempts )); then
echo "Execution of '$cmd' failed; no more attempts left"
return 1
else
(( attempt_num++ ))
echo "Execution of '$cmd' failed; retrying for attempt number $attempt_num..."
fi
done
}
# parse command line args & flags
while :; do
case "$1" in
--android)
RUN_ANDROID=1
shift
;;
--ios)
RUN_IOS=1
shift
;;
--js)
RUN_JS=1
shift
;;
--skip-cli-install)
RUN_CLI_INSTALL=0
shift
;;
--tvos)
RUN_IOS=1
shift
;;
*)
break
esac
done
function e2e_suite() {
cd $ROOT
if [ $RUN_ANDROID -eq 0 ] && [ $RUN_IOS -eq 0 ] && [ $RUN_JS -eq 0 ]; then
echo "No e2e tests specified!"
return 0
fi
# create temp dir
TEMP_DIR=$(mktemp -d /tmp/react-native-XXXXXXXX)
# To make sure we actually installed the local version
# of react-native, we will create a temp file inside the template
# and check that it exists after `react-native init
IOS_MARKER=$(mktemp $ROOT/local-cli/templates/HelloWorld/ios/HelloWorld/XXXXXXXX)
ANDROID_MARKER=$(mktemp ${ROOT}/local-cli/templates/HelloWorld/android/XXXXXXXX)
# install CLI
cd react-native-cli
npm pack
cd ..
# can skip cli install for non sudo mode
if [ $RUN_CLI_INSTALL -ne 0 ]; then
npm install -g $CLI_PACKAGE
if [ $? -ne 0 ]; then
echo "Could not install react-native-cli globally, please run in su mode"
echo "Or with --skip-cli-install to skip this step"
return 1
fi
fi
if [ $RUN_ANDROID -ne 0 ]; then
set +ex
# create virtual device
if ! android list avd | grep "$AVD_UUID" > /dev/null; then
echo no | android create avd -n $AVD_UUID -f -t android-19 --abi default/armeabi-v7a
fi
# newline at end of adb devices call and first line is headers
DEVICE_COUNT=$(adb devices | wc -l)
((DEVICE_COUNT -= 2))
# will always kill an existing emulator if one exists for fresh setup
if [[ $DEVICE_COUNT -ge 1 ]]; then
adb emu kill
fi
# emulator setup
emulator64-arm -avd $AVD_UUID -no-skin -no-audio -no-window -no-boot-anim &
bootanim=""
until [[ "$bootanim" =~ "stopped" ]]; do
sleep 5
bootanim=$(adb -e shell getprop init.svc.bootanim 2>&1)
echo "boot animation status=$bootanim"
done
set -ex
./gradlew :ReactAndroid:installArchives -Pjobs=1 -Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"
if [ $? -ne 0 ]; then
echo "Failed to compile Android binaries"
return 1
fi
fi
npm pack
if [ $? -ne 0 ]; then
echo "Failed to pack react-native"
return 1
fi
cd $TEMP_DIR
retry $RETRY_COUNT react-native init EndToEndTest --version $PACKAGE --npm
if [ $? -ne 0 ]; then
echo "Failed to execute react-native init"
echo "Most common reason is npm registry connectivity, try again"
return 1
fi
cd EndToEndTest
# android tests
if [ $RUN_ANDROID -ne 0 ]; then
echo "Running an Android e2e test"
echo "Installing e2e framework"
retry $RETRY_COUNT npm install --save-dev $ANDROID_NPM_DEPS --silent >> /dev/null
if [ $? -ne 0 ]; then
echo "Failed to install appium"
echo "Most common reason is npm registry connectivity, try again"
return 1
fi
cp $SCRIPTS/android-e2e-test.js android-e2e-test.js
cd android
echo "Downloading Maven deps"
./gradlew :app:copyDownloadableDepsToLibs
cd ..
keytool -genkey -v -keystore android/keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"
echo "Starting packager server"
node ./node_modules/.bin/appium >> /dev/null &
APPIUM_PID=$!
echo "Starting appium server $APPIUM_PID"
echo "Building app"
buck build android/app
# hack to get node unhung (kill buckd)
kill -9 $(pgrep java)
if [ $? -ne 0 ]; then
echo "could not execute Buck build, is it installed and in PATH?"
return 1
fi
npm start >> /dev/null &
SERVER_PID=$!
sleep 15
echo "Executing android e2e test"
retry $RETRY_COUNT node node_modules/.bin/_mocha android-e2e-test.js
if [ $? -ne 0 ]; then
echo "Failed to run Android e2e tests"
echo "Most likely the code is broken"
return 1
fi
# kill packager process
if kill -0 $SERVER_PID; then
echo "Killing packager $SERVER_PID"
kill -9 $SERVER_PID
fi
# kill appium process
if kill -0 $APPIUM_PID; then
echo "Killing appium $APPIUM_PID"
kill -9 $APPIUM_PID
fi
fi
# ios tests
if [ $RUN_IOS -ne 0 ]; then
echo "Running ios e2e tests not yet implemented for docker!"
fi
# js tests
if [ $RUN_JS -ne 0 ]; then
# Check the packager produces a bundle (doesn't throw an error)
REACT_NATIVE_MAX_WORKERS=1 react-native bundle --platform android --dev true --entry-file index.android.js --bundle-output android-bundle.js
if [ $? -ne 0 ]; then
echo "Could not build android bundle"
return 1
fi
REACT_NATIVE_MAX_WORKERS=1 react-native bundle --platform ios --dev true --entry-file index.ios.js --bundle-output ios-bundle.js
if [ $? -ne 0 ]; then
echo "Could not build iOS bundle"
return 1
fi
fi
# directory cleanup
rm $IOS_MARKER
rm $ANDROID_MARKER
return 0
}
retry $RETRY_COUNT e2e_suite
@@ -1,65 +0,0 @@
#!/bin/bash
# Python script to run instrumentation tests, copied from https://github.com/circleci/circle-dummy-android
# Example: ./scripts/run-android-instrumentation-tests.sh com.facebook.react.tests com.facebook.react.tests.ReactPickerTestCase
#
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH"
# clear the logs
adb logcat -c
# run tests and check output
python - $1 $2 << END
import re
import subprocess as sp
import sys
import threading
import time
done = False
test_app = sys.argv[1]
test_class = None
if len(sys.argv) > 2:
test_class = sys.argv[2]
def update():
# prevent CircleCI from killing the process for inactivity
while not done:
time.sleep(5)
print "Running in background. Waiting for 'adb' command reponse..."
t = threading.Thread(target=update)
t.dameon = True
t.start()
def run():
sp.Popen(['adb', 'wait-for-device']).communicate()
if (test_class != None):
p = sp.Popen('adb shell am instrument -w -e class %s %s/android.support.test.runner.AndroidJUnitRunner'
% (test_class, test_app), shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
else :
p = sp.Popen('adb shell am instrument -w %s/android.support.test.runner.AndroidJUnitRunner'
% (test_app), shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
return p.communicate()
success = re.compile(r'OK \(\d+ test(s)?\)')
stdout, stderr = run()
done = True
print stderr
print stdout
if success.search(stderr + stdout):
sys.exit(0)
else:
# dump the logs
sp.Popen(['adb', 'logcat', '-d']).communicate()
sys.exit(1) # make sure we fail if the test failed
END
RETVAL=$?
exit $RETVAL
-96
View File
@@ -1,96 +0,0 @@
# Dockerfile Tests
This is a high level overview of the test configuration using docker. It explains how to run the tests locally
and how they integrate with the Jenkins Pipeline script to run the automated tests on ContainerShip <https://www.containership.io/>.
## Docker Installation
It is required to have Docker running on your machine in order to build and run the tests in the Dockerfiles.
See <https://docs.docker.com/engine/installation/> for more information on how to install.
## Convenience NPM Run Scripts
We have added a number of default run scripts to the `package.json` file to simplify building and running your tests.
`npm run test-android-setup` - Pulls down the base android docker image used for running the tests
`npm run test-android-build` - Builds the docker image used to run the tests
`npm run test-android-run-unit` - Runs all the unit tests that have been built in the latest react/android docker image (note: you need to run test-android-build before executing this, if the image does not exist it will fail)
`npm run test-android-run-instrumentation` - Runs all the instrumentation tests that have been built in the latest react/android docker image (note: you need to run test-android-build before executing this, if the image does not exist it will fail). You can also pass additional flags to filter which tests instrumentation tests are run. Ex: `npm run test-android-run-instrumentation -- --filter=TestIdTestCase` to only run the TestIdTestCase instrumentation test. See below for more information
on the instrumentation test flags.
`npm run test-android-run-e2e` - Runs all the end to end tests that have been built in the latest react/android docker image (note: you need to run test-android-build before executing this, if the image does not exist it will fail)
`npm run test-android-unit` - Builds and runs the android unit tests.
`npm run test-android-instrumentation` - Builds and runs the android instrumentation tests.
`npm run test-android-e2e` - Builds and runs the android end to end tests.
## Detailed Android Setup
There are two Dockerfiles for use with the Android codebase.
The `Dockerfile.android-base` contains all the necessary prerequisites required to run the React Android tests. It is
separated out into a separate Dockerfile because these are dependencies that rarely change and also because it is quite
a beastly image since it contains all the Android depedencies for running android and the emulators (~9GB).
The good news is you should rarely have to build or pull down the base image! All iterative code updates happen as
part of the `Dockerfile.android` image build.
So step one...
`docker pull containership/android-base:latest`
This will take quite some time depending on your connection and you need to ensure you have ~10GB of free disk space.
Once this is done, you can run tests locally by executing two simple commands:
1. `docker build -t react/android -f ./ContainerShip/Dockerfile.android .`
2. `docker run --cap-add=SYS_ADMIN -it react/android bash ContainerShip/scripts/run-android-docker-unit-tests.sh`
> Note: `--cap-add=SYS_ADMIN` flag is required for the `ContainerShip/scripts/run-android-docker-unit-tests.sh` and
`ContainerShip/scripts/run-android-docker-instrumentation-tests.sh` in order to allow the remounting of `/dev/shm` as writeable
so the `buck` build system may write temporary output to that location
Every time you make any modifications to the codebase, you should re-run the `docker build ...` command in order for your
updates to be included in your local docker image.
The following shell scripts have been provided for android testing:
`ContainerShip/scripts/run-android-docker-unit-tests.sh` - Runs the standard android unit tests
`ContainerShip/scripts/run-android-docker-instrumentation-tests.sh` - Runs the android instrumentation tests on the emulator. *Note* that these
tests take quite some time to run so there are various flags you can pass in order to filter which tests are run (see below)
`ContainerShip/scripts/run-ci-e2e-tests.sh` - Runs the android end to end tests
#### ContainerShip/scripts/run-android-docker-instrumentation-tests.sh
The instrumentation test script accepts the following flags in order to customize the execution of the tests:
`--filter` - A regex that filters which instrumentation tests will be run. (Defaults to .*)
`--package` - Name of the java package containing the instrumentation tests (Defaults to com.facebook.react.tests)
`--path` - Path to the directory containing the instrumentation tests. (Defaults to ./ReactAndroid/src/androidTest/java/com/facebook/react/tests)
`--retries` - Number of times to retry a failed test before declaring a failure (Defaults to 2)
For example, if locally you only wanted to run the InitialPropsTestCase, you could do the following:
`docker run --cap-add=SYS_ADMIN -it react/android bash ContainerShip/scripts/run-android-docker-instrumentation-tests.sh --filter="InitialPropsTestCase"`
# Javascript Setup
There is a single Dockerfile for use with the javascript codebase.
The `Dockerfile.javascript` base requires all the necessary dependencies for running Javascript tests.
Any time you make an update to the codebase, you can build and run the javascript tests with the following three commands:
1. `docker build -t react/js -f ./ContainerShip/Dockerfile.javascript .`
2. `docker run -it react/js yarn test --maxWorkers=4`
3. `docker run -it react/js yarn run flow -- check`
@@ -0,0 +1,405 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
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 */; };
1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1461632C1AC3E22900C2F5AD /* libReact.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 */
/* Begin PBXContainerItemProxy section */
1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146163271AC3E22900C2F5AD /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
5F82F1761B85784500FAE87E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
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>"; };
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 = 2048/Images.xcassets; sourceTree = "<group>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5F82F1781B85785200FAE87E /* libRCTWebSocket.a in Frameworks */,
1461632D1AC3E23900C2F5AD /* libReact.a in Frameworks */,
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
13B07FAE1A68108700A75B9A /* 2048 */ = {
isa = PBXGroup;
children = (
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
);
name = 2048;
sourceTree = "<group>";
};
146163281AC3E22900C2F5AD /* Products */ = {
isa = PBXGroup;
children = (
1461632C1AC3E22900C2F5AD /* libReact.a */,
);
name = Products;
sourceTree = "<group>";
};
5F82F1731B85784500FAE87E /* Products */ = {
isa = PBXGroup;
children = (
5F82F1771B85784500FAE87E /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */,
146163271AC3E22900C2F5AD /* React.xcodeproj */,
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
};
832341B11AAA6A8300B99B32 /* Products */ = {
isa = PBXGroup;
children = (
832341B51AAA6A8300B99B32 /* libRCTText.a */,
);
name = Products;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
13B07FAE1A68108700A75B9A /* 2048 */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* 2048.app */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
13B07F861A680F5B00A75B9A /* 2048 */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "2048" */;
buildPhases = (
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = 2048;
productName = "Hello World";
productReference = 13B07F961A680F5B00A75B9A /* 2048.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = Facebook;
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "2048" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
},
{
ProductGroup = 5F82F1731B85784500FAE87E /* Products */;
ProjectRef = 5F82F1721B85784500FAE87E /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 146163281AC3E22900C2F5AD /* Products */;
ProjectRef = 146163271AC3E22900C2F5AD /* React.xcodeproj */;
},
);
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* 2048 */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
1461632C1AC3E22900C2F5AD /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libReact.a;
remoteRef = 1461632B1AC3E22900C2F5AD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
5F82F1771B85784500FAE87E /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 5F82F1761B85784500FAE87E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTText.a;
remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
13B07F8E1A680F5B00A75B9A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
13B07F871A680F5B00A75B9A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
path = 2048;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = 2048;
};
name = Debug;
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/2048/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = 2048;
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
83CBBA211A601CBA00E9B192 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "2048" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
13B07F951A680F5B00A75B9A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "2048" */ = {
isa = XCConfigurationList;
buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */,
83CBBA211A601CBA00E9B192 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}
+21
View File
@@ -0,0 +1,21 @@
/**
* 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>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
+66
View File
@@ -0,0 +1,66 @@
/**
* 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 "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/2048/Game2048.bundle?platform=ios&dev=true"];
/**
* 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/2048/Game2048.bundle?platform=ios' -o main.jsbundle
*
* then add the `main.jsbundle` file to your project and uncomment this line:
*/
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"Game2048"
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
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2048" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
@@ -8,11 +8,6 @@
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -21,15 +16,28 @@
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Automatic</string>
</dict>
</plist>
+23
View File
@@ -0,0 +1,23 @@
/**
* 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 "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
+324
View File
@@ -0,0 +1,324 @@
/**
* 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 Game2048
* @flow
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
} = React;
var Animated = require('Animated');
var GameBoard = require('GameBoard');
var TouchableBounce = require('TouchableBounce');
var BOARD_PADDING = 3;
var CELL_MARGIN = 4;
var CELL_SIZE = 60;
class Cell extends React.Component {
render() {
return <View style={styles.cell} />;
}
}
class Board extends React.Component {
render() {
return (
<View style={styles.board}>
<View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
<View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
<View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
<View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
{this.props.children}
</View>
);
}
}
class Tile extends React.Component {
state: any;
static _getPosition(index): number {
return BOARD_PADDING + (index * (CELL_SIZE + CELL_MARGIN * 2) + CELL_MARGIN);
}
constructor(props: {}) {
super(props);
var tile = this.props.tile;
this.state = {
opacity: new Animated.Value(0),
top: new Animated.Value(Tile._getPosition(tile.toRow())),
left: new Animated.Value(Tile._getPosition(tile.toColumn())),
};
}
calculateOffset(): {top: number; left: number; opacity: number} {
var tile = this.props.tile;
var offset = {
top: this.state.top,
left: this.state.left,
opacity: this.state.opacity,
};
if (tile.isNew()) {
Animated.timing(this.state.opacity, {
duration: 100,
toValue: 1,
}).start();
} else {
Animated.parallel([
Animated.timing(offset.top, {
duration: 100,
toValue: Tile._getPosition(tile.toRow()),
}),
Animated.timing(offset.left, {
duration: 100,
toValue: Tile._getPosition(tile.toColumn()),
}),
]).start();
}
return offset;
}
render() {
var tile = this.props.tile;
var tileStyles = [
styles.tile,
styles['tile' + tile.value],
this.calculateOffset(),
];
var textStyles = [
styles.value,
tile.value > 4 && styles.whiteText,
tile.value > 100 && styles.threeDigits,
tile.value > 1000 && styles.fourDigits,
];
return (
<Animated.View style={tileStyles}>
<Text style={textStyles}>{tile.value}</Text>
</Animated.View>
);
}
}
class GameEndOverlay extends React.Component {
render() {
var board = this.props.board;
if (!board.hasWon() && !board.hasLost()) {
return <View/>;
}
var message = board.hasWon() ?
'Good Job!' : 'Game Over';
return (
<View style={styles.overlay}>
<Text style={styles.overlayMessage}>{message}</Text>
<TouchableBounce onPress={this.props.onRestart} style={styles.tryAgain}>
<Text style={styles.tryAgainText}>Try Again?</Text>
</TouchableBounce>
</View>
);
}
}
class Game2048 extends React.Component {
startX: number;
startY: number;
state: any;
constructor(props: {}) {
super(props);
this.state = {
board: new GameBoard(),
};
this.startX = 0;
this.startY = 0;
}
restartGame() {
this.setState({board: new GameBoard()});
}
handleTouchStart(event: Object) {
if (this.state.board.hasWon()) {
return;
}
this.startX = event.nativeEvent.pageX;
this.startY = event.nativeEvent.pageY;
}
handleTouchEnd(event: Object) {
if (this.state.board.hasWon()) {
return;
}
var deltaX = event.nativeEvent.pageX - this.startX;
var deltaY = event.nativeEvent.pageY - this.startY;
var direction = -1;
if (Math.abs(deltaX) > 3 * Math.abs(deltaY) && Math.abs(deltaX) > 30) {
direction = deltaX > 0 ? 2 : 0;
} else if (Math.abs(deltaY) > 3 * Math.abs(deltaX) && Math.abs(deltaY) > 30) {
direction = deltaY > 0 ? 3 : 1;
}
if (direction !== -1) {
this.setState({board: this.state.board.move(direction)});
}
}
render() {
var tiles = this.state.board.tiles
.filter((tile) => tile.value)
.map((tile) => <Tile ref={tile.id} key={tile.id} tile={tile} />);
return (
<View
style={styles.container}
onTouchStart={(event) => this.handleTouchStart(event)}
onTouchEnd={(event) => this.handleTouchEnd(event)}>
<Board>
{tiles}
</Board>
<GameEndOverlay board={this.state.board} onRestart={() => this.restartGame()} />
</View>
);
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
board: {
padding: BOARD_PADDING,
backgroundColor: '#bbaaaa',
borderRadius: 5,
},
overlay: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(221, 221, 221, 0.5)',
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
overlayMessage: {
fontSize: 40,
marginBottom: 20,
},
tryAgain: {
backgroundColor: '#887761',
padding: 20,
borderRadius: 5,
},
tryAgainText: {
color: '#ffffff',
fontSize: 20,
fontWeight: '500',
},
cell: {
width: CELL_SIZE,
height: CELL_SIZE,
borderRadius: 5,
backgroundColor: '#ddccbb',
margin: CELL_MARGIN,
},
row: {
flexDirection: 'row',
},
tile: {
position: 'absolute',
width: CELL_SIZE,
height: CELL_SIZE,
backgroundColor: '#ddccbb',
borderRadius: 5,
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
value: {
fontSize: 24,
color: '#776666',
fontFamily: 'Verdana',
fontWeight: '500',
},
tile2: {
backgroundColor: '#eeeeee',
},
tile4: {
backgroundColor: '#eeeecc',
},
tile8: {
backgroundColor: '#ffbb87',
},
tile16: {
backgroundColor: '#ff9966',
},
tile32: {
backgroundColor: '#ff7755',
},
tile64: {
backgroundColor: '#ff5533',
},
tile128: {
backgroundColor: '#eecc77',
},
tile256: {
backgroundColor: '#eecc66',
},
tile512: {
backgroundColor: '#eecc55',
},
tile1024: {
backgroundColor: '#eecc33',
},
tile2048: {
backgroundColor: '#eecc22',
},
whiteText: {
color: '#ffffff',
},
threeDigits: {
fontSize: 20,
},
fourDigits: {
fontSize: 18,
},
});
AppRegistry.registerComponent('Game2048', () => Game2048);
module.exports = Game2048;
+201
View File
@@ -0,0 +1,201 @@
/**
* 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 GameBoard
* @flow
*/
'use strict';
// NB: Taken straight from: https://github.com/IvanVergiliev/2048-react/blob/master/src/board.js
// with no modification except to format it for CommonJS and fix lint/flow errors
var rotateLeft = function (matrix) {
var rows = matrix.length;
var columns = matrix[0].length;
var res = [];
for (var row = 0; row < rows; ++row) {
res.push([]);
for (var column = 0; column < columns; ++column) {
res[row][column] = matrix[column][columns - row - 1];
}
}
return res;
};
var Tile = function (value?: number, row?: number, column?: number) {
this.value = value || 0;
this.row = row || -1;
this.column = column || -1;
this.oldRow = -1;
this.oldColumn = -1;
this.markForDeletion = false;
this.mergedInto = null;
this.id = Tile.id++;
};
Tile.id = 0;
Tile.prototype.moveTo = function (row, column) {
this.oldRow = this.row;
this.oldColumn = this.column;
this.row = row;
this.column = column;
};
Tile.prototype.isNew = function () {
return this.oldRow === -1 && !this.mergedInto;
};
Tile.prototype.hasMoved = function () {
return (this.fromRow() !== -1 && (this.fromRow() !== this.toRow() || this.fromColumn() !== this.toColumn())) ||
this.mergedInto;
};
Tile.prototype.fromRow = function () {
return this.mergedInto ? this.row : this.oldRow;
};
Tile.prototype.fromColumn = function () {
return this.mergedInto ? this.column : this.oldColumn;
};
Tile.prototype.toRow = function () {
return this.mergedInto ? this.mergedInto.row : this.row;
};
Tile.prototype.toColumn = function () {
return this.mergedInto ? this.mergedInto.column : this.column;
};
var Board = function () {
this.tiles = [];
this.cells = [];
for (var i = 0; i < Board.size; ++i) {
this.cells[i] = [this.addTile(), this.addTile(), this.addTile(), this.addTile()];
}
this.addRandomTile();
this.setPositions();
this.won = false;
};
Board.prototype.addTile = function () {
var res = new Tile();
Tile.apply(res, arguments);
this.tiles.push(res);
return res;
};
Board.size = 4;
Board.prototype.moveLeft = function () {
var hasChanged = false;
for (var row = 0; row < Board.size; ++row) {
var currentRow = this.cells[row].filter(function (tile) { return tile.value !== 0; });
var resultRow = [];
for (var target = 0; target < Board.size; ++target) {
var targetTile = currentRow.length ? currentRow.shift() : this.addTile();
if (currentRow.length > 0 && currentRow[0].value === targetTile.value) {
var tile1 = targetTile;
targetTile = this.addTile(targetTile.value);
tile1.mergedInto = targetTile;
var tile2 = currentRow.shift();
tile2.mergedInto = targetTile;
targetTile.value += tile2.value;
}
resultRow[target] = targetTile;
this.won = this.won || (targetTile.value === 2048);
hasChanged = hasChanged || (targetTile.value !== this.cells[row][target].value);
}
this.cells[row] = resultRow;
}
return hasChanged;
};
Board.prototype.setPositions = function () {
this.cells.forEach(function (row, rowIndex) {
row.forEach(function (tile, columnIndex) {
tile.oldRow = tile.row;
tile.oldColumn = tile.column;
tile.row = rowIndex;
tile.column = columnIndex;
tile.markForDeletion = false;
});
});
};
Board.fourProbability = 0.1;
Board.prototype.addRandomTile = function () {
var emptyCells = [];
for (var r = 0; r < Board.size; ++r) {
for (var c = 0; c < Board.size; ++c) {
if (this.cells[r][c].value === 0) {
emptyCells.push({r: r, c: c});
}
}
}
var index = Math.floor(Math.random() * emptyCells.length);
var cell = emptyCells[index];
var newValue = Math.random() < Board.fourProbability ? 4 : 2;
this.cells[cell.r][cell.c] = this.addTile(newValue);
};
Board.prototype.move = function (direction) {
// 0 -> left, 1 -> up, 2 -> right, 3 -> down
this.clearOldTiles();
for (var i = 0; i < direction; ++i) {
this.cells = rotateLeft(this.cells);
}
var hasChanged = this.moveLeft();
for (var i = direction; i < 4; ++i) {
this.cells = rotateLeft(this.cells);
}
if (hasChanged) {
this.addRandomTile();
}
this.setPositions();
return this;
};
Board.prototype.clearOldTiles = function () {
this.tiles = this.tiles.filter(function (tile) { return tile.markForDeletion === false; });
this.tiles.forEach(function (tile) { tile.markForDeletion = true; });
};
Board.prototype.hasWon = function () {
return this.won;
};
Board.deltaX = [-1, 0, 1, 0];
Board.deltaY = [0, -1, 0, 1];
Board.prototype.hasLost = function () {
var canMove = false;
for (var row = 0; row < Board.size; ++row) {
for (var column = 0; column < Board.size; ++column) {
canMove = canMove || (this.cells[row][column].value === 0);
for (var dir = 0; dir < 4; ++dir) {
var newRow = row + Board.deltaX[dir];
var newColumn = column + Board.deltaY[dir];
if (newRow < 0 || newRow >= Board.size || newColumn < 0 || newColumn >= Board.size) {
continue;
}
canMove = canMove || (this.cells[row][column].value === this.cells[newRow][newColumn].value);
}
}
}
return !canMove;
};
module.exports = Board;
+106
View File
@@ -0,0 +1,106 @@
/**
* 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 {
Image,
Platform,
StyleSheet,
Text,
TouchableHighlight,
TouchableNativeFeedback,
View
} = React;
var getStyleFromScore = require('./getStyleFromScore');
var getImageSource = require('./getImageSource');
var getTextFromScore = require('./getTextFromScore');
var MovieCell = React.createClass({
render: function() {
var criticsScore = this.props.movie.ratings.critics_score;
var TouchableElement = TouchableHighlight;
if (Platform.OS === 'android') {
TouchableElement = TouchableNativeFeedback;
}
return (
<View>
<TouchableElement
onPress={this.props.onSelect}
onShowUnderlay={this.props.onHighlight}
onHideUnderlay={this.props.onUnhighlight}>
<View style={styles.row}>
{/* $FlowIssue #7363964 - There's a bug in Flow where you cannot
* omit a property or set it to undefined if it's inside a shape,
* even if it isn't required */}
<Image
source={getImageSource(this.props.movie, 'det')}
style={styles.cellImage}
/>
<View style={styles.textContainer}>
<Text style={styles.movieTitle} numberOfLines={2}>
{this.props.movie.title}
</Text>
<Text style={styles.movieYear} numberOfLines={1}>
{this.props.movie.year}
{' '}&bull;{' '}
<Text style={getStyleFromScore(criticsScore)}>
Critics {getTextFromScore(criticsScore)}
</Text>
</Text>
</View>
</View>
</TouchableElement>
</View>
);
}
});
var styles = StyleSheet.create({
textContainer: {
flex: 1,
},
movieTitle: {
flex: 1,
fontSize: 16,
fontWeight: '500',
marginBottom: 2,
},
movieYear: {
color: '#999999',
fontSize: 12,
},
row: {
alignItems: 'center',
backgroundColor: 'white',
flexDirection: 'row',
padding: 5,
},
cellImage: {
backgroundColor: '#dddddd',
height: 93,
marginRight: 10,
width: 60,
},
cellBorder: {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
height: StyleSheet.hairlineWidth,
marginLeft: 4,
},
});
module.exports = MovieCell;
+166
View File
@@ -0,0 +1,166 @@
/**
* 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 {
Image,
ScrollView,
StyleSheet,
Text,
View,
} = React;
var getImageSource = require('./getImageSource');
var getStyleFromScore = require('./getStyleFromScore');
var getTextFromScore = require('./getTextFromScore');
var MovieScreen = React.createClass({
render: function() {
return (
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={styles.mainSection}>
{/* $FlowIssue #7363964 - There's a bug in Flow where you cannot
* omit a property or set it to undefined if it's inside a shape,
* even if it isn't required */}
<Image
source={getImageSource(this.props.movie, 'det')}
style={styles.detailsImage}
/>
<View style={styles.rightPane}>
<Text style={styles.movieTitle}>{this.props.movie.title}</Text>
<Text>{this.props.movie.year}</Text>
<View style={styles.mpaaWrapper}>
<Text style={styles.mpaaText}>
{this.props.movie.mpaa_rating}
</Text>
</View>
<Ratings ratings={this.props.movie.ratings} />
</View>
</View>
<View style={styles.separator} />
<Text>
{this.props.movie.synopsis}
</Text>
<View style={styles.separator} />
<Cast actors={this.props.movie.abridged_cast} />
</ScrollView>
);
},
});
var Ratings = React.createClass({
render: function() {
var criticsScore = this.props.ratings.critics_score;
var audienceScore = this.props.ratings.audience_score;
return (
<View>
<View style={styles.rating}>
<Text style={styles.ratingTitle}>Critics:</Text>
<Text style={[styles.ratingValue, getStyleFromScore(criticsScore)]}>
{getTextFromScore(criticsScore)}
</Text>
</View>
<View style={styles.rating}>
<Text style={styles.ratingTitle}>Audience:</Text>
<Text style={[styles.ratingValue, getStyleFromScore(audienceScore)]}>
{getTextFromScore(audienceScore)}
</Text>
</View>
</View>
);
},
});
var Cast = React.createClass({
render: function() {
if (!this.props.actors) {
return null;
}
return (
<View>
<Text style={styles.castTitle}>Actors</Text>
{this.props.actors.map(actor =>
<Text key={actor.name} style={styles.castActor}>
&bull; {actor.name}
</Text>
)}
</View>
);
},
});
var styles = StyleSheet.create({
contentContainer: {
padding: 10,
},
rightPane: {
justifyContent: 'space-between',
flex: 1,
},
movieTitle: {
flex: 1,
fontSize: 16,
fontWeight: '500',
},
rating: {
marginTop: 10,
},
ratingTitle: {
fontSize: 14,
},
ratingValue: {
fontSize: 28,
fontWeight: '500',
},
mpaaWrapper: {
alignSelf: 'flex-start',
borderColor: 'black',
borderWidth: 1,
paddingHorizontal: 3,
marginVertical: 5,
},
mpaaText: {
fontFamily: 'Palatino',
fontSize: 13,
fontWeight: '500',
},
mainSection: {
flexDirection: 'row',
},
detailsImage: {
width: 134,
height: 200,
backgroundColor: '#eaeaea',
marginRight: 10,
},
separator: {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
height: StyleSheet.hairlineWidth,
marginVertical: 10,
},
castTitle: {
fontWeight: '500',
marginBottom: 3,
},
castActor: {
marginLeft: 2,
},
});
module.exports = MovieScreen;
@@ -0,0 +1,497 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341801B1AA91740003F314A /* libRCTNetwork.a */; };
13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13442C051AA90E7D0037E5B0 /* libRCTImage.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 */; };
140D9B661AC36C42004F25EE /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14312D241AC3654D00CDC950 /* libRCTLinking.a */; };
14A2D4421AC3E43800CC738A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14A2D4411AC3E41A00CC738A /* libReact.a */; };
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5725B1AA6236500CDF9C8 /* libRCTText.a */; };
67C95F201B0E64A30040BCE2 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67C95F1E1B0E647A0040BCE2 /* libRCTWebSocket.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
1341801A1AA91740003F314A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B511DB1A9E6C8500147676;
remoteInfo = RCTNetwork;
};
13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
remoteInfo = RCTImage;
};
14312D231AC3654D00CDC950 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTLinking;
};
14A2D4401AC3E41A00CC738A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 14A2D43C1AC3E41A00CC738A /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
67C95F1D1B0E647A0040BCE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
134180151AA91740003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* Movies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Movies.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Movies/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Movies/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 = Movies/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Movies/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Movies/main.m; sourceTree = "<group>"; };
14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
14A2D43C1AC3E41A00CC738A /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = SOURCE_ROOT; };
67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
67C95F201B0E64A30040BCE2 /* libRCTWebSocket.a in Frameworks */,
14A2D4421AC3E43800CC738A /* libReact.a in Frameworks */,
140D9B661AC36C42004F25EE /* libRCTLinking.a in Frameworks */,
1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */,
13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */,
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
134180161AA91740003F314A /* Products */ = {
isa = PBXGroup;
children = (
1341801B1AA91740003F314A /* libRCTNetwork.a */,
);
name = Products;
sourceTree = "<group>";
};
13442C011AA90E7D0037E5B0 /* Products */ = {
isa = PBXGroup;
children = (
13442C051AA90E7D0037E5B0 /* libRCTImage.a */,
);
name = Products;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* Movies */ = {
isa = PBXGroup;
children = (
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
);
name = Movies;
sourceTree = "<group>";
};
14312D1F1AC3654D00CDC950 /* Products */ = {
isa = PBXGroup;
children = (
14312D241AC3654D00CDC950 /* libRCTLinking.a */,
);
name = Products;
sourceTree = "<group>";
};
14A2D43D1AC3E41A00CC738A /* Products */ = {
isa = PBXGroup;
children = (
14A2D4411AC3E41A00CC738A /* libReact.a */,
);
name = Products;
sourceTree = "<group>";
};
58C571FC1AA6124500CDF9C8 /* Libraries */ = {
isa = PBXGroup;
children = (
67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */,
14A2D43C1AC3E41A00CC738A /* React.xcodeproj */,
14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */,
134180151AA91740003F314A /* RCTNetwork.xcodeproj */,
13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */,
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
};
58C572571AA6236500CDF9C8 /* Products */ = {
isa = PBXGroup;
children = (
58C5725B1AA6236500CDF9C8 /* libRCTText.a */,
);
name = Products;
sourceTree = "<group>";
};
67C95F161B0E647A0040BCE2 /* Products */ = {
isa = PBXGroup;
children = (
67C95F1E1B0E647A0040BCE2 /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
13B07FAE1A68108700A75B9A /* Movies */,
58C571FC1AA6124500CDF9C8 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* Movies.app */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
13B07F861A680F5B00A75B9A /* Movies */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Movies" */;
buildPhases = (
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Movies;
productName = "Hello World";
productReference = 13B07F961A680F5B00A75B9A /* Movies.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = Facebook;
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Movies" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 13442C011AA90E7D0037E5B0 /* Products */;
ProjectRef = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */;
},
{
ProductGroup = 14312D1F1AC3654D00CDC950 /* Products */;
ProjectRef = 14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */;
},
{
ProductGroup = 134180161AA91740003F314A /* Products */;
ProjectRef = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */;
},
{
ProductGroup = 58C572571AA6236500CDF9C8 /* Products */;
ProjectRef = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */;
},
{
ProductGroup = 67C95F161B0E647A0040BCE2 /* Products */;
ProjectRef = 67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 14A2D43D1AC3E41A00CC738A /* Products */;
ProjectRef = 14A2D43C1AC3E41A00CC738A /* React.xcodeproj */;
},
);
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* Movies */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
1341801B1AA91740003F314A /* libRCTNetwork.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTNetwork.a;
remoteRef = 1341801A1AA91740003F314A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
13442C051AA90E7D0037E5B0 /* libRCTImage.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTImage.a;
remoteRef = 13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
14312D241AC3654D00CDC950 /* libRCTLinking.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTLinking.a;
remoteRef = 14312D231AC3654D00CDC950 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
14A2D4411AC3E41A00CC738A /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libReact.a;
remoteRef = 14A2D4401AC3E41A00CC738A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
58C5725B1AA6236500CDF9C8 /* libRCTText.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTText.a;
remoteRef = 58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
67C95F1E1B0E647A0040BCE2 /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 67C95F1D1B0E647A0040BCE2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
13B07F8E1A680F5B00A75B9A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
13B07F871A680F5B00A75B9A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
path = Movies;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/Movies/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = Movies;
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../Libraries/**";
};
name = Debug;
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/Movies/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = Movies;
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../Libraries/**";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
83CBBA211A601CBA00E9B192 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Movies" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
13B07F951A680F5B00A75B9A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Movies" */ = {
isa = XCConfigurationList;
buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */,
83CBBA211A601CBA00E9B192 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Movies.app"
BlueprintName = "Movies"
ReferencedContainer = "container:Movies.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Movies.app"
BlueprintName = "Movies"
ReferencedContainer = "container:Movies.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Movies.app"
BlueprintName = "Movies"
ReferencedContainer = "container:Movies.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Movies.app"
BlueprintName = "Movies"
ReferencedContainer = "container:Movies.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -12,34 +12,11 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <XCTest/XCTest.h>
#import <UIKit/UIKit.h>
#import <React/RCTConvert.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@interface RCTConvert_YGValueTests : XCTestCase
@property (nonatomic, strong) UIWindow *window;
@end
@implementation RCTConvert_YGValueTests
- (void)testUndefined
{
YGValue value = [RCTConvert YGValue:nil];
XCTAssertEqual(value.unit, YGUnitUndefined);
}
- (void)testNumberPoints
{
YGValue value = [RCTConvert YGValue:@100];
XCTAssertEqual(value.unit, YGUnitPoint);
XCTAssertEqual(value.value, 100);
}
- (void)testStringPercent
{
YGValue value = [RCTConvert YGValue:@"100%"];
XCTAssertEqual(value.unit, YGUnitPercent);
XCTAssertEqual(value.value, 100);
}
@end
+78
View File
@@ -0,0 +1,78 @@
/**
* 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 "AppDelegate.h"
#import "RCTLinkingManager.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/Movies/MoviesApp.ios.bundle?platform=ios&dev=true"];
/**
* 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.ios.bundle?platform=ios&dev=true' -o main.jsbundle
*
* then add the `main.jsbundle` file to your project and uncomment this line:
*/
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"MoviesApp"
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;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [RCTLinkingManager application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}
@end
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Movies" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
@@ -0,0 +1,38 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -4,12 +4,10 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Hello App Display Name</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -20,10 +18,26 @@
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>movies</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
@@ -38,19 +52,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>
+22
View File
@@ -0,0 +1,22 @@
/**
* 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 "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
+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;
+51
View File
@@ -0,0 +1,51 @@
/**
* 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,
NavigatorIOS,
StyleSheet,
} = React;
var SearchScreen = require('./SearchScreen');
var MoviesApp = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
title: 'Movies',
component: SearchScreen,
}}
/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
});
AppRegistry.registerComponent('MoviesApp', () => MoviesApp);
module.exports = MoviesApp;
+42
View File
@@ -0,0 +1,42 @@
# Movies app
The Movies app is a demonstration of basic concepts, such as fetching data, rendering a list of data including images, and navigating between different screens.
## Running this app
Before running the app, make sure you ran:
git clone https://github.com/facebook/react-native.git
cd react-native
npm install
### Running on iOS
Mac OS and Xcode are required.
- Open `Examples/Movies/Movies.xcodeproj` in Xcode
- Hit the Run button
See [Running on device](https://facebook.github.io/react-native/docs/running-on-device-ios.html) if you want to use a physical device.
### Running on Android
You'll need to have all the [prerequisites](https://github.com/facebook/react-native/tree/master/ReactAndroid#prerequisites) (SDK, NDK) for Building React Native installed.
Start an Android emulator ([Genymotion](https://www.genymotion.com) is recommended).
cd react-native
./gradlew :Examples:Movies:android:app:installDebug
./packager/packager.sh
_Note: Building for the first time can take a while._
Open the Movies app in your emulator.
See [Running on Device](https://facebook.github.io/react-native/docs/running-on-device-android.html) in case you want to use a physical device.
## Built from source
Building the app on both iOS and Android means building the React Native framework from source. This way you're running the latest native and JS code the way you see it in your clone of the github repo.
This is different from apps created using `react-native init` which have a dependency on a specific version of React Native JS and native code, declared in a `package.json` file (and `build.gradle` for Android apps).
+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;
+66
View File
@@ -0,0 +1,66 @@
/**
* 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 {
ActivityIndicatorIOS,
TextInput,
StyleSheet,
View,
} = React;
var SearchBar = React.createClass({
render: function() {
return (
<View style={styles.searchBar}>
<TextInput
autoCapitalize="none"
autoCorrect={false}
onChange={this.props.onSearchChange}
placeholder="Search a movie..."
onFocus={this.props.onFocus}
style={styles.searchBarInput}
/>
<ActivityIndicatorIOS
animating={this.props.isLoading}
style={styles.spinner}
/>
</View>
);
}
});
var styles = StyleSheet.create({
searchBar: {
marginTop: 64,
padding: 3,
paddingLeft: 8,
flexDirection: 'row',
alignItems: 'center',
},
searchBarInput: {
fontSize: 15,
flex: 1,
height: 30,
},
spinner: {
width: 30,
},
});
module.exports = SearchBar;
+376
View File
@@ -0,0 +1,376 @@
/**
* 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 {
ActivityIndicatorIOS,
ListView,
Platform,
ProgressBarAndroid,
StyleSheet,
Text,
View,
} = React;
var TimerMixin = require('react-timer-mixin');
var invariant = require('fbjs/lib/invariant');
var dismissKeyboard = require('dismissKeyboard');
var MovieCell = require('./MovieCell');
var MovieScreen = require('./MovieScreen');
var SearchBar = require('SearchBar');
/**
* This is for demo purposes only, and rate limited.
* In case you want to use the Rotten Tomatoes' API on a real app you should
* create an account at http://developer.rottentomatoes.com/
*/
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/';
var API_KEYS = [
'7waqfqbprs7pajbz28mqf6vz',
// 'y4vwv8m33hed9ety83jmv52f', Fallback api_key
];
// Results should be cached keyed by the query
// with values of null meaning "being fetched"
// and anything besides null and undefined
// as the result of a valid query
var resultsCache = {
dataForQuery: {},
nextPageNumberForQuery: {},
totalForQuery: {},
};
var LOADING = {};
var SearchScreen = React.createClass({
mixins: [TimerMixin],
timeoutID: (null: any),
getInitialState: function() {
return {
isLoading: false,
isLoadingTail: false,
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
filter: '',
queryNumber: 0,
};
},
componentDidMount: function() {
this.searchMovies('');
},
_urlForQueryAndPage: function(query: string, pageNumber: number): string {
var apiKey = API_KEYS[this.state.queryNumber % API_KEYS.length];
if (query) {
return (
API_URL + 'movies.json?apikey=' + apiKey + '&q=' +
encodeURIComponent(query) + '&page_limit=20&page=' + pageNumber
);
} else {
// With no query, load latest movies
return (
API_URL + 'lists/movies/in_theaters.json?apikey=' + apiKey +
'&page_limit=20&page=' + pageNumber
);
}
},
searchMovies: function(query: string) {
this.timeoutID = null;
this.setState({filter: query});
var cachedResultsForQuery = resultsCache.dataForQuery[query];
if (cachedResultsForQuery) {
if (!LOADING[query]) {
this.setState({
dataSource: this.getDataSource(cachedResultsForQuery),
isLoading: false
});
} else {
this.setState({isLoading: true});
}
return;
}
LOADING[query] = true;
resultsCache.dataForQuery[query] = null;
this.setState({
isLoading: true,
queryNumber: this.state.queryNumber + 1,
isLoadingTail: false,
});
fetch(this._urlForQueryAndPage(query, 1))
.then((response) => response.json())
.catch((error) => {
LOADING[query] = false;
resultsCache.dataForQuery[query] = undefined;
this.setState({
dataSource: this.getDataSource([]),
isLoading: false,
});
})
.then((responseData) => {
LOADING[query] = false;
resultsCache.totalForQuery[query] = responseData.total;
resultsCache.dataForQuery[query] = responseData.movies;
resultsCache.nextPageNumberForQuery[query] = 2;
if (this.state.filter !== query) {
// do not update state if the query is stale
return;
}
this.setState({
isLoading: false,
dataSource: this.getDataSource(responseData.movies),
});
})
.done();
},
hasMore: function(): boolean {
var query = this.state.filter;
if (!resultsCache.dataForQuery[query]) {
return true;
}
return (
resultsCache.totalForQuery[query] !==
resultsCache.dataForQuery[query].length
);
},
onEndReached: function() {
var query = this.state.filter;
if (!this.hasMore() || this.state.isLoadingTail) {
// We're already fetching or have all the elements so noop
return;
}
if (LOADING[query]) {
return;
}
LOADING[query] = true;
this.setState({
queryNumber: this.state.queryNumber + 1,
isLoadingTail: true,
});
var page = resultsCache.nextPageNumberForQuery[query];
invariant(page != null, 'Next page number for "%s" is missing', query);
fetch(this._urlForQueryAndPage(query, page))
.then((response) => response.json())
.catch((error) => {
console.error(error);
LOADING[query] = false;
this.setState({
isLoadingTail: false,
});
})
.then((responseData) => {
var moviesForQuery = resultsCache.dataForQuery[query].slice();
LOADING[query] = false;
// We reached the end of the list before the expected number of results
if (!responseData.movies) {
resultsCache.totalForQuery[query] = moviesForQuery.length;
} else {
for (var i in responseData.movies) {
moviesForQuery.push(responseData.movies[i]);
}
resultsCache.dataForQuery[query] = moviesForQuery;
resultsCache.nextPageNumberForQuery[query] += 1;
}
if (this.state.filter !== query) {
// do not update state if the query is stale
return;
}
this.setState({
isLoadingTail: false,
dataSource: this.getDataSource(resultsCache.dataForQuery[query]),
});
})
.done();
},
getDataSource: function(movies: Array<any>): ListView.DataSource {
return this.state.dataSource.cloneWithRows(movies);
},
selectMovie: function(movie: Object) {
if (Platform.OS === 'ios') {
this.props.navigator.push({
title: movie.title,
component: MovieScreen,
passProps: {movie},
});
} else {
dismissKeyboard();
this.props.navigator.push({
title: movie.title,
name: 'movie',
movie: movie,
});
}
},
onSearchChange: function(event: Object) {
var filter = event.nativeEvent.text.toLowerCase();
this.clearTimeout(this.timeoutID);
this.timeoutID = this.setTimeout(() => this.searchMovies(filter), 100);
},
renderFooter: function() {
if (!this.hasMore() || !this.state.isLoadingTail) {
return <View style={styles.scrollSpinner} />;
}
if (Platform.OS === 'ios') {
return <ActivityIndicatorIOS style={styles.scrollSpinner} />;
} else {
return (
<View style={{alignItems: 'center'}}>
<ProgressBarAndroid styleAttr="Large"/>
</View>
);
}
},
renderSeparator: function(
sectionID: number | string,
rowID: number | string,
adjacentRowHighlighted: boolean
) {
var style = styles.rowSeparator;
if (adjacentRowHighlighted) {
style = [style, styles.rowSeparatorHide];
}
return (
<View key={'SEP_' + sectionID + '_' + rowID} style={style}/>
);
},
renderRow: function(
movie: Object,
sectionID: number | string,
rowID: number | string,
highlightRowFunc: (sectionID: ?number | string, rowID: ?number | string) => void,
) {
return (
<MovieCell
key={movie.id}
onSelect={() => this.selectMovie(movie)}
onHighlight={() => highlightRowFunc(sectionID, rowID)}
onUnhighlight={() => highlightRowFunc(null, null)}
movie={movie}
/>
);
},
render: function() {
var content = this.state.dataSource.getRowCount() === 0 ?
<NoMovies
filter={this.state.filter}
isLoading={this.state.isLoading}
/> :
<ListView
ref="listview"
renderSeparator={this.renderSeparator}
dataSource={this.state.dataSource}
renderFooter={this.renderFooter}
renderRow={this.renderRow}
onEndReached={this.onEndReached}
automaticallyAdjustContentInsets={false}
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps={true}
showsVerticalScrollIndicator={false}
/>;
return (
<View style={styles.container}>
<SearchBar
onSearchChange={this.onSearchChange}
isLoading={this.state.isLoading}
onFocus={() =>
this.refs.listview && this.refs.listview.getScrollResponder().scrollTo({ x: 0, y: 0 })}
/>
<View style={styles.separator} />
{content}
</View>
);
},
});
var NoMovies = React.createClass({
render: function() {
var text = '';
if (this.props.filter) {
text = `No results for "${this.props.filter}"`;
} else if (!this.props.isLoading) {
// If we're looking at the latest movies, aren't currently loading, and
// still have no results, show a message
text = 'No movies found';
}
return (
<View style={[styles.container, styles.centerText]}>
<Text style={styles.noMoviesText}>{text}</Text>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
centerText: {
alignItems: 'center',
},
noMoviesText: {
marginTop: 80,
color: '#888888',
},
separator: {
height: 1,
backgroundColor: '#eeeeee',
},
scrollSpinner: {
marginVertical: 20,
},
rowSeparator: {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
height: 1,
marginLeft: 4,
},
rowSeparatorHide: {
opacity: 0.0,
},
});
module.exports = SearchScreen;
@@ -0,0 +1,36 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*/
'use strict';
jest.dontMock('../getImageSource');
var getImageSource = require('../getImageSource');
describe('getImageSource', () => {
it('returns null for invalid input', () => {
expect(getImageSource().uri).toBe(null);
});
it('returns a movie thumbnail', () => {
var uri = 'https://facebook.com';
var source = {
posters: {
thumbnail: uri,
},
};
expect(getImageSource(source).uri).toBe(uri);
});
it('returns a movie thumbnail with kind', () => {
var uri = 'https://facebook.com?tmb';
var source = {
posters: {
thumbnail: uri,
},
};
expect(getImageSource(source, 'kind').uri).toBe(
'https://facebook.com?kind'
);
});
});
+43
View File
@@ -0,0 +1,43 @@
include_defs('//ReactAndroid/DEFS')
android_binary(
name = 'app',
manifest = 'src/main/AndroidManifest.xml',
keystore = '//keystores:debug',
deps = [
':movies-lib',
],
)
android_library(
name = 'movies-lib',
srcs = glob(['src/main/java/**/*.java']),
deps = [
react_native_target('java/com/facebook/csslayout:csslayout'),
react_native_target('java/com/facebook/react:react'),
react_native_target('java/com/facebook/react/devsupport:devsupport'),
react_native_target('java/com/facebook/react/modules/core:core'),
react_native_target('java/com/facebook/react/shell:shell'),
react_native_target('java/com/facebook/react/touch:touch'),
react_native_target('java/com/facebook/react/uimanager:uimanager'),
react_native_target('java/com/facebook/react/uimanager/annotations:annotations'),
react_native_target('java/com/facebook/react/views/image:image'),
react_native_target('java/com/facebook/react/views/recyclerview:recyclerview'),
react_native_target('java/com/facebook/react/views/scroll:scroll'),
react_native_target('java/com/facebook/react/views/text:text'),
react_native_target('java/com/facebook/react/views/view:view'),
# .so files are prebuilt by Gradle with `./gradlew :ReactAndroid:packageReactNdkLibsForBuck`
react_native_target('jni/prebuilt:reactnative-libs'),
react_native_target('jni/prebuilt:android-jsc'),
react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'),
react_native_dep('third-party/java/jsr-305:jsr-305'),
':res',
],
)
android_resource(
name = 'res',
res = 'src/main/res',
package = 'com.facebook.react.movies',
)
+31
View File
@@ -0,0 +1,31 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
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:23.0.1'
// Build React Native from source
compile project(':ReactAndroid')
}
@@ -0,0 +1 @@
android.useDeprecatedNdk=true
+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,23 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.react.movies">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<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,52 @@
/**
* 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 com.facebook.react.ReactActivity;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
public class MoviesActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "MoviesApp";
}
@Override
protected @Nullable String getBundleAssetName() {
return "MoviesApp.android.bundle";
};
@Override
protected String getJSMainModuleName() {
return "Examples/Movies/MoviesApp.android";
}
@Override
protected boolean getUseDeveloperSupport() {
return true;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
}
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>
+26
View File
@@ -0,0 +1,26 @@
/**
* 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';
function getImageSource(movie: Object, kind: ?string): {uri: ?string} {
var uri = movie && movie.posters ? movie.posters.thumbnail : null;
if (uri && kind) {
uri = uri.replace('tmb', kind);
}
return { uri };
}
module.exports = getImageSource;
@@ -1,5 +1,3 @@
#!/usr/bin/env node
/**
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
@@ -14,31 +12,37 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule http_test_server
*/
'use strict';
/* eslint-env node */
var React = require('react-native');
var {
StyleSheet,
} = React;
console.log(`\
Test server for WebSocketExample
var MAX_VALUE = 200;
This will set a cookie named "wstest" on the response of any incoming request.
`);
import type { StyleObj } from 'StyleSheetTypes';
const connect = require('connect');
const http = require('http');
function getStyleFromScore(score: number): StyleObj {
if (score < 0) {
return styles.noScore;
}
const app = connect();
app.use(function(req, res) {
console.log('received request');
const cookieOptions = {
//httpOnly: true, // the cookie is not accessible by the user (javascript,...)
secure: false, // allow HTTP
var normalizedScore = Math.round((score / 100) * MAX_VALUE);
return {
color: 'rgb(' +
(MAX_VALUE - normalizedScore) + ', ' +
normalizedScore + ', ' +
0 +
')'
};
res.cookie('wstest', 'OK', cookieOptions);
res.end('Cookie has been set!\n');
}
var styles = StyleSheet.create({
noScore: {
color: '#999999',
},
});
http.createServer(app).listen(5556);
module.exports = getStyleFromScore;
+22
View File
@@ -0,0 +1,22 @@
/**
* 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';
function getTextFromScore(score: number): string {
return score > 0 ? score + '%' : 'N/A';
}
module.exports = getTextFromScore;
@@ -0,0 +1,465 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1341803E1AA91802003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341803D1AA917ED003F314A /* libRCTImage.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 */; };
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 */
/* Begin PBXContainerItemProxy section */
1341803C1AA917ED003F314A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 134180381AA917ED003F314A /* RCTImage.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
remoteInfo = RCTImage;
};
144C5F671AC3E5D800B004E7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 144C5F631AC3E5D800B004E7 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
58C5724C1AA6224400CDF9C8 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */;
proxyType = 2;
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 */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTSettings;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
134180381AA917ED003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* TicTacToe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TicTacToe.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = TicTacToe/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = TicTacToe/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 = TicTacToe/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = TicTacToe/Info.plist; sourceTree = "<group>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
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 */,
832044981B492C2500E297FC /* libRCTSettings.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
134180391AA917ED003F314A /* Products */ = {
isa = PBXGroup;
children = (
1341803D1AA917ED003F314A /* libRCTImage.a */,
);
name = Products;
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* TicTacToe */ = {
isa = PBXGroup;
children = (
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
);
name = TicTacToe;
sourceTree = "<group>";
};
144C5F641AC3E5D800B004E7 /* Products */ = {
isa = PBXGroup;
children = (
144C5F681AC3E5D800B004E7 /* libReact.a */,
);
name = Products;
sourceTree = "<group>";
};
58C572071AA6126D00CDF9C8 /* Libraries */ = {
isa = PBXGroup;
children = (
5FF894281B8556F8007731BE /* RCTWebSocket.xcodeproj */,
144C5F631AC3E5D800B004E7 /* React.xcodeproj */,
134180381AA917ED003F314A /* RCTImage.xcodeproj */,
8320448F1B492C1E00E297FC /* RCTSettings.xcodeproj */,
587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
};
58C572481AA6224300CDF9C8 /* Products */ = {
isa = PBXGroup;
children = (
58C5724D1AA6224400CDF9C8 /* libRCTText.a */,
);
name = Products;
sourceTree = "<group>";
};
5FF894291B8556F8007731BE /* Products */ = {
isa = PBXGroup;
children = (
5FF8942D1B8556F8007731BE /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
832044901B492C1E00E297FC /* Products */ = {
isa = PBXGroup;
children = (
832044951B492C1E00E297FC /* libRCTSettings.a */,
);
name = Products;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
13B07FAE1A68108700A75B9A /* TicTacToe */,
58C572071AA6126D00CDF9C8 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* TicTacToe.app */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
13B07F861A680F5B00A75B9A /* TicTacToe */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "TicTacToe" */;
buildPhases = (
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = TicTacToe;
productName = "Hello World";
productReference = 13B07F961A680F5B00A75B9A /* TicTacToe.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = Facebook;
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 134180391AA917ED003F314A /* Products */;
ProjectRef = 134180381AA917ED003F314A /* RCTImage.xcodeproj */;
},
{
ProductGroup = 832044901B492C1E00E297FC /* Products */;
ProjectRef = 8320448F1B492C1E00E297FC /* RCTSettings.xcodeproj */;
},
{
ProductGroup = 58C572481AA6224300CDF9C8 /* Products */;
ProjectRef = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */;
},
{
ProductGroup = 5FF894291B8556F8007731BE /* Products */;
ProjectRef = 5FF894281B8556F8007731BE /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 144C5F641AC3E5D800B004E7 /* Products */;
ProjectRef = 144C5F631AC3E5D800B004E7 /* React.xcodeproj */;
},
);
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* TicTacToe */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
1341803D1AA917ED003F314A /* libRCTImage.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTImage.a;
remoteRef = 1341803C1AA917ED003F314A /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
144C5F681AC3E5D800B004E7 /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libReact.a;
remoteRef = 144C5F671AC3E5D800B004E7 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
58C5724D1AA6224400CDF9C8 /* libRCTText.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTText.a;
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;
path = libRCTSettings.a;
remoteRef = 832044941B492C1E00E297FC /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
13B07F8E1A680F5B00A75B9A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
13B07F871A680F5B00A75B9A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
path = TicTacToe;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/TicTacToe/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = TicTacToe;
};
name = Debug;
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
INFOPLIST_FILE = "$(SRCROOT)/TicTacToe/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = TicTacToe;
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
83CBBA211A601CBA00E9B192 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../React/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "TicTacToe" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */,
13B07F951A680F5B00A75B9A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */ = {
isa = XCConfigurationList;
buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */,
83CBBA211A601CBA00E9B192 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "TicTacToe.app"
BlueprintName = "TicTacToe"
ReferencedContainer = "container:TicTacToe.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "TicTacToe.app"
BlueprintName = "TicTacToe"
ReferencedContainer = "container:TicTacToe.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "TicTacToe.app"
BlueprintName = "TicTacToe"
ReferencedContainer = "container:TicTacToe.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "TicTacToe.app"
BlueprintName = "TicTacToe"
ReferencedContainer = "container:TicTacToe.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,21 @@
/**
* 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>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
@@ -0,0 +1,66 @@
/**
* 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 "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/TicTacToe/TicTacToeApp.bundle?platform=ios&dev=true"];
/**
* 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/TicTacToe/TicTacToeApp.bundle?platform=ios' -o main.jsbundle
*
* then add the `main.jsbundle` file to your project and uncomment this line:
*/
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"TicTacToeApp"
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
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TicTacToe" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
@@ -0,0 +1,38 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -13,16 +13,34 @@
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Facebook. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSAppTransportSecurity</key>
<dict>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
+22
View File
@@ -0,0 +1,22 @@
/**
* 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 "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
+321
View File
@@ -0,0 +1,321 @@
/**
* 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 TicTacToeApp
* @flow
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
TouchableHighlight,
View,
} = React;
class Board {
grid: Array<Array<number>>;
turn: number;
constructor() {
var size = 3;
var grid = Array(size);
for (var i = 0; i < size; i++) {
var row = Array(size);
for (var j = 0; j < size; j++) {
row[j] = 0;
}
grid[i] = row;
}
this.grid = grid;
this.turn = 1;
}
mark(row: number, col: number, player: number): Board {
this.grid[row][col] = player;
return this;
}
hasMark(row: number, col: number): boolean {
return this.grid[row][col] !== 0;
}
winner(): ?number {
for (var i = 0; i < 3; i++) {
if (this.grid[i][0] !== 0 && this.grid[i][0] === this.grid[i][1] &&
this.grid[i][0] === this.grid[i][2]) {
return this.grid[i][0];
}
}
for (var i = 0; i < 3; i++) {
if (this.grid[0][i] !== 0 && this.grid[0][i] === this.grid[1][i] &&
this.grid[0][i] === this.grid[2][i]) {
return this.grid[0][i];
}
}
if (this.grid[0][0] !== 0 && this.grid[0][0] === this.grid[1][1] &&
this.grid[0][0] === this.grid[2][2]) {
return this.grid[0][0];
}
if (this.grid[0][2] !== 0 && this.grid[0][2] === this.grid[1][1] &&
this.grid[0][2] === this.grid[2][0]) {
return this.grid[0][2];
}
return null;
}
tie(): boolean {
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (this.grid[i][j] === 0) {
return false;
}
}
}
return this.winner() === null;
}
}
var Cell = React.createClass({
cellStyle() {
switch (this.props.player) {
case 1:
return styles.cellX;
case 2:
return styles.cellO;
default:
return null;
}
},
textStyle() {
switch (this.props.player) {
case 1:
return styles.cellTextX;
case 2:
return styles.cellTextO;
default:
return {};
}
},
textContents() {
switch (this.props.player) {
case 1:
return 'X';
case 2:
return 'O';
default:
return '';
}
},
render() {
return (
<TouchableHighlight
onPress={this.props.onPress}
underlayColor="transparent"
activeOpacity={0.5}>
<View style={[styles.cell, this.cellStyle()]}>
<Text style={[styles.cellText, this.textStyle()]}>
{this.textContents()}
</Text>
</View>
</TouchableHighlight>
);
}
});
var GameEndOverlay = React.createClass({
render() {
var board = this.props.board;
var tie = board.tie();
var winner = board.winner();
if (!winner && !tie) {
return <View />;
}
var message;
if (tie) {
message = 'It\'s a tie!';
} else {
message = (winner === 1 ? 'X' : 'O') + ' wins!';
}
return (
<View style={styles.overlay}>
<Text style={styles.overlayMessage}>{message}</Text>
<TouchableHighlight
onPress={this.props.onRestart}
underlayColor="transparent"
activeOpacity={0.5}>
<View style={styles.newGame}>
<Text style={styles.newGameText}>New Game</Text>
</View>
</TouchableHighlight>
</View>
);
}
});
var TicTacToeApp = React.createClass({
getInitialState() {
return { board: new Board(), player: 1 };
},
restartGame() {
this.setState(this.getInitialState());
},
nextPlayer(): number {
return this.state.player === 1 ? 2 : 1;
},
handleCellPress(row: number, col: number) {
if (this.state.board.hasMark(row, col)) {
return;
}
this.setState({
board: this.state.board.mark(row, col, this.state.player),
player: this.nextPlayer(),
});
},
render() {
var rows = this.state.board.grid.map((cells, row) =>
<View key={'row' + row} style={styles.row}>
{cells.map((player, col) =>
<Cell
key={'cell' + col}
player={player}
onPress={this.handleCellPress.bind(this, row, col)}
/>
)}
</View>
);
return (
<View style={styles.container}>
<Text style={styles.title}>EXTREME T3</Text>
<View style={styles.board}>
{rows}
</View>
<GameEndOverlay
board={this.state.board}
onRestart={this.restartGame}
/>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
title: {
fontFamily: 'Chalkduster',
fontSize: 39,
marginBottom: 20,
},
board: {
padding: 5,
backgroundColor: '#47525d',
borderRadius: 10,
},
row: {
flexDirection: 'row',
},
// CELL
cell: {
width: 80,
height: 80,
borderRadius: 5,
backgroundColor: '#7b8994',
margin: 5,
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
cellX: {
backgroundColor: '#72d0eb',
},
cellO: {
backgroundColor: '#7ebd26',
},
// CELL TEXT
cellText: {
borderRadius: 5,
fontSize: 50,
fontFamily: 'AvenirNext-Bold',
},
cellTextX: {
color: '#19a9e5',
},
cellTextO: {
color: '#b9dc2f',
},
// GAME OVER
overlay: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(221, 221, 221, 0.5)',
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
overlayMessage: {
fontSize: 40,
marginBottom: 20,
marginLeft: 20,
marginRight: 20,
fontFamily: 'AvenirNext-DemiBold',
textAlign: 'center',
},
newGame: {
backgroundColor: '#887765',
padding: 20,
borderRadius: 5,
},
newGameText: {
color: 'white',
fontSize: 20,
fontFamily: 'AvenirNext-DemiBold',
},
});
AppRegistry.registerComponent('TicTacToeApp', () => TicTacToeApp);
module.exports = TicTacToeApp;
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -18,81 +11,57 @@
* 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 AccessibilityAndroidExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
AccessibilityInfo,
StyleSheet,
Text,
View,
ToastAndroid,
TouchableWithoutFeedback,
} = ReactNative;
} = React;
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
var importantForAccessibilityValues = ['auto', 'yes', 'no', 'no-hide-descendants'];
class AccessibilityAndroidExample extends React.Component {
static title = 'Accessibility';
static description = 'Examples of using Accessibility API.';
var AccessibilityAndroidExample = React.createClass({
state = {
count: 0,
backgroundImportantForAcc: 0,
forgroundImportantForAcc: 0,
screenReaderEnabled: false,
};
statics: {
title: 'Accessibility',
description: 'Examples of using Accessibility API.',
},
componentDidMount() {
AccessibilityInfo.addEventListener(
'change',
this._handleScreenReaderToggled
);
AccessibilityInfo.fetch().done((isEnabled) => {
this.setState({
screenReaderEnabled: isEnabled
});
});
}
getInitialState: function() {
return {
count: 0,
backgroundImportantForAcc: 0,
forgroundImportantForAcc: 0,
};
},
componentWillUnmount() {
AccessibilityInfo.removeEventListener(
'change',
this._handleScreenReaderToggled
);
}
_handleScreenReaderToggled = (isEnabled) => {
this.setState({
screenReaderEnabled: isEnabled,
});
}
_addOne = () => {
_addOne: function() {
this.setState({
count: ++this.state.count,
});
};
},
_changeBackgroundImportantForAcc = () => {
_changeBackgroundImportantForAcc: function() {
this.setState({
backgroundImportantForAcc: (this.state.backgroundImportantForAcc + 1) % 4,
});
};
},
_changeForgroundImportantForAcc = () => {
_changeForgroundImportantForAcc: function() {
this.setState({
forgroundImportantForAcc: (this.state.forgroundImportantForAcc + 1) % 4,
});
};
},
render() {
render: function() {
return (
<UIExplorerPage title={'Accessibility'}>
@@ -152,12 +121,6 @@ class AccessibilityAndroidExample extends React.Component {
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Check if the screen reader is enabled">
<Text>
The screen reader is {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}.
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Overlapping views and importantForAccessibility property">
<View style={styles.container}>
<View
@@ -231,8 +194,8 @@ class AccessibilityAndroidExample extends React.Component {
</UIExplorerPage>
);
}
}
},
});
var styles = StyleSheet.create({
embedded: {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,19 +12,16 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule AccessibilityIOSExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
AccessibilityInfo,
Text,
View,
} = ReactNative;
} = React;
class AccessibilityIOSExample extends React.Component {
var AccessibilityIOSExample = React.createClass({
render() {
return (
<View>
@@ -62,59 +52,14 @@ class AccessibilityIOSExample extends React.Component {
</View>
</View>
);
}
}
class ScreenReaderStatusExample extends React.Component {
state = {
screenReaderEnabled: false,
}
componentDidMount() {
AccessibilityInfo.addEventListener(
'change',
this._handleScreenReaderToggled
);
AccessibilityInfo.fetch().done((isEnabled) => {
this.setState({
screenReaderEnabled: isEnabled
});
});
}
componentWillUnmount() {
AccessibilityInfo.removeEventListener(
'change',
this._handleScreenReaderToggled
);
}
_handleScreenReaderToggled = (isEnabled) => {
this.setState({
screenReaderEnabled: isEnabled,
});
}
render() {
return (
<View>
<Text>
The screen reader is {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}.
</Text>
</View>
);
}
}
},
});
exports.title = 'AccessibilityIOS';
exports.description = 'Interface to show iOS\' accessibility samples';
exports.examples = [
{
title: 'Accessibility elements',
render(): React.Element<any> { return <AccessibilityIOSExample />; }
},
{
title: 'Check if the screen reader is enabled',
render(): React.Element<any> { return <ScreenReaderStatusExample />; }
render(): ReactElement { return <AccessibilityIOSExample />; }
},
];
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,19 +12,17 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule ActionSheetIOSExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
ActionSheetIOS,
StyleSheet,
takeSnapshot,
Text,
UIManager,
View,
} = ReactNative;
} = React;
var BUTTONS = [
'Option 0',
@@ -43,10 +34,12 @@ var BUTTONS = [
var DESTRUCTIVE_INDEX = 3;
var CANCEL_INDEX = 4;
class ActionSheetExample extends React.Component {
state = {
clicked: 'none',
};
var ActionSheetExample = React.createClass({
getInitialState() {
return {
clicked: 'none',
};
},
render() {
return (
@@ -59,9 +52,9 @@ class ActionSheetExample extends React.Component {
</Text>
</View>
);
}
},
showActionSheet = () => {
showActionSheet() {
ActionSheetIOS.showActionSheetWithOptions({
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
@@ -70,13 +63,15 @@ class ActionSheetExample extends React.Component {
(buttonIndex) => {
this.setState({ clicked: BUTTONS[buttonIndex] });
});
};
}
}
});
class ActionSheetTintExample extends React.Component {
state = {
clicked: 'none',
};
var ActionSheetTintExample = React.createClass({
getInitialState() {
return {
clicked: 'none',
};
},
render() {
return (
@@ -89,9 +84,9 @@ class ActionSheetTintExample extends React.Component {
</Text>
</View>
);
}
},
showActionSheet = () => {
showActionSheet() {
ActionSheetIOS.showActionSheetWithOptions({
options: BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
@@ -101,13 +96,15 @@ class ActionSheetTintExample extends React.Component {
(buttonIndex) => {
this.setState({ clicked: BUTTONS[buttonIndex] });
});
};
}
}
});
class ShareActionSheetExample extends React.Component {
state = {
text: ''
};
var ShareActionSheetExample = React.createClass({
getInitialState() {
return {
text: ''
};
},
render() {
return (
@@ -120,9 +117,9 @@ class ShareActionSheetExample extends React.Component {
</Text>
</View>
);
}
},
showShareActionSheet = () => {
showShareActionSheet() {
ActionSheetIOS.showShareActionSheetWithOptions({
url: this.props.url,
message: 'message to go with the shared url',
@@ -132,22 +129,24 @@ class ShareActionSheetExample extends React.Component {
]
},
(error) => alert(error),
(completed, method) => {
(success, method) => {
var text;
if (completed) {
if (success) {
text = `Shared via ${method}`;
} else {
text = 'You didn\'t share';
}
this.setState({text});
});
};
}
}
});
class ShareScreenshotExample extends React.Component {
state = {
text: ''
};
var ShareScreenshotExample = React.createClass({
getInitialState() {
return {
text: ''
};
},
render() {
return (
@@ -160,11 +159,11 @@ class ShareScreenshotExample extends React.Component {
</Text>
</View>
);
}
},
showShareActionSheet = () => {
showShareActionSheet() {
// Take the snapshot (returns a temp file uri)
takeSnapshot('window').then((uri) => {
UIManager.takeSnapshot('window').then((uri) => {
// Share image data
ActionSheetIOS.showShareActionSheetWithOptions({
url: uri,
@@ -173,9 +172,9 @@ class ShareScreenshotExample extends React.Component {
]
},
(error) => alert(error),
(completed, method) => {
(success, method) => {
var text;
if (completed) {
if (success) {
text = `Shared via ${method}`;
} else {
text = 'You didn\'t share';
@@ -183,8 +182,8 @@ class ShareScreenshotExample extends React.Component {
this.setState({text});
});
}).catch((error) => alert(error));
};
}
}
});
var style = StyleSheet.create({
button: {
@@ -198,27 +197,27 @@ exports.description = 'Interface to show iOS\' action sheets';
exports.examples = [
{
title: 'Show Action Sheet',
render(): React.Element<any> { return <ActionSheetExample />; }
render(): ReactElement { return <ActionSheetExample />; }
},
{
title: 'Show Action Sheet with tinted buttons',
render(): React.Element<any> { return <ActionSheetTintExample />; }
render(): ReactElement { return <ActionSheetTintExample />; }
},
{
title: 'Show Share Action Sheet',
render(): React.Element<any> {
render(): ReactElement {
return <ShareActionSheetExample url="https://code.facebook.com" />;
}
},
{
title: 'Share Local Image',
render(): React.Element<any> {
render(): ReactElement {
return <ShareActionSheetExample url="bunny.png" />;
}
},
{
title: 'Share Screenshot',
render(): React.Element<any> {
render(): ReactElement {
return <ShareScreenshotExample />;
}
}
@@ -0,0 +1,162 @@
/**
* 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 {
ActivityIndicatorIOS,
StyleSheet,
View,
} = React;
var TimerMixin = require('react-timer-mixin');
var ToggleAnimatingActivityIndicator = React.createClass({
mixins: [TimerMixin],
getInitialState: function() {
return {
animating: true,
};
},
setToggleTimeout: function() {
this.setTimeout(
() => {
this.setState({animating: !this.state.animating});
this.setToggleTimeout();
},
1200
);
},
componentDidMount: function() {
this.setToggleTimeout();
},
render: function() {
return (
<ActivityIndicatorIOS
animating={this.state.animating}
style={[styles.centering, {height: 80}]}
size="large"
/>
);
}
});
exports.displayName = (undefined: ?string);
exports.framework = 'React';
exports.title = '<ActivityIndicatorIOS>';
exports.description = 'Animated loading indicators.';
exports.examples = [
{
title: 'Default (small, white)',
render: function() {
return (
<ActivityIndicatorIOS
style={[styles.centering, styles.gray, {height: 40}]}
color="white"
/>
);
}
},
{
title: 'Gray',
render: function() {
return (
<View>
<ActivityIndicatorIOS
style={[styles.centering, {height: 40}]}
/>
<ActivityIndicatorIOS
style={[styles.centering, {backgroundColor: '#eeeeee', height: 40}]}
/>
</View>
);
}
},
{
title: 'Custom colors',
render: function() {
return (
<View style={styles.horizontal}>
<ActivityIndicatorIOS color="#0000ff" />
<ActivityIndicatorIOS color="#aa00aa" />
<ActivityIndicatorIOS color="#aa3300" />
<ActivityIndicatorIOS color="#00aa00" />
</View>
);
}
},
{
title: 'Large',
render: function() {
return (
<ActivityIndicatorIOS
style={[styles.centering, styles.gray, {height: 80}]}
color="white"
size="large"
/>
);
}
},
{
title: 'Large, custom colors',
render: function() {
return (
<View style={styles.horizontal}>
<ActivityIndicatorIOS
size="large"
color="#0000ff"
/>
<ActivityIndicatorIOS
size="large"
color="#aa00aa"
/>
<ActivityIndicatorIOS
size="large"
color="#aa3300"
/>
<ActivityIndicatorIOS
size="large"
color="#00aa00"
/>
</View>
);
}
},
{
title: 'Start/stop',
render: function(): ReactElement {
return <ToggleAnimatingActivityIndicator />;
}
},
];
var styles = StyleSheet.create({
centering: {
alignItems: 'center',
justifyContent: 'center',
},
gray: {
backgroundColor: '#cccccc',
},
horizontal: {
flexDirection: 'row',
justifyContent: 'space-around',
},
});
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,18 +12,16 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule AdSupportIOSExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
AdSupportIOS,
StyleSheet,
Text,
View,
} = ReactNative;
} = React;
exports.framework = 'React';
exports.title = 'Advertising ID';
@@ -39,19 +30,21 @@ exports.description = 'Example of using the ad support API.';
exports.examples = [
{
title: 'Ad Support IOS',
render: function(): React.Element<any> {
render: function(): ReactElement {
return <AdSupportIOSExample />;
},
}
];
class AdSupportIOSExample extends React.Component {
state = {
deviceID: 'No IDFA yet',
hasAdvertiserTracking: 'unset',
};
var AdSupportIOSExample = React.createClass({
getInitialState: function() {
return {
deviceID: 'No IDFA yet',
hasAdvertiserTracking: 'unset',
};
},
componentDidMount() {
componentDidMount: function() {
AdSupportIOS.getAdvertisingId(
this._onDeviceIDSuccess,
this._onDeviceIDFailure
@@ -61,33 +54,33 @@ class AdSupportIOSExample extends React.Component {
this._onHasTrackingSuccess,
this._onHasTrackingFailure
);
}
},
_onHasTrackingSuccess = (hasTracking) => {
_onHasTrackingSuccess: function(hasTracking) {
this.setState({
'hasAdvertiserTracking': hasTracking,
});
};
},
_onHasTrackingFailure = (e) => {
_onHasTrackingFailure: function(e) {
this.setState({
'hasAdvertiserTracking': 'Error!',
});
};
},
_onDeviceIDSuccess = (deviceID) => {
_onDeviceIDSuccess: function(deviceID) {
this.setState({
'deviceID': deviceID,
});
};
},
_onDeviceIDFailure = (e) => {
_onDeviceIDFailure: function(e) {
this.setState({
'deviceID': 'Error!',
});
};
},
render() {
render: function() {
return (
<View>
<Text>
@@ -101,7 +94,7 @@ class AdSupportIOSExample extends React.Component {
</View>
);
}
}
});
var styles = StyleSheet.create({
title: {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -18,20 +11,18 @@
* 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 AlertExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Alert,
StyleSheet,
Text,
TouchableHighlight,
View,
} = ReactNative;
} = React;
var UIExplorerBlock = require('./UIExplorerBlock');
@@ -42,8 +33,9 @@ var alertMessage = 'Credibly reintermediate next-generation potentialities after
/**
* Simple alert examples.
*/
class SimpleAlertExampleBlock extends React.Component {
render() {
var SimpleAlertExampleBlock = React.createClass({
render: function() {
return (
<View>
<TouchableHighlight style={styles.wrapper}
@@ -107,40 +99,25 @@ class SimpleAlertExampleBlock extends React.Component {
<Text>Alert with too many buttons</Text>
</View>
</TouchableHighlight>
<TouchableHighlight style={styles.wrapper}
onPress={() => Alert.alert(
'Alert Title',
null,
[
{text: 'OK', onPress: () => console.log('OK Pressed!')},
],
{
cancelable: false
}
)}>
<View style={styles.button}>
<Text>Alert that cannot be dismissed</Text>
</View>
</TouchableHighlight>
</View>
);
}
}
},
});
class AlertExample extends React.Component {
static title = 'Alert';
static description = 'Alerts display a concise and informative message ' +
'and prompt the user to make a decision.';
render() {
var AlertExample = React.createClass({
statics: {
title: 'Alert',
description: 'Alerts display a concise and informative message ' +
'and prompt the user to make a decision.',
},
render: function() {
return (
<UIExplorerBlock title={'Alert'}>
<SimpleAlertExampleBlock />
</UIExplorerBlock>
);
}
}
});
var styles = StyleSheet.create({
wrapper: {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,19 +12,17 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule AlertIOSExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
StyleSheet,
View,
Text,
TouchableHighlight,
AlertIOS,
} = ReactNative;
} = React;
var { SimpleAlertExampleBlock } = require('./AlertExample');
@@ -46,7 +37,7 @@ exports.examples = [{
},
{
title: 'Prompt Options',
render(): React.Element<any> {
render(): ReactElement {
return <PromptOptions />;
}
},
@@ -145,17 +136,6 @@ class PromptOptions extends React.Component {
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={() => AlertIOS.prompt('Type a phone number', null, null, 'plain-text', undefined, 'phone-pad')}>
<View style={styles.button}>
<Text>
prompt with title & custom keyboard
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={() => AlertIOS.prompt('Type a value', null, this.saveResponse, undefined, 'Default value')}>
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,19 +12,17 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule AnimatedExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
Easing,
StyleSheet,
Text,
View,
} = ReactNative;
} = React;
var UIExplorerButton = require('./UIExplorerButton');
exports.framework = 'React';
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,15 +16,14 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
LayoutAnimation,
PanResponder,
StyleSheet,
View,
} = ReactNative;
} = React;
var AnExSet = require('AnExSet');
@@ -83,14 +75,13 @@ class Circle extends React.Component {
y: gestureState.dy + this.props.restLayout.y,
});
this.props.onDeactivate();
this.state.pan.removeAllListeners();
},
})}, () => {
this.props.onActivate();
});
}
render(): React.Element<any> {
render(): ReactElement {
if (this.state.panResponder) {
var handlers = this.state.panResponder.panHandlers;
var dragStyle = { // Used to position while dragging
@@ -191,7 +182,7 @@ class AnExApp extends React.Component {
this._onMove = this._onMove.bind(this);
}
render(): React.Element<any> {
render(): ReactElement {
var circles = this.state.keys.map((key, idx) => {
if (key === this.state.activeKey) {
return <Circle key={key + 'd'} dummy={true} />;
@@ -289,6 +280,7 @@ function moveToClosest({activeKey, keys, restLayouts}, position) {
var styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 64, // push content below nav bar
},
grid: {
flex: 1,
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,14 +16,14 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
Image,
PanResponder,
StyleSheet,
View,
} = ReactNative;
} = React;
var NUM_BOBBLES = 5;
var RAD_EACH = Math.PI / 2 / (NUM_BOBBLES - 2);
@@ -95,7 +88,7 @@ class AnExBobble extends React.Component {
});
}
render(): React.Element<any> {
render(): ReactElement {
return (
<View style={styles.bobbleContainer}>
{this.state.bobbles.map((_, i) => {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,14 +16,14 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
Image,
PanResponder,
StyleSheet,
View,
} = ReactNative;
} = React;
class AnExChained extends React.Component {
state: any;
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,8 +16,7 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
Image,
@@ -32,7 +24,7 @@ var {
StyleSheet,
Text,
View,
} = ReactNative;
} = React;
class AnExScroll extends React.Component {
state: any = { scrollX: new Animated.Value(0) };
@@ -69,27 +61,18 @@ class AnExScroll extends React.Component {
<Animated.Image
pointerEvents="none"
style={[styles.bunny, {transform: [
{
translateX: this.state.scrollX.interpolate({
inputRange: [0, width, 2 * width],
outputRange: [0, 0, width / 3],
extrapolate: 'clamp',
}),
},
{
translateY: this.state.scrollX.interpolate({
inputRange: [0, width, 2 * width],
outputRange: [0, -200, -260],
extrapolate: 'clamp',
}),
},
{
scale: this.state.scrollX.interpolate({
inputRange: [0, width, 2 * width],
outputRange: [0.5, 0.5, 2],
extrapolate: 'clamp',
}),
},
{translateX: this.state.scrollX.interpolate({
inputRange: [0, width, 2 * width],
outputRange: [0, 0, width / 3]}), // multi-part ranges
extrapolate: 'clamp'}, // default is 'extend'
{translateY: this.state.scrollX.interpolate({
inputRange: [0, width, 2 * width],
outputRange: [0, -200, -260]}),
extrapolate: 'clamp'},
{scale: this.state.scrollX.interpolate({
inputRange: [0, width, 2 * width],
outputRange: [0.5, 0.5, 2]}),
extrapolate: 'clamp'},
]}]}
source={BUNNY_PIC}
/>
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,15 +16,14 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
PanResponder,
StyleSheet,
Text,
View,
} = ReactNative;
} = React;
var AnExBobble = require('./AnExBobble');
var AnExChained = require('./AnExChained');
@@ -52,7 +44,7 @@ class AnExSet extends React.Component {
openColor: randColor(),
};
}
render(): React.Element<any> {
render(): ReactElement {
var backgroundColor = this.props.openVal ?
this.props.openVal.interpolate({
inputRange: [0, 1],
@@ -98,13 +90,11 @@ class AnExSet extends React.Component {
toValue: this.state.dismissY.interpolate({ // Track dismiss gesture
inputRange: [0, 300], // and interpolate pixel distance
outputRange: [1, 0], // to a fraction.
}),
useNativeDriver: true,
})
}).start();
},
onPanResponderMove: Animated.event(
[null, {dy: this.state.dismissY}], // track pan gesture
{useNativeDriver: true}
[null, {dy: this.state.dismissY}] // track pan gesture
),
onPanResponderRelease: (e, gestureState) => {
if (gestureState.dy > 100) {
@@ -112,7 +102,6 @@ class AnExSet extends React.Component {
} else {
Animated.spring(this.props.openVal, {
toValue: 1, // animate back open if released early
useNativeDriver: true,
}).start();
}
},
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,13 +16,14 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Animated,
Image,
PanResponder,
StyleSheet,
} = ReactNative;
View,
} = React;
class AnExTilt extends React.Component {
state: any;
@@ -95,7 +89,7 @@ class AnExTilt extends React.Component {
this._startBurnsZoom();
}
render(): React.Element<any> {
render(): ReactElement {
return (
<Animated.View
{...this.state.tiltPanResponder.panHandlers}
@@ -123,7 +117,7 @@ class AnExTilt extends React.Component {
},
],
}}
source={require('./trees.jpg')}
source={NATURE_IMAGE}
/>
</Animated.View>
);
@@ -142,4 +136,6 @@ var styles = StyleSheet.create({
},
});
var NATURE_IMAGE = {uri: 'http://www.deshow.net/d/file/travel/2009-04/scenic-beauty-of-nature-photography-2-504-4.jpg'};
module.exports = AnExTilt;
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,52 +16,35 @@
*/
'use strict';
const React = require('react');
const ReactNative = require('react-native');
const {
var React = require('react-native');
var {
AppState,
Text,
View
} = ReactNative;
} = React;
class AppStateSubscription extends React.Component {
state = {
appState: AppState.currentState,
previousAppStates: [],
memoryWarnings: 0,
};
componentDidMount() {
var AppStateSubscription = React.createClass({
getInitialState() {
return {
appState: AppState.currentState,
previousAppStates: [],
};
},
componentDidMount: function() {
AppState.addEventListener('change', this._handleAppStateChange);
AppState.addEventListener('memoryWarning', this._handleMemoryWarning);
}
componentWillUnmount() {
},
componentWillUnmount: function() {
AppState.removeEventListener('change', this._handleAppStateChange);
AppState.removeEventListener('memoryWarning', this._handleMemoryWarning);
}
_handleMemoryWarning = () => {
this.setState({memoryWarnings: this.state.memoryWarnings + 1});
};
_handleAppStateChange = (appState) => {
},
_handleAppStateChange: function(appState) {
var previousAppStates = this.state.previousAppStates.slice();
previousAppStates.push(this.state.appState);
this.setState({
appState,
previousAppStates,
});
};
},
render() {
if (this.props.showMemoryWarnings) {
return (
<View>
<Text>{this.state.memoryWarnings}</Text>
</View>
);
}
if (this.props.showCurrentOnly) {
return (
<View>
@@ -82,7 +58,7 @@ class AppStateSubscription extends React.Component {
</View>
);
}
}
});
exports.title = 'AppState';
exports.description = 'app background status';
@@ -95,16 +71,10 @@ exports.examples = [
{
title: 'Subscribed AppState:',
description: 'This changes according to the current state, so you can only ever see it rendered as "active"',
render(): React.Element<any> { return <AppStateSubscription showCurrentOnly={true} />; }
render(): ReactElement { return <AppStateSubscription showCurrentOnly={true} />; }
},
{
title: 'Previous states:',
render(): React.Element<any> { return <AppStateSubscription showCurrentOnly={false} />; }
},
{
platform: 'ios',
title: 'Memory Warnings',
description: 'In the IOS simulator, hit Shift+Command+M to simulate a memory warning.',
render(): React.Element<any> { return <AppStateSubscription showMemoryWarnings={true} />; }
render(): ReactElement { return <AppStateSubscription showCurrentOnly={false} />; }
},
];
+98
View File
@@ -0,0 +1,98 @@
/**
* 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 AppStateIOSExample
* @flow
*/
'use strict';
var React = require('react-native');
var {
AppStateIOS,
Text,
View
} = React;
var AppStateSubscription = React.createClass({
getInitialState() {
return {
appState: AppStateIOS.currentState,
previousAppStates: [],
memoryWarnings: 0,
};
},
componentDidMount: function() {
AppStateIOS.addEventListener('change', this._handleAppStateChange);
AppStateIOS.addEventListener('memoryWarning', this._handleMemoryWarning);
},
componentWillUnmount: function() {
AppStateIOS.removeEventListener('change', this._handleAppStateChange);
AppStateIOS.removeEventListener('memoryWarning', this._handleMemoryWarning);
},
_handleMemoryWarning: function() {
this.setState({memoryWarnings: this.state.memoryWarnings + 1});
},
_handleAppStateChange: function(appState) {
var previousAppStates = this.state.previousAppStates.slice();
previousAppStates.push(this.state.appState);
this.setState({
appState,
previousAppStates,
});
},
render() {
if (this.props.showMemoryWarnings) {
return (
<View>
<Text>{this.state.memoryWarnings}</Text>
</View>
);
}
if (this.props.showCurrentOnly) {
return (
<View>
<Text>{this.state.appState}</Text>
</View>
);
}
return (
<View>
<Text>{JSON.stringify(this.state.previousAppStates)}</Text>
</View>
);
}
});
exports.title = 'AppStateIOS';
exports.description = 'iOS app background status';
exports.examples = [
{
title: 'AppStateIOS.currentState',
description: 'Can be null on app initialization',
render() { return <Text>{AppStateIOS.currentState}</Text>; }
},
{
title: 'Subscribed AppStateIOS:',
description: 'This changes according to the current state, so you can only ever see it rendered as "active"',
render(): ReactElement { return <AppStateSubscription showCurrentOnly={true} />; }
},
{
title: 'Previous states:',
render(): ReactElement { return <AppStateSubscription showCurrentOnly={false} />; }
},
{
title: 'Memory Warnings',
description: 'In the simulator, hit Shift+Command+M to simulate a memory warning.',
render(): ReactElement { return <AppStateSubscription showMemoryWarnings={true} />; }
},
];
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,23 +12,24 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule AssetScaledImageExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Image,
StyleSheet,
View,
ScrollView
} = ReactNative;
} = React;
class AssetScaledImageExample extends React.Component {
state = {
asset: this.props.asset
};
var AssetScaledImageExample = React.createClass({
getInitialState() {
return {
asset: this.props.asset
};
},
render() {
var image = this.state.asset.node.image;
@@ -55,8 +49,8 @@ class AssetScaledImageExample extends React.Component {
</View>
</ScrollView>
);
}
}
},
});
var styles = StyleSheet.create({
row: {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,34 +12,27 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule AsyncStorageExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
AsyncStorage,
PickerIOS,
Text,
View
} = ReactNative;
} = React;
var PickerItemIOS = PickerIOS.Item;
var STORAGE_KEY = '@AsyncStorageExample:key';
var COLORS = ['red', 'orange', 'yellow', 'green', 'blue'];
class BasicStorageExample extends React.Component {
state = {
selectedValue: COLORS[0],
messages: [],
};
var BasicStorageExample = React.createClass({
componentDidMount() {
this._loadInitialState().done();
}
},
_loadInitialState = async () => {
async _loadInitialState() {
try {
var value = await AsyncStorage.getItem(STORAGE_KEY);
if (value !== null){
@@ -58,7 +44,14 @@ class BasicStorageExample extends React.Component {
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
};
},
getInitialState() {
return {
selectedValue: COLORS[0],
messages: [],
};
},
render() {
var color = this.state.selectedValue;
@@ -90,9 +83,9 @@ class BasicStorageExample extends React.Component {
{this.state.messages.map((m) => <Text key={m}>{m}</Text>)}
</View>
);
}
},
_onValueChange = async (selectedValue) => {
async _onValueChange(selectedValue) {
this.setState({selectedValue});
try {
await AsyncStorage.setItem(STORAGE_KEY, selectedValue);
@@ -100,27 +93,27 @@ class BasicStorageExample extends React.Component {
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
};
},
_removeStorage = async () => {
async _removeStorage() {
try {
await AsyncStorage.removeItem(STORAGE_KEY);
this._appendMessage('Selection removed from disk.');
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
};
},
_appendMessage = (message) => {
_appendMessage(message) {
this.setState({messages: this.state.messages.concat(message)});
};
}
},
});
exports.title = 'AsyncStorage';
exports.description = 'Asynchronous local disk storage.';
exports.examples = [
{
title: 'Basics - getItem, setItem, removeItem',
render(): React.Element<any> { return <BasicStorageExample />; }
render(): ReactElement { return <BasicStorageExample />; }
},
];
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -17,16 +10,14 @@
* 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 BorderExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
StyleSheet,
View
} = ReactNative;
} = React;
var styles = StyleSheet.create({
box: {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -17,17 +10,15 @@
* 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 BoxShadowExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Image,
StyleSheet,
View
} = ReactNative;
} = React;
var styles = StyleSheet.create({
box: {
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,60 +12,60 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule CameraRollExample
*/
'use strict';
const React = require('react');
const ReactNative = require('react-native');
const React = require('react-native');
const {
CameraRoll,
Image,
Slider,
SliderIOS,
StyleSheet,
Switch,
Text,
View,
TouchableOpacity
} = ReactNative;
const invariant = require('fbjs/lib/invariant');
} = React;
const CameraRollView = require('./CameraRollView');
const AssetScaledImageExampleView = require('./AssetScaledImageExample');
class CameraRollExample extends React.Component {
state = {
groupTypes: 'SavedPhotos',
sliderValue: 1,
bigImages: true,
};
_cameraRollView: ?CameraRollView;
const CAMERA_ROLL_VIEW = 'camera_roll_view';
const CameraRollExample = React.createClass({
getInitialState() {
return {
groupTypes: 'SavedPhotos',
sliderValue: 1,
bigImages: true,
};
},
render() {
return (
<View>
<Switch
onValueChange={this._onSwitchChange}
value={this.state.bigImages}
/>
value={this.state.bigImages} />
<Text>{(this.state.bigImages ? 'Big' : 'Small') + ' Images'}</Text>
<Slider
<SliderIOS
value={this.state.sliderValue}
onValueChange={this._onSliderChange}
/>
<Text>{'Group Type: ' + this.state.groupTypes}</Text>
<CameraRollView
ref={(ref) => { this._cameraRollView = ref; }}
ref={CAMERA_ROLL_VIEW}
batchSize={20}
groupTypes={this.state.groupTypes}
renderImage={this._renderImage}
/>
</View>
);
}
},
loadAsset = (asset) => {
loadAsset(asset){
if (this.props.navigator) {
this.props.navigator.push({
title: 'Camera Roll Image',
@@ -81,13 +74,13 @@ class CameraRollExample extends React.Component {
passProps: { asset: asset },
});
}
};
},
_renderImage = (asset) => {
_renderImage(asset) {
const imageSize = this.state.bigImages ? 150 : 75;
const imageStyle = [styles.image, {width: imageSize, height: imageSize}];
const {location} = asset.node;
const locationStr = location ? JSON.stringify(location) : 'Unknown location';
const location = asset.node.location.longitude ?
JSON.stringify(asset.node.location) : 'Unknown location';
return (
<TouchableOpacity key={asset} onPress={ this.loadAsset.bind( this, asset ) }>
<View style={styles.row}>
@@ -97,30 +90,29 @@ class CameraRollExample extends React.Component {
/>
<View style={styles.info}>
<Text style={styles.url}>{asset.node.image.uri}</Text>
<Text>{locationStr}</Text>
<Text>{location}</Text>
<Text>{asset.node.group_name}</Text>
<Text>{new Date(asset.node.timestamp).toString()}</Text>
</View>
</View>
</TouchableOpacity>
);
};
},
_onSliderChange = (value) => {
_onSliderChange(value) {
const options = CameraRoll.GroupTypesOptions;
const index = Math.floor(value * options.length * 0.99);
const groupTypes = options[index];
if (groupTypes !== this.state.groupTypes) {
this.setState({groupTypes: groupTypes});
}
};
},
_onSwitchChange = (value) => {
invariant(this._cameraRollView, 'ref should be set');
this._cameraRollView.rendererChanged();
_onSwitchChange(value) {
this.refs[CAMERA_ROLL_VIEW].rendererChanged();
this.setState({ bigImages: value });
};
}
}
});
const styles = StyleSheet.create({
row: {
@@ -144,6 +136,6 @@ exports.description = 'Example component that uses CameraRoll to list user\'s ph
exports.examples = [
{
title: 'Photos',
render(): React.Element<any> { return <CameraRollExample />; }
render(): ReactElement { return <CameraRollExample />; }
}
];
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -23,19 +16,16 @@
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
ActivityIndicator,
Alert,
ActivityIndicatorIOS,
CameraRoll,
Image,
ListView,
PermissionsAndroid,
Platform,
StyleSheet,
View,
} = ReactNative;
} = React;
var groupByEveryN = require('groupByEveryN');
var logError = require('logError');
@@ -83,7 +73,6 @@ var propTypes = {
};
var CameraRollView = React.createClass({
// $FlowFixMe(>=0.41.0)
propTypes: propTypes,
getDefaultProps: function(): Object {
@@ -126,7 +115,6 @@ var CameraRollView = React.createClass({
rendererChanged: function() {
var ds = new ListView.DataSource({rowHasChanged: this._rowHasChanged});
this.state.dataSource = ds.cloneWithRows(
// $FlowFixMe(>=0.41.0)
groupByEveryN(this.state.assets, this.props.imagesPerRow)
);
},
@@ -141,32 +129,18 @@ var CameraRollView = React.createClass({
}
},
_fetch: async function(clear?: boolean) {
_fetch: function(clear?: boolean) {
if (clear) {
this.setState(this.getInitialState(), this.fetch);
return;
}
if (Platform.OS === 'android') {
const result = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: 'Permission Explanation',
message: 'UIExplorer would like to access your pictures.',
},
);
if (result !== 'granted') {
Alert.alert('Access to pictures was denied.');
return;
}
}
const fetchParams: Object = {
var fetchParams: Object = {
first: this.props.batchSize,
groupTypes: this.props.groupTypes,
assetType: this.props.assetType,
};
if (Platform.OS === 'android') {
if (Platform.OS === "android") {
// not supported in android
delete fetchParams.groupTypes;
}
@@ -174,12 +148,7 @@ var CameraRollView = React.createClass({
fetchParams.after = this.state.lastCursor;
}
try {
const data = await CameraRoll.getPhotos(fetchParams);
this._appendAssets(data);
} catch (e) {
logError(e);
}
CameraRoll.getPhotos(fetchParams, this._appendAssets, logError);
},
/**
@@ -200,7 +169,6 @@ var CameraRollView = React.createClass({
onEndReached={this._onEndReached}
style={styles.container}
dataSource={this.state.dataSource}
enableEmptySections
/>
);
},
@@ -221,7 +189,7 @@ var CameraRollView = React.createClass({
_renderFooterSpinner: function() {
if (!this.state.noMore) {
return <ActivityIndicator />;
return <ActivityIndicatorIOS style={styles.spinner} />;
}
return null;
},
@@ -232,7 +200,6 @@ var CameraRollView = React.createClass({
if (image === null) {
return null;
}
// $FlowFixMe(>=0.41.0)
return this.props.renderImage(image);
});
@@ -255,7 +222,6 @@ var CameraRollView = React.createClass({
newState.lastCursor = data.page_info.end_cursor;
newState.assets = this.state.assets.concat(assets);
newState.dataSource = this.state.dataSource.cloneWithRows(
// $FlowFixMe(>=0.41.0)
groupByEveryN(newState.assets, this.props.imagesPerRow)
);
}
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -19,24 +12,24 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @flow
* @providesModule ClipboardExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
Clipboard,
View,
Text,
} = ReactNative;
} = React;
class ClipboardExample extends React.Component {
state = {
content: 'Content will appear here'
};
var ClipboardExample = React.createClass({
getInitialState() {
return {
content: 'Content will appear here'
};
},
_setClipboardContent = async () => {
async _setClipboardContent(){
Clipboard.setString('Hello World');
try {
var content = await Clipboard.getString();
@@ -44,7 +37,7 @@ class ClipboardExample extends React.Component {
} catch (e) {
this.setState({content:e.message});
}
};
},
render() {
return (
@@ -58,7 +51,7 @@ class ClipboardExample extends React.Component {
</View>
);
}
}
});
exports.title = 'Clipboard';
exports.description = 'Show Clipboard contents.';
@@ -1,11 +1,4 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
@@ -17,47 +10,43 @@
* 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 DatePickerAndroidExample
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var React = require('react-native');
var {
DatePickerAndroid,
StyleSheet,
Text,
TouchableWithoutFeedback,
} = ReactNative;
} = React;
var UIExplorerBlock = require('./UIExplorerBlock');
var UIExplorerPage = require('./UIExplorerPage');
class DatePickerAndroidExample extends React.Component {
static title = 'DatePickerAndroid';
static description = 'Standard Android date picker dialog';
var DatePickerAndroidExample = React.createClass({
state = {
presetDate: new Date(2020, 4, 5),
simpleDate: new Date(2020, 4, 5),
spinnerDate: new Date(2020, 4, 5),
calendarDate: new Date(2020, 4, 5),
defaultDate: new Date(2020, 4, 5),
allDate: new Date(2020, 4, 5),
simpleText: 'pick a date',
spinnerText: 'pick a date',
calendarText: 'pick a date',
defaultText: 'pick a date',
minText: 'pick a date, no earlier than today',
maxText: 'pick a date, no later than today',
presetText: 'pick a date, preset to 2020/5/5',
allText: 'pick a date between 2020/5/1 and 2020/5/10',
};
statics: {
title: 'DatePickerAndroid',
description: 'Standard Android date picker dialog',
},
showPicker = async (stateKey, options) => {
getInitialState() {
return {
presetDate: new Date(2020, 4, 5),
allDate: new Date(2020, 4, 5),
simpleText: 'pick a date',
minText: 'pick a date, no earlier than today',
maxText: 'pick a date, no later than today',
presetText: 'pick a date, preset to 2020/5/5',
allText: 'pick a date between 2020/5/1 and 2020/5/10',
};
},
async showPicker(stateKey, options) {
try {
var newState = {};
const {action, year, month, day} = await DatePickerAndroid.open(options);
const {action, year, month, day} = await DatePickerAndroid.open(options);
if (action === DatePickerAndroid.dismissedAction) {
newState[stateKey + 'Text'] = 'dismissed';
} else {
@@ -69,7 +58,7 @@ class DatePickerAndroidExample extends React.Component {
} catch ({code, message}) {
console.warn(`Error in example '${stateKey}': `, message);
}
};
},
render() {
return (
@@ -80,24 +69,6 @@ class DatePickerAndroidExample extends React.Component {
<Text style={styles.text}>{this.state.simpleText}</Text>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="Simple spinner date picker">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'spinner', {date: this.state.spinnerDate, mode: 'spinner'})}>
<Text style={styles.text}>{this.state.spinnerText}</Text>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="Simple calendar date picker">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'calendar', {date: this.state.calendarDate, mode: 'calendar'})}>
<Text style={styles.text}>{this.state.calendarText}</Text>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="Simple default date picker">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'default', {date: this.state.defaultDate, mode: 'default'})}>
<Text style={styles.text}>{this.state.defaultText}</Text>
</TouchableWithoutFeedback>
</UIExplorerBlock>
<UIExplorerBlock title="Date picker with pre-set date">
<TouchableWithoutFeedback
onPress={this.showPicker.bind(this, 'preset', {date: this.state.presetDate})}>
@@ -134,8 +105,8 @@ class DatePickerAndroidExample extends React.Component {
</UIExplorerBlock>
</UIExplorerPage>
);
}
}
},
});
var styles = StyleSheet.create({
text: {

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