From 9159b9ce22efa4972792b5400fd384457c349caa Mon Sep 17 00:00:00 2001 From: Joseph Donofry Date: Tue, 11 Jun 2019 21:04:30 -0400 Subject: Initial Support for Rich Replies Add placeholder UI for showing replies in the text entry widget. Existing quoting capability has been removed (Temporarily), as it was replaced with the new reply capability. Replies sent from nheko do not currently appear correctly in the timeline (this will be fixed in a future commit). --- src/QuickSwitcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/QuickSwitcher.cpp') diff --git a/src/QuickSwitcher.cpp b/src/QuickSwitcher.cpp index eb79a427..f8f6c001 100644 --- a/src/QuickSwitcher.cpp +++ b/src/QuickSwitcher.cpp @@ -23,7 +23,7 @@ #include #include "QuickSwitcher.h" -#include "SuggestionsPopup.h" +#include "popups/SuggestionsPopup.h" RoomSearchInput::RoomSearchInput(QWidget *parent) : TextField(parent) -- cgit 1.5.1 From 5fc1f3bd678cca690268eafbb7e4595657a6e133 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 15 Dec 2019 02:56:04 +0100 Subject: Reduce overhead of Cache.h --- .gitignore | 1 + CMakeLists.txt | 2 +- src/AvatarProvider.cpp | 14 +- src/Cache.cpp | 561 +++++++++++++++++++++++++++++-- src/Cache.h | 744 +++++++++++++++-------------------------- src/Cache_p.h | 494 +++++++++++++++++++++++++++ src/ChatPage.cpp | 87 +++-- src/CommunitiesList.cpp | 4 +- src/MainWindow.cpp | 6 +- src/MxcImageProvider.cpp | 10 +- src/Olm.cpp | 27 +- src/QuickSwitcher.cpp | 3 +- src/TextInputWidget.cpp | 4 +- src/UserSettingsPage.cpp | 4 +- src/Utils.cpp | 2 +- src/Utils.h | 2 +- src/dialogs/MemberList.cpp | 4 +- src/dialogs/ReadReceipts.cpp | 2 +- src/dialogs/RoomSettings.cpp | 12 +- src/dialogs/RoomSettings.h | 4 +- src/dialogs/UserProfile.cpp | 8 +- src/popups/PopupItem.cpp | 6 +- src/popups/PopupItem.h | 3 +- src/popups/ReplyPopup.cpp | 1 + src/popups/ReplyPopup.h | 9 +- src/popups/SuggestionsPopup.h | 7 +- src/popups/UserMentions.cpp | 2 +- src/timeline/TimelineModel.cpp | 23 +- 28 files changed, 1403 insertions(+), 643 deletions(-) create mode 100644 src/Cache_p.h (limited to 'src/QuickSwitcher.cpp') diff --git a/.gitignore b/.gitignore index 2d772e58..6d178679 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ moc_*.cpp qrc_*.cpp ui_*.h *-build-* +/.clangd/ # QtCreator diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e86ee14..5c68d614 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -357,7 +357,7 @@ qt5_wrap_cpp(MOC_HEADERS src/notifications/Manager.h src/AvatarProvider.h - src/Cache.h + src/Cache_p.h src/ChatPage.h src/CommunitiesListItem.h src/CommunitiesList.h diff --git a/src/AvatarProvider.cpp b/src/AvatarProvider.cpp index 68b6901e..1587a9a1 100644 --- a/src/AvatarProvider.cpp +++ b/src/AvatarProvider.cpp @@ -35,9 +35,6 @@ resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback ca const auto cacheKey = avatarUrl + "_size_" + size; - if (!cache::client()) - return; - if (avatarUrl.isEmpty()) return; @@ -47,7 +44,7 @@ resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback ca return; } - auto data = cache::client()->image(avatarUrl); + auto data = cache::image(avatarUrl); if (!data.isNull()) { pixmap.loadFromData(data); avatar_cache.insert(cacheKey, pixmap); @@ -82,7 +79,7 @@ resolve(const QString &avatarUrl, int size, QObject *receiver, AvatarCallback ca return; } - cache::client()->saveImage(opts.mxc_url, res); + cache::saveImage(opts.mxc_url, res); emit proxy->avatarDownloaded(QByteArray(res.data(), res.size())); }); @@ -95,12 +92,7 @@ resolve(const QString &room_id, QObject *receiver, AvatarCallback callback) { - const auto key = QString("%1 %2").arg(room_id).arg(user_id); - const auto avatarUrl = Cache::avatarUrl(room_id, user_id); - const auto cacheKey = avatarUrl + "_size_" + size; - - if (!Cache::AvatarUrls.contains(key) || !cache::client()) - return; + const auto avatarUrl = cache::avatarUrl(room_id, user_id); resolve(avatarUrl, size, receiver, callback); } diff --git a/src/Cache.cpp b/src/Cache.cpp index ee53ffbd..79425fa1 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -30,6 +30,7 @@ #include #include "Cache.h" +#include "Cache_p.h" #include "Utils.h" //! Should be changed when a breaking change occurs in the cache format. @@ -89,29 +90,20 @@ namespace { std::unique_ptr instance_ = nullptr; } -namespace cache { -void -init(const QString &user_id) +int +numeric_key_comparison(const MDB_val *a, const MDB_val *b) { - qRegisterMetaType(); - qRegisterMetaType>(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); + auto lhs = std::stoull(std::string((char *)a->mv_data, a->mv_size)); + auto rhs = std::stoull(std::string((char *)b->mv_data, b->mv_size)); - instance_ = std::make_unique(user_id); -} + if (lhs < rhs) + return 1; + else if (lhs == rhs) + return 0; -Cache * -client() -{ - return instance_.get(); + return -1; } -} // namespace cache + Cache::Cache(const QString &userId, QObject *parent) : QObject{parent} @@ -2321,20 +2313,6 @@ from_json(const json &j, RoomInfo &info) info.tags = j.at("tags").get>(); } -int -numeric_key_comparison(const MDB_val *a, const MDB_val *b) -{ - auto lhs = std::stoull(std::string((char *)a->mv_data, a->mv_size)); - auto rhs = std::stoull(std::string((char *)b->mv_data, b->mv_size)); - - if (lhs < rhs) - return 1; - else if (lhs == rhs) - return 0; - - return -1; -} - void to_json(json &j, const ReadReceiptKey &key) { @@ -2407,3 +2385,520 @@ from_json(const nlohmann::json &obj, MegolmSessionIndex &msg) msg.session_id = obj.at("session_id"); msg.sender_key = obj.at("sender_key"); } + +namespace cache { +void +init(const QString &user_id) +{ + qRegisterMetaType(); + qRegisterMetaType>(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + + instance_ = std::make_unique(user_id); +} + +Cache * +client() +{ + return instance_.get(); +} + +std::string +displayName(const std::string &room_id, const std::string &user_id) +{ + return instance_->displayName(room_id, user_id); +} + +QString +displayName(const QString &room_id, const QString &user_id) +{ + return instance_->displayName(room_id, user_id); +} +QString +avatarUrl(const QString &room_id, const QString &user_id) +{ + return instance_->avatarUrl(room_id, user_id); +} + +QString +userColor(const QString &user_id) +{ + return instance_->userColor(user_id); +} + +void +removeDisplayName(const QString &room_id, const QString &user_id) +{ + instance_->removeDisplayName(room_id, user_id); +} +void +removeAvatarUrl(const QString &room_id, const QString &user_id) +{ + instance_->removeAvatarUrl(room_id, user_id); +} +void +removeUserColor(const QString &user_id) +{ + instance_->removeUserColor(user_id); +} + +void +insertDisplayName(const QString &room_id, const QString &user_id, const QString &display_name) +{ + instance_->insertDisplayName(room_id, user_id, display_name); +} +void +insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &avatar_url) +{ + instance_->insertAvatarUrl(room_id, user_id, avatar_url); +} +void +insertUserColor(const QString &user_id, const QString &color_name) +{ + instance_->insertUserColor(user_id, color_name); +} + +void +clearUserColors() +{ + instance_->clearUserColors(); +} + +//! Load saved data for the display names & avatars. +void +populateMembers() +{ + instance_->populateMembers(); +} + +std::vector +joinedRooms() +{ + return instance_->joinedRooms(); +} + +QMap +roomInfo(bool withInvites) +{ + return instance_->roomInfo(withInvites); +} +std::map +invites() +{ + return instance_->invites(); +} + +QString +getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb) +{ + return instance_->getRoomName(txn, statesdb, membersdb); +} +mtx::events::state::JoinRule +getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb) +{ + return instance_->getRoomJoinRule(txn, statesdb); +} +bool +getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb) +{ + return instance_->getRoomGuestAccess(txn, statesdb); +} +QString +getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb) +{ + return instance_->getRoomTopic(txn, statesdb); +} +QString +getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb, const QString &room_id) +{ + return instance_->getRoomAvatarUrl(txn, statesdb, membersdb, room_id); +} + +QString +getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb) +{ + return instance_->getRoomVersion(txn, statesdb); +} + +std::vector +getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len) +{ + return instance_->getMembers(room_id, startIndex, len); +} + +void +saveState(const mtx::responses::Sync &res) +{ + instance_->saveState(res); +} +bool +isInitialized() +{ + return instance_->isInitialized(); +} + +std::string +nextBatchToken() +{ + return instance_->nextBatchToken(); +} + +void +deleteData() +{ + instance_->deleteData(); +} + +void +removeInvite(lmdb::txn &txn, const std::string &room_id) +{ + instance_->removeInvite(txn, room_id); +} +void +removeInvite(const std::string &room_id) +{ + instance_->removeInvite(room_id); +} +void +removeRoom(lmdb::txn &txn, const std::string &roomid) +{ + instance_->removeRoom(txn, roomid); +} +void +removeRoom(const std::string &roomid) +{ + instance_->removeRoom(roomid); +} +void +removeRoom(const QString &roomid) +{ + instance_->removeRoom(roomid.toStdString()); +} +void +setup() +{ + instance_->setup(); +} + +bool +isFormatValid() +{ + return instance_->isFormatValid(); +} +void +setCurrentFormat() +{ + instance_->setCurrentFormat(); +} + +std::map +roomMessages() +{ + return instance_->roomMessages(); +} + +QMap +getTimelineMentions() +{ + return instance_->getTimelineMentions(); +} + +//! Retrieve all the user ids from a room. +std::vector +roomMembers(const std::string &room_id) +{ + return instance_->roomMembers(room_id); +} + +//! Check if the given user has power leve greater than than +//! lowest power level of the given events. +bool +hasEnoughPowerLevel(const std::vector &eventTypes, + const std::string &room_id, + const std::string &user_id) +{ + return instance_->hasEnoughPowerLevel(eventTypes, room_id, user_id); +} + +//! Retrieves the saved room avatar. +QImage +getRoomAvatar(const QString &id) +{ + return instance_->getRoomAvatar(id); +} +QImage +getRoomAvatar(const std::string &id) +{ + return instance_->getRoomAvatar(id); +} + +void +updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts) +{ + instance_->updateReadReceipt(txn, room_id, receipts); +} + +UserReceipts +readReceipts(const QString &event_id, const QString &room_id) +{ + return instance_->readReceipts(event_id, room_id); +} + +//! Filter the events that have at least one read receipt. +std::vector +filterReadEvents(const QString &room_id, + const std::vector &event_ids, + const std::string &excluded_user) +{ + return instance_->filterReadEvents(room_id, event_ids, excluded_user); +} +//! Add event for which we are expecting some read receipts. +void +addPendingReceipt(const QString &room_id, const QString &event_id) +{ + instance_->addPendingReceipt(room_id, event_id); +} +void +removePendingReceipt(lmdb::txn &txn, const std::string &room_id, const std::string &event_id) +{ + instance_->removePendingReceipt(txn, room_id, event_id); +} +void +notifyForReadReceipts(const std::string &room_id) +{ + instance_->notifyForReadReceipts(room_id); +} +std::vector +pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id) +{ + return instance_->pendingReceiptsEvents(txn, room_id); +} + +QByteArray +image(const QString &url) +{ + return instance_->image(url); +} +QByteArray +image(lmdb::txn &txn, const std::string &url) +{ + return instance_->image(txn, url); +} +void +saveImage(const std::string &url, const std::string &data) +{ + instance_->saveImage(url, data); +} +void +saveImage(const QString &url, const QByteArray &data) +{ + instance_->saveImage(url, data); +} + +RoomInfo +singleRoomInfo(const std::string &room_id) +{ + return instance_->singleRoomInfo(room_id); +} +std::vector +roomsWithStateUpdates(const mtx::responses::Sync &res) +{ + return instance_->roomsWithStateUpdates(res); +} +std::vector +roomsWithTagUpdates(const mtx::responses::Sync &res) +{ + return instance_->roomsWithTagUpdates(res); +} +std::map +getRoomInfo(const std::vector &rooms) +{ + return instance_->getRoomInfo(rooms); +} + +//! Calculates which the read status of a room. +//! Whether all the events in the timeline have been read. +bool +calculateRoomReadStatus(const std::string &room_id) +{ + return instance_->calculateRoomReadStatus(room_id); +} +void +calculateRoomReadStatus() +{ + instance_->calculateRoomReadStatus(); +} + +QVector +searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items) +{ + return instance_->searchUsers(room_id, query, max_items); +} +std::vector +searchRooms(const std::string &query, std::uint8_t max_items) +{ + return instance_->searchRooms(query, max_items); +} + +void +markSentNotification(const std::string &event_id) +{ + instance_->markSentNotification(event_id); +} +//! Removes an event from the sent notifications. +void +removeReadNotification(const std::string &event_id) +{ + instance_->removeReadNotification(event_id); +} +//! Check if we have sent a desktop notification for the given event id. +bool +isNotificationSent(const std::string &event_id) +{ + return instance_->isNotificationSent(event_id); +} + +//! Add all notifications containing a user mention to the db. +void +saveTimelineMentions(const mtx::responses::Notifications &res) +{ + instance_->saveTimelineMentions(res); +} + +//! Remove old unused data. +void +deleteOldMessages() +{ + instance_->deleteOldMessages(); +} +void +deleteOldData() noexcept +{ + instance_->deleteOldData(); +} +//! Retrieve all saved room ids. +std::vector +getRoomIds(lmdb::txn &txn) +{ + return instance_->getRoomIds(txn); +} + +//! Mark a room that uses e2e encryption. +void +setEncryptedRoom(lmdb::txn &txn, const std::string &room_id) +{ + instance_->setEncryptedRoom(txn, room_id); +} +bool +isRoomEncrypted(const std::string &room_id) +{ + return instance_->isRoomEncrypted(room_id); +} + +//! Check if a user is a member of the room. +bool +isRoomMember(const std::string &user_id, const std::string &room_id) +{ + return instance_->isRoomMember(user_id, room_id); +} + +// +// Outbound Megolm Sessions +// +void +saveOutboundMegolmSession(const std::string &room_id, + const OutboundGroupSessionData &data, + mtx::crypto::OutboundGroupSessionPtr session) +{ + instance_->saveOutboundMegolmSession(room_id, data, std::move(session)); +} +OutboundGroupSessionDataRef +getOutboundMegolmSession(const std::string &room_id) +{ + return instance_->getOutboundMegolmSession(room_id); +} +bool +outboundMegolmSessionExists(const std::string &room_id) noexcept +{ + return instance_->outboundMegolmSessionExists(room_id); +} +void +updateOutboundMegolmSession(const std::string &room_id, int message_index) +{ + instance_->updateOutboundMegolmSession(room_id, message_index); +} + +void +importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys) +{ + instance_->importSessionKeys(keys); +} +mtx::crypto::ExportedSessionKeys +exportSessionKeys() +{ + return instance_->exportSessionKeys(); +} + +// +// Inbound Megolm Sessions +// +void +saveInboundMegolmSession(const MegolmSessionIndex &index, + mtx::crypto::InboundGroupSessionPtr session) +{ + instance_->saveInboundMegolmSession(index, std::move(session)); +} +OlmInboundGroupSession * +getInboundMegolmSession(const MegolmSessionIndex &index) +{ + return instance_->getInboundMegolmSession(index); +} +bool +inboundMegolmSessionExists(const MegolmSessionIndex &index) +{ + return instance_->inboundMegolmSessionExists(index); +} + +// +// Olm Sessions +// +void +saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session) +{ + instance_->saveOlmSession(curve25519, std::move(session)); +} +std::vector +getOlmSessions(const std::string &curve25519) +{ + return instance_->getOlmSessions(curve25519); +} +std::optional +getOlmSession(const std::string &curve25519, const std::string &session_id) +{ + return instance_->getOlmSession(curve25519, session_id); +} + +void +saveOlmAccount(const std::string &pickled) +{ + instance_->saveOlmAccount(pickled); +} +std::string +restoreOlmAccount() +{ + return instance_->restoreOlmAccount(); +} + +void +restoreSessions() +{ + return instance_->restoreSessions(); +} +} // namespace cache + diff --git a/src/Cache.h b/src/Cache.h index 02346287..da4e2040 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -17,501 +17,285 @@ #pragma once -#include -#include - #include #include #include #include #include -#include #include -#include #include "CacheCryptoStructs.h" #include "CacheStructs.h" -#include "Logging.h" -#include "MatrixClient.h" -int -numeric_key_comparison(const MDB_val *a, const MDB_val *b); +namespace cache { +void +init(const QString &user_id); + +std::string +displayName(const std::string &room_id, const std::string &user_id); +QString +displayName(const QString &room_id, const QString &user_id); +QString +avatarUrl(const QString &room_id, const QString &user_id); +QString +userColor(const QString &user_id); + +void +removeDisplayName(const QString &room_id, const QString &user_id); +void +removeAvatarUrl(const QString &room_id, const QString &user_id); +void +removeUserColor(const QString &user_id); + +void +insertDisplayName(const QString &room_id, const QString &user_id, const QString &display_name); +void +insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &avatar_url); +void +insertUserColor(const QString &user_id, const QString &color_name); + +void +clearUserColors(); + +//! Load saved data for the display names & avatars. +void +populateMembers(); +std::vector +joinedRooms(); + +QMap +roomInfo(bool withInvites = true); +std::map +invites(); + +//! Calculate & return the name of the room. +QString +getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); +//! Get room join rules +mtx::events::state::JoinRule +getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb); +bool +getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb); +//! Retrieve the topic of the room if any. +QString +getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); +//! Retrieve the room avatar's url if any. +QString +getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb, const QString &room_id); +//! Retrieve the version of the room if any. +QString +getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb); + +//! Retrieve member info from a room. +std::vector +getMembers(const std::string &room_id, std::size_t startIndex = 0, std::size_t len = 30); -class Cache : public QObject +void +saveState(const mtx::responses::Sync &res); +bool +isInitialized(); + +std::string +nextBatchToken(); + +void +deleteData(); + +void +removeInvite(lmdb::txn &txn, const std::string &room_id); +void +removeInvite(const std::string &room_id); +void +removeRoom(lmdb::txn &txn, const std::string &roomid); +void +removeRoom(const std::string &roomid); +void +removeRoom(const QString &roomid); +void +setup(); + +bool +isFormatValid(); +void +setCurrentFormat(); + +std::map +roomMessages(); + +QMap +getTimelineMentions(); + +//! Retrieve all the user ids from a room. +std::vector +roomMembers(const std::string &room_id); + +//! Check if the given user has power leve greater than than +//! lowest power level of the given events. +bool +hasEnoughPowerLevel(const std::vector &eventTypes, + const std::string &room_id, + const std::string &user_id); + +//! Retrieves the saved room avatar. +QImage +getRoomAvatar(const QString &id); +QImage +getRoomAvatar(const std::string &id); + +//! Adds a user to the read list for the given event. +//! +//! There should be only one user id present in a receipt list per room. +//! The user id should be removed from any other lists. +using Receipts = std::map>; +void +updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts); + +//! Retrieve all the read receipts for the given event id and room. +//! +//! Returns a map of user ids and the time of the read receipt in milliseconds. +using UserReceipts = std::multimap>; +UserReceipts +readReceipts(const QString &event_id, const QString &room_id); + +//! Filter the events that have at least one read receipt. +std::vector +filterReadEvents(const QString &room_id, + const std::vector &event_ids, + const std::string &excluded_user); +//! Add event for which we are expecting some read receipts. +void +addPendingReceipt(const QString &room_id, const QString &event_id); +void +removePendingReceipt(lmdb::txn &txn, const std::string &room_id, const std::string &event_id); +void +notifyForReadReceipts(const std::string &room_id); +std::vector +pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id); + +QByteArray +image(const QString &url); +QByteArray +image(lmdb::txn &txn, const std::string &url); +inline QByteArray +image(const std::string &url) +{ + return image(QString::fromStdString(url)); +} +void +saveImage(const std::string &url, const std::string &data); +void +saveImage(const QString &url, const QByteArray &data); + +RoomInfo +singleRoomInfo(const std::string &room_id); +std::vector +roomsWithStateUpdates(const mtx::responses::Sync &res); +std::vector +roomsWithTagUpdates(const mtx::responses::Sync &res); +std::map +getRoomInfo(const std::vector &rooms); +inline std::map +roomUpdates(const mtx::responses::Sync &sync) { - Q_OBJECT - -public: - Cache(const QString &userId, QObject *parent = nullptr); - - static QHash DisplayNames; - static QHash AvatarUrls; - static QHash UserColors; - - static std::string displayName(const std::string &room_id, const std::string &user_id); - static QString displayName(const QString &room_id, const QString &user_id); - static QString avatarUrl(const QString &room_id, const QString &user_id); - static QString userColor(const QString &user_id); - - static void removeDisplayName(const QString &room_id, const QString &user_id); - static void removeAvatarUrl(const QString &room_id, const QString &user_id); - static void removeUserColor(const QString &user_id); - - static void insertDisplayName(const QString &room_id, - const QString &user_id, - const QString &display_name); - static void insertAvatarUrl(const QString &room_id, - const QString &user_id, - const QString &avatar_url); - static void insertUserColor(const QString &user_id, const QString &color_name); - - static void clearUserColors(); - - //! Load saved data for the display names & avatars. - void populateMembers(); - std::vector joinedRooms(); - - QMap roomInfo(bool withInvites = true); - std::map invites(); - - //! Calculate & return the name of the room. - QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); - //! Get room join rules - mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb); - bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb); - //! Retrieve the topic of the room if any. - QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); - //! Retrieve the room avatar's url if any. - QString getRoomAvatarUrl(lmdb::txn &txn, - lmdb::dbi &statesdb, - lmdb::dbi &membersdb, - const QString &room_id); - //! Retrieve the version of the room if any. - QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb); - - //! Retrieve member info from a room. - std::vector getMembers(const std::string &room_id, - std::size_t startIndex = 0, - std::size_t len = 30); - - void saveState(const mtx::responses::Sync &res); - bool isInitialized() const; - - std::string nextBatchToken() const; - - void deleteData(); - - void removeInvite(lmdb::txn &txn, const std::string &room_id); - void removeInvite(const std::string &room_id); - void removeRoom(lmdb::txn &txn, const std::string &roomid); - void removeRoom(const std::string &roomid); - void removeRoom(const QString &roomid) { removeRoom(roomid.toStdString()); }; - void setup(); - - bool isFormatValid(); - void setCurrentFormat(); - - std::map roomMessages(); - - QMap getTimelineMentions(); - - //! Retrieve all the user ids from a room. - std::vector roomMembers(const std::string &room_id); - - //! Check if the given user has power leve greater than than - //! lowest power level of the given events. - bool hasEnoughPowerLevel(const std::vector &eventTypes, - const std::string &room_id, - const std::string &user_id); - - //! Retrieves the saved room avatar. - QImage getRoomAvatar(const QString &id); - QImage getRoomAvatar(const std::string &id); - - //! Adds a user to the read list for the given event. - //! - //! There should be only one user id present in a receipt list per room. - //! The user id should be removed from any other lists. - using Receipts = std::map>; - void updateReadReceipt(lmdb::txn &txn, - const std::string &room_id, - const Receipts &receipts); - - //! Retrieve all the read receipts for the given event id and room. - //! - //! Returns a map of user ids and the time of the read receipt in milliseconds. - using UserReceipts = std::multimap>; - UserReceipts readReceipts(const QString &event_id, const QString &room_id); - - //! Filter the events that have at least one read receipt. - std::vector filterReadEvents(const QString &room_id, - const std::vector &event_ids, - const std::string &excluded_user); - //! Add event for which we are expecting some read receipts. - void addPendingReceipt(const QString &room_id, const QString &event_id); - void removePendingReceipt(lmdb::txn &txn, - const std::string &room_id, - const std::string &event_id); - void notifyForReadReceipts(const std::string &room_id); - std::vector pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id); - - QByteArray image(const QString &url) const; - QByteArray image(lmdb::txn &txn, const std::string &url) const; - QByteArray image(const std::string &url) const - { - return image(QString::fromStdString(url)); - } - void saveImage(const std::string &url, const std::string &data); - void saveImage(const QString &url, const QByteArray &data); - - RoomInfo singleRoomInfo(const std::string &room_id); - std::vector roomsWithStateUpdates(const mtx::responses::Sync &res); - std::vector roomsWithTagUpdates(const mtx::responses::Sync &res); - std::map getRoomInfo(const std::vector &rooms); - std::map roomUpdates(const mtx::responses::Sync &sync) - { - return getRoomInfo(roomsWithStateUpdates(sync)); - } - std::map roomTagUpdates(const mtx::responses::Sync &sync) - { - return getRoomInfo(roomsWithTagUpdates(sync)); - } - - //! Calculates which the read status of a room. - //! Whether all the events in the timeline have been read. - bool calculateRoomReadStatus(const std::string &room_id); - void calculateRoomReadStatus(); - - QVector searchUsers(const std::string &room_id, - const std::string &query, - std::uint8_t max_items = 5); - std::vector searchRooms(const std::string &query, - std::uint8_t max_items = 5); - - void markSentNotification(const std::string &event_id); - //! Removes an event from the sent notifications. - void removeReadNotification(const std::string &event_id); - //! Check if we have sent a desktop notification for the given event id. - bool isNotificationSent(const std::string &event_id); - - //! Add all notifications containing a user mention to the db. - void saveTimelineMentions(const mtx::responses::Notifications &res); - - //! Remove old unused data. - void deleteOldMessages(); - void deleteOldData() noexcept; - //! Retrieve all saved room ids. - std::vector getRoomIds(lmdb::txn &txn); - - //! Mark a room that uses e2e encryption. - void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id); - bool isRoomEncrypted(const std::string &room_id); - - //! Save the public keys for a device. - void saveDeviceKeys(const std::string &device_id); - void getDeviceKeys(const std::string &device_id); - - //! Save the device list for a user. - void setDeviceList(const std::string &user_id, const std::vector &devices); - std::vector getDeviceList(const std::string &user_id); - - //! Check if a user is a member of the room. - bool isRoomMember(const std::string &user_id, const std::string &room_id); - - // - // Outbound Megolm Sessions - // - void saveOutboundMegolmSession(const std::string &room_id, - const OutboundGroupSessionData &data, - mtx::crypto::OutboundGroupSessionPtr session); - OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id); - bool outboundMegolmSessionExists(const std::string &room_id) noexcept; - void updateOutboundMegolmSession(const std::string &room_id, int message_index); - - void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys); - mtx::crypto::ExportedSessionKeys exportSessionKeys(); - - // - // Inbound Megolm Sessions - // - void saveInboundMegolmSession(const MegolmSessionIndex &index, - mtx::crypto::InboundGroupSessionPtr session); - OlmInboundGroupSession *getInboundMegolmSession(const MegolmSessionIndex &index); - bool inboundMegolmSessionExists(const MegolmSessionIndex &index); - - // - // Olm Sessions - // - void saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session); - std::vector getOlmSessions(const std::string &curve25519); - std::optional getOlmSession(const std::string &curve25519, - const std::string &session_id); - - void saveOlmAccount(const std::string &pickled); - std::string restoreOlmAccount(); - - void restoreSessions(); - - OlmSessionStorage session_storage; - -signals: - void newReadReceipts(const QString &room_id, const std::vector &event_ids); - void roomReadStatus(const std::map &status); - -private: - //! Save an invited room. - void saveInvite(lmdb::txn &txn, - lmdb::dbi &statesdb, - lmdb::dbi &membersdb, - const mtx::responses::InvitedRoom &room); - - //! Add a notification containing a user mention to the db. - void saveTimelineMentions(lmdb::txn &txn, - const std::string &room_id, - const QList &res); - - //! Get timeline items that a user was mentions in for a given room - mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn, - const std::string &room_id); - - QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); - QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); - QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); - - DescInfo getLastMessageInfo(lmdb::txn &txn, const std::string &room_id); - void saveTimelineMessages(lmdb::txn &txn, - const std::string &room_id, - const mtx::responses::Timeline &res); - - mtx::responses::Timeline getTimelineMessages(lmdb::txn &txn, const std::string &room_id); - - //! Remove a room from the cache. - // void removeLeftRoom(lmdb::txn &txn, const std::string &room_id); - template - void saveStateEvents(lmdb::txn &txn, - const lmdb::dbi &statesdb, - const lmdb::dbi &membersdb, - const std::string &room_id, - const std::vector &events) - { - for (const auto &e : events) - saveStateEvent(txn, statesdb, membersdb, room_id, e); - } - - template - void saveStateEvent(lmdb::txn &txn, - const lmdb::dbi &statesdb, - const lmdb::dbi &membersdb, - const std::string &room_id, - const T &event) - { - using namespace mtx::events; - using namespace mtx::events::state; - - if (auto e = std::get_if>(&event); e != nullptr) { - switch (e->content.membership) { - // - // We only keep users with invite or join membership. - // - case Membership::Invite: - case Membership::Join: { - auto display_name = e->content.display_name.empty() - ? e->state_key - : e->content.display_name; - - // Lightweight representation of a member. - MemberInfo tmp{display_name, e->content.avatar_url}; - - lmdb::dbi_put(txn, - membersdb, - lmdb::val(e->state_key), - lmdb::val(json(tmp).dump())); - - insertDisplayName(QString::fromStdString(room_id), - QString::fromStdString(e->state_key), - QString::fromStdString(display_name)); - - insertAvatarUrl(QString::fromStdString(room_id), - QString::fromStdString(e->state_key), - QString::fromStdString(e->content.avatar_url)); - - break; - } - default: { - lmdb::dbi_del( - txn, membersdb, lmdb::val(e->state_key), lmdb::val("")); - - removeDisplayName(QString::fromStdString(room_id), - QString::fromStdString(e->state_key)); - removeAvatarUrl(QString::fromStdString(room_id), - QString::fromStdString(e->state_key)); - - break; - } - } - - return; - } else if (std::holds_alternative>(event)) { - setEncryptedRoom(txn, room_id); - return; - } - - if (!isStateEvent(event)) - return; - - std::visit( - [&txn, &statesdb](auto e) { - lmdb::dbi_put( - txn, statesdb, lmdb::val(to_string(e.type)), lmdb::val(json(e).dump())); - }, - event); - } - - template - bool isStateEvent(const T &e) - { - using namespace mtx::events; - using namespace mtx::events::state; - - return std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e); - } - - template - bool containsStateUpdates(const T &e) - { - using namespace mtx::events; - using namespace mtx::events::state; - - return std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e); - } - - bool containsStateUpdates(const mtx::events::collections::StrippedEvents &e) - { - using namespace mtx::events; - using namespace mtx::events::state; - - return std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e) || - std::holds_alternative>(e); - } - - void saveInvites(lmdb::txn &txn, - const std::map &rooms); - - //! Sends signals for the rooms that are removed. - void removeLeftRooms(lmdb::txn &txn, - const std::map &rooms) - { - for (const auto &room : rooms) { - removeRoom(txn, room.first); - - // Clean up leftover invites. - removeInvite(txn, room.first); - } - } - - lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn) - { - return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE); - } - - lmdb::dbi getMessagesDb(lmdb::txn &txn, const std::string &room_id) - { - auto db = - lmdb::dbi::open(txn, std::string(room_id + "/messages").c_str(), MDB_CREATE); - lmdb::dbi_set_compare(txn, db, numeric_key_comparison); - - return db; - } - - lmdb::dbi getInviteStatesDb(lmdb::txn &txn, const std::string &room_id) - { - return lmdb::dbi::open( - txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE); - } - - lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id) - { - return lmdb::dbi::open( - txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE); - } - - lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id) - { - return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE); - } - - lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id) - { - return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE); - } - - lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id) - { - return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE); - } - - //! Retrieves or creates the database that stores the open OLM sessions between our device - //! and the given curve25519 key which represents another device. - //! - //! Each entry is a map from the session_id to the pickled representation of the session. - lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key) - { - return lmdb::dbi::open( - txn, std::string("olm_sessions/" + curve25519_key).c_str(), MDB_CREATE); - } - - QString getDisplayName(const mtx::events::StateEvent &event) - { - if (!event.content.display_name.empty()) - return QString::fromStdString(event.content.display_name); - - return QString::fromStdString(event.state_key); - } - - void setNextBatchToken(lmdb::txn &txn, const std::string &token); - void setNextBatchToken(lmdb::txn &txn, const QString &token); - - lmdb::env env_; - lmdb::dbi syncStateDb_; - lmdb::dbi roomsDb_; - lmdb::dbi invitesDb_; - lmdb::dbi mediaDb_; - lmdb::dbi readReceiptsDb_; - lmdb::dbi notificationsDb_; - - lmdb::dbi devicesDb_; - lmdb::dbi deviceKeysDb_; - - lmdb::dbi inboundMegolmSessionDb_; - lmdb::dbi outboundMegolmSessionDb_; - - QString localUserId_; - QString cacheDirectory_; -}; + return getRoomInfo(roomsWithStateUpdates(sync)); +} +inline std::map +roomTagUpdates(const mtx::responses::Sync &sync) +{ + return getRoomInfo(roomsWithTagUpdates(sync)); +} -namespace cache { +//! Calculates which the read status of a room. +//! Whether all the events in the timeline have been read. +bool +calculateRoomReadStatus(const std::string &room_id); void -init(const QString &user_id); +calculateRoomReadStatus(); + +QVector +searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items = 5); +std::vector +searchRooms(const std::string &query, std::uint8_t max_items = 5); + +void +markSentNotification(const std::string &event_id); +//! Removes an event from the sent notifications. +void +removeReadNotification(const std::string &event_id); +//! Check if we have sent a desktop notification for the given event id. +bool +isNotificationSent(const std::string &event_id); + +//! Add all notifications containing a user mention to the db. +void +saveTimelineMentions(const mtx::responses::Notifications &res); -Cache * -client(); +//! Remove old unused data. +void +deleteOldMessages(); +void +deleteOldData() noexcept; +//! Retrieve all saved room ids. +std::vector +getRoomIds(lmdb::txn &txn); + +//! Mark a room that uses e2e encryption. +void +setEncryptedRoom(lmdb::txn &txn, const std::string &room_id); +bool +isRoomEncrypted(const std::string &room_id); + +//! Check if a user is a member of the room. +bool +isRoomMember(const std::string &user_id, const std::string &room_id); + +// +// Outbound Megolm Sessions +// +void +saveOutboundMegolmSession(const std::string &room_id, + const OutboundGroupSessionData &data, + mtx::crypto::OutboundGroupSessionPtr session); +OutboundGroupSessionDataRef +getOutboundMegolmSession(const std::string &room_id); +bool +outboundMegolmSessionExists(const std::string &room_id) noexcept; +void +updateOutboundMegolmSession(const std::string &room_id, int message_index); + +void +importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys); +mtx::crypto::ExportedSessionKeys +exportSessionKeys(); + +// +// Inbound Megolm Sessions +// +void +saveInboundMegolmSession(const MegolmSessionIndex &index, + mtx::crypto::InboundGroupSessionPtr session); +OlmInboundGroupSession * +getInboundMegolmSession(const MegolmSessionIndex &index); +bool +inboundMegolmSessionExists(const MegolmSessionIndex &index); + +// +// Olm Sessions +// +void +saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session); +std::vector +getOlmSessions(const std::string &curve25519); +std::optional +getOlmSession(const std::string &curve25519, const std::string &session_id); + +void +saveOlmAccount(const std::string &pickled); +std::string +restoreOlmAccount(); + +void +restoreSessions(); } diff --git a/src/Cache_p.h b/src/Cache_p.h new file mode 100644 index 00000000..47dd945a --- /dev/null +++ b/src/Cache_p.h @@ -0,0 +1,494 @@ +/* + * nheko Copyright (C) 2019 The nheko authors + * nheko Copyright (C) 2017 Konstantinos Sideris + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "CacheCryptoStructs.h" +#include "CacheStructs.h" +#include "Logging.h" +#include "MatrixClient.h" + +int +numeric_key_comparison(const MDB_val *a, const MDB_val *b); + +class Cache : public QObject +{ + Q_OBJECT + +public: + Cache(const QString &userId, QObject *parent = nullptr); + + static std::string displayName(const std::string &room_id, const std::string &user_id); + static QString displayName(const QString &room_id, const QString &user_id); + static QString avatarUrl(const QString &room_id, const QString &user_id); + static QString userColor(const QString &user_id); + + static void removeDisplayName(const QString &room_id, const QString &user_id); + static void removeAvatarUrl(const QString &room_id, const QString &user_id); + static void removeUserColor(const QString &user_id); + + static void insertDisplayName(const QString &room_id, + const QString &user_id, + const QString &display_name); + static void insertAvatarUrl(const QString &room_id, + const QString &user_id, + const QString &avatar_url); + static void insertUserColor(const QString &user_id, const QString &color_name); + + static void clearUserColors(); + + //! Load saved data for the display names & avatars. + void populateMembers(); + std::vector joinedRooms(); + + QMap roomInfo(bool withInvites = true); + std::map invites(); + + //! Calculate & return the name of the room. + QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); + //! Get room join rules + mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb); + bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb); + //! Retrieve the topic of the room if any. + QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); + //! Retrieve the room avatar's url if any. + QString getRoomAvatarUrl(lmdb::txn &txn, + lmdb::dbi &statesdb, + lmdb::dbi &membersdb, + const QString &room_id); + //! Retrieve the version of the room if any. + QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb); + + //! Retrieve member info from a room. + std::vector getMembers(const std::string &room_id, + std::size_t startIndex = 0, + std::size_t len = 30); + + void saveState(const mtx::responses::Sync &res); + bool isInitialized() const; + + std::string nextBatchToken() const; + + void deleteData(); + + void removeInvite(lmdb::txn &txn, const std::string &room_id); + void removeInvite(const std::string &room_id); + void removeRoom(lmdb::txn &txn, const std::string &roomid); + void removeRoom(const std::string &roomid); + void setup(); + + bool isFormatValid(); + void setCurrentFormat(); + + std::map roomMessages(); + + QMap getTimelineMentions(); + + //! Retrieve all the user ids from a room. + std::vector roomMembers(const std::string &room_id); + + //! Check if the given user has power leve greater than than + //! lowest power level of the given events. + bool hasEnoughPowerLevel(const std::vector &eventTypes, + const std::string &room_id, + const std::string &user_id); + + //! Retrieves the saved room avatar. + QImage getRoomAvatar(const QString &id); + QImage getRoomAvatar(const std::string &id); + + //! Adds a user to the read list for the given event. + //! + //! There should be only one user id present in a receipt list per room. + //! The user id should be removed from any other lists. + using Receipts = std::map>; + void updateReadReceipt(lmdb::txn &txn, + const std::string &room_id, + const Receipts &receipts); + + //! Retrieve all the read receipts for the given event id and room. + //! + //! Returns a map of user ids and the time of the read receipt in milliseconds. + using UserReceipts = std::multimap>; + UserReceipts readReceipts(const QString &event_id, const QString &room_id); + + //! Filter the events that have at least one read receipt. + std::vector filterReadEvents(const QString &room_id, + const std::vector &event_ids, + const std::string &excluded_user); + //! Add event for which we are expecting some read receipts. + void addPendingReceipt(const QString &room_id, const QString &event_id); + void removePendingReceipt(lmdb::txn &txn, + const std::string &room_id, + const std::string &event_id); + void notifyForReadReceipts(const std::string &room_id); + std::vector pendingReceiptsEvents(lmdb::txn &txn, const std::string &room_id); + + QByteArray image(const QString &url) const; + QByteArray image(lmdb::txn &txn, const std::string &url) const; + void saveImage(const std::string &url, const std::string &data); + void saveImage(const QString &url, const QByteArray &data); + + RoomInfo singleRoomInfo(const std::string &room_id); + std::vector roomsWithStateUpdates(const mtx::responses::Sync &res); + std::vector roomsWithTagUpdates(const mtx::responses::Sync &res); + std::map getRoomInfo(const std::vector &rooms); + + //! Calculates which the read status of a room. + //! Whether all the events in the timeline have been read. + bool calculateRoomReadStatus(const std::string &room_id); + void calculateRoomReadStatus(); + + QVector searchUsers(const std::string &room_id, + const std::string &query, + std::uint8_t max_items = 5); + std::vector searchRooms(const std::string &query, + std::uint8_t max_items = 5); + + void markSentNotification(const std::string &event_id); + //! Removes an event from the sent notifications. + void removeReadNotification(const std::string &event_id); + //! Check if we have sent a desktop notification for the given event id. + bool isNotificationSent(const std::string &event_id); + + //! Add all notifications containing a user mention to the db. + void saveTimelineMentions(const mtx::responses::Notifications &res); + + //! Remove old unused data. + void deleteOldMessages(); + void deleteOldData() noexcept; + //! Retrieve all saved room ids. + std::vector getRoomIds(lmdb::txn &txn); + + //! Mark a room that uses e2e encryption. + void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id); + bool isRoomEncrypted(const std::string &room_id); + + //! Check if a user is a member of the room. + bool isRoomMember(const std::string &user_id, const std::string &room_id); + + // + // Outbound Megolm Sessions + // + void saveOutboundMegolmSession(const std::string &room_id, + const OutboundGroupSessionData &data, + mtx::crypto::OutboundGroupSessionPtr session); + OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id); + bool outboundMegolmSessionExists(const std::string &room_id) noexcept; + void updateOutboundMegolmSession(const std::string &room_id, int message_index); + + void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys); + mtx::crypto::ExportedSessionKeys exportSessionKeys(); + + // + // Inbound Megolm Sessions + // + void saveInboundMegolmSession(const MegolmSessionIndex &index, + mtx::crypto::InboundGroupSessionPtr session); + OlmInboundGroupSession *getInboundMegolmSession(const MegolmSessionIndex &index); + bool inboundMegolmSessionExists(const MegolmSessionIndex &index); + + // + // Olm Sessions + // + void saveOlmSession(const std::string &curve25519, mtx::crypto::OlmSessionPtr session); + std::vector getOlmSessions(const std::string &curve25519); + std::optional getOlmSession(const std::string &curve25519, + const std::string &session_id); + + void saveOlmAccount(const std::string &pickled); + std::string restoreOlmAccount(); + + void restoreSessions(); + +signals: + void newReadReceipts(const QString &room_id, const std::vector &event_ids); + void roomReadStatus(const std::map &status); + +private: + //! Save an invited room. + void saveInvite(lmdb::txn &txn, + lmdb::dbi &statesdb, + lmdb::dbi &membersdb, + const mtx::responses::InvitedRoom &room); + + //! Add a notification containing a user mention to the db. + void saveTimelineMentions(lmdb::txn &txn, + const std::string &room_id, + const QList &res); + + //! Get timeline items that a user was mentions in for a given room + mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn, + const std::string &room_id); + + QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); + QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); + QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); + + DescInfo getLastMessageInfo(lmdb::txn &txn, const std::string &room_id); + void saveTimelineMessages(lmdb::txn &txn, + const std::string &room_id, + const mtx::responses::Timeline &res); + + mtx::responses::Timeline getTimelineMessages(lmdb::txn &txn, const std::string &room_id); + + //! Remove a room from the cache. + // void removeLeftRoom(lmdb::txn &txn, const std::string &room_id); + template + void saveStateEvents(lmdb::txn &txn, + const lmdb::dbi &statesdb, + const lmdb::dbi &membersdb, + const std::string &room_id, + const std::vector &events) + { + for (const auto &e : events) + saveStateEvent(txn, statesdb, membersdb, room_id, e); + } + + template + void saveStateEvent(lmdb::txn &txn, + const lmdb::dbi &statesdb, + const lmdb::dbi &membersdb, + const std::string &room_id, + const T &event) + { + using namespace mtx::events; + using namespace mtx::events::state; + + if (auto e = std::get_if>(&event); e != nullptr) { + switch (e->content.membership) { + // + // We only keep users with invite or join membership. + // + case Membership::Invite: + case Membership::Join: { + auto display_name = e->content.display_name.empty() + ? e->state_key + : e->content.display_name; + + // Lightweight representation of a member. + MemberInfo tmp{display_name, e->content.avatar_url}; + + lmdb::dbi_put(txn, + membersdb, + lmdb::val(e->state_key), + lmdb::val(json(tmp).dump())); + + insertDisplayName(QString::fromStdString(room_id), + QString::fromStdString(e->state_key), + QString::fromStdString(display_name)); + + insertAvatarUrl(QString::fromStdString(room_id), + QString::fromStdString(e->state_key), + QString::fromStdString(e->content.avatar_url)); + + break; + } + default: { + lmdb::dbi_del( + txn, membersdb, lmdb::val(e->state_key), lmdb::val("")); + + removeDisplayName(QString::fromStdString(room_id), + QString::fromStdString(e->state_key)); + removeAvatarUrl(QString::fromStdString(room_id), + QString::fromStdString(e->state_key)); + + break; + } + } + + return; + } else if (std::holds_alternative>(event)) { + setEncryptedRoom(txn, room_id); + return; + } + + if (!isStateEvent(event)) + return; + + std::visit( + [&txn, &statesdb](auto e) { + lmdb::dbi_put( + txn, statesdb, lmdb::val(to_string(e.type)), lmdb::val(json(e).dump())); + }, + event); + } + + template + bool isStateEvent(const T &e) + { + using namespace mtx::events; + using namespace mtx::events::state; + + return std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e); + } + + template + bool containsStateUpdates(const T &e) + { + using namespace mtx::events; + using namespace mtx::events::state; + + return std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e); + } + + bool containsStateUpdates(const mtx::events::collections::StrippedEvents &e) + { + using namespace mtx::events; + using namespace mtx::events::state; + + return std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e) || + std::holds_alternative>(e); + } + + void saveInvites(lmdb::txn &txn, + const std::map &rooms); + + //! Sends signals for the rooms that are removed. + void removeLeftRooms(lmdb::txn &txn, + const std::map &rooms) + { + for (const auto &room : rooms) { + removeRoom(txn, room.first); + + // Clean up leftover invites. + removeInvite(txn, room.first); + } + } + + lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn) + { + return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE); + } + + lmdb::dbi getMessagesDb(lmdb::txn &txn, const std::string &room_id) + { + auto db = + lmdb::dbi::open(txn, std::string(room_id + "/messages").c_str(), MDB_CREATE); + lmdb::dbi_set_compare(txn, db, numeric_key_comparison); + + return db; + } + + lmdb::dbi getInviteStatesDb(lmdb::txn &txn, const std::string &room_id) + { + return lmdb::dbi::open( + txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE); + } + + lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id) + { + return lmdb::dbi::open( + txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE); + } + + lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id) + { + return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE); + } + + lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id) + { + return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE); + } + + lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id) + { + return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE); + } + + //! Retrieves or creates the database that stores the open OLM sessions between our device + //! and the given curve25519 key which represents another device. + //! + //! Each entry is a map from the session_id to the pickled representation of the session. + lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key) + { + return lmdb::dbi::open( + txn, std::string("olm_sessions/" + curve25519_key).c_str(), MDB_CREATE); + } + + QString getDisplayName(const mtx::events::StateEvent &event) + { + if (!event.content.display_name.empty()) + return QString::fromStdString(event.content.display_name); + + return QString::fromStdString(event.state_key); + } + + void setNextBatchToken(lmdb::txn &txn, const std::string &token); + void setNextBatchToken(lmdb::txn &txn, const QString &token); + + lmdb::env env_; + lmdb::dbi syncStateDb_; + lmdb::dbi roomsDb_; + lmdb::dbi invitesDb_; + lmdb::dbi mediaDb_; + lmdb::dbi readReceiptsDb_; + lmdb::dbi notificationsDb_; + + lmdb::dbi devicesDb_; + lmdb::dbi deviceKeysDb_; + + lmdb::dbi inboundMegolmSessionDb_; + lmdb::dbi outboundMegolmSessionDb_; + + QString localUserId_; + QString cacheDirectory_; + + static QHash DisplayNames; + static QHash AvatarUrls; + static QHash UserColors; + + OlmSessionStorage session_storage; +}; + +namespace cache { +Cache * +client(); +} diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index c496acab..ad07efdd 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -22,6 +22,7 @@ #include "AvatarProvider.h" #include "Cache.h" +#include "Cache_p.h" #include "ChatPage.h" #include "Logging.h" #include "MainWindow.h" @@ -319,7 +320,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) auto bin = dev->peek(dev->size()); auto payload = std::string(bin.data(), bin.size()); std::optional encryptedFile; - if (cache::client()->isRoomEncrypted(current_room_.toStdString())) { + if (cache::isRoomEncrypted(current_room_.toStdString())) { mtx::crypto::BinaryBuf buf; std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload); payload = mtx::crypto::to_string(buf); @@ -408,7 +409,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) this, [](const mtx::responses::Notifications ¬if) { try { - cache::client()->saveTimelineMentions(notif); + cache::saveTimelineMentions(notif); } catch (const lmdb::error &e) { nhlog::db()->error("failed to save mentions: {}", e.what()); } @@ -457,7 +458,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) &popups::UserMentions::initializeMentions); connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) { try { - room_list_->cleanupInvites(cache::client()->invites()); + room_list_->cleanupInvites(cache::invites()); } catch (const lmdb::error &e) { nhlog::db()->error("failed to retrieve invites: {}", e.what()); } @@ -575,7 +576,7 @@ ChatPage::deleteConfigs() settings.remove(""); settings.endGroup(); - cache::client()->deleteData(); + cache::deleteData(); http::client()->clear(); } @@ -610,18 +611,18 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token) connect( cache::client(), &Cache::roomReadStatus, room_list_, &RoomList::updateReadStatus); - const bool isInitialized = cache::client()->isInitialized(); - const bool isValid = cache::client()->isFormatValid(); + const bool isInitialized = cache::isInitialized(); + const bool isValid = cache::isFormatValid(); if (!isInitialized) { - cache::client()->setCurrentFormat(); + cache::setCurrentFormat(); } else if (isInitialized && !isValid) { // TODO: Deleting session data but keep using the // same device doesn't work. - cache::client()->deleteData(); + cache::deleteData(); cache::init(userid); - cache::client()->setCurrentFormat(); + cache::setCurrentFormat(); } else if (isInitialized) { loadStateFromCache(); return; @@ -629,7 +630,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token) } catch (const lmdb::error &e) { nhlog::db()->critical("failure during boot: {}", e.what()); - cache::client()->deleteData(); + cache::deleteData(); nhlog::net()->info("falling back to initial sync"); } @@ -638,7 +639,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token) // There isn't a saved olm account to restore. nhlog::crypto()->info("creating new olm account"); olm::client()->create_new_account(); - cache::client()->saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY)); + cache::saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY)); } catch (const lmdb::error &e) { nhlog::crypto()->critical("failed to save olm account {}", e.what()); emit dropToLoginPageCb(QString::fromStdString(e.what())); @@ -671,7 +672,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id) } try { - auto room_info = cache::client()->getRoomInfo({room_id.toStdString()}); + auto room_info = cache::getRoomInfo({room_id.toStdString()}); if (room_info.find(room_id) == room_info.end()) return; @@ -682,7 +683,7 @@ ChatPage::changeTopRoomInfo(const QString &room_id) top_bar_->updateRoomName(name); top_bar_->updateRoomTopic(QString::fromStdString(room_info[room_id].topic)); - auto img = cache::client()->getRoomAvatar(room_id); + auto img = cache::getRoomAvatar(room_id); if (img.isNull()) top_bar_->updateRoomAvatarFromName(name); @@ -719,18 +720,17 @@ ChatPage::loadStateFromCache() QtConcurrent::run([this]() { try { - cache::client()->restoreSessions(); - olm::client()->load(cache::client()->restoreOlmAccount(), - STORAGE_SECRET_KEY); + cache::restoreSessions(); + olm::client()->load(cache::restoreOlmAccount(), STORAGE_SECRET_KEY); - cache::client()->populateMembers(); + cache::populateMembers(); - emit initializeEmptyViews(cache::client()->roomMessages()); - emit initializeRoomList(cache::client()->roomInfo()); - emit initializeMentions(cache::client()->getTimelineMentions()); - emit syncTags(cache::client()->roomInfo().toStdMap()); + emit initializeEmptyViews(cache::roomMessages()); + emit initializeRoomList(cache::roomInfo()); + emit initializeMentions(cache::getTimelineMentions()); + emit syncTags(cache::roomInfo().toStdMap()); - cache::client()->calculateRoomReadStatus(); + cache::calculateRoomReadStatus(); } catch (const mtx::crypto::olm_exception &e) { nhlog::crypto()->critical("failed to restore olm account: {}", e.what()); @@ -773,8 +773,8 @@ void ChatPage::removeRoom(const QString &room_id) { try { - cache::client()->removeRoom(room_id); - cache::client()->removeInvite(room_id.toStdString()); + cache::removeRoom(room_id); + cache::removeInvite(room_id.toStdString()); } catch (const lmdb::error &e) { nhlog::db()->critical("failure while removing room: {}", e.what()); // TODO: Notify the user. @@ -807,7 +807,7 @@ ChatPage::generateTypingUsers(const QString &room_id, const std::vectorremoveReadNotification(event_id); + cache::removeReadNotification(event_id); continue; } - if (!cache::client()->isNotificationSent(event_id)) { + if (!cache::isNotificationSent(event_id)) { const auto room_id = QString::fromStdString(item.room_id); const auto user_id = utils::event_sender(item.event); // We should only sent one notification per event. - cache::client()->markSentNotification(event_id); + cache::markSentNotification(event_id); // Don't send a notification when the current room is opened. if (isRoomActive(room_id)) @@ -871,11 +871,10 @@ ChatPage::sendDesktopNotifications(const mtx::responses::Notifications &res) notificationsManager.postNotification( room_id, QString::fromStdString(event_id), - QString::fromStdString( - cache::client()->singleRoomInfo(item.room_id).name), - Cache::displayName(room_id, user_id), + QString::fromStdString(cache::singleRoomInfo(item.room_id).name), + cache::displayName(room_id, user_id), utils::event_body(item.event), - cache::client()->getRoomAvatar(room_id)); + cache::getRoomAvatar(room_id)); } } catch (const lmdb::error &e) { nhlog::db()->warn("error while sending desktop notification: {}", e.what()); @@ -962,7 +961,7 @@ ChatPage::trySync() connectivityTimer_.start(); try { - opts.since = cache::client()->nextBatchToken(); + opts.since = cache::nextBatchToken(); } catch (const lmdb::error &e) { nhlog::db()->error("failed to retrieve next batch token: {}", e.what()); return; @@ -1015,22 +1014,22 @@ ChatPage::trySync() // TODO: fine grained error handling try { - cache::client()->saveState(res); + cache::saveState(res); olm::handle_to_device_messages(res.to_device); emit syncUI(res.rooms); - auto updates = cache::client()->roomUpdates(res); + auto updates = cache::roomUpdates(res); emit syncTopBar(updates); emit syncRoomlist(updates); - emit syncTags(cache::client()->roomTagUpdates(res)); + emit syncTags(cache::roomTagUpdates(res)); - cache::client()->deleteOldData(); + cache::deleteOldData(); } catch (const lmdb::map_full_error &e) { nhlog::db()->error("lmdb is full: {}", e.what()); - cache::client()->deleteOldData(); + cache::deleteOldData(); } catch (const lmdb::error &e) { nhlog::db()->error("saving sync response: {}", e.what()); } @@ -1058,7 +1057,7 @@ ChatPage::joinRoom(const QString &room) // We remove any invites with the same room_id. try { - cache::client()->removeInvite(room_id); + cache::removeInvite(room_id); } catch (const lmdb::error &e) { emit showNotification( QString("Failed to remove invite: %1").arg(e.what())); @@ -1156,16 +1155,16 @@ ChatPage::initialSyncHandler(const mtx::responses::Sync &res, mtx::http::Request nhlog::net()->info("initial sync completed"); try { - cache::client()->saveState(res); + cache::saveState(res); olm::handle_to_device_messages(res.to_device); emit initializeViews(std::move(res.rooms)); - emit initializeRoomList(cache::client()->roomInfo()); - emit initializeMentions(cache::client()->getTimelineMentions()); + emit initializeRoomList(cache::roomInfo()); + emit initializeMentions(cache::getTimelineMentions()); - cache::client()->calculateRoomReadStatus(); - emit syncTags(cache::client()->roomInfo().toStdMap()); + cache::calculateRoomReadStatus(); + emit syncTags(cache::roomInfo().toStdMap()); } catch (const lmdb::error &e) { nhlog::db()->error("failed to save state after initial sync: {}", e.what()); startInitialSync(); diff --git a/src/CommunitiesList.cpp b/src/CommunitiesList.cpp index 6e46741b..4ea99408 100644 --- a/src/CommunitiesList.cpp +++ b/src/CommunitiesList.cpp @@ -215,7 +215,7 @@ CommunitiesList::highlightSelectedCommunity(const QString &community_id) void CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUrl) { - auto savedImgData = cache::client()->image(avatarUrl); + auto savedImgData = cache::image(avatarUrl); if (!savedImgData.isNull()) { QPixmap pix; pix.loadFromData(savedImgData); @@ -238,7 +238,7 @@ CommunitiesList::fetchCommunityAvatar(const QString &id, const QString &avatarUr return; } - cache::client()->saveImage(opts.mxc_url, res); + cache::saveImage(opts.mxc_url, res); auto data = QByteArray(res.data(), res.size()); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 7d9a8902..b13f1b80 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -114,7 +114,7 @@ MainWindow::MainWindow(QWidget *parent) connect( userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool))); connect(userSettingsPage_, &UserSettingsPage::themeChanged, this, []() { - Cache::clearUserColors(); + cache::clearUserColors(); }); connect( userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged); @@ -444,7 +444,7 @@ MainWindow::openReadReceiptsDialog(const QString &event_id) const auto room_id = chat_page_->currentRoom(); try { - dialog->addUsers(cache::client()->readReceipts(event_id, room_id)); + dialog->addUsers(cache::readReceipts(event_id, room_id)); } catch (const lmdb::error &e) { nhlog::db()->warn("failed to retrieve read receipts for {} {}", event_id.toStdString(), @@ -507,4 +507,4 @@ MainWindow::loadJdenticonPlugin() nhlog::ui()->info("jdenticon plugin not found."); return false; -} \ No newline at end of file +} diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp index edf6ceb5..02ca2806 100644 --- a/src/MxcImageProvider.cpp +++ b/src/MxcImageProvider.cpp @@ -1,6 +1,8 @@ #include "MxcImageProvider.h" #include "Cache.h" +#include "MatrixClient.h" +#include "Logging.h" void MxcImageResponse::run() @@ -11,7 +13,7 @@ MxcImageResponse::run() .arg(m_requestedSize.width()) .arg(m_requestedSize.height()); - auto data = cache::client()->image(fileName); + auto data = cache::image(fileName); if (!data.isNull() && m_image.loadFromData(data)) { m_image = m_image.scaled(m_requestedSize, Qt::KeepAspectRatio); m_image.setText("mxc url", "mxc://" + m_id); @@ -36,14 +38,14 @@ MxcImageResponse::run() } auto data = QByteArray(res.data(), res.size()); - cache::client()->saveImage(fileName, data); + cache::saveImage(fileName, data); m_image.loadFromData(data); m_image.setText("mxc url", "mxc://" + m_id); emit finished(); }); } else { - auto data = cache::client()->image(m_id); + auto data = cache::image(m_id); if (!data.isNull() && m_image.loadFromData(data)) { m_image.setText("mxc url", "mxc://" + m_id); emit finished(); @@ -75,7 +77,7 @@ MxcImageResponse::run() m_image.setText("original filename", QString::fromStdString(originalFilename)); m_image.setText("mxc url", "mxc://" + m_id); - cache::client()->saveImage(m_id, data); + cache::saveImage(m_id, data); emit finished(); }); diff --git a/src/Olm.cpp b/src/Olm.cpp index 9c1a25df..5859fe8e 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -121,7 +121,7 @@ handle_pre_key_olm_message(const std::string &sender, // We also remove the one time key used to establish that // session so we'll have to update our copy of the account object. - cache::client()->saveOlmAccount(olm::client()->save("secret")); + cache::saveOlmAccount(olm::client()->save("secret")); } catch (const mtx::crypto::olm_exception &e) { nhlog::crypto()->critical( "failed to create inbound session with {}: {}", sender, e.what()); @@ -149,7 +149,7 @@ handle_pre_key_olm_message(const std::string &sender, nhlog::crypto()->debug("decrypted message: \n {}", plaintext.dump(2)); try { - cache::client()->saveOlmSession(sender_key, std::move(inbound_session)); + cache::saveOlmSession(sender_key, std::move(inbound_session)); } catch (const lmdb::error &e) { nhlog::db()->warn( "failed to save inbound olm session from {}: {}", sender, e.what()); @@ -166,7 +166,7 @@ encrypt_group_message(const std::string &room_id, using namespace mtx::events; // Always chech before for existence. - auto res = cache::client()->getOutboundMegolmSession(room_id); + auto res = cache::getOutboundMegolmSession(room_id); auto payload = olm::client()->encrypt_group_message(res.session, body); // Prepare the m.room.encrypted event. @@ -181,7 +181,7 @@ encrypt_group_message(const std::string &room_id, nhlog::crypto()->info("next message_index {}", message_index); // We need to re-pickle the session after we send a message to save the new message_index. - cache::client()->updateOutboundMegolmSession(room_id, message_index); + cache::updateOutboundMegolmSession(room_id, message_index); return data; } @@ -189,13 +189,13 @@ encrypt_group_message(const std::string &room_id, nlohmann::json try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCipherContent &msg) { - auto session_ids = cache::client()->getOlmSessions(sender_key); + auto session_ids = cache::getOlmSessions(sender_key); nhlog::crypto()->info("attempt to decrypt message with {} known session_ids", session_ids.size()); for (const auto &id : session_ids) { - auto session = cache::client()->getOlmSession(sender_key, id); + auto session = cache::getOlmSession(sender_key, id); if (!session) continue; @@ -204,7 +204,7 @@ try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCip try { text = olm::client()->decrypt_message(session->get(), msg.type, msg.body); - cache::client()->saveOlmSession(id, std::move(session.value())); + cache::saveOlmSession(id, std::move(session.value())); } catch (const mtx::crypto::olm_exception &e) { nhlog::crypto()->debug("failed to decrypt olm message ({}, {}) with {}: {}", msg.type, @@ -252,7 +252,7 @@ create_inbound_megolm_session(const std::string &sender, try { auto megolm_session = olm::client()->init_inbound_group_session(session_key); - cache::client()->saveInboundMegolmSession(index, std::move(megolm_session)); + cache::saveInboundMegolmSession(index, std::move(megolm_session)); } catch (const lmdb::error &e) { nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what()); return; @@ -268,7 +268,7 @@ void mark_keys_as_published() { olm::client()->mark_keys_as_published(); - cache::client()->saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY)); + cache::saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY)); } void @@ -355,13 +355,13 @@ handle_key_request_message(const mtx::events::msg::KeyRequest &req) } // Check if we have the keys for the requested session. - if (!cache::client()->outboundMegolmSessionExists(req.room_id)) { + if (!cache::outboundMegolmSessionExists(req.room_id)) { nhlog::crypto()->warn("requested session not found in room: {}", req.room_id); return; } // Check that the requested session_id and the one we have saved match. - const auto session = cache::client()->getOutboundMegolmSession(req.room_id); + const auto session = cache::getOutboundMegolmSession(req.room_id); if (req.session_id != session.data.session_id) { nhlog::crypto()->warn("session id of retrieved session doesn't match the request: " "requested({}), ours({})", @@ -370,7 +370,7 @@ handle_key_request_message(const mtx::events::msg::KeyRequest &req) return; } - if (!cache::client()->isRoomMember(req.sender, req.room_id)) { + if (!cache::isRoomMember(req.sender, req.room_id)) { nhlog::crypto()->warn( "user {} that requested the session key is not member of the room {}", req.sender, @@ -509,8 +509,7 @@ send_megolm_key_to_device(const std::string &user_id, device_msg = olm::client()->create_olm_encrypted_content( olm_session.get(), room_key, pks.curve25519); - cache::client()->saveOlmSession(pks.curve25519, - std::move(olm_session)); + cache::saveOlmSession(pks.curve25519, std::move(olm_session)); } catch (const json::exception &e) { nhlog::crypto()->warn("creating outbound session: {}", e.what()); diff --git a/src/QuickSwitcher.cpp b/src/QuickSwitcher.cpp index f8f6c001..29683bb3 100644 --- a/src/QuickSwitcher.cpp +++ b/src/QuickSwitcher.cpp @@ -93,8 +93,7 @@ QuickSwitcher::QuickSwitcher(QWidget *parent) QtConcurrent::run([this, query = query.toLower()]() { try { - emit queryResults( - cache::client()->searchRooms(query.toStdString())); + emit queryResults(cache::searchRooms(query.toStdString())); } catch (const lmdb::error &e) { qWarning() << "room search failed:" << e.what(); } diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 66700dbc..5e63eca5 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -529,12 +529,12 @@ TextInputWidget::TextInputWidget(QWidget *parent) emit heightChanged(widgetHeight); }); connect(input_, &FilteredTextEdit::showSuggestions, this, [this](const QString &q) { - if (q.isEmpty() || !cache::client()) + if (q.isEmpty()) return; QtConcurrent::run([this, q = q.toLower().toStdString()]() { try { - emit input_->resultsRetrieved(cache::client()->searchUsers( + emit input_->resultsRetrieved(cache::searchUsers( ChatPage::instance()->currentRoom().toStdString(), q)); } catch (const lmdb::error &e) { std::cout << e.what() << '\n'; diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 1caea449..772a8d13 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -555,7 +555,7 @@ UserSettingsPage::importSessionKeys() try { auto sessions = mtx::crypto::decrypt_exported_sessions(payload, password.toStdString()); - cache::client()->importSessionKeys(std::move(sessions)); + cache::importSessionKeys(std::move(sessions)); } catch (const mtx::crypto::sodium_exception &e) { QMessageBox::warning(this, tr("Error"), e.what()); } catch (const lmdb::error &e) { @@ -597,7 +597,7 @@ UserSettingsPage::exportSessionKeys() // Export sessions & save to file. try { auto encrypted_blob = mtx::crypto::encrypt_exported_sessions( - cache::client()->exportSessionKeys(), password.toStdString()); + cache::exportSessionKeys(), password.toStdString()); QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob)); diff --git a/src/Utils.cpp b/src/Utils.cpp index 3d69162f..918e1996 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -142,7 +142,7 @@ utils::getMessageDescription(const TimelineEvent &event, } else if (auto msg = std::get_if(&event); msg != nullptr) { const auto sender = QString::fromStdString(msg->sender); - const auto username = Cache::displayName(room_id, sender); + const auto username = cache::displayName(room_id, sender); const auto ts = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts); DescInfo info; diff --git a/src/Utils.h b/src/Utils.h index 6c0cf0dd..aa62b8e7 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -168,7 +168,7 @@ createDescriptionInfo(const Event &event, const QString &localUser, const QStrin const auto msg = std::get(event); const auto sender = QString::fromStdString(msg.sender); - const auto username = Cache::displayName(room_id, sender); + const auto username = cache::displayName(room_id, sender); const auto ts = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts); return DescInfo{QString::fromStdString(msg.event_id), diff --git a/src/dialogs/MemberList.cpp b/src/dialogs/MemberList.cpp index f62cf9fe..dfb3d984 100644 --- a/src/dialogs/MemberList.cpp +++ b/src/dialogs/MemberList.cpp @@ -110,11 +110,11 @@ MemberList::MemberList(const QString &room_id, QWidget *parent) const size_t numMembers = list_->count() - 1; if (numMembers > 0) - addUsers(cache::client()->getMembers(room_id_.toStdString(), numMembers)); + addUsers(cache::getMembers(room_id_.toStdString(), numMembers)); }); try { - addUsers(cache::client()->getMembers(room_id_.toStdString())); + addUsers(cache::getMembers(room_id_.toStdString())); } catch (const lmdb::error &e) { qCritical() << e.what(); } diff --git a/src/dialogs/ReadReceipts.cpp b/src/dialogs/ReadReceipts.cpp index 58ad59c3..0edd1ebf 100644 --- a/src/dialogs/ReadReceipts.cpp +++ b/src/dialogs/ReadReceipts.cpp @@ -35,7 +35,7 @@ ReceiptItem::ReceiptItem(QWidget *parent, QFont nameFont; nameFont.setPointSizeF(nameFont.pointSizeF() * 1.1); - auto displayName = Cache::displayName(room_id, user_id); + auto displayName = cache::displayName(room_id, user_id); avatar_ = new Avatar(this, 44); avatar_->setLetter(utils::firstChar(displayName)); diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp index 1be33d33..fcaa4fdc 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp @@ -485,8 +485,8 @@ void RoomSettings::retrieveRoomInfo() { try { - usesEncryption_ = cache::client()->isRoomEncrypted(room_id_.toStdString()); - info_ = cache::client()->singleRoomInfo(room_id_.toStdString()); + usesEncryption_ = cache::isRoomEncrypted(room_id_.toStdString()); + info_ = cache::singleRoomInfo(room_id_.toStdString()); setAvatar(); } catch (const lmdb::error &) { nhlog::db()->warn("failed to retrieve room info from cache: {}", @@ -529,8 +529,7 @@ bool RoomSettings::canChangeJoinRules(const std::string &room_id, const std::string &user_id) const { try { - return cache::client()->hasEnoughPowerLevel( - {EventType::RoomJoinRules}, room_id, user_id); + return cache::hasEnoughPowerLevel({EventType::RoomJoinRules}, room_id, user_id); } catch (const lmdb::error &e) { nhlog::db()->warn("lmdb error: {}", e.what()); } @@ -542,7 +541,7 @@ bool RoomSettings::canChangeNameAndTopic(const std::string &room_id, const std::string &user_id) const { try { - return cache::client()->hasEnoughPowerLevel( + return cache::hasEnoughPowerLevel( {EventType::RoomName, EventType::RoomTopic}, room_id, user_id); } catch (const lmdb::error &e) { nhlog::db()->warn("lmdb error: {}", e.what()); @@ -555,8 +554,7 @@ bool RoomSettings::canChangeAvatar(const std::string &room_id, const std::string &user_id) const { try { - return cache::client()->hasEnoughPowerLevel( - {EventType::RoomAvatar}, room_id, user_id); + return cache::hasEnoughPowerLevel({EventType::RoomAvatar}, room_id, user_id); } catch (const lmdb::error &e) { nhlog::db()->warn("lmdb error: {}", e.what()); } diff --git a/src/dialogs/RoomSettings.h b/src/dialogs/RoomSettings.h index e1807ba1..d71b70db 100644 --- a/src/dialogs/RoomSettings.h +++ b/src/dialogs/RoomSettings.h @@ -5,7 +5,9 @@ #include #include -#include "Cache.h" +#include + +#include "CacheStructs.h" class Avatar; class FlatButton; diff --git a/src/dialogs/UserProfile.cpp b/src/dialogs/UserProfile.cpp index 5ad3afa2..50c1c990 100644 --- a/src/dialogs/UserProfile.cpp +++ b/src/dialogs/UserProfile.cpp @@ -203,7 +203,7 @@ UserProfile::init(const QString &userId, const QString &roomId) { resetToDefaults(); - auto displayName = Cache::displayName(roomId, userId); + auto displayName = cache::displayName(roomId, userId); userIdLabel_->setText(userId); displayNameLabel_->setText(displayName); @@ -215,9 +215,9 @@ UserProfile::init(const QString &userId, const QString &roomId) try { bool hasMemberRights = - cache::client()->hasEnoughPowerLevel({mtx::events::EventType::RoomMember}, - roomId.toStdString(), - localUser.toStdString()); + cache::hasEnoughPowerLevel({mtx::events::EventType::RoomMember}, + roomId.toStdString(), + localUser.toStdString()); if (!hasMemberRights) { kickBtn_->hide(); banBtn_->hide(); diff --git a/src/popups/PopupItem.cpp b/src/popups/PopupItem.cpp index c4d4327f..db97e4a3 100644 --- a/src/popups/PopupItem.cpp +++ b/src/popups/PopupItem.cpp @@ -49,7 +49,7 @@ UserItem::UserItem(QWidget *parent, const QString &user_id) : PopupItem(parent) , userId_{user_id} { - auto displayName = Cache::displayName(ChatPage::instance()->currentRoom(), userId_); + auto displayName = cache::displayName(ChatPage::instance()->currentRoom(), userId_); avatar_->setLetter(utils::firstChar(displayName)); @@ -70,7 +70,7 @@ UserItem::updateItem(const QString &user_id) { userId_ = user_id; - auto displayName = Cache::displayName(ChatPage::instance()->currentRoom(), userId_); + auto displayName = cache::displayName(ChatPage::instance()->currentRoom(), userId_); // If it's a matrix id we use the second letter. if (displayName.size() > 1 && displayName.at(0) == '@') @@ -93,7 +93,7 @@ UserItem::mousePressEvent(QMouseEvent *event) { if (event->buttons() != Qt::RightButton) emit clicked( - Cache::displayName(ChatPage::instance()->currentRoom(), selectedText())); + cache::displayName(ChatPage::instance()->currentRoom(), selectedText())); QWidget::mousePressEvent(event); } diff --git a/src/popups/PopupItem.h b/src/popups/PopupItem.h index cab73a9d..7a710fdb 100644 --- a/src/popups/PopupItem.h +++ b/src/popups/PopupItem.h @@ -6,7 +6,6 @@ #include #include "../AvatarProvider.h" -#include "../Cache.h" #include "../ChatPage.h" class Avatar; @@ -81,4 +80,4 @@ private: QLabel *roomName_; QString roomId_; RoomSearchResult info_; -}; \ No newline at end of file +}; diff --git a/src/popups/ReplyPopup.cpp b/src/popups/ReplyPopup.cpp index 0ebf7c88..42a5a6d3 100644 --- a/src/popups/ReplyPopup.cpp +++ b/src/popups/ReplyPopup.cpp @@ -8,6 +8,7 @@ #include "../ui/Avatar.h" #include "../ui/DropShadow.h" #include "../ui/TextLabel.h" +#include "PopupItem.h" #include "ReplyPopup.h" ReplyPopup::ReplyPopup(QWidget *parent) diff --git a/src/popups/ReplyPopup.h b/src/popups/ReplyPopup.h index b28cd0cf..1fa3bb83 100644 --- a/src/popups/ReplyPopup.h +++ b/src/popups/ReplyPopup.h @@ -2,17 +2,14 @@ #include #include -#include #include #include -#include "../AvatarProvider.h" -#include "../Cache.h" -#include "../ChatPage.h" -#include "../Utils.h" #include "../ui/FlatButton.h" #include "../ui/TextLabel.h" -#include "PopupItem.h" + +struct RelatedInfo; +class UserItem; class ReplyPopup : public QWidget { diff --git a/src/popups/SuggestionsPopup.h b/src/popups/SuggestionsPopup.h index 536c82fb..de52760a 100644 --- a/src/popups/SuggestionsPopup.h +++ b/src/popups/SuggestionsPopup.h @@ -5,9 +5,8 @@ #include #include -#include "../AvatarProvider.h" -#include "../Cache.h" -#include "../ChatPage.h" +#include "CacheStructs.h" +#include "ChatPage.h" #include "PopupItem.h" Q_DECLARE_METATYPE(QVector) @@ -28,7 +27,7 @@ public: const auto &widget = qobject_cast(item->widget()); emit itemSelected( - Cache::displayName(ChatPage::instance()->currentRoom(), widget->selectedText())); + cache::displayName(ChatPage::instance()->currentRoom(), widget->selectedText())); resetSelection(); } diff --git a/src/popups/UserMentions.cpp b/src/popups/UserMentions.cpp index 3be5c462..763eeffc 100644 --- a/src/popups/UserMentions.cpp +++ b/src/popups/UserMentions.cpp @@ -103,7 +103,7 @@ UserMentions::showPopup() delete widget; } - auto notifs = cache::client()->getTimelineMentions(); + auto notifs = cache::getTimelineMentions(); initializeMentions(notifs); show(); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 1e069d50..d3d1ad34 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -422,7 +422,7 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj readEvent(event_id.toStdString()); // ask to be notified for read receipts - cache::client()->addPendingReceipt(room_id_, event_id); + cache::addPendingReceipt(room_id_, event_id); isProcessingPending = false; emit dataChanged(index(idx, 0), index(idx, 0)); @@ -575,8 +575,7 @@ TimelineModel::data(const QModelIndex &index, int role) const return qml_mtx_events::Failed; else if (pending.contains(id)) return qml_mtx_events::Sent; - else if (read.contains(id) || - cache::client()->readReceipts(id, room_id_).size() > 1) + else if (read.contains(id) || cache::readReceipts(id, room_id_).size() > 1) return qml_mtx_events::Read; else return qml_mtx_events::Received; @@ -805,13 +804,13 @@ TimelineModel::userColor(QString id, QColor background) QString TimelineModel::displayName(QString id) const { - return Cache::displayName(room_id_, id); + return cache::displayName(room_id_, id); } QString TimelineModel::avatarUrl(QString id) const { - return Cache::avatarUrl(room_id_, id); + return cache::avatarUrl(room_id_, id); } QString @@ -868,7 +867,7 @@ TimelineModel::decryptEvent(const mtx::events::EncryptedEventinboundMegolmSessionExists(index)) { + if (!cache::inboundMegolmSessionExists(index)) { nhlog::crypto()->info("Could not find inbound megolm session ({}, {}, {})", index.room_id, index.session_id, @@ -887,7 +886,7 @@ TimelineModel::decryptEvent(const mtx::events::EncryptedEventgetInboundMegolmSession(index); + auto session = cache::getInboundMegolmSession(index); auto res = olm::client()->decrypt_group_message(session, e.content.ciphertext); msg_str = std::string((char *)res.data.data(), res.data.size()); } catch (const lmdb::error &e) { @@ -1044,7 +1043,7 @@ TimelineModel::sendEncryptedMessage(const std::string &txn_id, nlohmann::json co try { // Check if we have already an outbound megolm session then we can use. - if (cache::client()->outboundMegolmSessionExists(room_id)) { + if (cache::outboundMegolmSessionExists(room_id)) { auto data = olm::encrypt_group_message( room_id, http::client()->device_id(), doc.dump()); @@ -1089,10 +1088,10 @@ TimelineModel::sendEncryptedMessage(const std::string &txn_id, nlohmann::json co session_data.session_id = session_id; session_data.session_key = session_key; session_data.message_index = 0; // TODO Update me - cache::client()->saveOutboundMegolmSession( + cache::saveOutboundMegolmSession( room_id, session_data, std::move(outbound_session)); - const auto members = cache::client()->roomMembers(room_id); + const auto members = cache::roomMembers(room_id); nhlog::ui()->info("retrieved {} members for {}", members.size(), room_id); auto keeper = @@ -1311,7 +1310,7 @@ TimelineModel::handleClaimedKeys(std::shared_ptr keeper, s.get(), room_keys.at(device_id), pks.at(device_id).curve25519); try { - cache::client()->saveOlmSession(id_key, std::move(s)); + cache::saveOlmSession(id_key, std::move(s)); } catch (const lmdb::error &e) { nhlog::db()->critical("failed to save outbound olm session: {}", e.what()); } catch (const mtx::crypto::olm_exception &e) { @@ -1353,7 +1352,7 @@ struct SendMessageVisitor void operator()(const mtx::events::RoomEvent &msg) { - if (cache::client()->isRoomEncrypted(model_->room_id_.toStdString())) { + if (cache::isRoomEncrypted(model_->room_id_.toStdString())) { model_->sendEncryptedMessage(txn_id_qstr_.toStdString(), nlohmann::json(msg.content)); } else { -- cgit 1.5.1 From 79f967da8c8c077a6fdbbd46ae9ee59a19a891a3 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 15 Dec 2019 03:34:17 +0100 Subject: Reduce Cache.h includes further via one forward declaration --- src/Cache.cpp | 2 -- src/ChatPage.h | 1 + src/MainWindow.cpp | 1 + src/MxcImageProvider.cpp | 2 +- src/QuickSwitcher.cpp | 1 + src/UserSettingsPage.cpp | 1 + src/Utils.cpp | 1 + src/Utils.h | 7 ++++++- src/dialogs/RoomSettings.cpp | 1 + 9 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/QuickSwitcher.cpp') diff --git a/src/Cache.cpp b/src/Cache.cpp index 79425fa1..0bfc2842 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -104,7 +104,6 @@ numeric_key_comparison(const MDB_val *a, const MDB_val *b) return -1; } - Cache::Cache(const QString &userId, QObject *parent) : QObject{parent} , env_{nullptr} @@ -2901,4 +2900,3 @@ restoreSessions() return instance_->restoreSessions(); } } // namespace cache - diff --git a/src/ChatPage.h b/src/ChatPage.h index a7fb31a8..9e88dcc6 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -22,6 +22,7 @@ #include #include +#include #include #include diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index b13f1b80..a24266fa 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -23,6 +23,7 @@ #include +#include "Cache.h" #include "ChatPage.h" #include "Config.h" #include "Logging.h" diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp index 02ca2806..d04eab24 100644 --- a/src/MxcImageProvider.cpp +++ b/src/MxcImageProvider.cpp @@ -1,8 +1,8 @@ #include "MxcImageProvider.h" #include "Cache.h" -#include "MatrixClient.h" #include "Logging.h" +#include "MatrixClient.h" void MxcImageResponse::run() diff --git a/src/QuickSwitcher.cpp b/src/QuickSwitcher.cpp index 29683bb3..53dd21e0 100644 --- a/src/QuickSwitcher.cpp +++ b/src/QuickSwitcher.cpp @@ -22,6 +22,7 @@ #include #include +#include "Cache.h" #include "QuickSwitcher.h" #include "popups/SuggestionsPopup.h" diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 772a8d13..6809d605 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -29,6 +29,7 @@ #include #include +#include "Cache.h" #include "Config.h" #include "MatrixClient.h" #include "Olm.h" diff --git a/src/Utils.cpp b/src/Utils.cpp index 918e1996..1c94761d 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -15,6 +15,7 @@ #include +#include "Cache.h" #include "Config.h" using TimelineEvent = mtx::events::collections::TimelineEvents; diff --git a/src/Utils.h b/src/Utils.h index aa62b8e7..6b809d63 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -2,7 +2,6 @@ #include -#include "Cache.h" #include "RoomInfoListItem.h" #include @@ -13,6 +12,12 @@ #include +namespace cache { +// Forward declarations to prevent dependency on Cache.h, since this header is included often! +QString +displayName(const QString &room_id, const QString &user_id); +} + class QComboBox; // Contains information about related events for diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp index fcaa4fdc..b214b35d 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp @@ -16,6 +16,7 @@ #include "dialogs/RoomSettings.h" +#include "Cache.h" #include "ChatPage.h" #include "Config.h" #include "Logging.h" -- cgit 1.5.1 From 127fb9370b8e131ad460b27aaa72de178e929096 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 31 Jan 2020 16:08:30 +0100 Subject: Remove metatypes from headers --- src/Cache.cpp | 11 +++++------ src/Cache.h | 2 +- src/Cache_p.h | 6 +++--- src/LoginPage.cpp | 1 + src/MatrixClient.cpp | 20 ++++++++++++++++++++ src/MatrixClient.h | 18 ------------------ src/QuickSwitcher.cpp | 2 ++ src/QuickSwitcher.h | 2 -- src/RegisterPage.cpp | 2 ++ src/RoomList.h | 3 --- src/TextInputWidget.cpp | 2 +- src/TextInputWidget.h | 4 ++-- src/dialogs/UserProfile.cpp | 2 ++ src/dialogs/UserProfile.h | 2 -- src/popups/SuggestionsPopup.cpp | 4 ++-- src/popups/SuggestionsPopup.h | 4 +--- 16 files changed, 42 insertions(+), 43 deletions(-) (limited to 'src/QuickSwitcher.cpp') diff --git a/src/Cache.cpp b/src/Cache.cpp index f6f8052d..dfd7475c 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -80,7 +80,7 @@ using CachedReceipts = std::multimap>; Q_DECLARE_METATYPE(SearchResult) -Q_DECLARE_METATYPE(QVector) +Q_DECLARE_METATYPE(std::vector) Q_DECLARE_METATYPE(RoomMember) Q_DECLARE_METATYPE(mtx::responses::Timeline) Q_DECLARE_METATYPE(RoomSearchResult) @@ -1834,7 +1834,7 @@ Cache::searchRooms(const std::string &query, std::uint8_t max_items) return results; } -QVector +std::vector Cache::searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items) { std::multimap> items; @@ -1857,7 +1857,7 @@ Cache::searchUsers(const std::string &room_id, const std::string &query, std::ui else if (items.size() > 0) std::advance(end, items.size()); - QVector results; + std::vector results; for (auto it = items.begin(); it != end; it++) { const auto user = it->second; results.push_back(SearchResult{QString::fromStdString(user.first), @@ -2390,12 +2390,11 @@ void init(const QString &user_id) { qRegisterMetaType(); - qRegisterMetaType>(); + qRegisterMetaType>(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType>(); - qRegisterMetaType>(); qRegisterMetaType>(); qRegisterMetaType>(); @@ -2734,7 +2733,7 @@ calculateRoomReadStatus() instance_->calculateRoomReadStatus(); } -QVector +std::vector searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items) { return instance_->searchUsers(room_id, query, max_items); diff --git a/src/Cache.h b/src/Cache.h index a8991eb5..69b3ef2d 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -218,7 +218,7 @@ calculateRoomReadStatus(const std::string &room_id); void calculateRoomReadStatus(); -QVector +std::vector searchUsers(const std::string &room_id, const std::string &query, std::uint8_t max_items = 5); std::vector searchRooms(const std::string &query, std::uint8_t max_items = 5); diff --git a/src/Cache_p.h b/src/Cache_p.h index 32f2a67d..b76a512f 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -172,9 +172,9 @@ public: bool calculateRoomReadStatus(const std::string &room_id); void calculateRoomReadStatus(); - QVector searchUsers(const std::string &room_id, - const std::string &query, - std::uint8_t max_items = 5); + std::vector searchUsers(const std::string &room_id, + const std::string &query, + std::uint8_t max_items = 5); std::vector searchRooms(const std::string &query, std::uint8_t max_items = 5); diff --git a/src/LoginPage.cpp b/src/LoginPage.cpp index c244db28..c06137c9 100644 --- a/src/LoginPage.cpp +++ b/src/LoginPage.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "Config.h" #include "Logging.h" diff --git a/src/MatrixClient.cpp b/src/MatrixClient.cpp index 12d7ac91..b69ba480 100644 --- a/src/MatrixClient.cpp +++ b/src/MatrixClient.cpp @@ -2,6 +2,26 @@ #include +#include +#include +#include + +#include "nlohmann/json.hpp" +#include + +Q_DECLARE_METATYPE(mtx::responses::Login) +Q_DECLARE_METATYPE(mtx::responses::Messages) +Q_DECLARE_METATYPE(mtx::responses::Notifications) +Q_DECLARE_METATYPE(mtx::responses::Rooms) +Q_DECLARE_METATYPE(mtx::responses::Sync) +Q_DECLARE_METATYPE(mtx::responses::JoinedGroups) +Q_DECLARE_METATYPE(mtx::responses::GroupProfile) + +Q_DECLARE_METATYPE(nlohmann::json) +Q_DECLARE_METATYPE(std::string) +Q_DECLARE_METATYPE(std::vector) +Q_DECLARE_METATYPE(std::vector) + namespace { auto client_ = std::make_shared(); } diff --git a/src/MatrixClient.h b/src/MatrixClient.h index c77b1183..4db51095 100644 --- a/src/MatrixClient.h +++ b/src/MatrixClient.h @@ -1,25 +1,7 @@ #pragma once -#include -#include -#include - -#include "nlohmann/json.hpp" -#include #include -Q_DECLARE_METATYPE(mtx::responses::Login) -Q_DECLARE_METATYPE(mtx::responses::Messages) -Q_DECLARE_METATYPE(mtx::responses::Notifications) -Q_DECLARE_METATYPE(mtx::responses::Rooms) -Q_DECLARE_METATYPE(mtx::responses::Sync) -Q_DECLARE_METATYPE(mtx::responses::JoinedGroups) -Q_DECLARE_METATYPE(mtx::responses::GroupProfile) -Q_DECLARE_METATYPE(std::string) -Q_DECLARE_METATYPE(nlohmann::json) -Q_DECLARE_METATYPE(std::vector) -Q_DECLARE_METATYPE(std::vector) - namespace http { mtx::http::Client * client(); diff --git a/src/QuickSwitcher.cpp b/src/QuickSwitcher.cpp index 53dd21e0..05a9f431 100644 --- a/src/QuickSwitcher.cpp +++ b/src/QuickSwitcher.cpp @@ -26,6 +26,8 @@ #include "QuickSwitcher.h" #include "popups/SuggestionsPopup.h" +Q_DECLARE_METATYPE(std::vector) + RoomSearchInput::RoomSearchInput(QWidget *parent) : TextField(parent) {} diff --git a/src/QuickSwitcher.h b/src/QuickSwitcher.h index 05f7be07..5bc31650 100644 --- a/src/QuickSwitcher.h +++ b/src/QuickSwitcher.h @@ -25,8 +25,6 @@ #include "popups/SuggestionsPopup.h" #include "ui/TextField.h" -Q_DECLARE_METATYPE(std::vector) - class RoomSearchInput : public TextField { Q_OBJECT diff --git a/src/RegisterPage.cpp b/src/RegisterPage.cpp index 942fd1b8..76721036 100644 --- a/src/RegisterPage.cpp +++ b/src/RegisterPage.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include "Config.h" #include "Logging.h" #include "MainWindow.h" diff --git a/src/RoomList.h b/src/RoomList.h index d921990b..51a24043 100644 --- a/src/RoomList.h +++ b/src/RoomList.h @@ -17,15 +17,12 @@ #pragma once -#include #include #include #include #include #include -#include - class LeaveRoomDialog; class OverlayModal; class RoomInfoListItem; diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 7be50ab5..2ad74e3a 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -109,7 +109,7 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent) } void -FilteredTextEdit::showResults(const QVector &results) +FilteredTextEdit::showResults(const std::vector &results) { QPoint pos; diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index a430aa5c..2f267a23 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -76,13 +76,13 @@ signals: //! Trigger the suggestion popup. void showSuggestions(const QString &query); - void resultsRetrieved(const QVector &results); + void resultsRetrieved(const std::vector &results); void selectNextSuggestion(); void selectPreviousSuggestion(); void selectHoveredSuggestion(); public slots: - void showResults(const QVector &results); + void showResults(const std::vector &results); protected: void keyPressEvent(QKeyEvent *event) override; diff --git a/src/dialogs/UserProfile.cpp b/src/dialogs/UserProfile.cpp index 273ffd54..f1dd77df 100644 --- a/src/dialogs/UserProfile.cpp +++ b/src/dialogs/UserProfile.cpp @@ -15,6 +15,8 @@ using namespace dialogs; +Q_DECLARE_METATYPE(std::vector) + constexpr int BUTTON_SIZE = 36; constexpr int BUTTON_RADIUS = BUTTON_SIZE / 2; constexpr int WIDGET_MARGIN = 20; diff --git a/src/dialogs/UserProfile.h b/src/dialogs/UserProfile.h index 0f684cda..81276d2a 100644 --- a/src/dialogs/UserProfile.h +++ b/src/dialogs/UserProfile.h @@ -15,8 +15,6 @@ struct DeviceInfo QString display_name; }; -Q_DECLARE_METATYPE(std::vector) - class Proxy : public QObject { Q_OBJECT diff --git a/src/popups/SuggestionsPopup.cpp b/src/popups/SuggestionsPopup.cpp index ba1f77b9..8f355b38 100644 --- a/src/popups/SuggestionsPopup.cpp +++ b/src/popups/SuggestionsPopup.cpp @@ -60,9 +60,9 @@ SuggestionsPopup::addRooms(const std::vector &rooms) } void -SuggestionsPopup::addUsers(const QVector &users) +SuggestionsPopup::addUsers(const std::vector &users) { - if (users.isEmpty()) { + if (users.empty()) { hide(); return; } diff --git a/src/popups/SuggestionsPopup.h b/src/popups/SuggestionsPopup.h index de52760a..dcd054f8 100644 --- a/src/popups/SuggestionsPopup.h +++ b/src/popups/SuggestionsPopup.h @@ -9,8 +9,6 @@ #include "ChatPage.h" #include "PopupItem.h" -Q_DECLARE_METATYPE(QVector) - class SuggestionsPopup : public QWidget { Q_OBJECT @@ -33,7 +31,7 @@ public: } public slots: - void addUsers(const QVector &users); + void addUsers(const std::vector &users); void addRooms(const std::vector &rooms); //! Move to the next available suggestion item. -- cgit 1.5.1