Merge pull request #2023 from famedly/krille/make-sure-we-do-not-override-state-on-fetch-history

fix: Older state events overwrite newer ones on fetching history
This commit is contained in:
Krille-chan 2025-02-12 14:39:36 +01:00 committed by GitHub
commit 352b3fa68b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 1 deletions

View File

@ -2665,8 +2665,27 @@ class Client extends MatrixApi {
if (syncRoomUpdate is JoinedRoomUpdate) { if (syncRoomUpdate is JoinedRoomUpdate) {
final state = syncRoomUpdate.state; final state = syncRoomUpdate.state;
// If we are receiving states when fetching history we need to check if
// we are not overwriting a newer state.
if (direction == Direction.b) {
await room.postLoad();
state?.removeWhere((state) {
final existingState =
room.getState(state.type, state.stateKey ?? '');
if (existingState == null) return false;
if (existingState is User) {
return existingState.originServerTs
?.isAfter(state.originServerTs) ??
true;
}
if (existingState is MatrixEvent) {
return existingState.originServerTs.isAfter(state.originServerTs);
}
return true;
});
}
if (state != null && state.isNotEmpty) { if (state != null && state.isNotEmpty) {
// TODO: This method seems to be comperatively slow for some updates
await _handleRoomEvents( await _handleRoomEvents(
room, room,
state, state,

View File

@ -256,6 +256,7 @@ class Event extends MatrixEvent {
typeKey: type, typeKey: type,
senderId: senderId, senderId: senderId,
room: room, room: room,
originServerTs: originServerTs,
); );
String get messageType => type == EventTypes.Sticker String get messageType => type == EventTypes.Sticker

View File

@ -22,12 +22,14 @@ import 'package:matrix/matrix.dart';
class User extends StrippedStateEvent { class User extends StrippedStateEvent {
final Room room; final Room room;
final Map<String, Object?>? prevContent; final Map<String, Object?>? prevContent;
final DateTime? originServerTs;
factory User( factory User(
String id, { String id, {
String? membership, String? membership,
String? displayName, String? displayName,
String? avatarUrl, String? avatarUrl,
DateTime? originServerTs,
required Room room, required Room room,
}) { }) {
return User.fromState( return User.fromState(
@ -40,6 +42,7 @@ class User extends StrippedStateEvent {
}, },
typeKey: EventTypes.RoomMember, typeKey: EventTypes.RoomMember,
room: room, room: room,
originServerTs: originServerTs,
); );
} }
@ -49,6 +52,7 @@ class User extends StrippedStateEvent {
required String typeKey, required String typeKey,
required super.senderId, required super.senderId,
required this.room, required this.room,
this.originServerTs,
this.prevContent, this.prevContent,
}) : super( }) : super(
type: typeKey, type: typeKey,
@ -254,5 +258,6 @@ extension FromStrippedStateEventExtension on StrippedStateEvent {
typeKey: type, typeKey: type,
senderId: senderId, senderId: senderId,
room: room, room: room,
originServerTs: null,
); );
} }

View File

@ -695,6 +695,35 @@ void main() {
); );
expect(room.lastEvent!.content['body'], '* floooof'); expect(room.lastEvent!.content['body'], '* floooof');
// Older state event should not overwrite current state events
room.partial = false;
await matrix.handleSync(
SyncUpdate(
nextBatch: '',
rooms: RoomsUpdate(
join: {
room.id: JoinedRoomUpdate(
state: [
MatrixEvent(
type: EventTypes.RoomMember,
content: {'displayname': 'Alice Catgirl'},
senderId: '@alice:example.com',
eventId: 'oldEventId',
stateKey: '@alice:example.com',
originServerTs:
DateTime.now().subtract(const Duration(days: 365 * 30)),
),
],
),
},
),
),
direction: Direction.b,
);
room.partial = true;
expect(room.getParticipants().first.id, '@alice:example.com');
expect(room.getParticipants().first.displayName, 'Alice Margatroid');
// accepts a consecutive edit // accepts a consecutive edit
await matrix.handleSync( await matrix.handleSync(
SyncUpdate.fromJson({ SyncUpdate.fromJson({