Skip to content

Commit

Permalink
More shared code refactoring in native-land
Browse files Browse the repository at this point in the history
  • Loading branch information
lmorchard committed Sep 18, 2015
1 parent 5afd577 commit ea7abb4
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 185 deletions.
61 changes: 11 additions & 50 deletions lib/views/android/TodoItem.js
@@ -1,61 +1,22 @@
var React = require('react-native');

var { Text, TextInput, View, ListView, SwitchAndroid,
TouchableHighlight } = React;
var { SwitchAndroid } = React;

var Views = require('../index');
var styles = require('./styles');

var TodoItem = module.exports = React.createClass({

mixins: [Views.TodoItemCommonMixin],

render() {

var title = (!this.state.editing) ? (
<Text style={styles.todoTitle} onPress={this.handleEditStart}>
{this.state.item.title}
</Text>
) : (
<View style={styles.todoEditGroup}>

<TextInput
style={styles.todoEditField}
ref="editField"
autoFocus={true}
defaultValue={this.state.item.title}
onSubmitEditing={this.handleEditSubmit} />

<TouchableHighlight
style={styles.todoDeleteButton}
activeOpacity={0.6}
underlayColor={'red'}
onPress={this.handleDelete}>

<Text style={styles.todoDeleteButtonText}>Delete</Text>

</TouchableHighlight>

</View>
);

styles: styles,
mixins: [
Views.TodoItemCommonMixin,
Views.TodoItemNativeCommonMixin
],
renderTodoCompleted() {
return (
<View style={styles.todoItem}>
<SwitchAndroid
style={styles.todoCompleted}
onValueChange={this.handleCompletedChange}
value={this.state.item.completed} />
{title}
</View>
<SwitchAndroid
style={this.styles.todoCompleted}
onValueChange={this.handleCompletedChange}
value={this.state.item.completed} />
);

},

handleEditSubmit(event) {
var val = event.nativeEvent.text.trim();
this.refs.editField.setNativeProps({text: ''});
this.setState({ editing: false });
this.state.item.title = val;
}

});
49 changes: 7 additions & 42 deletions lib/views/android/TodoList.js
@@ -1,51 +1,16 @@
var React = require('react-native');

var { ListView } = React;

var Views = require('../index');
var styles = require('./styles');
var TodoItem = require('./TodoItem');

var TodoList = module.exports = React.createClass({

mixins: [Views.TodoListCommonMixin],

render() {
return (
<ListView
style={styles.todoList}
dataSource={this.state.dataSource}
renderRow={(item) =>
<TodoItem key={item.cid} item={item} />}
/>
);
},

getInitialState() {
return {
collection: this.props.collection,
dataSource: new React.ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
})
};
},

componentDidMount() {
// TODO: Should this happen in getInitialState instead?
this.setState({ dataSource: this.updateDataSource() });

this.state.collection.on('change add remove', () => {
this.setState({ dataSource: this.updateDataSource() });
}, this);
},

updateDataSource() {
// NOTE: The DataSource retains a reference to the previous model list in
// order to diff it against new lists to detect changes. So, we have to
// make a fresh clone of the list, every time.
// TODO: Is there a better way to do this?
var rows = this.state.collection.map((model) => model);
return this.state.dataSource.cloneWithRows(rows);
styles: styles,
mixins: [
Views.TodoListCommonMixin,
Views.TodoListNativeCommonMixin
],
renderRow(item) {
return (<TodoItem key={item.cid} item={item} />);
}

});
91 changes: 90 additions & 1 deletion lib/views/index.js
@@ -1,4 +1,8 @@
// Mixins representing shared logic between web & iOS views.
var React = require('react-native');

var { Text, TextInput, View, ListView, SwitchAndroid,
TouchableHighlight } = React;

exports.LIST_MODES = [
{mode: 'all', label: 'All (%s)', state: 'totalCount'},
Expand Down Expand Up @@ -40,6 +44,42 @@ exports.TodoListCommonMixin = {
}
};

exports.TodoListNativeCommonMixin = {
render() {
return (
<ListView
style={this.styles.todoList}
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
);
},
getInitialState() {
return {
collection: this.props.collection,
dataSource: new React.ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
})
};
},
componentDidMount() {
// TODO: Should this happen in getInitialState instead?
this.setState({ dataSource: this.updateDataSource() });

this.state.collection.on('change add remove', () => {
this.setState({ dataSource: this.updateDataSource() });
}, this);
},
updateDataSource() {
// NOTE: The DataSource retains a reference to the previous model list in
// order to diff it against new lists to detect changes. So, we have to
// make a fresh clone of the list, every time.
// TODO: Is there a better way to do this?
var rows = this.state.collection.map((model) => model);
return this.state.dataSource.cloneWithRows(rows);
}
};

exports.TodoItemCommonMixin = {
getInitialState() {
return {
Expand Down Expand Up @@ -72,4 +112,53 @@ exports.TodoItemCommonMixin = {
this.state.item.on('change', () => this.forceUpdate(), this);
}
}
}
};

exports.TodoItemNativeCommonMixin = {

render() {

var title = (!this.state.editing) ? (
<Text style={this.styles.todoTitle} onPress={this.handleEditStart}>
{this.state.item.title}
</Text>
) : (
<View style={this.styles.todoEditGroup}>

<TextInput
style={this.styles.todoEditField}
ref="editField"
autoFocus={true}
defaultValue={this.state.item.title}
onSubmitEditing={this.handleEditSubmit} />

<TouchableHighlight
style={this.styles.todoDeleteButton}
activeOpacity={0.6}
underlayColor={'red'}
onPress={this.handleDelete}>

<Text style={this.styles.todoDeleteButtonText}>Delete</Text>

</TouchableHighlight>

</View>
);

return (
<View style={this.styles.todoItem}>
{this.renderTodoCompleted()}
{title}
</View>
);

},

handleEditSubmit(event) {
var val = event.nativeEvent.text.trim();
this.refs.editField.setNativeProps({text: ''});
this.setState({ editing: false });
this.state.item.title = val;
}

};
61 changes: 11 additions & 50 deletions lib/views/ios/TodoItem.js
@@ -1,61 +1,22 @@
var React = require('react-native');

var { Text, TextInput, View, ListView, SwitchIOS,
TouchableHighlight } = React;
var { SwitchIOS } = React;

var Views = require('../index');
var styles = require('./styles');

var TodoItem = module.exports = React.createClass({

mixins: [Views.TodoItemCommonMixin],

render() {

var title = (!this.state.editing) ? (
<Text style={styles.todoTitle} onPress={this.handleEditStart}>
{this.state.item.title}
</Text>
) : (
<View style={styles.todoEditGroup}>

<TextInput
style={styles.todoEditField}
ref="editField"
autoFocus={true}
defaultValue={this.state.item.title}
onSubmitEditing={this.handleEditSubmit} />

<TouchableHighlight
style={styles.todoDeleteButton}
activeOpacity={0.6}
underlayColor={'red'}
onPress={this.handleDelete}>

<Text style={styles.todoDeleteButtonText}>Delete</Text>

</TouchableHighlight>

</View>
);

styles: styles,
mixins: [
Views.TodoItemCommonMixin,
Views.TodoItemNativeCommonMixin
],
renderTodoCompleted() {
return (
<View style={styles.todoItem}>
<SwitchIOS
style={styles.todoCompleted}
onValueChange={this.handleCompletedChange}
value={this.state.item.completed} />
{title}
</View>
<SwitchIOS
style={styles.todoCompleted}
onValueChange={this.handleCompletedChange}
value={this.state.item.completed} />
);

},

handleEditSubmit(event) {
var val = event.nativeEvent.text.trim();
this.refs.editField.setNativeProps({text: ''});
this.setState({ editing: false });
this.state.item.title = val;
}

});
49 changes: 7 additions & 42 deletions lib/views/ios/TodoList.js
@@ -1,51 +1,16 @@
var React = require('react-native');

var { ListView } = React;

var Views = require('../index');
var styles = require('./styles');
var TodoItem = require('./TodoItem');

var TodoList = module.exports = React.createClass({

mixins: [Views.TodoListCommonMixin],

render() {
return (
<ListView
style={styles.todoList}
dataSource={this.state.dataSource}
renderRow={(item) =>
<TodoItem key={item.cid} item={item} />}
/>
);
},

getInitialState() {
return {
collection: this.props.collection,
dataSource: new React.ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
})
};
},

componentDidMount() {
// TODO: Should this happen in getInitialState instead?
this.setState({ dataSource: this.updateDataSource() });

this.state.collection.on('change add remove', () => {
this.setState({ dataSource: this.updateDataSource() });
}, this);
},

updateDataSource() {
// NOTE: The DataSource retains a reference to the previous model list in
// order to diff it against new lists to detect changes. So, we have to
// make a fresh clone of the list, every time.
// TODO: Is there a better way to do this?
var rows = this.state.collection.map((model) => model);
return this.state.dataSource.cloneWithRows(rows);
styles: styles,
mixins: [
Views.TodoListCommonMixin,
Views.TodoListNativeCommonMixin
],
renderRow(item) {
return (<TodoItem key={item.cid} item={item} />);
}

});

0 comments on commit ea7abb4

Please sign in to comment.