aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/connection.cpp21
-rw-r--r--lib/connection.h31
2 files changed, 38 insertions, 14 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index c17cbffc..18fa91e7 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -981,11 +981,12 @@ const ConnectionData* Connection::connectionData() const
return d->data.get();
}
-Room* Connection::provideRoom(const QString& id, JoinState joinState)
+Room* Connection::provideRoom(const QString& id, Omittable<JoinState> joinState)
{
// TODO: This whole function is a strong case for a RoomManager class.
Q_ASSERT_X(!id.isEmpty(), __FUNCTION__, "Empty room id");
+ // If joinState.omitted(), all joinState == comparisons below are false.
const auto roomKey = qMakePair(id, joinState == JoinState::Invite);
auto* room = d->roomMap.value(roomKey, nullptr);
if (room)
@@ -995,10 +996,19 @@ Room* Connection::provideRoom(const QString& id, JoinState joinState)
// and emit a signal. For Invite and Join, there's no such problem.
if (room->joinState() == joinState && joinState != JoinState::Leave)
return room;
+ } else if (joinState.omitted())
+ {
+ // No Join and Leave, maybe Invite?
+ room = d->roomMap.value({id, true}, nullptr);
+ if (room)
+ return room;
+ // No Invite either, setup a new room object below
}
- else
+
+ if (!room)
{
- room = roomFactory()(this, id, joinState);
+ room = roomFactory()(this, id,
+ joinState.omitted() ? JoinState::Join : joinState.value());
if (!room)
{
qCCritical(MAIN) << "Failed to create a room" << id;
@@ -1010,6 +1020,9 @@ Room* Connection::provideRoom(const QString& id, JoinState joinState)
this, &Connection::aboutToDeleteRoom);
emit newRoom(room);
}
+ if (joinState.omitted())
+ return room;
+
if (joinState == JoinState::Invite)
{
// prev is either Leave or nullptr
@@ -1018,7 +1031,7 @@ Room* Connection::provideRoom(const QString& id, JoinState joinState)
}
else
{
- room->setJoinState(joinState);
+ room->setJoinState(joinState.value());
// Preempt the Invite room (if any) with a room in Join/Leave state.
auto* prevInvite = d->roomMap.take({id, true});
if (joinState == JoinState::Join)
diff --git a/lib/connection.h b/lib/connection.h
index ff3e2028..f2e10488 100644
--- a/lib/connection.h
+++ b/lib/connection.h
@@ -670,16 +670,27 @@ namespace QMatrixClient
*/
const ConnectionData* connectionData() const;
- /**
- * @brief Find a (possibly new) Room object for the specified id
- * Use this method whenever you need to find a Room object in
- * the local list of rooms. Note that this does not interact with
- * the server; in particular, does not automatically create rooms
- * on the server.
- * @return a pointer to a Room object with the specified id; nullptr
- * if roomId is empty or roomFactory() failed to create a Room object.
- */
- Room* provideRoom(const QString& roomId, JoinState joinState);
+ /** Get a Room object for the given id in the given state
+ *
+ * Use this method when you need a Room object in the local list
+ * of rooms, with the given state. Note that this does not interact
+ * with the server; in particular, does not automatically create
+ * rooms on the server. This call performs necessary join state
+ * transitions; e.g., if it finds a room in Invite but
+ * `joinState == JoinState::Join` then the Invite room object
+ * will be deleted and a new room object with Join state created.
+ * In contrast, switching between Join and Leave happens within
+ * the same object.
+ * \param roomId room id (not alias!)
+ * \param joinState desired (target) join state of the room; if
+ * omitted, any state will be found and return unchanged, or a
+ * new Join room created.
+ * @return a pointer to a Room object with the specified id and the
+ * specified state; nullptr if roomId is empty or if roomFactory()
+ * failed to create a Room object.
+ */
+ Room* provideRoom(const QString& roomId,
+ Omittable<JoinState> joinState = none);
/**
* Completes loading sync data.