Mark encrypted messages with a lock icon
This commit is contained in:
parent
95ce2ef920
commit
ccc6cd8dab
@ -97,6 +97,7 @@ constexpr int headerLeftMargin = 15;
|
|||||||
|
|
||||||
namespace fonts {
|
namespace fonts {
|
||||||
constexpr int timestamp = 13;
|
constexpr int timestamp = 13;
|
||||||
|
constexpr int indicator = timestamp - 2;
|
||||||
constexpr int dateSeparator = conf::fontSize;
|
constexpr int dateSeparator = conf::fontSize;
|
||||||
} // namespace fonts
|
} // namespace fonts
|
||||||
} // namespace timeline
|
} // namespace timeline
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QLayout>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
@ -43,6 +44,46 @@ class VideoItem;
|
|||||||
class FileItem;
|
class FileItem;
|
||||||
class Avatar;
|
class Avatar;
|
||||||
|
|
||||||
|
enum class StatusIndicatorState
|
||||||
|
{
|
||||||
|
//! The encrypted message was received by the server.
|
||||||
|
Encrypted,
|
||||||
|
//! The plaintext message was received by the server.
|
||||||
|
Received,
|
||||||
|
//! The client sent the message. Not yet received.
|
||||||
|
Sent,
|
||||||
|
//! When the message is loaded from cache or backfill.
|
||||||
|
Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
//!
|
||||||
|
//! Used to notify the user about the status of a message.
|
||||||
|
//!
|
||||||
|
class StatusIndicator : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit StatusIndicator(QWidget *parent);
|
||||||
|
void setState(StatusIndicatorState state);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paintIcon(QPainter &p, QIcon &icon);
|
||||||
|
|
||||||
|
QIcon lockIcon_;
|
||||||
|
QIcon clockIcon_;
|
||||||
|
QIcon checkmarkIcon_;
|
||||||
|
|
||||||
|
QColor iconColor_ = QColor("#999");
|
||||||
|
|
||||||
|
StatusIndicatorState state_ = StatusIndicatorState::Empty;
|
||||||
|
|
||||||
|
static constexpr int MaxWidth = 24;
|
||||||
|
};
|
||||||
|
|
||||||
class TextLabel : public QTextBrowser
|
class TextLabel : public QTextBrowser
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -192,7 +233,8 @@ public:
|
|||||||
DescInfo descriptionMessage() const { return descriptionMsg_; }
|
DescInfo descriptionMessage() const { return descriptionMsg_; }
|
||||||
QString eventId() const { return event_id_; }
|
QString eventId() const { return event_id_; }
|
||||||
void setEventId(const QString &event_id) { event_id_ = event_id; }
|
void setEventId(const QString &event_id) { event_id_ = event_id; }
|
||||||
void markReceived();
|
void markReceived(bool isEncrypted);
|
||||||
|
void markSent();
|
||||||
bool isReceived() { return isReceived_; };
|
bool isReceived() { return isReceived_; };
|
||||||
void setRoomId(QString room_id) { room_id_ = room_id; }
|
void setRoomId(QString room_id) { room_id_ = room_id; }
|
||||||
void sendReadReceipt() const;
|
void sendReadReceipt() const;
|
||||||
@ -228,6 +270,9 @@ private:
|
|||||||
void setupAvatarLayout(const QString &userName);
|
void setupAvatarLayout(const QString &userName);
|
||||||
void setupSimpleLayout();
|
void setupSimpleLayout();
|
||||||
|
|
||||||
|
void adjustMessageLayout();
|
||||||
|
void adjustMessageLayoutForWidget();
|
||||||
|
|
||||||
//! Whether or not the event associated with the widget
|
//! Whether or not the event associated with the widget
|
||||||
//! has been acknowledged by the server.
|
//! has been acknowledged by the server.
|
||||||
bool isReceived_ = false;
|
bool isReceived_ = false;
|
||||||
@ -247,7 +292,6 @@ private:
|
|||||||
QHBoxLayout *topLayout_ = nullptr;
|
QHBoxLayout *topLayout_ = nullptr;
|
||||||
QHBoxLayout *messageLayout_ = nullptr;
|
QHBoxLayout *messageLayout_ = nullptr;
|
||||||
QVBoxLayout *mainLayout_ = nullptr;
|
QVBoxLayout *mainLayout_ = nullptr;
|
||||||
QVBoxLayout *headerLayout_ = nullptr;
|
|
||||||
QHBoxLayout *widgetLayout_ = nullptr;
|
QHBoxLayout *widgetLayout_ = nullptr;
|
||||||
|
|
||||||
Avatar *userAvatar_;
|
Avatar *userAvatar_;
|
||||||
@ -255,8 +299,9 @@ private:
|
|||||||
QFont font_;
|
QFont font_;
|
||||||
QFont usernameFont_;
|
QFont usernameFont_;
|
||||||
|
|
||||||
|
StatusIndicator *statusIndicator_;
|
||||||
|
|
||||||
QLabel *timestamp_;
|
QLabel *timestamp_;
|
||||||
QLabel *checkmark_;
|
|
||||||
QLabel *userName_;
|
QLabel *userName_;
|
||||||
TextLabel *body_;
|
TextLabel *body_;
|
||||||
};
|
};
|
||||||
@ -285,20 +330,13 @@ TimelineItem::setupLocalWidgetLayout(Widget *widget, const QString &userid, bool
|
|||||||
generateBody(userid, displayName, "");
|
generateBody(userid, displayName, "");
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
headerLayout_->addLayout(widgetLayout_);
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
} else {
|
} else {
|
||||||
setupSimpleLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
messageLayout_->addLayout(widgetLayout_, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
adjustMessageLayoutForWidget();
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
mainLayout_->addLayout(messageLayout_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Event, class Widget>
|
template<class Event, class Widget>
|
||||||
@ -331,18 +369,11 @@ TimelineItem::setupWidgetLayout(Widget *widget, const Event &event, bool withSen
|
|||||||
generateBody(sender, displayName, "");
|
generateBody(sender, displayName, "");
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
headerLayout_->addLayout(widgetLayout_);
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
} else {
|
} else {
|
||||||
setupSimpleLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
messageLayout_->addLayout(widgetLayout_, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
adjustMessageLayoutForWidget();
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
mainLayout_->addLayout(messageLayout_);
|
|
||||||
}
|
}
|
||||||
|
BIN
resources/icons/ui/checkmark.png
Normal file
BIN
resources/icons/ui/checkmark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 450 B |
BIN
resources/icons/ui/checkmark@2x.png
Normal file
BIN
resources/icons/ui/checkmark@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 551 B |
BIN
resources/icons/ui/clock.png
Normal file
BIN
resources/icons/ui/clock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 779 B |
BIN
resources/icons/ui/clock@2x.png
Normal file
BIN
resources/icons/ui/clock@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
resources/icons/ui/lock.png
Normal file
BIN
resources/icons/ui/lock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 602 B |
BIN
resources/icons/ui/lock@2x.png
Normal file
BIN
resources/icons/ui/lock@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 810 B |
@ -1,5 +1,11 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/icons">
|
<qresource prefix="/icons">
|
||||||
|
<file>icons/ui/lock.png</file>
|
||||||
|
<file>icons/ui/lock@2x.png</file>
|
||||||
|
<file>icons/ui/clock.png</file>
|
||||||
|
<file>icons/ui/clock@2x.png</file>
|
||||||
|
<file>icons/ui/checkmark.png</file>
|
||||||
|
<file>icons/ui/checkmark@2x.png</file>
|
||||||
<file>icons/ui/cursor.png</file>
|
<file>icons/ui/cursor.png</file>
|
||||||
<file>icons/ui/cursor@2x.png</file>
|
<file>icons/ui/cursor@2x.png</file>
|
||||||
<file>icons/ui/settings.png</file>
|
<file>icons/ui/settings.png</file>
|
||||||
|
@ -48,7 +48,7 @@ CommunitiesList > * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FlatButton {
|
FlatButton {
|
||||||
qproperty-foregroundColor: #14272d;
|
qproperty-foregroundColor: #495057;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileItem {
|
FileItem {
|
||||||
|
32
src/main.cc
32
src/main.cc
@ -38,6 +38,36 @@
|
|||||||
#include "RunGuard.h"
|
#include "RunGuard.h"
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
|
#if defined(Q_OS_LINUX)
|
||||||
|
#include <boost/stacktrace.hpp>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
stacktraceHandler(int signum)
|
||||||
|
{
|
||||||
|
auto dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
|
||||||
|
|
||||||
|
std::signal(signum, SIG_DFL);
|
||||||
|
boost::stacktrace::safe_dump_to(dir.toStdString() + "/backtrace.dump");
|
||||||
|
std::raise(SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
registerSignalHandlers()
|
||||||
|
{
|
||||||
|
std::signal(SIGSEGV, &stacktraceHandler);
|
||||||
|
std::signal(SIGABRT, &stacktraceHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// No implementation for systems with no stacktrace support.
|
||||||
|
void
|
||||||
|
registerSignalHandlers()
|
||||||
|
{}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
QPoint
|
QPoint
|
||||||
screenCenter(int width, int height)
|
screenCenter(int width, int height)
|
||||||
{
|
{
|
||||||
@ -126,6 +156,8 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
createCacheDirectory();
|
createCacheDirectory();
|
||||||
|
|
||||||
|
registerSignalHandlers();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
nhlog::init(QString("%1/nheko.log")
|
nhlog::init(QString("%1/nheko.log")
|
||||||
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
.arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "ChatPage.h"
|
#include "ChatPage.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Logging.hpp"
|
#include "Logging.hpp"
|
||||||
|
#include "Painter.h"
|
||||||
|
|
||||||
#include "timeline/TimelineItem.h"
|
#include "timeline/TimelineItem.h"
|
||||||
#include "timeline/widgets/AudioItem.h"
|
#include "timeline/widgets/AudioItem.h"
|
||||||
@ -31,11 +32,90 @@
|
|||||||
#include "timeline/widgets/ImageItem.h"
|
#include "timeline/widgets/ImageItem.h"
|
||||||
#include "timeline/widgets/VideoItem.h"
|
#include "timeline/widgets/VideoItem.h"
|
||||||
|
|
||||||
constexpr const static char *CHECKMARK = "✓";
|
|
||||||
|
|
||||||
constexpr int MSG_RIGHT_MARGIN = 7;
|
constexpr int MSG_RIGHT_MARGIN = 7;
|
||||||
constexpr int MSG_PADDING = 20;
|
constexpr int MSG_PADDING = 20;
|
||||||
|
|
||||||
|
StatusIndicator::StatusIndicator(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
lockIcon_.addFile(":/icons/icons/ui/lock.png");
|
||||||
|
clockIcon_.addFile(":/icons/icons/ui/clock.png");
|
||||||
|
checkmarkIcon_.addFile(":/icons/icons/ui/checkmark.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StatusIndicator::paintIcon(QPainter &p, QIcon &icon)
|
||||||
|
{
|
||||||
|
auto pixmap = icon.pixmap(width());
|
||||||
|
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||||
|
painter.fillRect(pixmap.rect(), p.pen().color());
|
||||||
|
|
||||||
|
QIcon(pixmap).paint(&p, rect(), Qt::AlignCenter, QIcon::Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StatusIndicator::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
if (state_ == StatusIndicatorState::Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Painter p(this);
|
||||||
|
PainterHighQualityEnabler hq(p);
|
||||||
|
|
||||||
|
p.setPen(iconColor_);
|
||||||
|
|
||||||
|
switch (state_) {
|
||||||
|
case StatusIndicatorState::Sent: {
|
||||||
|
paintIcon(p, clockIcon_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StatusIndicatorState::Encrypted:
|
||||||
|
paintIcon(p, lockIcon_);
|
||||||
|
break;
|
||||||
|
case StatusIndicatorState::Received: {
|
||||||
|
paintIcon(p, checkmarkIcon_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StatusIndicatorState::Empty:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StatusIndicator::setState(StatusIndicatorState state)
|
||||||
|
{
|
||||||
|
state_ = state;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineItem::adjustMessageLayoutForWidget()
|
||||||
|
{
|
||||||
|
messageLayout_->addLayout(widgetLayout_, 1);
|
||||||
|
messageLayout_->addWidget(statusIndicator_);
|
||||||
|
messageLayout_->addWidget(timestamp_);
|
||||||
|
|
||||||
|
messageLayout_->setAlignment(statusIndicator_, Qt::AlignTop);
|
||||||
|
messageLayout_->setAlignment(timestamp_, Qt::AlignTop);
|
||||||
|
|
||||||
|
mainLayout_->addLayout(messageLayout_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineItem::adjustMessageLayout()
|
||||||
|
{
|
||||||
|
messageLayout_->addWidget(body_, 1);
|
||||||
|
messageLayout_->addWidget(statusIndicator_);
|
||||||
|
messageLayout_->addWidget(timestamp_);
|
||||||
|
|
||||||
|
messageLayout_->setAlignment(statusIndicator_, Qt::AlignTop);
|
||||||
|
messageLayout_->setAlignment(timestamp_, Qt::AlignTop);
|
||||||
|
|
||||||
|
mainLayout_->addLayout(messageLayout_);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineItem::init()
|
TimelineItem::init()
|
||||||
{
|
{
|
||||||
@ -102,14 +182,13 @@ TimelineItem::init()
|
|||||||
mainLayout_->setContentsMargins(conf::timeline::headerLeftMargin, 0, 0, 0);
|
mainLayout_->setContentsMargins(conf::timeline::headerLeftMargin, 0, 0, 0);
|
||||||
mainLayout_->setSpacing(0);
|
mainLayout_->setSpacing(0);
|
||||||
|
|
||||||
QFont checkmarkFont;
|
QFont timestampFont;
|
||||||
checkmarkFont.setPixelSize(conf::timeline::fonts::timestamp);
|
timestampFont.setPixelSize(conf::timeline::fonts::indicator);
|
||||||
|
QFontMetrics tsFm(timestampFont);
|
||||||
|
|
||||||
// Setting fixed width for checkmark because systems may have a differing width for a
|
statusIndicator_ = new StatusIndicator(this);
|
||||||
// space and the Unicode checkmark.
|
statusIndicator_->setFixedWidth(tsFm.height() - tsFm.leading());
|
||||||
checkmark_ = new QLabel(this);
|
statusIndicator_->setFixedHeight(tsFm.height() - tsFm.leading());
|
||||||
checkmark_->setFont(checkmarkFont);
|
|
||||||
checkmark_->setFixedWidth(QFontMetrics{checkmarkFont}.width(CHECKMARK));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -147,20 +226,14 @@ TimelineItem::TimelineItem(mtx::events::MessageType ty,
|
|||||||
generateBody(userid, displayName, body);
|
generateBody(userid, displayName, body);
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
} else {
|
} else {
|
||||||
generateBody(body);
|
generateBody(body);
|
||||||
setupSimpleLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
messageLayout_->addWidget(body_, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
adjustMessageLayout();
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
mainLayout_->addLayout(messageLayout_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(ImageItem *image,
|
TimelineItem::TimelineItem(ImageItem *image,
|
||||||
@ -316,20 +389,14 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Notice
|
|||||||
generateBody(sender, displayName, body);
|
generateBody(sender, displayName, body);
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
} else {
|
} else {
|
||||||
generateBody(body);
|
generateBody(body);
|
||||||
setupSimpleLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
messageLayout_->addWidget(body_, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
adjustMessageLayout();
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
mainLayout_->addLayout(messageLayout_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -364,20 +431,14 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Emote>
|
|||||||
generateBody(sender, displayName, emoteMsg);
|
generateBody(sender, displayName, emoteMsg);
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
} else {
|
} else {
|
||||||
generateBody(emoteMsg);
|
generateBody(emoteMsg);
|
||||||
setupSimpleLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
messageLayout_->addWidget(body_, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
adjustMessageLayout();
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
mainLayout_->addLayout(messageLayout_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -417,28 +478,31 @@ TimelineItem::TimelineItem(const mtx::events::RoomEvent<mtx::events::msg::Text>
|
|||||||
generateBody(sender, displayName, body);
|
generateBody(sender, displayName, body);
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, sender, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
} else {
|
} else {
|
||||||
generateBody(body);
|
generateBody(body);
|
||||||
setupSimpleLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
messageLayout_->addWidget(body_, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
adjustMessageLayout();
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
mainLayout_->addLayout(messageLayout_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineItem::markReceived()
|
TimelineItem::markSent()
|
||||||
|
{
|
||||||
|
statusIndicator_->setState(StatusIndicatorState::Sent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineItem::markReceived(bool isEncrypted)
|
||||||
{
|
{
|
||||||
isReceived_ = true;
|
isReceived_ = true;
|
||||||
checkmark_->setText(CHECKMARK);
|
|
||||||
checkmark_->setAlignment(Qt::AlignTop);
|
if (isEncrypted)
|
||||||
|
statusIndicator_->setState(StatusIndicatorState::Encrypted);
|
||||||
|
else
|
||||||
|
statusIndicator_->setState(StatusIndicatorState::Received);
|
||||||
|
|
||||||
sendReadReceipt();
|
sendReadReceipt();
|
||||||
}
|
}
|
||||||
@ -506,17 +570,10 @@ TimelineItem::generateTimestamp(const QDateTime &time)
|
|||||||
QFont timestampFont;
|
QFont timestampFont;
|
||||||
timestampFont.setPixelSize(conf::timeline::fonts::timestamp);
|
timestampFont.setPixelSize(conf::timeline::fonts::timestamp);
|
||||||
|
|
||||||
QFontMetrics fm(timestampFont);
|
|
||||||
int topMargin = QFontMetrics(font_).ascent() - fm.ascent();
|
|
||||||
|
|
||||||
timestamp_ = new QLabel(this);
|
timestamp_ = new QLabel(this);
|
||||||
timestamp_->setAlignment(Qt::AlignTop);
|
|
||||||
timestamp_->setFont(timestampFont);
|
timestamp_->setFont(timestampFont);
|
||||||
timestamp_->setText(
|
timestamp_->setText(
|
||||||
QString("<span style=\"color: #999\"> %1 </span>").arg(time.toString("HH:mm")));
|
QString("<span style=\"color: #999\"> %1 </span>").arg(time.toString("HH:mm")));
|
||||||
timestamp_->setContentsMargins(0, topMargin, 0, 0);
|
|
||||||
timestamp_->setStyleSheet(
|
|
||||||
QString("font-size: %1px;").arg(conf::timeline::fonts::timestamp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
@ -557,15 +614,8 @@ TimelineItem::setupAvatarLayout(const QString &userName)
|
|||||||
topLayout_->insertWidget(0, userAvatar_);
|
topLayout_->insertWidget(0, userAvatar_);
|
||||||
topLayout_->setAlignment(userAvatar_, Qt::AlignTop);
|
topLayout_->setAlignment(userAvatar_, Qt::AlignTop);
|
||||||
|
|
||||||
headerLayout_ = new QVBoxLayout;
|
|
||||||
headerLayout_->setMargin(0);
|
|
||||||
headerLayout_->setSpacing(conf::timeline::headerSpacing);
|
|
||||||
|
|
||||||
if (userName_)
|
if (userName_)
|
||||||
headerLayout_->addWidget(userName_);
|
mainLayout_->insertWidget(0, userName_);
|
||||||
|
|
||||||
if (body_)
|
|
||||||
headerLayout_->addWidget(body_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -647,33 +697,8 @@ TimelineItem::addAvatar()
|
|||||||
userName_->setFont(usernameFont_);
|
userName_->setFont(usernameFont_);
|
||||||
userName_->setText(fm.elidedText(displayName, Qt::ElideRight, 500));
|
userName_->setText(fm.elidedText(displayName, Qt::ElideRight, 500));
|
||||||
|
|
||||||
QWidget *widget = nullptr;
|
|
||||||
|
|
||||||
// Extract the widget before we delete its layout.
|
|
||||||
if (widgetLayout_)
|
|
||||||
widget = widgetLayout_->itemAt(0)->widget();
|
|
||||||
|
|
||||||
// Remove all items from the layout.
|
|
||||||
QLayoutItem *item;
|
|
||||||
while ((item = messageLayout_->takeAt(0)) != 0)
|
|
||||||
delete item;
|
|
||||||
|
|
||||||
setupAvatarLayout(displayName);
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
// Restore widget's layout.
|
|
||||||
if (widget) {
|
|
||||||
widgetLayout_ = new QHBoxLayout();
|
|
||||||
widgetLayout_->setContentsMargins(0, 2, 0, 2);
|
|
||||||
widgetLayout_->addWidget(widget);
|
|
||||||
widgetLayout_->addStretch(1);
|
|
||||||
|
|
||||||
headerLayout_->addLayout(widgetLayout_);
|
|
||||||
}
|
|
||||||
|
|
||||||
messageLayout_->addLayout(headerLayout_, 1);
|
|
||||||
messageLayout_->addWidget(checkmark_);
|
|
||||||
messageLayout_->addWidget(timestamp_);
|
|
||||||
|
|
||||||
AvatarProvider::resolve(
|
AvatarProvider::resolve(
|
||||||
room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
|
room_id_, userid, this, [this](const QImage &img) { setUserAvatar(img); });
|
||||||
}
|
}
|
||||||
|
@ -625,7 +625,7 @@ TimelineView::updatePendingMessage(const std::string &txn_id, const QString &eve
|
|||||||
// If the response comes after we have received the event from sync
|
// If the response comes after we have received the event from sync
|
||||||
// we've already marked the widget as received.
|
// we've already marked the widget as received.
|
||||||
if (!msg.widget->isReceived()) {
|
if (!msg.widget->isReceived()) {
|
||||||
msg.widget->markReceived();
|
msg.widget->markReceived(msg.is_encrypted);
|
||||||
pending_sent_msgs_.append(msg);
|
pending_sent_msgs_.append(msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -690,6 +690,9 @@ TimelineView::sendNextPendingMessage()
|
|||||||
|
|
||||||
nhlog::ui()->info("[{}] sending next queued message", m.txn_id);
|
nhlog::ui()->info("[{}] sending next queued message", m.txn_id);
|
||||||
|
|
||||||
|
if (m.widget)
|
||||||
|
m.widget->markSent();
|
||||||
|
|
||||||
if (m.is_encrypted) {
|
if (m.is_encrypted) {
|
||||||
nhlog::ui()->info("[{}] sending encrypted event", m.txn_id);
|
nhlog::ui()->info("[{}] sending encrypted event", m.txn_id);
|
||||||
prepareEncryptedMessage(std::move(m));
|
prepareEncryptedMessage(std::move(m));
|
||||||
@ -835,7 +838,7 @@ TimelineView::removePendingMessage(const std::string &txn_id)
|
|||||||
for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); ++it) {
|
for (auto it = pending_msgs_.begin(); it != pending_msgs_.end(); ++it) {
|
||||||
if (it->txn_id == txn_id) {
|
if (it->txn_id == txn_id) {
|
||||||
if (it->widget)
|
if (it->widget)
|
||||||
it->widget->markReceived();
|
it->widget->markReceived(it->is_encrypted);
|
||||||
|
|
||||||
nhlog::ui()->info("[{}] received sync before message response", txn_id);
|
nhlog::ui()->info("[{}] received sync before message response", txn_id);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user