aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--connection.cpp65
-rw-r--r--connection.h9
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