Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56563f13b3 | ||
|
|
0a08879d70 | ||
|
|
b890969b1e | ||
|
|
3bc5b180b1 | ||
|
|
5fbe29903b | ||
|
|
7cc3ba99e0 | ||
|
|
77167b02ee | ||
|
|
aed1c76576 | ||
|
|
8187e9153c | ||
|
|
c98a6fbde1 | ||
|
|
e1032e1d09 | ||
|
|
0c2f3fe145 | ||
|
|
329f059ba9 | ||
|
|
2d8ec5eca7 | ||
|
|
6edb671e2d |
@@ -25,6 +25,12 @@ project.xcworkspace
|
||||
# OS X
|
||||
.DS_Store
|
||||
|
||||
# Android/IJ
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
|
||||
# Node
|
||||
node_modules
|
||||
*.log
|
||||
|
||||
@@ -37,14 +37,14 @@
|
||||
* on the same Wi-Fi network.
|
||||
*/
|
||||
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle"];
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/Movies/MoviesApp.ios.includeRequire.runModule.bundle"];
|
||||
|
||||
/**
|
||||
* OPTION 2
|
||||
* Load from pre-bundled file on disk. To re-generate the static bundle, `cd`
|
||||
* to your Xcode project folder in the terminal, and run
|
||||
*
|
||||
* $ curl 'http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle' -o main.jsbundle
|
||||
* $ curl 'http://localhost:8081/Examples/Movies/MoviesApp.ios.includeRequire.runModule.bundle' -o main.jsbundle
|
||||
*
|
||||
* then add the `main.jsbundle` file to your project and uncomment this line:
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "23.0.1"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.facebook.react.movies"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:22.2.0'
|
||||
|
||||
// Depend on pre-built React Native
|
||||
compile 'com.facebook.react:react-native:0.11.+'
|
||||
|
||||
// Depend on React Native source.
|
||||
// This is useful for testing your changes when working on React Native.
|
||||
// compile project(':ReactAndroid')
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,21 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.react.movies">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@drawable/rotten_tomatoes_icon"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MoviesActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.facebook.react.movies;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.facebook.react.LifecycleState;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
|
||||
public class MoviesActivity extends Activity implements DefaultHardwareBackBtnHandler {
|
||||
|
||||
private ReactInstanceManager mReactInstanceManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
mReactInstanceManager = ReactInstanceManager.builder()
|
||||
.setApplication(getApplication())
|
||||
.setBundleAssetName("MoviesApp.android.bundle")
|
||||
.setJSMainModuleName("Examples/Movies/MoviesApp.android")
|
||||
.addPackage(new MainReactPackage())
|
||||
.setUseDeveloperSupport(true)
|
||||
.setInitialLifecycleState(LifecycleState.RESUMED)
|
||||
.build();
|
||||
|
||||
((ReactRootView) findViewById(R.id.react_root_view))
|
||||
.startReactApplication(mReactInstanceManager, "MoviesApp", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
|
||||
mReactInstanceManager.showDevOptionsDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onResume(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onBackPressed();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeDefaultOnBackPressed() {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 237 B |
|
After Width: | Height: | Size: 575 B |
|
After Width: | Height: | Size: 190 B |
|
After Width: | Height: | Size: 337 B |
|
After Width: | Height: | Size: 266 B |
|
After Width: | Height: | Size: 581 B |
|
After Width: | Height: | Size: 337 B |
|
After Width: | Height: | Size: 930 B |
|
After Width: | Height: | Size: 57 KiB |
@@ -0,0 +1,12 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MoviesApp">
|
||||
|
||||
<com.facebook.react.ReactRootView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/react_root_view"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">MoviesApp</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.1"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.facebook.react.sample"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:23.0.0'
|
||||
|
||||
// Depend on pre-built React Native
|
||||
compile 'com.facebook.react:react-native:0.11.+'
|
||||
|
||||
// Depend on React Native source.
|
||||
// This is useful for testing your changes when working on React Native.
|
||||
// compile project(':ReactAndroid')
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,21 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.react.sample">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.facebook.react.sample;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.facebook.react.LifecycleState;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
|
||||
|
||||
private ReactInstanceManager mReactInstanceManager;
|
||||
private ReactRootView mReactRootView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
SoLoader.init(this, false);
|
||||
mReactRootView = new ReactRootView(this);
|
||||
|
||||
mReactInstanceManager = ReactInstanceManager.builder()
|
||||
.setApplication(getApplication())
|
||||
.setBundleAssetName("index.android.bundle")
|
||||
.setJSMainModuleName("Examples/SampleApp/index.android")
|
||||
.addPackage(new MainReactPackage())
|
||||
.setUseDeveloperSupport(BuildConfig.DEBUG)
|
||||
.setInitialLifecycleState(LifecycleState.RESUMED)
|
||||
.build();
|
||||
|
||||
mReactRootView.startReactApplication(
|
||||
mReactInstanceManager,
|
||||
"SampleApp",
|
||||
null);
|
||||
|
||||
setContentView(mReactRootView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
|
||||
mReactInstanceManager.showDevOptionsDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeDefaultOnBackPressed() {
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onResume(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">SampleApp</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AppRegistry,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var SampleApp = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.welcome}>
|
||||
Welcome to React Native!
|
||||
</Text>
|
||||
<Text style={styles.instructions}>
|
||||
To get started, edit index.android.js
|
||||
</Text>
|
||||
<Text style={styles.instructions}>
|
||||
Shake or press menu button for dev menu
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
welcome: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 10,
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('SampleApp', () => SampleApp);
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ToastAndroid,
|
||||
TouchableWithoutFeedback,
|
||||
} = React;
|
||||
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var importantForAccessibilityValues = ['auto', 'yes', 'no', 'no-hide-descendants'];
|
||||
|
||||
var AccessibilityAndroidExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: 'Accessibility',
|
||||
description: 'Examples of using Accessibility API.',
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
count: 0,
|
||||
backgroundImportantForAcc: 0,
|
||||
forgroundImportantForAcc: 0,
|
||||
};
|
||||
},
|
||||
|
||||
_addOne: function() {
|
||||
this.setState({
|
||||
count: ++this.state.count,
|
||||
});
|
||||
},
|
||||
|
||||
_changeBackgroundImportantForAcc: function() {
|
||||
this.setState({
|
||||
backgroundImportantForAcc: (this.state.backgroundImportantForAcc + 1) % 4,
|
||||
});
|
||||
},
|
||||
|
||||
_changeForgroundImportantForAcc: function() {
|
||||
this.setState({
|
||||
forgroundImportantForAcc: (this.state.forgroundImportantForAcc + 1) % 4,
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title={'Accessibility'}>
|
||||
|
||||
<UIExplorerBlock title="Nonaccessible view with TextViews">
|
||||
<View>
|
||||
<Text style={{color: 'green',}}>
|
||||
This is
|
||||
</Text>
|
||||
<Text style={{color: 'blue'}}>
|
||||
nontouchable normal view.
|
||||
</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Accessible view with TextViews wihout label">
|
||||
<View accessible={true}>
|
||||
<Text style={{color: 'green',}}>
|
||||
This is
|
||||
</Text>
|
||||
<Text style={{color: 'blue'}}>
|
||||
nontouchable accessible view without label.
|
||||
</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Accessible view with TextViews with label">
|
||||
<View accessible={true}
|
||||
accessibilityLabel="I have label, so I read it instead of embedded text.">
|
||||
<Text style={{color: 'green',}}>
|
||||
This is
|
||||
</Text>
|
||||
<Text style={{color: 'blue'}}>
|
||||
nontouchable accessible view with label.
|
||||
</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Touchable with component type = button">
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT)}
|
||||
accessibilityComponentType="button">
|
||||
<View style={styles.embedded}>
|
||||
<Text>Click me</Text>
|
||||
<Text>Or not</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="LiveRegion">
|
||||
<TouchableWithoutFeedback onPress={this._addOne}>
|
||||
<View style={styles.embedded}>
|
||||
<Text>Click me</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
<Text accessibilityLiveRegion="polite">
|
||||
Clicked {this.state.count} times
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Overlapping views and importantForAccessibility property">
|
||||
<View style={styles.container}>
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: 10,
|
||||
top: 10,
|
||||
right: 10,
|
||||
height: 100,
|
||||
backgroundColor: 'green'}}
|
||||
accessible={true}
|
||||
accessibilityLabel="First layout"
|
||||
importantForAccessibility={
|
||||
importantForAccessibilityValues[this.state.backgroundImportantForAcc]}>
|
||||
<View accessible={true}>
|
||||
<Text style={{fontSize: 25}}>
|
||||
Hello
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: 10,
|
||||
top: 25,
|
||||
right: 10,
|
||||
height: 110,
|
||||
backgroundColor: 'yellow', opacity: 0.5}}
|
||||
accessible={true}
|
||||
accessibilityLabel="Second layout"
|
||||
importantForAccessibility={
|
||||
importantForAccessibilityValues[this.state.forgroundImportantForAcc]}>
|
||||
<View accessible={true}>
|
||||
<Text style={{fontSize: 20}}>
|
||||
world
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<TouchableWithoutFeedback onPress={this._changeBackgroundImportantForAcc}>
|
||||
<View style={styles.embedded}>
|
||||
<Text>
|
||||
Change importantForAccessibility for background layout.
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
<View accessible={true}>
|
||||
<Text>
|
||||
Background layout importantForAccessibility
|
||||
</Text>
|
||||
<Text>
|
||||
{importantForAccessibilityValues[this.state.backgroundImportantForAcc]}
|
||||
</Text>
|
||||
</View>
|
||||
<TouchableWithoutFeedback onPress={this._changeForgroundImportantForAcc}>
|
||||
<View style={styles.embedded}>
|
||||
<Text>
|
||||
Change importantForAccessibility for forground layout.
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
<View accessible={true}>
|
||||
<Text>
|
||||
Forground layout importantForAccessibility
|
||||
</Text>
|
||||
<Text>
|
||||
{importantForAccessibilityValues[this.state.forgroundImportantForAcc]}
|
||||
</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
embedded: {
|
||||
backgroundColor: 'yellow',
|
||||
padding:10,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
padding: 10,
|
||||
height:150,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = AccessibilityAndroidExample;
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ProgressBar = require('ProgressBarAndroid');
|
||||
var React = require('React');
|
||||
var UIExplorerBlock = require('UIExplorerBlock');
|
||||
var UIExplorerPage = require('UIExplorerPage');
|
||||
|
||||
var ProgressBarAndroidExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: '<ProgressBarAndroid>',
|
||||
description: 'Visual indicator of progress of some operation. ' +
|
||||
'Shows either a cyclic animation or a horizontal bar.',
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title="ProgressBar Examples">
|
||||
<UIExplorerBlock title="Default ProgressBar">
|
||||
<ProgressBar />
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Small ProgressBar">
|
||||
<ProgressBar styleAttr="Small" />
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Large ProgressBar">
|
||||
<ProgressBar styleAttr="Large" />
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Inverse ProgressBar">
|
||||
<ProgressBar styleAttr="Inverse" />
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Small Inverse ProgressBar">
|
||||
<ProgressBar styleAttr="SmallInverse" />
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Large Inverse ProgressBar">
|
||||
<ProgressBar styleAttr="LargeInverse" />
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = ProgressBarAndroidExample;
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity
|
||||
} = React;
|
||||
|
||||
var NUM_ITEMS = 20;
|
||||
|
||||
var ScrollViewSimpleExample = React.createClass({
|
||||
statics: {
|
||||
title: '<ScrollView>',
|
||||
description: 'Component that enables scrolling through child components.'
|
||||
},
|
||||
|
||||
makeItems: function(nItems: number, styles): Array<any> {
|
||||
var items = [];
|
||||
for (var i = 0; i < nItems; i++) {
|
||||
items[i] = (
|
||||
<TouchableOpacity key={i} style={styles}>
|
||||
<Text>{'Item ' + i}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// One of the items is a horizontal scroll view
|
||||
var items = this.makeItems(NUM_ITEMS, styles.itemWrapper);
|
||||
items[4] = (
|
||||
<ScrollView key={'scrollView'} horizontal={true}>
|
||||
{this.makeItems(NUM_ITEMS, [styles.itemWrapper, styles.horizontalItemWrapper])}
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
var verticalScrollView = (
|
||||
<ScrollView style={styles.verticalScrollView}>
|
||||
{items}
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
return verticalScrollView;
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
verticalScrollView: {
|
||||
margin: 10,
|
||||
},
|
||||
itemWrapper: {
|
||||
backgroundColor: '#dddddd',
|
||||
alignItems: 'center',
|
||||
borderRadius: 5,
|
||||
borderWidth: 5,
|
||||
borderColor: '#a52a2a',
|
||||
padding: 30,
|
||||
margin: 5,
|
||||
},
|
||||
horizontalItemWrapper: {
|
||||
padding: 50
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ScrollViewSimpleExample;
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
|
||||
var SwitchAndroid = require('SwitchAndroid');
|
||||
var Text = require('Text');
|
||||
var UIExplorerBlock = require('UIExplorerBlock');
|
||||
var UIExplorerPage = require('UIExplorerPage');
|
||||
|
||||
var SwitchAndroidExample = React.createClass({
|
||||
statics: {
|
||||
title: '<SwitchAndroid>',
|
||||
description: 'Standard Android two-state toggle component'
|
||||
},
|
||||
|
||||
getInitialState : function() {
|
||||
return {
|
||||
trueSwitchIsOn: true,
|
||||
falseSwitchIsOn: false,
|
||||
colorTrueSwitchIsOn: true,
|
||||
colorFalseSwitchIsOn: false,
|
||||
eventSwitchIsOn: false,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title="<SwitchAndroid>">
|
||||
<UIExplorerBlock title="Switches can be set to true or false">
|
||||
<SwitchAndroid
|
||||
onValueChange={(value) => this.setState({falseSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.falseSwitchIsOn} />
|
||||
<SwitchAndroid
|
||||
onValueChange={(value) => this.setState({trueSwitchIsOn: value})}
|
||||
value={this.state.trueSwitchIsOn} />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Switches can be disabled">
|
||||
<SwitchAndroid
|
||||
disabled={true}
|
||||
style={{marginBottom: 10}}
|
||||
value={true} />
|
||||
<SwitchAndroid
|
||||
disabled={true}
|
||||
value={false} />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Change events can be detected">
|
||||
<SwitchAndroid
|
||||
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.eventSwitchIsOn} />
|
||||
<SwitchAndroid
|
||||
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.eventSwitchIsOn} />
|
||||
<Text>{this.state.eventSwitchIsOn ? "On" : "Off"}</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Switches are controlled components">
|
||||
<SwitchAndroid />
|
||||
<SwitchAndroid value={true} />
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = SwitchAndroidExample;
|
||||
@@ -0,0 +1,349 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var Entity = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<Text style={{fontWeight: 'bold', color: '#527fe4'}}>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var AttributeToggler = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {fontWeight: 'bold', fontSize: 15};
|
||||
},
|
||||
toggleWeight: function() {
|
||||
this.setState({
|
||||
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold'
|
||||
});
|
||||
},
|
||||
increaseSize: function() {
|
||||
this.setState({
|
||||
fontSize: this.state.fontSize + 1
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
var curStyle = {fontWeight: this.state.fontWeight, fontSize: this.state.fontSize};
|
||||
return (
|
||||
<View>
|
||||
<Text style={curStyle}>
|
||||
Tap the controls below to change attributes.
|
||||
</Text>
|
||||
<Text>
|
||||
<Text>See how it will even work on <Text style={curStyle}>this nested text</Text></Text>
|
||||
</Text>
|
||||
<Text>
|
||||
<Text onPress={this.toggleWeight}>Toggle Weight</Text>
|
||||
{' (with highlight onPress)'}
|
||||
</Text>
|
||||
<Text onPress={this.increaseSize} suppressHighlighting={true}>
|
||||
Increase Size (suppressHighlighting true)
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TextExample = React.createClass({
|
||||
statics: {
|
||||
title: '<Text>',
|
||||
description: 'Base component for rendering styled text.',
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title="<Text>">
|
||||
<UIExplorerBlock title="Wrap">
|
||||
<Text>
|
||||
The text should wrap if it goes on multiple lines.
|
||||
See, this is going to the next line.
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Padding">
|
||||
<Text style={{padding: 10}}>
|
||||
This text is indented by 10px padding on all sides.
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Font Family">
|
||||
<Text style={{fontFamily: 'sans-serif'}}>
|
||||
Sans-Serif
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif', fontWeight: 'bold'}}>
|
||||
Sans-Serif Bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'serif'}}>
|
||||
Serif
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'serif', fontWeight: 'bold'}}>
|
||||
Serif Bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'monospace'}}>
|
||||
Monospace
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'monospace', fontWeight: 'bold'}}>
|
||||
Monospace Bold (After 5.0)
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Android Material Design fonts">
|
||||
<View style={{flexDirection: 'row', alignItems: 'flex-start'}}>
|
||||
<View style={{flex: 1}}>
|
||||
<Text style={{fontFamily: 'sans-serif'}}>
|
||||
Roboto Regular
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif', fontStyle: 'italic'}}>
|
||||
Roboto Italic
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif', fontWeight: 'bold'}}>
|
||||
Roboto Bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif', fontStyle: 'italic', fontWeight: 'bold'}}>
|
||||
Roboto Bold Italic
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-light'}}>
|
||||
Roboto Light
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-light', fontStyle: 'italic'}}>
|
||||
Roboto Light Italic
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-thin'}}>
|
||||
Roboto Thin (After 4.2)
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-thin', fontStyle: 'italic'}}>
|
||||
Roboto Thin Italic (After 4.2)
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-condensed'}}>
|
||||
Roboto Condensed
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-condensed', fontStyle: 'italic'}}>
|
||||
Roboto Condensed Italic
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-condensed', fontWeight: 'bold'}}>
|
||||
Roboto Condensed Bold
|
||||
</Text>
|
||||
<Text style={{
|
||||
fontFamily: 'sans-serif-condensed',
|
||||
fontStyle: 'italic',
|
||||
fontWeight: 'bold'}}>
|
||||
Roboto Condensed Bold Italic
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-medium'}}>
|
||||
Roboto Medium (After 5.0)
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'sans-serif-medium', fontStyle: 'italic'}}>
|
||||
Roboto Medium Italic (After 5.0)
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Font Size">
|
||||
<Text style={{fontSize: 23}}>
|
||||
Size 23
|
||||
</Text>
|
||||
<Text style={{fontSize: 8}}>
|
||||
Size 8
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Color">
|
||||
<Text style={{color: 'red'}}>
|
||||
Red color
|
||||
</Text>
|
||||
<Text style={{color: 'blue'}}>
|
||||
Blue color
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Font Weight">
|
||||
<Text style={{fontWeight: 'bold'}}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
<Text style={{fontWeight: 'normal'}}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Font Style">
|
||||
<Text style={{fontStyle: 'italic'}}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
<Text style={{fontStyle: 'normal'}}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Font Style and Weight">
|
||||
<Text style={{fontStyle: 'italic', fontWeight: 'bold'}}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Nested">
|
||||
<Text onPress={() => console.log('1st')}>
|
||||
(Normal text,
|
||||
<Text style={{fontWeight: 'bold'}} onPress={() => console.log('2nd')}>
|
||||
(and bold
|
||||
<Text style={{fontStyle: 'italic', fontSize: 11, color: '#527fe4'}} onPress={() => console.log('3rd')}>
|
||||
(and tiny bold italic blue
|
||||
<Text style={{fontWeight: 'normal', fontStyle: 'normal'}} onPress={() => console.log('4th')}>
|
||||
(and tiny normal blue)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'serif'}} onPress={() => console.log('1st')}>
|
||||
(Serif
|
||||
<Text style={{fontStyle: 'italic', fontWeight: 'bold'}} onPress={() => console.log('2nd')}>
|
||||
(Serif Bold Italic
|
||||
<Text
|
||||
style={{fontFamily: 'monospace', fontStyle: 'normal', fontWeight: 'normal'}}
|
||||
onPress={() => console.log('3rd')}>
|
||||
(Monospace Normal
|
||||
<Text
|
||||
style={{fontFamily: 'sans-serif', fontWeight: 'bold'}}
|
||||
onPress={() => console.log('4th')}>
|
||||
(Sans-Serif Bold
|
||||
<Text style={{fontWeight: 'normal'}} onPress={() => console.log('5th')}>
|
||||
(and Sans-Serif Normal)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
<Text style={{fontSize: 12}}>
|
||||
<Entity>Entity Name</Entity>
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Text Align">
|
||||
<Text>
|
||||
auto (default) - english LTR
|
||||
</Text>
|
||||
<Text>
|
||||
أحب اللغة العربية auto (default) - arabic RTL
|
||||
</Text>
|
||||
<Text style={{textAlign: 'left'}}>
|
||||
left left left left left left left left left left left left left left left
|
||||
</Text>
|
||||
<Text style={{textAlign: 'center'}}>
|
||||
center center center center center center center center center center center
|
||||
</Text>
|
||||
<Text style={{textAlign: 'right'}}>
|
||||
right right right right right right right right right right right right right
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Unicode">
|
||||
<View style={{flex: 1}}>
|
||||
<View style={{flexDirection: 'row'}}>
|
||||
<Text style={{backgroundColor: 'red'}}>
|
||||
星际争霸是世界上最好的游戏。
|
||||
</Text>
|
||||
</View>
|
||||
<View style={{flex: 1}}>
|
||||
<Text style={{backgroundColor: 'red'}}>
|
||||
星际争霸是世界上最好的游戏。
|
||||
</Text>
|
||||
</View>
|
||||
<View style={{flex: 1, alignItems: 'center'}}>
|
||||
<Text style={{backgroundColor: 'red'}}>
|
||||
星际争霸是世界上最好的游戏。
|
||||
</Text>
|
||||
</View>
|
||||
<View style={{flex: 1}}>
|
||||
<Text style={{backgroundColor: 'red'}}>
|
||||
星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Spaces">
|
||||
<Text>
|
||||
A {'generated'} {' '} {'string'} and some spaces
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Line Height">
|
||||
<Text style={{lineHeight: 35}}>
|
||||
Holisticly formulate inexpensive ideas before best-of-breed benefits. <Text style={{fontSize: 20}}>Continually</Text> expedite magnetic potentialities rather than client-focused interfaces.
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Empty Text">
|
||||
<Text />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Toggling Attributes">
|
||||
<AttributeToggler />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="backgroundColor attribute">
|
||||
<Text style={{backgroundColor: '#ffaaaa'}}>
|
||||
Red background,
|
||||
<Text style={{backgroundColor: '#aaaaff'}}>
|
||||
{' '}blue background,
|
||||
<Text>
|
||||
{' '}inherited blue background,
|
||||
<Text style={{backgroundColor: '#aaffaa'}}>
|
||||
{' '}nested green background.
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="containerBackgroundColor attribute">
|
||||
<View style={{flexDirection: 'row', height: 85}}>
|
||||
<View style={{backgroundColor: '#ffaaaa', width: 150}} />
|
||||
<View style={{backgroundColor: '#aaaaff', width: 150}} />
|
||||
</View>
|
||||
<Text style={[styles.backgroundColorText, {top: -80}]}>
|
||||
Default containerBackgroundColor (inherited) + backgroundColor wash
|
||||
</Text>
|
||||
<Text style={[styles.backgroundColorText, {top: -70, backgroundColor: 'transparent'}]}>
|
||||
{"containerBackgroundColor: 'transparent' + backgroundColor wash"}
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="numberOfLines attribute">
|
||||
<Text numberOfLines={1}>
|
||||
Maximum of one line no matter now much I write here. If I keep writing it{"'"}ll just truncate after one line
|
||||
</Text>
|
||||
<Text numberOfLines={2} style={{marginTop: 20}}>
|
||||
Maximum of two lines no matter now much I write here. If I keep writing it{"'"}ll just truncate after two lines
|
||||
</Text>
|
||||
<Text style={{marginTop: 20}}>
|
||||
No maximum lines specified no matter now much I write here. If I keep writing it{"'"}ll just keep going and going
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
backgroundColorText: {
|
||||
left: 5,
|
||||
backgroundColor: 'rgba(100, 100, 100, 0.3)'
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = TextExample;
|
||||
@@ -0,0 +1,316 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
StyleSheet,
|
||||
} = React;
|
||||
|
||||
var TextEventsExample = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
curText: '<No Event>',
|
||||
prevText: '<No Event>',
|
||||
prev2Text: '<No Event>',
|
||||
};
|
||||
},
|
||||
|
||||
updateText: function(text) {
|
||||
this.setState((state) => {
|
||||
return {
|
||||
curText: text,
|
||||
prevText: state.curText,
|
||||
prev2Text: state.prevText,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
placeholder="Enter text to see events"
|
||||
autoCorrect={false}
|
||||
onFocus={() => this.updateText('onFocus')}
|
||||
onBlur={() => this.updateText('onBlur')}
|
||||
onChange={(event) => this.updateText(
|
||||
'onChange text: ' + event.nativeEvent.text
|
||||
)}
|
||||
onEndEditing={(event) => this.updateText(
|
||||
'onEndEditing text: ' + event.nativeEvent.text
|
||||
)}
|
||||
onSubmitEditing={(event) => this.updateText(
|
||||
'onSubmitEditing text: ' + event.nativeEvent.text
|
||||
)}
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
<Text style={styles.eventLabel}>
|
||||
{this.state.curText}{'\n'}
|
||||
(prev: {this.state.prevText}){'\n'}
|
||||
(prev2: {this.state.prev2Text})
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
class RewriteExample extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {text: ''};
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<TextInput
|
||||
onChangeText={(text) => {
|
||||
text = text.replace(/ /g, '_');
|
||||
this.setState({text});
|
||||
}}
|
||||
style={styles.singleLine}
|
||||
value={this.state.text}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
multiline: {
|
||||
height: 60,
|
||||
fontSize: 16,
|
||||
padding: 4,
|
||||
marginBottom: 10,
|
||||
},
|
||||
eventLabel: {
|
||||
margin: 3,
|
||||
fontSize: 12,
|
||||
},
|
||||
singleLine: {
|
||||
fontSize: 16,
|
||||
padding: 4,
|
||||
},
|
||||
singleLineWithHeightTextInput: {
|
||||
height: 30,
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<TextInput>';
|
||||
exports.description = 'Single and multi-line text inputs.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Auto-focus',
|
||||
render: function() {
|
||||
return <TextInput autoFocus={true} style={styles.singleLine} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Live Re-Write (<sp> -> '_')",
|
||||
render: function() {
|
||||
return <RewriteExample />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Auto-capitalize',
|
||||
render: function() {
|
||||
var autoCapitalizeTypes = [
|
||||
'none',
|
||||
'sentences',
|
||||
'words',
|
||||
'characters',
|
||||
];
|
||||
var examples = autoCapitalizeTypes.map((type) => {
|
||||
return (
|
||||
<TextInput
|
||||
autoCapitalize={type}
|
||||
placeholder={'autoCapitalize: ' + type}
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
);
|
||||
});
|
||||
return <View>{examples}</View>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Auto-correct',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
autoCorrect={true}
|
||||
placeholder="This has autoCorrect"
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
<TextInput
|
||||
autoCorrect={false}
|
||||
placeholder="This does not have autoCorrect"
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Keyboard types',
|
||||
render: function() {
|
||||
var keyboardTypes = [
|
||||
'default',
|
||||
'email-address',
|
||||
'numeric',
|
||||
];
|
||||
var examples = keyboardTypes.map((type) => {
|
||||
return (
|
||||
<TextInput
|
||||
keyboardType={type}
|
||||
placeholder={'keyboardType: ' + type}
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
);
|
||||
});
|
||||
return <View>{examples}</View>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Event handling',
|
||||
render: function(): ReactElement { return <TextEventsExample />; },
|
||||
},
|
||||
{
|
||||
title: 'Colors and text inputs',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
style={[styles.singleLine]}
|
||||
defaultValue="Default color text"
|
||||
/>
|
||||
<TextInput
|
||||
style={[styles.singleLine, {color: 'green'}]}
|
||||
defaultValue="Green Text"
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Default placeholder text color"
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Red placeholder text color"
|
||||
placeholderTextColor="red"
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Default underline color"
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Blue underline color"
|
||||
style={styles.singleLine}
|
||||
underlineColorAndroid="blue"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Text input, themes and heights',
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
placeholder="If you set height, beware of padding set from themes"
|
||||
style={[styles.singleLineWithHeightTextInput]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Passwords',
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
defaultValue="iloveturtles"
|
||||
password={true}
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Editable',
|
||||
render: function() {
|
||||
return (
|
||||
<TextInput
|
||||
defaultValue="Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^"
|
||||
editable={false}
|
||||
style={styles.singleLine}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Multiline',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
autoCorrect={true}
|
||||
placeholder="multiline, aligned top-left"
|
||||
placeholderTextColor="red"
|
||||
multiline={true}
|
||||
textAlign="start"
|
||||
textAlignVertical="top"
|
||||
style={styles.multiline}
|
||||
/>
|
||||
<TextInput
|
||||
autoCorrect={true}
|
||||
placeholder="multiline, aligned center"
|
||||
placeholderTextColor="green"
|
||||
multiline={true}
|
||||
textAlign="center"
|
||||
textAlignVertical="center"
|
||||
style={[styles.multiline]}
|
||||
/>
|
||||
<TextInput
|
||||
autoCorrect={true}
|
||||
multiline={true}
|
||||
textAlign="end"
|
||||
textAlignVertical="bottom"
|
||||
style={[styles.multiline, {color: 'blue'}]}>
|
||||
<Text style={styles.multiline}>multiline with children, aligned bottom-right</Text>
|
||||
</TextInput>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Fixed number of lines',
|
||||
platform: 'android',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput numberOfLines={2}
|
||||
multiline={true}
|
||||
placeholder="Two line input"
|
||||
/>
|
||||
<TextInput numberOfLines={5}
|
||||
multiline={true}
|
||||
placeholder="Five line input"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
ToastAndroid,
|
||||
TouchableWithoutFeedback
|
||||
} = React;
|
||||
|
||||
var UIExplorerBlock = require('UIExplorerBlock');
|
||||
var UIExplorerPage = require('UIExplorerPage');
|
||||
|
||||
var ToastExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: 'Toast Example',
|
||||
description: 'Toast Example',
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title="ToastAndroid">
|
||||
<UIExplorerBlock title="Simple toast">
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() =>
|
||||
ToastAndroid.show('This is a toast with short duration', ToastAndroid.SHORT)}>
|
||||
<Text style={styles.text}>Click me.</Text>
|
||||
</TouchableWithoutFeedback>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Toast with long duration">
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() =>
|
||||
ToastAndroid.show('This is a toast with long duration', ToastAndroid.LONG)}>
|
||||
<Text style={styles.text}>Click me too.</Text>
|
||||
</TouchableWithoutFeedback>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
text: {
|
||||
color: 'black',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = ToastExample;
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var SwitchAndroid = require('SwitchAndroid');
|
||||
var ToolbarAndroid = require('ToolbarAndroid');
|
||||
|
||||
var ToolbarAndroidExample = React.createClass({
|
||||
statics: {
|
||||
title: '<ToolbarAndroid>',
|
||||
description: 'Examples of using the Android toolbar.'
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
actionText: 'Example app with toolbar component',
|
||||
toolbarSwitch: false,
|
||||
colorProps: {
|
||||
titleColor: '#3b5998',
|
||||
subtitleColor: '#6a7180',
|
||||
},
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title="<ToolbarAndroid>">
|
||||
<UIExplorerBlock title="Toolbar with title/subtitle and actions">
|
||||
<ToolbarAndroid
|
||||
actions={toolbarActions}
|
||||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
onActionSelected={this._onActionSelected}
|
||||
onIconClicked={() => this.setState({actionText: 'Icon clicked'})}
|
||||
style={styles.toolbar}
|
||||
subtitle={this.state.actionText}
|
||||
title="Toolbar" />
|
||||
<Text>{this.state.actionText}</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Toolbar with logo & custom title view (a View with Switch+Text)">
|
||||
<ToolbarAndroid
|
||||
logo={require('image!launcher_icon')}
|
||||
style={styles.toolbar}>
|
||||
<View style={{height: 56, flexDirection: 'row', alignItems: 'center'}}>
|
||||
<SwitchAndroid
|
||||
value={this.state.toolbarSwitch}
|
||||
onValueChange={(value) => this.setState({'toolbarSwitch': value})} />
|
||||
<Text>{'\'Tis but a switch'}</Text>
|
||||
</View>
|
||||
</ToolbarAndroid>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Toolbar with no icon">
|
||||
<ToolbarAndroid
|
||||
actions={toolbarActions}
|
||||
style={styles.toolbar}
|
||||
subtitle="There be no icon here" />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Toolbar with navIcon & logo, no title">
|
||||
<ToolbarAndroid
|
||||
actions={toolbarActions}
|
||||
logo={require('image!launcher_icon')}
|
||||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
style={styles.toolbar} />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Toolbar with custom title colors">
|
||||
<ToolbarAndroid
|
||||
navIcon={require('image!ic_menu_black_24dp')}
|
||||
onIconClicked={() => this.setState({colorProps: {}})}
|
||||
title="Wow, such toolbar"
|
||||
style={styles.toolbar}
|
||||
subtitle="Much native"
|
||||
{...this.state.colorProps} />
|
||||
<Text>
|
||||
Touch the icon to reset the custom colors to the default (theme-provided) ones.
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
_onActionSelected: function(position) {
|
||||
this.setState({
|
||||
actionText: 'Selected ' + toolbarActions[position].title,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
var toolbarActions = [
|
||||
{title: 'Create', icon: require('image!ic_create_black_48dp'), show: 'always'},
|
||||
{title: 'Filter'},
|
||||
{title: 'Settings', icon: require('image!ic_settings_black_48dp'), show: 'always'},
|
||||
];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
toolbar: {
|
||||
backgroundColor: '#e9eaed',
|
||||
height: 56,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = ToolbarAndroidExample;
|
||||
@@ -18,34 +18,42 @@
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AppRegistry,
|
||||
BackAndroid,
|
||||
Dimensions,
|
||||
DrawerLayoutAndroid,
|
||||
StyleSheet,
|
||||
ToolbarAndroid,
|
||||
View,
|
||||
} = React;
|
||||
var UIExplorerList = require('./UIExplorerList');
|
||||
|
||||
// TODO: these should be exposed by the 'react-native' module.
|
||||
var DrawerLayoutAndroid = require('DrawerLayoutAndroid');
|
||||
var ToolbarAndroid = require('ToolbarAndroid');
|
||||
var UIExplorerList = require('./UIExplorerList.android');
|
||||
|
||||
var DRAWER_WIDTH_LEFT = 56;
|
||||
|
||||
var UIExplorerApp = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
example: {
|
||||
title: 'UIExplorer',
|
||||
component: this._renderHome(),
|
||||
},
|
||||
example: this._getUIExplorerHome(),
|
||||
};
|
||||
},
|
||||
|
||||
_getUIExplorerHome: function() {
|
||||
return {
|
||||
title: 'UIExplorer',
|
||||
component: this._renderHome(),
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
BackAndroid.addEventListener('hardwareBackPress', this._handleBackButtonPress);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<DrawerLayoutAndroid
|
||||
drawerPosition={DrawerLayoutAndroid.positions.Left}
|
||||
drawerWidth={Dimensions.get('window').width - DRAWER_WIDTH_LEFT}
|
||||
keyboardDismissMode="on-drag"
|
||||
ref={(drawer) => { this.drawer = drawer; }}
|
||||
renderNavigationView={this._renderNavigationView}>
|
||||
{this._renderNavigation()}
|
||||
@@ -64,14 +72,11 @@ var UIExplorerApp = React.createClass({
|
||||
|
||||
onSelectExample: function(example) {
|
||||
this.drawer.closeDrawer();
|
||||
if (example.title === 'UIExplorer') {
|
||||
example.component = this._renderHome();
|
||||
if (example.title === this._getUIExplorerHome().title) {
|
||||
example = this._getUIExplorerHome();
|
||||
}
|
||||
this.setState({
|
||||
example: {
|
||||
title: example.title,
|
||||
component: example.component,
|
||||
},
|
||||
example: example,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -105,16 +110,16 @@ var UIExplorerApp = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
_handleBackButtonPress: function() {
|
||||
if (this.state.example.title !== this._getUIExplorerHome().title) {
|
||||
this.onSelectExample(this._getUIExplorerHome());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
messageText: {
|
||||
fontSize: 17,
|
||||
fontWeight: '500',
|
||||
padding: 15,
|
||||
marginTop: 50,
|
||||
marginLeft: 15,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
@@ -124,4 +129,6 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);
|
||||
|
||||
module.exports = UIExplorerApp;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
var UIExplorerListBase = require('./UIExplorerListBase');
|
||||
|
||||
var COMPONENTS = [
|
||||
require('./ImageExample'),
|
||||
require('./ProgressBarAndroidExample'),
|
||||
require('./ScrollViewSimpleExample'),
|
||||
require('./SwitchAndroidExample'),
|
||||
require('./TextExample.android'),
|
||||
require('./TextInputExample.android'),
|
||||
require('./ToolbarAndroidExample'),
|
||||
require('./TouchableExample'),
|
||||
require('./ViewExample'),
|
||||
];
|
||||
|
||||
var APIS = [
|
||||
require('./AccessibilityAndroidExample.android'),
|
||||
require('./BorderExample'),
|
||||
require('./LayoutEventsExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./PanResponderExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./TimerExample'),
|
||||
require('./ToastAndroidExample.android'),
|
||||
require('./XHRExample'),
|
||||
];
|
||||
|
||||
type Props = {
|
||||
onSelectExample: Function,
|
||||
isInDrawer: bool,
|
||||
};
|
||||
|
||||
class UIExplorerList extends React.Component {
|
||||
props: Props;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<UIExplorerListBase
|
||||
components={COMPONENTS}
|
||||
apis={APIS}
|
||||
searchText=""
|
||||
renderAdditionalView={this.renderAdditionalView.bind(this)}
|
||||
onPressRow={this.onPressRow.bind(this)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderAdditionalView(renderRow, renderTextInput): React.Component {
|
||||
if (this.props.isInDrawer) {
|
||||
var homePage = renderRow({
|
||||
title: 'UIExplorer',
|
||||
description: 'List of examples',
|
||||
}, -1);
|
||||
return (
|
||||
<View>
|
||||
{homePage}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return renderTextInput(styles.searchTextInput);
|
||||
}
|
||||
|
||||
onPressRow(example: any) {
|
||||
var Component = UIExplorerListBase.makeRenderable(example);
|
||||
this.props.onSelectExample({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
searchTextInput: {
|
||||
padding: 2,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerList;
|
||||
@@ -0,0 +1,326 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
PixelRatio,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
// TODO t7093728 This is a simlified XHRExample.ios.js.
|
||||
// Once we have Camera roll, Toast, Intent (for opening URLs)
|
||||
// we should make this consistent with iOS.
|
||||
|
||||
class Downloader extends React.Component {
|
||||
|
||||
xhr: XMLHttpRequest;
|
||||
cancelled: boolean;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.cancelled = false;
|
||||
this.state = {
|
||||
status: '',
|
||||
contentSize: 1,
|
||||
downloaded: 0,
|
||||
};
|
||||
}
|
||||
|
||||
download() {
|
||||
this.xhr && this.xhr.abort();
|
||||
|
||||
var xhr = this.xhr || new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === xhr.HEADERS_RECEIVED) {
|
||||
var contentSize = parseInt(xhr.getResponseHeader('Content-Length'), 10);
|
||||
this.setState({
|
||||
contentSize: contentSize,
|
||||
downloaded: 0,
|
||||
});
|
||||
} else if (xhr.readyState === xhr.LOADING) {
|
||||
this.setState({
|
||||
downloaded: xhr.responseText.length,
|
||||
});
|
||||
console.log(xhr.responseText.length);
|
||||
} else if (xhr.readyState === xhr.DONE) {
|
||||
if (this.cancelled) {
|
||||
this.cancelled = false;
|
||||
return;
|
||||
}
|
||||
if (xhr.status === 200) {
|
||||
this.setState({
|
||||
status: 'Download complete!',
|
||||
});
|
||||
} else if (xhr.status !== 0) {
|
||||
this.setState({
|
||||
status: 'Error: Server returned HTTP status of ' + xhr.status + ' ' + xhr.responseText,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
status: 'Error: ' + xhr.responseText,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.open('GET', 'http://www.gutenberg.org/cache/epub/100/pg100.txt');
|
||||
xhr.send();
|
||||
this.xhr = xhr;
|
||||
|
||||
this.setState({status: 'Downloading...'});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.cancelled = true;
|
||||
this.xhr && this.xhr.abort();
|
||||
}
|
||||
|
||||
render() {
|
||||
var button = this.state.status === 'Downloading...' ? (
|
||||
<View style={styles.wrapper}>
|
||||
<View style={styles.button}>
|
||||
<Text>...</Text>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={this.download.bind(this)}>
|
||||
<View style={styles.button}>
|
||||
<Text>Download 5MB Text File</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
||||
return (
|
||||
<View>
|
||||
{button}
|
||||
<Text>{this.state.status}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FormUploader extends React.Component {
|
||||
|
||||
_isMounted: boolean;
|
||||
_addTextParam: () => void;
|
||||
_upload: () => void;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isUploading: false,
|
||||
uploadProgress: null,
|
||||
textParams: [],
|
||||
};
|
||||
this._isMounted = true;
|
||||
this._addTextParam = this._addTextParam.bind(this);
|
||||
this._upload = this._upload.bind(this);
|
||||
}
|
||||
|
||||
_addTextParam() {
|
||||
var textParams = this.state.textParams;
|
||||
textParams.push({name: '', value: ''});
|
||||
this.setState({textParams});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
_onTextParamNameChange(index, text) {
|
||||
var textParams = this.state.textParams;
|
||||
textParams[index].name = text;
|
||||
this.setState({textParams});
|
||||
}
|
||||
|
||||
_onTextParamValueChange(index, text) {
|
||||
var textParams = this.state.textParams;
|
||||
textParams[index].value = text;
|
||||
this.setState({textParams});
|
||||
}
|
||||
|
||||
_upload() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'http://posttestserver.com/post.php');
|
||||
xhr.onload = () => {
|
||||
this.setState({isUploading: false});
|
||||
if (xhr.status !== 200) {
|
||||
console.log(
|
||||
'Upload failed',
|
||||
'Expected HTTP 200 OK response, got ' + xhr.status
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!xhr.responseText) {
|
||||
console.log(
|
||||
'Upload failed',
|
||||
'No response payload.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
var index = xhr.responseText.indexOf('http://www.posttestserver.com/');
|
||||
if (index === -1) {
|
||||
console.log(
|
||||
'Upload failed',
|
||||
'Invalid response payload.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
var url = xhr.responseText.slice(index).split('\n')[0];
|
||||
console.log('Upload successful: ' + url);
|
||||
};
|
||||
var formdata = new FormData();
|
||||
this.state.textParams.forEach(
|
||||
(param) => formdata.append(param.name, param.value)
|
||||
);
|
||||
if (xhr.upload) {
|
||||
xhr.upload.onprogress = (event) => {
|
||||
console.log('upload onprogress', event);
|
||||
if (event.lengthComputable) {
|
||||
this.setState({uploadProgress: event.loaded / event.total});
|
||||
}
|
||||
};
|
||||
}
|
||||
xhr.send(formdata);
|
||||
this.setState({isUploading: true});
|
||||
}
|
||||
|
||||
render() {
|
||||
var textItems = this.state.textParams.map((item, index) => (
|
||||
<View style={styles.paramRow}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
onChangeText={this._onTextParamNameChange.bind(this, index)}
|
||||
placeholder="name..."
|
||||
style={styles.textInput}
|
||||
/>
|
||||
<Text style={styles.equalSign}>=</Text>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
onChangeText={this._onTextParamValueChange.bind(this, index)}
|
||||
placeholder="value..."
|
||||
style={styles.textInput}
|
||||
/>
|
||||
</View>
|
||||
));
|
||||
var uploadButtonLabel = this.state.isUploading ? 'Uploading...' : 'Upload';
|
||||
var uploadProgress = this.state.uploadProgress;
|
||||
if (uploadProgress !== null) {
|
||||
uploadButtonLabel += ' ' + Math.round(uploadProgress * 100) + '%';
|
||||
}
|
||||
var uploadButton = (
|
||||
<View style={styles.uploadButtonBox}>
|
||||
<Text style={styles.uploadButtonLabel}>{uploadButtonLabel}</Text>
|
||||
</View>
|
||||
);
|
||||
if (!this.state.isUploading) {
|
||||
uploadButton = (
|
||||
<TouchableHighlight onPress={this._upload}>
|
||||
{uploadButton}
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
{textItems}
|
||||
<View>
|
||||
<Text
|
||||
style={[styles.textButton, styles.addTextParamButton]}
|
||||
onPress={this._addTextParam}>
|
||||
Add a text param
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.uploadButton}>
|
||||
{uploadButton}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'XMLHttpRequest';
|
||||
exports.description = 'XMLHttpRequest';
|
||||
exports.examples = [{
|
||||
title: 'File Download',
|
||||
render() {
|
||||
return <Downloader/>;
|
||||
}
|
||||
}, {
|
||||
title: 'multipart/form-data Upload',
|
||||
render() {
|
||||
return <FormUploader/>;
|
||||
}
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
borderRadius: 5,
|
||||
marginBottom: 5,
|
||||
},
|
||||
button: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 8,
|
||||
},
|
||||
paramRow: {
|
||||
flexDirection: 'row',
|
||||
paddingVertical: 8,
|
||||
alignItems: 'center',
|
||||
borderBottomWidth: 1 / PixelRatio.get(),
|
||||
borderBottomColor: 'grey',
|
||||
},
|
||||
textButton: {
|
||||
color: 'blue',
|
||||
},
|
||||
addTextParamButton: {
|
||||
marginTop: 8,
|
||||
},
|
||||
textInput: {
|
||||
flex: 1,
|
||||
borderRadius: 3,
|
||||
borderColor: 'grey',
|
||||
borderWidth: 1,
|
||||
height: 30,
|
||||
paddingLeft: 8,
|
||||
},
|
||||
equalSign: {
|
||||
paddingHorizontal: 4,
|
||||
},
|
||||
uploadButton: {
|
||||
marginTop: 16,
|
||||
},
|
||||
uploadButtonBox: {
|
||||
flex: 1,
|
||||
paddingVertical: 12,
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'blue',
|
||||
borderRadius: 4,
|
||||
},
|
||||
uploadButtonLabel: {
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.1"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.facebook.react.uiapp"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:23.0.0'
|
||||
|
||||
// Depend on pre-built React Native
|
||||
compile 'com.facebook.react:react-native:0.11.+'
|
||||
|
||||
// Depend on React Native source.
|
||||
// This is useful for testing your changes when working on React Native.
|
||||
// compile project(':ReactAndroid')
|
||||
}
|
||||
@@ -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 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.react.uiapp" >
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/launcher_icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.ReactNative.AppCompat.Light" >
|
||||
<activity
|
||||
android:name=".UIExplorerActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* The examples provided by Facebook are for non-commercial testing and
|
||||
* evaluation purposes only.
|
||||
*
|
||||
* Facebook reserves all rights not expressly granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
||||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.facebook.react.uiapp;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.facebook.react.LifecycleState;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
|
||||
public class UIExplorerActivity extends Activity implements DefaultHardwareBackBtnHandler {
|
||||
|
||||
private ReactInstanceManager mReactInstanceManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
mReactInstanceManager = ReactInstanceManager.builder()
|
||||
.setApplication(getApplication())
|
||||
.setBundleAssetName("UIExplorerApp.android.bundle")
|
||||
.setJSMainModuleName("Examples/UIExplorer/UIExplorerApp.android")
|
||||
.addPackage(new MainReactPackage())
|
||||
.setUseDeveloperSupport(true)
|
||||
.setInitialLifecycleState(LifecycleState.RESUMED)
|
||||
.build();
|
||||
|
||||
((ReactRootView) findViewById(R.id.react_root_view))
|
||||
.startReactApplication(mReactInstanceManager, "UIExplorerApp", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
|
||||
mReactInstanceManager.showDevOptionsDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onResume(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onBackPressed();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeDefaultOnBackPressed() {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 403 B |
|
After Width: | Height: | Size: 420 B |
|
After Width: | Height: | Size: 850 B |
|
After Width: | Height: | Size: 1.1 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=".UIExplorerApp">
|
||||
|
||||
<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">UIExplorer App</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -16,11 +16,11 @@ var warning = require('warning');
|
||||
class AppStateIOS {
|
||||
|
||||
static addEventListener(type, handler) {
|
||||
warning('Cannot listen to AppStateIOS events on Android.');
|
||||
warning(false, 'Cannot listen to AppStateIOS events on Android.');
|
||||
}
|
||||
|
||||
static removeEventListener(type, handler) {
|
||||
warning('Cannot remove AppStateIOS listener on Android.');
|
||||
warning(false, 'Cannot remove AppStateIOS listener on Android.');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ActivityIndicatorIOS
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var View = require('View');
|
||||
|
||||
var ActivityIndicatorIOS = React.createClass({
|
||||
render(): ReactElement {
|
||||
return <View {...this.props} />;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ActivityIndicatorIOS;
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule DatePickerIOS
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var View = require('View');
|
||||
|
||||
var DummyDatePickerIOS = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={[styles.dummyDatePickerIOS, this.props.style]}>
|
||||
<Text style={styles.datePickerText}>DatePickerIOS is not supported on this platform!</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
dummyDatePickerIOS: {
|
||||
height: 100,
|
||||
width: 300,
|
||||
backgroundColor: '#ffbcbc',
|
||||
borderWidth: 1,
|
||||
borderColor: 'red',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
margin: 10,
|
||||
},
|
||||
datePickerText: {
|
||||
color: '#333333',
|
||||
margin: 20,
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = DummyDatePickerIOS;
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule DrawerLayoutAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var DrawerConsts = require('NativeModules').UIManager.AndroidDrawerLayout.Constants;
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var dismissKeyboard = require('dismissKeyboard');
|
||||
var merge = require('merge');
|
||||
|
||||
var RK_DRAWER_REF = 'drawerlayout';
|
||||
var INNERVIEW_REF = 'innerView';
|
||||
|
||||
var DrawerLayoutValidAttributes = {
|
||||
drawerWidth: true,
|
||||
drawerPosition: true,
|
||||
};
|
||||
|
||||
var DRAWER_STATES = [
|
||||
'Idle',
|
||||
'Dragging',
|
||||
'Settling',
|
||||
];
|
||||
|
||||
/**
|
||||
* React component that wraps the platform `DrawerLayout` (Android only). The
|
||||
* Drawer (typically used for navigation) is rendered with `renderNavigationView`
|
||||
* and direct children are the main view (where your content goes). The navigation
|
||||
* view is initially not visible on the screen, but can be pulled in from the
|
||||
* side of the window specified by the `drawerPosition` prop and its width can
|
||||
* be set by the `drawerWidth` prop.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* render: function() {
|
||||
* var navigationView = (
|
||||
* <Text style={{margin: 10, fontSize: 15, textAlign: 'left'}}>I'm in the Drawer!</Text>
|
||||
* );
|
||||
* return (
|
||||
* <DrawerLayoutAndroid
|
||||
* drawerWidth={300}
|
||||
* drawerPosition={DrawerLayoutAndroid.positions.Left}
|
||||
* renderNavigationView={() => navigationView}>
|
||||
* <Text style={{10, fontSize: 15, textAlign: 'right'}}>Hello</Text>
|
||||
* <Text style={{10, fontSize: 15, textAlign: 'right'}}>World!</Text>
|
||||
* </DrawerLayoutAndroid>
|
||||
* );
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
var DrawerLayoutAndroid = React.createClass({
|
||||
statics: {
|
||||
positions: DrawerConsts.DrawerPosition,
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Determines whether the keyboard gets dismissed in response to a drag.
|
||||
* - 'none' (the default), drags do not dismiss the keyboard.
|
||||
* - 'on-drag', the keyboard is dismissed when a drag begins.
|
||||
*/
|
||||
keyboardDismissMode: ReactPropTypes.oneOf([
|
||||
'none', // default
|
||||
'on-drag',
|
||||
]),
|
||||
/**
|
||||
* Specifies the side of the screen from which the drawer will slide in.
|
||||
*/
|
||||
drawerPosition: ReactPropTypes.oneOf([
|
||||
DrawerConsts.DrawerPosition.Left,
|
||||
DrawerConsts.DrawerPosition.Right
|
||||
]),
|
||||
/**
|
||||
* Specifies the width of the drawer, more precisely the width of the view that be pulled in
|
||||
* from the edge of the window.
|
||||
*/
|
||||
drawerWidth: ReactPropTypes.number,
|
||||
/**
|
||||
* Function called whenever there is an interaction with the navigation view.
|
||||
*/
|
||||
onDrawerSlide: ReactPropTypes.func,
|
||||
/**
|
||||
* Function called when the drawer state has changed. The drawer can be in 3 states:
|
||||
* - idle, meaning there is no interaction with the navigation view happening at the time
|
||||
* - dragging, meaning there is currently an interation with the navigation view
|
||||
* - settling, meaning that there was an interaction with the navigation view, and the
|
||||
* navigation view is now finishing it's closing or opening animation
|
||||
*/
|
||||
onDrawerStateChanged: ReactPropTypes.func,
|
||||
/**
|
||||
* Function called whenever the navigation view has been opened.
|
||||
*/
|
||||
onDrawerOpen: ReactPropTypes.func,
|
||||
/**
|
||||
* Function called whenever the navigation view has been closed.
|
||||
*/
|
||||
onDrawerClose: ReactPropTypes.func,
|
||||
/**
|
||||
* The navigation view that will be rendered to the side of the screen and can be pulled in.
|
||||
*/
|
||||
renderNavigationView: ReactPropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
getInnerViewNode: function() {
|
||||
return this.refs[INNERVIEW_REF].getInnerViewNode();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var drawerViewWrapper =
|
||||
<View style={[styles.drawerSubview, {width: this.props.drawerWidth}]} collapsable={false}>
|
||||
{this.props.renderNavigationView()}
|
||||
</View>;
|
||||
var childrenWrapper =
|
||||
<View ref={INNERVIEW_REF} style={styles.mainSubview} collapsable={false}>
|
||||
{this.props.children}
|
||||
</View>;
|
||||
return (
|
||||
<AndroidDrawerLayout
|
||||
{...this.props}
|
||||
ref={RK_DRAWER_REF}
|
||||
drawerWidth={this.props.drawerWidth}
|
||||
drawerPosition={this.props.drawerPosition}
|
||||
style={styles.base}
|
||||
onDrawerSlide={this._onDrawerSlide}
|
||||
onDrawerOpen={this._onDrawerOpen}
|
||||
onDrawerClose={this._onDrawerClose}
|
||||
onDrawerStateChanged={this._onDrawerStateChanged}>
|
||||
{childrenWrapper}
|
||||
{drawerViewWrapper}
|
||||
</AndroidDrawerLayout>
|
||||
);
|
||||
},
|
||||
|
||||
_onDrawerSlide: function(event) {
|
||||
if (this.props.onDrawerSlide) {
|
||||
this.props.onDrawerSlide(event);
|
||||
}
|
||||
if (this.props.keyboardDismissMode === 'on-drag') {
|
||||
dismissKeyboard();
|
||||
}
|
||||
},
|
||||
|
||||
_onDrawerOpen: function() {
|
||||
if (this.props.onDrawerOpen) {
|
||||
this.props.onDrawerOpen();
|
||||
}
|
||||
},
|
||||
|
||||
_onDrawerClose: function() {
|
||||
if (this.props.onDrawerClose) {
|
||||
this.props.onDrawerClose();
|
||||
}
|
||||
},
|
||||
|
||||
_onDrawerStateChanged: function(event) {
|
||||
if (this.props.onDrawerStateChanged) {
|
||||
this.props.onDrawerStateChanged(DRAWER_STATES[event.nativeEvent.drawerState]);
|
||||
}
|
||||
},
|
||||
|
||||
openDrawer: function() {
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this._getDrawerLayoutHandle(),
|
||||
RCTUIManager.AndroidDrawerLayout.Commands.openDrawer,
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
closeDrawer: function() {
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
this._getDrawerLayoutHandle(),
|
||||
RCTUIManager.AndroidDrawerLayout.Commands.closeDrawer,
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
_getDrawerLayoutHandle: function() {
|
||||
return React.findNodeHandle(this.refs[RK_DRAWER_REF]);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
base: {
|
||||
flex: 1,
|
||||
},
|
||||
mainSubview: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
drawerSubview: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
});
|
||||
|
||||
// The View that contains both the actual drawer and the main view
|
||||
var AndroidDrawerLayout = createReactNativeComponentClass({
|
||||
validAttributes: merge(ReactNativeViewAttributes.UIView, DrawerLayoutValidAttributes),
|
||||
uiViewClassName: 'AndroidDrawerLayout',
|
||||
});
|
||||
|
||||
module.exports = DrawerLayoutAndroid;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule DrawerLayoutAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = require('UnimplementedView');
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule NavigatorIOS
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = require('UnimplementedView');
|
||||
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule NavigatorBreadcrumbNavigationBarStyles
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var Dimensions = require('Dimensions');
|
||||
var NavigatorNavigationBarStyles = require('NavigatorNavigationBarStyles');
|
||||
|
||||
var buildStyleInterpolator = require('buildStyleInterpolator');
|
||||
var merge = require('merge');
|
||||
|
||||
var SCREEN_WIDTH = Dimensions.get('window').width;
|
||||
var NAV_BAR_HEIGHT = NavigatorNavigationBarStyles.General.NavBarHeight;
|
||||
|
||||
var SPACING = 8;
|
||||
var ICON_WIDTH = 40;
|
||||
var SEPARATOR_WIDTH = 9;
|
||||
var CRUMB_WIDTH = ICON_WIDTH + SEPARATOR_WIDTH;
|
||||
var NAV_ELEMENT_HEIGHT = NAV_BAR_HEIGHT;
|
||||
|
||||
var OPACITY_RATIO = 100;
|
||||
var ICON_INACTIVE_OPACITY = 0.6;
|
||||
var MAX_BREADCRUMBS = 10;
|
||||
|
||||
var CRUMB_BASE = {
|
||||
position: 'absolute',
|
||||
flexDirection: 'row',
|
||||
top: 0,
|
||||
width: CRUMB_WIDTH,
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
backgroundColor: 'transparent',
|
||||
};
|
||||
|
||||
var ICON_BASE = {
|
||||
width: ICON_WIDTH,
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
};
|
||||
|
||||
var SEPARATOR_BASE = {
|
||||
width: SEPARATOR_WIDTH,
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
};
|
||||
|
||||
var TITLE_BASE = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
backgroundColor: 'transparent',
|
||||
alignItems: 'flex-start',
|
||||
};
|
||||
|
||||
var FIRST_TITLE_BASE = merge(TITLE_BASE, {
|
||||
left: 0,
|
||||
right: 0,
|
||||
});
|
||||
|
||||
var RIGHT_BUTTON_BASE = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
overflow: 'hidden',
|
||||
opacity: 1,
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
backgroundColor: 'transparent',
|
||||
};
|
||||
|
||||
/**
|
||||
* Precompute crumb styles so that they don't need to be recomputed on every
|
||||
* interaction.
|
||||
*/
|
||||
var LEFT = [];
|
||||
var CENTER = [];
|
||||
var RIGHT = [];
|
||||
for (var i = 0; i < MAX_BREADCRUMBS; i++) {
|
||||
var crumbLeft = CRUMB_WIDTH * i + SPACING;
|
||||
LEFT[i] = {
|
||||
Crumb: merge(CRUMB_BASE, { left: crumbLeft }),
|
||||
Icon: merge(ICON_BASE, { opacity: ICON_INACTIVE_OPACITY }),
|
||||
Separator: merge(SEPARATOR_BASE, { opacity: 1 }),
|
||||
Title: merge(TITLE_BASE, { left: crumbLeft, opacity: 0 }),
|
||||
RightItem: merge(RIGHT_BUTTON_BASE, { opacity: 0 }),
|
||||
};
|
||||
CENTER[i] = {
|
||||
Crumb: merge(CRUMB_BASE, { left: crumbLeft }),
|
||||
Icon: merge(ICON_BASE, { opacity: 1 }),
|
||||
Separator: merge(SEPARATOR_BASE, { opacity: 0 }),
|
||||
Title: merge(TITLE_BASE, {
|
||||
left: crumbLeft + ICON_WIDTH,
|
||||
opacity: 1,
|
||||
}),
|
||||
RightItem: merge(RIGHT_BUTTON_BASE, { opacity: 1 }),
|
||||
};
|
||||
var crumbRight = crumbLeft + 50;
|
||||
RIGHT[i] = {
|
||||
Crumb: merge(CRUMB_BASE, { left: crumbRight}),
|
||||
Icon: merge(ICON_BASE, { opacity: 0 }),
|
||||
Separator: merge(SEPARATOR_BASE, { opacity: 0 }),
|
||||
Title: merge(TITLE_BASE, {
|
||||
left: crumbRight + ICON_WIDTH,
|
||||
opacity: 0,
|
||||
}),
|
||||
RightItem: merge(RIGHT_BUTTON_BASE, { opacity: 0 }),
|
||||
};
|
||||
}
|
||||
|
||||
// Special case the CENTER state of the first scene.
|
||||
CENTER[0] = {
|
||||
Crumb: merge(CRUMB_BASE, {left: SPACING + CRUMB_WIDTH}),
|
||||
Icon: merge(ICON_BASE, {opacity: 0}),
|
||||
Separator: merge(SEPARATOR_BASE, {opacity: 0}),
|
||||
Title: merge(FIRST_TITLE_BASE, {opacity: 1}),
|
||||
RightItem: CENTER[0].RightItem,
|
||||
};
|
||||
LEFT[0].Title = merge(FIRST_TITLE_BASE, {opacity: 0});
|
||||
RIGHT[0].Title = merge(FIRST_TITLE_BASE, {opacity: 0});
|
||||
|
||||
|
||||
var buildIndexSceneInterpolator = function(startStyles, endStyles) {
|
||||
return {
|
||||
Crumb: buildStyleInterpolator({
|
||||
translateX: {
|
||||
type: 'linear',
|
||||
from: 0,
|
||||
to: endStyles.Crumb.left - startStyles.Crumb.left,
|
||||
min: 0,
|
||||
max: 1,
|
||||
extrapolate: true,
|
||||
},
|
||||
left: {
|
||||
value: startStyles.Crumb.left,
|
||||
type: 'constant'
|
||||
},
|
||||
}),
|
||||
Icon: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.Icon.opacity,
|
||||
to: endStyles.Icon.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
},
|
||||
}),
|
||||
Separator: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.Separator.opacity,
|
||||
to: endStyles.Separator.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
},
|
||||
}),
|
||||
Title: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.Title.opacity,
|
||||
to: endStyles.Title.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
},
|
||||
translateX: {
|
||||
type: 'linear',
|
||||
from: 0,
|
||||
to: endStyles.Title.left - startStyles.Title.left,
|
||||
min: 0,
|
||||
max: 1,
|
||||
extrapolate: true,
|
||||
},
|
||||
left: {
|
||||
value: startStyles.Title.left,
|
||||
type: 'constant'
|
||||
},
|
||||
}),
|
||||
RightItem: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.RightItem.opacity,
|
||||
to: endStyles.RightItem.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
round: OPACITY_RATIO,
|
||||
},
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
var Interpolators = CENTER.map(function(_, ii) {
|
||||
return {
|
||||
// Animating *into* the center stage from the right
|
||||
RightToCenter: buildIndexSceneInterpolator(RIGHT[ii], CENTER[ii]),
|
||||
// Animating out of the center stage, to the left
|
||||
CenterToLeft: buildIndexSceneInterpolator(CENTER[ii], LEFT[ii]),
|
||||
// Both stages (animating *past* the center stage)
|
||||
RightToLeft: buildIndexSceneInterpolator(RIGHT[ii], LEFT[ii]),
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Contains constants that are used in constructing both `StyleSheet`s and
|
||||
* inline styles during transitions.
|
||||
*/
|
||||
module.exports = {
|
||||
Interpolators,
|
||||
Left: LEFT,
|
||||
Center: CENTER,
|
||||
Right: RIGHT,
|
||||
IconWidth: ICON_WIDTH,
|
||||
IconHeight: NAV_BAR_HEIGHT,
|
||||
SeparatorWidth: SEPARATOR_WIDTH,
|
||||
SeparatorHeight: NAV_BAR_HEIGHT,
|
||||
};
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule NavigatorNavigationBarStyles
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var buildStyleInterpolator = require('buildStyleInterpolator');
|
||||
var merge = require('merge');
|
||||
|
||||
// Android Material Design
|
||||
var NAV_BAR_HEIGHT = 56;
|
||||
var TITLE_LEFT = 72;
|
||||
var BUTTON_SIZE = 24;
|
||||
var TOUCH_TARGT_SIZE = 48;
|
||||
var BUTTON_HORIZONTAL_MARGIN = 16;
|
||||
|
||||
var BUTTON_EFFECTIVE_MARGIN = BUTTON_HORIZONTAL_MARGIN - (TOUCH_TARGT_SIZE - BUTTON_SIZE) / 2;
|
||||
var NAV_ELEMENT_HEIGHT = NAV_BAR_HEIGHT;
|
||||
|
||||
var BASE_STYLES = {
|
||||
Title: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
alignItems: 'flex-start',
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
backgroundColor: 'transparent',
|
||||
marginLeft: TITLE_LEFT,
|
||||
},
|
||||
LeftButton: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: BUTTON_EFFECTIVE_MARGIN,
|
||||
overflow: 'hidden',
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
RightButton: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: BUTTON_EFFECTIVE_MARGIN,
|
||||
overflow: 'hidden',
|
||||
alignItems: 'flex-end',
|
||||
height: NAV_ELEMENT_HEIGHT,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
};
|
||||
|
||||
// There are 3 stages: left, center, right. All previous navigation
|
||||
// items are in the left stage. The current navigation item is in the
|
||||
// center stage. All upcoming navigation items are in the right stage.
|
||||
// Another way to think of the stages is in terms of transitions. When
|
||||
// we move forward in the navigation stack, we perform a
|
||||
// right-to-center transition on the new navigation item and a
|
||||
// center-to-left transition on the current navigation item.
|
||||
var Stages = {
|
||||
Left: {
|
||||
Title: merge(BASE_STYLES.Title, { opacity: 0 }),
|
||||
LeftButton: merge(BASE_STYLES.LeftButton, { opacity: 0 }),
|
||||
RightButton: merge(BASE_STYLES.RightButton, { opacity: 0 }),
|
||||
},
|
||||
Center: {
|
||||
Title: merge(BASE_STYLES.Title, { opacity: 1 }),
|
||||
LeftButton: merge(BASE_STYLES.LeftButton, { opacity: 1 }),
|
||||
RightButton: merge(BASE_STYLES.RightButton, { opacity: 1 }),
|
||||
},
|
||||
Right: {
|
||||
Title: merge(BASE_STYLES.Title, { opacity: 0 }),
|
||||
LeftButton: merge(BASE_STYLES.LeftButton, { opacity: 0 }),
|
||||
RightButton: merge(BASE_STYLES.RightButton, { opacity: 0 }),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
var opacityRatio = 100;
|
||||
|
||||
function buildSceneInterpolators(startStyles, endStyles) {
|
||||
return {
|
||||
Title: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.Title.opacity,
|
||||
to: endStyles.Title.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
},
|
||||
left: {
|
||||
type: 'linear',
|
||||
from: startStyles.Title.left,
|
||||
to: endStyles.Title.left,
|
||||
min: 0,
|
||||
max: 1,
|
||||
extrapolate: true,
|
||||
},
|
||||
}),
|
||||
LeftButton: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.LeftButton.opacity,
|
||||
to: endStyles.LeftButton.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
round: opacityRatio,
|
||||
},
|
||||
left: {
|
||||
type: 'linear',
|
||||
from: startStyles.LeftButton.left,
|
||||
to: endStyles.LeftButton.left,
|
||||
min: 0,
|
||||
max: 1,
|
||||
},
|
||||
}),
|
||||
RightButton: buildStyleInterpolator({
|
||||
opacity: {
|
||||
type: 'linear',
|
||||
from: startStyles.RightButton.opacity,
|
||||
to: endStyles.RightButton.opacity,
|
||||
min: 0,
|
||||
max: 1,
|
||||
round: opacityRatio,
|
||||
},
|
||||
left: {
|
||||
type: 'linear',
|
||||
from: startStyles.RightButton.left,
|
||||
to: endStyles.RightButton.left,
|
||||
min: 0,
|
||||
max: 1,
|
||||
extrapolate: true,
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
var Interpolators = {
|
||||
// Animating *into* the center stage from the right
|
||||
RightToCenter: buildSceneInterpolators(Stages.Right, Stages.Center),
|
||||
// Animating out of the center stage, to the left
|
||||
CenterToLeft: buildSceneInterpolators(Stages.Center, Stages.Left),
|
||||
// Both stages (animating *past* the center stage)
|
||||
RightToLeft: buildSceneInterpolators(Stages.Right, Stages.Left),
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
General: {
|
||||
NavBarHeight: NAV_BAR_HEIGHT,
|
||||
StatusBarHeight: 0,
|
||||
TotalNavHeight: NAV_BAR_HEIGHT,
|
||||
},
|
||||
Interpolators,
|
||||
Stages,
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ProgressBarAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
|
||||
var STYLE_ATTRIBUTES = [
|
||||
'Horizontal',
|
||||
'Small',
|
||||
'Large',
|
||||
'Inverse',
|
||||
'SmallInverse',
|
||||
'LargeInverse'
|
||||
];
|
||||
|
||||
/**
|
||||
* React component that wraps the Android-only `ProgressBar`. This component is used to indicate
|
||||
* that the app is loading or there is some activity in the app.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* render: function() {
|
||||
* var progressBar =
|
||||
* <View style={styles.container}>
|
||||
* <ProgressBar styleAttr="Inverse" />
|
||||
* </View>;
|
||||
|
||||
* return (
|
||||
* <MyLoadingComponent
|
||||
* componentView={componentView}
|
||||
* loadingView={progressBar}
|
||||
* style={styles.loadingComponent}
|
||||
* />
|
||||
* );
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
var ProgressBarAndroid = React.createClass({
|
||||
propTypes: {
|
||||
/**
|
||||
* Style of the ProgressBar. One of:
|
||||
*
|
||||
* - Horizontal
|
||||
* - Small
|
||||
* - Large
|
||||
* - Inverse
|
||||
* - SmallInverse
|
||||
* - LargeInverse
|
||||
*/
|
||||
styleAttr: ReactPropTypes.oneOf(STYLE_ATTRIBUTES),
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: ReactPropTypes.string,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
styleAttr: 'Large',
|
||||
};
|
||||
},
|
||||
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
render: function() {
|
||||
return <AndroidProgressBar {...this.props} />;
|
||||
},
|
||||
});
|
||||
|
||||
var AndroidProgressBar = createReactNativeComponentClass({
|
||||
validAttributes: {
|
||||
...ReactNativeViewAttributes.UIView,
|
||||
styleAttr: true,
|
||||
},
|
||||
uiViewClassName: 'AndroidProgressBar',
|
||||
});
|
||||
|
||||
module.exports = ProgressBarAndroid;
|
||||
@@ -1,5 +1,10 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ProgressBarAndroid
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule SliderIOS
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = require('UnimplementedView');
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule StatusBarIOS
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = null;
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule SwitchAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
|
||||
var requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
var SWITCH = 'switch';
|
||||
|
||||
/**
|
||||
* Standard Android two-state toggle component
|
||||
*/
|
||||
var SwitchAndroid = React.createClass({
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Boolean value of the switch.
|
||||
*/
|
||||
value: PropTypes.bool,
|
||||
/**
|
||||
* If `true`, this component can't be interacted with.
|
||||
*/
|
||||
disabled: PropTypes.bool,
|
||||
/**
|
||||
* Invoked with the new value when the value chages.
|
||||
*/
|
||||
onValueChange: PropTypes.func,
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: PropTypes.string,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
value: false,
|
||||
disabled: false,
|
||||
};
|
||||
},
|
||||
|
||||
_onChange: function(event) {
|
||||
this.props.onChange && this.props.onChange(event);
|
||||
this.props.onValueChange && this.props.onValueChange(event.nativeEvent.value);
|
||||
|
||||
// The underlying switch might have changed, but we're controlled,
|
||||
// and so want to ensure it represents our value.
|
||||
this.refs[SWITCH].setNativeProps({on: this.props.value});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<RKSwitch
|
||||
ref={SWITCH}
|
||||
style={this.props.style}
|
||||
enabled={!this.props.disabled}
|
||||
on={this.props.value}
|
||||
onChange={this._onChange}
|
||||
testID={this.props.testID}
|
||||
onStartShouldSetResponder={() => true}
|
||||
onResponderTerminationRequest={() => false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var RKSwitch = requireNativeComponent('AndroidSwitch', null);
|
||||
|
||||
module.exports = SwitchAndroid;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule SwitchAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = require('UnimplementedView');
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ToastAndroid
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var RCTToastAndroid = require('NativeModules').ToastAndroid;
|
||||
|
||||
/**
|
||||
* This exposes the native ToastAndroid module as a JS module. This has a function 'showText'
|
||||
* which takes the following parameters:
|
||||
*
|
||||
* 1. String message: A string with the text to toast
|
||||
* 2. int duration: The duration of the toast. May be ToastAndroid.SHORT or ToastAndroid.LONG
|
||||
*/
|
||||
|
||||
var ToastAndroid = {
|
||||
|
||||
SHORT: RCTToastAndroid.SHORT,
|
||||
LONG: RCTToastAndroid.LONG,
|
||||
|
||||
show: function (
|
||||
message: string,
|
||||
duration: number
|
||||
): void {
|
||||
RCTToastAndroid.show(message, duration);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = ToastAndroid;
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ToastAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var warning = require('warning');
|
||||
|
||||
var ToastAndroid = {
|
||||
|
||||
show: function (
|
||||
message: string,
|
||||
duration: number
|
||||
): void {
|
||||
warning(false, 'Cannot use ToastAndroid on iOS.');
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = ToastAndroid;
|
||||
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ToolbarAndroid
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var Image = require('Image');
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var React = require('React');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
|
||||
/**
|
||||
* React component that wraps the Android-only [`Toolbar` widget][0]. A Toolbar can display a logo,
|
||||
* navigation icon (e.g. hamburger menu), a title & subtitle and a list of actions. The title and
|
||||
* subtitle are expanded so the logo and navigation icons are displayed on the left, title and
|
||||
* subtitle in the middle and the actions on the right.
|
||||
*
|
||||
* If the toolbar has an only child, it will be displayed between the title and actions.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* render: function() {
|
||||
* return (
|
||||
* <ToolbarAndroid
|
||||
* logo={require('image!app_logo')}
|
||||
* title="AwesomeApp"
|
||||
* actions={[{title: 'Settings', icon: require('image!icon_settings'), show: 'always'}]}
|
||||
* onActionSelected={this.onActionSelected} />
|
||||
* )
|
||||
* },
|
||||
* onActionSelected: function(position) {
|
||||
* if (position === 0) { // index of 'Settings'
|
||||
* showSettings();
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* [0]: https://developer.android.com/reference/android/support/v7/widget/Toolbar.html
|
||||
*/
|
||||
var ToolbarAndroid = React.createClass({
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Sets possible actions on the toolbar as part of the action menu. These are displayed as icons
|
||||
* or text on the right side of the widget. If they don't fit they are placed in an 'overflow'
|
||||
* menu.
|
||||
*
|
||||
* This property takes an array of objects, where each object has the following keys:
|
||||
*
|
||||
* * `title`: **required**, the title of this action
|
||||
* * `icon`: the icon for this action, e.g. `require('image!some_icon')`
|
||||
* * `show`: when to show this action as an icon or hide it in the overflow menu: `always`,
|
||||
* `ifRoom` or `never`
|
||||
* * `showWithText`: boolean, whether to show text alongside the icon or not
|
||||
*/
|
||||
actions: ReactPropTypes.arrayOf(ReactPropTypes.shape({
|
||||
title: ReactPropTypes.string.isRequired,
|
||||
icon: Image.propTypes.source,
|
||||
show: ReactPropTypes.oneOf(['always', 'ifRoom', 'never']),
|
||||
showWithText: ReactPropTypes.bool
|
||||
})),
|
||||
/**
|
||||
* Sets the toolbar logo.
|
||||
*/
|
||||
logo: Image.propTypes.source,
|
||||
/**
|
||||
* Sets the navigation icon.
|
||||
*/
|
||||
navIcon: Image.propTypes.source,
|
||||
/**
|
||||
* Callback that is called when an action is selected. The only argument that is passeed to the
|
||||
* callback is the position of the action in the actions array.
|
||||
*/
|
||||
onActionSelected: ReactPropTypes.func,
|
||||
/**
|
||||
* Callback called when the icon is selected.
|
||||
*/
|
||||
onIconClicked: ReactPropTypes.func,
|
||||
/**
|
||||
* Sets the toolbar subtitle.
|
||||
*/
|
||||
subtitle: ReactPropTypes.string,
|
||||
/**
|
||||
* Sets the toolbar subtitle color.
|
||||
*/
|
||||
subtitleColor: ReactPropTypes.string,
|
||||
/**
|
||||
* Sets the toolbar title.
|
||||
*/
|
||||
title: ReactPropTypes.string,
|
||||
/**
|
||||
* Sets the toolbar title color.
|
||||
*/
|
||||
titleColor: ReactPropTypes.string,
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: ReactPropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var nativeProps = {
|
||||
...this.props,
|
||||
};
|
||||
if (this.props.logo) {
|
||||
if (!this.props.logo.isStatic) {
|
||||
throw 'logo prop should be a static image (obtained via ix)';
|
||||
}
|
||||
nativeProps.logo = this.props.logo.uri;
|
||||
}
|
||||
if (this.props.navIcon) {
|
||||
if (!this.props.navIcon.isStatic) {
|
||||
throw 'navIcon prop should be static image (obtained via ix)';
|
||||
}
|
||||
nativeProps.navIcon = this.props.navIcon.uri;
|
||||
}
|
||||
if (this.props.actions) {
|
||||
nativeProps.actions = [];
|
||||
for (var i = 0; i < this.props.actions.length; i++) {
|
||||
var action = {
|
||||
...this.props.actions[i],
|
||||
};
|
||||
if (action.icon) {
|
||||
if (!action.icon.isStatic) {
|
||||
throw 'action icons should be static images (obtained via ix)';
|
||||
}
|
||||
action.icon = action.icon.uri;
|
||||
}
|
||||
nativeProps.actions.push(action);
|
||||
}
|
||||
}
|
||||
|
||||
return <NativeToolbar onSelect={this._onSelect} {...nativeProps} />;
|
||||
},
|
||||
|
||||
_onSelect: function(event) {
|
||||
var position = event.nativeEvent.position;
|
||||
if (position === -1) {
|
||||
this.props.onIconClicked && this.props.onIconClicked();
|
||||
} else {
|
||||
this.props.onActionSelected && this.props.onActionSelected(position);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var toolbarAttributes = {
|
||||
...ReactNativeViewAttributes.UIView,
|
||||
actions: true,
|
||||
logo: true,
|
||||
navIcon: true,
|
||||
subtitle: true,
|
||||
subtitleColor: true,
|
||||
title: true,
|
||||
titleColor: true,
|
||||
};
|
||||
|
||||
var NativeToolbar = createReactNativeComponentClass({
|
||||
validAttributes: toolbarAttributes,
|
||||
uiViewClassName: 'ToolbarAndroid',
|
||||
});
|
||||
|
||||
module.exports = ToolbarAndroid;
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ToolbarAndroid
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = require('UnimplementedView');
|
||||
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule TouchableNativeFeedback
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var RCTUIManager = require('NativeModules').UIManager;
|
||||
var React = require('React');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var Touchable = require('Touchable');
|
||||
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
|
||||
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var ensurePositiveDelayProps = require('ensurePositiveDelayProps');
|
||||
var onlyChild = require('onlyChild');
|
||||
|
||||
var rippleBackgroundPropType = createStrictShapeTypeChecker({
|
||||
type: React.PropTypes.oneOf(['RippleAndroid']),
|
||||
color: PropTypes.string,
|
||||
borderless: PropTypes.bool,
|
||||
});
|
||||
|
||||
var themeAttributeBackgroundPropType = createStrictShapeTypeChecker({
|
||||
type: React.PropTypes.oneOf(['ThemeAttrAndroid']),
|
||||
attribute: PropTypes.string.isRequired,
|
||||
});
|
||||
|
||||
var backgroundPropType = PropTypes.oneOfType([
|
||||
rippleBackgroundPropType,
|
||||
themeAttributeBackgroundPropType,
|
||||
]);
|
||||
|
||||
var TouchableView = createReactNativeComponentClass({
|
||||
validAttributes: {
|
||||
...ReactNativeViewAttributes.UIView,
|
||||
nativeBackgroundAndroid: backgroundPropType,
|
||||
},
|
||||
uiViewClassName: 'RCTView',
|
||||
});
|
||||
|
||||
var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
|
||||
|
||||
/**
|
||||
* A wrapper for making views respond properly to touches (Android only).
|
||||
* On Android this component uses native state drawable to display touch
|
||||
* feedback. At the moment it only supports having a single View instance as a
|
||||
* child node, as it's implemented by replacing that View with another instance
|
||||
* of RCTView node with some additional properties set.
|
||||
*
|
||||
* Background drawable of native feedback touchable can be customized with
|
||||
* `background` property.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* renderButton: function() {
|
||||
* return (
|
||||
* <TouchableNativeFeedback
|
||||
* onPress={this._onPressButton}
|
||||
* background={TouchableNativeFeedback.SelectableBackground()}>
|
||||
* <View style={{width: 150, height: 100, backgroundColor: 'red'}}>
|
||||
* <Text style={{margin: 30}}>Button</Text>
|
||||
* </View>
|
||||
* </TouchableHighlight>
|
||||
* );
|
||||
* },
|
||||
* ```
|
||||
*/
|
||||
|
||||
var TouchableNativeFeedback = React.createClass({
|
||||
propTypes: {
|
||||
...TouchableWithoutFeedback.propTypes,
|
||||
|
||||
/**
|
||||
* Determines the type of background drawable that's going to be used to
|
||||
* display feedback. It takes an object with `type` property and extra data
|
||||
* depending on the `type`. It's recommended to use one of the following
|
||||
* static methods to generate that dictionary:
|
||||
*
|
||||
* 1) TouchableNativeFeedback.SelectableBackground() - will create object
|
||||
* that represents android theme's default background for selectable
|
||||
* elements (?android:attr/selectableItemBackground)
|
||||
*
|
||||
* 2) TouchableNativeFeedback.SelectableBackgroundBorderless() - will create
|
||||
* object that represent android theme's default background for borderless
|
||||
* selectable elements (?android:attr/selectableItemBackgroundBorderless).
|
||||
* Available on android API level 21+
|
||||
*
|
||||
* 3) TouchableNativeFeedback.RippleAndroid(color, borderless) - will create
|
||||
* object that represents ripple drawable with specified color (as a
|
||||
* string). If property `borderless` evaluates to true the ripple will
|
||||
* render outside of the view bounds (see native actionbar buttons as an
|
||||
* example of that behavior). This background type is available on Android
|
||||
* API level 21+
|
||||
*/
|
||||
background: backgroundPropType,
|
||||
},
|
||||
|
||||
statics: {
|
||||
SelectableBackground: function() {
|
||||
return {type: 'ThemeAttrAndroid', attribute: 'selectableItemBackground'};
|
||||
},
|
||||
SelectableBackgroundBorderless: function() {
|
||||
return {type: 'ThemeAttrAndroid', attribute: 'selectableItemBackgroundBorderless'};
|
||||
},
|
||||
Ripple: function(color, borderless) {
|
||||
return {type: 'RippleAndroid', color: color, borderless: borderless};
|
||||
},
|
||||
},
|
||||
|
||||
mixins: [Touchable.Mixin],
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
background: this.SelectableBackground(),
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.touchableGetInitialState();
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
ensurePositiveDelayProps(this.props);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
ensurePositiveDelayProps(nextProps);
|
||||
},
|
||||
|
||||
/**
|
||||
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
|
||||
* defined on your component.
|
||||
*/
|
||||
touchableHandleActivePressIn: function() {
|
||||
this.props.onPressIn && this.props.onPressIn();
|
||||
this._dispatchPressedStateChange(true);
|
||||
this._dispatchHotspotUpdate(this.pressInLocation.pageX, this.pressInLocation.pageY);
|
||||
},
|
||||
|
||||
touchableHandleActivePressOut: function() {
|
||||
this.props.onPressOut && this.props.onPressOut();
|
||||
this._dispatchPressedStateChange(false);
|
||||
},
|
||||
|
||||
touchableHandlePress: function() {
|
||||
this.props.onPress && this.props.onPress();
|
||||
},
|
||||
|
||||
touchableHandleLongPress: function() {
|
||||
this.props.onLongPress && this.props.onLongPress();
|
||||
},
|
||||
|
||||
touchableGetPressRectOffset: function() {
|
||||
return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant!
|
||||
},
|
||||
|
||||
touchableGetHighlightDelayMS: function() {
|
||||
return this.props.delayPressIn;
|
||||
},
|
||||
|
||||
touchableGetLongPressDelayMS: function() {
|
||||
return this.props.delayLongPress;
|
||||
},
|
||||
|
||||
touchableGetPressOutDelayMS: function() {
|
||||
return this.props.delayPressOut;
|
||||
},
|
||||
|
||||
_handleResponderMove: function(e) {
|
||||
this.touchableHandleResponderMove(e);
|
||||
this._dispatchHotspotUpdate(e.nativeEvent.pageX, e.nativeEvent.pageY);
|
||||
},
|
||||
|
||||
_dispatchHotspotUpdate: function(destX, destY) {
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
React.findNodeHandle(this),
|
||||
RCTUIManager.RCTView.Commands.hotspotUpdate,
|
||||
[destX || 0, destY || 0]
|
||||
);
|
||||
},
|
||||
|
||||
_dispatchPressedStateChange: function(pressed) {
|
||||
RCTUIManager.dispatchViewManagerCommand(
|
||||
React.findNodeHandle(this),
|
||||
RCTUIManager.RCTView.Commands.setPressed,
|
||||
[pressed]
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var childProps = {
|
||||
...onlyChild(this.props.children).props,
|
||||
nativeBackgroundAndroid: this.props.background,
|
||||
accessible: this.props.accessible !== false,
|
||||
accessibilityComponentType: this.props.accessibilityComponentType,
|
||||
accessibilityTraits: this.props.accessibilityTraits,
|
||||
testID: this.props.testID,
|
||||
onLayout: this.props.onLayout,
|
||||
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
|
||||
onResponderTerminationRequest: this.touchableHandleResponderTerminationRequest,
|
||||
onResponderGrant: this.touchableHandleResponderGrant,
|
||||
onResponderMove: this._handleResponderMove,
|
||||
onResponderRelease: this.touchableHandleResponderRelease,
|
||||
onResponderTerminate: this.touchableHandleResponderTerminate,
|
||||
};
|
||||
return <TouchableView {...childProps}/>;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = TouchableNativeFeedback;
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule Image
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var NativeModules = require('NativeModules');
|
||||
var ImageResizeMode = require('ImageResizeMode');
|
||||
var ImageStylePropTypes = require('ImageStylePropTypes');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var View = require('View');
|
||||
|
||||
var createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var invariant = require('invariant');
|
||||
var merge = require('merge');
|
||||
var resolveAssetSource = require('resolveAssetSource');
|
||||
|
||||
/**
|
||||
* <Image> - A react component for displaying different types of images,
|
||||
* including network images, static resources, temporary local images, and
|
||||
* images from local disk, such as the camera roll. Example usage:
|
||||
*
|
||||
* renderImages: function() {
|
||||
* return (
|
||||
* <View>
|
||||
* <Image
|
||||
* style={styles.icon}
|
||||
* source={require('image!myIcon')}
|
||||
* />
|
||||
* <Image
|
||||
* style={styles.logo}
|
||||
* source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}}
|
||||
* />
|
||||
* </View>
|
||||
* );
|
||||
* },
|
||||
*
|
||||
* More example code in ImageExample.js
|
||||
*/
|
||||
|
||||
var ImageViewAttributes = merge(ReactNativeViewAttributes.UIView, {
|
||||
src: true,
|
||||
resizeMode: true,
|
||||
});
|
||||
|
||||
var Image = React.createClass({
|
||||
propTypes: {
|
||||
source: PropTypes.shape({
|
||||
/**
|
||||
* A string representing the resource identifier for the image, which
|
||||
* could be an http address, a local file path, or the name of a static image
|
||||
* resource (which should be wrapped in the `ix` function).
|
||||
*/
|
||||
uri: PropTypes.string,
|
||||
}).isRequired,
|
||||
style: StyleSheetPropType(ImageStylePropTypes),
|
||||
/**
|
||||
* Used to locate this view in end-to-end tests.
|
||||
*/
|
||||
testID: PropTypes.string,
|
||||
},
|
||||
|
||||
statics: {
|
||||
resizeMode: ImageResizeMode,
|
||||
},
|
||||
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
/**
|
||||
* `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We
|
||||
* make `this` look like an actual native component class. Since it can render
|
||||
* as 3 different native components we need to update viewConfig accordingly
|
||||
*/
|
||||
viewConfig: {
|
||||
uiViewClassName: 'RCTView',
|
||||
validAttributes: ReactNativeViewAttributes.RKView
|
||||
},
|
||||
|
||||
_updateViewConfig: function(props) {
|
||||
if (props.children) {
|
||||
this.viewConfig = {
|
||||
uiViewClassName: 'RCTView',
|
||||
validAttributes: ReactNativeViewAttributes.RKView,
|
||||
};
|
||||
} else {
|
||||
this.viewConfig = {
|
||||
uiViewClassName: 'RCTImageView',
|
||||
validAttributes: ImageViewAttributes,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._updateViewConfig(this.props);
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
this._updateViewConfig(nextProps);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var source = resolveAssetSource(this.props.source);
|
||||
if (source && source.uri) {
|
||||
var isNetwork = source.uri.match(/^https?:/);
|
||||
invariant(
|
||||
!(isNetwork && source.isStatic),
|
||||
'Static image URIs cannot start with "http": "' + source.uri + '"'
|
||||
);
|
||||
|
||||
var {width, height} = source;
|
||||
var style = flattenStyle([{width, height}, styles.base, this.props.style]);
|
||||
|
||||
var nativeProps = merge(this.props, {
|
||||
style,
|
||||
src: source.uri,
|
||||
});
|
||||
|
||||
if (nativeProps.children) {
|
||||
// TODO(6033040): Consider implementing this as a separate native component
|
||||
var imageProps = merge(nativeProps, {
|
||||
style: styles.absoluteImage,
|
||||
children: undefined,
|
||||
});
|
||||
return (
|
||||
<View style={nativeProps.style}>
|
||||
<RKImage {...imageProps}/>
|
||||
{this.props.children}
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
return <RKImage {...nativeProps}/>;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
base: {
|
||||
overflow: 'hidden',
|
||||
},
|
||||
absoluteImage: {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
position: 'absolute'
|
||||
}
|
||||
});
|
||||
|
||||
var RKImage = createReactNativeComponentClass({
|
||||
validAttributes: ImageViewAttributes,
|
||||
uiViewClassName: 'RCTImageView',
|
||||
});
|
||||
|
||||
module.exports = Image;
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule RCTNetworking
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
// Do not require the native RCTNetworking module directly! Use this wrapper module instead.
|
||||
// It will add the necessary requestId, so that you don't have to generate it yourself.
|
||||
var RCTNetworkingNative = require('NativeModules').Networking;
|
||||
|
||||
var _requestId = 1;
|
||||
var generateRequestId = function() {
|
||||
return _requestId++;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is a wrapper around the native RCTNetworking module. It adds a necessary unique
|
||||
* requestId to each network request that can be used to abort that request later on.
|
||||
*/
|
||||
class RCTNetworking {
|
||||
|
||||
static sendRequest(method, url, headers, data, callback) {
|
||||
var requestId = generateRequestId();
|
||||
RCTNetworkingNative.sendRequest(
|
||||
method,
|
||||
url,
|
||||
requestId,
|
||||
headers,
|
||||
data,
|
||||
callback);
|
||||
return requestId;
|
||||
}
|
||||
|
||||
static abortRequest(requestId) {
|
||||
RCTNetworkingNative.abortRequest(requestId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RCTNetworking;
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule XMLHttpRequest
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var FormData = require('FormData');
|
||||
var RCTNetworking = require('RCTNetworking');
|
||||
var XMLHttpRequestBase = require('XMLHttpRequestBase');
|
||||
|
||||
type Header = [string, string];
|
||||
|
||||
function convertHeadersMapToArray(headers: Object): Array<Header> {
|
||||
var headerArray = [];
|
||||
for (var name in headers) {
|
||||
headerArray.push([name, headers[name]]);
|
||||
}
|
||||
return headerArray;
|
||||
}
|
||||
|
||||
class XMLHttpRequest extends XMLHttpRequestBase {
|
||||
|
||||
_requestId: ?number;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._requestId = null;
|
||||
}
|
||||
|
||||
sendImpl(method: ?string, url: ?string, headers: Object, data: any): void {
|
||||
var body;
|
||||
if (typeof data === 'string') {
|
||||
body = {string: data};
|
||||
} else if (data instanceof FormData) {
|
||||
body = {
|
||||
formData: data.getParts().map((part) => {
|
||||
part.headers = convertHeadersMapToArray(part.headers);
|
||||
return part;
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
body = data;
|
||||
}
|
||||
|
||||
this._requestId = RCTNetworking.sendRequest(
|
||||
method,
|
||||
url,
|
||||
convertHeadersMapToArray(headers),
|
||||
body,
|
||||
this.callback.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
abortImpl(): void {
|
||||
this._requestId && RCTNetworking.abortRequest(this._requestId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = XMLHttpRequest;
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule renderApplication
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var Inspector = require('Inspector');
|
||||
var Portal = require('Portal');
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var React = require('React');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Subscribable = require('Subscribable');
|
||||
var View = require('View');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
// require BackAndroid so it sets the default handler that exits the app if no listeners respond
|
||||
require('BackAndroid');
|
||||
|
||||
var AppContainer = React.createClass({
|
||||
mixins: [Subscribable.Mixin],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
enabled: __DEV__,
|
||||
inspectorVisible: false,
|
||||
rootNodeHandle: null,
|
||||
rootImportanceForAccessibility: 'auto',
|
||||
};
|
||||
},
|
||||
|
||||
toggleElementInspector: function() {
|
||||
this.setState({
|
||||
inspectorVisible: !this.state.inspectorVisible,
|
||||
rootNodeHandle: React.findNodeHandle(this.refs.main),
|
||||
});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.addListenerOn(
|
||||
RCTDeviceEventEmitter,
|
||||
'toggleElementInspector',
|
||||
this.toggleElementInspector
|
||||
);
|
||||
|
||||
this._unmounted = false;
|
||||
},
|
||||
|
||||
renderInspector: function() {
|
||||
return this.state.inspectorVisible ?
|
||||
<Inspector
|
||||
rootTag={this.props.rootTag}
|
||||
inspectedViewTag={this.state.rootNodeHandle}
|
||||
/> :
|
||||
null;
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this._unmounted = true;
|
||||
},
|
||||
|
||||
setRootAccessibility: function(modalVisible) {
|
||||
if (this._unmounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
rootImportanceForAccessibility: modalVisible ? 'no-hide-descendants' : 'auto',
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var RootComponent = this.props.rootComponent;
|
||||
var appView =
|
||||
<View
|
||||
ref="main"
|
||||
collapsable={!this.state.inspectorVisible}
|
||||
style={styles.appContainer}>
|
||||
<RootComponent
|
||||
{...this.props.initialProps}
|
||||
rootTag={this.props.rootTag}
|
||||
importantForAccessibility={this.state.rootImportanceForAccessibility}/>
|
||||
<Portal
|
||||
onModalVisibilityChanged={this.setRootAccessibility}/>
|
||||
</View>;
|
||||
|
||||
return this.state.enabled ?
|
||||
<View style={styles.appContainer}>
|
||||
{appView}
|
||||
{this.renderInspector()}
|
||||
</View> :
|
||||
appView;
|
||||
}
|
||||
});
|
||||
|
||||
function renderApplication<D, P, S>(
|
||||
RootComponent: ReactClass<D, P, S>,
|
||||
initialProps: P,
|
||||
rootTag: any
|
||||
) {
|
||||
invariant(
|
||||
rootTag,
|
||||
'Expect to have a valid rootTag, instead got ', rootTag
|
||||
);
|
||||
React.render(
|
||||
<AppContainer
|
||||
rootComponent={RootComponent}
|
||||
initialProps={initialProps}
|
||||
rootTag={rootTag} />,
|
||||
rootTag
|
||||
);
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
// This is needed so the application covers the whole screen
|
||||
// and therefore the contents of the Portal are not clipped.
|
||||
appContainer: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = renderApplication;
|
||||
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule AsyncStorage
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTAsyncStorage = require('NativeModules').AsyncSQLiteDBStorage;
|
||||
|
||||
/**
|
||||
* AsyncStorage is a simple, asynchronous, persistent, global, key-value storage system.
|
||||
*
|
||||
* It is recommended that you use an abstraction on top of AsyncStorage instead of AsyncStorage
|
||||
* directly for anything more than light usage since it operates globally.
|
||||
*
|
||||
* This JS code is a simple facade over the native android implementation to provide a clear
|
||||
* JS API, real Error objects, and simple non-multi functions.
|
||||
*/
|
||||
var AsyncStorage = {
|
||||
/**
|
||||
* Fetches `key` and passes the result to `callback`, along with an `Error` if
|
||||
* there is any. Returns a `Promise` object.
|
||||
*/
|
||||
getItem: function(
|
||||
key: string,
|
||||
callback?: ?(error: ?Error, result: ?string) => void
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiGet([key], function(error, result) {
|
||||
var value = (result && result[0] && result[0][1]) ? result[0][1] : null;
|
||||
callback && callback((error && convertError(error)) || null, value);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(value);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Sets `value` for `key` and calls `callback` on completion, along with an
|
||||
* `Error` if there is any. Returns a `Promise` object.
|
||||
*/
|
||||
setItem: function(
|
||||
key: string,
|
||||
value: string,
|
||||
callback?: ?(error: ?Error) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiSet([[key,value]], function(error) {
|
||||
callback && callback((error && convertError(error)) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Returns a `Promise` object.
|
||||
*/
|
||||
removeItem: function(
|
||||
key: string,
|
||||
callback?: ?(error: ?Error) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiRemove([key], function(error) {
|
||||
callback && callback((error && convertError(error)) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Merges existing value with input value, assuming they are stringified json.
|
||||
* Returns a `Promise` object.
|
||||
*/
|
||||
mergeItem: function(
|
||||
key: string,
|
||||
value: string,
|
||||
callback?: ?(error: ?Error) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiMerge([[key,value]], function(error) {
|
||||
callback && callback((error && convertError(error)) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Erases *all* AsyncStorage for all clients, libraries, etc. You probably
|
||||
* don't want to call this - use removeItem or multiRemove to clear only your
|
||||
* own keys instead. Returns a `Promise` object.
|
||||
*/
|
||||
clear: function(callback?: ?(error: ?Error) => void): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.clear(function(error) {
|
||||
callback && callback(convertError(error) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Gets *all* keys known to the app, for all callers, libraries, etc. Returns a `Promise` object.
|
||||
*/
|
||||
getAllKeys: function(callback?: ?(error: ?Error, keys: ?Array<string>) => void): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.getAllKeys(function(error, keys) {
|
||||
callback && callback((error && convertError(error)) || null, keys);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(keys);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* The following batched functions are useful for executing a lot of
|
||||
* operations at once, allowing for native optimizations and provide the
|
||||
* convenience of a single callback after all operations are complete.
|
||||
*
|
||||
* In case of errors, these functions return the first encountered error and abort.
|
||||
*/
|
||||
|
||||
/**
|
||||
* multiGet invokes callback with an array of key-value pair arrays that
|
||||
* matches the input format of multiSet. Returns a `Promise` object.
|
||||
*
|
||||
* multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])
|
||||
*/
|
||||
multiGet: function(
|
||||
keys: Array<string>,
|
||||
callback?: ?(errors: ?Array<Error>, result: ?Array<Array<string>>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiGet(keys, function(error, result) {
|
||||
callback && callback((error && convertError(error)) || null, result);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* multiSet and multiMerge take arrays of key-value array pairs that match
|
||||
* the output of multiGet, e.g. Returns a `Promise` object.
|
||||
*
|
||||
* multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
|
||||
*/
|
||||
multiSet: function(
|
||||
keyValuePairs: Array<Array<string>>,
|
||||
callback?: ?(errors: ?Array<Error>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiSet(keyValuePairs, function(error) {
|
||||
callback && callback((error && convertError(error)) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Delete all the keys in the `keys` array. Returns a `Promise` object.
|
||||
*/
|
||||
multiRemove: function(
|
||||
keys: Array<string>,
|
||||
callback?: ?(errors: ?Array<Error>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiRemove(keys, function(error) {
|
||||
callback && callback((error && convertError(error)) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Merges existing values with input values, assuming they are stringified
|
||||
* json. Returns a `Promise` object.
|
||||
*/
|
||||
multiMerge: function(
|
||||
keyValuePairs: Array<Array<string>>,
|
||||
callback?: ?(errors: ?Array<Error>) => void
|
||||
): Promise {
|
||||
return new Promise((resolve, reject) => {
|
||||
RCTAsyncStorage.multiMerge(keyValuePairs, function(error) {
|
||||
callback && callback((error && convertError(error)) || null);
|
||||
if (error) {
|
||||
reject(convertError(error));
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
function convertError(error) {
|
||||
if (!error) {
|
||||
return null;
|
||||
}
|
||||
var out = new Error(error.message);
|
||||
return [out];
|
||||
}
|
||||
|
||||
module.exports = AsyncStorage;
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Detect hardware back button presses, and programatically invoke the default back button
|
||||
* functionality to exit the app if there are no listeners or if none of the listeners return true.
|
||||
*
|
||||
* @providesModule BackAndroid
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var Set = require('Set');
|
||||
var DeviceEventManager = require('NativeModules').DeviceEventManager;
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
|
||||
var DEVICE_BACK_EVENT = 'hardwareBackPress';
|
||||
|
||||
type BackPressEventName = $Enum<{
|
||||
backPress: string;
|
||||
}>;
|
||||
|
||||
var _backPressSubscriptions = new Set();
|
||||
|
||||
RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function() {
|
||||
var invokeDefault = true;
|
||||
_backPressSubscriptions.forEach((subscription) => {
|
||||
if (subscription()) {
|
||||
invokeDefault = false;
|
||||
}
|
||||
});
|
||||
if (invokeDefault) {
|
||||
BackAndroid.exitApp();
|
||||
}
|
||||
});
|
||||
|
||||
var BackAndroid = {
|
||||
|
||||
exitApp: function() {
|
||||
DeviceEventManager.invokeDefaultBackPressHandler();
|
||||
},
|
||||
|
||||
addEventListener: function (
|
||||
eventName: BackPressEventName,
|
||||
handler: Function
|
||||
): void {
|
||||
_backPressSubscriptions.add(handler);
|
||||
},
|
||||
|
||||
removeEventListener: function(
|
||||
eventName: BackPressEventName,
|
||||
handler: Function
|
||||
): void {
|
||||
_backPressSubscriptions.delete(handler);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = BackAndroid;
|
||||
@@ -1,4 +1,11 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* iOS stub for BackAndroid.android.js
|
||||
*
|
||||
* @providesModule BackAndroid
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule Platform
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var AndroidConstants = require('NativeModules').AndroidConstants;
|
||||
|
||||
var Platform = {
|
||||
OS: 'android',
|
||||
Version: AndroidConstants.Version,
|
||||
};
|
||||
|
||||
module.exports = Platform;
|
||||
@@ -21,6 +21,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||
// Components
|
||||
ActivityIndicatorIOS: require('ActivityIndicatorIOS'),
|
||||
DatePickerIOS: require('DatePickerIOS'),
|
||||
DrawerLayoutAndroid: require('DrawerLayoutAndroid'),
|
||||
Image: require('Image'),
|
||||
ListView: require('ListView'),
|
||||
MapView: require('MapView'),
|
||||
@@ -28,15 +29,20 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||
Navigator: require('Navigator'),
|
||||
NavigatorIOS: require('NavigatorIOS'),
|
||||
PickerIOS: require('PickerIOS'),
|
||||
ProgressBarAndroid: require('ProgressBarAndroid'),
|
||||
ProgressViewIOS: require('ProgressViewIOS'),
|
||||
ScrollView: require('ScrollView'),
|
||||
SegmentedControlIOS: require('SegmentedControlIOS'),
|
||||
SliderIOS: require('SliderIOS'),
|
||||
SwitchAndroid: require('SwitchAndroid'),
|
||||
SwitchIOS: require('SwitchIOS'),
|
||||
TabBarIOS: require('TabBarIOS'),
|
||||
Text: require('Text'),
|
||||
TextInput: require('TextInput'),
|
||||
ToastAndroid: require('ToastAndroid'),
|
||||
ToolbarAndroid: require('ToolbarAndroid'),
|
||||
TouchableHighlight: require('TouchableHighlight'),
|
||||
TouchableNativeFeedback: require('TouchableNativeFeedback'),
|
||||
TouchableOpacity: require('TouchableOpacity'),
|
||||
TouchableWithoutFeedback: require('TouchableWithoutFeedback'),
|
||||
View: require('View'),
|
||||
@@ -50,6 +56,7 @@ var ReactNative = Object.assign(Object.create(require('React')), {
|
||||
AppRegistry: require('AppRegistry'),
|
||||
AppStateIOS: require('AppStateIOS'),
|
||||
AsyncStorage: require('AsyncStorage'),
|
||||
BackAndroid: require('BackAndroid'),
|
||||
CameraRoll: require('CameraRoll'),
|
||||
Dimensions: require('Dimensions'),
|
||||
Easing: require('Easing'),
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright 2013-2014 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @providesModule ExecutionEnvironment
|
||||
*
|
||||
* NB: This is a temporary override that has not yet been merged upstream. It is NOT actually part
|
||||
* of react-core (yet)
|
||||
*
|
||||
* Stubs SignedSource<<7afee88a05412d0c4eef54817419648e>>
|
||||
*/
|
||||
|
||||
/*jslint evil: true */
|
||||
|
||||
"use strict";
|
||||
|
||||
var canUseDOM = false;
|
||||
|
||||
/**
|
||||
* Simple, lightweight module assisting with the detection and context of
|
||||
* Worker. Helps avoid circular dependencies and allows code to reason about
|
||||
* whether or not they are in a Worker, even if they never include the main
|
||||
* `ReactWorker` dependency.
|
||||
*/
|
||||
var ExecutionEnvironment = {
|
||||
|
||||
canUseDOM: canUseDOM,
|
||||
|
||||
canUseWorkers: typeof Worker !== 'undefined',
|
||||
|
||||
canUseEventListeners:
|
||||
canUseDOM && !!(window.addEventListener || window.attachEvent),
|
||||
|
||||
canUseViewport: canUseDOM && !!window.screen,
|
||||
|
||||
isInWorker: !canUseDOM // For now, this is true - might change in the future.
|
||||
|
||||
};
|
||||
|
||||
module.exports = ExecutionEnvironment;
|
||||
@@ -214,6 +214,30 @@ module.exports = MyCustomView;
|
||||
- `cd react-native && npm install`
|
||||
- `cd Examples`
|
||||
|
||||
Now open any example and hit run in Xcode.
|
||||
Now open any example (the `.xcodeproj` file in each of the `Examples` subdirectories) and hit Run in Xcode.
|
||||
|
||||
## Extending React Native
|
||||
|
||||
- Looking for a component? [react.parts](http://react.parts/)
|
||||
- Fellow developers write and publish React Native modules to npm and open source them on GitHub.
|
||||
- Making modules helps grow the React Native ecosystem and community. We recommend writing modules for your use cases and sharing them on npm.
|
||||
- Read the guides on Native Modules ([iOS](http://facebook.github.io/react-native/docs/native-modules-ios.html), [Android](http://facebook.github.io/react-native/docs/native-modules-android.html)) and Native UI Components ([iOS](http://facebook.github.io/react-native/docs/native-components-ios.html), [Android](http://facebook.github.io/react-native/docs/native-components-android.html)) if you are interested in extending native functionality.
|
||||
|
||||
## Opening Issues
|
||||
|
||||
If you encounter a bug with React Native we would like to hear about it. Search the [existing issues](https://github.com/facebook/react-native/issues) and try to make sure your problem doesn’t already exist before opening a new issue. It’s helpful if you include the version of React Native and OS you’re using. Please include a stack trace and reduced repro case when appropriate, too.
|
||||
|
||||
The GitHub issues are intended for bug reports and feature requests. For help and questions with using React Native please make use of the resources listed in the [Getting Help](#getting-help) section. There are limited resources available for handling issues and by keeping the list of open issues lean we can respond in a timely manner.
|
||||
|
||||
## Contributing
|
||||
|
||||
For more information about contributing, see our [Contribution Guidelines](https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
React is [BSD licensed](./LICENSE). We also provide an additional [patent grant](./PATENTS).
|
||||
|
||||
React documentation is [Creative Commons licensed](./LICENSE-docs).
|
||||
|
||||
Further documentation, tutorials, and more on the [React Native website](http://facebook.github.io/react-native/docs/getting-started.html).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React"
|
||||
s.version = "0.8.0"
|
||||
s.version = "0.11.4"
|
||||
s.summary = "Build high quality mobile apps using React."
|
||||
s.description = <<-DESC
|
||||
React Native apps are built using the React JS
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
Here's how to test the whole dev experience end-to-end. This will be eventually merged into the [Getting Started guide](https://facebook.github.io/react-native/docs/getting-started.html).
|
||||
|
||||
Assuming you have the [Android SDK](https://developer.android.com/sdk/installing/index.html) installed, run `android` to open the Android SDK Manager.
|
||||
|
||||
Make sure you have the following installed:
|
||||
|
||||
- Android SDK version 23
|
||||
- SDK build tools version 23
|
||||
- Android Support Repository 17 (for Android Support Library)
|
||||
|
||||
Follow steps on https://github.com/facebook/react-native/blob/master/react-native-cli/CONTRIBUTING.md, but be sure to bump the verison of react-native in package.json to some version > 0.9 (latest published npm version) or set up proxying properly for react-native
|
||||
|
||||
- From the react-native-android repo:
|
||||
- `./gradlew :ReactAndroid:installArchives`
|
||||
- *Assuming you already have android-jsc installed to local maven repo, no steps included here*
|
||||
- `react-native init ProjectName`
|
||||
- Open up your Android emulator (Genymotion is recommended)
|
||||
- `cd ProjectName`
|
||||
- `react-native run-android`
|
||||
|
||||
In case the app crashed:
|
||||
|
||||
- Run `adb logcat` and try to find a Java exception
|
||||
@@ -0,0 +1,101 @@
|
||||
# Building React Native for Android
|
||||
|
||||
This guide contains instructions for building the Android code and running the sample apps.
|
||||
|
||||
## Supported Operating Systems
|
||||
|
||||
This setup has only been tested on Mac OS so far.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Assuming you have the [Android SDK](https://developer.android.com/sdk/installing/index.html) installed, run `android` to open the Android SDK Manager.
|
||||
|
||||
Make sure you have the following installed:
|
||||
|
||||
- Android SDK version 22 (compileSdkVersion in [`build.gradle`](build.gradle))
|
||||
- SDK build tools version 22.0.1 (buildToolsVersion in [`build.gradle`](build.gradle))
|
||||
- Android Support Repository 17 (for Android Support Library)
|
||||
|
||||
Point Gradle to your Android SDK - in the root of your clone of the github repo, create a file called `local.properties` with the following contents:
|
||||
|
||||
sdk.dir=absolute_path_to_android_sdk
|
||||
ndk.dir=absolute_path_to_android_ndk
|
||||
|
||||
Example:
|
||||
|
||||
sdk.dir=/Users/your_unix_name/android-sdk-macosx
|
||||
ndk.dir=/Users/your_unix_name/android-ndk/android-ndk-r10c
|
||||
|
||||
## Run `npm install`
|
||||
|
||||
This is needed to fetch the dependencies for the packager.
|
||||
|
||||
```bash
|
||||
cd react-native-android
|
||||
npm install
|
||||
```
|
||||
|
||||
## Building from the command line
|
||||
|
||||
To build the framework code:
|
||||
|
||||
```bash
|
||||
cd react-native-android
|
||||
./gradlew :ReactAndroid:assembleDebug
|
||||
```
|
||||
|
||||
To install a snapshot version of the framework code in your local Maven repo:
|
||||
|
||||
```bash
|
||||
./gradlew :ReactAndroid:installArchives
|
||||
```
|
||||
|
||||
## Running the examples
|
||||
|
||||
To run the Sample app:
|
||||
|
||||
```bash
|
||||
cd react-native-android
|
||||
./gradlew :Examples:SampleApp:android:app:installDebug
|
||||
# Start the packager in a separate shell:
|
||||
# Make sure you ran npm install
|
||||
./packager/packager.sh
|
||||
# Open SampleApp in your emulator, Menu button -> Reload JS should work
|
||||
```
|
||||
|
||||
You can run any other sample app the same way, e.g.:
|
||||
|
||||
```bash
|
||||
./gradlew :Examples:Movies:android:app:installDebug
|
||||
./gradlew :Examples:UIExplorer:android:app:installDebug
|
||||
```
|
||||
|
||||
## Building from Android Studio
|
||||
|
||||
You'll need to do one additional step until we release the React Native Gradle plugin to Maven central. This is because Android Studio has its own local Maven repo:
|
||||
|
||||
mkdir -p /Applications/Android\ Studio.app/Contents/gradle/m2repository/com/facebook/react
|
||||
cp -r ~/.m2/repository/com/facebook/react/gradleplugin /Applications/Android\ Studio.app/Contents/gradle/m2repository/com/facebook/react/
|
||||
|
||||
Now, open Android Studio, click _Import Non-Android Studio project_ and find your `react-native-android` repo.
|
||||
|
||||
In the configurations dropdown, _app_ should be selected. Click _Run_.
|
||||
|
||||
## Installing the React Native .aar in your local Maven repo
|
||||
|
||||
In some cases, for example when working on the `react-native-cli` it's useful to publish a snapshot version of React Native into your local Maven repo. This way, Gradle can pick it up when building projects that have a Maven dependency on React Native.
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
cd react-native-android
|
||||
./gradlew :ReactAndroid:installArchives
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Gradle build fails in `ndk-build`. See the section about `local.properties` file above.
|
||||
|
||||
Gradle build fails "Could not find any version that matches com.facebook.react:gradleplugin:...". See the section about the React Native Gradle plugin above.
|
||||
|
||||
Packager throws an error saying a module is not found. Try running `npm install` in the root of the repo.
|
||||
@@ -0,0 +1,246 @@
|
||||
// Copyright 2015-present Facebook. All Rights Reserved.
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven'
|
||||
|
||||
apply plugin: 'de.undercouch.download'
|
||||
|
||||
import de.undercouch.gradle.tasks.download.Download
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
// We download various C++ open-source dependencies into downloads.
|
||||
// We then copy both downloaded code and our custom makefiles and headers into third-party-ndk
|
||||
// After that we build native code from src/main/jni with module path pointing at third-party-ndk
|
||||
|
||||
def downloadsDir = new File("$buildDir/downloads")
|
||||
def thirdPartyNdkDir = new File("$buildDir/third-party-ndk")
|
||||
|
||||
task createNativeDepsDirectories {
|
||||
downloadsDir.mkdirs()
|
||||
thirdPartyNdkDir.mkdirs()
|
||||
}
|
||||
|
||||
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
// Use ZIP version as it's faster this way to selectively extract some parts of the archive
|
||||
src 'https://downloads.sourceforge.net/project/boost/boost/1.57.0/boost_1_57_0.zip'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'boost_1_57_0.zip')
|
||||
}
|
||||
|
||||
task prepareBoost(dependsOn: downloadBoost, type: Copy) {
|
||||
from zipTree(downloadBoost.dest)
|
||||
from 'src/main/jni/third-party/boost/Android.mk'
|
||||
include 'boost_1_57_0/boost/**/*.hpp', 'Android.mk'
|
||||
into "$thirdPartyNdkDir/boost"
|
||||
}
|
||||
|
||||
task downloadDoubleConversion(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src 'https://github.com/google/double-conversion/archive/v1.1.1.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'double-conversion-1.1.1.tar.gz')
|
||||
}
|
||||
|
||||
task prepareDoubleConversion(dependsOn: downloadDoubleConversion, type: Copy) {
|
||||
from tarTree(downloadDoubleConversion.dest)
|
||||
from 'src/main/jni/third-party/double-conversion/Android.mk'
|
||||
include 'double-conversion-1.1.1/src/**/*', 'Android.mk'
|
||||
filesMatching('*/src/**/*', {fname -> fname.path = "double-conversion/${fname.name}"})
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/double-conversion"
|
||||
}
|
||||
|
||||
task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src 'https://github.com/facebook/folly/archive/v0.50.0.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'folly-0.50.0.tar.gz');
|
||||
}
|
||||
|
||||
task prepareFolly(dependsOn: downloadFolly, type: Copy) {
|
||||
from tarTree(downloadFolly.dest)
|
||||
from 'src/main/jni/third-party/folly/Android.mk'
|
||||
include 'folly-0.50.0/folly/**/*', 'Android.mk'
|
||||
eachFile {fname -> fname.path = (fname.path - "folly-0.50.0/")}
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/folly"
|
||||
}
|
||||
|
||||
task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src 'https://github.com/google/glog/archive/v0.3.3.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'glog-0.3.3.tar.gz')
|
||||
}
|
||||
|
||||
// Prepare glog sources to be compiled, this task will perform steps that normally shoudl've been
|
||||
// executed by automake. This way we can avoid dependencies on make/automake
|
||||
task prepareGlog(dependsOn: downloadGlog, type: Copy) {
|
||||
from tarTree(downloadGlog.dest)
|
||||
from 'src/main/jni/third-party/glog/'
|
||||
include 'glog-0.3.3/src/**/*', 'Android.mk', 'config.h'
|
||||
includeEmptyDirs = false
|
||||
filesMatching('**/*.h.in') {
|
||||
filter(ReplaceTokens, tokens: [
|
||||
ac_cv_have_unistd_h: '1',
|
||||
ac_cv_have_stdint_h: '1',
|
||||
ac_cv_have_systypes_h: '1',
|
||||
ac_cv_have_inttypes_h: '1',
|
||||
ac_cv_have_libgflags: '0',
|
||||
ac_google_start_namespace: 'namespace google {',
|
||||
ac_cv_have_uint16_t: '1',
|
||||
ac_cv_have_u_int16_t: '1',
|
||||
ac_cv_have___uint16: '0',
|
||||
ac_google_end_namespace: '}',
|
||||
ac_cv_have___builtin_expect: '1',
|
||||
ac_google_namespace: 'google',
|
||||
ac_cv___attribute___noinline: '__attribute__ ((noinline))',
|
||||
ac_cv___attribute___noreturn: '__attribute__ ((noreturn))',
|
||||
ac_cv___attribute___printf_4_5: '__attribute__((__format__ (__printf__, 4, 5)))'
|
||||
])
|
||||
it.path = (it.name - '.in')
|
||||
}
|
||||
into "$thirdPartyNdkDir/glog"
|
||||
}
|
||||
|
||||
task downloadJSCHeaders(type: Download) {
|
||||
def jscAPIBaseURL = 'https://svn.webkit.org/repository/webkit/!svn/bc/174650/trunk/Source/JavaScriptCore/API/'
|
||||
def jscHeaderFiles = ['JSBase.h', 'JSContextRef.h', 'JSObjectRef.h', 'JSRetainPtr.h', 'JSStringRef.h', 'JSValueRef.h', 'WebKitAvailability.h']
|
||||
def output = new File(downloadsDir, 'jsc')
|
||||
output.mkdirs()
|
||||
src(jscHeaderFiles.collect { headerName -> "$jscAPIBaseURL$headerName" })
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest output
|
||||
}
|
||||
|
||||
// Create Android.mk library module based on so files from mvn + include headers fetched from webkit.org
|
||||
task prepareJSC(dependsOn: downloadJSCHeaders) << {
|
||||
copy {
|
||||
from zipTree(configurations.compile.fileCollection { dep -> dep.name == 'android-jsc' }.singleFile)
|
||||
from {downloadJSCHeaders.dest}
|
||||
from 'src/main/jni/third-party/jsc/Android.mk'
|
||||
include 'jni/**/*.so', '*.h', 'Android.mk'
|
||||
filesMatching('*.h', { fname -> fname.path = "JavaScriptCore/${fname.path}"})
|
||||
into "$thirdPartyNdkDir/jsc";
|
||||
}
|
||||
}
|
||||
|
||||
def getNdkBuildName() {
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
return "ndk-build.cmd"
|
||||
} else {
|
||||
return "ndk-build"
|
||||
}
|
||||
}
|
||||
|
||||
def findNdkBuildFullPath() {
|
||||
// we allow to provide full path to ndk-build tool
|
||||
if (hasProperty('ndk.command')) {
|
||||
return property('ndk.command')
|
||||
}
|
||||
// or just a path to the containing directory
|
||||
if (hasProperty('ndk.path')) {
|
||||
def ndkDir = property('ndk.path')
|
||||
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
|
||||
}
|
||||
if (System.getenv('ANDROID_NDK') != null) {
|
||||
def ndkDir = System.getenv('ANDROID_NDK')
|
||||
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
|
||||
}
|
||||
def ndkDir = android.hasProperty('plugin') ? android.plugin.ndkFolder :
|
||||
plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder()
|
||||
if (ndkDir) {
|
||||
return new File(ndkDir, getNdkBuildName()).getAbsolutePath()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
def getNdkBuildFullPath() {
|
||||
def ndkBuildFullPath = findNdkBuildFullPath()
|
||||
if (ndkBuildFullPath == null || !new File(ndkBuildFullPath).canExecute()) {
|
||||
throw new GradleScriptException(
|
||||
"ndk-build binary cannot be found, check if you've set " +
|
||||
"\$ANDROID_NDK environment variable correctly or if ndk.dir is " +
|
||||
"setup in local.properties",
|
||||
null)
|
||||
}
|
||||
return ndkBuildFullPath
|
||||
}
|
||||
|
||||
task buildReactNdkLib(dependsOn: [prepareJSC, prepareBoost, prepareDoubleConversion, prepareFolly, prepareGlog], type: Exec) {
|
||||
inputs.file('src/main/jni/react')
|
||||
outputs.dir("$buildDir/react-ndk/all")
|
||||
commandLine getNdkBuildFullPath(),
|
||||
'NDK_PROJECT_PATH=null',
|
||||
"NDK_APPLICATION_MK=$projectDir/src/main/jni/Application.mk",
|
||||
'NDK_OUT=' + temporaryDir,
|
||||
"NDK_LIBS_OUT=$buildDir/react-ndk/all",
|
||||
"THIRD_PARTY_NDK_DIR=$buildDir/third-party-ndk",
|
||||
'-C', file('src/main/jni/react/jni').absolutePath,
|
||||
'--jobs', Runtime.runtime.availableProcessors()
|
||||
}
|
||||
|
||||
task cleanReactNdkLib(type: Exec) {
|
||||
commandLine getNdkBuildFullPath(),
|
||||
'-C', file('src/main/jni/react/jni').absolutePath,
|
||||
'clean'
|
||||
}
|
||||
|
||||
task packageReactNdkLibs(dependsOn: buildReactNdkLib, type: Copy) {
|
||||
from "$buildDir/react-ndk/all"
|
||||
exclude '**/libjsc.so'
|
||||
into "$buildDir/react-ndk/exported"
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "22.0.1"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
ndk {
|
||||
moduleName "reactnativejni"
|
||||
}
|
||||
|
||||
buildConfigField 'boolean', 'IS_INTERNAL_BUILD', 'false'
|
||||
}
|
||||
|
||||
sourceSets.main {
|
||||
jni.srcDirs = []
|
||||
jniLibs.srcDir "$buildDir/react-ndk/exported"
|
||||
res.srcDirs = ['src/main/res/devsupport', 'src/main/res/shell']
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
compileTask -> compileTask.dependsOn packageReactNdkLibs
|
||||
}
|
||||
|
||||
clean.dependsOn cleanReactNdkLib
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:22.2.0'
|
||||
compile 'com.facebook.fresco:fresco:0.6.1'
|
||||
compile 'com.facebook.fresco:imagepipeline-okhttp:0.6.1'
|
||||
compile 'com.fasterxml.jackson.core:jackson-core:2.2.3'
|
||||
compile 'com.google.code.findbugs:jsr305:3.0.0'
|
||||
compile 'com.squareup.okhttp:okhttp:2.4.0'
|
||||
compile 'com.squareup.okhttp:okhttp-ws:2.4.0'
|
||||
compile 'com.squareup.okio:okio:1.5.0'
|
||||
compile 'org.webkit:android-jsc:r174650'
|
||||
}
|
||||
|
||||
apply from: 'release.gradle'
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
VERSION_NAME=0.11.1-SNAPSHOT
|
||||
GROUP=com.facebook.react
|
||||
|
||||
POM_NAME=ReactNative
|
||||
POM_ARTIFACT_ID=react-native
|
||||
POM_PACKAGING=aar
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright 2015-present Facebook. All Rights Reserved.
|
||||
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'signing'
|
||||
|
||||
// Gradle tasks for publishing to maven
|
||||
// 1) To install in local maven repo use :installArchives task
|
||||
// 2) To upload artifact to maven central use: :uploadArchives (you'd need to have the permission to do that)
|
||||
|
||||
def isReleaseBuild() {
|
||||
return VERSION_NAME.contains('SNAPSHOT') == false
|
||||
}
|
||||
|
||||
def getRepositoryUrl() {
|
||||
return hasProperty('repositoryUrl') ? property('repositoryUrl') : 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
|
||||
}
|
||||
|
||||
def getRepositoryUsername() {
|
||||
return hasProperty('repositoryUsername') ? property('repositoryUsername') : ''
|
||||
}
|
||||
|
||||
def getRepositoryPassword() {
|
||||
return hasProperty('repositoryPassword') ? property('repositoryPassword') : ''
|
||||
}
|
||||
|
||||
def configureReactNativePom(def pom) {
|
||||
pom.project {
|
||||
name POM_NAME
|
||||
artifactId POM_ARTIFACT_ID
|
||||
packaging POM_PACKAGING
|
||||
description 'A framework for building native apps with React'
|
||||
url 'https://github.com/facebook/react-native'
|
||||
|
||||
scm {
|
||||
url 'https://github.com/facebook/react-native.git'
|
||||
connection 'scm:git:https://github.com/facebook/react-native.git'
|
||||
developerConnection 'scm:git:git@github.com:facebook/react-native.git'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'BSD License'
|
||||
url 'https://github.com/facebook/react-native/blob/master/LICENSE'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id 'facebook'
|
||||
name 'Facebook'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate { project ->
|
||||
|
||||
task androidJavadoc(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += files(android.bootClasspath)
|
||||
classpath += files(project.getConfigurations().getByName('compile').asList())
|
||||
include '**/*.java'
|
||||
exclude '**/ReactBuildConfig.java'
|
||||
}
|
||||
|
||||
task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
|
||||
classifier = 'javadoc'
|
||||
from androidJavadoc.destinationDir
|
||||
}
|
||||
|
||||
task androidSourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
include '**/*.java'
|
||||
}
|
||||
|
||||
android.libraryVariants.all { variant ->
|
||||
def name = variant.name.capitalize()
|
||||
task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) {
|
||||
from variant.javaCompile.destinationDir
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives androidSourcesJar
|
||||
// TODO Make Javadoc generation work with Java 1.8, currently only works with 1.7
|
||||
// archives androidJavadocJar
|
||||
}
|
||||
|
||||
version = VERSION_NAME
|
||||
group = GROUP
|
||||
|
||||
signing {
|
||||
required { isReleaseBuild() && gradle.taskGraph.hasTask('uploadArchives') }
|
||||
sign configurations.archives
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
configuration = configurations.archives
|
||||
repositories.mavenDeployer {
|
||||
beforeDeployment {
|
||||
MavenDeployment deployment -> signing.signPom(deployment)
|
||||
}
|
||||
|
||||
repository(url: getRepositoryUrl()) {
|
||||
authentication(
|
||||
userName: getRepositoryUsername(),
|
||||
password: getRepositoryPassword())
|
||||
|
||||
}
|
||||
|
||||
configureReactNativePom pom
|
||||
}
|
||||
}
|
||||
|
||||
task installArchives(type: Upload) {
|
||||
configuration = configurations.archives
|
||||
repositories.mavenDeployer {
|
||||
beforeDeployment {
|
||||
MavenDeployment deployment -> signing.signPom(deployment)
|
||||
}
|
||||
|
||||
repository url: "file://${System.properties['user.home']}/.m2/repository"
|
||||
configureReactNativePom pom
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.facebook.react">
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<application />
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
|
||||
// NOTE: this file is auto-copied from https://github.com/facebook/css-layout
|
||||
// @generated SignedSource<<0a1e3b1f834f027e7a5bc5303f945b0e>>
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSAlign {
|
||||
AUTO,
|
||||
FLEX_START,
|
||||
CENTER,
|
||||
FLEX_END,
|
||||
STRETCH,
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
|
||||
// NOTE: this file is auto-copied from https://github.com/facebook/css-layout
|
||||
// @generated SignedSource<<755069c4747cc9fc5624d70e5130e3d1>>
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public class CSSConstants {
|
||||
|
||||
public static final float UNDEFINED = Float.NaN;
|
||||
|
||||
public static boolean isUndefined(float value) {
|
||||
return Float.compare(value, UNDEFINED) == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
|
||||
// NOTE: this file is auto-copied from https://github.com/facebook/css-layout
|
||||
// @generated SignedSource<<5dc7f205706089599859188712b3bd8a>>
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSDirection {
|
||||
INHERIT,
|
||||
LTR,
|
||||
RTL,
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
|
||||
// NOTE: this file is auto-copied from https://github.com/facebook/css-layout
|
||||
// @generated SignedSource<<6183a87290f3acd1caef7b6301bbf3a7>>
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSFlexDirection {
|
||||
COLUMN,
|
||||
COLUMN_REVERSE,
|
||||
ROW,
|
||||
ROW_REVERSE
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) 2014-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.
|
||||
*/
|
||||
|
||||
// NOTE: this file is auto-copied from https://github.com/facebook/css-layout
|
||||
// @generated SignedSource<<619fbefba1cfee797bbc7dd18e22f50c>>
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSJustify {
|
||||
FLEX_START,
|
||||
CENTER,
|
||||
FLEX_END,
|
||||
SPACE_BETWEEN,
|
||||
SPACE_AROUND,
|
||||
}
|
||||