diff --git a/CHANGELOG.md b/CHANGELOG.md index 7796d3819..55cfc968e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) @@ -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)) diff --git a/lib/src/collections.dart b/lib/src/collections.dart index b511cdabc..0226605c6 100644 --- a/lib/src/collections.dart +++ b/lib/src/collections.dart @@ -43,8 +43,9 @@ class CollectionChanges { final List modifications; final List modificationsAfter; final List 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. @@ -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 get newModified => _changes.modificationsAfter; + + /// `true` if the collection was cleared. + bool get isCleared => _changes.isCleared; } extension RealmCollectionChangesInternal on RealmCollectionChanges { diff --git a/lib/src/native/realm_core.dart b/lib/src/native/realm_core.dart index efd8b3691..6dfa8ab97 100644 --- a/lib/src/native/realm_core.dart +++ b/lib/src/native/realm_core.dart @@ -1104,8 +1104,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, + ); }); } diff --git a/test/embedded_test.dart b/test/embedded_test.dart index 9db939c41..9c3bb2eaa 100644 --- a/test/embedded_test.dart +++ b/test/embedded_test.dart @@ -706,6 +706,13 @@ Future main([List? 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(); }); diff --git a/test/list_test.dart b/test/list_test.dart index f86c15e3f..269e90197 100644 --- a/test/list_test.dart +++ b/test/list_test.dart @@ -1176,4 +1176,19 @@ Future main([List? 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([ + isA>().having((changes) => changes.inserted, 'inserted', []), // always an empty event on subscription + isA>().having((changes) => changes.isCleared, 'isCleared', true), + ])); + realm.write(() => team.players.clear()); + }); } diff --git a/test/realm_set_test.dart b/test/realm_set_test.dart index 2860867d2..61565e26f 100644 --- a/test/realm_set_test.dart +++ b/test/realm_set_test.dart @@ -523,6 +523,28 @@ Future main([List? args]) async { await Future.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([ + isA>().having((changes) => changes.inserted, 'inserted', []), // always an empty event on subscription + isA>().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); @@ -580,7 +602,7 @@ Future main([List? args]) async { expect(realm.all().length, 0); }); - test('UnmanagedRealmSet deleteMany', () { + test('UnmanagedRealmSet deleteMany', () { var config = Configuration.local([TestRealmSets.schema, Car.schema]); var realm = getRealm(config); @@ -603,7 +625,6 @@ Future main([List? args]) async { expect(cars.length, 0); }); - test('RealmSet add a set of already managed objects', () { var config = Configuration.local([TestRealmSets.schema, Car.schema]); var realm = getRealm(config);