Skip to content

Commit

Permalink
CollectionChanges cleared notification (#1128)
Browse files Browse the repository at this point in the history
* Update realm-core to v13.3.0

* Ran ffigen to update realm_bindings.dart

* Remove realmSetAssign

Not used, and realm_set_assign no longer exposed in C-api.
Apparently it was never implemented.

* Handle new RLM_SYNC_SESSION_STATE_PAUSED

* Update CHANGELOG

* Collection cleared notification

* Test RealmList cleared

* RealmSet.cleared notification

* Modify embedded objects list notification test

* Update Changelog

* Code review changes

* rename cleared to isCleared

* fix test names

* fix bad code

---------

Co-authored-by: Kasper Overgård Nielsen <kasper@byolimit.com>
Co-authored-by: blagoev <lubo@blagoev.com>
  • Loading branch information
3 people authored Jan 30, 2023
1 parent 743a106 commit 43f3354
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 6 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Enhancements
* Add `App.reconnect()` providing a hint to Realm to reconnect all sync sessions.
* Add `Realm.refresh()` and `Realm.refreshAsync()` support. ([#1046](https://github.com/realm/realm-dart/pull/1046))
* Support change notifications property `isCleared` on list collections and sets. ([#1128](https://github.com/realm/realm-dart/pull/1128))

### Fixed
* `SyncSession.pause()` allow users to suspend a Realm's sync session until it is explicitly resumed with `SyncSession.resume()`. Previously it could be implicitly resumed in rare cases. (Core upgrade)
Expand Down Expand Up @@ -34,7 +35,6 @@
* Add support for Realm set data type. ([#1102](https://github.com/realm/realm-dart/pull/1102))
* Exposed realm `writeCopy` API to copy a Realm file and optionally encrypt it with a different key. ([#1103](https://github.com/realm/realm-dart/pull/1103))


### Fixed
* Added an error for default values for Realm object references in the Realm generator. ([#1102](https://github.com/realm/realm-dart/pull/1102))
* `realm.deleteMany()` will handle efficiently ManagedRealmList instances. ([#1117](https://github.com/realm/realm-dart/pull/1171))
Expand Down
6 changes: 5 additions & 1 deletion lib/src/collections.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ class CollectionChanges {
final List<int> modifications;
final List<int> modificationsAfter;
final List<Move> moves;
final bool isCleared;

const CollectionChanges(this.deletions, this.insertions, this.modifications, this.modificationsAfter, this.moves);
const CollectionChanges(this.deletions, this.insertions, this.modifications, this.modificationsAfter, this.moves, this.isCleared);
}

/// Describes the changes in a Realm collection since the last time the notification callback was invoked.
Expand All @@ -71,6 +72,9 @@ class RealmCollectionChanges implements Finalizable {
/// The indexes in the new version of the collection which were modified. Conceptually, it contains the same entries as [modified] but after the
/// insertions and deletions have been accounted for.
List<int> get newModified => _changes.modificationsAfter;

/// `true` if the collection was cleared.
bool get isCleared => _changes.isCleared;
}

extension RealmCollectionChangesInternal on RealmCollectionChanges {
Expand Down
10 changes: 8 additions & 2 deletions lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1120,8 +1120,14 @@ class _RealmCore {
moves[i] = Move(movePtr.ref.from, movePtr.ref.to);
}

return CollectionChanges(out_deletion_indexes.toIntList(deletionsCount), out_insertion_indexes.toIntList(insertionCount),
out_modification_indexes.toIntList(modificationCount), out_modification_indexes_after.toIntList(modificationCount), moves);
return CollectionChanges(
out_deletion_indexes.toIntList(deletionsCount),
out_insertion_indexes.toIntList(insertionCount),
out_modification_indexes.toIntList(modificationCount),
out_modification_indexes_after.toIntList(modificationCount),
moves,
out_collection_cleared.value,
);
});
}

Expand Down
7 changes: 7 additions & 0 deletions test/embedded_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,13 @@ Future<void> main([List<String>? args]) async {
event = await waitForNotification(notifications);
expect(event.deleted, [0]);

realm.write(() {
parent.recursiveList.clear();
});

event = await waitForNotification(notifications);
expect(event.isCleared, true);

await subscription.cancel();
});

Expand Down
15 changes: 15 additions & 0 deletions test/list_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1176,4 +1176,19 @@ Future<void> main([List<String>? args]) async {
realm.write(() => team.players.move(2, 3));
expect(team.players, [bob, alice, dan, carol]);
});

test('RealmList.isCleared notifications', () async {
final config = Configuration.local([Team.schema, Person.schema]);
final realm = getRealm(config);
final team = Team('Team 1', players: [Person('Alice'), Person('Bob')]);
realm.write(() => realm.add(team));

expectLater(
team.players.changes,
emitsInOrder(<Matcher>[
isA<RealmListChanges<Person>>().having((changes) => changes.inserted, 'inserted', <int>[]), // always an empty event on subscription
isA<RealmListChanges<Person>>().having((changes) => changes.isCleared, 'isCleared', true),
]));
realm.write(() => team.players.clear());
});
}
25 changes: 23 additions & 2 deletions test/realm_set_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,28 @@ Future<void> main([List<String>? args]) async {
await Future<void>.delayed(Duration(milliseconds: 20));
});

test('RealmSet<$type>.isCleared notifications', () async {
var config = Configuration.local([TestRealmSets.schema, Car.schema]);
var realm = getRealm(config);

var testSet = TestRealmSets(1);
realm.write(() => realm.add(testSet));

var set = testSet.setByType(type).set;
var values = testSet.setByType(type).values;
realm.write(() {
set.add(values.first);
});

expectLater(
set.changes,
emitsInOrder(<Matcher>[
isA<RealmSetChanges<Object?>>().having((changes) => changes.inserted, 'inserted', <int>[]), // always an empty event on subscription
isA<RealmSetChanges<Object?>>().having((changes) => changes.isCleared, 'isCleared', true),
]));
realm.write(() => set.clear());
});

test('RealmSet<$type> basic operations on unmanaged sets', () {
var config = Configuration.local([TestRealmSets.schema, Car.schema]);
var realm = getRealm(config);
Expand Down Expand Up @@ -580,7 +602,7 @@ Future<void> main([List<String>? args]) async {
expect(realm.all<Car>().length, 0);
});

test('UnmanagedRealmSet<RealmObject> deleteMany', () {
test('UnmanagedRealmSet<RealmObject> deleteMany', () {
var config = Configuration.local([TestRealmSets.schema, Car.schema]);
var realm = getRealm(config);

Expand All @@ -603,7 +625,6 @@ Future<void> main([List<String>? args]) async {
expect(cars.length, 0);
});


test('RealmSet<RealmObject> add a set of already managed objects', () {
var config = Configuration.local([TestRealmSets.schema, Car.schema]);
var realm = getRealm(config);
Expand Down

0 comments on commit 43f3354

Please sign in to comment.