todo example

This commit is contained in:
Ari Lazier 2015-08-24 09:22:37 -07:00
parent 95189a3a37
commit ccd2301d9e
6 changed files with 199 additions and 68 deletions

View File

@ -9,90 +9,196 @@ var React = require('react-native');
var { var {
AppRegistry, AppRegistry,
StyleSheet, StyleSheet,
NavigatorIOS,
AlertIOS,
ListView, ListView,
TouchableHighlight,
Text, Text,
TextInput,
View, View,
} = React; } = React;
var Person = function() {} var TodoItemSchema = {
Person.prototype.schema = { name: 'Todo',
name: 'Person',
properties: [ properties: [
{name: 'name', type: RealmType.String}, {name: 'text', type: RealmType.String},
{name: 'age', type: RealmType.Double},
] ]
}; };
Person.prototype.capitalName = function() { var TodoListSchmea = {
return this.name.toUpperCase(); name: 'TodoList',
properties: [
{name: 'name', type: RealmType.String},
{name: 'items', type: RealmType.Array, objectType: 'Todo'}
]
}; };
var RealmReact = React.createClass({ console.log(Realm.defaultPath);
getInitialState: function() { var realm = new Realm({schema: [TodoItemSchema, TodoListSchmea]});
return {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
};
},
renderPerson: function(person) {
return (
<View style={styles.container}>
<Text>{person.capitalName()} {person.age}</Text>
</View>
);
},
render: function() {
return (
<View style={styles.container}>
<ListView dataSource={this.state.dataSource} renderRow={this.renderPerson} style={styles.listView}/>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+Control+Z for dev menu
</Text>
</View>
);
},
componentDidMount: function() {
var realm = new Realm({schema: [Person]});
var objects = realm.objects('Person');
console.log(realm.path);
if (objects.length < 4) { class Edit extends React.Component {
realm.write(function() { componentWillMount() {
realm.create('Person', ['Joe', 26]); this.setState({text: this.props.text});
realm.create('Person', ['Sam', 20]);
realm.create('Person', ['Alexander', 37]);
realm.create('Person', ['Ari', 34]);
realm.create('Person', {'name': 'Bjarne', age: 37});
});
} }
var olderThan30 = realm.objects('Person', 'age > 30'); save() {
console.log(olderThan30.length); var list = this.props.list;
var id = this.props.todoId;
var text = this.state.text;
realm.write(function () {
if (id == list.items.length) {
list.items.push({text: text});
}
else {
var todoItem = list.items[id];
todoItem.text = text;
}
});
// should not be needed once we have notifications
this.props.parent.updateDataSource();
this.props.navigator.pop();
}
this.setState({ render() {
dataSource: this.state.dataSource.cloneWithRows(olderThan30), 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() {
this.list = realm.create('TodoList', ['List', []]);
});
}
else {
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({ var styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
backgroundColor: '#F5FCFF', backgroundColor: '#ffffff',
},
listItem: {
marginTop: 3,
padding: 2,
backgroundColor:'#ABABAB',
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: { instructions: {
textAlign: 'center', textAlign: 'center',
color: '#333333', color: '#333333',
marginBottom: 5, marginBottom: 5,
}, }
listView: {
paddingTop: 20,
backgroundColor: '#F5FCFF',
},
}); });
AppRegistry.registerComponent('ReactExample', () => RealmReact);

View File

@ -18,6 +18,7 @@
#include "RJSArray.hpp" #include "RJSArray.hpp"
#include "RJSObject.hpp" #include "RJSObject.hpp"
#include "RJSUtil.hpp"
#include "object_accessor.hpp" #include "object_accessor.hpp"
using namespace realm; using namespace realm;
@ -79,11 +80,29 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu
} }
} }
JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
ObjectArray *array = RJSGetInternal<ObjectArray *>(thisObject);
RJSValidateArgumentCount(argumentCount, 1);
array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[0]), array->object_schema.name, false));
}
catch (std::exception &exp) {
if (jsException) {
*jsException = RJSMakeError(ctx, exp);
}
}
return NULL;
}
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) { JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
return RJSWrapObject<ObjectArray *>(ctx, RJSArrayClass(), array); return RJSWrapObject<ObjectArray *>(ctx, RJSArrayClass(), array);
} }
JSClassRef RJSArrayClass() { JSClassRef RJSArrayClass() {
static JSClassRef s_objectClass = RJSCreateWrapperClass<Object>("Results", ArrayGetProperty, NULL, NULL, NULL, ArrayPropertyNames); const JSStaticFunction arrayFuncs[] = {
{"push", ArrayPush},
{NULL, NULL},
};
static JSClassRef s_objectClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, NULL, arrayFuncs, NULL, ArrayPropertyNames);
return s_objectClass; return s_objectClass;
} }

View File

@ -18,10 +18,13 @@
#import "RJSUtil.hpp" #import "RJSUtil.hpp"
#import "shared_realm.hpp" #import "shared_realm.hpp"
#import "object_accessor.hpp"
namespace realm { namespace realm {
class Object; class Object;
} }
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
JSClassRef RJSObjectClass(); JSClassRef RJSObjectClass();
JSObjectRef RJSObjectCreate(JSContextRef ctx, realm::Object object); JSObjectRef RJSObjectCreate(JSContextRef ctx, realm::Object object);

View File

@ -26,7 +26,6 @@
#import "object_accessor.hpp" #import "object_accessor.hpp"
using namespace realm; using namespace realm;
using RJSAccessor = NativeAccessor<JSValueRef, JSContextRef>;
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) { JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) {
Object *obj = RJSGetInternal<Object *>(jsObject); Object *obj = RJSGetInternal<Object *>(jsObject);
@ -164,13 +163,13 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val)
extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array); extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array);
template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &realm, JSValueRef &val, Property &prop, bool try_update) { template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &realm, JSValueRef &val, std::string &type, bool try_update) {
JSObjectRef object = RJSValidatedValueToObject(ctx, val); JSObjectRef object = RJSValidatedValueToObject(ctx, val);
if (JSValueIsObjectOfClass(ctx, val, RJSObjectClass())) { if (JSValueIsObjectOfClass(ctx, val, RJSObjectClass())) {
return RJSGetInternal<Object *>(object)->row.get_index(); return RJSGetInternal<Object *>(object)->row.get_index();
} }
ObjectSchema &object_schema = realm->config().schema->at(prop.object_type); ObjectSchema &object_schema = realm->config().schema->at(type);
if (RJSIsValueArray(ctx, object)) { if (RJSIsValueArray(ctx, object)) {
object = RJSDictForPropertyArray(ctx, object_schema, object); object = RJSDictForPropertyArray(ctx, object_schema, object);
} }

View File

@ -43,7 +43,7 @@ namespace realm {
// convert value to persisted object // convert value to persisted object
// for existing objects return the existing row index // for existing objects return the existing row index
// for new/updated objects return the row index // for new/updated objects return the row index
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, Property &prop, bool try_update); static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);
// array value acessors // array value acessors
static size_t array_size(ContextType ctx, ValueType &val); static size_t array_size(ContextType ctx, ValueType &val);
@ -125,7 +125,7 @@ namespace realm {
row.nullify_link(column); row.nullify_link(column);
} }
else { else {
row.set_link(column, Accessor::to_object_index(ctx, realm, value, property, try_update)); row.set_link(column, Accessor::to_object_index(ctx, realm, value, property.object_type, try_update));
} }
break; break;
} }
@ -135,7 +135,7 @@ namespace realm {
size_t count = Accessor::array_size(ctx, value); size_t count = Accessor::array_size(ctx, value);
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
ValueType element = Accessor::array_value_at_index(ctx, value, i); ValueType element = Accessor::array_value_at_index(ctx, value, i);
link_view->add(Accessor::to_object_index(ctx, realm, element, property, try_update)); link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update));
} }
break; break;
} }

View File

@ -104,4 +104,8 @@ var ArrayTests = {
} }
TestCase.assertEqual(2, count); TestCase.assertEqual(2, count);
}, },
testPush: function() {
}
}; };