Skip to content

Commit

Permalink
Support RoomMember for direct chats
Browse files Browse the repository at this point in the history
  • Loading branch information
James Graham committed Dec 3, 2023
1 parent 7970eb9 commit f24205e
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 2 deletions.
42 changes: 40 additions & 2 deletions Quotient/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@ void Connection::Private::consumeAccountData(Events&& accountDataEvents)
remove_if(directChatUsers, [&remoteRemovals](auto it) {
return remoteRemovals.contains(it.value(), it.key());
});
remove_if(directChatMemberIds, [&remoteRemovals, this](auto it) {
return remoteRemovals.contains(q->user(it.value()), it.key());
});
// Remove from dcLocalRemovals what the server already has.
remove_if(dcLocalRemovals, [&remoteRemovals](auto it) {
return remoteRemovals.contains(it.key(), it.value());
Expand All @@ -597,6 +600,7 @@ void Connection::Private::consumeAccountData(Events&& accountDataEvents)
remoteAdditions.insert(u, it.value());
directChats.insert(u, it.value());
directChatUsers.insert(it.value(), u);
directChatMemberIds.insert(it.value(), it.key());
qCDebug(MAIN) << "Marked room" << it.value()
<< "as a direct chat with" << u->id();
}
Expand Down Expand Up @@ -905,6 +909,7 @@ void Connection::doInDirectChat(User* u,
d->directChats.remove(it.key(), it.value());
d->directChatUsers.remove(it.value(),
const_cast<User*>(it.key())); // FIXME
d->directChatMemberIds.remove(it.value(), it.key()->id());
}
emit directChatsListChanged({}, removals);
}
Expand Down Expand Up @@ -1265,6 +1270,7 @@ void Connection::addToDirectChats(const Room* room, const QString& userId)
return;
Q_ASSERT(!d->directChatUsers.contains(room->id(), u));
d->directChats.insert(u, room->id());
d->directChatMemberIds.insert(room->id(), userId);
d->directChatUsers.insert(room->id(), u);
d->dcLocalAdditions.insert(u, room->id());
emit directChatsListChanged({ { u, room->id() } }, {});
Expand All @@ -1277,11 +1283,36 @@ void Connection::addToDirectChats(const Room* room, User* user)
return;
Q_ASSERT(!d->directChatUsers.contains(room->id(), user));
d->directChats.insert(user, room->id());
d->directChatMemberIds.insert(room->id(), user->id());
d->directChatUsers.insert(room->id(), user);
d->dcLocalAdditions.insert(user, room->id());
emit directChatsListChanged({ { user, room->id() } }, {});
}

void Connection::removeFromDirectChats(const QString& roomId, const QString& userId)
{
Q_ASSERT(!roomId.isEmpty());
const auto u = user(userId);
if ((!userId.isEmpty() && !d->directChats.contains(u, roomId))
|| d->directChats.key(roomId) == nullptr)
return;

DirectChatsMap removals;
if (u != nullptr) {
d->directChats.remove(u, roomId);
d->directChatUsers.remove(roomId, u);
d->directChatMemberIds.remove(roomId, u->id());
removals.insert(u, roomId);
d->dcLocalRemovals.insert(u, roomId);
} else {
removals = remove_if(d->directChats,
[&roomId](auto it) { return it.value() == roomId; });
d->directChatUsers.remove(roomId);
d->dcLocalRemovals += removals;
}
emit directChatsListChanged({}, removals);
}

void Connection::removeFromDirectChats(const QString& roomId, User* user)
{
Q_ASSERT(!roomId.isEmpty());
Expand All @@ -1293,6 +1324,7 @@ void Connection::removeFromDirectChats(const QString& roomId, User* user)
if (user != nullptr) {
d->directChats.remove(user, roomId);
d->directChatUsers.remove(roomId, user);
d->directChatMemberIds.remove(roomId, user->id());
removals.insert(user, roomId);
d->dcLocalRemovals.insert(user, roomId);
} else {
Expand All @@ -1306,7 +1338,13 @@ void Connection::removeFromDirectChats(const QString& roomId, User* user)

bool Connection::isDirectChat(const QString& roomId) const
{
return d->directChatUsers.contains(roomId);
return d->directChatMemberIds.contains(roomId);
}

QList<QString> Connection::directChatMemberIds(const Room* room) const
{
Q_ASSERT(room != nullptr);
return d->directChatMemberIds.values(room->id());
}

QList<User*> Connection::directChatUsers(const Room* room) const
Expand Down Expand Up @@ -1438,7 +1476,7 @@ void Connection::setEncryptionDefault(bool useByDefault)
Private::encryptionDefault = useByDefault;
}
#endif
dialog

void Connection::setRoomFactory(room_factory_t f)
{
_roomFactory = std::move(f);
Expand Down
17 changes: 17 additions & 0 deletions Quotient/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,17 @@ class QUOTIENT_API Connection : public QObject {
//! \sa directChatsListChanged
void addToDirectChats(const Room* room, User* user);

//! \brief Unmark the room from direct chats
//!
//! This function removes the room id from direct chats either for
//! a specific \p user or for all users if \p userId is empty.
//! The room id is used to allow removal of, e.g., ids of forgotten
//! rooms; a Room object need not exist. Emits the signal
//! immediately, without waiting to complete synchronisation with
//! the server.
//! \sa directChatsListChanged
void removeFromDirectChats(const QString& roomId, const QString& userId = {});

//! \brief Unmark the room from direct chats
//!
//! This function removes the room id from direct chats either for
Expand All @@ -250,6 +261,12 @@ class QUOTIENT_API Connection : public QObject {
//! Get the whole map from users to direct chat rooms
DirectChatsMap directChats() const;

//! \brief Retrieve the list of member IDs the room is a direct chat with
//!
//! \return The list of member IDs for which this room is marked as
//! a direct chat; an empty list if the room is not a direct chat
QList<QString> directChatMemberIds(const Room* room) const;

//! \brief Retrieve the list of users the room is a direct chat with
//! \return The list of users for which this room is marked as
//! a direct chat; an empty list if the room is not a direct chat
Expand Down
1 change: 1 addition & 0 deletions Quotient/connection_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Q_DECL_HIDDEN Quotient::Connection::Private {
QVector<QString> pendingStateRoomIds;
QMap<QString, User*> userMap;
DirectChatsMap directChats;
QMultiHash<QString, QString> directChatMemberIds;
DirectChatUsersMap directChatUsers;
// The below two variables track local changes between sync completions.
// See https://github.com/quotient-im/libQuotient/wiki/Handling-direct-chat-events
Expand Down
12 changes: 12 additions & 0 deletions Quotient/room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,18 @@ bool Room::isServerNoticeRoom() const

bool Room::isDirectChat() const { return connection()->isDirectChat(id()); }

QList<RoomMember> Room::directChatMembers() const
{
auto memberIds = connection()->directChatMemberIds(this);
QList<RoomMember> members;
for (const auto& memberId : memberIds) {
if (currentState().contains<RoomMemberEvent>(memberId)) {
members.append(RoomMember(this, currentState().get<RoomMemberEvent>(memberId)));
}
}
return members;
}

QList<User*> Room::directChatUsers() const
{
return connection()->directChatUsers(this);
Expand Down
3 changes: 3 additions & 0 deletions Quotient/room.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,9 @@ class QUOTIENT_API Room : public QObject {
/// Check whether this room is a direct chat
Q_INVOKABLE bool isDirectChat() const;

/// Get the list of members this room is a direct chat with
QList<RoomMember> directChatMembers() const;

/// Get the list of users this room is a direct chat with
QList<User*> directChatUsers() const;

Expand Down

0 comments on commit f24205e

Please sign in to comment.