Initial support for read receipts
This commit is contained in:
parent
44ee1b549d
commit
eaf05748ff
19 changed files with 434 additions and 33 deletions
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public:
|
|||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
static MainWindow *instance();
|
||||
static MainWindow *instance() { return instance_; };
|
||||
void saveCurrentWindowSize();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
50
include/dialogs/ReadReceipts.h
Normal file
50
include/dialogs/ReadReceipts.h
Normal file
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue