Merge pull request #1726 from famedly/nico/fix-state-handling-after-invite

fix state handling after invite
This commit is contained in:
Krille-chan 2024-03-05 09:01:31 +01:00 committed by GitHub
commit 2f95e41ee9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 113 additions and 45 deletions

View File

@ -1071,19 +1071,19 @@ class Client extends MatrixApi {
[]));
archivedRoom.prev_batch = update.timeline?.prevBatch;
update.state?.forEach((event) {
archivedRoom.setState(Event.fromMatrixEvent(
event,
archivedRoom,
));
});
update.timeline?.events?.forEach((event) {
archivedRoom.setState(Event.fromMatrixEvent(
event,
archivedRoom,
));
});
final stateEvents = roomUpdate.state;
if (stateEvents != null) {
await _handleRoomEvents(archivedRoom, stateEvents, EventUpdateType.state,
store: false);
}
final timelineEvents = roomUpdate.timeline?.events;
if (timelineEvents != null) {
await _handleRoomEvents(archivedRoom, timelineEvents.reversed.toList(),
EventUpdateType.timeline,
store: false);
}
for (var i = 0; i < timeline.events.length; i++) {
// Try to decrypt encrypted events but don't update the database.
@ -2463,6 +2463,10 @@ class Client extends MatrixApi {
final importantOrRoomLoaded =
eventUpdate.type == EventUpdateType.inviteState ||
!room.partial ||
// make sure we do overwrite events we have already loaded.
room.states[stateEvent.type]
?.containsKey(stateEvent.stateKey ?? '') ==
true ||
importantStateEvents.contains(stateEvent.type);
if ((noMessageOrNoEdit || editingLastEvent || consecutiveEdit) &&
importantOrRoomLoaded) {

View File

@ -210,10 +210,8 @@ class Event extends MatrixEvent {
type: jsonPayload['type'],
eventId: jsonPayload['event_id'] ?? '',
senderId: jsonPayload['sender'],
originServerTs: jsonPayload['origin_server_ts'] != null
? DateTime.fromMillisecondsSinceEpoch(
jsonPayload['origin_server_ts'])
: DateTime.now(),
originServerTs: DateTime.fromMillisecondsSinceEpoch(
jsonPayload['origin_server_ts'] ?? 0),
unsigned: unsigned,
room: room,
originalSource: originalSource.isEmpty

View File

@ -196,15 +196,6 @@ class Room {
return;
}
// Do not set old events as state events
final prevEvent = getState(state.type, stateKey);
if (prevEvent != null &&
prevEvent.eventId != state.eventId &&
prevEvent.originServerTs.millisecondsSinceEpoch >
state.originServerTs.millisecondsSinceEpoch) {
return;
}
(states[state.type] ??= {})[stateKey] = state;
client.onRoomState.add(state);
@ -1574,8 +1565,6 @@ class Room {
return <User>[];
}
bool _requestedParticipants = false;
/// Request the full list of participants from the server. The local list
/// from the store is not complete if the client uses lazy loading.
/// List `membershipFilter` defines with what membership do you want the
@ -1591,17 +1580,20 @@ class Room {
],
bool suppressWarning = false,
bool cache = true]) async {
if (!participantListComplete && partial) {
if (!participantListComplete || partial) {
// we aren't fully loaded, maybe the users are in the database
// We always need to check the database in the partial case, since state
// events won't get written to memory in this case and someone new could
// have joined, while someone else left, which might lead to the same
// count in the completeness check.
final users = await client.database?.getUsers(this) ?? [];
for (final user in users) {
setState(user);
}
}
// Do not request users from the server if we have already done it
// in this session or have a complete list locally.
if (_requestedParticipants || participantListComplete) {
// Do not request users from the server if we have already have a complete list locally.
if (participantListComplete) {
return getParticipants(membershipFilter);
}
@ -1626,7 +1618,6 @@ class Room {
}
}
_requestedParticipants = cache;
users.removeWhere((u) => !membershipFilter.contains(u.membership));
return users;
}
@ -1634,10 +1625,14 @@ class Room {
/// Checks if the local participant list of joined and invited users is complete.
bool get participantListComplete {
final knownParticipants = getParticipants();
knownParticipants.removeWhere(
(u) => ![Membership.join, Membership.invite].contains(u.membership));
return knownParticipants.length ==
(summary.mJoinedMemberCount ?? 0) + (summary.mInvitedMemberCount ?? 0);
final joinedCount =
knownParticipants.where((u) => u.membership == Membership.join).length;
final invitedCount = knownParticipants
.where((u) => u.membership == Membership.invite)
.length;
return (summary.mJoinedMemberCount ?? 0) == joinedCount &&
(summary.mInvitedMemberCount ?? 0) == invitedCount;
}
@Deprecated(

File diff suppressed because one or more lines are too long

View File

@ -70,6 +70,7 @@ void main() {
),
},
);
room.setState(Event(
room: room,
eventId: '143273582443PhrSn:example.org',
@ -80,6 +81,46 @@ void main() {
content: {'join_rule': 'public'},
stateKey: '',
));
room.setState(Event(
room: room,
eventId: '143273582443PhrSnY:example.org',
originServerTs: DateTime.fromMillisecondsSinceEpoch(1432735824653),
senderId: matrix.userID!,
type: 'm.room.member',
unsigned: {'age': 1234},
content: {'membership': 'join', 'displayname': 'YOU'},
stateKey: matrix.userID!,
));
room.setState(Event(
room: room,
eventId: '143273582443PhrSnA:example.org',
originServerTs: DateTime.fromMillisecondsSinceEpoch(1432735824653),
senderId: '@alice:matrix.org',
type: 'm.room.member',
unsigned: {'age': 1234},
content: {'membership': 'join', 'displayname': 'Alice Margatroid'},
stateKey: '@alice:matrix.org',
));
room.setState(Event(
room: room,
eventId: '143273582443PhrSnB:example.org',
originServerTs: DateTime.fromMillisecondsSinceEpoch(1432735824653),
senderId: '@bob:example.com',
type: 'm.room.member',
unsigned: {'age': 1234},
content: {'membership': 'invite', 'displayname': 'Bob'},
stateKey: '@bob:example.com',
));
room.setState(Event(
room: room,
eventId: '143273582443PhrSnC:example.org',
originServerTs: DateTime.fromMillisecondsSinceEpoch(1432735824653),
senderId: '@charley:example.org',
type: 'm.room.member',
unsigned: {'age': 1234},
content: {'membership': 'invite', 'displayname': 'Charley'},
stateKey: '@charley:example.org',
));
final heroUsers = await room.loadHeroUsers();
expect(heroUsers.length, 3);
@ -89,9 +130,10 @@ void main() {
expect(room.notificationCount, notificationCount);
expect(room.highlightCount, highlightCount);
expect(room.summary.mJoinedMemberCount, notificationCount);
expect(room.summary.mInvitedMemberCount, notificationCount);
expect(room.summary.mInvitedMemberCount, 2);
expect(room.summary.mHeroes, heroes);
expect(room.getLocalizedDisplayname(), 'Group with Alice, Bob, Charley');
expect(room.getLocalizedDisplayname(),
'Group with Alice Margatroid, Bob, Charley');
expect(
room.getState('m.room.join_rules')?.content['join_rule'], 'public');
expect(room.roomAccountData['com.test.foo']?.content['foo'], 'bar');
@ -434,12 +476,12 @@ void main() {
test('requestParticipants', () async {
final participants = await room.requestParticipants();
expect(participants.length, 1);
final user = participants[0];
expect(user.id, '@alice:example.org');
expect(participants.length, 4);
final user = participants.singleWhere((u) => u.id == '@alice:matrix.org');
expect(user.id, '@alice:matrix.org');
expect(user.displayName, 'Alice Margatroid');
expect(user.membership, Membership.join);
expect(user.avatarUrl.toString(), 'mxc://example.org/SEsfnsuifSDFSSEF');
//expect(user.avatarUrl.toString(), 'mxc://example.org/SEsfnsuifSDFSSEF');
expect(user.room.id, '!localpart:server.abc');
});
@ -1405,10 +1447,13 @@ void main() {
test('getMention', () async {
expect(room.getMention('@invalid'), null);
expect(room.getMention('@[Alice Margatroid]'), '@alice:example.org');
expect(room.getMention('@[Alice Margatroid]#1754'), '@alice:example.org');
expect(room.getMention('@[Alice Margatroid]'), '@alice:matrix.org');
expect(room.getMention('@[Alice Margatroid]#1667'), '@alice:matrix.org');
});
test('inviteLink', () async {
// ensure we don't rerequest members
room.summary.mJoinedMemberCount = 4;
var matrixToLink = await room.matrixToInviteLink();
expect(matrixToLink.toString(),
'https://matrix.to/#/%23testalias%3Aexample.com');
@ -1424,7 +1469,7 @@ void main() {
);
matrixToLink = await room.matrixToInviteLink();
expect(matrixToLink.toString(),
'https://matrix.to/#/!localpart%3Aserver.abc?via=example.org&via=example.com&via=test.abc');
'https://matrix.to/#/!localpart%3Aserver.abc?via=example.com&via=test.abc&via=example.org');
});
test('callMemberStateIsExpired', () {