mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-26 23:05:00 +08:00
Updates from Wed 18 Mar
- [ReactNative] Add AsyncStorageTest | Spencer Ahrens - [ReactNative] Add timers integration test | Spencer Ahrens - [ReactNative] Remove ExpandingText | Tadeu Zagallo - [TouchableHighlight] Preserve underlay style when restoring inactive props | Christopher Chedeau - clean flow errors in react-native-github | Basil Hosmer - [ReactNative] Sort React Native exports into two groups, Components and APIs | Christopher Chedeau - [ReactNative] Rename Slider to SliderIOS | Tadeu Zagallo - [react_native] JS files from D1919491: Improve JS logging | Martin Kosiba - [ReactNative] Add TimerExample | Spencer Ahrens - [RFC][ReactNative] increase timer resolution | Spencer Ahrens - [ReactNative] Strip prefixes from NativeModules keys | Spencer Ahrens - [ReactNative] Small docs cleanup in ActivityIndicatorIOS and DatePickerIOS | Christopher Chedeau - [ReactNative] Improvements on perf measurement output | Jing Chen - [ReactNative] Clean up Touchable PropTypes | Christopher Chedeau - [ReactKit] Fail tests when redbox shows up | Alex Kotliarskyi
This commit is contained in:
@@ -7,7 +7,7 @@ var React = require('react-native');
|
||||
var {
|
||||
CameraRoll,
|
||||
Image,
|
||||
Slider,
|
||||
SliderIOS,
|
||||
StyleSheet,
|
||||
SwitchIOS,
|
||||
Text,
|
||||
@@ -35,7 +35,7 @@ var CameraRollExample = React.createClass({
|
||||
onValueChange={this._onSwitchChange}
|
||||
value={this.state.bigImages} />
|
||||
<Text>{(this.state.bigImages ? 'Big' : 'Small') + ' Images'}</Text>
|
||||
<Slider
|
||||
<SliderIOS
|
||||
value={this.state.sliderValue}
|
||||
onValueChange={this._onSliderChange}
|
||||
/>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*/
|
||||
'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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}];
|
||||
@@ -99,11 +99,11 @@ var ListViewPagingExample = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
renderRow: function(rowData, sectionID, rowID) {
|
||||
renderRow: function(rowData: string, sectionID: string, rowID: string): ReactElement {
|
||||
return (<Thumb text={rowData}/>);
|
||||
},
|
||||
|
||||
renderSectionHeader: function(sectionData, sectionID) {
|
||||
renderSectionHeader: function(sectionData: string, sectionID: string) {
|
||||
return (
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.text}>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
Slider,
|
||||
SliderIOS,
|
||||
Text,
|
||||
StyleSheet,
|
||||
View,
|
||||
@@ -24,7 +24,7 @@ var SliderExample = React.createClass({
|
||||
<Text style={styles.text} >
|
||||
{this.state.value}
|
||||
</Text>
|
||||
<Slider
|
||||
<SliderIOS
|
||||
style={styles.slider}
|
||||
onValueChange={(value) => this.setState({value: value})} />
|
||||
</View>
|
||||
@@ -45,11 +45,11 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<Slider>';
|
||||
exports.title = '<SliderIOS>';
|
||||
exports.description = 'Slider input for numeric values';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Slider',
|
||||
title: 'SliderIOS',
|
||||
render() { return <SliderExample />; }
|
||||
}
|
||||
];
|
||||
193
Examples/UIExplorer/TimerExample.js
Normal file
193
Examples/UIExplorer/TimerExample.js
Normal file
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
AlertIOS,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TimerMixin,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var Button = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<TouchableHighlight
|
||||
onPress={this.props.onPress}
|
||||
style={styles.button}
|
||||
underlayColor="#eeeeee">
|
||||
<Text>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
var TimerTester = React.createClass({
|
||||
mixins: [TimerMixin],
|
||||
|
||||
render: function() {
|
||||
var args = 'fn' + (this.props.dt !== undefined ? ', ' + this.props.dt : '');
|
||||
return (
|
||||
<Button onPress={this._run}>
|
||||
Measure: {this.props.type}({args}) - {this._ii || 0}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
|
||||
_run: function() {
|
||||
if (!this._start) {
|
||||
var d = new Date();
|
||||
this._start = d.getTime();
|
||||
this._iters = 100;
|
||||
this._ii = 0;
|
||||
if (this.props.type === 'setTimeout') {
|
||||
if (this.props.dt < 1) {
|
||||
this._iters = 5000;
|
||||
} else if (this.props.dt > 20) {
|
||||
this._iters = 10;
|
||||
}
|
||||
this._timerFn = () => this.setTimeout(this._run, this.props.dt);
|
||||
} else if (this.props.type === 'requestAnimationFrame') {
|
||||
this._timerFn = () => this.requestAnimationFrame(this._run);
|
||||
} else if (this.props.type === 'setImmediate') {
|
||||
this._iters = 5000;
|
||||
this._timerFn = () => this.setImmediate(this._run);
|
||||
} else if (this.props.type === 'setInterval') {
|
||||
this._iters = 30; // Only used for forceUpdate periodicidy
|
||||
this._timerFn = null;
|
||||
this._handle = this.setInterval(this._run, this.props.dt);
|
||||
}
|
||||
}
|
||||
if (this._ii >= this._iters && !this._handle) {
|
||||
var d = new Date();
|
||||
var e = (d.getTime() - this._start);
|
||||
var msg = 'Finished ' + this._ii + ' ' + this.props.type + ' calls.\n' +
|
||||
'Elapsed time: ' + e + ' ms\n' + (e / this._ii) + ' ms / iter';
|
||||
console.log(msg);
|
||||
AlertIOS.alert(msg);
|
||||
this._start = null;
|
||||
this.forceUpdate(() => { this._ii = 0; });
|
||||
return;
|
||||
}
|
||||
this._ii++;
|
||||
// Only re-render occasionally so we don't slow down timers.
|
||||
if (this._ii % (this._iters / 5) === 0) {
|
||||
this.forceUpdate();
|
||||
}
|
||||
this._timerFn && this._timerFn();
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.clearInterval(this._handle); // invalid handles are ignored
|
||||
if (this._handle) {
|
||||
// Configure things so we can do a final run to update UI and reset state.
|
||||
this._handle = null;
|
||||
this._iters = this._ii;
|
||||
this._run();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
button: {
|
||||
borderColor: 'gray',
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
padding: 10,
|
||||
margin: 5,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'Timers, TimerMixin';
|
||||
exports.description = 'The TimerMixin provides timer functions for executing ' +
|
||||
'code in the future that are safely cleaned up when the component unmounts.';
|
||||
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'this.setTimeout(fn, t)',
|
||||
description: 'Execute function fn t milliseconds in the future. If ' +
|
||||
't === 0, it will be enqueued immediately in the next event loop. ' +
|
||||
'Larger values will fire on the closest frame.',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TimerTester type="setTimeout" dt={0} />
|
||||
<TimerTester type="setTimeout" dt={1} />
|
||||
<TimerTester type="setTimeout" dt={100} />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'this.requestAnimationFrame(fn)',
|
||||
description: 'Execute function fn on the next frame.',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TimerTester type="requestAnimationFrame" />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'this.setImmediate(fn)',
|
||||
description: 'Execute function fn at the end of the current JS event loop.',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<TimerTester type="setImmediate" />
|
||||
</View>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'this.setInterval(fn, t)',
|
||||
description: 'Execute function fn every t milliseconds until cancelled ' +
|
||||
'or component is unmounted.',
|
||||
render: function() {
|
||||
var IntervalExample = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
showTimer: true,
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.showTimer) {
|
||||
var timer =
|
||||
<TimerTester ref="interval" dt={25} type="setInterval" />;
|
||||
var toggleText = 'Unmount timer';
|
||||
} else {
|
||||
var timer = null;
|
||||
var toggleText = 'Mount new timer';
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
{timer}
|
||||
<Button onPress={() => this.refs.interval.clear() }>
|
||||
Clear interval
|
||||
</Button>
|
||||
<Button onPress={this._toggleTimer}>
|
||||
{toggleText}
|
||||
</Button>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
_toggleTimer: function() {
|
||||
this.setState({showTimer: !this.state.showTimer});
|
||||
},
|
||||
});
|
||||
return <IntervalExample />;
|
||||
},
|
||||
},
|
||||
];
|
||||
72
Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj.rej
Normal file
72
Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj.rej
Normal file
@@ -0,0 +1,72 @@
|
||||
diff a/Libraries/FBReactKit/js/react-native-github/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj b/Libraries/FBReactKit/js/react-native-github/Examples/UIExplorer/UIExplorer.xcodeproj/project.pbxproj (rejected hunks)
|
||||
@@ -19,6 +19,7 @@
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
+ D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -78,6 +79,13 @@
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RCTActionSheet;
|
||||
};
|
||||
+ D85B829B1AB6D5CE003F4FE2 /* PBXContainerItemProxy */ = {
|
||||
+ isa = PBXContainerItemProxy;
|
||||
+ containerPortal = D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */;
|
||||
+ proxyType = 2;
|
||||
+ remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
|
||||
+ remoteInfo = RCTVibration;
|
||||
+ };
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -98,6 +106,7 @@
|
||||
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>"; };
|
||||
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
|
||||
+ D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -112,6 +121,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
+ D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
|
||||
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */,
|
||||
134454601AAFCABD003F0779 /* libRCTAdSupport.a in Frameworks */,
|
||||
134A8A2A1AACED7A00945AAE /* libRCTGeolocation.a in Frameworks */,
|
||||
@@ -145,6 +155,7 @@
|
||||
1316A21D1AA397F400C0188E /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
+ D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */,
|
||||
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */,
|
||||
13417FFA1AA91531003F314A /* ReactKit.xcodeproj */,
|
||||
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */,
|
||||
@@ -334,6 +353,10 @@
|
||||
ProjectRef = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */;
|
||||
},
|
||||
{
|
||||
+ ProductGroup = D85B82921AB6D5CE003F4FE2 /* Products */;
|
||||
+ ProjectRef = D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */;
|
||||
+ },
|
||||
+ {
|
||||
ProductGroup = 13417FFB1AA91531003F314A /* Products */;
|
||||
ProjectRef = 13417FFA1AA91531003F314A /* ReactKit.xcodeproj */;
|
||||
},
|
||||
@@ -396,6 +419,13 @@
|
||||
remoteRef = 147CED4A1AB34F8C00DA3E4C /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
+ D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */ = {
|
||||
+ isa = PBXReferenceProxy;
|
||||
+ fileType = archive.ar;
|
||||
+ path = libRCTVibration.a;
|
||||
+ remoteRef = D85B829B1AB6D5CE003F4FE2 /* PBXContainerItemProxy */;
|
||||
+ sourceTree = BUILT_PRODUCTS_DIR;
|
||||
+ };
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
@@ -20,8 +20,8 @@ var EXAMPLES = [
|
||||
require('./ViewExample'),
|
||||
require('./LayoutExample'),
|
||||
require('./TextExample.ios'),
|
||||
require('./TimerExample'),
|
||||
require('./TextInputExample'),
|
||||
require('./ExpandingTextExample'),
|
||||
require('./ImageExample'),
|
||||
require('./ListViewSimpleExample'),
|
||||
require('./ListViewPagingExample'),
|
||||
@@ -36,7 +36,7 @@ var EXAMPLES = [
|
||||
require('./GeolocationExample'),
|
||||
require('./TabBarExample'),
|
||||
require('./SwitchExample'),
|
||||
require('./SliderExample'),
|
||||
require('./SliderIOSExample'),
|
||||
require('./AsyncStorageExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
require('./MapViewExample'),
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "RCTRedBox.h"
|
||||
|
||||
#define TIMEOUT_SECONDS 240
|
||||
|
||||
@interface UIExplorerTests : XCTestCase
|
||||
@@ -29,11 +31,14 @@
|
||||
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||
BOOL foundElement = NO;
|
||||
NSString *redboxError = nil;
|
||||
|
||||
while ([date timeIntervalSinceNow] > 0 && !foundElement) {
|
||||
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:date];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:date];
|
||||
|
||||
redboxError = [[RCTRedBox sharedInstance] currentErrorMessage];
|
||||
|
||||
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
|
||||
if ([view respondsToSelector:@selector(attributedText)]) {
|
||||
NSString *text = [(id)view attributedText].string;
|
||||
@@ -45,6 +50,7 @@
|
||||
}];
|
||||
}
|
||||
|
||||
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
|
||||
XCTAssertTrue(foundElement, @"Cound't find element with '<View>' text in %d seconds", TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user