fix: make sure to keep track of aggregated events after requesting history or future

This commit is contained in:
td 2025-04-30 17:43:55 +02:00
parent 94f23272c3
commit 7e41b01176
No known key found for this signature in database
GPG Key ID: 62A30523D4D6CE28
5 changed files with 116 additions and 11 deletions

View File

@ -1521,6 +1521,7 @@ class Room {
void Function()? onNewEvent,
void Function()? onUpdate,
String? eventContextId,
int? limit = Room.defaultHistoryCount,
}) async {
await postLoad();
@ -1529,7 +1530,7 @@ class Room {
if (!isArchived) {
events = await client.database?.getEventList(
this,
limit: defaultHistoryCount,
limit: limit,
) ??
<Event>[];
} else {

View File

@ -152,6 +152,9 @@ class Timeline {
);
if (eventsFromStore != null && eventsFromStore.isNotEmpty) {
for (final e in eventsFromStore) {
addAggregatedEvent(e);
}
// Fetch all users from database we have got here.
for (final event in events) {
if (room.getState(EventTypes.RoomMember, event.senderId) != null) {
@ -500,12 +503,12 @@ class Timeline {
if (relationshipType == null || relationshipEventId == null) {
return; // nothing to do
}
final events = (aggregatedEvents[relationshipEventId] ??=
final e = (aggregatedEvents[relationshipEventId] ??=
<String, Set<Event>>{})[relationshipType] ??= <Event>{};
// remove a potential old event
_removeEventFromSet(events, event);
_removeEventFromSet(e, event);
// add the new one
events.add(event);
e.add(event);
if (onChange != null) {
final index = _findEvent(event_id: relationshipEventId);
onChange?.call(index);
@ -518,8 +521,8 @@ class Timeline {
aggregatedEvents.remove(event.transactionId);
}
for (final types in aggregatedEvents.values) {
for (final events in types.values) {
_removeEventFromSet(events, event);
for (final e in types.values) {
_removeEventFromSet(e, event);
}
}
}

View File

@ -32,7 +32,7 @@ dependencies:
sqflite_common: ^2.4.5
sqlite3: ^2.1.0
typed_data: ^1.3.2
webrtc_interface: ^1.2.2+hotfix.1
webrtc_interface: ^1.2.0
dev_dependencies:
build_runner: ^2.4.15

View File

@ -1098,6 +1098,111 @@ void main() {
expect(timeline.events[0].status, EventStatus.synced);
expect(timeline.events.length, 1);
});
test('make sure aggregated events are updated on requestHistory', () async {
timeline.events.clear();
await client.handleSync(
SyncUpdate(
nextBatch: 'something',
rooms: RoomsUpdate(
join: {
timeline.room.id: JoinedRoomUpdate(
timeline: TimelineUpdate(
events: [
MatrixEvent.fromJson({
'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'event_id': '11',
'sender': '@alice:example.com',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}),
MatrixEvent.fromJson({
'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'event_id': '22',
'sender': '@alice:example.com',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}),
MatrixEvent.fromJson({
'type': 'm.room.message',
'content': {
'msgtype': 'm.text',
'body': '* edit 11',
'm.new_content': {
'msgtype': 'm.text',
'body': 'edit 11',
'm.mentions': {},
},
'm.mentions': {},
'm.relates_to': {
'rel_type': 'm.replace',
'event_id': '11',
},
},
'event_id': '33',
'sender': '@alice:example.com',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}),
MatrixEvent.fromJson({
'type': 'm.room.message',
'content': {
'msgtype': 'm.text',
'body': '* edit 22',
'm.new_content': {
'msgtype': 'm.text',
'body': 'edit 22',
'm.mentions': {},
},
'm.mentions': {},
'm.relates_to': {
'rel_type': 'm.replace',
'event_id': '22',
},
},
'event_id': '44',
'sender': '@alice:example.com',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}),
],
),
),
},
),
),
);
final t = await room.getTimeline(limit: 1);
expect(t.events.length, 1);
expect(
t.events.single.getDisplayEvent(t).body,
'* edit 22',
);
await t.requestHistory();
expect(
t.events.reversed
.where(
(element) => element.relationshipType != RelationshipTypes.edit,
)
.last
.getDisplayEvent(t)
.body,
'edit 22',
);
expect(
t.events.reversed
.where(
(element) => element.relationshipType != RelationshipTypes.edit,
)
.first
.getDisplayEvent(t)
.body,
'edit 11',
);
});
test('logout', () async {
await client.logout();
});

View File

@ -849,8 +849,4 @@ class MockVideoRenderer implements VideoRenderer {
// Mock implementation for disposing VideoRenderer
Logs().i('Mock: Disposing VideoRenderer');
}
@override
// TODO: implement videoValue
RTCVideoValue get videoValue => RTCVideoValue.empty;
}