Merge pull request #1726 from famedly/nico/fix-state-handling-after-invite
fix state handling after invite
This commit is contained in:
commit
2f95e41ee9
|
|
@ -1071,19 +1071,19 @@ class Client extends MatrixApi {
|
||||||
[]));
|
[]));
|
||||||
|
|
||||||
archivedRoom.prev_batch = update.timeline?.prevBatch;
|
archivedRoom.prev_batch = update.timeline?.prevBatch;
|
||||||
update.state?.forEach((event) {
|
|
||||||
archivedRoom.setState(Event.fromMatrixEvent(
|
|
||||||
event,
|
|
||||||
archivedRoom,
|
|
||||||
));
|
|
||||||
});
|
|
||||||
|
|
||||||
update.timeline?.events?.forEach((event) {
|
final stateEvents = roomUpdate.state;
|
||||||
archivedRoom.setState(Event.fromMatrixEvent(
|
if (stateEvents != null) {
|
||||||
event,
|
await _handleRoomEvents(archivedRoom, stateEvents, EventUpdateType.state,
|
||||||
archivedRoom,
|
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++) {
|
for (var i = 0; i < timeline.events.length; i++) {
|
||||||
// Try to decrypt encrypted events but don't update the database.
|
// Try to decrypt encrypted events but don't update the database.
|
||||||
|
|
@ -2463,6 +2463,10 @@ class Client extends MatrixApi {
|
||||||
final importantOrRoomLoaded =
|
final importantOrRoomLoaded =
|
||||||
eventUpdate.type == EventUpdateType.inviteState ||
|
eventUpdate.type == EventUpdateType.inviteState ||
|
||||||
!room.partial ||
|
!room.partial ||
|
||||||
|
// make sure we do overwrite events we have already loaded.
|
||||||
|
room.states[stateEvent.type]
|
||||||
|
?.containsKey(stateEvent.stateKey ?? '') ==
|
||||||
|
true ||
|
||||||
importantStateEvents.contains(stateEvent.type);
|
importantStateEvents.contains(stateEvent.type);
|
||||||
if ((noMessageOrNoEdit || editingLastEvent || consecutiveEdit) &&
|
if ((noMessageOrNoEdit || editingLastEvent || consecutiveEdit) &&
|
||||||
importantOrRoomLoaded) {
|
importantOrRoomLoaded) {
|
||||||
|
|
|
||||||
|
|
@ -210,10 +210,8 @@ class Event extends MatrixEvent {
|
||||||
type: jsonPayload['type'],
|
type: jsonPayload['type'],
|
||||||
eventId: jsonPayload['event_id'] ?? '',
|
eventId: jsonPayload['event_id'] ?? '',
|
||||||
senderId: jsonPayload['sender'],
|
senderId: jsonPayload['sender'],
|
||||||
originServerTs: jsonPayload['origin_server_ts'] != null
|
originServerTs: DateTime.fromMillisecondsSinceEpoch(
|
||||||
? DateTime.fromMillisecondsSinceEpoch(
|
jsonPayload['origin_server_ts'] ?? 0),
|
||||||
jsonPayload['origin_server_ts'])
|
|
||||||
: DateTime.now(),
|
|
||||||
unsigned: unsigned,
|
unsigned: unsigned,
|
||||||
room: room,
|
room: room,
|
||||||
originalSource: originalSource.isEmpty
|
originalSource: originalSource.isEmpty
|
||||||
|
|
|
||||||
|
|
@ -196,15 +196,6 @@ class Room {
|
||||||
return;
|
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;
|
(states[state.type] ??= {})[stateKey] = state;
|
||||||
|
|
||||||
client.onRoomState.add(state);
|
client.onRoomState.add(state);
|
||||||
|
|
@ -1574,8 +1565,6 @@ class Room {
|
||||||
return <User>[];
|
return <User>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _requestedParticipants = false;
|
|
||||||
|
|
||||||
/// Request the full list of participants from the server. The local list
|
/// Request the full list of participants from the server. The local list
|
||||||
/// from the store is not complete if the client uses lazy loading.
|
/// from the store is not complete if the client uses lazy loading.
|
||||||
/// List `membershipFilter` defines with what membership do you want the
|
/// List `membershipFilter` defines with what membership do you want the
|
||||||
|
|
@ -1591,17 +1580,20 @@ class Room {
|
||||||
],
|
],
|
||||||
bool suppressWarning = false,
|
bool suppressWarning = false,
|
||||||
bool cache = true]) async {
|
bool cache = true]) async {
|
||||||
if (!participantListComplete && partial) {
|
if (!participantListComplete || partial) {
|
||||||
// we aren't fully loaded, maybe the users are in the database
|
// 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) ?? [];
|
final users = await client.database?.getUsers(this) ?? [];
|
||||||
for (final user in users) {
|
for (final user in users) {
|
||||||
setState(user);
|
setState(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not request users from the server if we have already done it
|
// Do not request users from the server if we have already have a complete list locally.
|
||||||
// in this session or have a complete list locally.
|
if (participantListComplete) {
|
||||||
if (_requestedParticipants || participantListComplete) {
|
|
||||||
return getParticipants(membershipFilter);
|
return getParticipants(membershipFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1626,7 +1618,6 @@ class Room {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_requestedParticipants = cache;
|
|
||||||
users.removeWhere((u) => !membershipFilter.contains(u.membership));
|
users.removeWhere((u) => !membershipFilter.contains(u.membership));
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
@ -1634,10 +1625,14 @@ class Room {
|
||||||
/// Checks if the local participant list of joined and invited users is complete.
|
/// Checks if the local participant list of joined and invited users is complete.
|
||||||
bool get participantListComplete {
|
bool get participantListComplete {
|
||||||
final knownParticipants = getParticipants();
|
final knownParticipants = getParticipants();
|
||||||
knownParticipants.removeWhere(
|
final joinedCount =
|
||||||
(u) => ![Membership.join, Membership.invite].contains(u.membership));
|
knownParticipants.where((u) => u.membership == Membership.join).length;
|
||||||
return knownParticipants.length ==
|
final invitedCount = knownParticipants
|
||||||
(summary.mJoinedMemberCount ?? 0) + (summary.mInvitedMemberCount ?? 0);
|
.where((u) => u.membership == Membership.invite)
|
||||||
|
.length;
|
||||||
|
|
||||||
|
return (summary.mJoinedMemberCount ?? 0) == joinedCount &&
|
||||||
|
(summary.mInvitedMemberCount ?? 0) == invitedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -70,6 +70,7 @@ void main() {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
room.setState(Event(
|
room.setState(Event(
|
||||||
room: room,
|
room: room,
|
||||||
eventId: '143273582443PhrSn:example.org',
|
eventId: '143273582443PhrSn:example.org',
|
||||||
|
|
@ -80,6 +81,46 @@ void main() {
|
||||||
content: {'join_rule': 'public'},
|
content: {'join_rule': 'public'},
|
||||||
stateKey: '',
|
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();
|
final heroUsers = await room.loadHeroUsers();
|
||||||
expect(heroUsers.length, 3);
|
expect(heroUsers.length, 3);
|
||||||
|
|
@ -89,9 +130,10 @@ void main() {
|
||||||
expect(room.notificationCount, notificationCount);
|
expect(room.notificationCount, notificationCount);
|
||||||
expect(room.highlightCount, highlightCount);
|
expect(room.highlightCount, highlightCount);
|
||||||
expect(room.summary.mJoinedMemberCount, notificationCount);
|
expect(room.summary.mJoinedMemberCount, notificationCount);
|
||||||
expect(room.summary.mInvitedMemberCount, notificationCount);
|
expect(room.summary.mInvitedMemberCount, 2);
|
||||||
expect(room.summary.mHeroes, heroes);
|
expect(room.summary.mHeroes, heroes);
|
||||||
expect(room.getLocalizedDisplayname(), 'Group with Alice, Bob, Charley');
|
expect(room.getLocalizedDisplayname(),
|
||||||
|
'Group with Alice Margatroid, Bob, Charley');
|
||||||
expect(
|
expect(
|
||||||
room.getState('m.room.join_rules')?.content['join_rule'], 'public');
|
room.getState('m.room.join_rules')?.content['join_rule'], 'public');
|
||||||
expect(room.roomAccountData['com.test.foo']?.content['foo'], 'bar');
|
expect(room.roomAccountData['com.test.foo']?.content['foo'], 'bar');
|
||||||
|
|
@ -434,12 +476,12 @@ void main() {
|
||||||
|
|
||||||
test('requestParticipants', () async {
|
test('requestParticipants', () async {
|
||||||
final participants = await room.requestParticipants();
|
final participants = await room.requestParticipants();
|
||||||
expect(participants.length, 1);
|
expect(participants.length, 4);
|
||||||
final user = participants[0];
|
final user = participants.singleWhere((u) => u.id == '@alice:matrix.org');
|
||||||
expect(user.id, '@alice:example.org');
|
expect(user.id, '@alice:matrix.org');
|
||||||
expect(user.displayName, 'Alice Margatroid');
|
expect(user.displayName, 'Alice Margatroid');
|
||||||
expect(user.membership, Membership.join);
|
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');
|
expect(user.room.id, '!localpart:server.abc');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1405,10 +1447,13 @@ void main() {
|
||||||
|
|
||||||
test('getMention', () async {
|
test('getMention', () async {
|
||||||
expect(room.getMention('@invalid'), null);
|
expect(room.getMention('@invalid'), null);
|
||||||
expect(room.getMention('@[Alice Margatroid]'), '@alice:example.org');
|
expect(room.getMention('@[Alice Margatroid]'), '@alice:matrix.org');
|
||||||
expect(room.getMention('@[Alice Margatroid]#1754'), '@alice:example.org');
|
expect(room.getMention('@[Alice Margatroid]#1667'), '@alice:matrix.org');
|
||||||
});
|
});
|
||||||
test('inviteLink', () async {
|
test('inviteLink', () async {
|
||||||
|
// ensure we don't rerequest members
|
||||||
|
room.summary.mJoinedMemberCount = 4;
|
||||||
|
|
||||||
var matrixToLink = await room.matrixToInviteLink();
|
var matrixToLink = await room.matrixToInviteLink();
|
||||||
expect(matrixToLink.toString(),
|
expect(matrixToLink.toString(),
|
||||||
'https://matrix.to/#/%23testalias%3Aexample.com');
|
'https://matrix.to/#/%23testalias%3Aexample.com');
|
||||||
|
|
@ -1424,7 +1469,7 @@ void main() {
|
||||||
);
|
);
|
||||||
matrixToLink = await room.matrixToInviteLink();
|
matrixToLink = await room.matrixToInviteLink();
|
||||||
expect(matrixToLink.toString(),
|
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', () {
|
test('callMemberStateIsExpired', () {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue