Merge branch 'krille/timeline-auto-update-list' into 'main'

feat: Add onInsert, onRemove and onUpdate cb to timeline

See merge request famedly/company/frontend/famedlysdk!880
This commit is contained in:
Nicolas Werner 2021-11-09 13:08:42 +00:00
commit 7f9a75a43d
2 changed files with 53 additions and 21 deletions

View File

@ -35,7 +35,9 @@ class Timeline {
final Map<String, Map<String, Set<Event>>> aggregatedEvents = {};
final void Function()? onUpdate;
final void Function(int insertID)? onInsert;
final void Function(int index)? onChange;
final void Function(int index)? onInsert;
final void Function(int index)? onRemove;
StreamSubscription<EventUpdate>? sub;
StreamSubscription<SyncUpdate>? roomSub;
@ -86,6 +88,11 @@ class Timeline {
);
if (eventsFromStore != null && eventsFromStore.isNotEmpty) {
events.addAll(eventsFromStore);
final startIndex = events.length - eventsFromStore.length;
final endIndex = events.length;
for (var i = startIndex; i < endIndex; i++) {
onInsert?.call(i);
}
} else {
Logs().v('No more events found in the store. Request from server...');
await room.requestHistory(
@ -102,9 +109,14 @@ class Timeline {
}
}
Timeline(
{required this.room, List<Event>? events, this.onUpdate, this.onInsert})
: events = events ?? [] {
Timeline({
required this.room,
List<Event>? events,
this.onUpdate,
this.onChange,
this.onInsert,
this.onRemove,
}) : events = events ?? [] {
sub = room.client.onEvent.stream.listen(_handleEventUpdate);
// If the timeline is limited we want to clear our events cache
roomSub = room.client.onSync.stream
@ -142,6 +154,7 @@ class Timeline {
events[i].content['session_id'] == sessionId) {
events[i] = await encryption.decryptRoomEvent(room.id, events[i],
store: true);
onChange?.call(i);
if (events[i].type != EventTypes.Encrypted) {
decryptAtLeastOneEvent = true;
}
@ -249,19 +262,21 @@ class Timeline {
EventStatus.synced.intValue);
// Redaction events are handled as modification for existing events.
if (eventUpdate.content['type'] == EventTypes.Redaction) {
final eventId = _findEvent(event_id: eventUpdate.content['redacts']);
if (eventId < events.length) {
removeAggregatedEvent(events[eventId]);
events[eventId].setRedactionEvent(Event.fromJson(
final index = _findEvent(event_id: eventUpdate.content['redacts']);
if (index < events.length) {
removeAggregatedEvent(events[index]);
events[index].setRedactionEvent(Event.fromJson(
eventUpdate.content,
room,
));
onChange?.call(index);
}
} else if (status.isRemoved) {
final i = _findEvent(event_id: eventUpdate.content['event_id']);
if (i < events.length) {
removeAggregatedEvent(events[i]);
events.removeAt(i);
onRemove?.call(i);
}
} else {
final i = _findEvent(
@ -283,6 +298,7 @@ class Timeline {
events[i].status = oldStatus;
}
addAggregatedEvent(events[i]);
onChange?.call(i);
} else {
final newEvent = Event.fromJson(
eventUpdate.content,
@ -293,14 +309,16 @@ class Timeline {
events.indexWhere(
(e) => e.eventId == eventUpdate.content['event_id']) !=
-1) return;
var index = events.length;
if (eventUpdate.type == EventUpdateType.history) {
events.add(newEvent);
} else {
events.insert(events.firstIndexWhereNotError, newEvent);
index = events.firstIndexWhereNotError;
events.insert(index, newEvent);
}
addAggregatedEvent(newEvent);
onInsert?.call(0);
onInsert?.call(index);
}
}
if (update && !_collectHistoryUpdates) {

View File

@ -34,6 +34,8 @@ void main() {
final testTimeStamp = DateTime.now().millisecondsSinceEpoch;
var updateCount = 0;
final insertList = <int>[];
final changeList = <int>[];
final removeList = <int>[];
var olmEnabled = true;
late Client client;
@ -54,14 +56,15 @@ void main() {
room = Room(
id: roomID, client: client, prev_batch: '1234', roomAccountData: {});
timeline = Timeline(
room: room,
events: [],
onUpdate: () {
updateCount++;
},
onInsert: (int insertID) {
insertList.add(insertID);
});
room: room,
events: [],
onUpdate: () {
updateCount++;
},
onInsert: insertList.add,
onChange: changeList.add,
onRemove: removeList.add,
);
});
test('Create', () async {
@ -100,6 +103,8 @@ void main() {
expect(updateCount, 2);
expect(insertList, [0, 0]);
expect(insertList.length, timeline.events.length);
expect(changeList, []);
expect(removeList, []);
expect(timeline.events.length, 2);
expect(timeline.events[0].eventId, '1');
expect(timeline.events[0].sender.id, '@alice:example.com');
@ -146,6 +151,8 @@ void main() {
expect(updateCount, 3);
expect(insertList, [0, 0]);
expect(insertList.length, timeline.events.length);
expect(changeList, [1]);
expect(removeList, []);
expect(timeline.events.length, 2);
expect(timeline.events[1].redacted, true);
});
@ -211,8 +218,10 @@ void main() {
await Future.delayed(Duration(milliseconds: 50));
expect(updateCount, 13);
expect(insertList, [0, 0, 0, 0, 0, 0, 0]);
expect(insertList, [0, 0, 0, 0, 0, 1, 2]);
expect(insertList.length, timeline.events.length);
expect(changeList, [1, 0, 0, 0, 1, 2]);
expect(removeList, []);
expect(timeline.events[0].status, EventStatus.error);
expect(timeline.events[1].status, EventStatus.error);
expect(timeline.events[2].status, EventStatus.error);
@ -225,7 +234,9 @@ void main() {
expect(updateCount, 14);
expect(insertList, [0, 0, 0, 0, 0, 0, 0]);
expect(insertList, [0, 0, 0, 0, 0, 1, 2]);
expect(changeList, [1, 0, 0, 0, 1, 2]);
expect(removeList, [0]);
expect(timeline.events.length, 6);
expect(timeline.events[0].status, EventStatus.error);
});
@ -270,7 +281,9 @@ void main() {
expect(updateCount, 17);
expect(insertList, [0, 0, 0, 0, 0, 0, 0, 0]);
expect(insertList, [0, 0, 0, 0, 0, 1, 2, 0]);
expect(changeList, [1, 0, 0, 0, 1, 2, 0, 0]);
expect(removeList, [0]);
expect(timeline.events.length, 1);
expect(timeline.events[0].status, EventStatus.sent);
});
@ -283,6 +296,7 @@ void main() {
await Future.delayed(Duration(milliseconds: 50));
expect(updateCount, 20);
expect(insertList, [0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2]);
expect(timeline.events.length, 3);
expect(timeline.events[0].eventId, '3143273582443PhrSn:example.org');
expect(timeline.events[1].eventId, '2143273582443PhrSn:example.org');