Merge pull request #1849 from realm/tg/new-modifications
Expose both newModifications and oldModifications on change events
This commit is contained in:
commit
d8e41fa469
|
@ -10,7 +10,7 @@ X.Y.Z Release notes
|
||||||
* None.
|
* None.
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
* None.
|
* Add the `oldModifications` and `newModifications` properties to the listener change objects, which report the indices that changed in the collection both before and after the changes being notified for. The `modifications` property is kept as an alias for `oldModifications` but might be removed in a future version.
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
* [Sync] Fixed a bug which crash query-based Realms. A bug in gcc's optimizer will generate code which in some case will lead to a memory violation and eventually a segmentation fault.
|
* [Sync] Fixed a bug which crash query-based Realms. A bug in gcc's optimizer will generate code which in some case will lead to a memory violation and eventually a segmentation fault.
|
||||||
|
|
|
@ -427,22 +427,19 @@ class Collection {
|
||||||
* @param {function(collection, changes)} callback - A function to be called when changes occur.
|
* @param {function(collection, changes)} callback - A function to be called when changes occur.
|
||||||
* The callback function is called with two arguments:
|
* The callback function is called with two arguments:
|
||||||
* - `collection`: the collection instance that changed,
|
* - `collection`: the collection instance that changed,
|
||||||
* - `changes`: a dictionary with keys `insertions`, `modifications` and `deletions`,
|
* - `changes`: a dictionary with keys `insertions`, `newModifications`, `oldModifications`
|
||||||
* each containing a list of indices that were inserted, updated or deleted respectively. If
|
* and `deletions`, each containing a list of indices in the collection that were
|
||||||
* partial sync is enabled, an additional key `partial_sync` is added.
|
* inserted, updated or deleted respectively. `deletions` and `oldModifications` are
|
||||||
* - `changes.partial_sync`: `error` indicates if an error has occurred, `old_state` is the previous
|
* indices into the collection before the change happened, while `insertions` and
|
||||||
* state, and `new_state` is the current state.
|
* `newModifications` are indices into the new version of the collection.
|
||||||
* @throws {Error} If `callback` is not a function.
|
* @throws {Error} If `callback` is not a function.
|
||||||
* @example
|
* @example
|
||||||
* wines.addListener((collection, changes) => {
|
* wines.addListener((collection, changes) => {
|
||||||
* // collection === wines
|
* // collection === wines
|
||||||
* if (changes.partial_sync.new_state == Realm.Sync.SubscriptionState.Initialized) {
|
|
||||||
* console.log('Our subset is ready');
|
|
||||||
* console.log(`${changes.insertions.length} insertions`);
|
* console.log(`${changes.insertions.length} insertions`);
|
||||||
* console.log(`${changes.modifications.length} modifications`);
|
* console.log(`${changes.modifications.length} modifications`);
|
||||||
* console.log(`${changes.deletions.length} deletions`);
|
* console.log(`${changes.deletions.length} deletions`);
|
||||||
* console.log(`new size of collection: ${collection.length}`);
|
* console.log(`new size of collection: ${collection.length}`);
|
||||||
* }
|
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
addListener(callback) {}
|
addListener(callback) {}
|
||||||
|
|
|
@ -140,6 +140,8 @@ declare namespace Realm {
|
||||||
insertions: number[];
|
insertions: number[];
|
||||||
deletions: number[];
|
deletions: number[];
|
||||||
modifications: number[];
|
modifications: number[];
|
||||||
|
newModifications: number[];
|
||||||
|
oldModifications: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type CollectionChangeCallback<T> = (collection: Collection<T>, change: CollectionChangeSet) => void;
|
type CollectionChangeCallback<T> = (collection: Collection<T>, change: CollectionChangeSet) => void;
|
||||||
|
|
|
@ -50,27 +50,28 @@ template<typename T>
|
||||||
typename T::Value CollectionClass<T>::create_collection_change_set(ContextType ctx, const CollectionChangeSet &change_set)
|
typename T::Value CollectionClass<T>::create_collection_change_set(ContextType ctx, const CollectionChangeSet &change_set)
|
||||||
{
|
{
|
||||||
ObjectType object = Object::create_empty(ctx);
|
ObjectType object = Object::create_empty(ctx);
|
||||||
std::vector<ValueType> deletions, insertions, modifications;
|
std::vector<ValueType> scratch;
|
||||||
|
auto make_array = [&](realm::IndexSet const& index_set) {
|
||||||
|
scratch.clear();
|
||||||
|
scratch.reserve(index_set.count());
|
||||||
|
for (auto index : index_set.as_indexes()) {
|
||||||
|
scratch.push_back(Value::from_number(ctx, index));
|
||||||
|
}
|
||||||
|
return Object::create_array(ctx, scratch);
|
||||||
|
};
|
||||||
|
|
||||||
if (change_set.deletions.count() == std::numeric_limits<size_t>::max()) {
|
if (change_set.deletions.count() == std::numeric_limits<size_t>::max()) {
|
||||||
deletions.push_back(Value::from_null(ctx));
|
Object::set_property(ctx, object, "deletions", Object::create_array(ctx, {Value::from_null(ctx)}));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (auto index : change_set.deletions.as_indexes()) {
|
Object::set_property(ctx, object, "deletions", make_array(change_set.deletions));
|
||||||
deletions.push_back(Value::from_number(ctx, index));
|
|
||||||
}
|
}
|
||||||
}
|
Object::set_property(ctx, object, "insertions", make_array(change_set.insertions));
|
||||||
Object::set_property(ctx, object, "deletions", Object::create_array(ctx, deletions));
|
Object::set_property(ctx, object, "newModifications", make_array(change_set.modifications_new));
|
||||||
|
|
||||||
for (auto index : change_set.insertions.as_indexes()) {
|
auto old_modifications = make_array(change_set.modifications);
|
||||||
insertions.push_back(Value::from_number(ctx, index));
|
Object::set_property(ctx, object, "modifications", old_modifications);
|
||||||
}
|
Object::set_property(ctx, object, "oldModifications", old_modifications);
|
||||||
Object::set_property(ctx, object, "insertions", Object::create_array(ctx, insertions));
|
|
||||||
|
|
||||||
for (auto index : change_set.modifications.as_indexes()) {
|
|
||||||
modifications.push_back(Value::from_number(ctx, index));
|
|
||||||
}
|
|
||||||
Object::set_property(ctx, object, "modifications", Object::create_array(ctx, modifications));
|
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
|
@ -452,10 +452,16 @@ module.exports = {
|
||||||
if (first) {
|
if (first) {
|
||||||
TestCase.assertEqual(testObjects.length, 3);
|
TestCase.assertEqual(testObjects.length, 3);
|
||||||
TestCase.assertEqual(changes.insertions.length, 0);
|
TestCase.assertEqual(changes.insertions.length, 0);
|
||||||
|
TestCase.assertEqual(changes.modifications.length, 0);
|
||||||
|
TestCase.assertEqual(changes.newModifications.length, 0);
|
||||||
|
TestCase.assertEqual(changes.oldModifications.length, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TestCase.assertEqual(testObjects.length, 4);
|
TestCase.assertEqual(testObjects.length, 4);
|
||||||
TestCase.assertEqual(changes.insertions.length, 1);
|
TestCase.assertEqual(changes.insertions.length, 1);
|
||||||
|
TestCase.assertEqual(changes.modifications.length, 1);
|
||||||
|
TestCase.assertEqual(changes.newModifications.length, 1);
|
||||||
|
TestCase.assertEqual(changes.oldModifications.length, 1);
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
resolve();
|
resolve();
|
||||||
|
@ -464,6 +470,7 @@ module.exports = {
|
||||||
return new Promise((r, _reject) => {
|
return new Promise((r, _reject) => {
|
||||||
resolve = r;
|
resolve = r;
|
||||||
realm.write(() => {
|
realm.write(() => {
|
||||||
|
realm.objects('TestObject')[0].doubleCol = 5;
|
||||||
realm.create('TestObject', { doubleCol: 1 });
|
realm.create('TestObject', { doubleCol: 1 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue