Refactor and re-style example app
This commit is contained in:
parent
0b35564830
commit
549c2ceff7
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es6": true
|
||||
},
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-no-duplicate-props": 2,
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/no-direct-mutation-state": 1,
|
||||
"react/prefer-es6-class": 1,
|
||||
"react/react-in-jsx-scope": 2
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
const Realm = require('realm');
|
||||
|
||||
module.exports = new Realm({
|
||||
schema: [
|
||||
{
|
||||
name: 'Todo',
|
||||
properties: [
|
||||
{name: 'text', type: Realm.Types.STRING},
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'TodoList',
|
||||
properties: [
|
||||
{name: 'name', type: Realm.Types.STRING},
|
||||
{name: 'items', type: Realm.Types.LIST, objectType: 'Todo'},
|
||||
]
|
||||
},
|
||||
],
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
|
||||
module.exports = React.StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'stretch',
|
||||
backgroundColor: '#ffffff',
|
||||
},
|
||||
listItem: {
|
||||
padding: 12,
|
||||
borderColor: "#c8c7cc",
|
||||
borderBottomWidth: 0.5,
|
||||
alignItems: 'center',
|
||||
alignSelf: 'stretch',
|
||||
flexDirection: 'row',
|
||||
flex: 1,
|
||||
height: 44,
|
||||
},
|
||||
listItemText: {
|
||||
fontFamily: 'System',
|
||||
fontSize: 15,
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
lineHeight: 16,
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
}
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
const TodoList = require('./todo-list');
|
||||
const realm = require('./realm');
|
||||
|
||||
const { NavigatorIOS } = React;
|
||||
|
||||
class TodoApp extends React.Component {
|
||||
componentWillMount() {
|
||||
let todoLists = realm.objects('TodoList');
|
||||
|
||||
if (todoLists.length < 1) {
|
||||
realm.write(() => {
|
||||
realm.create('TodoList', {name: 'Todo List', items: []});
|
||||
});
|
||||
}
|
||||
|
||||
this.todoLists = todoLists;
|
||||
}
|
||||
|
||||
render() {
|
||||
let list = this.todoLists[0];
|
||||
|
||||
let route = {
|
||||
title: list.name,
|
||||
component: TodoList,
|
||||
passProps: {
|
||||
ref: 'todoList',
|
||||
list: list,
|
||||
},
|
||||
rightButtonTitle: 'Add',
|
||||
onRightButtonPress: () => this._addNewItem(list)
|
||||
};
|
||||
|
||||
return (
|
||||
<NavigatorIOS ref="nav" initialRoute={route} style={{flex: 1}} />
|
||||
);
|
||||
}
|
||||
|
||||
_addNewItem(list) {
|
||||
realm.write(() => {
|
||||
list.items.push({text: ''});
|
||||
});
|
||||
|
||||
let todoList = this.refs.nav.refs.todoList;
|
||||
todoList.setState({editingRow: list.items.length - 1});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TodoApp;
|
|
@ -0,0 +1,77 @@
|
|||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
const realm = require('./realm');
|
||||
const styles = require('./styles');
|
||||
|
||||
const { Text, TextInput, View } = React;
|
||||
|
||||
class TodoItem extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this._onChangeText = this._onChangeText.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// The autoFocus prop on TextInput was not working for us :(
|
||||
this._focusInputIfNecessary();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._focusInputIfNecessary();
|
||||
}
|
||||
|
||||
render() {
|
||||
let contents;
|
||||
|
||||
if (this.props.editing) {
|
||||
contents = (
|
||||
<TextInput
|
||||
ref="input"
|
||||
value={this.props.item.text}
|
||||
placeholder="Call Mom"
|
||||
style={styles.listItemText}
|
||||
onChangeText={this._onChangeText}
|
||||
onEndEditing={this.props.onEndEditing}
|
||||
enablesReturnKeyAutomatically={true} />
|
||||
);
|
||||
} else {
|
||||
contents = (
|
||||
<Text
|
||||
style={styles.listItemText}
|
||||
onPress={this.props.onPress}
|
||||
suppressHighlighting={true}>
|
||||
{this.props.item.text}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.listItem}>
|
||||
{contents}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_onChangeText(text) {
|
||||
realm.write(() => {
|
||||
this.props.item.text = text;
|
||||
});
|
||||
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
_focusInputIfNecessary() {
|
||||
if (!this.props.editing) {
|
||||
return;
|
||||
}
|
||||
|
||||
let input = this.refs.input;
|
||||
if (!input.isFocused()) {
|
||||
input.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TodoItem;
|
|
@ -0,0 +1,70 @@
|
|||
'use strict';
|
||||
|
||||
const React = require('react-native');
|
||||
const TodoItem = require('./todo-item');
|
||||
const realm = require('./realm');
|
||||
const styles = require('./styles');
|
||||
|
||||
const { ListView, Text, View } = React;
|
||||
|
||||
class TodoList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.dataSource = new ListView.DataSource({
|
||||
rowHasChanged: (row1, row2) => row1 !== row2
|
||||
});
|
||||
|
||||
this.state = {};
|
||||
this._renderRow = this._renderRow.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
let dataSource = this.dataSource.cloneWithRows(this.props.list.items);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ListView style={styles.listView} dataSource={dataSource} renderRow={this._renderRow} />
|
||||
<Text style={styles.instructions}>
|
||||
Press Cmd+R to reload,{'\n'}
|
||||
Cmd+D for dev menu
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(item, sectionIndex, rowIndex) {
|
||||
return (
|
||||
<TodoItem
|
||||
item={item}
|
||||
editing={this.state.editingRow == rowIndex}
|
||||
onPress={() => this._onPressRow(rowIndex)}
|
||||
onEndEditing={() => this._onEndEditingRow(rowIndex)} />
|
||||
);
|
||||
}
|
||||
|
||||
_onPressRow(rowIndex) {
|
||||
let editingRow = this.state.editingRow;
|
||||
|
||||
if (editingRow != null && editingRow != rowIndex) {
|
||||
this._onEndEditingRow(editingRow);
|
||||
}
|
||||
|
||||
this.setState({editingRow: rowIndex});
|
||||
}
|
||||
|
||||
_onEndEditingRow(rowIndex) {
|
||||
let items = this.props.list.items;
|
||||
|
||||
// Delete the todo item if it doesn't have any text.
|
||||
if (!items[rowIndex].text) {
|
||||
realm.write(() => items.splice(rowIndex, 1));
|
||||
}
|
||||
|
||||
if (this.state.editingRow == rowIndex) {
|
||||
this.setState({editingRow: null});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TodoList;
|
|
@ -1,198 +1,6 @@
|
|||
/**
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var Realm = require('realm');
|
||||
var React = require('react-native');
|
||||
const React = require('react-native');
|
||||
const TodoApp = require('./components/todo-app');
|
||||
|
||||
var {
|
||||
AppRegistry,
|
||||
StyleSheet,
|
||||
NavigatorIOS,
|
||||
AlertIOS,
|
||||
ListView,
|
||||
TouchableHighlight,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var TodoItemSchema = {
|
||||
name: 'Todo',
|
||||
properties: [
|
||||
{name: 'text', type: Realm.Types.STRING},
|
||||
]
|
||||
};
|
||||
var TodoListSchmea = {
|
||||
name: 'TodoList',
|
||||
properties: [
|
||||
{name: 'name', type: Realm.Types.STRING},
|
||||
{name: 'items', type: Realm.Types.LIST, objectType: 'Todo'}
|
||||
]
|
||||
};
|
||||
|
||||
console.log(Realm.defaultPath);
|
||||
var realm = new Realm({schema: [TodoItemSchema, TodoListSchmea]});
|
||||
|
||||
class Edit extends React.Component {
|
||||
componentWillMount() {
|
||||
this.setState({text: this.props.text});
|
||||
}
|
||||
|
||||
save() {
|
||||
realm.write(function () {
|
||||
if (this.props.todoId == this.props.list.items.length) {
|
||||
this.props.list.items.push({text: this.state.text});
|
||||
}
|
||||
else {
|
||||
var todoItem = this.props.list.items[this.props.todoId];
|
||||
todoItem.text = this.state.text;
|
||||
}
|
||||
}.bind(this));
|
||||
// should not be needed once we have notifications
|
||||
this.props.parent.updateDataSource();
|
||||
this.props.navigator.pop();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{flex:1, justifyContent: 'flex-start'}}>
|
||||
<TextInput multiline={true} style={styles.textInput}
|
||||
placeholder='Enter Todo' autoFocus={true}
|
||||
onChangeText={(text) => this.setState({text})} value={this.state.text}/>
|
||||
<TouchableHighlight
|
||||
style={styles.button}
|
||||
onPress={this.save.bind(this)}
|
||||
underlayColor='#99d9f4'>
|
||||
<Text style={styles.buttonText}>Save</Text>
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
class TodoList extends React.Component {
|
||||
componentWillMount() {
|
||||
this.lists = realm.objects('TodoList');
|
||||
if (this.lists.length < 1) {
|
||||
realm.write(function() {
|
||||
realm.create('TodoList', ['List', []]);
|
||||
});
|
||||
}
|
||||
this.list = this.lists[0];
|
||||
this.menu = this.menu.bind(this);
|
||||
this.delete = this.delete.bind(this);
|
||||
var dataSource = new ListView.DataSource({
|
||||
rowHasChanged: (row1, row2) => row1 !== row2
|
||||
});
|
||||
|
||||
this.updateDataSource(dataSource);
|
||||
}
|
||||
|
||||
updateDataSource(oldDataSource) {
|
||||
if (!oldDataSource) {
|
||||
oldDataSource = this.state.dataSource;
|
||||
}
|
||||
this.setState({dataSource: oldDataSource.cloneWithRows(this.list.items)});
|
||||
}
|
||||
|
||||
menu(todo, todoID) {
|
||||
AlertIOS.alert(
|
||||
todo.text,
|
||||
todoID,
|
||||
[
|
||||
{text: 'Complete', onPress: () => this.delete(todoID)},
|
||||
{text: 'Edit', onPress: () => this.edit(todoID, todo.text)},
|
||||
{text: 'Cancel'}
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
delete(todoID) {
|
||||
var item = this.list.items[todoID];
|
||||
realm.write(function() {
|
||||
realm.delete(item);
|
||||
})
|
||||
this.updateDataSource();
|
||||
}
|
||||
|
||||
edit(todoId, text) {
|
||||
this.props.navigator.push({
|
||||
title: text,
|
||||
component: Edit,
|
||||
passProps: {list: this.list, todoId: todoId, text: text, parent: this}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ListView style={styles.listView} dataSource={this.state.dataSource} renderRow={(rowData, sectionID, rowID) =>
|
||||
<TouchableHighlight style={styles.listItem} onPress={() => this.menu(rowData, rowID)}>
|
||||
<Text>{rowData.text}</Text>
|
||||
</TouchableHighlight>
|
||||
}/>
|
||||
<TouchableHighlight style={styles.button}
|
||||
onPress={() => this.edit(this.list.items.length, "")}>
|
||||
<Text style={styles.buttonText}>+</Text>
|
||||
</TouchableHighlight>
|
||||
<Text style={styles.instructions}>
|
||||
Press Cmd+R to reload,{'\n'}
|
||||
Cmd+Control+Z for dev menu
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class Navigator extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<NavigatorIOS initialRoute={{component: TodoList, title: 'Todo Items'}} style={{flex:1}}/>
|
||||
);
|
||||
}
|
||||
};
|
||||
AppRegistry.registerComponent('ReactExample', () => Navigator);
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'stretch',
|
||||
backgroundColor: '#ffffff',
|
||||
},
|
||||
listItem: {
|
||||
marginTop: 3,
|
||||
padding: 6,
|
||||
backgroundColor:'#ACACAC',
|
||||
alignSelf: 'stretch',
|
||||
flexDirection: 'row',
|
||||
flex:1,
|
||||
},
|
||||
textInput: {
|
||||
alignSelf: 'stretch',
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#0f0f0f',
|
||||
height: 200,
|
||||
fontSize: 13,
|
||||
margin: 6,
|
||||
marginTop: 70,
|
||||
padding: 4,
|
||||
},
|
||||
button: {
|
||||
height: 36,
|
||||
backgroundColor: '#48BBEC',
|
||||
alignSelf: 'stretch',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
buttonText: {
|
||||
alignSelf: 'center',
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
}
|
||||
});
|
||||
React.AppRegistry.registerComponent('ReactExample', () => TodoApp);
|
||||
|
|
Loading…
Reference in New Issue