Integrate internal changes
* Remove unnecessary type cast
* Fix ObservableMap to notify on all mutations (issue #91)
PiperOrigin-RevId: 413202846
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4ec2494..f1c8c44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## 0.24.0-dev
* Migrate to [null safety](https://dart.dev/null-safety).
+* Update ObservableMap to notify observers about changes for all methods.
## 0.23.0
diff --git a/lib/src/observable_list.dart b/lib/src/observable_list.dart
index c25534f..85c34ef 100644
--- a/lib/src/observable_list.dart
+++ b/lib/src/observable_list.dart
@@ -244,7 +244,6 @@
// We are modifying the length just below these checks. Without the checks
// Array.copy could throw an exception, leaving the list in a bad state
// (with a length that has been increased, but without a new element).
- if (index is! int) throw ArgumentError(index);
RangeError.checkValidIndex(index, this);
_list
// Increase the length by adding [element], in case [E] isn't nullable.
diff --git a/lib/src/observable_map.dart b/lib/src/observable_map.dart
index ec256f7..05f2a4f 100644
--- a/lib/src/observable_map.dart
+++ b/lib/src/observable_map.dart
@@ -190,7 +190,9 @@
@override
void addEntries(Iterable<MapEntry<K, V>> entries) {
- _map.addEntries(entries);
+ for (var entry in entries) {
+ this[entry.key] = entry.value;
+ }
}
@override
@@ -200,15 +202,21 @@
@override
V update(K key, V Function(V value) update, {V Function()? ifAbsent}) {
- return _map.update(key, update, ifAbsent: ifAbsent);
+ var value = containsKey(key) ? update(this[key] as V) : ifAbsent!();
+ return this[key] = value;
}
@override
- void updateAll(V Function(K key, V value) update) => _map.updateAll(update);
+ void updateAll(V Function(K key, V value) update) {
+ for (var key in keys) {
+ this[key] = update(key, this[key] as V);
+ }
+ }
@override
- void removeWhere(bool Function(K key, V value) test) =>
- _map.removeWhere(test);
+ void removeWhere(bool Function(K key, V value) test) {
+ keys.where((key) => test(key, this[key] as V)).toList().forEach(remove);
+ }
// Note: we don't really have a reasonable old/new value to use here.
// But this should fix "keys" and "values" in templates with minimal overhead.
diff --git a/test/observable_map_test.dart b/test/observable_map_test.dart
index 5743001..b980983 100644
--- a/test/observable_map_test.dart
+++ b/test/observable_map_test.dart
@@ -86,7 +86,7 @@
});
group('observe item', () {
- late ObservableMap map;
+ late ObservableMap<String, int?> map;
List<ChangeRecord>? changes;
setUp(() {
@@ -177,6 +177,48 @@
]);
});
});
+
+ test('change the item as part of addAll', () {
+ map.addAll({'b': 13, 'd': 4});
+ expect(map, {'a': 1, 'b': 13, 'c': 3, 'd': 4});
+ return Future(() {
+ expect(changes, [_changeKey('b', 2, 13)]);
+ });
+ });
+
+ test('change the item as part of addEntries', () {
+ map.addEntries(
+ [MapEntry<String, int>('b', 13), MapEntry<String, int>('d', 4)]);
+ expect(map, {'a': 1, 'b': 13, 'c': 3, 'd': 4});
+ return Future(() {
+ expect(changes, [_changeKey('b', 2, 13)]);
+ });
+ });
+
+ test('update the item', () {
+ map.update('b', (int? value) => value == null ? value : value + 1);
+ expect(map, {'a': 1, 'b': 3, 'c': 3});
+ return Future(() {
+ expect(changes, [_changeKey('b', 2, 3)]);
+ });
+ });
+
+ test('update all items', () {
+ map.updateAll(
+ (String key, int? value) => value == null ? value : value + 1);
+ expect(map, {'a': 2, 'b': 3, 'c': 4});
+ return Future(() {
+ expect(changes, [_changeKey('b', 2, 3)]);
+ });
+ });
+
+ test('remove the item as part of removeWhere', () {
+ map.removeWhere((key, value) => value != null && value > 1);
+ expect(map, {'a': 1});
+ return Future(() {
+ expect(changes, [_removeKey('b', 2)]);
+ });
+ });
});
test('toString', () {