...
 
Commits (2)
......@@ -89,5 +89,5 @@ class AliasesChangeDiff extends Diff {
AliasesChangeDiff(this._previous, this._current);
List<Change<RoomAlias>> get aliases =>
_previous.aliases.diff(_current.aliases);
Change.createList(_previous?.aliases, _current.aliases);
}
......@@ -18,13 +18,13 @@ class PowerLevelsChangeEvent extends StateEvent implements HasDiff {
final PowerLevelsChange previousContent;
@override
final PowerLevelChangeDiff diff;
final PowerLevelsChangeDiff diff;
PowerLevelsChangeEvent(
RoomEventArgs args, {
@required this.content,
this.previousContent,
}) : diff = PowerLevelChangeDiff(previousContent, content),
}) : diff = PowerLevelsChangeDiff(previousContent, content),
super(args, stateKey: '');
factory PowerLevelsChangeEvent.fromJson(RoomEventArgs args, dynamic json) {
......@@ -167,46 +167,52 @@ class PowerLevelsChange extends EventContent {
}
}
class PowerLevelChangeDiff extends Diff {
class PowerLevelsChangeDiff extends Diff {
final PowerLevelsChange _previous;
final PowerLevelsChange _current;
PowerLevelChangeDiff(this._previous, this._current);
PowerLevelsChangeDiff(this._previous, this._current);
Change<int> get banLevel => Change(_previous.banLevel, _current.banLevel);
Change<int> get banLevel => Change(_previous?.banLevel, _current.banLevel);
Change<int> get inviteLevel =>
Change(_previous.inviteLevel, _current.inviteLevel);
Change(_previous?.inviteLevel, _current.inviteLevel);
Change<int> get kickLevel => Change(_previous.kickLevel, _current.kickLevel);
Change<int> get kickLevel => Change(_previous?.kickLevel, _current.kickLevel);
Change<int> get redactLevel =>
Change(_previous.redactLevel, _current.redactLevel);
Change(_previous?.redactLevel, _current.redactLevel);
Change<int> get stateEventsDefaultLevel => Change(
_previous.stateEventsDefaultLevel,
_previous?.stateEventsDefaultLevel,
_current.stateEventsDefaultLevel,
);
Change<int> get eventsDefaultLevel =>
Change(_previous.eventsDefaultLevel, _current.eventsDefaultLevel);
Change(_previous?.eventsDefaultLevel, _current.eventsDefaultLevel);
Map<Type, Change<int>> get eventLevels => _previous.eventLevels
.diff(_current.eventLevels)
// Handle removals as changes to default levels
.map((key, change) => change is Removed
? MapEntry(key, Edited(change.value, _current.eventsDefaultLevel))
: MapEntry(key, change));
Map<Type, Change<int>> get eventLevels =>
Change.createMap(_previous?.eventLevels, _current.eventLevels)
.toEdited(defaultValue: _current.eventsDefaultLevel);
Change<int> get userDefaultLevel =>
Change(_previous.userDefaultLevel, _current.userDefaultLevel);
Change(_previous?.userDefaultLevel, _current.userDefaultLevel);
Map<UserId, Change<int>> get userLevels => _previous.userLevels
.diff(_current.userLevels) // Handle removals as changes to default levels
.map((key, change) => change is Removed
? MapEntry(key, Edited(change.value, _current.userDefaultLevel))
: MapEntry(key, change));
Map<UserId, Change<int>> get userLevels =>
Change.createMap(_previous?.userLevels, _current.userLevels)
.toEdited(defaultValue: _current.userDefaultLevel);
Change<int> get roomNotificationLevel =>
Change(_previous.roomNotificationLevel, _current.roomNotificationLevel);
Change(_previous?.roomNotificationLevel, _current.roomNotificationLevel);
}
extension _ChangeMapExtension<K, V> on Map<K, Change<V>> {
/// Handle removals and additions as changes to or from a [defaultValue].
Map<K, Change<V>> toEdited({@required V defaultValue}) {
return this.map((key, change) => change is Removed
? MapEntry(key, Edited(change.value, defaultValue))
: change is Added
? MapEntry(key, Edited(defaultValue, change.value))
: MapEntry(key, change));
}
}
......@@ -44,8 +44,8 @@ abstract class Change<T> {
Change._();
factory Change(T previous, T current, {bool inMap = false}) {
if (!inMap) {
factory Change(T previous, T current, {bool inIterable = false}) {
if (!inIterable) {
return previous != current
? Edited(previous, current)
: Unchanged(current);
......@@ -62,34 +62,41 @@ abstract class Change<T> {
}
}
@override
String toString() => '$runtimeType($value)';
}
static Map<K, Change<V>> createMap<K, V>(
Map<K, V> previous,
Map<K, V> current,
) {
return previous == null || previous.isEmpty
? current.map((key, value) => MapEntry(key, Added(value)))
: Map.fromEntries(
previous.keys.followedBy(current.keys).toSet().map(
(key) => MapEntry(
key,
Change(previous[key], current[key], inIterable: true),
),
),
);
}
extension DiffMapExtension<K, V> on Map<K, V> {
Map<K, Change<V>> diff(Map<K, V> current) => Map.fromEntries(
this.keys.followedBy(current.keys).toSet().map(
(key) => MapEntry(
key,
Change(this[key], current[key], inMap: true),
),
),
);
}
static List<Change<T>> createList<T>(List<T> previous, List<T> current) {
if (previous == null || previous.isEmpty) {
return current.map((e) => Added(e)).toList(growable: false);
}
extension DiffListExtension<T> on List<T> {
List<Change<T>> diff(List<T> current) {
final removals =
this.where((e) => !current.contains(e)).map((e) => Removed(e));
previous.where((e) => !current.contains(e)).map((e) => Removed(e));
final additions =
current.where((e) => !this.contains(e)).map((e) => Added(e));
current.where((e) => !previous.contains(e)).map((e) => Added(e));
final unchanged =
this.where((e) => current.contains(e)).map((e) => Unchanged(e));
previous.where((e) => current.contains(e)).map((e) => Unchanged(e));
return [...unchanged, ...additions, ...removals];
}
@override
String toString() => '$runtimeType($value)';
}
class Unchanged<T> extends Change<T> {
......