diff options
-rw-r--r-- | lib/connection.cpp | 26 | ||||
-rw-r--r-- | lib/connection.h | 7 | ||||
-rw-r--r-- | lib/room.cpp | 3 |
3 files changed, 29 insertions, 7 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index 18fa91e7..c582cf94 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -84,6 +84,7 @@ class Connection::Private QHash<QPair<QString, bool>, Room*> roomMap; QVector<QString> roomIdsToForget; QVector<Room*> firstTimeRooms; + QVector<QString> pendingStateRoomIds; QMap<QString, User*> userMap; DirectChatsMap directChats; DirectChatUsersMap directChatUsers; @@ -339,6 +340,7 @@ void Connection::onSyncSuccess(SyncData &&data, bool fromCache) { } if ( auto* r = provideRoom(roomData.roomId, roomData.joinState) ) { + d->pendingStateRoomIds.removeOne(roomData.roomId); r->updateData(std::move(roomData), fromCache); if (d->firstTimeRooms.removeOne(r)) emit loadedRoomState(r); @@ -427,14 +429,32 @@ JoinRoomJob* Connection::joinRoom(const QString& roomAlias, const QStringList& serverNames) { auto job = callApi<JoinRoomJob>(roomAlias, serverNames); + // Upon completion, ensure a room object in Join state is created but only + // if it's not already there due to a sync completing earlier. connect(job, &JoinRoomJob::success, - this, [this, job] { provideRoom(job->roomId(), JoinState::Join); }); + this, [this, job] { provideRoom(job->roomId()); }); return job; } -void Connection::leaveRoom(Room* room) +LeaveRoomJob* Connection::leaveRoom(Room* room) { - callApi<LeaveRoomJob>(room->id()); + const auto& roomId = room->id(); + const auto job = callApi<LeaveRoomJob>(roomId); + if (room->joinState() == JoinState::Invite) + { + // Workaround matrix-org/synapse#2181 - if the room is in invite state + // the invite may have been cancelled but Synapse didn't send it in + // `/sync`. See also #273 for the discussion in the library context. + d->pendingStateRoomIds.push_back(roomId); + connect(job, &LeaveRoomJob::success, this, [this,roomId] { + if (d->pendingStateRoomIds.removeOne(roomId)) + { + qCDebug(MAIN) << "Forcing the room to Leave status"; + provideRoom(roomId, JoinState::Leave); + } + }); + } + return job; } inline auto splitMediaId(const QString& mediaId) diff --git a/lib/connection.h b/lib/connection.h index f2e10488..cba57e3d 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -48,6 +48,7 @@ namespace QMatrixClient class DownloadFileJob; class SendToDeviceJob; class SendMessageJob; + class LeaveRoomJob; /** Create a single-shot connection that triggers on the signal and * then self-disconnects @@ -494,14 +495,14 @@ namespace QMatrixClient SendMessageJob* sendMessage(const QString& roomId, const RoomEvent& event) const; + /** \deprecated Do not use this directly, use Room::leaveRoom() instead */ + virtual LeaveRoomJob* leaveRoom( Room* room ); + // Old API that will be abolished any time soon. DO NOT USE. /** @deprecated Use callApi<PostReceiptJob>() or Room::postReceipt() instead */ virtual PostReceiptJob* postReceipt(Room* room, RoomEvent* event) const; - /** @deprecated Use callApi<LeaveRoomJob>() or Room::leaveRoom() instead */ - virtual void leaveRoom( Room* room ); - signals: /** * @deprecated diff --git a/lib/room.cpp b/lib/room.cpp index 1931be49..d806183f 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1633,7 +1633,8 @@ void Room::inviteToRoom(const QString& memberId) LeaveRoomJob* Room::leaveRoom() { - return connection()->callApi<LeaveRoomJob>(id()); + // FIXME, #63: It should be RoomManager, not Connection + return connection()->leaveRoom(this); } SetRoomStateWithKeyJob*Room::setMemberState(const QString& memberId, const RoomMemberEvent& event) const |