Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CollectionChanges cleared notification #1128

Merged
merged 16 commits into from
Jan 30, 2023
Merged
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 @@ -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,
);
});
}

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