diff options
-rw-r--r-- | connection.cpp | 65 | ||||
-rw-r--r-- | connection.h | 9 |
2 files changed, 45 insertions, 29 deletions
diff --git a/connection.cpp b/connection.cpp index b32f38ea..2a748eb1 100644 --- a/connection.cpp +++ b/connection.cpp @@ -436,38 +436,45 @@ CreateRoomJob* Connection::createRoom(RoomVisibility visibility, void Connection::requestDirectChat(const QString& userId) { - auto roomId = d->directChats.value(user(userId)); - if (roomId.isEmpty()) - { - auto j = createDirectChat(userId); - connect(j, &BaseJob::success, this, [this,j,userId,roomId] { - qCDebug(MAIN) << "Direct chat with" << userId - << "has been created as" << roomId; - emit directChatAvailable(roomMap().value({j->roomId(), false})); - }); - return; - } + doInDirectChat(userId, [this] (Room* r) { emit directChatAvailable(r); }); +} - auto room = roomMap().value({roomId, false}, nullptr); - if (room) - { - Q_ASSERT(room->id() == roomId); - qCDebug(MAIN) << "Requested direct chat with" << userId - << "is already available as" << room->id(); - emit directChatAvailable(room); - return; - } - room = roomMap().value({roomId, true}, nullptr); - if (room) +void Connection::doInDirectChat(const QString& userId, + std::function<void (Room*)> operation) +{ + // There can be more than one DC; find the first valid, and delete invalid + // (left/forgotten) ones along the way. + for (auto roomId: d->directChats.values(user(userId))) { - Q_ASSERT(room->id() == roomId); - auto j = joinRoom(room->id()); - connect(j, &BaseJob::success, this, [this,j,roomId,userId] { - qCDebug(MAIN) << "Joined the already invited direct chat with" - << userId << "as" << roomId; - emit directChatAvailable(roomMap().value({roomId, false})); - }); + if (auto r = room(roomId, JoinState::Join)) + { + Q_ASSERT(r->id() == roomId); + qCDebug(MAIN) << "Requested direct chat with" << userId + << "is already available as" << r->id(); + operation(r); + return; + } + if (auto ir = invitation(roomId)) + { + Q_ASSERT(ir->id() == roomId); + auto j = joinRoom(ir->id()); + connect(j, &BaseJob::success, this, [this,roomId,userId,operation] { + qCDebug(MAIN) << "Joined the already invited direct chat with" + << userId << "as" << roomId; + operation(room(roomId, JoinState::Join)); + }); + } + qCWarning(MAIN) << "Direct chat with" << userId << "known as room" + << roomId << "is not valid, discarding it"; + removeFromDirectChats(roomId); } + + auto j = createDirectChat(userId); + connect(j, &BaseJob::success, this, [this,j,userId,operation] { + qCDebug(MAIN) << "Direct chat with" << userId + << "has been created as" << j->roomId(); + operation(room(j->roomId(), JoinState::Join)); + }); } CreateRoomJob* Connection::createDirectChat(const QString& userId, diff --git a/connection.h b/connection.h index 6a5285f9..7c11c32d 100644 --- a/connection.h +++ b/connection.h @@ -261,6 +261,15 @@ namespace QMatrixClient */ Q_INVOKABLE void requestDirectChat(const QString& userId); + /** Run an operation in a direct chat with the user + * This method may return synchronously or asynchoronously depending + * on whether a direct chat room with the respective person exists + * already. Instead of emitting a signal it executes the passed + * function object with the direct chat room as its parameter. + */ + Q_INVOKABLE void doInDirectChat(const QString& userId, + std::function<void(Room*)> operation); + /** Create a direct chat with a single user, optional name and topic * A room will always be created, unlike in requestDirectChat. * It is advised to use requestDirectChat as a default way of getting |