fix: leave->invite in the same sync would hide the invite

Synapse includes the room in both sections if you have both an
invite->leave and a leave->invite transition in one sync response.
Transitions in the other order are only included once (in the leave
section) it seems, so this should work correctly in all cases.

Fixes https://github.com/famedly/product-management/issues/2283
This commit is contained in:
Nicolas Werner 2024-07-31 19:01:12 +02:00
parent 6dbc11180c
commit 3d92428b7e
No known key found for this signature in database
GPG Key ID: B38119FF80087618
2 changed files with 68 additions and 4 deletions

View File

@ -2037,14 +2037,18 @@ class Client extends MatrixApi {
if (join != null) {
await _handleRooms(join, direction: direction);
}
final invite = sync.rooms?.invite;
if (invite != null) {
await _handleRooms(invite, direction: direction);
}
// We need to handle leave before invite. If you decline an invite and
// then get another invite to the same room, Synapse will include the
// room both in invite and leave. If you get an invite and then leave, it
// will only be included in leave.
final leave = sync.rooms?.leave;
if (leave != null) {
await _handleRooms(leave, direction: direction);
}
final invite = sync.rooms?.invite;
if (invite != null) {
await _handleRooms(invite, direction: direction);
}
}
for (final newPresence in sync.presence ?? <Presence>[]) {
final cachedPresence = CachedPresence.fromMatrixEvent(newPresence);

View File

@ -709,6 +709,66 @@ void main() {
await client.database?.clearCache();
await client.dispose(closeDatabase: true);
});
test('leaveThenInvite should be invited', () async {
// Synapse includes a room in both invite and leave if you leave and get
// reinvited while you are offline. The other direction only contains the
// room in leave. Verify that we actually store the invite in the first
// case. See also
// https://github.com/famedly/product-management/issues/2283
final client = await getClient();
await client.abortSync();
client.rooms.clear();
await client.database?.clearCache();
final roomId = '!inviteLeaveRoom:example.com';
await client.handleSync(
SyncUpdate(
nextBatch: 'ABCDEF',
rooms: RoomsUpdate(
invite: {
roomId: InvitedRoomUpdate(
inviteState: [
StrippedStateEvent(
type: EventTypes.RoomMember,
senderId: '@bob:example.com',
stateKey: client.userID,
content: {
'membership': 'invite',
},
),
],
),
},
leave: {
roomId: LeftRoomUpdate(
state: [
MatrixEvent(
type: EventTypes.RoomMember,
senderId: client.userID!,
stateKey: client.userID,
originServerTs: DateTime.now(),
eventId:
'\$abcdefwsjaskdfabsjfhabfsjgbahsjfkgbasjffsajfgsfd',
content: {
'membership': 'leave',
},
),
],
),
},
),
),
);
final room = client.getRoomById(roomId);
expect(room?.membership, Membership.invite);
await client.abortSync();
client.rooms.clear();
await client.database?.clearCache();
await client.dispose(closeDatabase: true);
});
test('ownProfile', () async {
final client = await getClient();
await client.abortSync();