diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-08-11 19:06:20 +0900 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-08-11 19:06:20 +0900 |
commit | b3559aa9ac082abe96da2bae084d0645b93fb658 (patch) | |
tree | e46f11654c5dbeddf0a68a23b1e34d93d0133f77 | |
parent | 082f233dc9f429d06548fba90c8129ef3f83a4b4 (diff) | |
download | libquotient-b3559aa9ac082abe96da2bae084d0645b93fb658.tar.gz libquotient-b3559aa9ac082abe96da2bae084d0645b93fb658.zip |
Reverse direct chats map
Speeds up lookup of user(s) in a direct chat room.
Also: "The other one's" avatar is used to set the avatar of direct
chats only, not any room with 2 participants.
-rw-r--r-- | lib/connection.cpp | 37 | ||||
-rw-r--r-- | lib/connection.h | 15 | ||||
-rw-r--r-- | lib/room.cpp | 17 | ||||
-rw-r--r-- | lib/room.h | 2 | ||||
-rw-r--r-- | lib/user.cpp | 4 | ||||
-rw-r--r-- | lib/user.h | 4 |
6 files changed, 47 insertions, 32 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index fcd73d04..29c044f1 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -89,6 +89,7 @@ class Connection::Private QVector<Room*> firstTimeRooms; QMap<QString, User*> userMap; DirectChatsMap directChats; + DirectChatUsersMap directChatUsers; std::unordered_map<QString, EventPtr> accountData; QString userId; @@ -356,6 +357,9 @@ void Connection::onSyncSuccess(SyncData &&data) { erase_if(d->directChats, [&usersToDCs] (auto it) { return !usersToDCs.contains(it.key()->id(), it.value()); }); + erase_if(d->directChatUsers, [&usersToDCs] (auto it) { + return !usersToDCs.contains(it.value()->id(), it.key()); + }); if (MAIN().isDebugEnabled()) for (auto it = removals.begin(); it != removals.end(); ++it) qCDebug(MAIN) << it.value() @@ -364,12 +368,14 @@ void Connection::onSyncSuccess(SyncData &&data) { DirectChatsMap additions; for (auto it = usersToDCs.begin(); it != usersToDCs.end(); ++it) { - if (const auto* u = user(it.key())) + if (auto* u = user(it.key())) { if (!d->directChats.contains(u, it.value())) { + Q_ASSERT(!d->directChatUsers.contains(it.value(), u)); additions.insert(u, it.value()); d->directChats.insert(u, it.value()); + d->directChatUsers.insert(it.value(), u); qCDebug(MAIN) << "Marked room" << it.value() << "as a direct chat with" << u->id(); } @@ -520,7 +526,7 @@ CreateRoomJob* Connection::createRoom(RoomVisibility visibility, void Connection::requestDirectChat(const QString& userId) { - if (const auto* u = user(userId)) + if (auto* u = user(userId)) requestDirectChat(u); else qCCritical(MAIN) @@ -528,7 +534,7 @@ void Connection::requestDirectChat(const QString& userId) << userId; } -void Connection::requestDirectChat(const User* u) +void Connection::requestDirectChat(User* u) { doInDirectChat(u, [this] (Room* r) { emit directChatAvailable(r); }); } @@ -536,7 +542,7 @@ void Connection::requestDirectChat(const User* u) void Connection::doInDirectChat(const QString& userId, const std::function<void(Room*)>& operation) { - if (const auto* u = user(userId)) + if (auto* u = user(userId)) doInDirectChat(u, operation); else qCCritical(MAIN) @@ -544,7 +550,7 @@ void Connection::doInDirectChat(const QString& userId, << userId; } -void Connection::doInDirectChat(const User* u, +void Connection::doInDirectChat(User* u, const std::function<void(Room*)>& operation) { Q_ASSERT(u); @@ -591,7 +597,10 @@ void Connection::doInDirectChat(const User* u, if (!removals.isEmpty()) { for (auto it = removals.cbegin(); it != removals.cend(); ++it) + { d->directChats.remove(it.key(), it.value()); + d->directChatUsers.remove(it.value(), it.key()); + } d->broadcastDirectChatUpdates({}, removals); } @@ -871,17 +880,19 @@ void Connection::Private::broadcastDirectChatUpdates(const DirectChatsMap& addit emit q->directChatsListChanged(additions, removals); } -void Connection::addToDirectChats(const Room* room, const User* user) +void Connection::addToDirectChats(const Room* room, User* user) { Q_ASSERT(room != nullptr && user != nullptr); if (d->directChats.contains(user, room->id())) return; + Q_ASSERT(!d->directChatUsers.contains(room->id(), user)); d->directChats.insert(user, room->id()); + d->directChatUsers.insert(room->id(), user); DirectChatsMap additions { { user, room->id() } }; d->broadcastDirectChatUpdates(additions, {}); } -void Connection::removeFromDirectChats(const QString& roomId, const User* user) +void Connection::removeFromDirectChats(const QString& roomId, User* user) { Q_ASSERT(!roomId.isEmpty()); if ((user != nullptr && !d->directChats.contains(user, roomId)) || @@ -893,22 +904,24 @@ void Connection::removeFromDirectChats(const QString& roomId, const User* user) { removals.insert(user, roomId); d->directChats.remove(user, roomId); - } - else + d->directChatUsers.remove(roomId, user); + } else { removals = erase_if(d->directChats, [&roomId] (auto it) { return it.value() == roomId; }); + d->directChatUsers.remove(roomId); + } d->broadcastDirectChatUpdates({}, removals); } bool Connection::isDirectChat(const QString& roomId) const { - return d->directChats.key(roomId) != nullptr; + return d->directChatUsers.contains(roomId); } -QList<const User*> Connection::directChatUsers(const Room* room) const +QList<User*> Connection::directChatUsers(const Room* room) const { Q_ASSERT(room != nullptr); - return d->directChats.keys(room->id()); + return d->directChatUsers.values(room->id()); } bool Connection::isIgnored(const User* user) const diff --git a/lib/connection.h b/lib/connection.h index e761acfd..9b253711 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -94,7 +94,12 @@ namespace QMatrixClient using user_factory_t = std::function<User*(Connection*, const QString&)>; + // Room ids, rather than room pointers, are used in the direct chat + // map types because the library keeps Invite rooms separate from + // rooms in Join and Leave state; and direct chats in account data + // are stored with no regard to their state. using DirectChatsMap = QMultiHash<const User*, QString>; + using DirectChatUsersMap = QMultiHash<QString, User*>; using IgnoredUsersList = IgnoredUsersEvent::content_type; using UsersToDevicesToEvents = @@ -171,7 +176,7 @@ namespace QMatrixClient * * \sa directChatsListChanged */ - void addToDirectChats(const Room* room, const User* user); + void addToDirectChats(const Room* room, User* user); /** Unmark the room from direct chats * This function removes the room id from direct chats either for @@ -184,7 +189,7 @@ namespace QMatrixClient * \sa directChatsListChanged */ void removeFromDirectChats(const QString& roomId, - const User* user = nullptr); + User* user = nullptr); /** Check whether the room id corresponds to a direct chat */ bool isDirectChat(const QString& roomId) const; @@ -196,7 +201,7 @@ namespace QMatrixClient * @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 */ - QList<const User*> directChatUsers(const Room* room) const; + QList<User*> directChatUsers(const Room* room) const; /** Check whether a particular user is in the ignore list */ bool isIgnored(const User* user) const; @@ -392,7 +397,7 @@ namespace QMatrixClient * * \sa directChatAvailable */ - void requestDirectChat(const User* u); + void requestDirectChat(User* u); /** Run an operation in a direct chat with the user * This method may return synchronously or asynchoronously depending @@ -409,7 +414,7 @@ namespace QMatrixClient * already. Instead of emitting a signal it executes the passed * function object with the direct chat room as its parameter. */ - void doInDirectChat(const User* u, + void doInDirectChat(User* u, const std::function<void(Room*)>& operation); /** Create a direct chat with a single user, optional name and topic diff --git a/lib/room.cpp b/lib/room.cpp index 27f54ddb..91fb6831 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -332,15 +332,12 @@ QImage Room::avatar(int width, int height) return d->avatar.get(connection(), width, height, [=] { emit avatarChanged(); }); - // Use the other side's avatar for 1:1's - if (d->membersMap.size() == 2) - { - auto theOtherOneIt = d->membersMap.begin(); - if (theOtherOneIt.value() == localUser()) - ++theOtherOneIt; - return (*theOtherOneIt)->avatar(width, height, this, - [=] { emit avatarChanged(); }); - } + // Use the first (excluding self) user's avatar for direct chats + const auto dcUsers = directChatUsers(); + for (auto* u: dcUsers) + if (u != localUser()) + return u->avatar(width, height, this, [=] { emit avatarChanged(); }); + return {}; } @@ -760,7 +757,7 @@ bool Room::isDirectChat() const return connection()->isDirectChat(id()); } -QList<const User*> Room::directChatUsers() const +QList<User*> Room::directChatUsers() const { return connection()->directChatUsers(this); } @@ -285,7 +285,7 @@ namespace QMatrixClient Q_INVOKABLE bool isDirectChat() const; /** Get the list of users this room is a direct chat with */ - QList<const User*> directChatUsers() const; + QList<User*> directChatUsers() const; Q_INVOKABLE QUrl urlToThumbnail(const QString& eventId); Q_INVOKABLE QUrl urlToDownload(const QString& eventId); diff --git a/lib/user.cpp b/lib/user.cpp index 12977b8a..b9f493c5 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -299,7 +299,7 @@ bool User::setAvatar(QIODevice* source) std::bind(&Private::setAvatarOnServer, d.data(), _1, this)); } -void User::requestDirectChat() const +void User::requestDirectChat() { connection()->requestDirectChat(this); } @@ -356,7 +356,7 @@ QImage User::avatar(int width, int height, const Room* room) } QImage User::avatar(int width, int height, const Room* room, - Avatar::get_callback_t callback) + const Avatar::get_callback_t& callback) { return avatarObject(room).get(d->connection, width, height, [=] { emit avatarChanged(this, room); callback(); }); @@ -100,7 +100,7 @@ namespace QMatrixClient Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight, const Room* room = nullptr); QImage avatar(int width, int height, const Room* room, - Avatar::get_callback_t callback); + const Avatar::get_callback_t& callback); QString avatarMediaId(const Room* room = nullptr) const; QUrl avatarUrl(const Room* room = nullptr) const; @@ -120,7 +120,7 @@ namespace QMatrixClient * The resulting chat is returned asynchronously via * Connection::directChatAvailable() */ - void requestDirectChat() const; + void requestDirectChat(); /** Add the user to the ignore list */ void ignore(); /** Remove the user from the ignore list */ |