update website
@@ -1,10 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "RCTRootView.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
NSURL *jsCodeLocation;
|
||||
RCTRootView *rootView = [[RCTRootView alloc] init];
|
||||
|
||||
// Loading JavaScript code - uncomment the one you want.
|
||||
|
||||
// OPTION 1
|
||||
// Load from development server. Start the server from the repository root:
|
||||
//
|
||||
// $ npm start
|
||||
//
|
||||
// To run on device, change `localhost` to the IP address of your computer, and make sure your computer and
|
||||
// iOS device are on the same Wi-Fi network.
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle"];
|
||||
|
||||
// OPTION 2
|
||||
// Load from pre-bundled file on disk. To re-generate the static bundle, run
|
||||
//
|
||||
// $ curl http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle -o main.jsbundle
|
||||
//
|
||||
// and uncomment the next following line
|
||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
|
||||
rootView.scriptURL = jsCodeLocation;
|
||||
rootView.moduleName = @"MoviesApp";
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [[UIViewController alloc] init];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
||||
<rect key="frame" x="20" y="439" width="441" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Movies" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
PixelRatio,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View
|
||||
} = React;
|
||||
|
||||
var getStyleFromScore = require('./getStyleFromScore');
|
||||
var getImageSource = require('./getImageSource');
|
||||
var getTextFromScore = require('./getTextFromScore');
|
||||
|
||||
var MovieCell = React.createClass({
|
||||
render: function() {
|
||||
var criticsScore = this.props.movie.ratings.critics_score;
|
||||
return (
|
||||
<View>
|
||||
<TouchableHighlight onPress={this.props.onSelect}>
|
||||
<View style={styles.row}>
|
||||
<Image
|
||||
source={getImageSource(this.props.movie, 'det')}
|
||||
style={styles.cellImage}
|
||||
/>
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.movieTitle} numberOfLines={2}>
|
||||
{this.props.movie.title}
|
||||
</Text>
|
||||
<Text style={styles.movieYear} numberOfLines={1}>
|
||||
{this.props.movie.year}
|
||||
{' '}•{' '}
|
||||
<Text style={getStyleFromScore(criticsScore)}>
|
||||
Critics {getTextFromScore(criticsScore)}
|
||||
</Text>
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<View style={styles.cellBorder} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
movieTitle: {
|
||||
flex: 1,
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 2,
|
||||
},
|
||||
movieYear: {
|
||||
color: '#999999',
|
||||
fontSize: 12,
|
||||
},
|
||||
row: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'white',
|
||||
flexDirection: 'row',
|
||||
padding: 5,
|
||||
},
|
||||
cellImage: {
|
||||
backgroundColor: '#dddddd',
|
||||
height: 93,
|
||||
marginRight: 10,
|
||||
width: 60,
|
||||
},
|
||||
cellBorder: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
||||
// Trick to get the thinest line the device can display
|
||||
height: 1 / PixelRatio.get(),
|
||||
marginLeft: 4,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = MovieCell;
|
||||
@@ -1,155 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ExpandingText,
|
||||
Image,
|
||||
PixelRatio,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var getImageSource = require('./getImageSource');
|
||||
var getStyleFromScore = require('./getStyleFromScore');
|
||||
var getTextFromScore = require('./getTextFromScore');
|
||||
|
||||
var MovieScreen = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<ScrollView contentContainerStyle={styles.contentContainer}>
|
||||
<View style={styles.mainSection}>
|
||||
<Image
|
||||
source={getImageSource(this.props.movie, 'det')}
|
||||
style={styles.detailsImage}
|
||||
/>
|
||||
<View style={styles.rightPane}>
|
||||
<Text style={styles.movieTitle}>{this.props.movie.title}</Text>
|
||||
<Text>{this.props.movie.year}</Text>
|
||||
<View style={styles.mpaaWrapper}>
|
||||
<Text style={styles.mpaaText}>
|
||||
{this.props.movie.mpaa_rating}
|
||||
</Text>
|
||||
</View>
|
||||
<Ratings ratings={this.props.movie.ratings} />
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.separator} />
|
||||
<ExpandingText
|
||||
truncLength={200}
|
||||
text={this.props.movie.synopsis}
|
||||
/>
|
||||
<View style={styles.separator} />
|
||||
<Cast actors={this.props.movie.abridged_cast} />
|
||||
</ScrollView>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var Ratings = React.createClass({
|
||||
render: function() {
|
||||
var criticsScore = this.props.ratings.critics_score;
|
||||
var audienceScore = this.props.ratings.audience_score;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.rating}>
|
||||
<Text style={styles.ratingTitle}>Critics:</Text>
|
||||
<Text style={[styles.ratingValue, getStyleFromScore(criticsScore)]}>
|
||||
{getTextFromScore(criticsScore)}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.rating}>
|
||||
<Text style={styles.ratingTitle}>Audience:</Text>
|
||||
<Text style={[styles.ratingValue, getStyleFromScore(audienceScore)]}>
|
||||
{getTextFromScore(audienceScore)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var Cast = React.createClass({
|
||||
render: function() {
|
||||
if (!this.props.actors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text style={styles.castTitle}>Actors</Text>
|
||||
{this.props.actors.map(actor =>
|
||||
<Text key={actor.name} style={styles.castActor}>
|
||||
• {actor.name}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
contentContainer: {
|
||||
padding: 10,
|
||||
},
|
||||
rightPane: {
|
||||
justifyContent: 'space-between',
|
||||
flex: 1,
|
||||
},
|
||||
movieTitle: {
|
||||
flex: 1,
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
rating: {
|
||||
marginTop: 10,
|
||||
},
|
||||
ratingTitle: {
|
||||
fontSize: 14,
|
||||
},
|
||||
ratingValue: {
|
||||
fontSize: 28,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
mpaaWrapper: {
|
||||
alignSelf: 'flex-start',
|
||||
borderColor: 'black',
|
||||
borderWidth: 1,
|
||||
paddingHorizontal: 3,
|
||||
marginVertical: 5,
|
||||
},
|
||||
mpaaText: {
|
||||
fontFamily: 'Palatino',
|
||||
fontSize: 13,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
mainSection: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
detailsImage: {
|
||||
width: 134,
|
||||
height: 200,
|
||||
backgroundColor: '#eaeaea',
|
||||
marginRight: 10,
|
||||
},
|
||||
separator: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
||||
height: 1 / PixelRatio.get(),
|
||||
marginVertical: 10,
|
||||
},
|
||||
castTitle: {
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 3,
|
||||
},
|
||||
castActor: {
|
||||
marginLeft: 2,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = MovieScreen;
|
||||
@@ -1,435 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341801B1AA91740003F314A /* libRCTNetwork.a */; };
|
||||
13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13442C051AA90E7D0037E5B0 /* libRCTImage.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5725B1AA6236500CDF9C8 /* libRCTText.a */; };
|
||||
58C5726C1AA623A200CDF9C8 /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C572681AA6236600CDF9C8 /* libReactKit.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
1341801A1AA91740003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B511DB1A9E6C8500147676;
|
||||
remoteInfo = RCTNetwork;
|
||||
};
|
||||
13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
|
||||
remoteInfo = RCTImage;
|
||||
};
|
||||
58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
|
||||
remoteInfo = RCTText;
|
||||
};
|
||||
58C572671AA6236600CDF9C8 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
||||
remoteInfo = ReactKit;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
134180151AA91740003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||
13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* Movies.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Movies.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */,
|
||||
13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */,
|
||||
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */,
|
||||
58C5726C1AA623A200CDF9C8 /* libReactKit.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
134180161AA91740003F314A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1341801B1AA91740003F314A /* libRCTNetwork.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13442C011AA90E7D0037E5B0 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13442C051AA90E7D0037E5B0 /* libRCTImage.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* Movies */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = Movies;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58C571FC1AA6124500CDF9C8 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134180151AA91740003F314A /* RCTNetwork.xcodeproj */,
|
||||
13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */,
|
||||
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */,
|
||||
587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58C572571AA6236500CDF9C8 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58C5725B1AA6236500CDF9C8 /* libRCTText.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58C5725C1AA6236500CDF9C8 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58C572681AA6236600CDF9C8 /* libReactKit.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* Movies */,
|
||||
58C571FC1AA6124500CDF9C8 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* Movies.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* Movies */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Movies" */;
|
||||
buildPhases = (
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Movies;
|
||||
productName = "Hello World";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* Movies.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Movies" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 13442C011AA90E7D0037E5B0 /* Products */;
|
||||
ProjectRef = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 134180161AA91740003F314A /* Products */;
|
||||
ProjectRef = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 58C572571AA6236500CDF9C8 /* Products */;
|
||||
ProjectRef = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 58C5725C1AA6236500CDF9C8 /* Products */;
|
||||
ProjectRef = 587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* Movies */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
1341801B1AA91740003F314A /* libRCTNetwork.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTNetwork.a;
|
||||
remoteRef = 1341801A1AA91740003F314A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
13442C051AA90E7D0037E5B0 /* libRCTImage.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTImage.a;
|
||||
remoteRef = 13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
58C5725B1AA6236500CDF9C8 /* libRCTText.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTText.a;
|
||||
remoteRef = 58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
58C572681AA6236600CDF9C8 /* libReactKit.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReactKit.a;
|
||||
remoteRef = 58C572671AA6236600CDF9C8 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Network/build/Debug-iphoneos",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = Movies;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Network/build/Debug-iphoneos",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = Movies;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Movies" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Movies" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0610"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "Movies.app"
|
||||
BlueprintName = "Movies"
|
||||
ReferencedContainer = "container:Movies.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "Movies.app"
|
||||
BlueprintName = "Movies"
|
||||
ReferencedContainer = "container:Movies.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "Movies.app"
|
||||
BlueprintName = "Movies"
|
||||
ReferencedContainer = "container:Movies.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "Movies.app"
|
||||
BlueprintName = "Movies"
|
||||
ReferencedContainer = "container:Movies.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule MoviesApp
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native/addons');
|
||||
var {
|
||||
AppRegistry,
|
||||
NavigatorIOS,
|
||||
StyleSheet,
|
||||
} = React;
|
||||
|
||||
var SearchScreen = require('./SearchScreen');
|
||||
|
||||
var MoviesApp = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'Movies',
|
||||
component: SearchScreen,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('MoviesApp', () => MoviesApp);
|
||||
|
||||
module.exports = MoviesApp;
|
||||
@@ -1,337 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ListView,
|
||||
ScrollView,
|
||||
ActivityIndicatorIOS,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
TimerMixin,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var MovieCell = require('./MovieCell');
|
||||
var MovieScreen = require('./MovieScreen');
|
||||
|
||||
var fetch = require('fetch');
|
||||
|
||||
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/';
|
||||
var API_KEYS = ['7waqfqbprs7pajbz28mqf6vz', 'y4vwv8m33hed9ety83jmv52f'];
|
||||
|
||||
// Results should be cached keyed by the query
|
||||
// with values of null meaning "being fetched"
|
||||
// and anything besides null and undefined
|
||||
// as the result of a valid query
|
||||
var resultsCache = {
|
||||
dataForQuery: {},
|
||||
nextPageNumberForQuery: {},
|
||||
totalForQuery: {},
|
||||
};
|
||||
|
||||
var LOADING = {};
|
||||
|
||||
var SearchScreen = React.createClass({
|
||||
mixins: [TimerMixin],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isLoadingTail: false,
|
||||
dataSource: new ListView.DataSource({
|
||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
||||
}),
|
||||
filter: '',
|
||||
queryNumber: 0,
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.searchMovies('');
|
||||
},
|
||||
|
||||
_urlForQueryAndPage: function(query: string, pageNumber: ?number): string {
|
||||
var apiKey = API_KEYS[this.state.queryNumber % API_KEYS.length];
|
||||
if (query) {
|
||||
return (
|
||||
API_URL + 'movies.json?apikey=' + apiKey + '&q=' +
|
||||
encodeURIComponent(query) + '&page_limit=20&page=' + pageNumber
|
||||
);
|
||||
} else {
|
||||
// With no query, load latest movies
|
||||
return (
|
||||
API_URL + 'lists/movies/in_theaters.json?apikey=' + apiKey +
|
||||
'&page_limit=20&page=' + pageNumber
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
searchMovies: function(query: string) {
|
||||
this.timeoutID = null;
|
||||
|
||||
this.setState({filter: query});
|
||||
|
||||
var cachedResultsForQuery = resultsCache.dataForQuery[query];
|
||||
if (cachedResultsForQuery) {
|
||||
if (!LOADING[query]) {
|
||||
this.setState({
|
||||
dataSource: this.getDataSource(cachedResultsForQuery),
|
||||
isLoading: false
|
||||
});
|
||||
} else {
|
||||
this.setState({isLoading: true});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LOADING[query] = true;
|
||||
resultsCache.dataForQuery[query] = null;
|
||||
this.setState({
|
||||
isLoading: true,
|
||||
queryNumber: this.state.queryNumber + 1,
|
||||
isLoadingTail: false,
|
||||
});
|
||||
|
||||
fetch(this._urlForQueryAndPage(query, 1))
|
||||
.then((response) => response.json())
|
||||
.then((responseData) => {
|
||||
LOADING[query] = false;
|
||||
resultsCache.totalForQuery[query] = responseData.total;
|
||||
resultsCache.dataForQuery[query] = responseData.movies;
|
||||
resultsCache.nextPageNumberForQuery[query] = 2;
|
||||
|
||||
if (this.state.filter !== query) {
|
||||
// do not update state if the query is stale
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
dataSource: this.getDataSource(responseData.movies),
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
LOADING[query] = false;
|
||||
resultsCache.dataForQuery[query] = undefined;
|
||||
|
||||
this.setState({
|
||||
dataSource: this.getDataSource([]),
|
||||
isLoading: false,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
hasMore: function(): boolean {
|
||||
var query = this.state.filter;
|
||||
if (!resultsCache.dataForQuery[query]) {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
resultsCache.totalForQuery[query] !==
|
||||
resultsCache.dataForQuery[query].length
|
||||
);
|
||||
},
|
||||
|
||||
onEndReached: function() {
|
||||
var query = this.state.filter;
|
||||
if (!this.hasMore() || this.state.isLoadingTail) {
|
||||
// We're already fetching or have all the elements so noop
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOADING[query]) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOADING[query] = true;
|
||||
this.setState({
|
||||
queryNumber: this.state.queryNumber + 1,
|
||||
isLoadingTail: true,
|
||||
});
|
||||
|
||||
var page = resultsCache.nextPageNumberForQuery[query];
|
||||
fetch(this._urlForQueryAndPage(query, page))
|
||||
.then((response) => response.json())
|
||||
.then((responseData) => {
|
||||
var moviesForQuery = resultsCache.dataForQuery[query].slice();
|
||||
|
||||
LOADING[query] = false;
|
||||
// We reached the end of the list before the expected number of results
|
||||
if (!responseData.movies) {
|
||||
resultsCache.totalForQuery[query] = moviesForQuery.length;
|
||||
} else {
|
||||
for (var i in responseData.movies) {
|
||||
moviesForQuery.push(responseData.movies[i]);
|
||||
}
|
||||
resultsCache.dataForQuery[query] = moviesForQuery;
|
||||
resultsCache.nextPageNumberForQuery[query] += 1;
|
||||
}
|
||||
|
||||
if (this.state.filter !== query) {
|
||||
// do not update state if the query is stale
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isLoadingTail: false,
|
||||
dataSource: this.getDataSource(resultsCache.dataForQuery[query]),
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
LOADING[query] = false;
|
||||
this.setState({
|
||||
isLoadingTail: false,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getDataSource: function(movies: Array<any>): ListView.DataSource {
|
||||
return this.state.dataSource.cloneWithRows(movies);
|
||||
},
|
||||
|
||||
selectMovie: function(movie: Object) {
|
||||
this.props.navigator.push({
|
||||
title: movie.title,
|
||||
component: MovieScreen,
|
||||
passProps: {movie},
|
||||
});
|
||||
},
|
||||
|
||||
onSearchChange: function(event: Object) {
|
||||
var filter = event.nativeEvent.text.toLowerCase();
|
||||
|
||||
this.clearTimeout(this.timeoutID);
|
||||
this.timeoutID = this.setTimeout(() => this.searchMovies(filter), 100);
|
||||
},
|
||||
|
||||
renderFooter: function() {
|
||||
if (!this.hasMore() || !this.state.isLoadingTail) {
|
||||
return <View style={styles.scrollSpinner} />;
|
||||
}
|
||||
return <ActivityIndicatorIOS style={styles.scrollSpinner} />;
|
||||
},
|
||||
|
||||
renderRow: function(movie: Object) {
|
||||
return (
|
||||
<MovieCell
|
||||
onSelect={() => this.selectMovie(movie)}
|
||||
movie={movie}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var content = this.state.dataSource.getRowCount() === 0 ?
|
||||
<NoMovies
|
||||
filter={this.state.filter}
|
||||
isLoading={this.state.isLoading}
|
||||
/> :
|
||||
<ListView
|
||||
ref="listview"
|
||||
dataSource={this.state.dataSource}
|
||||
renderFooter={this.renderFooter}
|
||||
renderRow={this.renderRow}
|
||||
onEndReached={this.onEndReached}
|
||||
automaticallyAdjustContentInsets={false}
|
||||
keyboardDismissMode="onDrag"
|
||||
keyboardShouldPersistTaps={true}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<SearchBar
|
||||
onSearchChange={this.onSearchChange}
|
||||
isLoading={this.state.isLoading}
|
||||
onFocus={() => this.refs.listview.getScrollResponder().scrollTo(0, 0)}
|
||||
/>
|
||||
<View style={styles.separator} />
|
||||
{content}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var NoMovies = React.createClass({
|
||||
render: function() {
|
||||
var text = '';
|
||||
if (this.props.filter) {
|
||||
text = `No results for “${this.props.filter}”`;
|
||||
} else if (!this.props.isLoading) {
|
||||
// If we're looking at the latest movies, aren't currently loading, and
|
||||
// still have no results, show a message
|
||||
text = 'No movies found';
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.container, styles.centerText]}>
|
||||
<Text style={styles.noMoviesText}>{text}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var SearchBar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.searchBar}>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
onChange={this.props.onSearchChange}
|
||||
placeholder="Search a movie..."
|
||||
onFocus={this.props.onFocus}
|
||||
style={styles.searchBarInput}
|
||||
/>
|
||||
<ActivityIndicatorIOS
|
||||
animating={this.props.isLoading}
|
||||
style={styles.spinner}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
centerText: {
|
||||
alignItems: 'center',
|
||||
},
|
||||
noMoviesText: {
|
||||
marginTop: 80,
|
||||
color: '#888888',
|
||||
},
|
||||
searchBar: {
|
||||
marginTop: 64,
|
||||
padding: 3,
|
||||
paddingLeft: 8,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
searchBarInput: {
|
||||
fontSize: 15,
|
||||
flex: 1,
|
||||
height: 30,
|
||||
},
|
||||
separator: {
|
||||
height: 1,
|
||||
backgroundColor: '#eeeeee',
|
||||
},
|
||||
spinner: {
|
||||
width: 30,
|
||||
},
|
||||
scrollSpinner: {
|
||||
marginVertical: 20,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = SearchScreen;
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
jest.dontMock('../getImageSource');
|
||||
|
||||
var getImageSource = require('../getImageSource');
|
||||
|
||||
describe('getImageSource', () => {
|
||||
it('returns null for invalid input', () => {
|
||||
expect(getImageSource().uri).toBe(null);
|
||||
});
|
||||
|
||||
it('returns a movie thumbnail', () => {
|
||||
var uri = 'https://facebook.com';
|
||||
var source = {
|
||||
posters: {
|
||||
thumbnail: uri,
|
||||
},
|
||||
};
|
||||
expect(getImageSource(source).uri).toBe(uri);
|
||||
});
|
||||
|
||||
it('returns a movie thumbnail with kind', () => {
|
||||
var uri = 'https://facebook.com?tmb';
|
||||
var source = {
|
||||
posters: {
|
||||
thumbnail: uri,
|
||||
},
|
||||
};
|
||||
expect(getImageSource(source, 'kind').uri).toBe(
|
||||
'https://facebook.com?kind'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
function getImageSource(movie: Object, kind: ?string): {uri: ?string} {
|
||||
var uri = movie && movie.posters ? movie.posters.thumbnail : null;
|
||||
if (uri && kind) {
|
||||
uri = uri.replace('tmb', kind);
|
||||
}
|
||||
return { uri };
|
||||
}
|
||||
|
||||
module.exports = getImageSource;
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
} = React;
|
||||
|
||||
var MAX_VALUE = 200;
|
||||
|
||||
function getStyleFromScore(score: number): {color: string} {
|
||||
if (score < 0) {
|
||||
return styles.noScore;
|
||||
}
|
||||
|
||||
var normalizedScore = Math.round((score / 100) * MAX_VALUE);
|
||||
return {
|
||||
color: 'rgb(' +
|
||||
(MAX_VALUE - normalizedScore) + ', ' +
|
||||
normalizedScore + ', ' +
|
||||
0 +
|
||||
')'
|
||||
};
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
noScore: {
|
||||
color: '#999999',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = getStyleFromScore;
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
function getTextFromScore(score: number): string {
|
||||
return score > 0 ? score + '%' : 'N/A';
|
||||
}
|
||||
|
||||
module.exports = getTextFromScore;
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
@end
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "RCTRootView.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
NSURL *jsCodeLocation;
|
||||
RCTRootView *rootView = [[RCTRootView alloc] init];
|
||||
|
||||
// Loading JavaScript code - uncomment the one you want.
|
||||
|
||||
// OPTION 1
|
||||
// Load from development server. Start the server from the repository root:
|
||||
//
|
||||
// $ npm start
|
||||
//
|
||||
// To run on device, change `localhost` to the IP address of your computer, and make sure your computer and
|
||||
// iOS device are on the same Wi-Fi network.
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/TicTacToe/TicTacToeApp.includeRequire.runModule.bundle"];
|
||||
|
||||
// OPTION 2
|
||||
// Load from pre-bundled file on disk. To re-generate the static bundle, run
|
||||
//
|
||||
// $ curl http://localhost:8081/Examples/TicTacToe/TicTacToeApp.includeRequire.runModule.bundle -o main.jsbundle
|
||||
//
|
||||
// and uncomment the next following line
|
||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
|
||||
rootView.scriptURL = jsCodeLocation;
|
||||
rootView.moduleName = @"TicTacToeApp";
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [[UIViewController alloc] init];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
||||
<rect key="frame" x="20" y="439" width="441" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="TicTacToe" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,389 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1341803E1AA91802003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341803D1AA917ED003F314A /* libRCTImage.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
58C572501AA6229900CDF9C8 /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C572471AA6224300CDF9C8 /* libReactKit.a */; };
|
||||
58C572511AA6229D00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5724D1AA6224400CDF9C8 /* libRCTText.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
1341803C1AA917ED003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134180381AA917ED003F314A /* RCTImage.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
|
||||
remoteInfo = RCTImage;
|
||||
};
|
||||
58C572461AA6224300CDF9C8 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
||||
remoteInfo = ReactKit;
|
||||
};
|
||||
58C5724C1AA6224400CDF9C8 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
|
||||
remoteInfo = RCTText;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
134180381AA917ED003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* TicTacToe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TicTacToe.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
||||
587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1341803E1AA91802003F314A /* libRCTImage.a in Frameworks */,
|
||||
58C572501AA6229900CDF9C8 /* libReactKit.a in Frameworks */,
|
||||
58C572511AA6229D00CDF9C8 /* libRCTText.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
134180391AA917ED003F314A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1341803D1AA917ED003F314A /* libRCTImage.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* TicTacToe */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = TicTacToe;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58C572071AA6126D00CDF9C8 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134180381AA917ED003F314A /* RCTImage.xcodeproj */,
|
||||
587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */,
|
||||
587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58C572411AA6224300CDF9C8 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58C572471AA6224300CDF9C8 /* libReactKit.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58C572481AA6224300CDF9C8 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
58C5724D1AA6224400CDF9C8 /* libRCTText.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* TicTacToe */,
|
||||
58C572071AA6126D00CDF9C8 /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* TicTacToe.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* TicTacToe */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "TicTacToe" */;
|
||||
buildPhases = (
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = TicTacToe;
|
||||
productName = "Hello World";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* TicTacToe.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 134180391AA917ED003F314A /* Products */;
|
||||
ProjectRef = 134180381AA917ED003F314A /* RCTImage.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 58C572481AA6224300CDF9C8 /* Products */;
|
||||
ProjectRef = 587650DA1A9EB0DB008B8F17 /* RCTText.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 58C572411AA6224300CDF9C8 /* Products */;
|
||||
ProjectRef = 587650E31A9EB0DF008B8F17 /* ReactKit.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* TicTacToe */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
1341803D1AA917ED003F314A /* libRCTImage.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTImage.a;
|
||||
remoteRef = 1341803C1AA917ED003F314A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
58C572471AA6224300CDF9C8 /* libReactKit.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReactKit.a;
|
||||
remoteRef = 58C572461AA6224300CDF9C8 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
58C5724D1AA6224400CDF9C8 /* libRCTText.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTText.a;
|
||||
remoteRef = 58C5724C1AA6224400CDF9C8 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = TicTacToe;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = TicTacToe;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "TicTacToe" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "TicTacToe" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0610"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "TicTacToe.app"
|
||||
BlueprintName = "TicTacToe"
|
||||
ReferencedContainer = "container:TicTacToe.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "TicTacToe.app"
|
||||
BlueprintName = "TicTacToe"
|
||||
ReferencedContainer = "container:TicTacToe.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "TicTacToe.app"
|
||||
BlueprintName = "TicTacToe"
|
||||
ReferencedContainer = "container:TicTacToe.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "TicTacToe.app"
|
||||
BlueprintName = "TicTacToe"
|
||||
ReferencedContainer = "container:TicTacToe.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,322 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule TicTacToeApp
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AppRegistry,
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
class Board {
|
||||
grid: Array<Array<number>>;
|
||||
turn: number;
|
||||
|
||||
constructor() {
|
||||
var size = 3;
|
||||
var grid = Array(size);
|
||||
for (var i = 0; i < size; i++) {
|
||||
var row = Array(size);
|
||||
for (var j = 0; j < size; j++) {
|
||||
row[j] = 0;
|
||||
}
|
||||
grid[i] = row;
|
||||
}
|
||||
this.grid = grid;
|
||||
|
||||
this.turn = 1;
|
||||
}
|
||||
|
||||
mark(row: number, col: number, player: number): Board {
|
||||
this.grid[row][col] = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
hasMark(row: number, col: number): boolean {
|
||||
return this.grid[row][col] !== 0;
|
||||
}
|
||||
|
||||
winner(): ?number {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
if (this.grid[i][0] !== 0 && this.grid[i][0] === this.grid[i][1] &&
|
||||
this.grid[i][0] === this.grid[i][2]) {
|
||||
return this.grid[i][0];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
if (this.grid[0][i] !== 0 && this.grid[0][i] === this.grid[1][i] &&
|
||||
this.grid[0][i] === this.grid[2][i]) {
|
||||
return this.grid[0][i];
|
||||
}
|
||||
}
|
||||
|
||||
if (this.grid[0][0] !== 0 && this.grid[0][0] === this.grid[1][1] &&
|
||||
this.grid[0][0] === this.grid[2][2]) {
|
||||
return this.grid[0][0];
|
||||
}
|
||||
|
||||
if (this.grid[0][2] !== 0 && this.grid[0][2] === this.grid[1][1] &&
|
||||
this.grid[0][2] === this.grid[2][0]) {
|
||||
return this.grid[0][2];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
tie(): boolean {
|
||||
for (var i = 0; i < 3; i++) {
|
||||
for (var j = 0; j < 3; j++) {
|
||||
if (this.grid[i][j] === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.winner() === null;
|
||||
}
|
||||
}
|
||||
|
||||
var Cell = React.createClass({
|
||||
cellStyle() {
|
||||
switch (this.props.player) {
|
||||
case 1:
|
||||
return styles.cellX;
|
||||
case 2:
|
||||
return styles.cellO;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
textStyle() {
|
||||
switch (this.props.player) {
|
||||
case 1:
|
||||
return styles.cellTextX;
|
||||
case 2:
|
||||
return styles.cellTextO;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
textContents() {
|
||||
switch (this.props.player) {
|
||||
case 1:
|
||||
return 'X';
|
||||
case 2:
|
||||
return 'O';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
imageContents() {
|
||||
switch (this.props.player) {
|
||||
case 1:
|
||||
return 'http://www.picgifs.com/alphabets/alphabets/children-5/alphabets-children-5-277623.gif';
|
||||
case 2:
|
||||
return 'http://www.picgifs.com/alphabets/alphabets/children-5/alphabets-children-5-730492.gif';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TouchableHighlight
|
||||
onPress={this.props.onPress}
|
||||
underlayColor="transparent"
|
||||
activeOpacity={0.5}>
|
||||
<View style={[styles.cell, this.cellStyle()]}>
|
||||
<Image source={{uri: this.imageContents()}} />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var GameEndOverlay = React.createClass({
|
||||
render() {
|
||||
var board = this.props.board;
|
||||
|
||||
var tie = board.tie();
|
||||
var winner = board.winner();
|
||||
if (!winner && !tie) {
|
||||
return <View />;
|
||||
}
|
||||
|
||||
var message;
|
||||
if (tie) {
|
||||
message = 'It\'s a tie!';
|
||||
} else {
|
||||
message = (winner === 1 ? 'X' : 'O') + ' wins!';
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.overlay}>
|
||||
<Text style={styles.overlayMessage}>{message}</Text>
|
||||
<TouchableHighlight
|
||||
onPress={this.props.onRestart}
|
||||
underlayColor="transparent"
|
||||
activeOpacity={0.5}>
|
||||
<View style={styles.newGame}>
|
||||
<Text style={styles.newGameText}>New Game</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TicTacToeApp = React.createClass({
|
||||
getInitialState() {
|
||||
return { board: new Board(), player: 1 };
|
||||
},
|
||||
|
||||
restartGame() {
|
||||
this.setState(this.getInitialState());
|
||||
},
|
||||
|
||||
nextPlayer(): number {
|
||||
return this.state.player === 1 ? 2 : 1;
|
||||
},
|
||||
|
||||
handleCellPress(row: number, col: number) {
|
||||
if (this.state.board.hasMark(row, col)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
board: this.state.board.mark(row, col, this.state.player),
|
||||
player: this.nextPlayer(),
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
var rows = this.state.board.grid.map((cells, row) =>
|
||||
<View key={'row' + row} style={styles.row}>
|
||||
{cells.map((player, col) =>
|
||||
<Cell
|
||||
key={'cell' + col}
|
||||
player={player}
|
||||
onPress={this.handleCellPress.bind(this, row, col)}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>EXTREME T3</Text>
|
||||
<View style={styles.board}>
|
||||
{rows}
|
||||
</View>
|
||||
<GameEndOverlay
|
||||
board={this.state.board}
|
||||
onRestart={this.restartGame}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'white'
|
||||
},
|
||||
title: {
|
||||
fontFamily: 'Chalkduster',
|
||||
fontSize: 39,
|
||||
marginBottom: 20,
|
||||
},
|
||||
board: {
|
||||
padding: 5,
|
||||
backgroundColor: '#47525d',
|
||||
borderRadius: 10,
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
|
||||
// CELL
|
||||
|
||||
cell: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: 5,
|
||||
backgroundColor: '#7b8994',
|
||||
margin: 5,
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
cellX: {
|
||||
backgroundColor: '#72d0eb',
|
||||
},
|
||||
cellO: {
|
||||
backgroundColor: '#7ebd26',
|
||||
},
|
||||
|
||||
// CELL TEXT
|
||||
|
||||
cellText: {
|
||||
borderRadius: 5,
|
||||
fontSize: 50,
|
||||
fontFamily: 'AvenirNext-Bold',
|
||||
},
|
||||
cellTextX: {
|
||||
color: '#19a9e5',
|
||||
},
|
||||
cellTextO: {
|
||||
color: '#b9dc2f',
|
||||
},
|
||||
|
||||
// GAME OVER
|
||||
|
||||
overlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
backgroundColor: 'rgba(221, 221, 221, 0.5)',
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
overlayMessage: {
|
||||
fontSize: 40,
|
||||
marginBottom: 20,
|
||||
marginLeft: 20,
|
||||
marginRight: 20,
|
||||
fontFamily: 'AvenirNext-DemiBold',
|
||||
textAlign: 'center',
|
||||
},
|
||||
newGame: {
|
||||
backgroundColor: '#887766',
|
||||
padding: 20,
|
||||
borderRadius: 5,
|
||||
},
|
||||
newGameText: {
|
||||
color: 'white',
|
||||
fontSize: 20,
|
||||
fontFamily: 'AvenirNext-DemiBold',
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('TicTacToeApp', () => TicTacToeApp);
|
||||
|
||||
module.exports = TicTacToeApp;
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ActivityIndicatorExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ActivityIndicatorIOS,
|
||||
StyleSheet,
|
||||
TimerMixin,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var ToggleAnimatingActivityIndicator = React.createClass({
|
||||
mixins: [TimerMixin],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
animating: true,
|
||||
};
|
||||
},
|
||||
|
||||
setToggleTimeout: function() {
|
||||
this.setTimeout(
|
||||
() => {
|
||||
this.setState({animating: !this.state.animating});
|
||||
this.setToggleTimeout();
|
||||
},
|
||||
1200
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.setToggleTimeout();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<ActivityIndicatorIOS
|
||||
animating={this.state.animating}
|
||||
style={[styles.centering, {height: 80}]}
|
||||
size="large"
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = '<ActivityIndicatorIOS>';
|
||||
exports.description = 'Animated loading indicators.';
|
||||
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Default (small, white)',
|
||||
render: function() {
|
||||
return (
|
||||
<ActivityIndicatorIOS
|
||||
style={[styles.centering, styles.gray, {height: 40}]}
|
||||
color="white"
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Gray',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<ActivityIndicatorIOS
|
||||
style={[styles.centering, {height: 40}]}
|
||||
/>
|
||||
<ActivityIndicatorIOS
|
||||
style={[styles.centering, {backgroundColor: '#eeeeee', height: 40}]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Custom colors',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<ActivityIndicatorIOS color="#0000ff" />
|
||||
<ActivityIndicatorIOS color="#aa00aa" />
|
||||
<ActivityIndicatorIOS color="#aa3300" />
|
||||
<ActivityIndicatorIOS color="#00aa00" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Large',
|
||||
render: function() {
|
||||
return (
|
||||
<ActivityIndicatorIOS
|
||||
style={[styles.centering, styles.gray, {height: 80}]}
|
||||
color="white"
|
||||
size="large"
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Large, custom colors',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<ActivityIndicatorIOS
|
||||
size="large"
|
||||
color="#0000ff"
|
||||
/>
|
||||
<ActivityIndicatorIOS
|
||||
size="large"
|
||||
color="#aa00aa"
|
||||
/>
|
||||
<ActivityIndicatorIOS
|
||||
size="large"
|
||||
color="#aa3300"
|
||||
/>
|
||||
<ActivityIndicatorIOS
|
||||
size="large"
|
||||
color="#00aa00"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Start/stop',
|
||||
render: function() {
|
||||
return <ToggleAnimatingActivityIndicator />;
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
centering: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
gray: {
|
||||
backgroundColor: '#cccccc',
|
||||
},
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
},
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "RCTRootView.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
NSURL *jsCodeLocation;
|
||||
RCTRootView *rootView = [[RCTRootView alloc] init];
|
||||
|
||||
// Loading JavaScript code - uncomment the one you want.
|
||||
|
||||
// OPTION 1
|
||||
// Load from development server. Start the server from the repository root:
|
||||
//
|
||||
// $ npm start
|
||||
//
|
||||
// To run on device, change `localhost` to the IP address of your computer, and make sure your computer and
|
||||
// iOS device are on the same Wi-Fi network.
|
||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.includeRequire.runModule.bundle"];
|
||||
|
||||
// OPTION 2
|
||||
// Load from pre-bundled file on disk. To re-generate the static bundle, run
|
||||
//
|
||||
// $ curl http://localhost:8081/Examples/UIExplorer/UIExplorerApp.includeRequire.runModule.bundle -o main.jsbundle
|
||||
//
|
||||
// and uncomment the next following line
|
||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
|
||||
rootView.scriptURL = jsCodeLocation;
|
||||
rootView.moduleName = @"UIExplorerApp";
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
UIViewController *rootViewController = [[UIViewController alloc] init];
|
||||
rootViewController.view = rootView;
|
||||
self.window.rootViewController = rootViewController;
|
||||
[self.window makeKeyAndVisible];
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Facebook. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
||||
<rect key="frame" x="20" y="439" width="441" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="UIExplorer" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
|
||||
<rect key="frame" x="20" y="140" width="441" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
|
||||
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
|
||||
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
|
||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
||||
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -1,157 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule DatePickerExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
DatePickerIOS,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var DatePickerExample = React.createClass({
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
date: new Date(),
|
||||
timeZoneOffsetInHours: (-1) * (new Date()).getTimezoneOffset() / 60,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
date: this.props.date,
|
||||
timeZoneOffsetInHours: this.props.timeZoneOffsetInHours,
|
||||
};
|
||||
},
|
||||
|
||||
onDateChange: function(date) {
|
||||
this.setState({date: date});
|
||||
},
|
||||
|
||||
onTimezoneChange: function(event) {
|
||||
var offset = parseInt(event.nativeEvent.text, 10);
|
||||
if (isNaN(offset)) {
|
||||
return;
|
||||
}
|
||||
this.setState({timeZoneOffsetInHours: offset});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// Ideally, the timezone input would be a picker rather than a
|
||||
// text input, but we don't have any pickers yet :(
|
||||
return (
|
||||
<View>
|
||||
<WithLabel label="Value:">
|
||||
<Text>{
|
||||
this.state.date.toLocaleDateString() +
|
||||
' ' +
|
||||
this.state.date.toLocaleTimeString()
|
||||
}</Text>
|
||||
</WithLabel>
|
||||
<WithLabel label="Timezone:">
|
||||
<TextInput
|
||||
onChange={this.onTimezoneChange}
|
||||
style={styles.textinput}
|
||||
value={this.state.timeZoneOffsetInHours.toString()}
|
||||
/>
|
||||
<Text> hours from UTC</Text>
|
||||
</WithLabel>
|
||||
<Heading label="Date + time picker" />
|
||||
<DatePickerIOS
|
||||
date={this.state.date}
|
||||
mode="datetime"
|
||||
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
|
||||
onDateChange={this.onDateChange}
|
||||
/>
|
||||
<Heading label="Date picker" />
|
||||
<DatePickerIOS
|
||||
date={this.state.date}
|
||||
mode="date"
|
||||
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
|
||||
onDateChange={this.onDateChange}
|
||||
/>
|
||||
<Heading label="Time picker, 10-minute interval" />
|
||||
<DatePickerIOS
|
||||
date={this.state.date}
|
||||
mode="time"
|
||||
timeZoneOffsetInMinutes={this.state.timeZoneOffsetInHours * 60}
|
||||
onDateChange={this.onDateChange}
|
||||
minuteInterval={10}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var WithLabel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.labelContainer}>
|
||||
<View style={styles.labelView}>
|
||||
<Text style={styles.label}>
|
||||
{this.props.label}
|
||||
</Text>
|
||||
</View>
|
||||
{this.props.children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Heading = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.headingContainer}>
|
||||
<Text style={styles.heading}>
|
||||
{this.props.label}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
exports.title = '<DatePickerIOS>';
|
||||
exports.description = 'Select dates and times using the native UIDatePicker.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: '<DatePickerIOS>',
|
||||
render: function() {
|
||||
return <DatePickerExample />;
|
||||
},
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
textinput: {
|
||||
height: 26,
|
||||
width: 50,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#0f0f0f',
|
||||
padding: 4,
|
||||
fontSize: 13,
|
||||
},
|
||||
labelContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginVertical: 2,
|
||||
},
|
||||
labelView: {
|
||||
marginRight: 10,
|
||||
paddingVertical: 2,
|
||||
},
|
||||
label: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
headingContainer: {
|
||||
padding: 4,
|
||||
backgroundColor: '#f6f7f8',
|
||||
},
|
||||
heading: {
|
||||
fontWeight: 'bold',
|
||||
fontSize: 14,
|
||||
},
|
||||
});
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ExpandingTextExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ExpandingText
|
||||
} = React;
|
||||
|
||||
var LOREM = 'Lorem ipsum dolor sit amet, mea adipisci inimicus ex, paulo essent bonorum et ius, rebum deserunt mediocritatem ius ei.';
|
||||
|
||||
exports.title = '<ExpandingText>';
|
||||
exports.description = 'Base component for rendering text that is truncated and can be expanded upon tap.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Expanding text (truncLength=20)',
|
||||
description: 'Setting the truncLength prop will cause the text to truncate to that character length',
|
||||
render: function() {
|
||||
return <ExpandingText truncLength={20} text={LOREM} />;
|
||||
}
|
||||
}, {
|
||||
title: 'Expanding text (truncLength=80)',
|
||||
description: 'The higher the truncLength the more characters that will be shown by default',
|
||||
render: function() {
|
||||
return <ExpandingText truncLength={80} text={LOREM + LOREM} />;
|
||||
}
|
||||
}, {
|
||||
title: 'Expanding text with custom style',
|
||||
description: 'You can style the text within the ExpandingText component',
|
||||
render: function() {
|
||||
return (
|
||||
<ExpandingText
|
||||
textStyle={{fontFamily: 'Verdana'}}
|
||||
truncLength={80}
|
||||
text={LOREM + LOREM}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}, {
|
||||
title: 'See More button with custom style' ,
|
||||
description: 'You can also style just the See More button',
|
||||
render: function() {
|
||||
return (
|
||||
<ExpandingText
|
||||
seeMoreStyle={{color: 'red'}}
|
||||
truncLength={80}
|
||||
text={LOREM}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}];
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule GeolocationExample
|
||||
*/
|
||||
/* eslint no-console: 0 */
|
||||
'use strict';
|
||||
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'Geolocation';
|
||||
exports.description = 'Examples of using the Geolocation API.';
|
||||
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'navigator.geolocation',
|
||||
render: function() {
|
||||
return <GeolocationExample />;
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
var GeolocationExample = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
initialPosition: 'unknown',
|
||||
lastPosition: 'unknown',
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(initialPosition) => this.setState({initialPosition}),
|
||||
(error) => console.error(error)
|
||||
);
|
||||
this.watchID = navigator.geolocation.watchPosition((lastPosition) => {
|
||||
this.setState({lastPosition});
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
navigator.geolocation.clearWatch(this.watchID);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
<Text style={styles.title}>Initial position: </Text>
|
||||
{JSON.stringify(this.state.initialPosition)}
|
||||
</Text>
|
||||
<Text>
|
||||
<Text style={styles.title}>Current position: </Text>
|
||||
{JSON.stringify(this.state.lastPosition)}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
title: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ImageCapInsetsExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ix,
|
||||
} = React;
|
||||
|
||||
var ImageCapInsetsExample = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.background}>
|
||||
<Text>
|
||||
capInsets: none
|
||||
</Text>
|
||||
<Image
|
||||
source={ix('story-background')}
|
||||
style={styles.storyBackground}
|
||||
capInsets={{left: 0, right: 0, bottom: 0, top: 0}}
|
||||
/>
|
||||
</View>
|
||||
<View style={[styles.background, {paddingTop: 10}]}>
|
||||
<Text>
|
||||
capInsets: 15
|
||||
</Text>
|
||||
<Image
|
||||
source={ix('story-background')}
|
||||
style={styles.storyBackground}
|
||||
capInsets={{left: 15, right: 15, bottom: 15, top: 15}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
background: {
|
||||
backgroundColor: '#F6F6F6',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
storyBackground: {
|
||||
width: 250,
|
||||
height: 150,
|
||||
borderWidth: 1,
|
||||
resizeMode: Image.resizeMode.stretch,
|
||||
},
|
||||
text: {
|
||||
fontSize: 13.5,
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ImageCapInsetsExample;
|
||||
@@ -1,305 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ImageExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ix,
|
||||
} = React;
|
||||
|
||||
var ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = '<Image>';
|
||||
exports.description = 'Base component for displaying different types of images.';
|
||||
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Plain Network Image',
|
||||
description: 'If the `source` prop `uri` property is prefixed with ' +
|
||||
'"http", then it will be downloaded from the network.',
|
||||
render: function() {
|
||||
return (
|
||||
<Image
|
||||
source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}}
|
||||
style={styles.base}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Plain Static Image',
|
||||
description: 'Static assets must be referenced with the `ix` wrapper and ' +
|
||||
'located in the app bundle.',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image source={ix('uie_thumb_normal')} style={styles.icon} />
|
||||
<Image source={ix('uie_thumb_selected')} style={styles.icon} />
|
||||
<Image source={ix('uie_comment_normal')} style={styles.icon} />
|
||||
<Image source={ix('uie_comment_highlighted')} style={styles.icon} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Border Color',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[
|
||||
styles.base,
|
||||
styles.background,
|
||||
{borderWidth: 3, borderColor: '#f099f0'}
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Border Width',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={smallImage}
|
||||
style={[
|
||||
styles.base,
|
||||
styles.background,
|
||||
{borderWidth: 5, borderColor: '#f099f0'}
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Border Radius',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
style={[styles.base, styles.background, {borderRadius: 5}]}
|
||||
source={smallImage}
|
||||
/>
|
||||
<Image
|
||||
style={[
|
||||
styles.base,
|
||||
styles.background,
|
||||
styles.leftMargin,
|
||||
{borderRadius: 19}
|
||||
]}
|
||||
source={smallImage}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Background Color',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image source={smallImage} style={styles.base} />
|
||||
<Image
|
||||
style={[
|
||||
styles.base,
|
||||
styles.leftMargin,
|
||||
{backgroundColor: 'rgba(0, 0, 100, 0.25)'}
|
||||
]}
|
||||
source={smallImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {backgroundColor: 'red'}]}
|
||||
source={smallImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {backgroundColor: 'black'}]}
|
||||
source={smallImage}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Opacity',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
style={[styles.base, {opacity: 1}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.8}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.6}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.4}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0.2}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
<Image
|
||||
style={[styles.base, styles.leftMargin, {opacity: 0}]}
|
||||
source={fullImage}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Nesting',
|
||||
render: function() {
|
||||
return (
|
||||
<Image
|
||||
style={{width: 60, height: 60, backgroundColor: 'transparent'}}
|
||||
source={fullImage}>
|
||||
<Text style={styles.nestedText}>
|
||||
React
|
||||
</Text>
|
||||
</Image>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Tint Color',
|
||||
description: 'The `tintColor` style prop changes all the non-alpha ' +
|
||||
'pixels to the tint color.',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<Image
|
||||
source={ix('uie_thumb_normal')}
|
||||
style={[styles.icon, {tintColor: 'blue' }]}
|
||||
/>
|
||||
<Image
|
||||
source={ix('uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: 'green' }]}
|
||||
/>
|
||||
<Image
|
||||
source={ix('uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: 'red' }]}
|
||||
/>
|
||||
<Image
|
||||
source={ix('uie_thumb_normal')}
|
||||
style={[styles.icon, styles.leftMargin, {tintColor: 'black' }]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Resize Mode',
|
||||
description: 'The `resizeMode` style prop controls how the image is ' +
|
||||
'rendered within the frame.',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.horizontal}>
|
||||
<View>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Contain
|
||||
</Text>
|
||||
<Image
|
||||
style={[
|
||||
styles.resizeMode,
|
||||
{resizeMode: Image.resizeMode.contain}
|
||||
]}
|
||||
source={fullImage}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Cover
|
||||
</Text>
|
||||
<Image
|
||||
style={[
|
||||
styles.resizeMode,
|
||||
{resizeMode: Image.resizeMode.cover}
|
||||
]}
|
||||
source={fullImage}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.leftMargin}>
|
||||
<Text style={[styles.resizeModeText]}>
|
||||
Stretch
|
||||
</Text>
|
||||
<Image
|
||||
style={[
|
||||
styles.resizeMode,
|
||||
{resizeMode: Image.resizeMode.stretch}
|
||||
]}
|
||||
source={fullImage}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Cap Insets',
|
||||
description:
|
||||
'When the image is resized, the corners of the size specified ' +
|
||||
'by capInsets will stay a fixed size, but the center content and ' +
|
||||
'borders of the image will be stretched. This is useful for creating ' +
|
||||
'resizable rounded buttons, shadows, and other resizable assets.',
|
||||
render: function() {
|
||||
return <ImageCapInsetsExample />;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
var fullImage = {uri: 'http://facebook.github.io/react/img/logo_og.png'};
|
||||
var smallImage = {uri: 'http://facebook.github.io/react/img/logo_small.png'};
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
base: {
|
||||
width: 38,
|
||||
height: 38,
|
||||
},
|
||||
leftMargin: {
|
||||
marginLeft: 10,
|
||||
},
|
||||
background: {
|
||||
backgroundColor: '#222222'
|
||||
},
|
||||
nestedText: {
|
||||
marginLeft: 12,
|
||||
marginTop: 20,
|
||||
backgroundColor: 'transparent',
|
||||
color: 'white'
|
||||
},
|
||||
resizeMode: {
|
||||
width: 90,
|
||||
height: 60,
|
||||
borderWidth: 0.5,
|
||||
borderColor: 'black'
|
||||
},
|
||||
resizeModeText: {
|
||||
fontSize: 11,
|
||||
marginBottom: 3,
|
||||
},
|
||||
icon: {
|
||||
width: 15,
|
||||
height: 15,
|
||||
},
|
||||
horizontal: {
|
||||
flexDirection: 'row',
|
||||
}
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-1.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-2.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-3.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-5.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "uie_icon@2x-4.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "story-background.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x",
|
||||
"filename" : "story-background@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 657 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x",
|
||||
"filename" : "uie_comment_highlighted@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 403 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x",
|
||||
"filename" : "uie_comment_normal@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 420 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x",
|
||||
"filename" : "uie_thumb_normal@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 850 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x",
|
||||
"filename" : "uie_thumb_selected@2x.png"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.facebook.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation, otherwise it is going to *fail silently*!</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,145 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule LayoutExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var Circle = React.createClass({
|
||||
render: function() {
|
||||
var size = this.props.size || 20;
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
borderRadius: size / 2,
|
||||
backgroundColor: '#527fe4',
|
||||
width: size,
|
||||
height: size,
|
||||
margin: 1,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var CircleBlock = React.createClass({
|
||||
render: function() {
|
||||
var circleStyle = {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '#f6f7f8',
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#d6d7da',
|
||||
marginBottom: 2,
|
||||
};
|
||||
return (
|
||||
<View style={[circleStyle, this.props.style]}>
|
||||
{this.props.children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var LayoutExample = React.createClass({
|
||||
statics: {
|
||||
title: 'Layout - Flexbox',
|
||||
description: 'Examples of using the flexbox API to layout views.'
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title={this.props.navigator ? null : 'Layout'}>
|
||||
<UIExplorerBlock title="Flex Direction">
|
||||
<Text>row</Text>
|
||||
<CircleBlock style={{flexDirection: 'row'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
<Text>column</Text>
|
||||
<CircleBlock style={{flexDirection: 'column'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
<View style={[styles.overlay, {position: 'absolute', top: 15, left: 160}]}>
|
||||
<Text>{'top: 15, left: 160'}</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
|
||||
<UIExplorerBlock title="Justify Content - Main Direction">
|
||||
<Text>flex-start</Text>
|
||||
<CircleBlock style={{justifyContent: 'flex-start'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
<Text>center</Text>
|
||||
<CircleBlock style={{justifyContent: 'center'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
<Text>flex-end</Text>
|
||||
<CircleBlock style={{justifyContent: 'flex-end'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
<Text>space-between</Text>
|
||||
<CircleBlock style={{justifyContent: 'space-between'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
<Text>space-around</Text>
|
||||
<CircleBlock style={{justifyContent: 'space-around'}}>
|
||||
<Circle /><Circle /><Circle /><Circle /><Circle />
|
||||
</CircleBlock>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Align Items - Other Direction">
|
||||
<Text>flex-start</Text>
|
||||
<CircleBlock style={{alignItems: 'flex-start', height: 30}}>
|
||||
<Circle size={15} /><Circle size={10} /><Circle size={20} />
|
||||
<Circle size={17} /><Circle size={12} /><Circle size={15} />
|
||||
<Circle size={10} /><Circle size={20} /><Circle size={17} />
|
||||
<Circle size={12} /><Circle size={15} /><Circle size={10} />
|
||||
<Circle size={20} /><Circle size={17} /><Circle size={12} />
|
||||
<Circle size={15} /><Circle size={8} />
|
||||
</CircleBlock>
|
||||
<Text>center</Text>
|
||||
<CircleBlock style={{alignItems: 'center', height: 30}}>
|
||||
<Circle size={15} /><Circle size={10} /><Circle size={20} />
|
||||
<Circle size={17} /><Circle size={12} /><Circle size={15} />
|
||||
<Circle size={10} /><Circle size={20} /><Circle size={17} />
|
||||
<Circle size={12} /><Circle size={15} /><Circle size={10} />
|
||||
<Circle size={20} /><Circle size={17} /><Circle size={12} />
|
||||
<Circle size={15} /><Circle size={8} />
|
||||
</CircleBlock>
|
||||
<Text>flex-end</Text>
|
||||
<CircleBlock style={{alignItems: 'flex-end', height: 30}}>
|
||||
<Circle size={15} /><Circle size={10} /><Circle size={20} />
|
||||
<Circle size={17} /><Circle size={12} /><Circle size={15} />
|
||||
<Circle size={10} /><Circle size={20} /><Circle size={17} />
|
||||
<Circle size={12} /><Circle size={15} /><Circle size={10} />
|
||||
<Circle size={20} /><Circle size={17} /><Circle size={12} />
|
||||
<Circle size={15} /><Circle size={8} />
|
||||
</CircleBlock>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Flex Wrap">
|
||||
<CircleBlock style={{flexWrap: 'wrap'}}>
|
||||
{'oooooooooooooooo'.split('').map((char, i) => <Circle key={i} />)}
|
||||
</CircleBlock>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
overlay: {
|
||||
backgroundColor: '#aaccff',
|
||||
borderRadius: 10,
|
||||
borderWidth: 0.5,
|
||||
opacity: 0.5,
|
||||
padding: 5,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = LayoutExample;
|
||||
@@ -1,249 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ListViewPagingExample
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
LayoutAnimation,
|
||||
ListView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var PAGE_SIZE = 4;
|
||||
var THUMB_URLS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png'];
|
||||
var NUM_SECTIONS = 100;
|
||||
var NUM_ROWS_PER_SECTION = 10;
|
||||
|
||||
var Thumb = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {thumbIndex: this._getThumbIdx(), dir: 'row'};
|
||||
},
|
||||
_getThumbIdx: function() {
|
||||
return Math.floor(Math.random() * THUMB_URLS.length);
|
||||
},
|
||||
_onPressThumb: function() {
|
||||
var config = layoutAnimationConfigs[this.state.thumbIndex % layoutAnimationConfigs.length];
|
||||
LayoutAnimation.configureNext(config);
|
||||
this.setState({
|
||||
thumbIndex: this._getThumbIdx(),
|
||||
dir: this.state.dir === 'row' ? 'column' : 'row',
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<TouchableOpacity onPress={this._onPressThumb}>
|
||||
<View style={[styles.buttonContents, {flexDirection: this.state.dir}]}>
|
||||
<Image style={styles.img} source={{uri: THUMB_URLS[this.state.thumbIndex]}} />
|
||||
<Image style={styles.img} source={{uri: THUMB_URLS[this.state.thumbIndex]}} />
|
||||
<Image style={styles.img} source={{uri: THUMB_URLS[this.state.thumbIndex]}} />
|
||||
{this.state.dir === 'column' ?
|
||||
<Text>
|
||||
Oooo, look at this new text! So awesome it may just be crazy.
|
||||
Let me keep typing here so it wraps at least one line.
|
||||
</Text> :
|
||||
<Text />
|
||||
}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ListViewPagingExample = React.createClass({
|
||||
statics: {
|
||||
title: '<ListView> - Paging',
|
||||
description: 'Floating headers & layout animations.'
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var getSectionData = (dataBlob, sectionID) => {
|
||||
return dataBlob[sectionID];
|
||||
};
|
||||
var getRowData = (dataBlob, sectionID, rowID) => {
|
||||
return dataBlob[rowID];
|
||||
};
|
||||
|
||||
var dataSource = new ListView.DataSource({
|
||||
getRowData: getRowData,
|
||||
getSectionHeaderData: getSectionData,
|
||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
||||
sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
|
||||
});
|
||||
|
||||
var dataBlob = {};
|
||||
var sectionIDs = [];
|
||||
var rowIDs = [];
|
||||
for (var ii = 0; ii < NUM_SECTIONS; ii++) {
|
||||
var sectionName = 'Section ' + ii;
|
||||
sectionIDs.push(sectionName);
|
||||
dataBlob[sectionName] = sectionName;
|
||||
rowIDs[ii] = [];
|
||||
|
||||
for (var jj = 0; jj < NUM_ROWS_PER_SECTION; jj++) {
|
||||
var rowName = 'S' + ii + ', R' + jj;
|
||||
rowIDs[ii].push(rowName);
|
||||
dataBlob[rowName] = rowName;
|
||||
}
|
||||
}
|
||||
return {
|
||||
dataSource: dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs),
|
||||
headerPressCount: 0,
|
||||
};
|
||||
},
|
||||
|
||||
renderRow: function(rowData, sectionID, rowID) {
|
||||
return (<Thumb text={rowData}/>);
|
||||
},
|
||||
|
||||
renderSectionHeader: function(sectionData, sectionID) {
|
||||
return (
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.text}>
|
||||
{sectionData}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
renderHeader: function() {
|
||||
var headerLikeText = this.state.headerPressCount % 2 ?
|
||||
<View><Text style={styles.text}>1 Like</Text></View> :
|
||||
null;
|
||||
return (
|
||||
<TouchableOpacity onPress={this._onPressHeader}>
|
||||
<View style={styles.header}>
|
||||
{headerLikeText}
|
||||
<View>
|
||||
<Text style={styles.text}>
|
||||
Table Header (click me)
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
},
|
||||
|
||||
renderFooter: function() {
|
||||
return (
|
||||
<View style={styles.header}>
|
||||
<Text onPress={() => console.log('Footer!')} style={styles.text}>
|
||||
Table Footer
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<ListView
|
||||
style={styles.listview}
|
||||
dataSource={this.state.dataSource}
|
||||
onChangeVisibleRows={(visibleRows, changedRows) => console.log({visibleRows, changedRows})}
|
||||
renderHeader={this.renderHeader}
|
||||
renderFooter={this.renderFooter}
|
||||
renderSectionHeader={this.renderSectionHeader}
|
||||
renderRow={this.renderRow}
|
||||
initialListSize={10}
|
||||
pageSize={PAGE_SIZE}
|
||||
scrollRenderAheadDistance={2000}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
_onPressHeader: function() {
|
||||
var config = layoutAnimationConfigs[Math.floor(this.state.headerPressCount / 2) % layoutAnimationConfigs.length];
|
||||
LayoutAnimation.configureNext(config);
|
||||
this.setState({headerPressCount: this.state.headerPressCount + 1});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
listview: {
|
||||
backgroundColor: '#B0C4DE',
|
||||
},
|
||||
header: {
|
||||
height: 40,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#3B5998',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
text: {
|
||||
color: 'white',
|
||||
paddingHorizontal: 8,
|
||||
},
|
||||
rowText: {
|
||||
color: '#888888',
|
||||
},
|
||||
thumbText: {
|
||||
fontSize: 20,
|
||||
color: '#888888',
|
||||
},
|
||||
buttonContents: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginHorizontal: 5,
|
||||
marginVertical: 3,
|
||||
padding: 5,
|
||||
backgroundColor: '#EAEAEA',
|
||||
borderRadius: 3,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
img: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
marginHorizontal: 10,
|
||||
},
|
||||
section: {
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'flex-start',
|
||||
padding: 6,
|
||||
backgroundColor: '#5890ff',
|
||||
},
|
||||
});
|
||||
|
||||
var animations = {
|
||||
layout: {
|
||||
spring: {
|
||||
duration: 0.75,
|
||||
create: {
|
||||
duration: 0.3,
|
||||
type: LayoutAnimation.Types.easeInEaseOut,
|
||||
property: LayoutAnimation.Properties.opacity,
|
||||
},
|
||||
update: {
|
||||
type: LayoutAnimation.Types.spring,
|
||||
springDamping: 0.4,
|
||||
},
|
||||
},
|
||||
easeInEaseOut: {
|
||||
duration: 0.3,
|
||||
create: {
|
||||
type: LayoutAnimation.Types.easeInEaseOut,
|
||||
property: LayoutAnimation.Properties.scaleXY,
|
||||
},
|
||||
update: {
|
||||
delay: 0.1,
|
||||
type: LayoutAnimation.Types.easeInEaseOut,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var layoutAnimationConfigs = [
|
||||
animations.layout.spring,
|
||||
animations.layout.easeInEaseOut,
|
||||
];
|
||||
|
||||
module.exports = ListViewPagingExample;
|
||||
@@ -1,120 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @provides ListViewSimpleExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Image,
|
||||
ListView,
|
||||
TouchableHighlight,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var ListViewSimpleExample = React.createClass({
|
||||
statics: {
|
||||
title: '<ListView> - Simple',
|
||||
description: 'Performant, scrollable list of data.'
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
|
||||
return {
|
||||
dataSource: ds.cloneWithRows(this._genRows({})),
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._pressData = {};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage
|
||||
title={this.props.navigator ? null : '<ListView> - Simple'}
|
||||
noSpacer={true}
|
||||
noScroll={true}>
|
||||
<ListView
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this._renderRow}
|
||||
/>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
|
||||
_renderRow: function(rowData, sectionID, rowID) {
|
||||
var rowHash = Math.abs(hashCode(rowData));
|
||||
var imgSource = {
|
||||
uri: THUMB_URLS[rowHash % THUMB_URLS.length],
|
||||
};
|
||||
return (
|
||||
<TouchableHighlight onPress={() => this._pressRow(rowID)}>
|
||||
<View>
|
||||
<View style={styles.row}>
|
||||
<Image style={styles.thumb} source={imgSource} />
|
||||
<Text style={styles.text}>
|
||||
{rowData + ' - ' + LOREM_IPSUM.substr(0, rowHash % 301 + 10)}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.separator} />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
},
|
||||
|
||||
_genRows: function(pressData) {
|
||||
var dataBlob = [];
|
||||
for (var ii = 0; ii < 100; ii++) {
|
||||
var pressedText = pressData[ii] ? ' (pressed)' : '';
|
||||
dataBlob.push('Row ' + ii + pressedText);
|
||||
}
|
||||
return dataBlob;
|
||||
},
|
||||
|
||||
_pressRow: function(rowID) {
|
||||
this._pressData[rowID] = !this._pressData[rowID];
|
||||
this.setState({dataSource: this.state.dataSource.cloneWithRows(
|
||||
this._genRows(this._pressData)
|
||||
)});
|
||||
},
|
||||
});
|
||||
|
||||
var THUMB_URLS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png'];
|
||||
var LOREM_IPSUM = 'Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud modus, putant invidunt reprehendunt ne qui.';
|
||||
|
||||
/* eslint no-bitwise: 0 */
|
||||
var hashCode = function(str) {
|
||||
var hash = 15;
|
||||
for (var ii = str.length - 1; ii >= 0; ii--) {
|
||||
hash = ((hash << 5) - hash) + str.charCodeAt(ii);
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
padding: 10,
|
||||
backgroundColor: '#F6F6F6',
|
||||
},
|
||||
separator: {
|
||||
height: 1,
|
||||
backgroundColor: '#CCCCCC',
|
||||
},
|
||||
thumb: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
},
|
||||
text: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = ListViewSimpleExample;
|
||||
@@ -1,216 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule NavigatorIOSExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native/addons');
|
||||
var ViewExample = require('./ViewExample');
|
||||
var {
|
||||
PixelRatio,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var EmptyPage = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.emptyPage}>
|
||||
<Text style={styles.emptyPageText}>
|
||||
{this.props.text}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var NavigatorIOSExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: '<NavigatorIOS>',
|
||||
description: 'iOS navigation capabilities',
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var recurseTitle = 'Recurse Navigation';
|
||||
if (!this.props.topExampleRoute) {
|
||||
recurseTitle += ' - more examples here';
|
||||
}
|
||||
return (
|
||||
<ScrollView style={styles.list}>
|
||||
<View style={styles.line}/>
|
||||
<View style={styles.group}>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowNote}>
|
||||
See <UIExplorerApp> for top-level usage.
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.line}/>
|
||||
<View style={styles.groupSpace}/>
|
||||
<View style={styles.line}/>
|
||||
<View style={styles.group}>
|
||||
{this._renderRow(recurseTitle, () => {
|
||||
this.props.navigator.push({
|
||||
title: NavigatorIOSExample.title,
|
||||
component: NavigatorIOSExample,
|
||||
backButtonTitle: 'Custom Back',
|
||||
passProps: {topExampleRoute: this.props.topExampleRoute || this.props.route},
|
||||
});
|
||||
})}
|
||||
{this._renderRow('Push View Example', () => {
|
||||
this.props.navigator.push({
|
||||
title: 'Very Long Custom View Example Title',
|
||||
component: ViewExample,
|
||||
});
|
||||
})}
|
||||
{this._renderRow('Custom Right Button', () => {
|
||||
this.props.navigator.push({
|
||||
title: NavigatorIOSExample.title,
|
||||
component: EmptyPage,
|
||||
rightButtonTitle: 'Cancel',
|
||||
onRightButtonPress: () => this.props.navigator.pop(),
|
||||
passProps: {
|
||||
text: 'This page has a right button in the nav bar',
|
||||
}
|
||||
});
|
||||
})}
|
||||
{this._renderRow('Pop', () => {
|
||||
this.props.navigator.pop();
|
||||
})}
|
||||
{this._renderRow('Pop to top', () => {
|
||||
this.props.navigator.popToTop();
|
||||
})}
|
||||
{this._renderRow('Replace here', () => {
|
||||
var prevRoute = this.props.route;
|
||||
this.props.navigator.replace({
|
||||
title: 'New Navigation',
|
||||
component: EmptyPage,
|
||||
rightButtonTitle: 'Undo',
|
||||
onRightButtonPress: () => this.props.navigator.replace(prevRoute),
|
||||
passProps: {
|
||||
text: 'The component is replaced, but there is currently no ' +
|
||||
'way to change the right button or title of the current route',
|
||||
}
|
||||
});
|
||||
})}
|
||||
{this._renderReplacePrevious()}
|
||||
{this._renderReplacePreviousAndPop()}
|
||||
{this._renderPopToTopNavExample()}
|
||||
</View>
|
||||
<View style={styles.line}/>
|
||||
</ScrollView>
|
||||
);
|
||||
},
|
||||
|
||||
_renderPopToTopNavExample: function() {
|
||||
if (!this.props.topExampleRoute) {
|
||||
return null;
|
||||
}
|
||||
return this._renderRow('Pop to top NavigatorIOSExample', () => {
|
||||
this.props.navigator.popToRoute(this.props.topExampleRoute);
|
||||
});
|
||||
},
|
||||
|
||||
_renderReplacePrevious: function() {
|
||||
if (!this.props.topExampleRoute) {
|
||||
// this is to avoid replacing the UIExplorerList at the top of the stack
|
||||
return null;
|
||||
}
|
||||
return this._renderRow('Replace previous', () => {
|
||||
this.props.navigator.replacePrevious({
|
||||
title: 'Replaced',
|
||||
component: EmptyPage,
|
||||
passProps: {
|
||||
text: 'This is a replaced "previous" page',
|
||||
},
|
||||
wrapperStyle: styles.customWrapperStyle,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_renderReplacePreviousAndPop: function() {
|
||||
if (!this.props.topExampleRoute) {
|
||||
// this is to avoid replacing the UIExplorerList at the top of the stack
|
||||
return null;
|
||||
}
|
||||
return this._renderRow('Replace previous and pop', () => {
|
||||
this.props.navigator.replacePreviousAndPop({
|
||||
title: 'Replaced and Popped',
|
||||
component: EmptyPage,
|
||||
passProps: {
|
||||
text: 'This is a replaced "previous" page',
|
||||
},
|
||||
wrapperStyle: styles.customWrapperStyle,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_renderRow: function(title, onPress) {
|
||||
return (
|
||||
<View>
|
||||
<TouchableHighlight onPress={onPress}>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowText}>
|
||||
{title}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<View style={styles.separator} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
customWrapperStyle: {
|
||||
backgroundColor: '#bbdddd',
|
||||
},
|
||||
emptyPage: {
|
||||
flex: 1,
|
||||
paddingTop: 64,
|
||||
},
|
||||
emptyPageText: {
|
||||
margin: 10,
|
||||
},
|
||||
list: {
|
||||
backgroundColor: '#eeeeee',
|
||||
marginTop: 10,
|
||||
},
|
||||
group: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
groupSpace: {
|
||||
height: 15,
|
||||
},
|
||||
line: {
|
||||
backgroundColor: '#bbbbbb',
|
||||
height: 1 / PixelRatio.get(),
|
||||
},
|
||||
row: {
|
||||
backgroundColor: 'white',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 15,
|
||||
},
|
||||
separator: {
|
||||
height: 1 / PixelRatio.get(),
|
||||
backgroundColor: '#bbbbbb',
|
||||
marginLeft: 15,
|
||||
},
|
||||
rowNote: {
|
||||
fontSize: 17,
|
||||
},
|
||||
rowText: {
|
||||
fontSize: 17,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = NavigatorIOSExample;
|
||||
@@ -1,239 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule PointerEventsExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var ExampleBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
log: [],
|
||||
};
|
||||
},
|
||||
handleLog: function(msg) {
|
||||
this.state.log = this.state.log.concat([msg]);
|
||||
},
|
||||
flushReactChanges: function() {
|
||||
this.forceUpdate();
|
||||
},
|
||||
/**
|
||||
* Capture phase of bubbling to append separator before any of the bubbling
|
||||
* happens.
|
||||
*/
|
||||
handleTouchCapture: function() {
|
||||
this.state.log = this.state.log.concat(['---']);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<View
|
||||
onTouchEndCapture={this.handleTouchCapture}
|
||||
onTouchStart={this.flushReactChanges}>
|
||||
<this.props.Component onLog={this.handleLog} />
|
||||
</View>
|
||||
<View
|
||||
style={styles.logBox}>
|
||||
<DemoText style={styles.logText}>
|
||||
{this.state.log.join('\n')}
|
||||
</DemoText>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var NoneExample = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View
|
||||
onTouchStart={() => this.props.onLog('A unspecified touched')}
|
||||
style={styles.box}>
|
||||
<DemoText style={styles.text}>
|
||||
A: unspecified
|
||||
</DemoText>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
onTouchStart={() => this.props.onLog('B none touched')}
|
||||
style={[styles.box, styles.boxPassedThrough]}>
|
||||
<DemoText style={[styles.text, styles.textPassedThrough]}>
|
||||
B: none
|
||||
</DemoText>
|
||||
<View
|
||||
onTouchStart={() => this.props.onLog('C unspecified touched')}
|
||||
style={[styles.box, styles.boxPassedThrough]}>
|
||||
<DemoText style={[styles.text, styles.textPassedThrough]}>
|
||||
C: unspecified
|
||||
</DemoText>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Special demo text that makes itself untouchable so that it doesn't destroy
|
||||
* the experiment and confuse the output.
|
||||
*/
|
||||
var DemoText = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View pointerEvents="none">
|
||||
<Text
|
||||
style={this.props.style}>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var BoxNoneExample = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View
|
||||
onTouchStart={() => this.props.onLog('A unspecified touched')}
|
||||
style={styles.box}>
|
||||
<DemoText style={styles.text}>
|
||||
A: unspecified
|
||||
</DemoText>
|
||||
<View
|
||||
pointerEvents="box-none"
|
||||
onTouchStart={() => this.props.onLog('B box-none touched')}
|
||||
style={[styles.box, styles.boxPassedThrough]}>
|
||||
<DemoText style={[styles.text, styles.textPassedThrough]}>
|
||||
B: box-none
|
||||
</DemoText>
|
||||
<View
|
||||
onTouchStart={() => this.props.onLog('C unspecified touched')}
|
||||
style={styles.box}>
|
||||
<DemoText style={styles.text}>
|
||||
C: unspecified
|
||||
</DemoText>
|
||||
</View>
|
||||
<View
|
||||
pointerEvents="auto"
|
||||
onTouchStart={() => this.props.onLog('C explicitly unspecified touched')}
|
||||
style={[styles.box]}>
|
||||
<DemoText style={[styles.text]}>
|
||||
C: explicitly unspecified
|
||||
</DemoText>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var BoxOnlyExample = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View
|
||||
onTouchStart={() => this.props.onLog('A unspecified touched')}
|
||||
style={styles.box}>
|
||||
<DemoText style={styles.text}>
|
||||
A: unspecified
|
||||
</DemoText>
|
||||
<View
|
||||
pointerEvents="box-only"
|
||||
onTouchStart={() => this.props.onLog('B box-only touched')}
|
||||
style={styles.box}>
|
||||
<DemoText style={styles.text}>
|
||||
B: box-only
|
||||
</DemoText>
|
||||
<View
|
||||
onTouchStart={() => this.props.onLog('C unspecified touched')}
|
||||
style={[styles.box, styles.boxPassedThrough]}>
|
||||
<DemoText style={[styles.text, styles.textPassedThrough]}>
|
||||
C: unspecified
|
||||
</DemoText>
|
||||
</View>
|
||||
<View
|
||||
pointerEvents="auto"
|
||||
onTouchStart={() => this.props.onLog('C explicitly unspecified touched')}
|
||||
style={[styles.box, styles.boxPassedThrough]}>
|
||||
<DemoText style={[styles.text, styles.textPassedThrough]}>
|
||||
C: explicitly unspecified
|
||||
</DemoText>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var exampleClasses = [
|
||||
{
|
||||
Component: NoneExample,
|
||||
title: '`none`',
|
||||
description: '`none` causes touch events on the container and its child components to pass through to the parent container.',
|
||||
},
|
||||
{
|
||||
Component: BoxNoneExample,
|
||||
title: '`box-none`',
|
||||
description: '`box-none` causes touch events on the container to pass through and will only detect touch events on its child components.',
|
||||
},
|
||||
{
|
||||
Component: BoxOnlyExample,
|
||||
title: '`box-only`',
|
||||
description: '`box-only` causes touch events on the container\'s child components to pass through and will only detect touch events on the container itself.',
|
||||
}
|
||||
];
|
||||
|
||||
var infoToExample = (info) => {
|
||||
return {
|
||||
title: info.title,
|
||||
description: info.description,
|
||||
render: function() {
|
||||
return <ExampleBox key={info.title} Component={info.Component} />;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
text: {
|
||||
fontSize: 10,
|
||||
color: '#5577cc',
|
||||
},
|
||||
textPassedThrough: {
|
||||
color: '#88aadd',
|
||||
},
|
||||
box: {
|
||||
backgroundColor: '#aaccff',
|
||||
borderWidth: 1,
|
||||
borderColor: '#7799cc',
|
||||
padding: 10,
|
||||
margin: 5,
|
||||
},
|
||||
boxPassedThrough: {
|
||||
borderColor: '#99bbee',
|
||||
},
|
||||
logText: {
|
||||
fontSize: 9,
|
||||
},
|
||||
logBox: {
|
||||
padding: 20,
|
||||
margin: 10,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#f0f0f0',
|
||||
backgroundColor: '#f9f9f9',
|
||||
},
|
||||
bottomSpacer: {
|
||||
marginBottom: 100,
|
||||
},
|
||||
});
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'Pointer Events';
|
||||
exports.description = '`pointerEvents` is a prop of View that gives control ' +
|
||||
'of how touches should be handled.';
|
||||
exports.examples = exampleClasses.map(infoToExample);
|
||||
@@ -1,102 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ScrollViewExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
Image
|
||||
} = React;
|
||||
|
||||
exports.title = '<ScrollView>';
|
||||
exports.description = 'Component that enables scrolling through child components';
|
||||
exports.examples = [
|
||||
{
|
||||
title: '<ScrollView>',
|
||||
description: 'To make content scrollable, wrap it within a <ScrollView> component',
|
||||
render: function() {
|
||||
return (
|
||||
<ScrollView
|
||||
onScroll={() => { console.log('onScroll!'); }}
|
||||
throttleScrollCallbackMS={200}
|
||||
contentInset={{top: -50}}
|
||||
style={styles.scrollView}>
|
||||
{THUMBS.map(createThumbRow)}
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
}, {
|
||||
title: '<ScrollView> (horizontal = true)',
|
||||
description: 'You can display <ScrollView>\'s child components horizontally rather than vertically',
|
||||
render: function() {
|
||||
return (
|
||||
<ScrollView
|
||||
horizontal={true}
|
||||
contentInset={{top: -50}}
|
||||
style={[styles.scrollView, styles.horizontalScrollView]}>
|
||||
{THUMBS.map(createThumbRow)}
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
var Thumb = React.createClass({
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
return false;
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.button}>
|
||||
<Image style={styles.img} source={{uri:this.props.uri}} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var THUMBS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png'];
|
||||
THUMBS = THUMBS.concat(THUMBS); // double length of THUMBS
|
||||
var createThumbRow = (uri, i) => <Thumb key={i} uri={uri} />;
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
scrollView: {
|
||||
backgroundColor: '#6A85B1',
|
||||
height: 300,
|
||||
},
|
||||
horizontalScrollView: {
|
||||
height: 120,
|
||||
},
|
||||
containerPage: {
|
||||
height: 50,
|
||||
width: 50,
|
||||
backgroundColor: '#527FE4',
|
||||
padding: 5,
|
||||
},
|
||||
text: {
|
||||
fontSize: 20,
|
||||
color: '#888888',
|
||||
left: 80,
|
||||
top: 20,
|
||||
height: 40,
|
||||
},
|
||||
button: {
|
||||
margin: 7,
|
||||
padding: 5,
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#eaeaea',
|
||||
borderRadius: 3,
|
||||
},
|
||||
buttonContents: {
|
||||
flexDirection: 'row',
|
||||
width: 64,
|
||||
height: 64,
|
||||
},
|
||||
img: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
}
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule SliderExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Slider,
|
||||
Text,
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var SliderExample = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
value: 0,
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={styles.text} >
|
||||
{this.state.value}
|
||||
</Text>
|
||||
<Slider
|
||||
style={styles.slider}
|
||||
onValueChange={(value) => this.setState({value: value})} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
slider: {
|
||||
height: 10,
|
||||
margin: 10,
|
||||
},
|
||||
text: {
|
||||
fontSize: 14,
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
margin: 10,
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<Slider>';
|
||||
exports.description = 'Slider input for numeric values';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Slider',
|
||||
render() { return <SliderExample />; }
|
||||
}
|
||||
];
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule StatusBarIOSExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
StatusBarIOS,
|
||||
} = React;
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'StatusBarIOS';
|
||||
exports.description = 'Module for controlling iOS status bar';
|
||||
exports.examples = [{
|
||||
title: 'Status Bar Style',
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
{Object.keys(StatusBarIOS.Style).map((key) =>
|
||||
<TouchableHighlight style={styles.wrapper}
|
||||
onPress={() => StatusBarIOS.setStyle(StatusBarIOS.Style[key])}>
|
||||
<View style={styles.button}>
|
||||
<Text>setStyle(StatusBarIOS.Style.{key})</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Status Bar Style Animated',
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
{Object.keys(StatusBarIOS.Style).map((key) =>
|
||||
<TouchableHighlight style={styles.wrapper}
|
||||
onPress={() => StatusBarIOS.setStyle(StatusBarIOS.Style[key], true)}>
|
||||
<View style={styles.button}>
|
||||
<Text>setStyle(StatusBarIOS.Style.{key}, true)</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Status Bar Hidden',
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
{Object.keys(StatusBarIOS.Animation).map((key) =>
|
||||
<View>
|
||||
<TouchableHighlight style={styles.wrapper}
|
||||
onPress={() => StatusBarIOS.setHidden(true, StatusBarIOS.Animation[key])}>
|
||||
<View style={styles.button}>
|
||||
<Text>setHidden(true, StatusBarIOS.Animation.{key})</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight style={styles.wrapper}
|
||||
onPress={() => StatusBarIOS.setHidden(false, StatusBarIOS.Animation[key])}>
|
||||
<View style={styles.button}>
|
||||
<Text>setHidden(false, StatusBarIOS.Animation.{key})</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
wrapper: {
|
||||
borderRadius: 5,
|
||||
marginBottom: 5,
|
||||
},
|
||||
button: {
|
||||
backgroundColor: '#eeeeee',
|
||||
padding: 10,
|
||||
},
|
||||
});
|
||||
@@ -1,141 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule SwitchExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
SwitchIOS,
|
||||
Text,
|
||||
View
|
||||
} = React;
|
||||
|
||||
var BasicSwitchExample = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
trueSwitchIsOn: true,
|
||||
falseSwitchIsOn: false,
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({falseSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.falseSwitchIsOn} />
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({trueSwitchIsOn: value})}
|
||||
value={this.state.trueSwitchIsOn} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var DisabledSwitchExample = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<SwitchIOS
|
||||
disabled={true}
|
||||
style={{marginBottom: 10}}
|
||||
value={true} />
|
||||
<SwitchIOS
|
||||
disabled={true}
|
||||
value={false} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var ColorSwitchExample = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
colorTrueSwitchIsOn: true,
|
||||
colorFalseSwitchIsOn: false,
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({colorFalseSwitchIsOn: value})}
|
||||
onTintColor="#00ff00"
|
||||
style={{marginBottom: 10}}
|
||||
thumbTintColor="#0000ff"
|
||||
tintColor="#ff0000"
|
||||
value={this.state.colorFalseSwitchIsOn} />
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({colorTrueSwitchIsOn: value})}
|
||||
onTintColor="#00ff00"
|
||||
thumbTintColor="#0000ff"
|
||||
tintColor="#ff0000"
|
||||
value={this.state.colorTrueSwitchIsOn} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var EventSwitchExample = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
eventSwitchIsOn: false,
|
||||
eventSwitchRegressionIsOn: true,
|
||||
};
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-around' }}>
|
||||
<View>
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.eventSwitchIsOn} />
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({eventSwitchIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.eventSwitchIsOn} />
|
||||
<Text>{this.state.eventSwitchIsOn ? "On" : "Off"}</Text>
|
||||
</View>
|
||||
<View>
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({eventSwitchRegressionIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.eventSwitchRegressionIsOn} />
|
||||
<SwitchIOS
|
||||
onValueChange={(value) => this.setState({eventSwitchRegressionIsOn: value})}
|
||||
style={{marginBottom: 10}}
|
||||
value={this.state.eventSwitchRegressionIsOn} />
|
||||
<Text>{this.state.eventSwitchRegressionIsOn ? "On" : "Off"}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
exports.title = '<SwitchIOS>';
|
||||
exports.description = 'Native boolean input';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Switches can be set to true or false',
|
||||
render() { return <BasicSwitchExample />; }
|
||||
},
|
||||
{
|
||||
title: 'Switches can be disabled',
|
||||
render() { return <DisabledSwitchExample />; }
|
||||
},
|
||||
{
|
||||
title: 'Custom colors can be provided',
|
||||
render() { return <ColorSwitchExample />; }
|
||||
},
|
||||
{
|
||||
title: 'Change events can be detected',
|
||||
render() { return <EventSwitchExample />; }
|
||||
},
|
||||
{
|
||||
title: 'Switches are controlled components',
|
||||
render() { return <SwitchIOS />; }
|
||||
}
|
||||
];
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule TabBarExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
var TabBarIOS = require('TabBarIOS');
|
||||
var TabBarItemIOS = require('TabBarItemIOS');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var Text = require('Text');
|
||||
var View = require('View');
|
||||
|
||||
var ix = require('ix');
|
||||
|
||||
var TabBarExample = React.createClass({
|
||||
|
||||
statics: {
|
||||
title: '<TabBarIOS>',
|
||||
description: 'Tab-based navigation.'
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selectedTab: 'redTab',
|
||||
notifCount: 0,
|
||||
presses: 0,
|
||||
};
|
||||
},
|
||||
|
||||
_renderContent: function(color, pageText) {
|
||||
return (
|
||||
<View style={[styles.tabContent, {backgroundColor: color}]}>
|
||||
<Text style={styles.tabText}>{pageText}</Text>
|
||||
<Text style={styles.tabText}>{this.state.presses} re-renders of this tab</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<TabBarIOS
|
||||
selectedTab={this.state.selectedTab}>
|
||||
<TabBarItemIOS
|
||||
name="blueTab"
|
||||
icon={ix('favorites')}
|
||||
accessibilityLabel="Blue Tab"
|
||||
selected={this.state.selectedTab === 'blueTab'}
|
||||
onPress={() => {
|
||||
this.setState({
|
||||
selectedTab: 'blueTab',
|
||||
});
|
||||
}}>
|
||||
{this._renderContent('#414A8C', 'Blue Tab')}
|
||||
</TabBarItemIOS>
|
||||
<TabBarItemIOS
|
||||
accessibilityLabel="Red Tab"
|
||||
name="redTab"
|
||||
icon={ix('history')}
|
||||
badgeValue={this.state.notifCount ? String(this.state.notifCount) : null}
|
||||
selected={this.state.selectedTab === 'redTab'}
|
||||
onPress={() => {
|
||||
this.setState({
|
||||
selectedTab: 'redTab',
|
||||
notifCount: this.state.notifCount + 1,
|
||||
});
|
||||
}}>
|
||||
{this._renderContent('#783E33', 'Red Tab')}
|
||||
</TabBarItemIOS>
|
||||
<TabBarItemIOS
|
||||
name="greenTab"
|
||||
icon={ix('more')}
|
||||
accessibilityLabel="Green Tab"
|
||||
selected={this.state.selectedTab === 'greenTab'}
|
||||
onPress={() => {
|
||||
this.setState({
|
||||
selectedTab: 'greenTab',
|
||||
presses: this.state.presses + 1
|
||||
});
|
||||
}}>
|
||||
{this._renderContent('#21551C', 'Green Tab')}
|
||||
</TabBarItemIOS>
|
||||
</TabBarIOS>
|
||||
);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
tabContent: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
},
|
||||
tabText: {
|
||||
color: 'white',
|
||||
margin: 50,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = TabBarExample;
|
||||
@@ -1,279 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule TextExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var Entity = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<Text style={styles.entity}>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var AttributeToggler = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {fontWeight: 'bold', fontSize: 15};
|
||||
},
|
||||
increaseSize: function() {
|
||||
this.setState({
|
||||
fontSize: this.state.fontSize + 1
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
var curStyle = {fontSize: this.state.fontSize};
|
||||
return (
|
||||
<Text>
|
||||
<Text style={curStyle}>
|
||||
Tap the controls below to change attributes.
|
||||
</Text>
|
||||
<Text>
|
||||
See how it will even work on{' '}
|
||||
<Text style={curStyle}>
|
||||
this nested text
|
||||
</Text>
|
||||
<Text onPress={this.increaseSize}>
|
||||
{'>> Increase Size <<'}
|
||||
</Text>
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
exports.title = '<Text>';
|
||||
exports.description = 'Base component for rendering styled text.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Wrap',
|
||||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
The text should wrap if it goes on multiple lines. See, this is going to
|
||||
the next line.
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Font Family',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontFamily: 'Cochin'}}>
|
||||
Cochin
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Cochin', fontWeight: 'bold'}}>
|
||||
Cochin bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Helvetica'}}>
|
||||
Helvetica
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Helvetica', fontWeight: 'bold'}}>
|
||||
Helvetica bold
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Verdana'}}>
|
||||
Verdana
|
||||
</Text>
|
||||
<Text style={{fontFamily: 'Verdana', fontWeight: 'bold'}}>
|
||||
Verdana bold
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Font Size',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontSize: 23}}>
|
||||
Size 23
|
||||
</Text>
|
||||
<Text style={{fontSize: 8}}>
|
||||
Size 8
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Color',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{color: 'red'}}>
|
||||
Red color
|
||||
</Text>
|
||||
<Text style={{color: 'blue'}}>
|
||||
Blue color
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Font Weight',
|
||||
render: function() {
|
||||
return (
|
||||
<Text style={{fontWeight: 'bold'}}>
|
||||
Move fast and be bold
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Nested',
|
||||
description: 'Nested text components will inherit the styles of their ' +
|
||||
'parents (only backgroundColor is inherited from non-Text parents). ' +
|
||||
'<Text> only supports other <Text> and raw text (strings) as children.',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
(Normal text,
|
||||
<Text style={{fontWeight: 'bold'}}>
|
||||
(and bold
|
||||
<Text style={{fontSize: 11, color: '#527fe4'}}>
|
||||
(and tiny inherited bold blue)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
)
|
||||
</Text>
|
||||
<Text style={{fontSize: 12}}>
|
||||
<Entity>Entity Name</Entity>
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Text Align',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<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>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Spaces',
|
||||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
A {'generated'} {' '} {'string'} and some spaces
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Line Height',
|
||||
render: function() {
|
||||
return (
|
||||
<Text>
|
||||
<Text style={{lineHeight: 35}}>
|
||||
A lot of space between the lines of this long passage that should
|
||||
wrap once.
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Empty Text',
|
||||
description: 'It\'s ok to have Text with zero or null children.',
|
||||
render: function() {
|
||||
return (
|
||||
<Text />
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Toggling Attributes',
|
||||
render: function() {
|
||||
return <AttributeToggler />;
|
||||
},
|
||||
}, {
|
||||
title: 'backgroundColor attribute',
|
||||
description: 'backgroundColor is inherited from all types of views.',
|
||||
render: function() {
|
||||
return (
|
||||
<View style={{backgroundColor: 'yellow'}}>
|
||||
<Text>
|
||||
Yellow background inherited from View parent,
|
||||
<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>
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'containerBackgroundColor attribute',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<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, containerBackgroundColor: 'transparent'}]}>
|
||||
{"containerBackgroundColor: 'transparent' + backgroundColor wash"}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'numberOfLines attribute',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<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>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
backgroundColorText: {
|
||||
left: 5,
|
||||
backgroundColor: 'rgba(100, 100, 100, 0.3)'
|
||||
},
|
||||
entity: {
|
||||
fontWeight: 'bold',
|
||||
color: '#527fe4',
|
||||
},
|
||||
});
|
||||
@@ -1,221 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule TextInputExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
StyleSheet,
|
||||
} = React;
|
||||
|
||||
var WithLabel = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.labelContainer}>
|
||||
<View style={styles.label}>
|
||||
<Text>{this.props.label}</Text>
|
||||
</View>
|
||||
{this.props.children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TextEventsExample = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
curText: '<No Event>',
|
||||
prevText: '<No Event>',
|
||||
};
|
||||
},
|
||||
|
||||
updateText: function(text) {
|
||||
this.setState({
|
||||
curText: text,
|
||||
prevText: this.state.curText,
|
||||
});
|
||||
},
|
||||
|
||||
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.default}
|
||||
/>
|
||||
<Text style={styles.eventLabel}>
|
||||
{this.state.curText}{'\n'}
|
||||
(prev: {this.state.prevText})
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
page: {
|
||||
paddingBottom: 300,
|
||||
},
|
||||
default: {
|
||||
height: 26,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#0f0f0f',
|
||||
padding: 4,
|
||||
flex: 1,
|
||||
fontSize: 13,
|
||||
},
|
||||
multiline: {
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#0f0f0f',
|
||||
flex: 1,
|
||||
fontSize: 13,
|
||||
height: 50,
|
||||
},
|
||||
eventLabel: {
|
||||
margin: 3,
|
||||
fontSize: 12,
|
||||
},
|
||||
labelContainer: {
|
||||
flexDirection: 'row',
|
||||
marginVertical: 2,
|
||||
flex: 1,
|
||||
},
|
||||
label: {
|
||||
width: 80,
|
||||
justifyContent: 'flex-end',
|
||||
flexDirection: 'row',
|
||||
marginRight: 10,
|
||||
paddingTop: 2,
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<TextInput>';
|
||||
exports.description = 'Single-line text inputs.';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Auto-focus',
|
||||
render: function() {
|
||||
return <TextInput autoFocus={true} style={styles.default} />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Auto-capitalize',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<WithLabel label="none">
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
style={styles.default}
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="sentences">
|
||||
<TextInput
|
||||
autoCapitalize="sentences"
|
||||
style={styles.default}
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="words">
|
||||
<TextInput
|
||||
autoCapitalize="words"
|
||||
style={styles.default}
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="characters">
|
||||
<TextInput
|
||||
autoCapitalize="characters"
|
||||
style={styles.default}
|
||||
/>
|
||||
</WithLabel>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Auto-correct',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<WithLabel label="true">
|
||||
<TextInput autoCorrect={true} style={styles.default} />
|
||||
</WithLabel>
|
||||
<WithLabel label="false">
|
||||
<TextInput autoCorrect={false} style={styles.default} />
|
||||
</WithLabel>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Event handling',
|
||||
render: () => <TextEventsExample />,
|
||||
},
|
||||
{
|
||||
title: 'Colored input text',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
style={[styles.default, {color: 'blue'}]}
|
||||
value="Blue"
|
||||
/>
|
||||
<TextInput
|
||||
style={[styles.default, {color: 'green'}]}
|
||||
value="Green"
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Clear button mode',
|
||||
render: function () {
|
||||
return (
|
||||
<View>
|
||||
<WithLabel label="never">
|
||||
<TextInput
|
||||
style={styles.default}
|
||||
clearButtonMode="never"
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="while editing">
|
||||
<TextInput
|
||||
style={styles.default}
|
||||
clearButtonMode="while-editing"
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="unless editing">
|
||||
<TextInput
|
||||
style={styles.default}
|
||||
clearButtonMode="unless-editing"
|
||||
/>
|
||||
</WithLabel>
|
||||
<WithLabel label="always">
|
||||
<TextInput
|
||||
style={styles.default}
|
||||
clearButtonMode="always"
|
||||
/>
|
||||
</WithLabel>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
},
|
||||
];
|
||||
@@ -1,188 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule TouchableExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
PixelRatio,
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
exports.title = '<Touchable*> and onPress';
|
||||
exports.examples = [
|
||||
{
|
||||
title: '<TouchableHighlight>',
|
||||
description: 'TouchableHighlight works by adding an extra view with a ' +
|
||||
'black background under the single child view. This works best when the ' +
|
||||
'child view is fully opaque, although it can be made to work as a simple ' +
|
||||
'background color change as well with the activeOpacity and ' +
|
||||
'underlayColor props.',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.row}>
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
onPress={() => console.log('stock THW image - highlight')}>
|
||||
<Image
|
||||
source={heartImage}
|
||||
style={styles.image}
|
||||
/>
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight
|
||||
style={styles.wrapper}
|
||||
activeOpacity={1}
|
||||
animationVelocity={0}
|
||||
underlayColor="rgb(210, 230, 255)"
|
||||
onPress={() => console.log('custom THW text - hightlight')}>
|
||||
<View style={styles.wrapperCustom}>
|
||||
<Text style={styles.text}>
|
||||
Tap Here For Custom Highlight!
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: '<Text onPress={fn}> with highlight',
|
||||
render: function() {
|
||||
return <TextOnPressBox />;
|
||||
},
|
||||
}, {
|
||||
title: 'Touchable feedback events',
|
||||
description: '<Touchable*> components accept onPress, onPressIn, ' +
|
||||
'onPressOut, and onLongPress as props.',
|
||||
render: function() {
|
||||
return <TouchableFeedbackEvents />;
|
||||
},
|
||||
}];
|
||||
|
||||
var TextOnPressBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
timesPressed: 0,
|
||||
};
|
||||
},
|
||||
textOnPress: function() {
|
||||
this.setState({
|
||||
timesPressed: this.state.timesPressed + 1,
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
var textLog = '';
|
||||
if (this.state.timesPressed > 1) {
|
||||
textLog = this.state.timesPressed + 'x text onPress';
|
||||
} else if (this.state.timesPressed > 0) {
|
||||
textLog = 'text onPress';
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text
|
||||
style={styles.textBlock}
|
||||
onPress={this.textOnPress}>
|
||||
Text has built-in onPress handling
|
||||
</Text>
|
||||
<View style={styles.logBox}>
|
||||
<Text>
|
||||
{textLog}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TouchableFeedbackEvents = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
eventLog: [],
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<View style={[styles.row, {justifyContent: 'center'}]}>
|
||||
<TouchableOpacity
|
||||
style={styles.wrapper}
|
||||
onPress={() => this._appendEvent('press')}
|
||||
onPressIn={() => this._appendEvent('pressIn')}
|
||||
onPressOut={() => this._appendEvent('pressOut')}
|
||||
onLongPress={() => this._appendEvent('longPress')}>
|
||||
<Text style={styles.button}>
|
||||
Press Me
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.eventLogBox}>
|
||||
{this.state.eventLog.map((e, ii) => <Text key={ii}>{e}</Text>)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
_appendEvent: function(eventName) {
|
||||
var limit = 6;
|
||||
var eventLog = this.state.eventLog.slice(0, limit - 1);
|
||||
eventLog.unshift(eventName);
|
||||
this.setState({eventLog});
|
||||
},
|
||||
});
|
||||
|
||||
var heartImage = {uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small'};
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
row: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
icon: {
|
||||
width: 24,
|
||||
height: 24,
|
||||
},
|
||||
image: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
},
|
||||
text: {
|
||||
fontSize: 16,
|
||||
},
|
||||
button: {
|
||||
color: '#007AFF',
|
||||
},
|
||||
wrapper: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
wrapperCustom: {
|
||||
borderRadius: 8,
|
||||
padding: 6,
|
||||
},
|
||||
logBox: {
|
||||
padding: 20,
|
||||
margin: 10,
|
||||
borderWidth: 1 / PixelRatio.get(),
|
||||
borderColor: '#f0f0f0',
|
||||
backgroundColor: '#f9f9f9',
|
||||
},
|
||||
eventLogBox: {
|
||||
padding: 10,
|
||||
margin: 10,
|
||||
height: 120,
|
||||
borderWidth: 1 / PixelRatio.get(),
|
||||
borderColor: '#f0f0f0',
|
||||
backgroundColor: '#f9f9f9',
|
||||
},
|
||||
textBlock: {
|
||||
fontWeight: 'bold',
|
||||
color: 'blue',
|
||||
},
|
||||
});
|
||||
@@ -1,459 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FE81AA91428003F314A /* libRCTImage.a */; };
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FEF1AA914B8003F314A /* libRCTText.a */; };
|
||||
134180021AA9153C003F314A /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 13417FFF1AA91531003F314A /* libReactKit.a */; };
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1341802B1AA91779003F314A /* libRCTNetwork.a */; };
|
||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 134A8A251AACED6A00945AAE /* libRCTGeolocation.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
13417FE71AA91428003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
|
||||
remoteInfo = RCTImage;
|
||||
};
|
||||
13417FEE1AA914B8003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
|
||||
remoteInfo = RCTText;
|
||||
};
|
||||
13417FFE1AA91531003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
|
||||
remoteInfo = ReactKit;
|
||||
};
|
||||
1341802A1AA91779003F314A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 58B511DB1A9E6C8500147676;
|
||||
remoteInfo = RCTNetwork;
|
||||
};
|
||||
134A8A241AACED6A00945AAE /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTGeolocation;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../../Libraries/Image/RCTImage.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = "<group>"; };
|
||||
13417FFA1AA91531003F314A /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = "<group>"; };
|
||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../../Libraries/Network/RCTNetwork.xcodeproj; sourceTree = "<group>"; };
|
||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../../Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIExplorer.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */,
|
||||
1341802C1AA9178B003F314A /* libRCTNetwork.a in Frameworks */,
|
||||
134180011AA9153C003F314A /* libRCTText.a in Frameworks */,
|
||||
134180021AA9153C003F314A /* libReactKit.a in Frameworks */,
|
||||
13417FE91AA91432003F314A /* libRCTImage.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1316A21D1AA397F400C0188E /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */,
|
||||
13417FFA1AA91531003F314A /* ReactKit.xcodeproj */,
|
||||
134180261AA91779003F314A /* RCTNetwork.xcodeproj */,
|
||||
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */,
|
||||
13417FE31AA91428003F314A /* RCTImage.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13417FE41AA91428003F314A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13417FE81AA91428003F314A /* libRCTImage.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13417FEB1AA914B8003F314A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13417FEF1AA914B8003F314A /* libRCTText.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13417FFB1AA91531003F314A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13417FFF1AA91531003F314A /* libReactKit.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
134180271AA91779003F314A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1341802B1AA91779003F314A /* libRCTNetwork.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
134A8A211AACED6A00945AAE /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134A8A251AACED6A00945AAE /* libRCTGeolocation.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* UIExplorer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = UIExplorer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* UIExplorer */,
|
||||
1316A21D1AA397F400C0188E /* Libraries */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* UIExplorer.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
13B07F861A680F5B00A75B9A /* UIExplorer */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "UIExplorer" */;
|
||||
buildPhases = (
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = UIExplorer;
|
||||
productName = "Hello World";
|
||||
productReference = 13B07F961A680F5B00A75B9A /* UIExplorer.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = 134A8A211AACED6A00945AAE /* Products */;
|
||||
ProjectRef = 134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 13417FE41AA91428003F314A /* Products */;
|
||||
ProjectRef = 13417FE31AA91428003F314A /* RCTImage.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 134180271AA91779003F314A /* Products */;
|
||||
ProjectRef = 134180261AA91779003F314A /* RCTNetwork.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 13417FEB1AA914B8003F314A /* Products */;
|
||||
ProjectRef = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 13417FFB1AA91531003F314A /* Products */;
|
||||
ProjectRef = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* UIExplorer */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
13417FE81AA91428003F314A /* libRCTImage.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTImage.a;
|
||||
remoteRef = 13417FE71AA91428003F314A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
13417FEF1AA914B8003F314A /* libRCTText.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTText.a;
|
||||
remoteRef = 13417FEE1AA914B8003F314A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
13417FFF1AA91531003F314A /* libReactKit.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReactKit.a;
|
||||
remoteRef = 13417FFE1AA91531003F314A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
1341802B1AA91779003F314A /* libRCTNetwork.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTNetwork.a;
|
||||
remoteRef = 1341802A1AA91779003F314A /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
134A8A251AACED6A00945AAE /* libRCTGeolocation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRCTGeolocation.a;
|
||||
remoteRef = 134A8A241AACED6A00945AAE /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
13B07FB21A68108700A75B9A /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = UIExplorer;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(inherited)";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = UIExplorer;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../../ReactKit/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "UIExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "UIExplorer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:UIExplorer.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -1,86 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0610"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "UIExplorer.app"
|
||||
BlueprintName = "UIExplorer"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "UIExplorer.app"
|
||||
BlueprintName = "UIExplorer"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "UIExplorer.app"
|
||||
BlueprintName = "UIExplorer"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "UIExplorer.app"
|
||||
BlueprintName = "UIExplorer"
|
||||
ReferencedContainer = "container:UIExplorer.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule UIExplorerApp
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native/addons');
|
||||
var UIExplorerList = require('./UIExplorerList');
|
||||
|
||||
var {
|
||||
AppRegistry,
|
||||
NavigatorIOS,
|
||||
StyleSheet,
|
||||
} = React;
|
||||
|
||||
|
||||
var UIExplorerApp = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<NavigatorIOS
|
||||
style={styles.container}
|
||||
initialRoute={{
|
||||
title: 'UIExplorer',
|
||||
component: UIExplorerList,
|
||||
}}
|
||||
itemWrapperStyle={styles.itemWrapper}
|
||||
tintColor='#008888'/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
itemWrapper: {
|
||||
backgroundColor: '#eaeaea',
|
||||
},
|
||||
});
|
||||
|
||||
AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);
|
||||
|
||||
module.exports = UIExplorerApp;
|
||||
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule UIExplorerBlock
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var UIExplorerBlock = React.createClass({
|
||||
propTypes: {
|
||||
title: React.PropTypes.string,
|
||||
description: React.PropTypes.string,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {description: null};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var description;
|
||||
if (this.props.description) {
|
||||
description =
|
||||
<Text style={styles.descriptionText}>
|
||||
{this.props.description}
|
||||
</Text>;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={styles.titleText}>
|
||||
{this.props.title}
|
||||
</Text>
|
||||
{description}
|
||||
</View>
|
||||
<View style={styles.children}>
|
||||
{this.props.children}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
borderRadius: 3,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#d6d7da',
|
||||
backgroundColor: '#ffffff',
|
||||
margin: 10,
|
||||
marginVertical: 5,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
titleContainer: {
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#d6d7da',
|
||||
backgroundColor: '#f6f7f8',
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 5,
|
||||
},
|
||||
titleRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
titleText: {
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
descriptionText: {
|
||||
fontSize: 14,
|
||||
},
|
||||
disclosure: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
padding: 10,
|
||||
},
|
||||
disclosureIcon: {
|
||||
width: 12,
|
||||
height: 8,
|
||||
},
|
||||
children: {
|
||||
padding: 10,
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = UIExplorerBlock;
|
||||
@@ -1,118 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native/addons');
|
||||
var {
|
||||
PixelRatio,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
invariant,
|
||||
} = React;
|
||||
|
||||
var createExamplePage = require('./createExamplePage');
|
||||
|
||||
var EXAMPLES = [
|
||||
require('./ViewExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TextInputExample'),
|
||||
require('./ExpandingTextExample'),
|
||||
require('./ImageExample'),
|
||||
require('./ListViewSimpleExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
require('./NavigatorIOSExample'),
|
||||
require('./StatusBarIOSExample'),
|
||||
require('./PointerEventsExample'),
|
||||
require('./TouchableExample'),
|
||||
require('./ActivityIndicatorExample'),
|
||||
require('./ScrollViewExample'),
|
||||
require('./DatePickerExample'),
|
||||
require('./GeolocationExample'),
|
||||
require('./TabBarExample'),
|
||||
require('./SwitchExample'),
|
||||
require('./SliderExample'),
|
||||
];
|
||||
|
||||
var UIExplorerList = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<ScrollView style={styles.list}>
|
||||
<View style={styles.group}>
|
||||
<View style={styles.line} />
|
||||
{EXAMPLES.map(this._renderRow)}
|
||||
<View style={styles.line} />
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
},
|
||||
|
||||
_renderRow: function(example, i) {
|
||||
invariant(example.title, 'Example must provide a title.');
|
||||
return (
|
||||
<View key={i}>
|
||||
<TouchableHighlight onPress={() => this._onPressRow(example)}>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowTitleText}>
|
||||
{example.title}
|
||||
</Text>
|
||||
<Text style={styles.rowDetailText}>
|
||||
{example.description}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<View style={styles.separator} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
_onPressRow: function(example) {
|
||||
var Component = example.examples ?
|
||||
createExamplePage(null, example) :
|
||||
example;
|
||||
this.props.navigator.push({
|
||||
title: Component.title,
|
||||
component: Component,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
list: {
|
||||
backgroundColor: '#eeeeee',
|
||||
},
|
||||
group: {
|
||||
backgroundColor: 'white',
|
||||
marginVertical: 25,
|
||||
},
|
||||
line: {
|
||||
backgroundColor: '#bbbbbb',
|
||||
height: 1 / PixelRatio.get(),
|
||||
},
|
||||
row: {
|
||||
backgroundColor: 'white',
|
||||
justifyContent: 'center',
|
||||
paddingHorizontal: 15,
|
||||
paddingVertical: 8,
|
||||
},
|
||||
separator: {
|
||||
height: 1 / PixelRatio.get(),
|
||||
backgroundColor: '#bbbbbb',
|
||||
marginLeft: 15,
|
||||
},
|
||||
rowTitleText: {
|
||||
fontSize: 17,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
rowDetailText: {
|
||||
fontSize: 15,
|
||||
color: '#888888',
|
||||
lineHeight: 20,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerList;
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule UIExplorerPage
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var UIExplorerTitle = require('./UIExplorerTitle');
|
||||
|
||||
var UIExplorerPage = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
keyboardShouldPersistTaps: React.PropTypes.bool,
|
||||
noScroll: React.PropTypes.bool,
|
||||
noSpacer: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var ContentWrapper;
|
||||
var wrapperProps = {};
|
||||
if (this.props.noScroll) {
|
||||
ContentWrapper = View;
|
||||
} else {
|
||||
ContentWrapper = ScrollView;
|
||||
wrapperProps.keyboardShouldPeristTaps = true;
|
||||
wrapperProps.keyboardDismissMode = 'interactive';
|
||||
}
|
||||
var title = this.props.title ?
|
||||
<UIExplorerTitle title={this.props.title} /> :
|
||||
null;
|
||||
var spacer = this.props.noSpacer ? null : <View style={styles.spacer} />;
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{title}
|
||||
<ContentWrapper
|
||||
style={styles.wrapper}
|
||||
{...wrapperProps}>
|
||||
{this.props.children}
|
||||
{spacer}
|
||||
</ContentWrapper>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: '#e9eaed',
|
||||
paddingTop: 15,
|
||||
flex: 1,
|
||||
},
|
||||
spacer: {
|
||||
height: 270,
|
||||
},
|
||||
wrapper: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerPage;
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule UIExplorerTitle
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var UIExplorerTitle = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.text}>
|
||||
{this.props.title}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
borderRadius: 4,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#d6d7da',
|
||||
margin: 10,
|
||||
height: 45,
|
||||
padding: 10,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
text: {
|
||||
fontSize: 19,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = UIExplorerTitle;
|
||||
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ViewExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var ViewExample = React.createClass({
|
||||
statics: {
|
||||
title: '<View>',
|
||||
description: 'Basic building block of all UI.'
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
textBorderExampleHeight: 20,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title={this.props.navigator ? null : '<View>'}>
|
||||
<UIExplorerBlock title="Background Color">
|
||||
<View style={{backgroundColor: '#527FE4', padding: 5}}>
|
||||
<Text style={{fontSize: 11}}>
|
||||
Blue background
|
||||
</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Border">
|
||||
<View style={{borderColor: '#527FE4', borderWidth: 5, padding: 10}}>
|
||||
<Text style={{fontSize: 11}}>5px blue border</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Padding/Margin">
|
||||
<View style={{borderColor: '#bb0000', borderWidth: 0.5}}>
|
||||
<View style={[styles.box, {padding: 5}]}>
|
||||
<Text style={{fontSize: 11}}>5px padding</Text>
|
||||
</View>
|
||||
<View style={[styles.box, {margin: 5}]}>
|
||||
<Text style={{fontSize: 11}}>5px margin</Text>
|
||||
</View>
|
||||
<View style={[styles.box, {margin: 5, padding: 5, alignSelf: 'flex-start'}]}>
|
||||
<Text style={{fontSize: 11}}>
|
||||
5px margin and padding,
|
||||
</Text>
|
||||
<Text style={{fontSize: 11}}>
|
||||
widthAutonomous=true
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Border Radius">
|
||||
<View style={{borderWidth: 0.5, borderRadius: 5, padding: 5}}>
|
||||
<Text style={{fontSize: 11}}>
|
||||
Too much use of `borderRadius` (especially large radii) on
|
||||
anything which is scrolling may result in dropped frames.
|
||||
Use sparingly.
|
||||
</Text>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Circle with Border Radius">
|
||||
<View style={{borderRadius: 10, borderWidth: 1, width: 20, height: 20}} />
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Overflow">
|
||||
<View style={{flexDirection: 'row'}}>
|
||||
<View
|
||||
style={{
|
||||
width: 95,
|
||||
height: 10,
|
||||
marginRight: 10,
|
||||
marginBottom: 5,
|
||||
overflow: 'hidden',
|
||||
borderWidth: 0.5,
|
||||
}}>
|
||||
<View style={{width: 200, height: 20}}>
|
||||
<Text>Overflow hidden</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={{width: 95, height: 10, marginBottom: 5, borderWidth: 0.5}}>
|
||||
<View style={{width: 200, height: 20}}>
|
||||
<Text>Overflow visible</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Opacity">
|
||||
<View style={{opacity: 0}}><Text>Opacity 0</Text></View>
|
||||
<View style={{opacity: 0.1}}><Text>Opacity 0.1</Text></View>
|
||||
<View style={{opacity: 0.3}}><Text>Opacity 0.3</Text></View>
|
||||
<View style={{opacity: 0.5}}><Text>Opacity 0.5</Text></View>
|
||||
<View style={{opacity: 0.7}}><Text>Opacity 0.7</Text></View>
|
||||
<View style={{opacity: 0.9}}><Text>Opacity 0.9</Text></View>
|
||||
<View style={{opacity: 1}}><Text>Opacity 1</Text></View>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
},
|
||||
|
||||
updateHeight: function() {
|
||||
var height = this.state.textBorderExampleHeight === 50 ? 20 : 50;
|
||||
this.setState({textBorderExampleHeight: height});
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
box: {
|
||||
backgroundColor: '#527FE4',
|
||||
borderColor: '#000033',
|
||||
borderWidth: 1,
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ViewExample;
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule createExamplePage
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var UIExplorerBlock = require('./UIExplorerBlock');
|
||||
var UIExplorerPage = require('./UIExplorerPage');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
var createExamplePage = function(title, exampleModule) {
|
||||
invariant(!!exampleModule.examples, 'The module must have examples');
|
||||
|
||||
var ExamplePage = React.createClass({
|
||||
statics: {
|
||||
title: exampleModule.title,
|
||||
description: exampleModule.description,
|
||||
},
|
||||
|
||||
getBlock: function(example, i) {
|
||||
// Hack warning: This is a hack because the www UI explorer requires
|
||||
// renderComponent to be called.
|
||||
var originalRenderComponent = React.renderComponent;
|
||||
var originalRender = React.render;
|
||||
var renderedComponent;
|
||||
React.render = React.renderComponent = function(element, container) {
|
||||
renderedComponent = element;
|
||||
};
|
||||
var result = example.render(null);
|
||||
if (result) {
|
||||
renderedComponent = result;
|
||||
}
|
||||
React.renderComponent = originalRenderComponent;
|
||||
React.render = originalRender;
|
||||
return (
|
||||
<UIExplorerBlock
|
||||
key={i}
|
||||
title={example.title}
|
||||
description={example.description}>
|
||||
{renderedComponent}
|
||||
</UIExplorerBlock>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title={title}>
|
||||
{exampleModule.examples.map(this.getBlock)}
|
||||
</UIExplorerPage>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return ExamplePage;
|
||||
};
|
||||
|
||||
module.exports = createExamplePage;
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
*
|
||||
* React Native software is currently provided by Facebook to you for
|
||||
* non-commercial testing and evaluation purposes only. Facebook reserves all
|
||||
* rights not expressly granted. An open source version of this software will
|
||||
* be provided at a later date.
|
||||
*
|
||||
* 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 NONINFRINGEMENT. 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.
|
||||
*/
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule LayoutAnimation
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var RKUIManager = require('NativeModules').RKUIManager;
|
||||
|
||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var keyMirror = require('keyMirror');
|
||||
|
||||
var Types = keyMirror({
|
||||
spring: true,
|
||||
linear: true,
|
||||
easeInEaseOut: true,
|
||||
easeIn: true,
|
||||
easeOut: true,
|
||||
});
|
||||
|
||||
var Properties = keyMirror({
|
||||
opacity: true,
|
||||
scaleXY: true,
|
||||
});
|
||||
|
||||
var animChecker = createStrictShapeTypeChecker({
|
||||
duration: PropTypes.number,
|
||||
delay: PropTypes.number,
|
||||
springDamping: PropTypes.number,
|
||||
initialVelocity: PropTypes.number,
|
||||
type: PropTypes.oneOf(
|
||||
Object.keys(Types)
|
||||
),
|
||||
property: PropTypes.oneOf( // Only applies to create/delete
|
||||
Object.keys(Properties)
|
||||
),
|
||||
});
|
||||
|
||||
var configChecker = createStrictShapeTypeChecker({
|
||||
duration: PropTypes.number.isRequired,
|
||||
create: animChecker,
|
||||
update: animChecker,
|
||||
delete: animChecker,
|
||||
});
|
||||
|
||||
var LayoutAnimation = {
|
||||
configureNext(config, onAnimationDidEnd, onError) {
|
||||
configChecker({config}, 'config', 'LayoutAnimation.configureNext');
|
||||
RKUIManager.configureNextLayoutAnimation(config, onAnimationDidEnd, onError);
|
||||
},
|
||||
create(duration, type, creationProp) {
|
||||
return {
|
||||
duration,
|
||||
create: {
|
||||
type,
|
||||
property: creationProp,
|
||||
},
|
||||
update: {
|
||||
type,
|
||||
},
|
||||
};
|
||||
},
|
||||
Types: Types,
|
||||
Properties: Properties,
|
||||
configChecker: configChecker,
|
||||
};
|
||||
|
||||
LayoutAnimation.Presets = {
|
||||
easeInEaseOut: LayoutAnimation.create(
|
||||
0.3, Types.easeInEaseOut, Properties.opacity
|
||||
),
|
||||
linear: LayoutAnimation.create(
|
||||
0.5, Types.linear, Properties.opacity
|
||||
),
|
||||
spring: {
|
||||
duration: 0.7,
|
||||
create: {
|
||||
type: Types.linear,
|
||||
property: Properties.opacity,
|
||||
},
|
||||
update: {
|
||||
type: Types.spring,
|
||||
springDamping: 0.4,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = LayoutAnimation;
|
||||
@@ -1,250 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule POPAnimationMixin
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var POPAnimation = require('POPAnimation');
|
||||
if (!POPAnimation) {
|
||||
// POP animation isn't available in the OSS fork - this is a temporary
|
||||
// workaround to enable its availability to be determined at runtime.
|
||||
module.exports = null;
|
||||
} else {
|
||||
|
||||
var invariant = require('invariant');
|
||||
var warning = require('warning');
|
||||
|
||||
var POPAnimationMixin = {
|
||||
/**
|
||||
* Different ways to interpolate between beginning and end states
|
||||
* of properties during animation, such as spring, linear, and decay.
|
||||
*/
|
||||
AnimationTypes: POPAnimation.Types,
|
||||
AnimationProperties: POPAnimation.Properties,
|
||||
|
||||
getInitialState: function(): Object {
|
||||
return {
|
||||
_currentAnimationsByNodeHandle: {},
|
||||
};
|
||||
},
|
||||
|
||||
_ensureBookkeepingSetup: function(nodeHandle: any) {
|
||||
if (!this.state._currentAnimationsByNodeHandle[nodeHandle]) {
|
||||
this.state._currentAnimationsByNodeHandle[nodeHandle] = [];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Start animating the View with ref `refKey`.
|
||||
*
|
||||
* @param {key} refKey The key to reference the View to be animated.
|
||||
*
|
||||
* @param {number|Object} anim Either the identifier returned by
|
||||
* POPAnimation.create* or an object defining all the necessary
|
||||
* properties of the animation you wish to start (including type, matching
|
||||
* an entry in AnimationTypes).
|
||||
*
|
||||
* @param {func} doneCallback A callback fired when the animation is done, and
|
||||
* is passed a `finished` param that indicates whether the animation
|
||||
* completely finished, or was interrupted.
|
||||
*/
|
||||
startAnimation: function(
|
||||
refKey: string,
|
||||
anim: number | {type: number; property: number;},
|
||||
doneCallback: (finished: bool) => void
|
||||
) {
|
||||
var animID: number = 0;
|
||||
if (typeof anim === 'number') {
|
||||
animID = anim;
|
||||
} else {
|
||||
invariant(
|
||||
anim instanceof Object &&
|
||||
anim.type !== undefined &&
|
||||
anim.property !== undefined,
|
||||
'Animation definitions must specify a type of animation and a ' +
|
||||
'property to animate.'
|
||||
);
|
||||
animID = POPAnimation.createAnimation(anim.type, anim);
|
||||
}
|
||||
invariant(
|
||||
this.refs[refKey],
|
||||
'Invalid refKey ' + refKey + ' for anim:\n' + JSON.stringify(anim) +
|
||||
'\nvalid refs: ' + JSON.stringify(Object.keys(this.refs))
|
||||
);
|
||||
var refNodeHandle = this.refs[refKey].getNodeHandle();
|
||||
this.startAnimationWithNodeHandle(refNodeHandle, animID, doneCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts an animation on a native node.
|
||||
*
|
||||
* @param {NodeHandle} nodeHandle Handle to underlying native node.
|
||||
* @see `startAnimation`.
|
||||
*/
|
||||
startAnimationWithNodeHandle: function(
|
||||
nodeHandle: any,
|
||||
animID: number,
|
||||
doneCallback: (finished: bool) => void
|
||||
) {
|
||||
this._ensureBookkeepingSetup(nodeHandle);
|
||||
var animations = this.state._currentAnimationsByNodeHandle[nodeHandle];
|
||||
var animIndex = animations.length;
|
||||
animations.push(animID);
|
||||
var cleanupWrapper = (finished) => {
|
||||
if (!this.isMounted()) {
|
||||
return;
|
||||
}
|
||||
animations[animIndex] = 0; // zero it out so we don't try to stop it
|
||||
var allDone = true;
|
||||
for (var ii = 0; ii < animations.length; ii++) {
|
||||
if (animations[ii]) {
|
||||
allDone = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allDone) {
|
||||
this.state._currentAnimationsByNodeHandle[nodeHandle] = undefined;
|
||||
}
|
||||
doneCallback && doneCallback(finished);
|
||||
};
|
||||
POPAnimation.addAnimation(nodeHandle, animID, cleanupWrapper);
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts multiple animations with one shared callback that is called when all
|
||||
* animations complete.
|
||||
*
|
||||
* @param {Array(Object} animations Array of objects defining all the
|
||||
* animations to start, each with shape `{ref|nodeHandle, anim}`.
|
||||
* @param {func} onSuccess A callback fired when all animations have returned,
|
||||
* and is passed a finished arg that is true if all animations finished
|
||||
* completely.
|
||||
* @param {func} onFailure Not supported yet.
|
||||
*/
|
||||
startAnimations: function(
|
||||
animations: Array<Object>,
|
||||
onSuccess: (finished: boolean) => void,
|
||||
onFailure: () => void
|
||||
) {
|
||||
var numReturned = 0;
|
||||
var numFinished = 0;
|
||||
var numAnimations = animations.length;
|
||||
var metaCallback = (finished) => {
|
||||
if (finished) {
|
||||
++numFinished;
|
||||
}
|
||||
if (++numReturned === numAnimations) {
|
||||
onSuccess && onSuccess(numFinished === numAnimations);
|
||||
}
|
||||
};
|
||||
animations.forEach((anim) => {
|
||||
warning(
|
||||
anim.ref != null || anim.nodeHandle != null &&
|
||||
!anim.ref !== !anim.nodeHandle,
|
||||
'Animations must be specified with either ref xor nodeHandle'
|
||||
);
|
||||
if (anim.ref) {
|
||||
this.startAnimation(anim.ref, anim.anim, metaCallback);
|
||||
} else if (anim.nodeHandle) {
|
||||
this.startAnimationWithNodeHandle(anim.nodeHandle, anim.anim, metaCallback);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop any and all animations operating on the View with native node handle
|
||||
* `nodeHandle`.
|
||||
*
|
||||
* @param {NodeHandle} component The instance to stop animations
|
||||
* on. Do not pass a composite component.
|
||||
*/
|
||||
stopNodeHandleAnimations: function(nodeHandle: any) {
|
||||
if (!this.state._currentAnimationsByNodeHandle[nodeHandle]) {
|
||||
return;
|
||||
}
|
||||
var anims = this.state._currentAnimationsByNodeHandle[nodeHandle];
|
||||
for (var i = 0; i < anims.length; i++) {
|
||||
var anim = anims[i];
|
||||
if (anim) {
|
||||
// Note: Converting the string key to a number `nodeHandle`.
|
||||
POPAnimation.removeAnimation(+nodeHandle, anim);
|
||||
}
|
||||
}
|
||||
this.state._currentAnimationsByNodeHandle[nodeHandle] = undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop any and all animations operating on the View with ref `refKey`.
|
||||
*
|
||||
* @param {key} refKey The key to reference the View to be animated.
|
||||
*/
|
||||
stopAnimations: function(refKey: string) {
|
||||
invariant(this.refs[refKey], 'invalid ref');
|
||||
this.stopNodeHandleAnimations(this.refs[refKey].getNodeHandle());
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop any and all animations created by this component on itself and
|
||||
* subviews.
|
||||
*/
|
||||
stopAllAnimations: function() {
|
||||
for (var nodeHandle in this.state._currentAnimationsByNodeHandle) {
|
||||
this.stopNodeHandleAnimations(nodeHandle);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Animates size and position of a view referenced by `refKey` to a specific
|
||||
* frame.
|
||||
*
|
||||
* @param {key} refKey ref key for view to animate.
|
||||
* @param {Object} frame The frame to animate the view to, specified as {left,
|
||||
* top, width, height}.
|
||||
* @param {const} type What type of interpolation to use, selected from
|
||||
* `inperpolationTypes`.
|
||||
* @param {Object} event Event encapsulating synthetic and native data that
|
||||
* may have triggered this animation. Velocity is extracted from it if
|
||||
* possible and applied to the animation.
|
||||
* @param {func} doneCallback A callback fired when the animation is done, and
|
||||
* is passed a `finished` param that indicates whether the animation
|
||||
* completely finished, or was interrupted.
|
||||
*/
|
||||
animateToFrame: function(
|
||||
refKey: string,
|
||||
frame: {left: number; top: number; width: number; height: number;},
|
||||
type: number,
|
||||
velocity: number,
|
||||
doneCallback: (finished: boolean) => void
|
||||
) {
|
||||
var animFrame = { // Animations use a centered coordinate system.
|
||||
x: frame.left + frame.width / 2,
|
||||
y: frame.top + frame.height / 2,
|
||||
w: frame.width,
|
||||
h: frame.height
|
||||
};
|
||||
frame = undefined;
|
||||
var velocity = velocity || [0, 0];
|
||||
var posAnim = POPAnimation.createAnimation(type, {
|
||||
property: POPAnimation.Properties.position,
|
||||
toValue: [animFrame.x, animFrame.y],
|
||||
velocity: velocity,
|
||||
});
|
||||
var sizeAnim = POPAnimation.createAnimation(type, {
|
||||
property: POPAnimation.Properties.size,
|
||||
toValue: [animFrame.w, animFrame.h]
|
||||
});
|
||||
this.startAnimation(refKey, posAnim, doneCallback);
|
||||
this.startAnimation(refKey, sizeAnim);
|
||||
},
|
||||
|
||||
// Cleanup any potentially leaked animations.
|
||||
componentWillUnmount: function() {
|
||||
this.stopAllAnimations();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = POPAnimationMixin;
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule AppRegistry
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var invariant = require('invariant');
|
||||
var renderApplication = require('renderApplication');
|
||||
|
||||
if (__DEV__) {
|
||||
// In order to use Cmd+P to record/dump perf data, we need to make sure
|
||||
// this module is available in the bundle
|
||||
require('RCTRenderingPerf');
|
||||
}
|
||||
|
||||
var runnables = {};
|
||||
|
||||
/**
|
||||
* `AppRegistry` is the JS entry point to running all React Native apps. App
|
||||
* root components should register themselves with
|
||||
* `AppRegistry.registerComponent`, then the native system can load the bundle
|
||||
* for the app and then actually run the app when it's ready by invoking
|
||||
* `AppRegistry.runApplication`.
|
||||
*
|
||||
* `AppRegistry` should be `require`d early in the `require` sequence to make
|
||||
* sure the JS execution environment is setup before other modules are
|
||||
* `require`d.
|
||||
*/
|
||||
var AppRegistry = {
|
||||
registerConfig: function(config) {
|
||||
for (var i = 0; i < config.length; ++i) {
|
||||
if (config[i].run) {
|
||||
AppRegistry.registerRunnable(config[i].appKey, config[i].run);
|
||||
} else {
|
||||
AppRegistry.registerComponent(config[i].appKey, config[i].component);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
registerComponent: function(appKey, getComponentFunc) {
|
||||
runnables[appKey] = {
|
||||
run: (appParameters) =>
|
||||
renderApplication(getComponentFunc(), appParameters.initialProps, appParameters.rootTag)
|
||||
};
|
||||
return appKey;
|
||||
},
|
||||
|
||||
registerRunnable: function(appKey, func) {
|
||||
runnables[appKey] = {run: func};
|
||||
return appKey;
|
||||
},
|
||||
|
||||
runApplication: function(appKey, appParameters) {
|
||||
console.log(
|
||||
'Running application "' + appKey + '" with appParams: ',
|
||||
appParameters
|
||||
);
|
||||
|
||||
invariant(
|
||||
runnables[appKey] && runnables[appKey].run,
|
||||
'Application ' + appKey + ' has not been registered.'
|
||||
);
|
||||
runnables[appKey].run(appParameters);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = AppRegistry;
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule NativeModules
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeModules = require('BatchedBridge').RemoteModules;
|
||||
|
||||
// Dirty hack to support old (RK) and new (RCT) native module name conventions
|
||||
Object.keys(NativeModules).forEach((moduleName) => {
|
||||
var rkModuleName = moduleName.replace(/^RCT/, 'RK');
|
||||
NativeModules[rkModuleName] = NativeModules[moduleName];
|
||||
});
|
||||
|
||||
module.exports = NativeModules;
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule NativeModulesDeprecated
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RemoteModulesDeprecated = require('BatchedBridge').RemoteModulesDeprecated;
|
||||
|
||||
// Dirty hack to support old (RK) and new (RCT) native module name conventions
|
||||
Object.keys(RemoteModulesDeprecated).forEach((moduleName) => {
|
||||
var rkModuleName = moduleName.replace(/^RCT/, 'RK');
|
||||
RemoteModulesDeprecated[rkModuleName] = RemoteModulesDeprecated[moduleName];
|
||||
});
|
||||
|
||||
module.exports = RemoteModulesDeprecated;
|
||||
@@ -1,166 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule POPAnimation
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RKPOPAnimationManager = require('NativeModulesDeprecated').RKPOPAnimationManager;
|
||||
if (!RKPOPAnimationManager) {
|
||||
// POP animation isn't available in the OSS fork - this is a temporary
|
||||
// workaround to enable its availability to be determined at runtime.
|
||||
module.exports = null;
|
||||
} else {
|
||||
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
|
||||
var getObjectValues = require('getObjectValues');
|
||||
var invariant = require('invariant');
|
||||
var merge = require('merge');
|
||||
|
||||
var RKTypes = RKPOPAnimationManager.Types;
|
||||
var RKProperties = RKPOPAnimationManager.Properties;
|
||||
|
||||
var Properties = {
|
||||
bounds: RKProperties.bounds,
|
||||
opacity: RKProperties.opacity,
|
||||
position: RKProperties.position,
|
||||
positionX: RKProperties.positionX,
|
||||
positionY: RKProperties.positionY,
|
||||
zPosition: RKProperties.zPosition,
|
||||
rotation: RKProperties.rotation,
|
||||
rotationX: RKProperties.rotationX,
|
||||
rotationY: RKProperties.rotationY,
|
||||
scaleX: RKProperties.scaleX,
|
||||
scaleXY: RKProperties.scaleXY,
|
||||
scaleY: RKProperties.scaleY,
|
||||
shadowColor: RKProperties.shadowColor,
|
||||
shadowOffset: RKProperties.shadowOffset,
|
||||
shadowOpacity: RKProperties.shadowOpacity,
|
||||
shadowRadius: RKProperties.shadowRadius,
|
||||
size: RKProperties.size,
|
||||
subscaleXY: RKProperties.subscaleXY,
|
||||
subtranslationX: RKProperties.subtranslationX,
|
||||
subtranslationXY: RKProperties.subtranslationXY,
|
||||
subtranslationY: RKProperties.subtranslationY,
|
||||
subtranslationZ: RKProperties.subtranslationZ,
|
||||
translationX: RKProperties.translationX,
|
||||
translationXY: RKProperties.translationXY,
|
||||
translationY: RKProperties.translationY,
|
||||
translationZ: RKProperties.translationZ,
|
||||
};
|
||||
|
||||
var Types = {
|
||||
decay: RKTypes.decay,
|
||||
easeIn: RKTypes.easeIn,
|
||||
easeInEaseOut: RKTypes.easeInEaseOut,
|
||||
easeOut: RKTypes.easeOut,
|
||||
linear: RKTypes.linear,
|
||||
spring: RKTypes.spring,
|
||||
};
|
||||
|
||||
var POPAnimation = {
|
||||
Types: Types,
|
||||
Properties: Properties,
|
||||
|
||||
attributeChecker: createStrictShapeTypeChecker({
|
||||
type: ReactPropTypes.oneOf(getObjectValues(Types)),
|
||||
property: ReactPropTypes.oneOf(getObjectValues(Properties)),
|
||||
fromValue: ReactPropTypes.any,
|
||||
toValue: ReactPropTypes.any,
|
||||
duration: ReactPropTypes.any,
|
||||
velocity: ReactPropTypes.any,
|
||||
deceleration: ReactPropTypes.any,
|
||||
springBounciness: ReactPropTypes.any,
|
||||
dynamicsFriction: ReactPropTypes.any,
|
||||
dynamicsMass: ReactPropTypes.any,
|
||||
dynamicsTension: ReactPropTypes.any,
|
||||
}),
|
||||
|
||||
lastUsedTag: 0,
|
||||
allocateTagForAnimation: function() {
|
||||
return ++this.lastUsedTag;
|
||||
},
|
||||
|
||||
createAnimation: function(typeName, attrs) {
|
||||
var tag = this.allocateTagForAnimation();
|
||||
|
||||
if (__DEV__) {
|
||||
POPAnimation.attributeChecker(
|
||||
{attrs},
|
||||
'attrs',
|
||||
'POPAnimation.createAnimation'
|
||||
);
|
||||
POPAnimation.attributeChecker(
|
||||
{attrs: {type: typeName}},
|
||||
'attrs',
|
||||
'POPAnimation.createAnimation'
|
||||
);
|
||||
}
|
||||
|
||||
RKPOPAnimationManager.createAnimationInternal(tag, typeName, attrs);
|
||||
return tag;
|
||||
},
|
||||
|
||||
createSpringAnimation: function(attrs) {
|
||||
return this.createAnimation(this.Types.spring, attrs);
|
||||
},
|
||||
|
||||
createDecayAnimation: function(attrs) {
|
||||
return this.createAnimation(this.Types.decay, attrs);
|
||||
},
|
||||
|
||||
createLinearAnimation: function(attrs) {
|
||||
return this.createAnimation(this.Types.linear, attrs);
|
||||
},
|
||||
|
||||
createEaseInAnimation: function(attrs) {
|
||||
return this.createAnimation(this.Types.easeIn, attrs);
|
||||
},
|
||||
|
||||
createEaseOutAnimation: function(attrs) {
|
||||
return this.createAnimation(this.Types.easeOut, attrs);
|
||||
},
|
||||
|
||||
createEaseInEaseOutAnimation: function(attrs) {
|
||||
return this.createAnimation(this.Types.easeInEaseOut, attrs);
|
||||
},
|
||||
|
||||
addAnimation: function(nodeHandle, anim, callback) {
|
||||
RKPOPAnimationManager.addAnimation(nodeHandle, anim, callback);
|
||||
},
|
||||
|
||||
removeAnimation: function(nodeHandle, anim) {
|
||||
RKPOPAnimationManager.removeAnimation(nodeHandle, anim);
|
||||
},
|
||||
};
|
||||
|
||||
// Make sure that we correctly propagate RKPOPAnimationManager constants
|
||||
// to POPAnimation
|
||||
if (__DEV__) {
|
||||
var allProperties = merge(
|
||||
RKPOPAnimationManager.Properties,
|
||||
RKPOPAnimationManager.Properties
|
||||
);
|
||||
for (var key in allProperties) {
|
||||
invariant(
|
||||
POPAnimation.Properties[key] === RKPOPAnimationManager.Properties[key],
|
||||
'POPAnimation doesn\'t copy property ' + key + ' correctly'
|
||||
);
|
||||
}
|
||||
|
||||
var allTypes = merge(
|
||||
RKPOPAnimationManager.Types,
|
||||
RKPOPAnimationManager.Types
|
||||
);
|
||||
for (var key in allTypes) {
|
||||
invariant(
|
||||
POPAnimation.Types[key] === RKPOPAnimationManager.Types[key],
|
||||
'POPAnimation doesn\'t copy type ' + key + ' correctly'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = POPAnimation;
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule RCTEventEmitter
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ReactIOSEventEmitter = require('ReactIOSEventEmitter');
|
||||
|
||||
// Completely locally implemented - no native hooks.
|
||||
module.exports = ReactIOSEventEmitter;
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule RCTJSTimers
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var JSTimersExecution = require('JSTimersExecution');
|
||||
|
||||
var RCTJSTimers = JSTimersExecution;
|
||||
|
||||
module.exports = RCTJSTimers;
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule RKAlertManager
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RKAlertManager = require('NativeModulesDeprecated').RKAlertManager;
|
||||
|
||||
module.exports = RKAlertManager;
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule BatchedBridge
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var BatchedBridgeFactory = require('BatchedBridgeFactory');
|
||||
var MessageQueue = require('MessageQueue');
|
||||
|
||||
/**
|
||||
* Signature that matches the native IOS modules/methods that are exposed. We
|
||||
* indicate which ones accept a callback. The order of modules and methods
|
||||
* within them implicitly define their numerical *ID* that will be used to
|
||||
* describe method calls across the wire. This is so that memory is used
|
||||
* efficiently and we do not need to copy strings in native land - or across any
|
||||
* wire.
|
||||
*/
|
||||
|
||||
var remoteModulesConfig = __fbBatchedBridgeConfig.remoteModuleConfig;
|
||||
var localModulesConfig = __fbBatchedBridgeConfig.localModulesConfig;
|
||||
|
||||
|
||||
var BatchedBridge = BatchedBridgeFactory.create(
|
||||
MessageQueue,
|
||||
remoteModulesConfig,
|
||||
localModulesConfig
|
||||
);
|
||||
|
||||
BatchedBridge._config = remoteModulesConfig;
|
||||
|
||||
module.exports = BatchedBridge;
|
||||
@@ -1,106 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule BatchedBridgeFactory
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var invariant = require('invariant');
|
||||
var keyMirror = require('keyMirror');
|
||||
var mapObject = require('mapObject');
|
||||
var warning = require('warning');
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
var MethodTypes = keyMirror({
|
||||
remote: null,
|
||||
local: null,
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates remotely invokable modules.
|
||||
*/
|
||||
var BatchedBridgeFactory = {
|
||||
MethodTypes: MethodTypes,
|
||||
/**
|
||||
* @deprecated: Remove callsites and delete this method.
|
||||
*
|
||||
* @param {MessageQueue} messageQueue Message queue that has been created with
|
||||
* the `moduleConfig` (among others perhaps).
|
||||
* @param {object} moduleConfig Configuration of module names/method
|
||||
* names to callback types.
|
||||
* @return {object} Remote representation of configured module.
|
||||
*/
|
||||
_createDeprecatedBridgedModule: function(messageQueue, moduleConfig, moduleName) {
|
||||
var remoteModule = mapObject(moduleConfig.methods, function(methodConfig, memberName) {
|
||||
return methodConfig.type === MethodTypes.local ? null : function() {
|
||||
var lastArg = arguments.length ? arguments[arguments.length - 1] : null;
|
||||
var hasCB =
|
||||
typeof lastArg == 'function';
|
||||
var args = slice.call(arguments, 0, arguments.length - (hasCB ? 1 : 0));
|
||||
var cb = hasCB ? lastArg : null;
|
||||
return messageQueue.callDeprecated(moduleName, memberName, args, cb);
|
||||
};
|
||||
});
|
||||
for (var constName in moduleConfig.constants) {
|
||||
warning(!remoteModule[constName], 'saw constant and method named %s', constName);
|
||||
remoteModule[constName] = moduleConfig.constants[constName];
|
||||
}
|
||||
return remoteModule;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {MessageQueue} messageQueue Message queue that has been created with
|
||||
* the `moduleConfig` (among others perhaps).
|
||||
* @param {object} moduleConfig Configuration of module names/method
|
||||
* names to callback types.
|
||||
* @return {object} Remote representation of configured module.
|
||||
*/
|
||||
_createBridgedModule: function(messageQueue, moduleConfig, moduleName) {
|
||||
var remoteModule = mapObject(moduleConfig.methods, function(methodConfig, memberName) {
|
||||
return methodConfig.type === MethodTypes.local ? null : function() {
|
||||
var lastArg = arguments.length > 0 ? arguments[arguments.length - 1] : null;
|
||||
var secondLastArg = arguments.length > 1 ? arguments[arguments.length - 2] : null;
|
||||
var hasSuccCB = typeof lastArg === 'function';
|
||||
var hasErrorCB = typeof secondLastArg === 'function';
|
||||
var hasCBs = hasSuccCB;
|
||||
invariant(
|
||||
(hasSuccCB && hasErrorCB) || (!hasSuccCB && !hasErrorCB),
|
||||
'You must supply error callbacks and success callbacks or neither'
|
||||
);
|
||||
var args = slice.call(arguments, 0, arguments.length - (hasCBs ? 2 : 0));
|
||||
var onSucc = hasCBs ? lastArg : null;
|
||||
var onFail = hasCBs ? secondLastArg : null;
|
||||
return messageQueue.call(moduleName, memberName, args, onFail, onSucc);
|
||||
};
|
||||
});
|
||||
for (var constName in moduleConfig.constants) {
|
||||
warning(!remoteModule[constName], 'saw constant and method named %s', constName);
|
||||
remoteModule[constName] = moduleConfig.constants[constName];
|
||||
}
|
||||
return remoteModule;
|
||||
},
|
||||
|
||||
|
||||
create: function(MessageQueue, modulesConfig, localModulesConfig) {
|
||||
var messageQueue = new MessageQueue(modulesConfig, localModulesConfig);
|
||||
return {
|
||||
callFunction: messageQueue.callFunction.bind(messageQueue),
|
||||
callFunctionReturnFlushedQueue:
|
||||
messageQueue.callFunctionReturnFlushedQueue.bind(messageQueue),
|
||||
invokeCallback: messageQueue.invokeCallback.bind(messageQueue),
|
||||
invokeCallbackAndReturnFlushedQueue:
|
||||
messageQueue.invokeCallbackAndReturnFlushedQueue.bind(messageQueue),
|
||||
flushedQueue: messageQueue.flushedQueue.bind(messageQueue),
|
||||
// These deprecated modules do not accept an error callback.
|
||||
RemoteModulesDeprecated: mapObject(modulesConfig, this._createDeprecatedBridgedModule.bind(this, messageQueue)),
|
||||
RemoteModules: mapObject(modulesConfig, this._createBridgedModule.bind(this, messageQueue)),
|
||||
setLoggingEnabled: messageQueue.setLoggingEnabled.bind(messageQueue),
|
||||
getLoggedOutgoingItems: messageQueue.getLoggedOutgoingItems.bind(messageQueue),
|
||||
getLoggedIncomingItems: messageQueue.getLoggedIncomingItems.bind(messageQueue),
|
||||
replayPreviousLog: messageQueue.replayPreviousLog.bind(messageQueue)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = BatchedBridgeFactory;
|
||||
@@ -1,98 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ActivityIndicatorIOS
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var NativeModules = require('NativeModules');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var keyMirror = require('keyMirror');
|
||||
var merge = require('merge');
|
||||
|
||||
var SpinnerSize = keyMirror({
|
||||
large: null,
|
||||
small: null,
|
||||
});
|
||||
|
||||
var GRAY = '#999999';
|
||||
|
||||
var ActivityIndicatorIOS = React.createClass({
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Whether to show the indicator (true, the default) or hide it (false).
|
||||
*/
|
||||
animating: PropTypes.bool,
|
||||
/**
|
||||
* The foreground color of the spinner (default is gray).
|
||||
*/
|
||||
color: PropTypes.string,
|
||||
|
||||
size: PropTypes.oneOf([
|
||||
'small', // default
|
||||
'large',
|
||||
]),
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
animating: true,
|
||||
size: SpinnerSize.small,
|
||||
color: GRAY,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var style = styles.sizeSmall;
|
||||
var NativeConstants = NativeModules.RKUIManager.UIActivityIndicatorView.Constants;
|
||||
var activityIndicatorViewStyle = NativeConstants.StyleWhite;
|
||||
if (this.props.size === 'large') {
|
||||
style = styles.sizeLarge;
|
||||
activityIndicatorViewStyle = NativeConstants.StyleWhiteLarge;
|
||||
}
|
||||
return (
|
||||
<View
|
||||
style={[styles.container, style, this.props.style]}>
|
||||
<UIActivityIndicatorView
|
||||
activityIndicatorViewStyle={activityIndicatorViewStyle}
|
||||
animating={this.props.animating}
|
||||
color={this.props.color}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
sizeSmall: {
|
||||
height: 20,
|
||||
},
|
||||
sizeLarge: {
|
||||
height: 36,
|
||||
}
|
||||
});
|
||||
|
||||
var UIActivityIndicatorView = createReactIOSNativeComponentClass({
|
||||
validAttributes: merge(
|
||||
ReactIOSViewAttributes.UIView, {
|
||||
activityIndicatorViewStyle: true, // UIActivityIndicatorViewStyle=UIActivityIndicatorViewStyleWhite
|
||||
animating: true,
|
||||
color: true,
|
||||
}),
|
||||
uiViewClassName: 'UIActivityIndicatorView',
|
||||
});
|
||||
|
||||
module.exports = ActivityIndicatorIOS;
|
||||
@@ -1,155 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule DatePickerIOS
|
||||
*
|
||||
* This is a controlled component version of RKDatePickerIOS
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var RKDatePickerIOSConsts = require('NativeModules').RKUIManager.RCTDatePicker.Constants;
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass =
|
||||
require('createReactIOSNativeComponentClass');
|
||||
var merge = require('merge');
|
||||
|
||||
var DATEPICKER = 'datepicker';
|
||||
|
||||
/**
|
||||
* Use `DatePickerIOS` to render a date/time picker (selector) on iOS. This is
|
||||
* a controlled component, so you must hook in to the `onDateChange` callback
|
||||
* and update the `date` prop in order for the component to update, otherwise
|
||||
* the user's change will be reverted immediately to reflect `props.date` as the
|
||||
* source of truth.
|
||||
*/
|
||||
var DatePickerIOS = React.createClass({
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* The currently selected date.
|
||||
*/
|
||||
date: PropTypes.instanceOf(Date).isRequired,
|
||||
|
||||
/**
|
||||
* Date change handler.
|
||||
*
|
||||
* This is called when the user changes the date or time in the UI.
|
||||
* The first and only argument is a Date object representing the new
|
||||
* date and time.
|
||||
*/
|
||||
onDateChange: PropTypes.func.isRequired,
|
||||
|
||||
/**
|
||||
* Maximum date.
|
||||
*
|
||||
* Restricts the range of possible date/time values.
|
||||
*/
|
||||
maximumDate: PropTypes.instanceOf(Date),
|
||||
|
||||
/**
|
||||
* Minimum date.
|
||||
*
|
||||
* Restricts the range of possible date/time values.
|
||||
*/
|
||||
minimumDate: PropTypes.instanceOf(Date),
|
||||
|
||||
/**
|
||||
* The date picker mode.
|
||||
*
|
||||
* Valid modes on iOS are: 'date', 'time', 'datetime'.
|
||||
*/
|
||||
mode: PropTypes.oneOf(Object.keys(RKDatePickerIOSConsts.DatePickerModes)),
|
||||
|
||||
/**
|
||||
* The interval at which minutes can be selected.
|
||||
*/
|
||||
minuteInterval: PropTypes.oneOf([1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30]),
|
||||
|
||||
/**
|
||||
* Timezone offset in seconds.
|
||||
*
|
||||
* By default, the date picker will use the device's timezone. With this
|
||||
* parameter, it is possible to force a certain timezone offset. For
|
||||
* instance, to show times in Pacific Standard Time, pass -7 * 60.
|
||||
*/
|
||||
timeZoneOffsetInMinutes: PropTypes.number,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
mode: 'datetime',
|
||||
};
|
||||
},
|
||||
|
||||
_onChange: function(event) {
|
||||
var nativeTimeStamp = event.nativeEvent.timestamp;
|
||||
this.props.onDateChange && this.props.onDateChange(
|
||||
new Date(nativeTimeStamp)
|
||||
);
|
||||
this.props.onChange && this.props.onChange(event);
|
||||
|
||||
// We expect the onChange* handlers to be in charge of updating our `date`
|
||||
// prop. That way they can also disallow/undo/mutate the selection of
|
||||
// certain values. In other words, the embedder of this component should
|
||||
// be the source of truth, not the native component.
|
||||
var propsTimeStamp = this.props.date.getTime();
|
||||
if (nativeTimeStamp !== propsTimeStamp) {
|
||||
this.refs[DATEPICKER].setNativeProps({
|
||||
date: propsTimeStamp,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var props = this.props;
|
||||
return (
|
||||
<View style={props.style}>
|
||||
<RKDatePickerIOS
|
||||
ref={DATEPICKER}
|
||||
style={styles.rkDatePickerIOS}
|
||||
date={props.date.getTime()}
|
||||
maximumDate={
|
||||
props.maximumDate ? props.maximumDate.getTime() : undefined
|
||||
}
|
||||
minimumDate={
|
||||
props.minimumDate ? props.minimumDate.getTime() : undefined
|
||||
}
|
||||
mode={RKDatePickerIOSConsts.DatePickerModes[props.mode]}
|
||||
minuteInterval={props.minuteInterval}
|
||||
timeZoneOffsetInMinutes={props.timeZoneOffsetInMinutes}
|
||||
onChange={this._onChange}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
rkDatePickerIOS: {
|
||||
height: RKDatePickerIOSConsts.ComponentHeight,
|
||||
width: RKDatePickerIOSConsts.ComponentWidth,
|
||||
},
|
||||
});
|
||||
|
||||
var rkDatePickerIOSAttributes = merge(ReactIOSViewAttributes.UIView, {
|
||||
date: true,
|
||||
maximumDate: true,
|
||||
minimumDate: true,
|
||||
mode: true,
|
||||
minuteInterval: true,
|
||||
timeZoneOffsetInMinutes: true,
|
||||
});
|
||||
|
||||
var RKDatePickerIOS = createReactIOSNativeComponentClass({
|
||||
validAttributes: rkDatePickerIOSAttributes,
|
||||
uiViewClassName: 'RCTDatePicker',
|
||||
});
|
||||
|
||||
module.exports = DatePickerIOS;
|
||||
@@ -1,475 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ListView
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var ListViewDataSource = require('ListViewDataSource');
|
||||
var React = require('React');
|
||||
var RKUIManager = require('NativeModules').RKUIManager;
|
||||
var ScrollView = require('ScrollView');
|
||||
var ScrollResponder = require('ScrollResponder');
|
||||
var StaticRenderer = require('StaticRenderer');
|
||||
var TimerMixin = require('TimerMixin');
|
||||
|
||||
var logError = require('logError');
|
||||
var merge = require('merge');
|
||||
var isEmpty = require('isEmpty');
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
|
||||
var DEFAULT_PAGE_SIZE = 1;
|
||||
var DEFAULT_INITIAL_ROWS = 10;
|
||||
var DEFAULT_SCROLL_RENDER_AHEAD = 1000;
|
||||
var DEFAULT_END_REACHED_THRESHOLD = 1000;
|
||||
var DEFAULT_SCROLL_CALLBACK_THROTTLE = 50;
|
||||
var RENDER_INTERVAL = 20;
|
||||
var SCROLLVIEW_REF = 'listviewscroll';
|
||||
|
||||
|
||||
/**
|
||||
* ListView - A core component designed for efficient display of vertically
|
||||
* scrolling lists of changing data. The minimal API is to create a
|
||||
* `ListView.DataSource`, populate it with a simple array of data blobs, and
|
||||
* instantiate a `ListView` component with that data source and a `renderRow`
|
||||
* callback which takes a blob from the data array and returns a renderable
|
||||
* component.
|
||||
*
|
||||
* Minimal example:
|
||||
*
|
||||
* ```
|
||||
* getInitialState: function() {
|
||||
* var ds = new ListViewDataSource({rowHasChanged: (r1, r2) => r1 !== r2});
|
||||
* return {
|
||||
* dataSource: ds.cloneWithRows(['row 1', 'row 2']),
|
||||
* };
|
||||
* },
|
||||
*
|
||||
* render: function() {
|
||||
* return (
|
||||
* <ListView
|
||||
* dataSource={this.state.dataSource}
|
||||
* renderRow={(rowData) => <Text>{rowData}</Text>}
|
||||
* />
|
||||
* );
|
||||
* },
|
||||
* ```
|
||||
*
|
||||
* ListView also supports more advanced features, including sections with sticky
|
||||
* section headers, header and footer support, callbacks on reaching the end of
|
||||
* the available data (`onEndReached`) and on the set of rows that are visible
|
||||
* in the device viewport change (`onChangeVisibleRows`), and several
|
||||
* performance optimizations.
|
||||
*
|
||||
* There are a few performance operations designed to make ListView scroll
|
||||
* smoothly while dynamically loading potentially very large (or conceptually
|
||||
* infinite) data sets:
|
||||
*
|
||||
* * Only re-render changed rows - the hasRowChanged function provided to the
|
||||
* data source tells the ListView if it needs to re-render a row because the
|
||||
* source data has changed - see ListViewDataSource for more details.
|
||||
*
|
||||
* * Rate-limited row rendering - By default, only one row is rendered per
|
||||
* event-loop (customizable with the `pageSize` prop). This breaks up the
|
||||
* work into smaller chunks to reduce the chance of dropping frames while
|
||||
* rendering rows.
|
||||
*/
|
||||
|
||||
var ListView = React.createClass({
|
||||
mixins: [ScrollResponder.Mixin, TimerMixin],
|
||||
|
||||
statics: {
|
||||
DataSource: ListViewDataSource,
|
||||
},
|
||||
|
||||
/**
|
||||
* You must provide a renderRow function. If you omit any of the other render
|
||||
* functions, ListView will simply skip rendering them.
|
||||
*
|
||||
* - renderRow(rowData, sectionID, rowID);
|
||||
* - renderSectionHeader(sectionData, sectionID);
|
||||
*/
|
||||
propTypes: {
|
||||
...ScrollView.propTypes,
|
||||
|
||||
dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired,
|
||||
/**
|
||||
* (rowData, sectionID, rowID) => renderable
|
||||
* Takes a data entry from the data source and its ids and should return
|
||||
* a renderable component to be rendered as the row. By default the data
|
||||
* is exactly what was put into the data source, but it's also possible to
|
||||
* provide custom extractors.
|
||||
*/
|
||||
renderRow: PropTypes.func.isRequired,
|
||||
/**
|
||||
* How many rows to render on initial component mount. Use this to make
|
||||
* it so that the first screen worth of data apears at one time instead of
|
||||
* over the course of multiple frames.
|
||||
*/
|
||||
initialListSize: PropTypes.number,
|
||||
/**
|
||||
* Called when all rows have been rendered and the list has been scrolled
|
||||
* to within onEndReachedThreshold of the bottom. The native scroll
|
||||
* event is provided.
|
||||
*/
|
||||
onEndReached: PropTypes.func,
|
||||
/**
|
||||
* Threshold in pixels for onEndReached.
|
||||
*/
|
||||
onEndReachedThreshold: PropTypes.number,
|
||||
/**
|
||||
* Number of rows to render per event loop.
|
||||
*/
|
||||
pageSize: PropTypes.number,
|
||||
/**
|
||||
* () => renderable
|
||||
*
|
||||
* The header and footer are always rendered (if these props are provided)
|
||||
* on every render pass. If they are expensive to re-render, wrap them
|
||||
* in StaticContainer or other mechanism as appropriate. Footer is always
|
||||
* at the bottom of the list, and header at the top, on every render pass.
|
||||
*/
|
||||
renderFooter: PropTypes.func,
|
||||
renderHeader: PropTypes.func,
|
||||
/**
|
||||
* (sectionData, sectionID) => renderable
|
||||
*
|
||||
* If provided, a sticky header is rendered for this section. The sticky
|
||||
* behavior means that it will scroll with the content at the top of the
|
||||
* section until it reaches the top of the screen, at which point it will
|
||||
* stick to the top until it is pushed off the screen by the next section
|
||||
* header.
|
||||
*/
|
||||
renderSectionHeader: PropTypes.func,
|
||||
/**
|
||||
* How early to start rendering rows before they come on screen, in
|
||||
* pixels.
|
||||
*/
|
||||
scrollRenderAheadDistance: React.PropTypes.number,
|
||||
/**
|
||||
* (visibleRows, changedRows) => void
|
||||
*
|
||||
* Called when the set of visible rows changes. `visibleRows` maps
|
||||
* { sectionID: { rowID: true }} for all the visible rows, and
|
||||
* `changedRows` maps { sectionID: { rowID: true | false }} for the rows
|
||||
* that have changed their visibility, with true indicating visible, and
|
||||
* false indicating the view has moved out of view.
|
||||
*/
|
||||
onChangeVisibleRows: React.PropTypes.func,
|
||||
/**
|
||||
* An experimental performance optimization for improving scroll perf of
|
||||
* large lists, used in conjunction with overflow: 'hidden' on the row
|
||||
* containers. Use at your own risk.
|
||||
*/
|
||||
removeClippedSubviews: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
/**
|
||||
* Exports some data, e.g. for perf investigations or analytics.
|
||||
*/
|
||||
getMetrics: function() {
|
||||
return {
|
||||
contentHeight: this.scrollProperties.contentHeight,
|
||||
totalRows: this.props.dataSource.getRowCount(),
|
||||
renderedRows: this.state.curRenderedRowsCount,
|
||||
visibleRows: Object.keys(this._visibleRows).length,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides a handle to the underlying scroll responder to support operations
|
||||
* such as scrollTo.
|
||||
*/
|
||||
getScrollResponder: function() {
|
||||
return this.refs[SCROLLVIEW_REF];
|
||||
},
|
||||
|
||||
setNativeProps: function(props) {
|
||||
this.refs[SCROLLVIEW_REF].setNativeProps(props);
|
||||
},
|
||||
|
||||
/**
|
||||
* React life cycle hooks.
|
||||
*/
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
initialListSize: DEFAULT_INITIAL_ROWS,
|
||||
pageSize: DEFAULT_PAGE_SIZE,
|
||||
scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD,
|
||||
onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
curRenderedRowsCount: this.props.initialListSize,
|
||||
prevRenderedRowsCount: 0,
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
// this data should never trigger a render pass, so don't put in state
|
||||
this.scrollProperties = {
|
||||
visibleHeight: null,
|
||||
contentHeight: null,
|
||||
offsetY: 0
|
||||
};
|
||||
this._childFrames = [];
|
||||
this._visibleRows = {};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// do this in animation frame until componentDidMount actually runs after
|
||||
// the component is laid out
|
||||
this.requestAnimationFrame(() => {
|
||||
this._measureAndUpdateScrollProps();
|
||||
this.setInterval(this._renderMoreRowsIfNeeded, RENDER_INTERVAL);
|
||||
});
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
if (this.props.dataSource !== nextProps.dataSource) {
|
||||
this.setState({prevRenderedRowsCount: 0});
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var bodyComponents = [];
|
||||
|
||||
var dataSource = this.props.dataSource;
|
||||
var allRowIDs = dataSource.rowIdentities;
|
||||
var rowCount = 0;
|
||||
var sectionHeaderIndices = [];
|
||||
|
||||
var header = this.props.renderHeader && this.props.renderHeader();
|
||||
var footer = this.props.renderFooter && this.props.renderFooter();
|
||||
var totalIndex = header ? 1 : 0;
|
||||
|
||||
for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) {
|
||||
var sectionID = dataSource.sectionIdentities[sectionIdx];
|
||||
var rowIDs = allRowIDs[sectionIdx];
|
||||
if (rowIDs.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.props.renderSectionHeader) {
|
||||
var shouldUpdateHeader = rowCount >= this.state.prevRenderedRowsCount &&
|
||||
dataSource.sectionHeaderShouldUpdate(sectionIdx);
|
||||
bodyComponents.push(
|
||||
<StaticRenderer
|
||||
key={'s_' + sectionID}
|
||||
shouldUpdate={!!shouldUpdateHeader}
|
||||
render={this.props.renderSectionHeader.bind(
|
||||
null,
|
||||
dataSource.getSectionHeaderData(sectionIdx),
|
||||
sectionID
|
||||
)}
|
||||
/>
|
||||
);
|
||||
sectionHeaderIndices.push(totalIndex++);
|
||||
}
|
||||
|
||||
for (var rowIdx = 0; rowIdx < rowIDs.length; rowIdx++) {
|
||||
var rowID = rowIDs[rowIdx];
|
||||
var comboID = sectionID + rowID;
|
||||
var shouldUpdateRow = rowCount >= this.state.prevRenderedRowsCount &&
|
||||
dataSource.rowShouldUpdate(sectionIdx, rowIdx);
|
||||
var row =
|
||||
<StaticRenderer
|
||||
key={'r_' + comboID}
|
||||
shouldUpdate={!!shouldUpdateRow}
|
||||
render={this.props.renderRow.bind(
|
||||
null,
|
||||
dataSource.getRowData(sectionIdx, rowIdx),
|
||||
sectionID,
|
||||
rowID
|
||||
)}
|
||||
/>;
|
||||
bodyComponents.push(row);
|
||||
totalIndex++;
|
||||
if (++rowCount === this.state.curRenderedRowsCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rowCount >= this.state.curRenderedRowsCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var props = merge(
|
||||
this.props, {
|
||||
onScroll: this._onScroll,
|
||||
stickyHeaderIndices: sectionHeaderIndices,
|
||||
}
|
||||
);
|
||||
if (!props.throttleScrollCallbackMS) {
|
||||
props.throttleScrollCallbackMS = DEFAULT_SCROLL_CALLBACK_THROTTLE;
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView {...props}
|
||||
ref={SCROLLVIEW_REF}>
|
||||
{header}
|
||||
{bodyComponents}
|
||||
{footer}
|
||||
</ScrollView>
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Private methods
|
||||
*/
|
||||
|
||||
_measureAndUpdateScrollProps: function() {
|
||||
RKUIManager.measureLayout(
|
||||
this.refs[SCROLLVIEW_REF].getInnerViewNode(),
|
||||
this.refs[SCROLLVIEW_REF].getNodeHandle(),
|
||||
logError,
|
||||
this._setScrollContentHeight
|
||||
);
|
||||
RKUIManager.measureLayoutRelativeToParent(
|
||||
this.refs[SCROLLVIEW_REF].getNodeHandle(),
|
||||
logError,
|
||||
this._setScrollVisibleHeight
|
||||
);
|
||||
},
|
||||
|
||||
_setScrollContentHeight: function(left, top, width, height) {
|
||||
this.scrollProperties.contentHeight = height;
|
||||
},
|
||||
|
||||
_setScrollVisibleHeight: function(left, top, width, height) {
|
||||
this.scrollProperties.visibleHeight = height;
|
||||
this._updateVisibleRows();
|
||||
},
|
||||
|
||||
_renderMoreRowsIfNeeded: function() {
|
||||
if (this.scrollProperties.contentHeight === null ||
|
||||
this.scrollProperties.visibleHeight === null ||
|
||||
this.state.curRenderedRowsCount === this.props.dataSource.getRowCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var distanceFromEnd = this._getDistanceFromEnd(this.scrollProperties);
|
||||
if (distanceFromEnd < this.props.scrollRenderAheadDistance) {
|
||||
this._pageInNewRows();
|
||||
}
|
||||
},
|
||||
|
||||
_pageInNewRows: function() {
|
||||
var rowsToRender = Math.min(
|
||||
this.state.curRenderedRowsCount + this.props.pageSize,
|
||||
this.props.dataSource.getRowCount()
|
||||
);
|
||||
this.setState(
|
||||
{
|
||||
prevRenderedRowsCount: this.state.curRenderedRowsCount,
|
||||
curRenderedRowsCount: rowsToRender
|
||||
},
|
||||
() => {
|
||||
this._measureAndUpdateScrollProps();
|
||||
this.setState({
|
||||
prevRenderedRowsCount: this.state.curRenderedRowsCount,
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_getDistanceFromEnd: function(scrollProperties) {
|
||||
return scrollProperties.contentHeight -
|
||||
scrollProperties.visibleHeight -
|
||||
scrollProperties.offsetY;
|
||||
},
|
||||
|
||||
_updateVisibleRows: function(e) {
|
||||
if (!this.props.onChangeVisibleRows) {
|
||||
return; // No need to compute visible rows if there is no callback
|
||||
}
|
||||
var updatedFrames = e && e.nativeEvent.updatedChildFrames;
|
||||
if (updatedFrames) {
|
||||
updatedFrames.forEach((frame) => {
|
||||
this._childFrames[frame.index] = merge(frame);
|
||||
});
|
||||
}
|
||||
var dataSource = this.props.dataSource;
|
||||
var visibleTop = this.scrollProperties.offsetY;
|
||||
var visibleBottom = visibleTop + this.scrollProperties.visibleHeight;
|
||||
var allRowIDs = dataSource.rowIdentities;
|
||||
|
||||
var header = this.props.renderHeader && this.props.renderHeader();
|
||||
var totalIndex = header ? 1 : 0;
|
||||
var visibilityChanged = false;
|
||||
var changedRows = {};
|
||||
for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) {
|
||||
var rowIDs = allRowIDs[sectionIdx];
|
||||
if (rowIDs.length === 0) {
|
||||
continue;
|
||||
}
|
||||
var sectionID = dataSource.sectionIdentities[sectionIdx];
|
||||
if (this.props.renderSectionHeader) {
|
||||
totalIndex++;
|
||||
}
|
||||
var visibleSection = this._visibleRows[sectionID];
|
||||
if (!visibleSection) {
|
||||
visibleSection = {};
|
||||
}
|
||||
for (var rowIdx = 0; rowIdx < rowIDs.length; rowIdx++) {
|
||||
var rowID = rowIDs[rowIdx];
|
||||
var frame = this._childFrames[totalIndex];
|
||||
totalIndex++;
|
||||
if (!frame) {
|
||||
break;
|
||||
}
|
||||
var rowVisible = visibleSection[rowID];
|
||||
var top = frame.y;
|
||||
var bottom = top + frame.height;
|
||||
if (top > visibleBottom || bottom < visibleTop) {
|
||||
if (rowVisible) {
|
||||
visibilityChanged = true;
|
||||
delete visibleSection[rowID];
|
||||
if (!changedRows[sectionID]) {
|
||||
changedRows[sectionID] = {};
|
||||
}
|
||||
changedRows[sectionID][rowID] = false;
|
||||
}
|
||||
} else if (!rowVisible) {
|
||||
visibilityChanged = true;
|
||||
visibleSection[rowID] = true;
|
||||
if (!changedRows[sectionID]) {
|
||||
changedRows[sectionID] = {};
|
||||
}
|
||||
changedRows[sectionID][rowID] = true;
|
||||
}
|
||||
}
|
||||
if (!isEmpty(visibleSection)) {
|
||||
this._visibleRows[sectionID] = visibleSection;
|
||||
} else if (this._visibleRows[sectionID]) {
|
||||
delete this._visibleRows[sectionID];
|
||||
}
|
||||
}
|
||||
visibilityChanged && this.props.onChangeVisibleRows(this._visibleRows, changedRows);
|
||||
},
|
||||
|
||||
_onScroll: function(e) {
|
||||
this.scrollProperties.visibleHeight = e.nativeEvent.layoutMeasurement.height;
|
||||
this.scrollProperties.contentHeight = e.nativeEvent.contentSize.height;
|
||||
this.scrollProperties.offsetY = e.nativeEvent.contentOffset.y;
|
||||
this._updateVisibleRows(e);
|
||||
var nearEnd = this._getDistanceFromEnd(this.scrollProperties) < this.props.onEndReachedThreshold;
|
||||
if (nearEnd &&
|
||||
this.props.onEndReached &&
|
||||
this.scrollProperties.contentHeight !== this._sentEndForContentHeight &&
|
||||
this.state.curRenderedRowsCount === this.props.dataSource.getRowCount()) {
|
||||
this._sentEndForContentHeight = this.scrollProperties.contentHeight;
|
||||
this.props.onEndReached(e);
|
||||
} else {
|
||||
this._renderMoreRowsIfNeeded();
|
||||
}
|
||||
|
||||
this.props.onScroll && this.props.onScroll(e);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = ListView;
|
||||
@@ -1,379 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ListViewDataSource
|
||||
* @typechecks
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var invariant = require('invariant');
|
||||
var isEmpty = require('isEmpty');
|
||||
var warning = require('warning');
|
||||
|
||||
/**
|
||||
* ListViewDataSource - Provides efficient data processing and access to the
|
||||
* ListView component. A ListViewDataSource is created with functions for
|
||||
* extracting data from the input blob, and comparing elements (with default
|
||||
* implementations for convenience). The input blob can be as simple as an
|
||||
* array of strings, or an object with rows nested inside section objects.
|
||||
*
|
||||
* To update the data in the datasource, use `cloneWithRows` (or
|
||||
* `cloneWithRowsAndSections` if you care about sections). The data in the
|
||||
* data source is immutable, so you can't modify it directly. The clone methods
|
||||
* suck in the new data and compute a diff for each row so ListView knows
|
||||
* whether to re-render it or not.
|
||||
*
|
||||
* In this example, a component receives data in chunks, handled by
|
||||
* `_onDataArrived`, which concats the new data onto the old data and updates the
|
||||
* data source. We use `concat` to create a new array - mutating `this._data`,
|
||||
* e.g. with `this._data.push(newRowData)`, would be an error. `_rowHasChanged`
|
||||
* understands the shape of the row data and knows how to efficiently compare
|
||||
* it.
|
||||
*
|
||||
* getInitialState: function() {
|
||||
* var ds = new ListViewDataSource({rowHasChanged: this._rowHasChanged});
|
||||
* return {ds};
|
||||
* },
|
||||
* _onDataArrived(newData) {
|
||||
* this._data = this._data.concat(newData);
|
||||
* this.setState({
|
||||
* ds: this.state.ds.cloneWithRows(this._data)
|
||||
* });
|
||||
* }
|
||||
*/
|
||||
|
||||
function defaultGetRowData(
|
||||
dataBlob: any,
|
||||
sectionID: number | string,
|
||||
rowID: number | string
|
||||
): any {
|
||||
return dataBlob[sectionID][rowID];
|
||||
}
|
||||
|
||||
function defaultGetSectionHeaderData(
|
||||
dataBlob: any,
|
||||
sectionID: number | string
|
||||
): any {
|
||||
return dataBlob[sectionID];
|
||||
}
|
||||
|
||||
type differType = (data1: any, data2: any) => bool;
|
||||
|
||||
type ParamType = {
|
||||
rowHasChanged: differType;
|
||||
getRowData: ?typeof defaultGetRowData;
|
||||
sectionHeaderHasChanged: ?differType;
|
||||
getSectionHeaderData: ?typeof defaultGetSectionHeaderData;
|
||||
}
|
||||
|
||||
class ListViewDataSource {
|
||||
|
||||
/**
|
||||
* @param {ParamType} params
|
||||
*
|
||||
* You can provide custom extraction and 'hasChanged' functions for section
|
||||
* headers and rows. If absent, data will be extracted with the
|
||||
* `defaultGetRowData` and `defaultGetSectionHeaderData` functions.
|
||||
*
|
||||
* - getRowData(dataBlob, sectionID, rowID);
|
||||
* - getSectionHeaderData(dataBlob, sectionID);
|
||||
* - rowHasChanged(prevRowData, nextRowData);
|
||||
* - sectionHeaderHasChanged(prevSectionData, nextSectionData);
|
||||
*/
|
||||
constructor(params: ParamType) {
|
||||
invariant(
|
||||
params && typeof params.rowHasChanged === 'function',
|
||||
'Must provide a rowHasChanged function.'
|
||||
);
|
||||
this._rowHasChanged = params.rowHasChanged;
|
||||
this._getRowData = params.getRowData || defaultGetRowData;
|
||||
this._sectionHeaderHasChanged = params.sectionHeaderHasChanged;
|
||||
this._getSectionHeaderData =
|
||||
params.getSectionHeaderData || defaultGetSectionHeaderData;
|
||||
|
||||
this._dataBlob = null;
|
||||
this._dirtyRows = [];
|
||||
this._dirtySections = [];
|
||||
this._cachedRowCount = 0;
|
||||
|
||||
// These two private variables are accessed by outsiders because ListView
|
||||
// uses them to iterate over the data in this class.
|
||||
this.rowIdentities = [];
|
||||
this.sectionIdentities = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} dataBlob -- This is an arbitrary blob of data. An extractor
|
||||
* function was defined at construction time. The default extractor assumes
|
||||
* the data is a plain array or keyed object.
|
||||
*/
|
||||
cloneWithRows(
|
||||
dataBlob: Array<any> | {[key: string]: any},
|
||||
rowIdentities: ?Array<string>
|
||||
): ListViewDataSource {
|
||||
var rowIds = rowIdentities ? [rowIdentities] : null;
|
||||
if (!this._sectionHeaderHasChanged) {
|
||||
this._sectionHeaderHasChanged = () => false;
|
||||
}
|
||||
return this.cloneWithRowsAndSections({s1: dataBlob}, ['s1'], rowIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} dataBlob -- This is an arbitrary blob of data. An extractor
|
||||
* function was defined at construction time. The default extractor assumes
|
||||
* the data is a nested array or keyed object of the form:
|
||||
*
|
||||
* { sectionID_1: { rowID_1: <rowData1>, ... }, ... }
|
||||
*
|
||||
* or
|
||||
*
|
||||
* [ [ <rowData1>, <rowData2>, ... ], ... ]
|
||||
*
|
||||
* @param {array} sectionIdentities -- This is an array of identifiers for
|
||||
* sections. ie. ['s1', 's2', ...]. If not provided, it's assumed that the
|
||||
* keys of dataBlob are the section identities.
|
||||
* @param {array} rowIdentities -- This is a 2D array of identifiers for rows.
|
||||
* ie. [['a1', 'a2'], ['b1', 'b2', 'b3'], ...]. If not provided, it's
|
||||
* assumed that the keys of the section data are the row identities.
|
||||
*
|
||||
* Note: this returns a new object!
|
||||
*/
|
||||
cloneWithRowsAndSections(
|
||||
dataBlob: any,
|
||||
sectionIdentities: ?Array<string>,
|
||||
rowIdentities: ?Array<Array<string>>
|
||||
): ListViewDataSource {
|
||||
invariant(
|
||||
typeof this._sectionHeaderHasChanged === 'function',
|
||||
'Must provide a sectionHeaderHasChanged function with section data.'
|
||||
);
|
||||
var newSource = new ListViewDataSource({
|
||||
getRowData: this._getRowData,
|
||||
getSectionHeaderData: this._getSectionHeaderData,
|
||||
rowHasChanged: this._rowHasChanged,
|
||||
sectionHeaderHasChanged: this._sectionHeaderHasChanged,
|
||||
});
|
||||
newSource._dataBlob = dataBlob;
|
||||
if (sectionIdentities) {
|
||||
newSource.sectionIdentities = sectionIdentities;
|
||||
} else {
|
||||
newSource.sectionIdentities = Object.keys(dataBlob);
|
||||
}
|
||||
if (rowIdentities) {
|
||||
newSource.rowIdentities = rowIdentities;
|
||||
} else {
|
||||
newSource.rowIdentities = [];
|
||||
newSource.sectionIdentities.forEach((sectionID) => {
|
||||
newSource.rowIdentities.push(Object.keys(dataBlob[sectionID]));
|
||||
});
|
||||
}
|
||||
newSource._cachedRowCount = countRows(newSource.rowIdentities);
|
||||
|
||||
newSource._calculateDirtyArrays(
|
||||
this._dataBlob,
|
||||
this.sectionIdentities,
|
||||
this.rowIdentities
|
||||
);
|
||||
|
||||
return newSource;
|
||||
}
|
||||
|
||||
getRowCount(): number {
|
||||
return this._cachedRowCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} sectionIndex
|
||||
* @param {number} rowIndex
|
||||
*
|
||||
* Returns if the row is dirtied and needs to be rerendered
|
||||
*/
|
||||
rowShouldUpdate(sectionIndex: number, rowIndex: number): bool {
|
||||
var needsUpdate = this._dirtyRows[sectionIndex][rowIndex];
|
||||
warning(needsUpdate !== undefined,
|
||||
'missing dirtyBit for section, row: ' + sectionIndex + ', ' + rowIndex);
|
||||
return needsUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} sectionIndex
|
||||
* @param {number} rowIndex
|
||||
*
|
||||
* Gets the data required to render the row.
|
||||
*/
|
||||
getRowData(sectionIndex: number, rowIndex: number): any {
|
||||
var sectionID = this.sectionIdentities[sectionIndex];
|
||||
var rowID = this.rowIdentities[sectionIndex][rowIndex];
|
||||
warning(
|
||||
sectionID !== undefined && rowID !== undefined,
|
||||
'rendering invalid section, row: ' + sectionIndex + ', ' + rowIndex
|
||||
);
|
||||
return this._getRowData(this._dataBlob, sectionID, rowID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
*
|
||||
* Gets the rowID at index provided if the dataSource arrays were flattened
|
||||
*/
|
||||
getRowIDForFlatIndex(index: number): string {
|
||||
var accessIndex = index;
|
||||
for (var ii = 0; ii < this.sectionIdentities.length; ii++) {
|
||||
if (accessIndex >= this.rowIdentities[ii].length) {
|
||||
accessIndex -= this.rowIdentities[ii].length;
|
||||
} else {
|
||||
return this.rowIdentities[ii][accessIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
*
|
||||
* Gets the sectionID at index provided if the dataSource arrays were flattened
|
||||
*/
|
||||
getSectionIDForFlatIndex(index: number): string {
|
||||
var accessIndex = index;
|
||||
for (var ii = 0; ii < this.sectionIdentities.length; ii++) {
|
||||
if (accessIndex >= this.rowIdentities[ii].length) {
|
||||
accessIndex -= this.rowIdentities[ii].length;
|
||||
} else {
|
||||
return this.sectionIdentities[ii];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing the number of rows in each section
|
||||
*/
|
||||
getSectionLengths(): Array<number> {
|
||||
var results = [];
|
||||
for (var ii = 0; ii < this.sectionIdentities.length; ii++) {
|
||||
results.push(this.rowIdentities[ii].length);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} sectionIndex
|
||||
*
|
||||
* Returns if the section header is dirtied and needs to be rerendered
|
||||
*/
|
||||
sectionHeaderShouldUpdate(sectionIndex: number): bool {
|
||||
var needsUpdate = this._dirtySections[sectionIndex];
|
||||
warning(needsUpdate !== undefined,
|
||||
'missing dirtyBit for section: ' + sectionIndex);
|
||||
return needsUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} sectionIndex
|
||||
*
|
||||
* Gets the data required to render the section header
|
||||
*/
|
||||
getSectionHeaderData(sectionIndex: number): any {
|
||||
if (!this._getSectionHeaderData) {
|
||||
return null;
|
||||
}
|
||||
var sectionID = this.sectionIdentities[sectionIndex];
|
||||
warning(sectionID !== undefined,
|
||||
'renderSection called on invalid section: ' + sectionIndex);
|
||||
return this._getSectionHeaderData(this._dataBlob, sectionID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private members and methods.
|
||||
*/
|
||||
|
||||
_getRowData: typeof defaultGetRowData;
|
||||
_getSectionHeaderData: typeof defaultGetSectionHeaderData;
|
||||
_rowHasChanged: differType;
|
||||
_sectionHeaderHasChanged: ?differType;
|
||||
|
||||
_dataBlob: any;
|
||||
_dirtyRows: Array<Array<bool>>;
|
||||
_dirtySections: Array<bool>;
|
||||
_cachedRowCount: number;
|
||||
|
||||
// These two 'protected' variables are accessed by ListView to iterate over
|
||||
// the data in this class.
|
||||
rowIdentities: Array<Array<string>>;
|
||||
sectionIdentities: Array<string>;
|
||||
|
||||
_calculateDirtyArrays(
|
||||
prevDataBlob: any,
|
||||
prevSectionIDs: Array<string>,
|
||||
prevRowIDs: Array<Array<string>>
|
||||
): void {
|
||||
// construct a hashmap of the existing (old) id arrays
|
||||
var prevSectionsHash = keyedDictionaryFromArray(prevSectionIDs);
|
||||
var prevRowsHash = {};
|
||||
for (var ii = 0; ii < prevRowIDs.length; ii++) {
|
||||
var sectionID = prevSectionIDs[ii];
|
||||
warning(
|
||||
!prevRowsHash[sectionID],
|
||||
'SectionID appears more than once: ' + sectionID
|
||||
);
|
||||
prevRowsHash[sectionID] = keyedDictionaryFromArray(prevRowIDs[ii]);
|
||||
}
|
||||
|
||||
// compare the 2 identity array and get the dirtied rows
|
||||
this._dirtySections = [];
|
||||
this._dirtyRows = [];
|
||||
|
||||
var dirty;
|
||||
for (var sIndex = 0; sIndex < this.sectionIdentities.length; sIndex++) {
|
||||
var sectionID = this.sectionIdentities[sIndex];
|
||||
// dirty if the sectionHeader is new or _sectionHasChanged is true
|
||||
dirty = !prevSectionsHash[sectionID];
|
||||
var sectionHeaderHasChanged = this._sectionHeaderHasChanged;
|
||||
if (!dirty && sectionHeaderHasChanged) {
|
||||
dirty = sectionHeaderHasChanged(
|
||||
this._getSectionHeaderData(prevDataBlob, sectionID),
|
||||
this._getSectionHeaderData(this._dataBlob, sectionID)
|
||||
);
|
||||
}
|
||||
this._dirtySections.push(!!dirty);
|
||||
|
||||
this._dirtyRows[sIndex] = [];
|
||||
for (var rIndex = 0; rIndex < this.rowIdentities[sIndex].length; rIndex++) {
|
||||
var rowID = this.rowIdentities[sIndex][rIndex];
|
||||
// dirty if the section is new, row is new or _rowHasChanged is true
|
||||
dirty =
|
||||
!prevSectionsHash[sectionID] ||
|
||||
!prevRowsHash[sectionID][rowID] ||
|
||||
this._rowHasChanged(
|
||||
this._getRowData(prevDataBlob, sectionID, rowID),
|
||||
this._getRowData(this._dataBlob, sectionID, rowID)
|
||||
);
|
||||
this._dirtyRows[sIndex].push(!!dirty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function countRows(allRowIDs) {
|
||||
var totalRows = 0;
|
||||
for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) {
|
||||
var rowIDs = allRowIDs[sectionIdx];
|
||||
totalRows += rowIDs.length;
|
||||
}
|
||||
return totalRows;
|
||||
}
|
||||
|
||||
function keyedDictionaryFromArray(arr) {
|
||||
if (isEmpty(arr)) {
|
||||
return {};
|
||||
}
|
||||
var result = {};
|
||||
for (var ii = 0; ii < arr.length; ii++) {
|
||||
var key = arr[ii];
|
||||
warning(!result[key], 'Value appears more than once in array: ' + key);
|
||||
result[key] = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
module.exports = ListViewDataSource;
|
||||
@@ -1,566 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule NavigatorIOS
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var EventEmitter = require('EventEmitter');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var { RKNavigatorManager } = require('NativeModules');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StaticContainer = require('StaticContainer.react');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass =
|
||||
require('createReactIOSNativeComponentClass');
|
||||
var invariant = require('invariant');
|
||||
var logError = require('logError');
|
||||
var merge = require('merge');
|
||||
|
||||
var TRANSITIONER_REF = 'transitionerRef';
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
|
||||
var __uid = 0;
|
||||
function getuid() {
|
||||
return __uid++;
|
||||
}
|
||||
|
||||
var RKNavigator = createReactIOSNativeComponentClass({
|
||||
validAttributes: merge(ReactIOSViewAttributes.UIView, {
|
||||
requestedTopOfStack: true
|
||||
}),
|
||||
uiViewClassName: 'RCTNavigator',
|
||||
});
|
||||
|
||||
var RKNavigatorItem = createReactIOSNativeComponentClass({
|
||||
validAttributes: {
|
||||
// TODO: Remove or fix the attributes that are not fully functional.
|
||||
// NavigatorIOS does not use them all, because some are problematic
|
||||
title: true,
|
||||
barTintColor: true,
|
||||
rightButtonTitle: true,
|
||||
onNavRightButtonTap: true,
|
||||
tintColor: true,
|
||||
backButtonTitle: true,
|
||||
titleTextColor: true,
|
||||
style: true,
|
||||
},
|
||||
uiViewClassName: 'RCTNavItem',
|
||||
});
|
||||
|
||||
var NavigatorTransitionerIOS = React.createClass({
|
||||
requestSchedulingNavigation: function(cb) {
|
||||
RKNavigatorManager.requestSchedulingJavaScriptNavigation(
|
||||
this.getNodeHandle(),
|
||||
logError,
|
||||
cb
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<RKNavigator {...this.props}/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Think of `<NavigatorIOS>` as simply a component that renders an
|
||||
* `RKNavigator`, and moves the `RKNavigator`'s `requestedTopOfStack` pointer
|
||||
* forward and backward. The `RKNavigator` interprets changes in
|
||||
* `requestedTopOfStack` to be pushes and pops of children that are rendered.
|
||||
* `<NavigatorIOS>` always ensures that whenever the `requestedTopOfStack`
|
||||
* pointer is moved, that we've also rendered enough children so that the
|
||||
* `RKNavigator` can carry out the push/pop with those children.
|
||||
* `<NavigatorIOS>` also removes children that will no longer be needed
|
||||
* (after the pop of a child has been fully completed/animated out).
|
||||
*/
|
||||
|
||||
/**
|
||||
* NavigatorIOS wraps UIKit navigation and allows you to add back-swipe
|
||||
* functionality across your app.
|
||||
*
|
||||
* #### Routes
|
||||
* A route is an object used to describe each page in the navigator. The first
|
||||
* route is provided to NavigatorIOS as `initialRoute`:
|
||||
*
|
||||
* ```
|
||||
* render: function() {
|
||||
* return (
|
||||
* <NavigatorIOS
|
||||
* initialRoute={{
|
||||
* component: MyView,
|
||||
* title: 'My View Title',
|
||||
* passProps: { myProp: 'foo' },
|
||||
* }}
|
||||
* />
|
||||
* );
|
||||
* },
|
||||
* ```
|
||||
*
|
||||
* Now MyView will be rendered by the navigator. It will recieve the route
|
||||
* object in the `route` prop, a navigator, and all of the props specified in
|
||||
* `passProps`.
|
||||
*
|
||||
* See the initialRoute propType for a complete definition of a route.
|
||||
*
|
||||
* #### Navigator
|
||||
*
|
||||
* A `navigator` is an object of navigation functions that a view can call. It
|
||||
* is passed as a prop to any component rendered by NavigatorIOS.
|
||||
*
|
||||
* ```
|
||||
* var MyView = React.createClass({
|
||||
* _handleBackButtonPress: function() {
|
||||
* this.props.navigator.pop();
|
||||
* },
|
||||
* _handleNextButtonPress: function() {
|
||||
* this.props.navigator.push(nextRoute);
|
||||
* },
|
||||
* ...
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* A navigation object contains the following functions:
|
||||
*
|
||||
* - `push(route)` - Navigate forward to a new route
|
||||
* - `pop()` - Go back one page
|
||||
* - `popN(n)` - Go back N pages at once. When N=1, behavior matches `pop()`
|
||||
* - `replace(route)` - Replace the route for the current page and immediately
|
||||
* load the view for the new route
|
||||
* - `replacePrevious(route)` - Replace the route/view for the previous page
|
||||
* - `replacePreviousAndPop(route)` - Replaces the previous route/view and
|
||||
* transitions back to it
|
||||
* - `resetTo(route)` - Replaces the top item and popToTop
|
||||
* - `popToRoute(route)` - Go back to the item for a particular route object
|
||||
* - `popToTop()` - Go back to the top item
|
||||
*
|
||||
* Navigator functions are also available on the NavigatorIOS component:
|
||||
*
|
||||
* ```
|
||||
* var MyView = React.createClass({
|
||||
* _handleNavigationRequest: function() {
|
||||
* this.refs.nav.push(otherRoute);
|
||||
* },
|
||||
* render: () => (
|
||||
* <NavigatorIOS
|
||||
* ref="nav"
|
||||
* initialRoute={...}
|
||||
* />
|
||||
* ),
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
var NavigatorIOS = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
|
||||
/**
|
||||
* NavigatorIOS uses "route" objects to identify child views, their props,
|
||||
* and navigation bar configuration. "push" and all the other navigation
|
||||
* operations expect routes to be like this:
|
||||
*/
|
||||
initialRoute: PropTypes.shape({
|
||||
/**
|
||||
* The React Class to render for this route
|
||||
*/
|
||||
component: PropTypes.func.isRequired,
|
||||
|
||||
/**
|
||||
* The title displayed in the nav bar and back button for this route
|
||||
*/
|
||||
title: PropTypes.string.isRequired,
|
||||
|
||||
/**
|
||||
* Specify additional props passed to the component. NavigatorIOS will
|
||||
* automatically provide "route" and "navigator" components
|
||||
*/
|
||||
passProps: PropTypes.object,
|
||||
|
||||
/**
|
||||
* If set, the left header button will appear with this name. Note that
|
||||
* this doesn't apply for the header of the current view, but the ones
|
||||
* of the views that are pushed afterward.
|
||||
*/
|
||||
backButtonTitle: PropTypes.string,
|
||||
|
||||
/**
|
||||
* If set, the right header button will appear with this name
|
||||
*/
|
||||
rightButtonTitle: PropTypes.string,
|
||||
|
||||
/**
|
||||
* Called when the right header button is pressed
|
||||
*/
|
||||
onRightButtonPress: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Styles for the navigation item containing the component
|
||||
*/
|
||||
wrapperStyle: View.propTypes.style,
|
||||
|
||||
}).isRequired,
|
||||
|
||||
/**
|
||||
* The default wrapper style for components in the navigator.
|
||||
* A common use case is to set the backgroundColor for every page
|
||||
*/
|
||||
itemWrapperStyle: View.propTypes.style,
|
||||
|
||||
/**
|
||||
* The color used for buttons in the navigation bar
|
||||
*/
|
||||
tintColor: PropTypes.string,
|
||||
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
// Precompute a pack of callbacks that's frequently generated and passed to
|
||||
// instances.
|
||||
this.navigator = {
|
||||
push: this.push,
|
||||
pop: this.pop,
|
||||
popN: this.popN,
|
||||
replace: this.replace,
|
||||
replacePrevious: this.replacePrevious,
|
||||
replacePreviousAndPop: this.replacePreviousAndPop,
|
||||
resetTo: this.resetTo,
|
||||
popToRoute: this.popToRoute,
|
||||
popToTop: this.popToTop,
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
idStack: [getuid()],
|
||||
routeStack: [this.props.initialRoute],
|
||||
// The navigation index that we wish to push/pop to.
|
||||
requestedTopOfStack: 0,
|
||||
// The last index that native has sent confirmation of completed push/pop
|
||||
// for. At this point, we can discard any views that are beyond the
|
||||
// `requestedTopOfStack`. A value of `null` means we have not received
|
||||
// any confirmation, ever. We may receive an `observedTopOfStack` without
|
||||
// ever requesting it - native can instigate pops of its own with the
|
||||
// backswipe gesture.
|
||||
observedTopOfStack: 0,
|
||||
progress: 1,
|
||||
fromIndex: 0,
|
||||
toIndex: 0,
|
||||
// Whether or not we are making a navigator request to push/pop. (Used
|
||||
// for performance optimization).
|
||||
makingNavigatorRequest: false,
|
||||
// Whether or not we are updating children of navigator and if so (not
|
||||
// `null`) which index marks the beginning of all updates. Used for
|
||||
// performance optimization.
|
||||
updatingAllIndicesAtOrBeyond: 0,
|
||||
};
|
||||
},
|
||||
|
||||
_handleFocusRequest: function(item) {
|
||||
if (this.state.makingNavigatorRequest) {
|
||||
this._toFocusOnNavigationComplete = item;
|
||||
} else {
|
||||
this._getFocusEmitter().emit('focus', item);
|
||||
}
|
||||
},
|
||||
|
||||
_getFocusEmitter: function() {
|
||||
if (!this._focusEmitter) {
|
||||
this._focusEmitter = new EventEmitter();
|
||||
}
|
||||
return this._focusEmitter;
|
||||
},
|
||||
|
||||
getChildContext: function() {
|
||||
return {
|
||||
onFocusRequested: this._handleFocusRequest,
|
||||
focusEmitter: this._getFocusEmitter(),
|
||||
};
|
||||
},
|
||||
|
||||
childContextTypes: {
|
||||
onFocusRequested: React.PropTypes.func,
|
||||
focusEmitter: React.PropTypes.instanceOf(EventEmitter),
|
||||
},
|
||||
|
||||
_tryLockNavigator: function(cb) {
|
||||
this.refs[TRANSITIONER_REF].requestSchedulingNavigation(
|
||||
(acquiredLock) => acquiredLock && cb()
|
||||
);
|
||||
},
|
||||
|
||||
_handleNavigatorStackChanged: function(e) {
|
||||
var newObservedTopOfStack = e.nativeEvent.stackLength - 1;
|
||||
invariant(
|
||||
newObservedTopOfStack <= this.state.requestedTopOfStack,
|
||||
'No navigator item should be pushed without JS knowing about it %s %s', newObservedTopOfStack, this.state.requestedTopOfStack
|
||||
);
|
||||
var wasWaitingForConfirmation =
|
||||
this.state.requestedTopOfStack !== this.state.observedTopOfStack;
|
||||
if (wasWaitingForConfirmation) {
|
||||
invariant(
|
||||
newObservedTopOfStack === this.state.requestedTopOfStack,
|
||||
'If waiting for observedTopOfStack to reach requestedTopOfStack, ' +
|
||||
'the only valid observedTopOfStack should be requestedTopOfStack.'
|
||||
);
|
||||
}
|
||||
// Mark the most recent observation regardless of if we can lock the
|
||||
// navigator. `observedTopOfStack` merely represents what we've observed
|
||||
// and this first `setState` is only executed to update debugging
|
||||
// overlays/navigation bar.
|
||||
// Also reset progress, toIndex, and fromIndex as they might not end
|
||||
// in the correct states for a two possible reasons:
|
||||
// Progress isn't always 0 or 1 at the end, the system rounds
|
||||
// If the Navigator is offscreen these values won't be updated
|
||||
// TOOD: Revisit this decision when no longer relying on native navigator.
|
||||
var nextState = {
|
||||
observedTopOfStack: newObservedTopOfStack,
|
||||
makingNavigatorRequest: false,
|
||||
updatingAllIndicesAtOrBeyond: null,
|
||||
progress: 1,
|
||||
toIndex: newObservedTopOfStack,
|
||||
fromIndex: newObservedTopOfStack,
|
||||
};
|
||||
this.setState(nextState, this._eliminateUnneededChildren);
|
||||
},
|
||||
|
||||
_eliminateUnneededChildren: function() {
|
||||
// Updating the indices that we're deleting and that's all. (Truth: Nothing
|
||||
// even uses the indices in this case, but let's make this describe the
|
||||
// truth anyways).
|
||||
var updatingAllIndicesAtOrBeyond =
|
||||
this.state.routeStack.length > this.state.observedTopOfStack + 1 ?
|
||||
this.state.observedTopOfStack + 1 :
|
||||
null;
|
||||
this.setState({
|
||||
idStack: this.state.idStack.slice(0, this.state.observedTopOfStack + 1),
|
||||
routeStack: this.state.routeStack.slice(0, this.state.observedTopOfStack + 1),
|
||||
// Now we rerequest the top of stack that we observed.
|
||||
requestedTopOfStack: this.state.observedTopOfStack,
|
||||
makingNavigatorRequest: true,
|
||||
updatingAllIndicesAtOrBeyond: updatingAllIndicesAtOrBeyond,
|
||||
});
|
||||
},
|
||||
|
||||
push: function(route) {
|
||||
invariant(!!route, 'Must supply route to push');
|
||||
// Make sure all previous requests are caught up first. Otherwise reject.
|
||||
if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
|
||||
this._tryLockNavigator(() => {
|
||||
var nextStack = this.state.routeStack.concat([route]);
|
||||
var nextIDStack = this.state.idStack.concat([getuid()]);
|
||||
this.setState({
|
||||
// We have to make sure that we've also supplied enough views to
|
||||
// satisfy our request to adjust the `requestedTopOfStack`.
|
||||
idStack: nextIDStack,
|
||||
routeStack: nextStack,
|
||||
requestedTopOfStack: nextStack.length - 1,
|
||||
makingNavigatorRequest: true,
|
||||
updatingAllIndicesAtOrBeyond: nextStack.length - 1,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
popN: function(n) {
|
||||
if (n === 0) {
|
||||
return;
|
||||
}
|
||||
// Make sure all previous requests are caught up first. Otherwise reject.
|
||||
if (this.state.requestedTopOfStack === this.state.observedTopOfStack) {
|
||||
if (this.state.requestedTopOfStack > 0) {
|
||||
this._tryLockNavigator(() => {
|
||||
invariant(
|
||||
this.state.requestedTopOfStack - n >= 0,
|
||||
'Cannot pop below 0'
|
||||
);
|
||||
this.setState({
|
||||
requestedTopOfStack: this.state.requestedTopOfStack - n,
|
||||
makingNavigatorRequest: true,
|
||||
// Not actually updating the indices yet until we get the native
|
||||
// `onNavigationComplete`.
|
||||
updatingAllIndicesAtOrBeyond: null,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
pop: function() {
|
||||
this.popN(1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Replace a route in the navigation stack.
|
||||
*
|
||||
* `index` specifies the route in the stack that should be replaced.
|
||||
* If it's negative, it counts from the back.
|
||||
*/
|
||||
replaceAtIndex: function(route, index) {
|
||||
invariant(!!route, 'Must supply route to replace');
|
||||
if (index < 0) {
|
||||
index += this.state.routeStack.length;
|
||||
}
|
||||
|
||||
if (this.state.routeStack.length <= index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// I don't believe we need to lock for a replace since there's no
|
||||
// navigation actually happening
|
||||
var nextIDStack = this.state.idStack.slice();
|
||||
var nextRouteStack = this.state.routeStack.slice();
|
||||
nextIDStack[index] = getuid();
|
||||
nextRouteStack[index] = route;
|
||||
|
||||
this.setState({
|
||||
idStack: nextIDStack,
|
||||
routeStack: nextRouteStack,
|
||||
makingNavigatorRequest: false,
|
||||
updatingAllIndicesAtOrBeyond: index,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces the top of the navigation stack.
|
||||
*/
|
||||
replace: function(route) {
|
||||
this.replaceAtIndex(route, -1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Replace the current route's parent.
|
||||
*/
|
||||
replacePrevious: function(route) {
|
||||
this.replaceAtIndex(route, -2);
|
||||
},
|
||||
|
||||
popToTop: function() {
|
||||
this.popToRoute(this.state.routeStack[0]);
|
||||
},
|
||||
|
||||
popToRoute: function(route) {
|
||||
var indexOfRoute = this.state.routeStack.indexOf(route);
|
||||
invariant(
|
||||
indexOfRoute !== -1,
|
||||
'Calling pop to route for a route that doesn\'t exist!'
|
||||
);
|
||||
var numToPop = this.state.routeStack.length - indexOfRoute - 1;
|
||||
this.popN(numToPop);
|
||||
},
|
||||
|
||||
replacePreviousAndPop: function(route) {
|
||||
// Make sure all previous requests are caught up first. Otherwise reject.
|
||||
if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) {
|
||||
return;
|
||||
}
|
||||
if (this.state.routeStack.length < 2) {
|
||||
return;
|
||||
}
|
||||
this._tryLockNavigator(() => {
|
||||
this.replacePrevious(route);
|
||||
this.setState({
|
||||
requestedTopOfStack: this.state.requestedTopOfStack - 1,
|
||||
makingNavigatorRequest: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
resetTo: function(route) {
|
||||
invariant(!!route, 'Must supply route to push');
|
||||
// Make sure all previous requests are caught up first. Otherwise reject.
|
||||
if (this.state.requestedTopOfStack !== this.state.observedTopOfStack) {
|
||||
return;
|
||||
}
|
||||
this.replaceAtIndex(route, 0);
|
||||
this.popToRoute(route);
|
||||
},
|
||||
|
||||
handleNavigationComplete: function(e) {
|
||||
if (this._toFocusOnNavigationComplete) {
|
||||
this._getFocusEmitter().emit('focus', this._toFocusOnNavigationComplete);
|
||||
this._toFocusOnNavigationComplete = null;
|
||||
}
|
||||
this._handleNavigatorStackChanged(e);
|
||||
},
|
||||
|
||||
_routeToStackItem: function(route, i) {
|
||||
var Component = route.component;
|
||||
var shouldUpdateChild = this.state.updatingAllIndicesAtOrBeyond !== null &&
|
||||
this.state.updatingAllIndicesAtOrBeyond >= i;
|
||||
|
||||
return (
|
||||
<StaticContainer key={'nav' + i} shouldUpdate={shouldUpdateChild}>
|
||||
<RKNavigatorItem
|
||||
title={route.title}
|
||||
style={[
|
||||
styles.stackItem,
|
||||
this.props.itemWrapperStyle,
|
||||
route.wrapperStyle
|
||||
]}
|
||||
backButtonTitle={route.backButtonTitle}
|
||||
rightButtonTitle={route.rightButtonTitle}
|
||||
onNavRightButtonTap={route.onRightButtonPress}
|
||||
tintColor={this.props.tintColor}>
|
||||
<Component
|
||||
navigator={this.navigator}
|
||||
route={route}
|
||||
{...route.passProps}
|
||||
/>
|
||||
</RKNavigatorItem>
|
||||
</StaticContainer>
|
||||
);
|
||||
},
|
||||
|
||||
renderNavigationStackItems: function() {
|
||||
var shouldRecurseToNavigator =
|
||||
this.state.makingNavigatorRequest ||
|
||||
this.state.updatingAllIndicesAtOrBeyond !== null;
|
||||
// If not recursing update to navigator at all, may as well avoid
|
||||
// computation of navigator children.
|
||||
var items = shouldRecurseToNavigator ?
|
||||
this.state.routeStack.map(this._routeToStackItem) : null;
|
||||
return (
|
||||
<StaticContainer shouldUpdate={shouldRecurseToNavigator}>
|
||||
<NavigatorTransitionerIOS
|
||||
ref={TRANSITIONER_REF}
|
||||
style={styles.transitioner}
|
||||
vertical={this.props.vertical}
|
||||
requestedTopOfStack={this.state.requestedTopOfStack}
|
||||
onNavigationComplete={this.handleNavigationComplete}>
|
||||
{items}
|
||||
</NavigatorTransitionerIOS>
|
||||
</StaticContainer>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<View style={this.props.style}>
|
||||
{this.renderNavigationStackItems()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
stackItem: {
|
||||
backgroundColor: 'white',
|
||||
overflow: 'hidden',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
transitioner: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = NavigatorIOS;
|
||||
@@ -1,458 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ScrollResponder
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeModules = require('NativeModules');
|
||||
var NativeModulesDeprecated = require('NativeModulesDeprecated');
|
||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
||||
var Subscribable = require('Subscribable');
|
||||
var TextInputState = require('TextInputState');
|
||||
|
||||
var RKUIManager = NativeModules.RKUIManager;
|
||||
var RKUIManagerDeprecated = NativeModulesDeprecated.RKUIManager;
|
||||
var RKScrollViewConsts = RKUIManager.RCTScrollView.Constants;
|
||||
|
||||
var warning = require('warning');
|
||||
|
||||
/**
|
||||
* Mixin that can be integrated in order to handle scrolling that plays well
|
||||
* with `ResponderEventPlugin`. Integrate with your platform specific scroll
|
||||
* views, or even your custom built (every-frame animating) scroll views so that
|
||||
* all of these systems play well with the `ResponderEventPlugin`.
|
||||
*
|
||||
* iOS scroll event timing nuances:
|
||||
* ===============================
|
||||
*
|
||||
*
|
||||
* Scrolling without bouncing, if you touch down:
|
||||
* -------------------------------
|
||||
*
|
||||
* 1. `onMomentumScrollBegin` (when animation begins after letting up)
|
||||
* ... physical touch starts ...
|
||||
* 2. `onTouchStartCapture` (when you press down to stop the scroll)
|
||||
* 3. `onTouchStart` (same, but bubble phase)
|
||||
* 4. `onResponderRelease` (when lifting up - you could pause forever before * lifting)
|
||||
* 5. `onMomentumScrollEnd`
|
||||
*
|
||||
*
|
||||
* Scrolling with bouncing, if you touch down:
|
||||
* -------------------------------
|
||||
*
|
||||
* 1. `onMomentumScrollBegin` (when animation begins after letting up)
|
||||
* ... bounce begins ...
|
||||
* ... some time elapses ...
|
||||
* ... physical touch during bounce ...
|
||||
* 2. `onMomentumScrollEnd` (Makes no sense why this occurs first during bounce)
|
||||
* 3. `onTouchStartCapture` (immediately after `onMomentumScrollEnd`)
|
||||
* 4. `onTouchStart` (same, but bubble phase)
|
||||
* 5. `onTouchEnd` (You could hold the touch start for a long time)
|
||||
* 6. `onMomentumScrollBegin` (When releasing the view starts bouncing back)
|
||||
*
|
||||
* So when we receive an `onTouchStart`, how can we tell if we are touching
|
||||
* *during* an animation (which then causes the animation to stop)? The only way
|
||||
* to tell is if the `touchStart` occurred immediately after the
|
||||
* `onMomentumScrollEnd`.
|
||||
*
|
||||
* This is abstracted out for you, so you can just call this.scrollResponderIsAnimating() if
|
||||
* necessary
|
||||
*
|
||||
* `ScrollResponder` also includes logic for blurring a currently focused input
|
||||
* if one is focused while scrolling. The `ScrollResponder` is a natural place
|
||||
* to put this logic since it can support not dismissing the keyboard while
|
||||
* scrolling, unless a recognized "tap"-like gesture has occurred.
|
||||
*
|
||||
* The public lifecycle API includes events for keyboard interaction, responder
|
||||
* interaction, and scrolling (among others). The keyboard callbacks
|
||||
* `onKeyboardWill/Did/*` are *global* events, but are invoked on scroll
|
||||
* responder's props so that you can guarantee that the scroll responder's
|
||||
* internal state has been updated accordingly (and deterministically) by
|
||||
* the time the props callbacks are invoke. Otherwise, you would always wonder
|
||||
* if the scroll responder is currently in a state where it recognizes new
|
||||
* keyboard positions etc. If coordinating scrolling with keyboard movement,
|
||||
* *always* use these hooks instead of listening to your own global keyboard
|
||||
* events.
|
||||
*
|
||||
* Public keyboard lifecycle API: (props callbacks)
|
||||
*
|
||||
* Standard Keyboard Appearance Sequence:
|
||||
*
|
||||
* this.props.onKeyboardWillShow
|
||||
* this.props.onKeyboardDidShow
|
||||
*
|
||||
* `onScrollResponderKeyboardDismissed` will be invoked if an appropriate
|
||||
* tap inside the scroll responder's scrollable region was responsible
|
||||
* for the dismissal of the keyboard. There are other reasons why the
|
||||
* keyboard could be dismissed.
|
||||
*
|
||||
* this.props.onScrollResponderKeyboardDismissed
|
||||
*
|
||||
* Standard Keyboard Hide Sequence:
|
||||
*
|
||||
* this.props.onKeyboardWillHide
|
||||
* this.props.onKeyboardDidHide
|
||||
*/
|
||||
|
||||
var IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16;
|
||||
|
||||
var ScrollResponderMixin = {
|
||||
mixins: [Subscribable.Mixin],
|
||||
statics: RKScrollViewConsts,
|
||||
scrollResponderMixinGetInitialState: function() {
|
||||
return {
|
||||
isTouching: false,
|
||||
lastMomentumScrollBeginTime: 0,
|
||||
lastMomentumScrollEndTime: 0,
|
||||
|
||||
// Reset to false every time becomes responder. This is used to:
|
||||
// - Determine if the scroll view has been scrolled and therefore should
|
||||
// refuse to give up its responder lock.
|
||||
// - Determine if releasing should dismiss the keyboard when we are in
|
||||
// tap-to-dismiss mode (!this.props.keyboardShouldPersistTaps).
|
||||
observedScrollSinceBecomingResponder: false,
|
||||
becameResponderWhileAnimating: false,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onScroll` event.
|
||||
*/
|
||||
scrollResponderHandleScrollShouldSetResponder: function() {
|
||||
return this.state.isTouching;
|
||||
},
|
||||
|
||||
/**
|
||||
* Merely touch starting is not sufficient for a scroll view to become the
|
||||
* responder. Being the "responder" means that the very next touch move/end
|
||||
* event will result in an action/movement.
|
||||
*
|
||||
* Invoke this from an `onStartShouldSetResponder` event.
|
||||
*
|
||||
* `onStartShouldSetResponder` is used when the next move/end will trigger
|
||||
* some UI movement/action, but when you want to yield priority to views
|
||||
* nested inside of the view.
|
||||
*
|
||||
* There may be some cases where scroll views actually should return `true`
|
||||
* from `onStartShouldSetResponder`: Any time we are detecting a standard tap
|
||||
* that gives priority to nested views.
|
||||
*
|
||||
* - If a single tap on the scroll view triggers an action such as
|
||||
* recentering a map style view yet wants to give priority to interaction
|
||||
* views inside (such as dropped pins or labels), then we would return true
|
||||
* from this method when there is a single touch.
|
||||
*
|
||||
* - Similar to the previous case, if a two finger "tap" should trigger a
|
||||
* zoom, we would check the `touches` count, and if `>= 2`, we would return
|
||||
* true.
|
||||
*
|
||||
*/
|
||||
scrollResponderHandleStartShouldSetResponder: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* There are times when the scroll view wants to become the responder
|
||||
* (meaning respond to the next immediate `touchStart/touchEnd`), in a way
|
||||
* that *doesn't* give priority to nested views (hence the capture phase):
|
||||
*
|
||||
* - Currently animating.
|
||||
* - Tapping anywhere that is not the focused input, while the keyboard is
|
||||
* up (which should dismiss the keyboard).
|
||||
*
|
||||
* Invoke this from an `onStartShouldSetResponderCapture` event.
|
||||
*/
|
||||
scrollResponderHandleStartShouldSetResponderCapture: function(e) {
|
||||
// First see if we want to eat taps while the keyboard is up
|
||||
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
if (!this.props.keyboardShouldPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target != currentlyFocusedTextInput) {
|
||||
return true;
|
||||
}
|
||||
return this.scrollResponderIsAnimating();
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onResponderReject` event.
|
||||
*
|
||||
* Some other element is not yielding its role as responder. Normally, we'd
|
||||
* just disable the `UIScrollView`, but a touch has already began on it, the
|
||||
* `UIScrollView` will not accept being disabled after that. The easiest
|
||||
* solution for now is to accept the limitation of disallowing this
|
||||
* altogether. To improve this, find a way to disable the `UIScrollView` after
|
||||
* a touch has already started.
|
||||
*/
|
||||
scrollResponderHandleResponderReject: function() {
|
||||
warning(false, "ScrollView doesn't take rejection well - scrolls anyway");
|
||||
},
|
||||
|
||||
/**
|
||||
* We will allow the scroll view to give up its lock iff it acquired the lock
|
||||
* during an animation. This is a very useful default that happens to satisfy
|
||||
* many common user experiences.
|
||||
*
|
||||
* - Stop a scroll on the left edge, then turn that into an outer view's
|
||||
* backswipe.
|
||||
* - Stop a scroll mid-bounce at the top, continue pulling to have the outer
|
||||
* view dismiss.
|
||||
* - However, without catching the scroll view mid-bounce (while it is
|
||||
* motionless), if you drag far enough for the scroll view to become
|
||||
* responder (and therefore drag the scroll view a bit), any backswipe
|
||||
* navigation of a swipe gesture higher in the view hierarchy, should be
|
||||
* rejected.
|
||||
*/
|
||||
scrollResponderHandleTerminationRequest: function() {
|
||||
return !this.state.observedScrollSinceBecomingResponder;
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onTouchEnd` event.
|
||||
*
|
||||
* @param {SyntheticEvent} e Event.
|
||||
*/
|
||||
scrollResponderHandleTouchEnd: function(e) {
|
||||
var nativeEvent = e.nativeEvent;
|
||||
this.state.isTouching = nativeEvent.touches.length !== 0;
|
||||
this.props.onTouchEnd && this.props.onTouchEnd(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onResponderRelease` event.
|
||||
*/
|
||||
scrollResponderHandleResponderRelease: function(e) {
|
||||
this.props.onResponderRelease && this.props.onResponderRelease(e);
|
||||
|
||||
// By default scroll views will unfocus a textField
|
||||
// if another touch occurs outside of it
|
||||
var currentlyFocusedTextInput = TextInputState.currentlyFocusedField();
|
||||
if (!this.props.keyboardShouldPersistTaps &&
|
||||
currentlyFocusedTextInput != null &&
|
||||
e.target != currentlyFocusedTextInput &&
|
||||
!this.state.observedScrollSinceBecomingResponder &&
|
||||
!this.state.becameResponderWhileAnimating) {
|
||||
this.props.onScrollResponderKeyboardDismissed &&
|
||||
this.props.onScrollResponderKeyboardDismissed(e);
|
||||
TextInputState.blurTextInput(currentlyFocusedTextInput);
|
||||
}
|
||||
},
|
||||
|
||||
scrollResponderHandleScroll: function(e) {
|
||||
this.state.observedScrollSinceBecomingResponder = true;
|
||||
this.props.onScroll && this.props.onScroll(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onResponderGrant` event.
|
||||
*/
|
||||
scrollResponderHandleResponderGrant: function(e) {
|
||||
this.state.observedScrollSinceBecomingResponder = false;
|
||||
this.props.onResponderGrant && this.props.onResponderGrant(e);
|
||||
this.state.becameResponderWhileAnimating = this.scrollResponderIsAnimating();
|
||||
},
|
||||
|
||||
/**
|
||||
* Unfortunately, `onScrollBeginDrag` also fires when *stopping* the scroll
|
||||
* animation, and there's not an easy way to distinguish a drag vs. stopping
|
||||
* momentum.
|
||||
*
|
||||
* Invoke this from an `onScrollBeginDrag` event.
|
||||
*/
|
||||
scrollResponderHandleScrollBeginDrag: function(e) {
|
||||
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onScrollEndDrag` event.
|
||||
*/
|
||||
scrollResponderHandleScrollEndDrag: function(e) {
|
||||
this.props.onScrollEndDrag && this.props.onScrollEndDrag(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onMomentumScrollBegin` event.
|
||||
*/
|
||||
scrollResponderHandleMomentumScrollBegin: function(e) {
|
||||
this.state.lastMomentumScrollBeginTime = Date.now();
|
||||
this.props.onMomentumScrollBegin && this.props.onMomentumScrollBegin(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onMomentumScrollEnd` event.
|
||||
*/
|
||||
scrollResponderHandleMomentumScrollEnd: function(e) {
|
||||
this.state.lastMomentumScrollEndTime = Date.now();
|
||||
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onTouchStart` event.
|
||||
*
|
||||
* Since we know that the `SimpleEventPlugin` occurs later in the plugin
|
||||
* order, after `ResponderEventPlugin`, we can detect that we were *not*
|
||||
* permitted to be the responder (presumably because a contained view became
|
||||
* responder). The `onResponderReject` won't fire in that case - it only
|
||||
* fires when a *current* responder rejects our request.
|
||||
*
|
||||
* @param {SyntheticEvent} e Touch Start event.
|
||||
*/
|
||||
scrollResponderHandleTouchStart: function(e) {
|
||||
this.state.isTouching = true;
|
||||
this.props.onTouchStart && this.props.onTouchStart(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoke this from an `onTouchMove` event.
|
||||
*
|
||||
* Since we know that the `SimpleEventPlugin` occurs later in the plugin
|
||||
* order, after `ResponderEventPlugin`, we can detect that we were *not*
|
||||
* permitted to be the responder (presumably because a contained view became
|
||||
* responder). The `onResponderReject` won't fire in that case - it only
|
||||
* fires when a *current* responder rejects our request.
|
||||
*
|
||||
* @param {SyntheticEvent} e Touch Start event.
|
||||
*/
|
||||
scrollResponderHandleTouchMove: function(e) {
|
||||
this.props.onTouchMove && this.props.onTouchMove(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function for this class that lets us quickly determine if the
|
||||
* view is currently animating. This is particularly useful to know when
|
||||
* a touch has just started or ended.
|
||||
*/
|
||||
scrollResponderIsAnimating: function() {
|
||||
var now = Date.now();
|
||||
var timeSinceLastMomentumScrollEnd = now - this.state.lastMomentumScrollEndTime;
|
||||
var isAnimating = timeSinceLastMomentumScrollEnd < IS_ANIMATING_TOUCH_START_THRESHOLD_MS ||
|
||||
this.state.lastMomentumScrollEndTime < this.state.lastMomentumScrollBeginTime;
|
||||
return isAnimating;
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function to scroll to a specific point in the scrollview.
|
||||
* This is currently used to help focus on child textview's, but this
|
||||
* can also be used to quickly scroll to any element we want to focus
|
||||
*/
|
||||
scrollResponderScrollTo: function(offsetX, offsetY) {
|
||||
RKUIManagerDeprecated.scrollTo(this.getNodeHandle(), offsetX, offsetY);
|
||||
},
|
||||
|
||||
/**
|
||||
* A helper function to zoom to a specific rect in the scrollview.
|
||||
* @param {object} rect Should have shape {x, y, w, h}
|
||||
*/
|
||||
scrollResponderZoomTo: function(rect) {
|
||||
RKUIManagerDeprecated.zoomToRect(this.getNodeHandle(), rect);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method should be used as the callback to onFocus in a TextInputs'
|
||||
* parent view. Note that any module using this mixin needs to return
|
||||
* the parent view's ref in getScrollViewRef() in order to use this method
|
||||
*/
|
||||
scrollResponderScrollNativeHandleToKeyboard: function(nodeHandle, additionalOffset) {
|
||||
this.additionalScrollOffset = additionalOffset || 0;
|
||||
RKUIManager.measureLayout(
|
||||
nodeHandle,
|
||||
this.getNodeHandle(),
|
||||
this.scrollResponderTextInputFocusError,
|
||||
this.scrollResponderInputMeasureAndScrollToKeyboard
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* The calculations performed here assume the scroll view takes up the entire
|
||||
* screen - even if has some content inset. We then measure the offsets of the
|
||||
* keyboard, and compensate both for the scroll view's "contentInset".
|
||||
*
|
||||
* @param {number} left Position of input w.r.t. table view.
|
||||
* @param {number} top Position of input w.r.t. table view.
|
||||
* @param {number} width Width of the text input.
|
||||
* @param {number} height Height of the text input.
|
||||
*/
|
||||
scrollResponderInputMeasureAndScrollToKeyboard: function(left, top, width, height) {
|
||||
if (this.keyboardWillOpenTo) {
|
||||
var scrollOffsetY =
|
||||
top - this.keyboardWillOpenTo.endCoordinates.screenY + height +
|
||||
this.additionalScrollOffset;
|
||||
this.scrollResponderScrollTo(0, scrollOffsetY);
|
||||
}
|
||||
this.additionalOffset = 0;
|
||||
},
|
||||
|
||||
scrollResponderTextInputFocusError: function(e) {
|
||||
console.error('Error measuring text field: ', e);
|
||||
},
|
||||
|
||||
/**
|
||||
* `componentWillMount` is the closest thing to a standard "constructor" for
|
||||
* React components.
|
||||
*
|
||||
* The `keyboardWillShow` is called before input focus.
|
||||
*/
|
||||
componentWillMount: function() {
|
||||
this.keyboardWillOpenTo = null;
|
||||
this.additionalScrollOffset = 0;
|
||||
this.addListenerOn(RCTDeviceEventEmitter, 'keyboardWillShow', this.scrollResponderKeyboardWillShow);
|
||||
this.addListenerOn(RCTDeviceEventEmitter, 'keyboardWillHide', this.scrollResponderKeyboardWillHide);
|
||||
this.addListenerOn(RCTDeviceEventEmitter, 'keyboardDidShow', this.scrollResponderKeyboardDidShow);
|
||||
this.addListenerOn(RCTDeviceEventEmitter, 'keyboardDidHide', this.scrollResponderKeyboardDidHide);
|
||||
},
|
||||
|
||||
/**
|
||||
* Warning, this may be called several times for a single keyboard opening.
|
||||
* It's best to store the information in this method and then take any action
|
||||
* at a later point (either in `keyboardDidShow` or other).
|
||||
*
|
||||
* Here's the order that events occur in:
|
||||
* - focus
|
||||
* - willShow {startCoordinates, endCoordinates} several times
|
||||
* - didShow several times
|
||||
* - blur
|
||||
* - willHide {startCoordinates, endCoordinates} several times
|
||||
* - didHide several times
|
||||
*
|
||||
* The `ScrollResponder` providesModule callbacks for each of these events.
|
||||
* Even though any user could have easily listened to keyboard events
|
||||
* themselves, using these `props` callbacks ensures that ordering of events
|
||||
* is consistent - and not dependent on the order that the keyboard events are
|
||||
* subscribed to. This matters when telling the scroll view to scroll to where
|
||||
* the keyboard is headed - the scroll responder better have been notified of
|
||||
* the keyboard destination before being instructed to scroll to where the
|
||||
* keyboard will be. Stick to the `ScrollResponder` callbacks, and everything
|
||||
* will work.
|
||||
*
|
||||
* WARNING: These callbacks will fire even if a keyboard is displayed in a
|
||||
* different navigation pane. Filter out the events to determine if they are
|
||||
* relevant to you. (For example, only if you receive these callbacks after
|
||||
* you had explicitly focused a node etc).
|
||||
*/
|
||||
scrollResponderKeyboardWillShow: function(e) {
|
||||
this.keyboardWillOpenTo = e;
|
||||
this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e);
|
||||
},
|
||||
|
||||
scrollResponderKeyboardWillHide: function(e) {
|
||||
this.keyboardWillOpenTo = null;
|
||||
this.props.onKeyboardWillHide && this.props.onKeyboardWillHide(e);
|
||||
},
|
||||
|
||||
scrollResponderKeyboardDidShow: function() {
|
||||
this.keyboardWillOpenTo = null;
|
||||
this.props.onKeyboardDidShow && this.props.onKeyboardDidShow();
|
||||
},
|
||||
|
||||
scrollResponderKeyboardDidHide: function() {
|
||||
this.keyboardWillOpenTo = null;
|
||||
this.props.onKeyboardDidHide && this.props.onKeyboardDidHide();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var ScrollResponder = {
|
||||
Mixin: ScrollResponderMixin,
|
||||
};
|
||||
|
||||
module.exports = ScrollResponder;
|
||||
@@ -1,349 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule ScrollView
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var EdgeInsetsPropType = require('EdgeInsetsPropType');
|
||||
var Platform = require('Platform');
|
||||
var PointPropType = require('PointPropType');
|
||||
var RCTScrollView = require('NativeModules').RKUIManager.RCTScrollView;
|
||||
var RCTScrollViewConsts = RCTScrollView.Constants;
|
||||
var React = require('React');
|
||||
var ReactIOSTagHandles = require('ReactIOSTagHandles');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var RKUIManager = require('NativeModulesDeprecated').RKUIManager;
|
||||
var ScrollResponder = require('ScrollResponder');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
var View = require('View');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
var deepDiffer = require('deepDiffer');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
var invariant = require('invariant');
|
||||
var pointsDiffer = require('pointsDiffer');
|
||||
|
||||
var PropTypes = React.PropTypes;
|
||||
|
||||
var SCROLLVIEW = 'ScrollView';
|
||||
var INNERVIEW = 'InnerScrollView';
|
||||
|
||||
var keyboardDismissModeConstants = {
|
||||
'none': RCTScrollViewConsts.KeyboardDismissMode.None, // default
|
||||
'interactive': RCTScrollViewConsts.KeyboardDismissMode.Interactive,
|
||||
'onDrag': RCTScrollViewConsts.KeyboardDismissMode.OnDrag,
|
||||
};
|
||||
|
||||
/**
|
||||
* Component that wraps platform ScrollView while providing
|
||||
* integration with touch locking "responder" system.
|
||||
*
|
||||
* Doesn't yet support other contained responders from blocking this scroll
|
||||
* view from becoming the responder.
|
||||
*/
|
||||
|
||||
var ScrollView = React.createClass({
|
||||
|
||||
// Only for compatibility with Android which is not yet up to date,
|
||||
// DO NOT ADD NEW CALL SITES!
|
||||
statics: {
|
||||
keyboardDismissMode: {
|
||||
None: 'none',
|
||||
Interactive: 'interactive',
|
||||
OnDrag: 'onDrag',
|
||||
},
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
automaticallyAdjustContentInsets: PropTypes.bool, // true
|
||||
contentInset: EdgeInsetsPropType, // zeros
|
||||
contentOffset: PointPropType, // zeros
|
||||
onScroll: PropTypes.func,
|
||||
onScrollAnimationEnd: PropTypes.func,
|
||||
scrollEnabled: PropTypes.bool, // tre
|
||||
scrollIndicatorInsets: EdgeInsetsPropType, // zeros
|
||||
showsHorizontalScrollIndicator: PropTypes.bool,
|
||||
showsVerticalScrollIndicator: PropTypes.bool,
|
||||
style: StyleSheetPropType(ViewStylePropTypes),
|
||||
throttleScrollCallbackMS: PropTypes.number, // null
|
||||
|
||||
/**
|
||||
* When true, the scroll view bounces horizontally when it reaches the end
|
||||
* even if the content is smaller than the scroll view itself. The default
|
||||
* value is true when `horizontal={true}` and false otherwise.
|
||||
*/
|
||||
alwaysBounceHorizontal: PropTypes.bool,
|
||||
/**
|
||||
* When true, the scroll view bounces vertically when it reaches the end
|
||||
* even if the content is smaller than the scroll view itself. The default
|
||||
* value is false when `horizontal={true}` and true otherwise.
|
||||
*/
|
||||
alwaysBounceVertical: PropTypes.bool,
|
||||
/**
|
||||
* When true, the scroll view automatically centers the content when the
|
||||
* content is smaller than the scroll view bounds; when the content is
|
||||
* larger than the scroll view, this property has no effect. The default
|
||||
* value is false.
|
||||
*/
|
||||
centerContent: PropTypes.bool,
|
||||
/**
|
||||
* These styles will be applied to the scroll view content container which
|
||||
* wraps all of the child views. Example:
|
||||
*
|
||||
* return (
|
||||
* <ScrollView contentContainerStyle={styles.contentContainer}>
|
||||
* </ScrollView>
|
||||
* );
|
||||
* ...
|
||||
* var styles = StyleSheet.create({
|
||||
* contentContainer: {
|
||||
* paddingVertical: 20
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
contentContainerStyle: StyleSheetPropType(ViewStylePropTypes),
|
||||
/**
|
||||
* A floating-point number that determines how quickly the scroll view
|
||||
* decelerates after the user lifts their finger. Reasonable choices include
|
||||
* - Normal: 0.998 (the default)
|
||||
* - Fast: 0.9
|
||||
*/
|
||||
decelerationRate: PropTypes.number,
|
||||
/**
|
||||
* When true, the scroll view's children are arranged horizontally in a row
|
||||
* instead of vertically in a column. The default value is false.
|
||||
*/
|
||||
horizontal: PropTypes.bool,
|
||||
/**
|
||||
* Determines whether the keyboard gets dismissed in response to a drag.
|
||||
* - 'none' (the default), drags do not dismiss the keyboard.
|
||||
* - 'onDrag', the keyboard is dismissed when a drag begins.
|
||||
* - 'interactive', the keyboard is dismissed interactively with the drag
|
||||
* and moves in synchrony with the touch; dragging upwards cancels the
|
||||
* dismissal.
|
||||
*/
|
||||
keyboardDismissMode: PropTypes.oneOf([
|
||||
'none', // default
|
||||
'interactive',
|
||||
'onDrag',
|
||||
]),
|
||||
/**
|
||||
* When false, tapping outside of the focused text input when the keyboard
|
||||
* is up dismisses the keyboard. When true, the scroll view will not catch
|
||||
* taps, and the keyboard will not dismiss automatically. The default value
|
||||
* is false.
|
||||
*/
|
||||
keyboardShouldPersistTaps: PropTypes.bool,
|
||||
/**
|
||||
* The maximum allowed zoom scale. The default value is 1.0.
|
||||
*/
|
||||
maximumZoomScale: PropTypes.number,
|
||||
/**
|
||||
* The minimum allowed zoom scale. The default value is 1.0.
|
||||
*/
|
||||
minimumZoomScale: PropTypes.number,
|
||||
/**
|
||||
* When true, the scroll view stops on multiples of the scroll view's size
|
||||
* when scrolling. This can be used for horizontal pagination. The default
|
||||
* value is false.
|
||||
*/
|
||||
pagingEnabled: PropTypes.bool,
|
||||
/**
|
||||
* When true, the scroll view scrolls to top when the status bar is tapped.
|
||||
* The default value is true.
|
||||
*/
|
||||
scrollsToTop: PropTypes.bool,
|
||||
/**
|
||||
* An array of child indices determining which children get docked to the
|
||||
* top of the screen when scrolling. For example, passing
|
||||
* `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the
|
||||
* top of the scroll view. This property is not supported in conjunction
|
||||
* with `horizontal={true}`.
|
||||
*/
|
||||
stickyHeaderIndices: PropTypes.arrayOf(PropTypes.number),
|
||||
/**
|
||||
* Experimental: When true, offscreen child views (whose `overflow` value is
|
||||
* `hidden`) are removed from their native backing superview when offscreen.
|
||||
* This canimprove scrolling performance on long lists. The default value is
|
||||
* false.
|
||||
*/
|
||||
removeClippedSubviews: PropTypes.bool,
|
||||
/**
|
||||
* The current scale of the scroll view content. The default value is 1.0.
|
||||
*/
|
||||
zoomScale: PropTypes.number,
|
||||
},
|
||||
|
||||
mixins: [ScrollResponder.Mixin],
|
||||
|
||||
getInitialState: function() {
|
||||
return this.scrollResponderMixinGetInitialState();
|
||||
},
|
||||
|
||||
setNativeProps: function(props) {
|
||||
this.refs[SCROLLVIEW].setNativeProps(props);
|
||||
},
|
||||
|
||||
getInnerViewNode: function() {
|
||||
return this.refs[INNERVIEW].getNodeHandle();
|
||||
},
|
||||
|
||||
scrollTo: function(destY, destX) {
|
||||
RKUIManager.scrollTo(
|
||||
ReactIOSTagHandles.rootNodeIDToTag[this._rootNodeID],
|
||||
destX || 0,
|
||||
destY || 0
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var contentContainerStyle = [
|
||||
this.props.horizontal && styles.contentContainerHorizontal,
|
||||
this.props.contentContainerStyle,
|
||||
];
|
||||
if (__DEV__ && this.props.style) {
|
||||
var style = flattenStyle(this.props.style);
|
||||
var childLayoutProps = ['alignItems', 'justifyContent']
|
||||
.filter((prop) => style[prop] !== undefined);
|
||||
invariant(
|
||||
childLayoutProps.length === 0,
|
||||
'ScrollView child layout (' + JSON.stringify(childLayoutProps) +
|
||||
') must by applied through the contentContainerStyle prop.'
|
||||
);
|
||||
}
|
||||
if (__DEV__) {
|
||||
if (this.props.onScroll && !this.props.throttleScrollCallbackMS) {
|
||||
var onScroll = this.props.onScroll;
|
||||
this.props.onScroll = function() {
|
||||
console.log(
|
||||
'You specified `onScroll` on a <ScrollView> but not ' +
|
||||
'`throttleScrollCallbackMS`. You will only receive one event. ' +
|
||||
'Using `16` you get all the events but be aware that it may ' +
|
||||
'cause frame drops, use a bigger number if you don\'t need as ' +
|
||||
'much precision.'
|
||||
);
|
||||
onScroll.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var contentContainer =
|
||||
<View
|
||||
ref={INNERVIEW}
|
||||
style={contentContainerStyle}
|
||||
removeClippedSubviews={this.props.removeClippedSubviews}>
|
||||
{this.props.children}
|
||||
</View>;
|
||||
|
||||
var alwaysBounceHorizontal =
|
||||
this.props.alwaysBounceHorizontal !== undefined ?
|
||||
this.props.alwaysBounceHorizontal :
|
||||
this.props.horizontal;
|
||||
|
||||
var alwaysBounceVertical =
|
||||
this.props.alwaysBounceVertical !== undefined ?
|
||||
this.props.alwaysBounceVertical :
|
||||
!this.props.horizontal;
|
||||
|
||||
var props = {
|
||||
...this.props,
|
||||
alwaysBounceHorizontal,
|
||||
alwaysBounceVertical,
|
||||
keyboardDismissMode: this.props.keyboardDismissMode ?
|
||||
keyboardDismissModeConstants[this.props.keyboardDismissMode] :
|
||||
undefined,
|
||||
style: [styles.base, this.props.style],
|
||||
onTouchStart: this.scrollResponderHandleTouchStart,
|
||||
onTouchMove: this.scrollResponderHandleTouchMove,
|
||||
onTouchEnd: this.scrollResponderHandleTouchEnd,
|
||||
onScrollBeginDrag: this.scrollResponderHandleScrollBeginDrag,
|
||||
onScrollEndDrag: this.scrollResponderHandleScrollEndDrag,
|
||||
onMomentumScrollBegin: this.scrollResponderHandleMomentumScrollBegin,
|
||||
onMomentumScrollEnd: this.scrollResponderHandleMomentumScrollEnd,
|
||||
onStartShouldSetResponder: this.scrollResponderHandleStartShouldSetResponder,
|
||||
onStartShouldSetResponderCapture: this.scrollResponderHandleStartShouldSetResponderCapture,
|
||||
onScrollShouldSetResponder: this.scrollResponderHandleScrollShouldSetResponder,
|
||||
onScroll: this.scrollResponderHandleScroll,
|
||||
onResponderGrant: this.scrollResponderHandleResponderGrant,
|
||||
onResponderTerminationRequest: this.scrollResponderHandleTerminationRequest,
|
||||
onResponderTerminate: this.scrollResponderHandleTerminate,
|
||||
onResponderRelease: this.scrollResponderHandleResponderRelease,
|
||||
onResponderReject: this.scrollResponderHandleResponderReject,
|
||||
};
|
||||
|
||||
var ScrollViewClass;
|
||||
if (Platform.OS === 'ios') {
|
||||
ScrollViewClass = RCTScrollView;
|
||||
} else if (Platform.OS === 'android') {
|
||||
if (this.props.horizontal) {
|
||||
ScrollViewClass = AndroidHorizontalScrollView;
|
||||
} else {
|
||||
ScrollViewClass = AndroidScrollView;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollViewClass {...props} ref={SCROLLVIEW}>
|
||||
{contentContainer}
|
||||
</ScrollViewClass>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
base: {
|
||||
flex: 1,
|
||||
},
|
||||
contentContainerHorizontal: {
|
||||
alignSelf: 'flex-start',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
});
|
||||
|
||||
var validAttributes = {
|
||||
...ReactIOSViewAttributes.UIView,
|
||||
alwaysBounceHorizontal: true,
|
||||
alwaysBounceVertical: true,
|
||||
automaticallyAdjustContentInsets: true,
|
||||
centerContent: true,
|
||||
contentInset: insetsDiffer,
|
||||
contentOffset: pointsDiffer,
|
||||
decelerationRate: true,
|
||||
horizontal: true,
|
||||
keyboardDismissMode: true,
|
||||
keyboardShouldPersistTaps: true,
|
||||
maximumZoomScale: true,
|
||||
minimumZoomScale: true,
|
||||
pagingEnabled: true,
|
||||
removeClippedSubviews: true,
|
||||
scrollEnabled: true,
|
||||
scrollIndicatorInsets: insetsDiffer,
|
||||
scrollsToTop: true,
|
||||
showsHorizontalScrollIndicator: true,
|
||||
showsVerticalScrollIndicator: true,
|
||||
stickyHeaderIndices: deepDiffer,
|
||||
throttleScrollCallbackMS: true,
|
||||
zoomScale: true,
|
||||
};
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
var AndroidScrollView = createReactIOSNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'AndroidScrollView',
|
||||
});
|
||||
var AndroidHorizontalScrollView = createReactIOSNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'AndroidHorizontalScrollView',
|
||||
});
|
||||
} else if (Platform.OS === 'ios') {
|
||||
var RCTScrollView = createReactIOSNativeComponentClass({
|
||||
validAttributes: validAttributes,
|
||||
uiViewClassName: 'RCTScrollView',
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = ScrollView;
|
||||
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule Slider
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
var PropTypes = require('ReactPropTypes');
|
||||
var React = require('React');
|
||||
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var View = require('View');
|
||||
|
||||
var createReactIOSNativeComponentClass =
|
||||
require('createReactIOSNativeComponentClass');
|
||||
var merge = require('merge');
|
||||
|
||||
var Slider = React.createClass({
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Used to style and layout the `Slider`. See `StyleSheet.js` and
|
||||
* `ViewStylePropTypes.js` for more info.
|
||||
*/
|
||||
style: View.propTypes.style,
|
||||
|
||||
/**
|
||||
* Initial value of the slider. The value should be between 0 and 1.
|
||||
* Default value is 0.
|
||||
*
|
||||
* *This is not a controlled component*, e.g. if you don't update
|
||||
* the value, the component won't be reseted to it's inital value.
|
||||
*/
|
||||
value: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Callback continuously called while the user is dragging the slider.
|
||||
*/
|
||||
onValueChange: PropTypes.func,
|
||||
|
||||
/**
|
||||
* Callback called when the user finishes changing the value (e.g. when
|
||||
* the slider is released).
|
||||
*/
|
||||
onSlidingComplete: PropTypes.func,
|
||||
},
|
||||
|
||||
_onValueChange: function(event) {
|
||||
this.props.onChange && this.props.onChange(event);
|
||||
if (event.nativeEvent.continuous) {
|
||||
this.props.onValueChange &&
|
||||
this.props.onValueChange(event.nativeEvent.value);
|
||||
} else {
|
||||
this.props.onSlidingComplete && event.nativeEvent.value !== undefined &&
|
||||
this.props.onSlidingComplete(event.nativeEvent.value);
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<RKSlider
|
||||
style={[styles.slider, this.props.style]}
|
||||
value={this.props.value}
|
||||
onChange={this._onValueChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
slider: {
|
||||
height: 40,
|
||||
},
|
||||
});
|
||||
|
||||
var RKSlider = createReactIOSNativeComponentClass({
|
||||
validAttributes: merge(ReactIOSViewAttributes.UIView, {value: true}),
|
||||
uiViewClassName: 'RCTSlider',
|
||||
});
|
||||
|
||||
module.exports = Slider;
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @provides StaticRenderer
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('React');
|
||||
|
||||
var StaticRenderer = React.createClass({
|
||||
propTypes: {
|
||||
shouldUpdate: React.PropTypes.bool.isRequired,
|
||||
render: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
shouldComponentUpdate: function(nextProps) {
|
||||
return nextProps.shouldUpdate;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return this.props.render();
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = StaticRenderer;
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule StatusBarIOS
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var { RKStatusBarManager } = require('NativeModules');
|
||||
|
||||
var StatusBarIOS = {
|
||||
|
||||
Style: {
|
||||
default: RKStatusBarManager.Style.default,
|
||||
lightContent: RKStatusBarManager.Style.lightContent
|
||||
},
|
||||
|
||||
Animation: {
|
||||
none: RKStatusBarManager.Animation.none,
|
||||
fade: RKStatusBarManager.Animation.fade,
|
||||
slide: RKStatusBarManager.Animation.slide,
|
||||
},
|
||||
|
||||
setStyle(style: number, animated: boolean) {
|
||||
animated = animated || false;
|
||||
RKStatusBarManager.setStyle(style, animated);
|
||||
},
|
||||
|
||||
setHidden(hidden: boolean, animation: number) {
|
||||
animation = animation || StatusBarIOS.Animation.none;
|
||||
RKStatusBarManager.setHidden(hidden, animation);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = StatusBarIOS;
|
||||
@@ -1,333 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule Subscribable
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Subscribable wraps EventEmitter in a clean interface, and provides a mixin
|
||||
* so components can easily subscribe to events and not worry about cleanup on
|
||||
* unmount.
|
||||
*
|
||||
* Also acts as a basic store because it records the last data that it emitted,
|
||||
* and provides a way to populate the initial data. The most recent data can be
|
||||
* fetched from the Subscribable by calling `get()`
|
||||
*
|
||||
* Advantages over EventEmitter + Subscibable.Mixin.addListenerOn:
|
||||
* - Cleaner usage: no strings to identify the event
|
||||
* - Lifespan pattern enforces cleanup
|
||||
* - More logical: Subscribable.Mixin now uses a Subscribable class
|
||||
* - Subscribable saves the last data and makes it available with `.get()`
|
||||
*
|
||||
* Legacy Subscribable.Mixin.addListenerOn allowed automatic subscription to
|
||||
* EventEmitters. Now we should avoid EventEmitters and wrap with Subscribable
|
||||
* instead:
|
||||
*
|
||||
* ```
|
||||
* AppState.networkReachability = new Subscribable(
|
||||
* RCTDeviceEventEmitter,
|
||||
* 'reachabilityDidChange',
|
||||
* (resp) => resp.network_reachability,
|
||||
* RKReachability.getCurrentReachability
|
||||
* );
|
||||
*
|
||||
* var myComponent = React.createClass({
|
||||
* mixins: [Subscribable.Mixin],
|
||||
* getInitialState: function() {
|
||||
* return {
|
||||
* isConnected: AppState.networkReachability.get() !== 'none'
|
||||
* };
|
||||
* },
|
||||
* componentDidMount: function() {
|
||||
* this._reachSubscription = this.subscribeTo(
|
||||
* AppState.networkReachability,
|
||||
* (reachability) => {
|
||||
* this.setState({ isConnected: reachability !== 'none' })
|
||||
* }
|
||||
* );
|
||||
* },
|
||||
* render: function() {
|
||||
* return (
|
||||
* <Text>
|
||||
* {this.state.isConnected ? 'Network Connected' : 'No network'}
|
||||
* </Text>
|
||||
* <Text onPress={() => this._reachSubscription.remove()}>
|
||||
* End reachability subscription
|
||||
* </Text>
|
||||
* );
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
var EventEmitter = require('EventEmitter');
|
||||
|
||||
var invariant = require('invariant');
|
||||
var logError = require('logError');
|
||||
|
||||
var SUBSCRIBABLE_INTERNAL_EVENT = 'subscriptionEvent';
|
||||
|
||||
|
||||
class Subscribable {
|
||||
/**
|
||||
* Creates a new Subscribable object
|
||||
*
|
||||
* @param {EventEmitter} eventEmitter Emitter to trigger subscription events.
|
||||
* @param {string} eventName Name of emitted event that triggers subscription
|
||||
* events.
|
||||
* @param {function} eventMapping (optional) Function to convert the output
|
||||
* of the eventEmitter to the subscription output.
|
||||
* @param {function} getInitData (optional) Async function to grab the initial
|
||||
* data to publish. Signature `function(successCallback, errorCallback)`.
|
||||
* The resolved data will be transformed with the eventMapping before it
|
||||
* gets emitted.
|
||||
*/
|
||||
constructor(eventEmitter, eventName, eventMapping, getInitData) {
|
||||
|
||||
this._internalEmitter = new EventEmitter();
|
||||
this._eventMapping = eventMapping || (data => data);
|
||||
|
||||
this._upstreamSubscription = eventEmitter.addListener(
|
||||
eventName,
|
||||
this._handleEmit,
|
||||
this
|
||||
);
|
||||
|
||||
// Asyncronously get the initial data, if provided
|
||||
getInitData && getInitData(this._handleInitData.bind(this), logError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last data emitted from the Subscribable, or undefined
|
||||
*/
|
||||
get() {
|
||||
return this._lastData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from the upstream EventEmitter
|
||||
*/
|
||||
cleanup() {
|
||||
this._upstreamSubscription && this._upstreamSubscription.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new listener to the subscribable. This should almost never be used
|
||||
* directly, and instead through Subscribable.Mixin.subscribeTo
|
||||
*
|
||||
* @param {object} lifespan Object with `addUnmountCallback` that accepts
|
||||
* a handler to be called when the component unmounts. This is required and
|
||||
* desirable because it enforces cleanup. There is no easy way to leave the
|
||||
* subsciption hanging
|
||||
* {
|
||||
* addUnmountCallback: function(newUnmountHanlder) {...},
|
||||
* }
|
||||
* @param {function} callback Handler to call when Subscribable has data
|
||||
* updates
|
||||
* @param {object} context Object to bind the handler on, as "this"
|
||||
*
|
||||
* @return {object} the subscription object:
|
||||
* {
|
||||
* remove: function() {...},
|
||||
* }
|
||||
* Call `remove` to terminate the subscription before unmounting
|
||||
*/
|
||||
subscribe(lifespan, callback, context) {
|
||||
invariant(
|
||||
typeof lifespan.addUnmountCallback === 'function',
|
||||
'Must provide a valid lifespan, which provides a way to add a ' +
|
||||
'callback for when subscription can be cleaned up. This is used ' +
|
||||
'automatically by Subscribable.Mixin'
|
||||
);
|
||||
invariant(
|
||||
typeof callback === 'function',
|
||||
'Must provide a valid subscription handler.'
|
||||
);
|
||||
|
||||
// Add a listener to the internal EventEmitter
|
||||
var subscription = this._internalEmitter.addListener(
|
||||
SUBSCRIBABLE_INTERNAL_EVENT,
|
||||
callback,
|
||||
context
|
||||
);
|
||||
|
||||
// Clean up subscription upon the lifespan unmount callback
|
||||
lifespan.addUnmountCallback(() => {
|
||||
subscription.remove();
|
||||
});
|
||||
|
||||
return subscription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the initial data resolution. Currently behaves the same as
|
||||
* `_handleEmit`, but we may eventually want to keep track of the difference
|
||||
*/
|
||||
_handleInitData(dataInput) {
|
||||
var emitData = this._eventMapping(dataInput);
|
||||
this._lastData = emitData;
|
||||
this._internalEmitter.emit(SUBSCRIBABLE_INTERNAL_EVENT, emitData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle new data emissions. Pass the data through our eventMapping
|
||||
* transformation, store it for later `get()`ing, and emit it for subscribers
|
||||
*/
|
||||
_handleEmit(dataInput) {
|
||||
var emitData = this._eventMapping(dataInput);
|
||||
this._lastData = emitData;
|
||||
this._internalEmitter.emit(SUBSCRIBABLE_INTERNAL_EVENT, emitData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Subscribable.Mixin = {
|
||||
|
||||
/**
|
||||
* @return {object} lifespan Object with `addUnmountCallback` that accepts
|
||||
* a handler to be called when the component unmounts
|
||||
* {
|
||||
* addUnmountCallback: function(newUnmountHanlder) {...},
|
||||
* }
|
||||
*/
|
||||
_getSubscribableLifespan: function() {
|
||||
if (!this._subscribableLifespan) {
|
||||
this._subscribableLifespan = {
|
||||
addUnmountCallback: (cb) => {
|
||||
this._endSubscribableLifespanCallbacks.push(cb);
|
||||
},
|
||||
};
|
||||
}
|
||||
return this._subscribableLifespan;
|
||||
},
|
||||
|
||||
_endSubscribableLifespan: function() {
|
||||
this._endSubscribableLifespanCallbacks.forEach(cb => cb());
|
||||
},
|
||||
|
||||
/**
|
||||
* Components use `subscribeTo` for listening to Subscribable stores. Cleanup
|
||||
* is automatic on component unmount.
|
||||
*
|
||||
* To stop listening to the subscribable and end the subscription early,
|
||||
* components should store the returned subscription object and invoke the
|
||||
* `remove()` function on it
|
||||
*
|
||||
* @param {Subscribable} subscription to subscribe to.
|
||||
* @param {function} listener Function to invoke when event occurs.
|
||||
* @param {object} context Object to bind the handler on, as "this"
|
||||
*
|
||||
* @return {object} the subscription object:
|
||||
* {
|
||||
* remove: function() {...},
|
||||
* }
|
||||
* Call `remove` to terminate the subscription before unmounting
|
||||
*/
|
||||
subscribeTo: function(subscribable, handler, context) {
|
||||
invariant(
|
||||
subscribable instanceof Subscribable,
|
||||
'Must provide a Subscribable'
|
||||
);
|
||||
return subscribable.subscribe(
|
||||
this._getSubscribableLifespan(),
|
||||
handler,
|
||||
context
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a Subscribable store, scoped to the component, that can be passed to
|
||||
* children. The component will automatically clean up the subscribable's
|
||||
* subscription to the eventEmitter when unmounting.
|
||||
*
|
||||
* `provideSubscribable` will always return the same Subscribable for any
|
||||
* particular emitter/eventName combo, so it can be called directly from
|
||||
* render, and it will never create duplicate Subscribables.
|
||||
*
|
||||
* @param {EventEmitter} eventEmitter Emitter to trigger subscription events.
|
||||
* @param {string} eventName Name of emitted event that triggers subscription
|
||||
* events.
|
||||
* @param {function} eventMapping (optional) Function to convert the output
|
||||
* of the eventEmitter to the subscription output.
|
||||
* @param {function} getInitData (optional) Async function to grab the initial
|
||||
* data to publish. Signature `function(successCallback, errorCallback)`.
|
||||
* The resolved data will be transformed with the eventMapping before it
|
||||
* gets emitted.
|
||||
*/
|
||||
provideSubscribable: function(eventEmitter, eventName, eventMapping, getInitData) {
|
||||
this._localSubscribables = this._localSubscribables || {};
|
||||
this._localSubscribables[eventEmitter] =
|
||||
this._localSubscribables[eventEmitter] || {};
|
||||
if (!this._localSubscribables[eventEmitter][eventName]) {
|
||||
this._localSubscribables[eventEmitter][eventName] =
|
||||
new Subscribable(eventEmitter, eventName, eventMapping, getInitData);
|
||||
}
|
||||
return this._localSubscribables[eventEmitter][eventName];
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes any local Subscribables created with `provideSubscribable`, so the
|
||||
* component can unmount without leaving any dangling listeners on
|
||||
* eventEmitters
|
||||
*/
|
||||
_cleanupLocalSubscribables: function() {
|
||||
if (!this._localSubscribables) {
|
||||
return;
|
||||
}
|
||||
var emitterSubscribables;
|
||||
Object.keys(this._localSubscribables).forEach((eventEmitter) => {
|
||||
emitterSubscribables = this._localSubscribables[eventEmitter];
|
||||
Object.keys(emitterSubscribables).forEach((eventName) => {
|
||||
emitterSubscribables[eventName].cleanup();
|
||||
});
|
||||
});
|
||||
this._localSubscribables = null;
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._endSubscribableLifespanCallbacks = [];
|
||||
|
||||
// DEPRECATED addListenerOn* usage:
|
||||
this._subscribableSubscriptions = [];
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
// Resolve the lifespan, which will cause Subscribable to clean any
|
||||
// remaining subscriptions
|
||||
this._endSubscribableLifespan && this._endSubscribableLifespan();
|
||||
|
||||
this._cleanupLocalSubscribables();
|
||||
|
||||
// DEPRECATED addListenerOn* usage uses _subscribableSubscriptions array
|
||||
// instead of lifespan
|
||||
this._subscribableSubscriptions.forEach(
|
||||
(subscription) => subscription.remove()
|
||||
);
|
||||
this._subscribableSubscriptions = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* DEPRECATED - Use `Subscribable` and `Mixin.subscribeTo` instead.
|
||||
* `addListenerOn` subscribes the component to an `EventEmitter`.
|
||||
*
|
||||
* Special form of calling `addListener` that *guarantees* that a
|
||||
* subscription *must* be tied to a component instance, and therefore will
|
||||
* be cleaned up when the component is unmounted. It is impossible to create
|
||||
* the subscription and pass it in - this method must be the one to create
|
||||
* the subscription and therefore can guarantee it is retained in a way that
|
||||
* will be cleaned up.
|
||||
*
|
||||
* @param {EventEmitter} eventEmitter emitter to subscribe to.
|
||||
* @param {string} eventType Type of event to listen to.
|
||||
* @param {function} listener Function to invoke when event occurs.
|
||||
* @param {object} context Object to use as listener context.
|
||||
*/
|
||||
addListenerOn: function(eventEmitter, eventType, listener, context) {
|
||||
this._subscribableSubscriptions.push(
|
||||
eventEmitter.addListener(eventType, listener, context)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Subscribable;
|
||||