summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-01-03 18:05:49 +0200
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-01-03 18:06:29 +0200
commiteaf05748ff1fc2b1ced8fdb329661ff20d6b7b85 (patch)
tree4d2f190f9662581f7ff8a1e95b146ba225e0a8a6 /include
parentAdd Alpine Linux installation instructions (#191) (diff)
downloadnheko-eaf05748ff1fc2b1ced8fdb329661ff20d6b7b85.tar.xz
Initial support for read receipts
Diffstat (limited to 'include')
-rw-r--r--include/AvatarProvider.h4
-rw-r--r--include/Cache.h55
-rw-r--r--include/ChatPage.h12
-rw-r--r--include/Config.h4
-rw-r--r--include/MainWindow.h2
-rw-r--r--include/dialogs/ReadReceipts.h50
-rw-r--r--include/timeline/TimelineItem.h8
-rw-r--r--include/ui/OverlayModal.h2
8 files changed, 132 insertions, 5 deletions
diff --git a/include/AvatarProvider.h b/include/AvatarProvider.h

index 906f2593..44bf1ad2 100644 --- a/include/AvatarProvider.h +++ b/include/AvatarProvider.h
@@ -36,7 +36,7 @@ class AvatarProvider : public QObject public: static void init(QSharedPointer<MatrixClient> client); - static void resolve(const QString &userId, TimelineItem *item); + static void resolve(const QString &userId, std::function<void(QImage)> callback); static void setAvatarUrl(const QString &userId, const QUrl &url); static void clear(); @@ -48,5 +48,5 @@ private: using UserID = QString; static QMap<UserID, AvatarData> avatars_; - static QMap<UserID, QList<TimelineItem *>> toBeResolved_; + static QMap<UserID, QList<std::function<void(QImage)>>> toBeResolved_; }; diff --git a/include/Cache.h b/include/Cache.h
index 1f6c59f0..ae58e418 100644 --- a/include/Cache.h +++ b/include/Cache.h
@@ -18,11 +18,52 @@ #pragma once #include <QDir> +#include <json.hpp> #include <lmdb++.h> #include <mtx/responses.hpp> class RoomState; +//! Used to uniquely identify a list of read receipts. +struct ReadReceiptKey +{ + std::string event_id; + std::string room_id; +}; + +inline void +to_json(json &j, const ReadReceiptKey &key) +{ + j = json{{"event_id", key.event_id}, {"room_id", key.room_id}}; +} + +inline void +from_json(const json &j, ReadReceiptKey &key) +{ + key.event_id = j.at("event_id").get<std::string>(); + key.room_id = j.at("room_id").get<std::string>(); +} + +//! Decribes a read receipt stored in cache. +struct ReadReceiptValue +{ + std::string user_id; + uint64_t ts; +}; + +inline void +to_json(json &j, const ReadReceiptValue &value) +{ + j = json{{"user_id", value.user_id}, {"ts", value.ts}}; +} + +inline void +from_json(const json &j, ReadReceiptValue &value) +{ + value.user_id = j.at("user_id").get<std::string>(); + value.ts = j.at("ts").get<uint64_t>(); +} + class Cache { public: @@ -48,6 +89,19 @@ public: bool isFormatValid(); void setCurrentFormat(); + //! 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<std::string, std::map<std::string, uint64_t>>; + void updateReadReceipt(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<uint64_t, std::string>; + UserReceipts readReceipts(const QString &event_id, const QString &room_id); + QByteArray image(const QString &url) const; void saveImage(const QString &url, const QByteArray &data); @@ -60,6 +114,7 @@ private: lmdb::dbi roomDb_; lmdb::dbi invitesDb_; lmdb::dbi imagesDb_; + lmdb::dbi readReceiptsDb_; bool isMounted_; diff --git a/include/ChatPage.h b/include/ChatPage.h
index 24fc6a25..584424c0 100644 --- a/include/ChatPage.h +++ b/include/ChatPage.h
@@ -42,6 +42,10 @@ class TypingDisplay; class UserInfoWidget; class UserSettings; +namespace dialogs { +class ReadReceipts; +} + constexpr int CONSENSUS_TIMEOUT = 1000; constexpr int SHOW_CONTENT_TIMEOUT = 3000; constexpr int TYPING_REFRESH_TIMEOUT = 10000; @@ -59,6 +63,9 @@ public: // Initialize all the components of the UI. void bootstrap(QString userid, QString homeserver, QString token); void showQuickSwitcher(); + void showReadReceipts(const QString &event_id); + + static ChatPage *instance() { return instance_; } signals: void contentLoaded(); @@ -84,6 +91,8 @@ private slots: void removeInvite(const QString &room_id); private: + static ChatPage *instance_; + using UserID = QString; using RoomStates = QMap<UserID, RoomState>; using Membership = mtx::events::StateEvent<mtx::events::state::Member>; @@ -150,6 +159,9 @@ private: QSharedPointer<QuickSwitcher> quickSwitcher_; QSharedPointer<OverlayModal> quickSwitcherModal_; + QSharedPointer<dialogs::ReadReceipts> receiptsDialog_; + QSharedPointer<OverlayModal> receiptsModal_; + // Matrix Client API provider. QSharedPointer<MatrixClient> client_; diff --git a/include/Config.h b/include/Config.h
index 7d35094e..5492e5fb 100644 --- a/include/Config.h +++ b/include/Config.h
@@ -15,6 +15,10 @@ static constexpr int emojiSize = 14; static constexpr int headerFontSize = 21; static constexpr int typingNotificationFontSize = 11; +namespace receipts { +static constexpr int font = 12; +} + namespace dialogs { static constexpr int labelSize = 15; } diff --git a/include/MainWindow.h b/include/MainWindow.h
index 2d047b51..d7c5e41d 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h
@@ -42,7 +42,7 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); - static MainWindow *instance(); + static MainWindow *instance() { return instance_; }; void saveCurrentWindowSize(); protected: diff --git a/include/dialogs/ReadReceipts.h b/include/dialogs/ReadReceipts.h new file mode 100644
index 00000000..42a9e1b7 --- /dev/null +++ b/include/dialogs/ReadReceipts.h
@@ -0,0 +1,50 @@ +#pragma once + +#include <QDateTime> +#include <QFrame> +#include <QHBoxLayout> +#include <QLabel> +#include <QListWidget> +#include <QVBoxLayout> + +class Avatar; + +namespace dialogs { + +class ReceiptItem : public QWidget +{ + Q_OBJECT + +public: + ReceiptItem(QWidget *parent, const QString &user_id, uint64_t timestamp); + +private: + QString dateFormat(const QDateTime &then) const; + + QHBoxLayout *topLayout_; + QVBoxLayout *textLayout_; + + Avatar *avatar_; + + QLabel *userName_; + QLabel *timestamp_; +}; + +class ReadReceipts : public QFrame +{ + Q_OBJECT +public: + explicit ReadReceipts(QWidget *parent = nullptr); + +public slots: + void addUsers(const std::multimap<uint64_t, std::string> &users); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + QLabel *topLabel_; + + QListWidget *userList_; +}; +} // dialogs diff --git a/include/timeline/TimelineItem.h b/include/timeline/TimelineItem.h
index f1498d1b..78fb95c9 100644 --- a/include/timeline/TimelineItem.h +++ b/include/timeline/TimelineItem.h
@@ -87,6 +87,7 @@ public: protected: void paintEvent(QPaintEvent *event) override; + void contextMenuEvent(QContextMenuEvent *event) override; private: void init(); @@ -116,6 +117,9 @@ private: DescInfo descriptionMsg_; + QMenu *receiptsMenu_; + QAction *showReadReceipts_; + QHBoxLayout *topLayout_; QVBoxLayout *sideLayout_; // Avatar or Timestamp QVBoxLayout *mainLayout_; // Header & Message body @@ -156,7 +160,7 @@ TimelineItem::setupLocalWidgetLayout(Widget *widget, setupAvatarLayout(displayName); mainLayout_->addLayout(headerLayout_); - AvatarProvider::resolve(userid, this); + AvatarProvider::resolve(userid, [=](const QImage &img) { setUserAvatar(img); }); } else { setupSimpleLayout(); } @@ -199,7 +203,7 @@ TimelineItem::setupWidgetLayout(Widget *widget, mainLayout_->addLayout(headerLayout_); - AvatarProvider::resolve(sender, this); + AvatarProvider::resolve(sender, [=](const QImage &img) { setUserAvatar(img); }); } else { setupSimpleLayout(); } diff --git a/include/ui/OverlayModal.h b/include/ui/OverlayModal.h
index 167ba71a..5f6b6eee 100644 --- a/include/ui/OverlayModal.h +++ b/include/ui/OverlayModal.h
@@ -18,6 +18,7 @@ #pragma once #include <QGraphicsOpacityEffect> +#include <QKeyEvent> #include <QPaintEvent> #include <QPropertyAnimation> @@ -37,6 +38,7 @@ public: protected: void paintEvent(QPaintEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; private: int duration_;