From ccd2301d9ef8f69f387c89ceaee6194b07181851 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 24 Aug 2015 09:22:37 -0700 Subject: [PATCH] todo example --- examples/ReactExample/index.ios.js | 228 ++++++++++++++++++++------- src/RJSArray.cpp | 21 ++- src/RJSObject.hpp | 3 + src/RJSObject.mm | 5 +- src/object-store/object_accessor.hpp | 6 +- tests/ArrayTests.js | 4 + 6 files changed, 199 insertions(+), 68 deletions(-) diff --git a/examples/ReactExample/index.ios.js b/examples/ReactExample/index.ios.js index 5c393c26..707f2246 100644 --- a/examples/ReactExample/index.ios.js +++ b/examples/ReactExample/index.ios.js @@ -9,90 +9,196 @@ var React = require('react-native'); var { AppRegistry, StyleSheet, + NavigatorIOS, + AlertIOS, ListView, + TouchableHighlight, Text, + TextInput, View, } = React; -var Person = function() {} -Person.prototype.schema = { - name: 'Person', +var TodoItemSchema = { + name: 'Todo', properties: [ - {name: 'name', type: RealmType.String}, - {name: 'age', type: RealmType.Double}, + {name: 'text', type: RealmType.String}, ] }; -Person.prototype.capitalName = function() { - return this.name.toUpperCase(); +var TodoListSchmea = { + name: 'TodoList', + properties: [ + {name: 'name', type: RealmType.String}, + {name: 'items', type: RealmType.Array, objectType: 'Todo'} + ] }; -var RealmReact = React.createClass({ - getInitialState: function() { - return { - dataSource: new ListView.DataSource({ - rowHasChanged: (row1, row2) => row1 !== row2, - }), - }; - }, - renderPerson: function(person) { - return ( - - {person.capitalName()} {person.age} - - ); - }, - render: function() { - return ( - - - - Press Cmd+R to reload,{'\n'} - Cmd+Control+Z for dev menu - - - ); - }, - componentDidMount: function() { - var realm = new Realm({schema: [Person]}); - var objects = realm.objects('Person'); - - console.log(realm.path); +console.log(Realm.defaultPath); +var realm = new Realm({schema: [TodoItemSchema, TodoListSchmea]}); - if (objects.length < 4) { - realm.write(function() { - realm.create('Person', ['Joe', 26]); - realm.create('Person', ['Sam', 20]); - realm.create('Person', ['Alexander', 37]); - realm.create('Person', ['Ari', 34]); - realm.create('Person', {'name': 'Bjarne', age: 37}); - }); +class Edit extends React.Component { + componentWillMount() { + this.setState({text: this.props.text}); } - var olderThan30 = realm.objects('Person', 'age > 30'); - console.log(olderThan30.length); + save() { + 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({ - dataSource: this.state.dataSource.cloneWithRows(olderThan30), - }); - }, -}); + render() { + return ( + + this.setState({text})} value={this.state.text}/> + + Save + + + ) + } +}; + +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 ( + + + this.menu(rowData, rowID)}> + + {rowData.text} + + + }/> + this.edit(this.list.items.length, "")}> + + + + + Press Cmd+R to reload,{'\n'} + Cmd+Control+Z for dev menu + + + ); + } +}; + +class Navigator extends React.Component { + render() { + return ( + + ); + } +}; +AppRegistry.registerComponent('ReactExample', () => Navigator); var styles = StyleSheet.create({ container: { flex: 1, justifyContent: '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: { textAlign: 'center', color: '#333333', marginBottom: 5, - }, - listView: { - paddingTop: 20, - backgroundColor: '#F5FCFF', - }, + } }); - -AppRegistry.registerComponent('ReactExample', () => RealmReact); diff --git a/src/RJSArray.cpp b/src/RJSArray.cpp index 69f97d39..38004fe9 100644 --- a/src/RJSArray.cpp +++ b/src/RJSArray.cpp @@ -18,6 +18,7 @@ #include "RJSArray.hpp" #include "RJSObject.hpp" +#include "RJSUtil.hpp" #include "object_accessor.hpp" 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(thisObject); + RJSValidateArgumentCount(argumentCount, 1); + array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast(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) { return RJSWrapObject(ctx, RJSArrayClass(), array); } JSClassRef RJSArrayClass() { - static JSClassRef s_objectClass = RJSCreateWrapperClass("Results", ArrayGetProperty, NULL, NULL, NULL, ArrayPropertyNames); + const JSStaticFunction arrayFuncs[] = { + {"push", ArrayPush}, + {NULL, NULL}, + }; + static JSClassRef s_objectClass = RJSCreateWrapperClass("RealmArray", ArrayGetProperty, NULL, arrayFuncs, NULL, ArrayPropertyNames); return s_objectClass; } diff --git a/src/RJSObject.hpp b/src/RJSObject.hpp index 807f22ca..6f32f248 100644 --- a/src/RJSObject.hpp +++ b/src/RJSObject.hpp @@ -18,10 +18,13 @@ #import "RJSUtil.hpp" #import "shared_realm.hpp" +#import "object_accessor.hpp" namespace realm { class Object; } +using RJSAccessor = realm::NativeAccessor; + JSClassRef RJSObjectClass(); JSObjectRef RJSObjectCreate(JSContextRef ctx, realm::Object object); diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 37284ff5..cb292c3c 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -26,7 +26,6 @@ #import "object_accessor.hpp" using namespace realm; -using RJSAccessor = NativeAccessor; JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) { Object *obj = RJSGetInternal(jsObject); @@ -164,13 +163,13 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) 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); if (JSValueIsObjectOfClass(ctx, val, RJSObjectClass())) { return RJSGetInternal(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)) { object = RJSDictForPropertyArray(ctx, object_schema, object); } diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index fdc33462..c7f92022 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -43,7 +43,7 @@ namespace realm { // convert value to persisted object // for existing objects return the existing 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 static size_t array_size(ContextType ctx, ValueType &val); @@ -125,7 +125,7 @@ namespace realm { row.nullify_link(column); } 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; } @@ -135,7 +135,7 @@ namespace realm { size_t count = Accessor::array_size(ctx, value); for (size_t i = 0; i < count; 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; } diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 2c4387af..6deda1a3 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -104,4 +104,8 @@ var ArrayTests = { } TestCase.assertEqual(2, count); }, + + testPush: function() { + + } };