summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-04-21 16:34:50 +0300
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-04-21 16:35:03 +0300
commit2f00fc51bf27708a9c0ac1ce186043059f93923e (patch)
tree2e65159dd08fd9576b18f7f1570b41b56029ccda /include
parentPopup improvements (diff)
downloadnheko-2f00fc51bf27708a9c0ac1ce186043059f93923e.tar.xz
Cache refactoring
Diffstat (limited to 'include')
-rw-r--r--include/AvatarProvider.h25
-rw-r--r--include/Cache.h317
-rw-r--r--include/ChatPage.h60
-rw-r--r--include/MatrixClient.h2
-rw-r--r--include/RoomInfoListItem.h42
-rw-r--r--include/RoomList.h19
-rw-r--r--include/SuggestionsPopup.hpp10
-rw-r--r--include/TextInputWidget.h7
-rw-r--r--include/Utils.h2
-rw-r--r--include/dialogs/ReadReceipts.h5
-rw-r--r--include/timeline/TimelineItem.h44
-rw-r--r--include/timeline/TimelineView.h9
-rw-r--r--include/timeline/TimelineViewManager.h5
13 files changed, 385 insertions, 162 deletions
diff --git a/include/AvatarProvider.h b/include/AvatarProvider.h

index 95a5765d..dabd609c 100644 --- a/include/AvatarProvider.h +++ b/include/AvatarProvider.h
@@ -17,45 +17,30 @@ #pragma once +#include <QHash> #include <QImage> #include <QSharedPointer> -#include <QUrl> #include <functional> class MatrixClient; class TimelineItem; -//! Saved cache data per user. -struct AvatarData -{ - //! The avatar image of the user. - QImage img; - //! The url that was used to download the avatar. - QUrl url; -}; - class AvatarProvider : public QObject { Q_OBJECT public: - static void init(QSharedPointer<MatrixClient> client); + static void init(QSharedPointer<MatrixClient> client) { client_ = client; } //! The callback is called with the downloaded avatar for the given user //! or the avatar is downloaded first and then saved for re-use. - static void resolve(const QString &userId, + static void resolve(const QString &room_id, + const QString &userId, QObject *receiver, std::function<void(QImage)> callback); - //! Used to initialize the mapping user -> avatar url. - static void setAvatarUrl(const QString &userId, const QUrl &url); //! Remove all saved data. static void clear() { avatars_.clear(); }; private: - //! Update the cache with the downloaded avatar. - static void updateAvatar(const QString &uid, const QImage &img); - static QSharedPointer<MatrixClient> client_; - - using UserID = QString; - static std::map<UserID, AvatarData> avatars_; + static QHash<QString, QImage> avatars_; }; diff --git a/include/Cache.h b/include/Cache.h
index 93668b8c..b3bc085b 100644 --- a/include/Cache.h +++ b/include/Cache.h
@@ -17,12 +17,23 @@ #pragma once +#include <QDebug> #include <QDir> #include <json.hpp> #include <lmdb++.h> #include <mtx/responses.hpp> #include "RoomState.h" +#include "Utils.h" + +struct SearchResult +{ + QString user_id; + QString display_name; +}; + +Q_DECLARE_METATYPE(SearchResult) +Q_DECLARE_METATYPE(QVector<SearchResult>) //! Used to uniquely identify a list of read receipts. struct ReadReceiptKey @@ -44,6 +55,60 @@ from_json(const json &j, ReadReceiptKey &key) key.room_id = j.at("room_id").get<std::string>(); } +//! UI info associated with a room. +struct RoomInfo +{ + //! The calculated name of the room. + std::string name; + //! The topic of the room. + std::string topic; + //! The calculated avatar url of the room. + std::string avatar_url; + //! Whether or not the room is an invite. + bool is_invite = false; +}; + +inline void +to_json(json &j, const RoomInfo &info) +{ + j["name"] = info.name; + j["topic"] = info.topic; + j["avatar_url"] = info.avatar_url; + j["is_invite"] = info.is_invite; +} + +inline void +from_json(const json &j, RoomInfo &info) +{ + info.name = j.at("name"); + info.topic = j.at("topic"); + info.avatar_url = j.at("avatar_url"); + info.is_invite = j.at("is_invite"); +} + +//! Basic information per member; +struct MemberInfo +{ + std::string name; + std::string avatar_url; +}; + +inline void +to_json(json &j, const MemberInfo &info) +{ + j["name"] = info.name; + j["avatar_url"] = info.avatar_url; +} + +inline void +from_json(const json &j, MemberInfo &info) +{ + info.name = j.at("name"); + info.avatar_url = j.at("avatar_url"); +} + +Q_DECLARE_METATYPE(RoomInfo) + class Cache : public QObject { Q_OBJECT @@ -51,22 +116,50 @@ class Cache : public QObject public: Cache(const QString &userId, QObject *parent = nullptr); - void setState(const QString &nextBatchToken, - const std::map<QString, QSharedPointer<RoomState>> &states); + static QHash<QString, QString> DisplayNames; + static QHash<QString, QString> AvatarUrls; + + 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 void removeDisplayName(const QString &room_id, const QString &user_id); + static void removeAvatarUrl(const QString &room_id, 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); + + //! Load saved data for the display names & avatars. + void populateMembers(); + std::vector<std::string> joinedRooms(); + + QMap<QString, RoomInfo> roomInfo(); + + //! Calculate & return the name of the room. + QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); + //! 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); + + void saveState(const mtx::responses::Sync &res); bool isInitialized() const; QString nextBatchToken() const; - void states(); - - using Invites = std::map<std::string, mtx::responses::InvitedRoom>; - Invites invites(); - void setInvites(const Invites &invites); void deleteData(); - void unmount() { isMounted_ = false; }; - void removeRoom(const QString &roomid); - void removeInvite(const QString &roomid); + 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(); @@ -88,24 +181,206 @@ public: QByteArray image(const QString &url) const; void saveImage(const QString &url, const QByteArray &data); -signals: - void statesLoaded(std::map<QString, RoomState> states); + std::vector<std::string> roomsWithStateUpdates(const mtx::responses::Sync &res); + std::map<QString, RoomInfo> getRoomInfo(const std::vector<std::string> &rooms); + std::map<QString, RoomInfo> roomUpdates(const mtx::responses::Sync &sync) + { + return getRoomInfo(roomsWithStateUpdates(sync)); + } + + QVector<SearchResult> getAutocompleteMatches(const std::string &room_id, + const std::string &query, + std::uint8_t max_items = 5); private: + //! Save an invited room. + void saveInvite(lmdb::txn &txn, + lmdb::dbi &statesdb, + lmdb::dbi &membersdb, + const mtx::responses::InvitedRoom &room); + + 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); + + //! Remove a room from the cache. + // void removeLeftRoom(lmdb::txn &txn, const std::string &room_id); + template<class T> + void saveStateEvents(lmdb::txn &txn, + const lmdb::dbi &statesdb, + const lmdb::dbi &membersdb, + const std::string &room_id, + const std::vector<T> &events) + { + for (const auto &e : events) + saveStateEvent(txn, statesdb, membersdb, room_id, e); + } + + template<class T> + 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 (mpark::holds_alternative<StateEvent<Member>>(event)) { + const auto e = mpark::get<StateEvent<Member>>(event); + + 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; + } + + if (!isStateEvent(event)) + return; + + mpark::visit( + [&txn, &statesdb](auto e) { + lmdb::dbi_put( + txn, statesdb, lmdb::val(to_string(e.type)), lmdb::val(json(e).dump())); + }, + event); + } + + template<class T> + bool isStateEvent(const T &e) + { + using namespace mtx::events; + using namespace mtx::events::state; + + return mpark::holds_alternative<StateEvent<Aliases>>(e) || + mpark::holds_alternative<StateEvent<state::Avatar>>(e) || + mpark::holds_alternative<StateEvent<CanonicalAlias>>(e) || + mpark::holds_alternative<StateEvent<Create>>(e) || + mpark::holds_alternative<StateEvent<GuestAccess>>(e) || + mpark::holds_alternative<StateEvent<HistoryVisibility>>(e) || + mpark::holds_alternative<StateEvent<JoinRules>>(e) || + mpark::holds_alternative<StateEvent<Name>>(e) || + mpark::holds_alternative<StateEvent<PowerLevels>>(e) || + mpark::holds_alternative<StateEvent<Topic>>(e); + } + + template<class T> + bool containsStateUpdates(const T &e) + { + using namespace mtx::events; + using namespace mtx::events::state; + + return mpark::holds_alternative<StateEvent<state::Avatar>>(e) || + mpark::holds_alternative<StateEvent<CanonicalAlias>>(e) || + mpark::holds_alternative<StateEvent<Name>>(e) || + mpark::holds_alternative<StateEvent<Member>>(e) || + mpark::holds_alternative<StateEvent<Topic>>(e); + } + + bool containsStateUpdates(const mtx::events::collections::StrippedEvents &e) + { + using namespace mtx::events; + using namespace mtx::events::state; + + return mpark::holds_alternative<StrippedEvent<state::Avatar>>(e) || + mpark::holds_alternative<StrippedEvent<CanonicalAlias>>(e) || + mpark::holds_alternative<StrippedEvent<Name>>(e) || + mpark::holds_alternative<StrippedEvent<Member>>(e) || + mpark::holds_alternative<StrippedEvent<Topic>>(e); + } + + void saveInvites(lmdb::txn &txn, + const std::map<std::string, mtx::responses::InvitedRoom> &rooms); + + //! Remove any saved invites that are not found in the input. + void removeStaleInvites(lmdb::txn &txn, const std::map<std::string, bool> &curr); + + //! Sends signals for the rooms that are removed. + void removeLeftRooms(lmdb::txn &txn, + const std::map<std::string, mtx::responses::LeftRoom> &rooms) + { + for (const auto &room : rooms) + removeRoom(txn, room.first); + } + + 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); + } + + QString getDisplayName(const mtx::events::StateEvent<mtx::events::state::Member> &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); - void insertRoomState(lmdb::txn &txn, - const QString &roomid, - const QSharedPointer<RoomState> &state); lmdb::env env_; - lmdb::dbi stateDb_; - lmdb::dbi roomDb_; + lmdb::dbi syncStateDb_; + lmdb::dbi roomsDb_; lmdb::dbi invitesDb_; - lmdb::dbi imagesDb_; + lmdb::dbi mediaDb_; lmdb::dbi readReceiptsDb_; - bool isMounted_; - - QString userId_; + QString localUserId_; QString cacheDirectory_; }; diff --git a/include/ChatPage.h b/include/ChatPage.h
index 25cd8615..a6789aea 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h
@@ -24,16 +24,16 @@ #include <QTimer> #include <QWidget> +#include "Cache.h" #include "CommunitiesList.h" #include "Community.h" + #include <mtx.hpp> -class Cache; class MatrixClient; class OverlayModal; class QuickSwitcher; class RoomList; -class RoomSettings; class RoomState; class SideBarActions; class Splitter; @@ -52,6 +52,9 @@ constexpr int CONSENSUS_TIMEOUT = 1000; constexpr int SHOW_CONTENT_TIMEOUT = 3000; constexpr int TYPING_REFRESH_TIMEOUT = 10000; +Q_DECLARE_METATYPE(mtx::responses::Rooms); +Q_DECLARE_METATYPE(std::vector<std::string>); + class ChatPage : public QWidget { Q_OBJECT @@ -88,6 +91,14 @@ signals: void showLoginPage(const QString &msg); void showUserSettingsPage(); void showOverlayProgressBar(); + void startConsesusTimer(); + + void initializeRoomList(QMap<QString, RoomInfo>); + void initializeViews(const mtx::responses::Rooms &rooms); + void initializeEmptyViews(const std::vector<std::string> &rooms); + void syncUI(const mtx::responses::Rooms &rooms); + void continueSync(const QString &next_batch); + void syncRoomlist(const std::map<QString, RoomInfo> &updates); private slots: void showUnreadMessageNotification(int count); @@ -98,9 +109,9 @@ private slots: void syncCompleted(const mtx::responses::Sync &response); void changeTopRoomInfo(const QString &room_id); void logout(); - void addRoom(const QString &room_id); void removeRoom(const QString &room_id); - void removeInvite(const QString &room_id); + //! Handles initial sync failures. + void retryInitialSync(int status_code = -1); private: static ChatPage *instance_; @@ -110,28 +121,11 @@ private: using Membership = mtx::events::StateEvent<mtx::events::state::Member>; using Memberships = std::map<std::string, Membership>; - using JoinedRooms = std::map<std::string, mtx::responses::JoinedRoom>; - using LeftRooms = std::map<std::string, mtx::responses::LeftRoom>; - using InvitedRooms = std::map<std::string, mtx::responses::InvitedRoom>; - + using LeftRooms = std::map<std::string, mtx::responses::LeftRoom>; void removeLeftRooms(const LeftRooms &rooms); - void updateJoinedRooms(const JoinedRooms &rooms); - void trackInvites(const InvitedRooms &rooms) - { - for (const auto &invite : rooms) - roomInvites_[QString::fromStdString(invite.first)] = true; - } - - std::map<QString, QSharedPointer<RoomState>> generateMembershipDifference( - const JoinedRooms &rooms, - const RoomStates &states) const; void updateTypingUsers(const QString &roomid, const std::vector<std::string> &user_ids); - using MemberEvent = mtx::events::StateEvent<mtx::events::state::Member>; - void updateUserDisplayName(const MemberEvent &event); - void updateUserAvatarUrl(const MemberEvent &event); - void loadStateFromCache(); void deleteConfigs(); void resetUI(); @@ -141,10 +135,6 @@ private: template<class Collection> Memberships getMemberships(const std::vector<Collection> &events) const; - template<class Collection> - void updateUserMetadata(const std::vector<Collection> &collection); - - void retryInitialSync(int status_code = -1); //! Update the room with the new notification count. void updateRoomNotificationCount(const QString &room_id, uint16_t notification_count); @@ -186,8 +176,6 @@ private: UserInfoWidget *user_info_widget_; RoomStates roomStates_; - std::map<QString, QSharedPointer<RoomSettings>> roomSettings_; - std::map<QString, bool> roomInvites_; std::map<QString, QSharedPointer<Community>> communities_; @@ -212,22 +200,6 @@ private: }; template<class Collection> -void -ChatPage::updateUserMetadata(const std::vector<Collection> &collection) -{ - using Member = mtx::events::StateEvent<mtx::events::state::Member>; - - for (const auto &event : collection) { - if (mpark::holds_alternative<Member>(event)) { - auto member = mpark::get<Member>(event); - - updateUserAvatarUrl(member); - updateUserDisplayName(member); - } - } -} - -template<class Collection> std::map<std::string, mtx::events::StateEvent<mtx::events::state::Member>> ChatPage::getMemberships(const std::vector<Collection> &collection) const { diff --git a/include/MatrixClient.h b/include/MatrixClient.h
index 62ac2088..d16031d3 100644 --- a/include/MatrixClient.h +++ b/include/MatrixClient.h
@@ -32,6 +32,8 @@ signals: void avatarDownloaded(const QImage &img); }; +Q_DECLARE_METATYPE(mtx::responses::Sync) + /* * MatrixClient provides the high level API to communicate with * a Matrix homeserver. All the responses are returned through signals. diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h
index 35214c30..d06a759e 100644 --- a/include/RoomInfoListItem.h +++ b/include/RoomInfoListItem.h
@@ -24,11 +24,9 @@ #include <mtx/responses.hpp> -#include "RoomState.h" - class Menu; class RippleOverlay; -class RoomSettings; +struct RoomInfo; struct DescInfo { @@ -70,24 +68,13 @@ class RoomInfoListItem : public QWidget Q_PROPERTY(QColor btnTextColor READ btnTextColor WRITE setBtnTextColor) public: - RoomInfoListItem(QSharedPointer<RoomSettings> settings, - QSharedPointer<RoomState> state, - QString room_id, - QWidget *parent = 0); - - RoomInfoListItem(QString room_id, mtx::responses::InvitedRoom room, QWidget *parent = 0); + RoomInfoListItem(QString room_id, RoomInfo info, QWidget *parent = 0); void updateUnreadMessageCount(int count); void clearUnreadMessageCount() { updateUnreadMessageCount(0); }; - void setState(QSharedPointer<RoomState> state) - { - state_ = state; - update(); - } QString roomId() { return roomId_; } bool isPressed() const { return isPressed_; } - QSharedPointer<RoomState> state() const { return state_; } int unreadMessageCount() const { return unreadMsgCount_; } void setAvatar(const QImage &avatar_image); @@ -133,6 +120,15 @@ public: void setBubbleFgColor(QColor &color) { bubbleFgColor_ = color; } void setBubbleBgColor(QColor &color) { bubbleBgColor_ = color; } + void setRoomName(const QString &name) { roomName_ = name; } + void setRoomType(bool isInvite) + { + if (isInvite) + roomType_ = RoomType::Invited; + else + roomType_ = RoomType::Joined; + } + signals: void clicked(const QString &room_id); void leaveRoom(const QString &room_id); @@ -150,15 +146,7 @@ protected: private: void init(QWidget *parent); - QString roomName() - { - if (roomType_ == RoomType::Joined) - return state_->getName(); - - return roomName_; - } - - QString notificationText(); + QString roomName() { return roomName_; } RippleOverlay *ripple_overlay_; @@ -170,9 +158,6 @@ private: RoomType roomType_ = RoomType::Joined; - // State information for the joined rooms. - QSharedPointer<RoomState> state_; - // State information for the invited rooms. mtx::responses::InvitedRoom invitedRoom_; @@ -184,11 +169,8 @@ private: QPixmap roomAvatar_; Menu *menu_; - QAction *toggleNotifications_; QAction *leaveRoom_; - QSharedPointer<RoomSettings> roomSettings_; - bool isPressed_ = false; int unreadMsgCount_ = 0; diff --git a/include/RoomList.h b/include/RoomList.h
index bcac8094..f9cdc210 100644 --- a/include/RoomList.h +++ b/include/RoomList.h
@@ -23,14 +23,13 @@ #include <QVBoxLayout> #include <QWidget> +#include "Cache.h" #include <mtx.hpp> class LeaveRoomDialog; class MatrixClient; -class Cache; class OverlayModal; class RoomInfoListItem; -class RoomSettings; class RoomState; class Sync; class UserSettings; @@ -46,22 +45,18 @@ public: QWidget *parent = 0); void setCache(QSharedPointer<Cache> cache) { cache_ = cache; } - void setInitialRooms(const std::map<QString, QSharedPointer<RoomSettings>> &settings, - const std::map<QString, QSharedPointer<RoomState>> &states); - void sync(const std::map<QString, QSharedPointer<RoomState>> &states, - const std::map<QString, QSharedPointer<RoomSettings>> &settings); - void syncInvites(const std::map<std::string, mtx::responses::InvitedRoom> &rooms); + void initialize(const QMap<QString, RoomInfo> &info); + void sync(const std::map<QString, RoomInfo> &info); - void clear(); + void clear() { rooms_.clear(); }; void updateAvatar(const QString &room_id, const QString &url); - void addRoom(const QSharedPointer<RoomSettings> &settings, - const QSharedPointer<RoomState> &state, - const QString &room_id); - void addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRoom &room); + void addRoom(const QString &room_id, const RoomInfo &info); + void addInvitedRoom(const QString &room_id, const RoomInfo &info); void removeRoom(const QString &room_id, bool reset); void setFilterRooms(bool filterRooms); void setRoomFilter(std::vector<QString> room_ids); + void updateRoom(const QString &room_id, const RoomInfo &info); signals: void roomChanged(const QString &room_id); diff --git a/include/SuggestionsPopup.hpp b/include/SuggestionsPopup.hpp
index dcbe52fa..64a86d7a 100644 --- a/include/SuggestionsPopup.hpp +++ b/include/SuggestionsPopup.hpp
@@ -6,15 +6,7 @@ #include <QWidget> class Avatar; - -struct SearchResult -{ - QString user_id; - QString display_name; -}; - -Q_DECLARE_METATYPE(SearchResult) -Q_DECLARE_METATYPE(QVector<SearchResult>) +struct SearchResult; class PopupItem : public QWidget { diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h
index 7a52ea77..1f122504 100644 --- a/include/TextInputWidget.h +++ b/include/TextInputWidget.h
@@ -36,7 +36,7 @@ #include "emoji/PickButton.h" -class RoomState; +class Cache; namespace dialogs { class PreviewUploadOverlay; @@ -131,12 +131,12 @@ public: QColor borderColor() const { return borderColor_; } void setBorderColor(QColor &color) { borderColor_ = color; } + void setCache(QSharedPointer<Cache> cache) { cache_ = cache; } public slots: void openFileSelection(); void hideUploadSpinner(); void focusLineEdit() { input_->setFocus(); } - void setRoomState(QSharedPointer<RoomState> state) { currState_ = state; } private slots: void addSelectedEmoji(const QString &emoji); @@ -172,8 +172,7 @@ private: FlatButton *sendMessageBtn_; emoji::PickButton *emojiBtn_; - //! State of the current room. - QSharedPointer<RoomState> currState_; + QSharedPointer<Cache> cache_; QColor borderColor_; }; diff --git a/include/Utils.h b/include/Utils.h
index cbecb4ac..5586a479 100644 --- a/include/Utils.h +++ b/include/Utils.h
@@ -16,7 +16,7 @@ descriptiveTime(const QDateTime &then); //! Generate a message description from the event to be displayed //! in the RoomList. DescInfo -getMessageDescription(const TimelineEvent &event, const QString &localUser); +getMessageDescription(const TimelineEvent &event, const QString &localUser, const QString &room_id); //! Get the first character of a string, taking into account that //! surrogate pairs might be in use. diff --git a/include/dialogs/ReadReceipts.h b/include/dialogs/ReadReceipts.h
index 8f860b46..bd4e4fc5 100644 --- a/include/dialogs/ReadReceipts.h +++ b/include/dialogs/ReadReceipts.h
@@ -16,7 +16,10 @@ class ReceiptItem : public QWidget Q_OBJECT public: - ReceiptItem(QWidget *parent, const QString &user_id, uint64_t timestamp); + ReceiptItem(QWidget *parent, + const QString &user_id, + uint64_t timestamp, + const QString &room_id); private: QString dateFormat(const QDateTime &then) const; diff --git a/include/timeline/TimelineItem.h b/include/timeline/TimelineItem.h
index b7a5623f..952fb661 100644 --- a/include/timeline/TimelineItem.h +++ b/include/timeline/TimelineItem.h
@@ -26,9 +26,9 @@ #include <QStyleOption> #include "AvatarProvider.h" +#include "Cache.h" #include "ChatPage.h" #include "RoomInfoListItem.h" -#include "TimelineViewManager.h" #include "Utils.h" class ImageItem; @@ -43,12 +43,15 @@ class TimelineItem : public QWidget public: TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Notice> &e, bool with_sender, + const QString &room_id, QWidget *parent = 0); TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Text> &e, bool with_sender, + const QString &room_id, QWidget *parent = 0); TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Emote> &e, bool with_sender, + const QString &room_id, QWidget *parent = 0); // For local messages. @@ -57,28 +60,49 @@ public: const QString &userid, QString body, bool withSender, + const QString &room_id, QWidget *parent = 0); // m.image - TimelineItem(ImageItem *item, const QString &userid, bool withSender, QWidget *parent = 0); - TimelineItem(FileItem *item, const QString &userid, bool withSender, QWidget *parent = 0); - TimelineItem(AudioItem *item, const QString &userid, bool withSender, QWidget *parent = 0); - TimelineItem(VideoItem *item, const QString &userid, bool withSender, QWidget *parent = 0); + TimelineItem(ImageItem *item, + const QString &userid, + bool withSender, + const QString &room_id, + QWidget *parent = 0); + TimelineItem(FileItem *item, + const QString &userid, + bool withSender, + const QString &room_id, + QWidget *parent = 0); + TimelineItem(AudioItem *item, + const QString &userid, + bool withSender, + const QString &room_id, + QWidget *parent = 0); + TimelineItem(VideoItem *item, + const QString &userid, + bool withSender, + const QString &room_id, + QWidget *parent = 0); TimelineItem(ImageItem *img, const mtx::events::RoomEvent<mtx::events::msg::Image> &e, bool with_sender, + const QString &room_id, QWidget *parent); TimelineItem(FileItem *file, const mtx::events::RoomEvent<mtx::events::msg::File> &e, bool with_sender, + const QString &room_id, QWidget *parent); TimelineItem(AudioItem *audio, const mtx::events::RoomEvent<mtx::events::msg::Audio> &e, bool with_sender, + const QString &room_id, QWidget *parent); TimelineItem(VideoItem *video, const mtx::events::RoomEvent<mtx::events::msg::Video> &e, bool with_sender, + const QString &room_id, QWidget *parent); void setUserAvatar(const QImage &pixmap); @@ -86,7 +110,7 @@ public: QString eventId() const { return event_id_; } void setEventId(const QString &event_id) { event_id_ = event_id; } void markReceived(); - void setRoomId(const QString &room_id) { room_id_ = room_id; } + void setRoomId(QString room_id) { room_id_ = room_id; } void sendReadReceipt() const { if (!event_id_.isEmpty()) @@ -159,7 +183,7 @@ TimelineItem::setupLocalWidgetLayout(Widget *widget, const QString &msgDescription, bool withSender) { - auto displayName = TimelineViewManager::displayName(userid); + auto displayName = Cache::displayName(room_id_, userid); auto timestamp = QDateTime::currentDateTime(); descriptionMsg_ = {"You", @@ -183,7 +207,7 @@ TimelineItem::setupLocalWidgetLayout(Widget *widget, messageLayout_->addLayout(headerLayout_, 1); AvatarProvider::resolve( - userid, this, [this](const QImage &img) { setUserAvatar(img); }); + room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); }); } else { setupSimpleLayout(); @@ -208,7 +232,7 @@ TimelineItem::setupWidgetLayout(Widget *widget, const auto sender = QString::fromStdString(event.sender); auto timestamp = QDateTime::fromMSecsSinceEpoch(event.origin_server_ts); - auto displayName = TimelineViewManager::displayName(sender); + auto displayName = Cache::displayName(room_id_, sender); QSettings settings; descriptionMsg_ = {sender == settings.value("auth/user_id") ? "You" : displayName, @@ -232,7 +256,7 @@ TimelineItem::setupWidgetLayout(Widget *widget, messageLayout_->addLayout(headerLayout_, 1); AvatarProvider::resolve( - sender, this, [this](const QImage &img) { setUserAvatar(img); }); + room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); }); } else { setupSimpleLayout(); diff --git a/include/timeline/TimelineView.h b/include/timeline/TimelineView.h
index b38d6a7d..6f70dd1c 100644 --- a/include/timeline/TimelineView.h +++ b/include/timeline/TimelineView.h
@@ -259,8 +259,7 @@ TimelineView::addUserMessage(const QString &url, auto widget = new Widget(client_, url, trimmed, size, this); TimelineItem *view_item = - new TimelineItem(widget, local_user_, with_sender, scroll_widget_); - view_item->setRoomId(room_id_); + new TimelineItem(widget, local_user_, with_sender, room_id_, scroll_widget_); addTimelineItem(view_item); @@ -280,8 +279,7 @@ template<class Event> TimelineItem * TimelineView::createTimelineItem(const Event &event, bool withSender) { - TimelineItem *item = new TimelineItem(event, withSender, scroll_widget_); - item->setRoomId(room_id_); + TimelineItem *item = new TimelineItem(event, withSender, room_id_, scroll_widget_); return item; } @@ -290,8 +288,7 @@ TimelineItem * TimelineView::createTimelineItem(const Event &event, bool withSender) { auto eventWidget = new Widget(client_, event); - auto item = new TimelineItem(eventWidget, event, withSender, scroll_widget_); - item->setRoomId(room_id_); + auto item = new TimelineItem(eventWidget, event, withSender, room_id_, scroll_widget_); return item; } diff --git a/include/timeline/TimelineViewManager.h b/include/timeline/TimelineViewManager.h
index c7bbd71a..4c994098 100644 --- a/include/timeline/TimelineViewManager.h +++ b/include/timeline/TimelineViewManager.h
@@ -39,7 +39,7 @@ public: // Initialize with timeline events. void initialize(const mtx::responses::Rooms &rooms); // Empty initialization. - void initialize(const std::vector<QString> &rooms); + void initialize(const std::vector<std::string> &rooms); void addRoom(const mtx::responses::JoinedRoom &room, const QString &room_id); void addRoom(const QString &room_id); @@ -51,9 +51,6 @@ public: bool hasLoaded() const; static QString chooseRandomColor(); - static QString displayName(const QString &userid); - - static std::map<QString, QString> DISPLAY_NAMES; signals: void clearRoomMessageCount(QString roomid);