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 --- src/Cache_p.h | 494 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 src/Cache_p.h (limited to 'src/Cache_p.h') 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(); +} -- cgit 1.5.1 From d10276253fb9258412d5b23caa54b34c5cde24d1 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 24 Jan 2020 18:39:26 +0100 Subject: Fix include of lmdb++ with hunter --- src/Cache.h | 4 ++++ src/Cache_p.h | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'src/Cache_p.h') diff --git a/src/Cache.h b/src/Cache.h index da4e2040..a8991eb5 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -22,7 +22,11 @@ #include #include +#if __has_include() +#include +#else #include +#endif #include diff --git a/src/Cache_p.h b/src/Cache_p.h index 47dd945a..32f2a67d 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -26,7 +26,11 @@ #include #include +#if __has_include() +#include +#else #include +#endif #include #include -- 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/Cache_p.h') 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 From bd3b6aefb4d5ca738d499fca72ab05c2b39061d7 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 31 Jan 2020 16:36:58 +0100 Subject: Remove even more headers --- src/Cache.cpp | 1 + src/Cache_p.h | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'src/Cache_p.h') diff --git a/src/Cache.cpp b/src/Cache.cpp index dfd7475c..2e02a488 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -31,6 +31,7 @@ #include "Cache.h" #include "Cache_p.h" +#include "Logging.h" #include "Utils.h" //! Should be changed when a breaking change occurs in the cache format. diff --git a/src/Cache_p.h b/src/Cache_p.h index b76a512f..eacb28a7 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -18,7 +18,6 @@ #pragma once -#include #include #include @@ -38,8 +37,6 @@ #include "CacheCryptoStructs.h" #include "CacheStructs.h" -#include "Logging.h" -#include "MatrixClient.h" int numeric_key_comparison(const MDB_val *a, const MDB_val *b); -- cgit 1.5.1 From 6bdc75d07319b3b2a846ee4a905288ec0d9371f6 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Thu, 20 Feb 2020 20:51:07 +0100 Subject: Reset user colors on theme change (in qml timeline) --- resources/qml/TimelineRow.qml | 2 +- resources/qml/TimelineView.qml | 4 +-- resources/qml/delegates/MessageDelegate.qml | 2 +- resources/qml/delegates/Reply.qml | 2 +- src/Cache.cpp | 51 ----------------------------- src/Cache.h | 9 ----- src/Cache_p.h | 6 ---- src/MainWindow.cpp | 3 -- src/timeline/TimelineModel.cpp | 15 ++------- src/timeline/TimelineModel.h | 2 -- src/timeline/TimelineViewManager.cpp | 11 +++++++ src/timeline/TimelineViewManager.h | 2 ++ 12 files changed, 20 insertions(+), 89 deletions(-) (limited to 'src/Cache_p.h') diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml index a371f78b..fa427bfd 100644 --- a/resources/qml/TimelineRow.qml +++ b/resources/qml/TimelineRow.qml @@ -23,7 +23,7 @@ RowLayout { Reply { visible: model.replyTo modelData: chat.model.getDump(model.replyTo) - userColor: chat.model.userColor(modelData.userId, colors.window) + userColor: timelineManager.userColor(modelData.userId, colors.window) } // actual message content diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 9730422d..46cf484b 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -218,7 +218,7 @@ Item { Text { id: userName text: chat.model.escapeEmoji(modelData.userName) - color: chat.model.userColor(modelData.userId, colors.window) + color: timelineManager.userColor(modelData.userId, colors.window) textFormat: Text.RichText MouseArea { @@ -283,7 +283,7 @@ Item { anchors.bottom: parent.bottom modelData: chat.model ? chat.model.getDump(timelineManager.replyingEvent) : {} - userColor: chat.model ? chat.model.userColor(modelData.userId, colors.window) : colors.window + userColor: timelineManager.userColor(modelData.userId, colors.window) } ImageButton { diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml index f043efec..ab633087 100644 --- a/resources/qml/delegates/MessageDelegate.qml +++ b/resources/qml/delegates/MessageDelegate.qml @@ -34,7 +34,7 @@ Item { roleValue: MtxEvent.EmoteMessage NoticeMessage { formatted: chat.model.escapeEmoji(modelData.userName) + " " + model.data.formattedBody - color: chat.model.userColor(modelData.userId, colors.window) + color: timelineManager.userColor(modelData.userId, colors.window) } } DelegateChoice { diff --git a/resources/qml/delegates/Reply.qml b/resources/qml/delegates/Reply.qml index a1ddc8f0..8bb9ed38 100644 --- a/resources/qml/delegates/Reply.qml +++ b/resources/qml/delegates/Reply.qml @@ -19,7 +19,7 @@ Rectangle { anchors.bottom: replyContainer.bottom width: 4 - color: chat.model ? chat.model.userColor(reply.modelData.userId, colors.window) : colors.window + color: timelineManager.userColor(reply.modelData.userId, colors.window) } Column { diff --git a/src/Cache.cpp b/src/Cache.cpp index e73f7754..caa3f1ec 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -2186,7 +2186,6 @@ Cache::roomMembers(const std::string &room_id) QHash Cache::DisplayNames; QHash Cache::AvatarUrls; -QHash Cache::UserColors; QString Cache::displayName(const QString &room_id, const QString &user_id) @@ -2218,16 +2217,6 @@ Cache::avatarUrl(const QString &room_id, const QString &user_id) return QString(); } -QString -Cache::userColor(const QString &user_id) -{ - if (UserColors.contains(user_id)) { - return UserColors[user_id]; - } - - return QString(); -} - void Cache::insertDisplayName(const QString &room_id, const QString &user_id, @@ -2258,24 +2247,6 @@ Cache::removeAvatarUrl(const QString &room_id, const QString &user_id) AvatarUrls.remove(fmt); } -void -Cache::insertUserColor(const QString &user_id, const QString &color_name) -{ - UserColors.insert(user_id, color_name); -} - -void -Cache::removeUserColor(const QString &user_id) -{ - UserColors.remove(user_id); -} - -void -Cache::clearUserColors() -{ - UserColors.clear(); -} - void to_json(json &j, const RoomInfo &info) { @@ -2425,12 +2396,6 @@ 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) { @@ -2441,11 +2406,6 @@ 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) @@ -2457,17 +2417,6 @@ insertAvatarUrl(const QString &room_id, const QString &user_id, const QString &a { 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 diff --git a/src/Cache.h b/src/Cache.h index 69b3ef2d..bb042ea9 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -43,25 +43,16 @@ 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 diff --git a/src/Cache_p.h b/src/Cache_p.h index eacb28a7..137408b9 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -51,11 +51,9 @@ public: 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, @@ -63,9 +61,6 @@ public: 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(); @@ -484,7 +479,6 @@ private: static QHash DisplayNames; static QHash AvatarUrls; - static QHash UserColors; OlmSessionStorage session_storage; }; diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 1b378ca9..17a04a41 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -115,9 +115,6 @@ MainWindow::MainWindow(QWidget *parent) connect( userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool))); - connect(userSettingsPage_, &UserSettingsPage::themeChanged, this, []() { - cache::clearUserColors(); - }); connect( userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged); connect(trayIcon_, diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8de6bec6..cad39bc5 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -196,9 +196,6 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj if (idx >= 0) emit dataChanged(index(idx, 0), index(idx, 0)); }); - - connect( - ChatPage::instance(), &ChatPage::themeChanged, this, [this]() { userColors.clear(); }); } QHash @@ -650,15 +647,6 @@ TimelineModel::addBackwardsEvents(const mtx::responses::Messages &msgs) prev_batch_token_ = QString::fromStdString(msgs.end); } -QColor -TimelineModel::userColor(QString id, QColor background) -{ - if (!userColors.contains(id)) - userColors.insert( - id, QColor(utils::generateContrastingHexColor(id, background.name()))); - return userColors.value(id); -} - QString TimelineModel::displayName(QString id) const { @@ -1446,7 +1434,8 @@ TimelineModel::formatTypingUsers(const std::vector &users, QColor bg) auto formatUser = [this, bg](const QString &user_id) -> QString { auto uncoloredUsername = escapeEmoji(displayName(user_id).toHtmlEscaped()); - QString prefix = QString("").arg(userColor(user_id, bg).name()); + QString prefix = + QString("").arg(manager_->userColor(user_id, bg).name()); // color only parts that don't have a font already specified QString coloredUsername; diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 642e9bbc..f06de5d9 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -165,7 +165,6 @@ public: bool canFetchMore(const QModelIndex &) const override; void fetchMore(const QModelIndex &) override; - Q_INVOKABLE QColor userColor(QString id, QColor background); Q_INVOKABLE QString displayName(QString id) const; Q_INVOKABLE QString avatarUrl(QString id) const; Q_INVOKABLE QString formatDateSeparator(QDate date) const; @@ -248,7 +247,6 @@ private: bool paginationInProgress = false; bool isProcessingPending = false; - QHash userColors; QString currentId; std::vector typingUsers_; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 7cd1432d..14f903a1 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -18,6 +18,8 @@ Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) void TimelineViewManager::updateColorPalette() { + userColors.clear(); + if (settings->theme() == "light") { QPalette lightActive(/*windowText*/ QColor("#333"), /*button*/ QColor("#333"), @@ -53,6 +55,15 @@ TimelineViewManager::updateColorPalette() } } +QColor +TimelineViewManager::userColor(QString id, QColor background) +{ + if (!userColors.contains(id)) + userColors.insert( + id, QColor(utils::generateContrastingHexColor(id, background.name()))); + return userColors.value(id); +} + TimelineViewManager::TimelineViewManager(QSharedPointer userSettings, QWidget *parent) : imgProvider(new MxcImageProvider()) , colorImgProvider(new ColorImageProvider()) diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 625999c9..338101c7 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -40,6 +40,7 @@ public: Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; } Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; } Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const; + Q_INVOKABLE QColor userColor(QString id, QColor background); signals: void clearRoomMessageCount(QString roomid); @@ -118,4 +119,5 @@ private: QString replyingEvent_; QSharedPointer settings; + QHash userColors; }; -- cgit 1.5.1 From 1eb2869fa8d034a6619546f5628c3a0bae064e16 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 24 Feb 2020 01:07:25 +0100 Subject: Fix stuck unread messages by storing state events in the db This may increase the db size by a factor of 1000 in the worst case and it will need some fixes, when we decide to not show some events in the timeline, but it should work for now. --- src/Cache.cpp | 49 +++++++++++++++++++++++++++++++++++++------------ src/Cache_p.h | 1 + src/Utils.cpp | 4 ++-- 3 files changed, 40 insertions(+), 14 deletions(-) (limited to 'src/Cache_p.h') diff --git a/src/Cache.cpp b/src/Cache.cpp index 1361606f..856c2942 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -43,9 +43,9 @@ static lmdb::val NEXT_BATCH_KEY("next_batch"); static lmdb::val OLM_ACCOUNT_KEY("olm_account"); static lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version"); -constexpr size_t MAX_RESTORED_MESSAGES = 30; +constexpr size_t MAX_RESTORED_MESSAGES = 30'000; -constexpr auto DB_SIZE = 32UL * 1024UL * 1024UL * 1024ULL; // 32 GB +constexpr auto DB_SIZE = 32ULL * 1024ULL * 1024ULL * 1024ULL; // 32 GB constexpr auto MAX_DBS = 8092UL; //! Cache databases and their format. @@ -915,16 +915,17 @@ Cache::calculateRoomReadStatus(const std::string &room_id) auto txn = lmdb::txn::begin(env_); // Get last event id on the room. - const auto last_event_id = getLastMessageInfo(txn, room_id).event_id; + const auto last_event_id = getLastEventId(txn, room_id); const auto localUser = utils::localUser().toStdString(); - if (last_event_id.isEmpty()) - return false; - txn.commit(); + if (last_event_id.empty()) + return false; + // Retrieve all read receipts for that event. - const auto receipts = readReceipts(last_event_id, QString::fromStdString(room_id)); + const auto receipts = + readReceipts(QString::fromStdString(last_event_id), QString::fromStdString(room_id)); if (receipts.size() == 0) return true; @@ -1258,6 +1259,7 @@ Cache::getTimelineMentions() mtx::responses::Timeline Cache::getTimelineMessages(lmdb::txn &txn, const std::string &room_id) { + // TODO(nico): Limit the messages returned by this maybe? auto db = getMessagesDb(txn, room_id); mtx::responses::Timeline timeline; @@ -1325,6 +1327,31 @@ Cache::roomInfo(bool withInvites) return result; } +std::string +Cache::getLastEventId(lmdb::txn &txn, const std::string &room_id) +{ + auto db = getMessagesDb(txn, room_id); + + if (db.size(txn) == 0) + return {}; + + std::string timestamp, msg; + + auto cursor = lmdb::cursor::open(txn, db); + while (cursor.get(timestamp, msg, MDB_NEXT)) { + auto obj = json::parse(msg); + + if (obj.count("event") == 0) + continue; + + cursor.close(); + return obj["event"]["event_id"]; + } + cursor.close(); + + return {}; +} + DescInfo Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id) { @@ -1336,13 +1363,14 @@ Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id) std::string timestamp, msg; QSettings settings; - auto local_user = settings.value("auth/user_id").toString(); + const auto local_user = utils::localUser(); auto cursor = lmdb::cursor::open(txn, db); while (cursor.get(timestamp, msg, MDB_NEXT)) { auto obj = json::parse(msg); - if (obj.count("event") == 0) + if (obj.count("event") == 0 || !(obj["event"]["type"] == "m.room.message" || + obj["event"]["type"] == "m.sticker")) continue; mtx::events::collections::TimelineEvent event; @@ -1937,9 +1965,6 @@ Cache::saveTimelineMessages(lmdb::txn &txn, using namespace mtx::events::state; for (const auto &e : res.events) { - if (isStateEvent(e)) - continue; - if (std::holds_alternative>(e)) continue; diff --git a/src/Cache_p.h b/src/Cache_p.h index 137408b9..14ceafe8 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h @@ -250,6 +250,7 @@ private: QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); + std::string getLastEventId(lmdb::txn &txn, const std::string &room_id); DescInfo getLastMessageInfo(lmdb::txn &txn, const std::string &room_id); void saveTimelineMessages(lmdb::txn &txn, const std::string &room_id, diff --git a/src/Utils.cpp b/src/Utils.cpp index a185a207..33b75894 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -17,6 +17,7 @@ #include "Cache.h" #include "Config.h" +#include "MatrixClient.h" using TimelineEvent = mtx::events::collections::TimelineEvents; @@ -44,8 +45,7 @@ createDescriptionInfo(const Event &event, const QString &localUser, const QStrin QString utils::localUser() { - QSettings settings; - return settings.value("auth/user_id").toString(); + return QString::fromStdString(http::client()->user_id().to_string()); } QString -- cgit 1.5.1