feat: Add onInsert, onRemove and onUpdate cb to timeline
This makes it finally possible to use Flutters AnimatedListView with our Timeline class and in web we can now update single elements instead of the whole timeline on every change which should be quiet good for the performance
This commit is contained in:
parent
0e2542b172
commit
e1f93637b3
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
Loading…
Reference in New Issue