Updates from Sat 14 Mar

- Unforked RKWebView | Nick Lockwood
- [ReactNative] Add integration test stuff | Spencer Ahrens
- [ReactNative] AlertIOS.alert and examples | Eric Vicenti
- [react-packager] Implement image loading i.e. ix('img') -> require('image!img'); | Amjad Masad
- Fixed scrollOffset bug | Nick Lockwood
- [React Native] Update 2048 | Alex Akers
- deepDiffer should support explicitly undefined values | Thomas Aylott
This commit is contained in:
Christopher Chedeau
2015-03-14 10:52:40 -07:00
parent 74899c8ee0
commit 41ae2314ce
52 changed files with 2807 additions and 74 deletions

View File

@@ -15,20 +15,20 @@ var {
View,
} = React;
var GameBoard = require('./GameBoard');
var GameBoard = require('GameBoard');
var TouchableBounce = require('TouchableBounce');
var BOARD_PADDING = 3;
var CELL_MARGIN = 4;
var CELL_SIZE = 60;
var Cell = React.createClass({
render: function() {
class Cell extends React.Component {
render() {
return <View style={styles.cell} />;
}
});
}
var Board = React.createClass({
class Board extends React.Component {
render() {
return (
<View style={styles.board}>
@@ -40,12 +40,10 @@ var Board = React.createClass({
</View>
);
}
});
}
var Tile = React.createClass({
mixins: [Animation.Mixin],
calculateOffset() {
class Tile extends React.Component {
calculateOffset(): {top: number; left: number; opacity: number} {
var tile = this.props.tile;
var pos = (i) => {
@@ -59,6 +57,7 @@ var Tile = React.createClass({
var offset = {
top: pos(tile.toRow()),
left: pos(tile.toColumn()),
opacity: 1,
};
if (tile.isNew()) {
@@ -68,18 +67,18 @@ var Tile = React.createClass({
animationPosition(tile.toColumn()),
animationPosition(tile.toRow()),
];
this.startAnimation('this', 100, 0, 'easeInOutQuad', {position: point});
Animation.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {position: point});
}
return offset;
},
}
componentDidMount() {
setTimeout(() => {
this.startAnimation('this', 300, 0, 'easeInOutQuad', {scaleXY: [1, 1]});
this.startAnimation('this', 100, 0, 'easeInOutQuad', {opacity: 1});
Animation.startAnimation(this.refs['this'], 300, 0, 'easeInOutQuad', {scaleXY: [1, 1]});
Animation.startAnimation(this.refs['this'], 100, 0, 'easeInOutQuad', {opacity: 1});
}, 0);
},
}
render() {
var tile = this.props.tile;
@@ -103,9 +102,9 @@ var Tile = React.createClass({
</View>
);
}
});
}
var GameEndOverlay = React.createClass({
class GameEndOverlay extends React.Component {
render() {
var board = this.props.board;
@@ -127,27 +126,30 @@ var GameEndOverlay = React.createClass({
</View>
);
}
});
}
var Game2048 = React.createClass({
getInitialState() {
return { board: new GameBoard() };
},
class Game2048 extends React.Component {
constructor(props) {
super(props);
this.state = {
board: new GameBoard(),
};
}
restartGame() {
this.setState(this.getInitialState());
},
this.setState({board: new GameBoard()});
}
handleTouchStart(event) {
handleTouchStart(event: Object) {
if (this.state.board.hasWon()) {
return;
}
this.startX = event.nativeEvent.pageX;
this.startY = event.nativeEvent.pageY;
},
}
handleTouchEnd(event) {
handleTouchEnd(event: Object) {
if (this.state.board.hasWon()) {
return;
}
@@ -165,7 +167,7 @@ var Game2048 = React.createClass({
if (direction !== -1) {
this.setState({board: this.state.board.move(direction)});
}
},
}
render() {
var tiles = this.state.board.tiles
@@ -175,16 +177,16 @@ var Game2048 = React.createClass({
return (
<View
style={styles.container}
onTouchStart={this.handleTouchStart}
onTouchEnd={this.handleTouchEnd}>
onTouchStart={(event) => this.handleTouchStart(event)}
onTouchEnd={(event) => this.handleTouchEnd(event)}>
<Board>
{tiles}
</Board>
<GameEndOverlay board={this.state.board} onRestart={this.restartGame} />
<GameEndOverlay board={this.state.board} onRestart={() => this.restartGame()} />
</View>
);
}
});
}
var styles = StyleSheet.create({
container: {

View File

@@ -6,6 +6,6 @@
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@@ -0,0 +1,98 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*/
'use strict';
var React = require('react-native');
var {
StyleSheet,
View,
Text,
TouchableHighlight,
AlertIOS,
} = React;
exports.framework = 'React';
exports.title = 'AlertIOS';
exports.description = 'iOS alerts and action sheets';
exports.examples = [{
title: 'Alerts',
render() {
return (
<View>
<TouchableHighlight style={styles.wrapper}
onPress={() => AlertIOS.alert(
'Foo Title',
'My Alert Msg'
)}>
<View style={styles.button}>
<Text>Alert with message and default button</Text>
</View>
</TouchableHighlight>
<TouchableHighlight style={styles.wrapper}
onPress={() => AlertIOS.alert(
null,
null,
[
{text: 'Button', onPress: () => console.log('Button Pressed!')},
]
)}>
<View style={styles.button}>
<Text>Alert with only one button</Text>
</View>
</TouchableHighlight>
<TouchableHighlight style={styles.wrapper}
onPress={() => AlertIOS.alert(
'Foo Title',
'My Alert Msg',
[
{text: 'Foo', onPress: () => console.log('Foo Pressed!')},
{text: 'Bar', onPress: () => console.log('Bar Pressed!')},
]
)}>
<View style={styles.button}>
<Text>Alert with two buttons</Text>
</View>
</TouchableHighlight>
<TouchableHighlight style={styles.wrapper}
onPress={() => AlertIOS.alert(
'Foo Title',
null,
[
{text: 'Foo', onPress: () => console.log('Foo Pressed!')},
{text: 'Bar', onPress: () => console.log('Bar Pressed!')},
{text: 'Baz', onPress: () => console.log('Baz Pressed!')},
]
)}>
<View style={styles.button}>
<Text>Alert with 3 buttons</Text>
</View>
</TouchableHighlight>
<TouchableHighlight style={styles.wrapper}
onPress={() => AlertIOS.alert(
'Foo Title',
'My Alert Msg',
'..............'.split('').map((dot, index) => ({
text: 'Button ' + index,
onPress: () => console.log('Pressed ' + index)
}))
)}>
<View style={styles.button}>
<Text>Alert with too many buttons</Text>
</View>
</TouchableHighlight>
</View>
);
},
}];
var styles = StyleSheet.create({
wrapper: {
borderRadius: 5,
marginBottom: 5,
},
button: {
backgroundColor: '#eeeeee',
padding: 10,
},
});

View File

@@ -40,7 +40,9 @@ var EXAMPLES = [
require('./AsyncStorageExample'),
require('./CameraRollExample.ios'),
require('./MapViewExample'),
require('./WebViewExample'),
require('./AppStateIOSExample'),
require('./AlertIOSExample'),
require('./AdSupportIOSExample'),
require('./AppStateExample'),
require('./ActionSheetIOSExample'),

View File

@@ -0,0 +1,264 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*/
'use strict';
var React = require('react-native');
var StyleSheet = require('StyleSheet');
var {
ActivityIndicatorIOS,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
WebView
} = React;
var HEADER = '#3b5998';
var BGWASH = 'rgba(255,255,255,0.8)';
var DISABLED_WASH = 'rgba(255,255,255,0.25)';
var TEXT_INPUT_REF = 'urlInput';
var WEBVIEW_REF = 'webview';
var DEFAULT_URL = 'https://m.facebook.com';
var WebViewExample = React.createClass({
getInitialState: function() {
return {
url: DEFAULT_URL,
status: 'No Page Loaded',
backButtonEnabled: false,
forwardButtonEnabled: false,
loading: true,
};
},
handleTextInputChange: function(event) {
this.inputText = event.nativeEvent.text;
},
render: function() {
this.inputText = this.state.url;
return (
<View style={[styles.container]}>
<View style={[styles.addressBarRow]}>
<TouchableOpacity onPress={this.goBack}>
<View style={this.state.backButtonEnabled ? styles.navButton : styles.disabledButton}>
<Text>
{'<'}
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this.goForward}>
<View style={this.state.forwardButtonEnabled ? styles.navButton : styles.disabledButton}>
<Text>
{'>'}
</Text>
</View>
</TouchableOpacity>
<TextInput
ref={TEXT_INPUT_REF}
autoCapitalize="none"
value={this.state.url}
onSubmitEditing={this.onSubmitEditing}
onChange={this.handleTextInputChange}
clearButtonMode="while-editing"
style={styles.addressBarTextInput}
/>
<TouchableOpacity onPress={this.pressGoButton}>
<View style={styles.goButton}>
<Text>
Go!
</Text>
</View>
</TouchableOpacity>
</View>
<WebView
ref={WEBVIEW_REF}
automaticallyAdjustContentInsets={false}
style={styles.webView}
url={this.state.url}
renderErrorView={this.renderErrorView}
renderLoadingView={this.renderLoadingView}
onNavigationStateChange={this.onNavigationStateChange}
startInLoadingState={true}
/>
<View style={styles.statusBar}>
<Text style={styles.statusBarText}>{this.state.status}</Text>
</View>
</View>
);
},
goBack: function() {
this.refs[WEBVIEW_REF].goBack();
},
goForward: function() {
this.refs[WEBVIEW_REF].goForward();
},
reload: function() {
this.refs[WEBVIEW_REF].reload();
},
onNavigationStateChange: function(navState) {
this.setState({
backButtonEnabled: navState.canGoBack,
forwardButtonEnabled: navState.canGoForward,
url: navState.url,
status: navState.title,
loading: navState.loading,
});
},
renderErrorView: function(errorDomain, errorCode, errorDesc) {
return (
<View style={styles.errorContainer}>
<Text style={styles.errorTextTitle}>
Error loading page
</Text>
<Text style={styles.errorText}>
{'Domain: ' + errorDomain}
</Text>
<Text style={styles.errorText}>
{'Error Code: ' + errorCode}
</Text>
<Text style={styles.errorText}>
{'Description: ' + errorDesc}
</Text>
</View>
);
},
renderLoadingView: function() {
return (
<View style={styles.loadingView}>
<ActivityIndicatorIOS />
</View>
);
},
onSubmitEditing: function(event) {
this.pressGoButton();
},
pressGoButton: function() {
var url = this.inputText.toLowerCase();
if (url === this.state.url) {
this.reload();
} else {
this.setState({
url: url,
});
}
// dismiss keyoard
this.refs[TEXT_INPUT_REF].blur();
},
});
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: HEADER,
},
addressBarRow: {
flexDirection: 'row',
padding: 8,
},
webView: {
backgroundColor: BGWASH,
height: 350,
},
addressBarTextInput: {
backgroundColor: BGWASH,
borderColor: 'transparent',
borderRadius: 3,
borderWidth: 1,
height: 24,
paddingLeft: 10,
paddingTop: 3,
paddingBottom: 3,
flex: 1,
fontSize: 14,
},
navButton: {
width: 20,
padding: 3,
marginRight: 3,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: BGWASH,
borderColor: 'transparent',
borderRadius: 3,
},
disabledButton: {
width: 20,
padding: 3,
marginRight: 3,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: DISABLED_WASH,
borderColor: 'transparent',
borderRadius: 3,
},
goButton: {
height: 24,
padding: 3,
marginLeft: 8,
alignItems: 'center',
backgroundColor: BGWASH,
borderColor: 'transparent',
borderRadius: 3,
alignSelf: 'stretch',
},
loadingView: {
backgroundColor: BGWASH,
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: BGWASH,
},
errorTextTitle: {
fontSize: 15,
fontWeight: 'bold',
marginBottom: 10,
},
errorText: {
fontSize: 14,
textAlign: 'center',
marginBottom: 2,
},
statusBar: {
flexDirection: 'row',
alignItems: 'center',
paddingLeft: 5,
height: 22,
},
statusBarText: {
color: 'white',
fontSize: 13,
},
spinner: {
width: 20,
marginRight: 6,
},
});
exports.title = '<WebView>';
exports.description = 'Base component to display web content';
exports.examples = [
{
title: 'WebView',
render() { return <WebViewExample />; }
}
];