2016-02-18 19:59:34 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Copyright 2016 Realm Inc.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
2015-10-27 23:19:30 +00:00
|
|
|
|
|
2015-10-07 23:20:05 +00:00
|
|
|
|
'use strict';
|
|
|
|
|
|
2016-05-16 20:21:28 +00:00
|
|
|
|
import React from 'react';
|
|
|
|
|
|
|
|
|
|
import {
|
2016-01-14 01:05:52 +00:00
|
|
|
|
Navigator,
|
2016-05-16 20:21:28 +00:00
|
|
|
|
Platform,
|
|
|
|
|
StatusBar,
|
2016-01-14 01:05:52 +00:00
|
|
|
|
Text,
|
|
|
|
|
TouchableOpacity,
|
2016-01-19 23:10:06 +00:00
|
|
|
|
View,
|
2016-02-15 23:03:16 +00:00
|
|
|
|
} from 'react-native';
|
|
|
|
|
|
|
|
|
|
import TodoItem from './todo-item';
|
|
|
|
|
import TodoListView from './todo-listview';
|
|
|
|
|
import realm from './realm';
|
|
|
|
|
import styles from './styles';
|
2015-10-07 23:20:05 +00:00
|
|
|
|
|
2016-05-27 18:30:17 +00:00
|
|
|
|
export default class TodoApp extends React.Component {
|
2015-10-27 08:52:26 +00:00
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
2015-10-07 23:20:05 +00:00
|
|
|
|
|
2016-10-04 22:02:51 +00:00
|
|
|
|
// This is a Results object, which will live-update.
|
|
|
|
|
this.todoLists = realm.objects('TodoList').sorted('creationDate');
|
|
|
|
|
if (this.todoLists.length < 1) {
|
2015-10-07 23:20:05 +00:00
|
|
|
|
realm.write(() => {
|
2016-10-04 22:02:51 +00:00
|
|
|
|
realm.create('TodoList', {name: 'Todo List', creationDate: new Date()});
|
2015-10-07 23:20:05 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
2016-10-04 22:02:51 +00:00
|
|
|
|
this.todoLists.addListener((name, changes) => {
|
|
|
|
|
console.log("changed: " + JSON.stringify(changes));
|
|
|
|
|
});
|
|
|
|
|
console.log("registered listener");
|
2015-10-07 23:20:05 +00:00
|
|
|
|
|
2016-01-14 01:05:52 +00:00
|
|
|
|
|
|
|
|
|
// Bind all the methods that we will be passing as props.
|
|
|
|
|
this.renderScene = this.renderScene.bind(this);
|
|
|
|
|
this._addNewTodoList = this._addNewTodoList.bind(this);
|
|
|
|
|
this._onPressTodoList = this._onPressTodoList.bind(this);
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
this.state = {};
|
2015-10-07 23:20:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
get currentListView() {
|
|
|
|
|
let refs = this.refs.nav.refs;
|
|
|
|
|
return refs.listItemView || refs.listView;
|
|
|
|
|
}
|
2015-10-07 23:20:05 +00:00
|
|
|
|
|
2016-01-19 23:10:06 +00:00
|
|
|
|
componentWillMount() {
|
2016-05-16 20:21:28 +00:00
|
|
|
|
if (Platform.OS == 'ios') {
|
|
|
|
|
StatusBar.setBarStyle('light-content');
|
2016-01-19 23:10:06 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
render() {
|
2016-02-18 05:23:43 +00:00
|
|
|
|
let objects = realm.objects('Todo');
|
2015-10-27 10:08:18 +00:00
|
|
|
|
let extraItems = [
|
2016-02-18 05:23:43 +00:00
|
|
|
|
{name: 'Complete', items: objects.filtered('done = true')},
|
2016-02-18 05:34:41 +00:00
|
|
|
|
{name: 'Incomplete', items: objects.filtered('done = false')},
|
2015-10-27 10:08:18 +00:00
|
|
|
|
];
|
|
|
|
|
|
2015-10-07 23:20:05 +00:00
|
|
|
|
let route = {
|
2015-10-27 08:52:26 +00:00
|
|
|
|
title: 'My Todo Lists',
|
|
|
|
|
component: TodoListView,
|
2015-10-07 23:20:05 +00:00
|
|
|
|
passProps: {
|
2015-10-27 08:52:26 +00:00
|
|
|
|
ref: 'listView',
|
2015-10-27 10:08:18 +00:00
|
|
|
|
extraItems: extraItems,
|
2016-01-14 01:05:52 +00:00
|
|
|
|
onPressItem: this._onPressTodoList,
|
2015-10-07 23:20:05 +00:00
|
|
|
|
},
|
2015-10-27 10:08:18 +00:00
|
|
|
|
backButtonTitle: 'Lists',
|
2015-10-07 23:20:05 +00:00
|
|
|
|
rightButtonTitle: 'Add',
|
2016-01-14 01:05:52 +00:00
|
|
|
|
onRightButtonPress: this._addNewTodoList,
|
2015-10-07 23:20:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-01-14 01:05:52 +00:00
|
|
|
|
let navigationBar = (
|
|
|
|
|
<Navigator.NavigationBar routeMapper={RouteMapper} style={styles.navBar} />
|
|
|
|
|
);
|
|
|
|
|
|
2015-10-07 23:20:05 +00:00
|
|
|
|
return (
|
2016-01-14 01:05:52 +00:00
|
|
|
|
<Navigator
|
|
|
|
|
ref="nav"
|
|
|
|
|
initialRoute={route}
|
|
|
|
|
navigationBar={navigationBar}
|
|
|
|
|
renderScene={this.renderScene}
|
|
|
|
|
sceneStyle={styles.navScene}
|
|
|
|
|
style={styles.navigator}
|
|
|
|
|
/>
|
2015-10-07 23:20:05 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-14 01:05:52 +00:00
|
|
|
|
renderScene(route) {
|
2016-10-04 22:02:51 +00:00
|
|
|
|
console.log(this.todoLists);
|
|
|
|
|
return <route.component items={this.todoLists} {...route.passProps} />
|
2016-01-14 01:05:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
_addNewTodoItem(list) {
|
2015-10-28 18:23:37 +00:00
|
|
|
|
let items = list.items;
|
|
|
|
|
if (!this._shouldAddNewItem(items)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-07 23:20:05 +00:00
|
|
|
|
realm.write(() => {
|
2015-10-28 18:23:37 +00:00
|
|
|
|
items.push({text: ''});
|
2015-10-07 23:20:05 +00:00
|
|
|
|
});
|
|
|
|
|
|
2015-10-28 18:23:37 +00:00
|
|
|
|
this._setEditingRow(items.length - 1);
|
2015-10-27 08:52:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_addNewTodoList() {
|
2015-10-28 18:23:37 +00:00
|
|
|
|
let items = this.todoLists;
|
|
|
|
|
if (!this._shouldAddNewItem(items)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
realm.write(() => {
|
2016-10-04 22:02:51 +00:00
|
|
|
|
realm.create('TodoList', {name: '', creationDate: new Date()});
|
2015-10-27 08:52:26 +00:00
|
|
|
|
});
|
|
|
|
|
|
2015-10-28 18:23:37 +00:00
|
|
|
|
this._setEditingRow(items.length - 1);
|
2015-10-27 08:52:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_onPressTodoList(list) {
|
2015-10-27 10:08:18 +00:00
|
|
|
|
let items = list.items;
|
|
|
|
|
|
|
|
|
|
let route = {
|
2015-10-27 08:52:26 +00:00
|
|
|
|
title: list.name,
|
|
|
|
|
component: TodoListView,
|
|
|
|
|
passProps: {
|
|
|
|
|
ref: 'listItemView',
|
2015-10-27 10:08:18 +00:00
|
|
|
|
items: items,
|
2015-10-27 08:52:26 +00:00
|
|
|
|
rowClass: TodoItem,
|
|
|
|
|
},
|
2015-10-27 10:08:18 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Check if the items are mutable (i.e. List rather than Results).
|
|
|
|
|
if (items.push) {
|
|
|
|
|
Object.assign(route, {
|
|
|
|
|
rightButtonTitle: 'Add',
|
|
|
|
|
onRightButtonPress: () => this._addNewTodoItem(list),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.refs.nav.push(route);
|
2015-10-27 08:52:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-28 18:23:37 +00:00
|
|
|
|
_shouldAddNewItem(items) {
|
|
|
|
|
let editingRow = this.currentListView.state.editingRow;
|
|
|
|
|
let editingItem = editingRow != null && items[editingRow];
|
|
|
|
|
|
|
|
|
|
// Don't allow adding a new item if the one being edited is empty.
|
|
|
|
|
return !editingItem || !!editingItem.text || !!editingItem.name;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
_setEditingRow(rowIndex) {
|
2016-01-12 00:01:37 +00:00
|
|
|
|
let listView = this.currentListView;
|
|
|
|
|
|
2015-10-27 08:52:26 +00:00
|
|
|
|
// Update the state on the currently displayed TodoList to edit this new item.
|
2016-01-12 00:01:37 +00:00
|
|
|
|
listView.setState({editingRow: rowIndex});
|
|
|
|
|
listView.updateDataSource();
|
2015-10-07 23:20:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-14 01:05:52 +00:00
|
|
|
|
const RouteMapper = {
|
|
|
|
|
LeftButton(route, navigator, index, navState) {
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let prevRoute = navState.routeStack[index - 1];
|
|
|
|
|
return (
|
2016-01-19 23:10:06 +00:00
|
|
|
|
<TouchableOpacity onPress={() => navigator.pop()}>
|
|
|
|
|
<View style={[styles.navBarView, styles.navBarLeftButton]}>
|
2016-01-14 01:05:52 +00:00
|
|
|
|
<Text style={styles.navBarLeftArrow}>‹</Text>
|
2016-01-19 23:10:06 +00:00
|
|
|
|
<Text style={styles.navBarText}>
|
|
|
|
|
{prevRoute.backButtonTitle || prevRoute.title || 'Back'}
|
|
|
|
|
</Text>
|
|
|
|
|
</View>
|
2016-01-14 01:05:52 +00:00
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
RightButton(route) {
|
|
|
|
|
if (!route.rightButtonTitle) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2016-01-19 23:10:06 +00:00
|
|
|
|
<TouchableOpacity onPress={route.onRightButtonPress}>
|
|
|
|
|
<View style={[styles.navBarView, styles.navBarRightButton]}>
|
|
|
|
|
<Text style={styles.navBarText}>
|
|
|
|
|
{route.rightButtonTitle}
|
|
|
|
|
</Text>
|
|
|
|
|
</View>
|
2016-01-14 01:05:52 +00:00
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
Title(route) {
|
|
|
|
|
return (
|
2016-01-19 23:10:06 +00:00
|
|
|
|
<View style={styles.navBarView}>
|
|
|
|
|
<Text style={[styles.navBarText, styles.navBarTitleText]}>
|
|
|
|
|
{route.title}
|
|
|
|
|
</Text>
|
|
|
|
|
</View>
|
2016-01-14 01:05:52 +00:00
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
};
|