Add initial support for unread message count

- Add border width on Badge
This commit is contained in:
Konstantinos Sideris 2017-04-15 02:56:04 +03:00
parent 793c2136b7
commit 3b0ff1a4cd
11 changed files with 102 additions and 11 deletions

View file

@ -54,7 +54,7 @@ public:
~HistoryView(); ~HistoryView();
void addHistoryItem(const Event &event, const QString &color, bool with_sender); void addHistoryItem(const Event &event, const QString &color, bool with_sender);
void addEvents(const QList<Event> &events); int addEvents(const QList<Event> &events);
void addUserTextMessage(const QString &msg, int txn_id); void addUserTextMessage(const QString &msg, int txn_id);
void updatePendingMessage(int txn_id, QString event_id); void updatePendingMessage(int txn_id, QString event_id);
void clear(); void clear();

View file

@ -44,6 +44,9 @@ public:
static QString getUserColor(const QString &userid); static QString getUserColor(const QString &userid);
static QMap<QString, QString> NICK_COLORS; static QMap<QString, QString> NICK_COLORS;
signals:
void unreadMessages(QString roomid, int count);
public slots: public slots:
void setHistoryView(const RoomInfo &info); void setHistoryView(const RoomInfo &info);
void sendTextMessage(const QString &msg); void sendTextMessage(const QString &msg);

View file

@ -24,6 +24,7 @@
#include <QtWidgets/QWidget> #include <QtWidgets/QWidget>
#include "Avatar.h" #include "Avatar.h"
#include "Badge.h"
#include "RippleOverlay.h" #include "RippleOverlay.h"
#include "RoomInfo.h" #include "RoomInfo.h"
@ -35,6 +36,9 @@ public:
RoomInfoListItem(RoomInfo info, QWidget *parent = 0); RoomInfoListItem(RoomInfo info, QWidget *parent = 0);
~RoomInfoListItem(); ~RoomInfoListItem();
void updateUnreadMessageCount(int count);
void clearUnreadMessageCount();
inline bool isPressed(); inline bool isPressed();
inline RoomInfo info(); inline RoomInfo info();
inline void setAvatar(const QImage &avatar_image); inline void setAvatar(const QImage &avatar_image);
@ -67,12 +71,15 @@ private:
QLabel *roomTopic_; QLabel *roomTopic_;
Avatar *roomAvatar_; Avatar *roomAvatar_;
Badge *unreadMessagesBadge_;
QString pressed_style_; QString pressed_style_;
QString normal_style_; QString normal_style_;
bool is_pressed_; bool is_pressed_;
int max_height_; int max_height_;
int unread_msg_count_;
}; };
inline bool RoomInfoListItem::isPressed() inline bool RoomInfoListItem::isPressed()

View file

@ -52,6 +52,7 @@ signals:
public slots: public slots:
void updateRoomAvatar(const QString &roomid, const QPixmap &img); void updateRoomAvatar(const QString &roomid, const QPixmap &img);
void highlightSelectedRoom(const RoomInfo &info); void highlightSelectedRoom(const RoomInfo &info);
void updateUnreadMessageCount(const QString &roomid, int count);
private: private:
Ui::RoomList *ui; Ui::RoomList *ui;

View file

@ -30,6 +30,7 @@ public:
void setRelativeXPosition(qreal x); void setRelativeXPosition(qreal x);
void setRelativeYPosition(qreal y); void setRelativeYPosition(qreal y);
void setText(const QString &text); void setText(const QString &text);
void setDiameter(int diameter);
QIcon icon() const; QIcon icon() const;
QString text() const; QString text() const;
@ -40,9 +41,10 @@ public:
qreal relativeXPosition() const; qreal relativeXPosition() const;
qreal relativeYPosition() const; qreal relativeYPosition() const;
int diameter() const;
protected: protected:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
int getDiameter() const;
private: private:
void init(); void init();
@ -55,6 +57,7 @@ private:
QString text_; QString text_;
int padding_; int padding_;
int diameter_;
qreal x_; qreal x_;
qreal y_; qreal y_;

View file

@ -64,6 +64,11 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
view_manager_, view_manager_,
SLOT(setHistoryView(const RoomInfo &))); SLOT(setHistoryView(const RoomInfo &)));
connect(view_manager_,
SIGNAL(unreadMessages(const QString &, int)),
room_list_,
SLOT(updateUnreadMessageCount(const QString &, int)));
connect(text_input_, connect(text_input_,
SIGNAL(sendTextMessage(const QString &)), SIGNAL(sendTextMessage(const QString &)),
view_manager_, view_manager_,

View file

@ -50,11 +50,13 @@ void HistoryView::sliderRangeChanged(int min, int max)
scroll_area_->verticalScrollBar()->setValue(max); scroll_area_->verticalScrollBar()->setValue(max);
} }
void HistoryView::addEvents(const QList<Event> &events) int HistoryView::addEvents(const QList<Event> &events)
{ {
QSettings settings; QSettings settings;
auto local_user = settings.value("auth/user_id").toString(); auto local_user = settings.value("auth/user_id").toString();
int message_count = 0;
for (const auto &event : events) { for (const auto &event : events) {
if (event.type() == "m.room.message") { if (event.type() == "m.room.message") {
auto msg_type = event.content().value("msgtype").toString(); auto msg_type = event.content().value("msgtype").toString();
@ -70,9 +72,13 @@ void HistoryView::addEvents(const QList<Event> &events)
addHistoryItem(event, color, with_sender); addHistoryItem(event, color, with_sender);
last_sender_ = event.sender(); last_sender_ = event.sender();
message_count += 1;
} }
} }
} }
return message_count;
} }
void HistoryView::init() void HistoryView::init()

View file

@ -106,7 +106,11 @@ void HistoryViewManager::sync(const Rooms &rooms)
auto view = views_.value(roomid); auto view = views_.value(roomid);
auto events = it.value().timeline().events(); auto events = it.value().timeline().events();
view->addEvents(events); int msgs_added = view->addEvents(events);
// TODO: Take into account window focus
if (msgs_added > 0 && roomid != active_room_.id())
emit unreadMessages(roomid, msgs_added);
} }
} }

View file

@ -27,6 +27,7 @@ RoomInfoListItem::RoomInfoListItem(RoomInfo info, QWidget *parent)
, info_(info) , info_(info)
, is_pressed_(false) , is_pressed_(false)
, max_height_(60) , max_height_(60)
, unread_msg_count_(0)
{ {
normal_style_ = normal_style_ =
"QWidget { color: black; background-color: #f8fbfe}" "QWidget { color: black; background-color: #f8fbfe}"
@ -63,6 +64,16 @@ RoomInfoListItem::RoomInfoListItem(RoomInfo info, QWidget *parent)
roomAvatar_->setSize(max_height_ - 20); roomAvatar_->setSize(max_height_ - 20);
roomAvatar_->setTextColor("#555459"); roomAvatar_->setTextColor("#555459");
roomAvatar_->setBackgroundColor("#d6dde3"); roomAvatar_->setBackgroundColor("#d6dde3");
unreadMessagesBadge_ = new Badge(roomAvatar_);
unreadMessagesBadge_->setRelativePosition(12, 10);
unreadMessagesBadge_->setDiameter(5);
unreadMessagesBadge_->setBackgroundColor("#f8fbfe");
unreadMessagesBadge_->setTextColor("black");
// TODO: Initialize when nheko can restore messages from previous session.
unreadMessagesBadge_->hide();
avatarLayout_->addWidget(roomAvatar_); avatarLayout_->addWidget(roomAvatar_);
roomName_ = new QLabel(info_.name(), textWidget_); roomName_ = new QLabel(info_.name(), textWidget_);
@ -94,6 +105,20 @@ RoomInfoListItem::RoomInfoListItem(RoomInfo info, QWidget *parent)
setLayout(topLayout_); setLayout(topLayout_);
} }
void RoomInfoListItem::updateUnreadMessageCount(int count)
{
unread_msg_count_ += count;
unreadMessagesBadge_->setText(QString::number(unread_msg_count_));
unreadMessagesBadge_->show();
}
void RoomInfoListItem::clearUnreadMessageCount()
{
unread_msg_count_ = 0;
unreadMessagesBadge_->setText("");
unreadMessagesBadge_->hide();
}
void RoomInfoListItem::setPressedState(bool state) void RoomInfoListItem::setPressedState(bool state)
{ {
if (!is_pressed_ && state) { if (!is_pressed_ && state) {

View file

@ -81,6 +81,16 @@ RoomInfo RoomList::extractRoomInfo(const State &room_state)
return info; return info;
} }
void RoomList::updateUnreadMessageCount(const QString &roomid, int count)
{
if (!rooms_.contains(roomid)) {
qWarning() << "UpdateUnreadMessageCount: Unknown roomid";
return;
}
rooms_[roomid]->updateUnreadMessageCount(count);
}
void RoomList::setInitialRooms(const Rooms &rooms) void RoomList::setInitialRooms(const Rooms &rooms)
{ {
rooms_.clear(); rooms_.clear();
@ -117,6 +127,16 @@ void RoomList::highlightSelectedRoom(const RoomInfo &info)
{ {
emit roomChanged(info); emit roomChanged(info);
if (!rooms_.contains(info.id())) {
qDebug() << "RoomList: clicked unknown roomid";
return;
}
// TODO: Send a read receipt for the last event.
auto room = rooms_[info.id()];
room->clearUnreadMessageCount();
for (auto it = rooms_.constBegin(); it != rooms_.constEnd(); it++) { for (auto it = rooms_.constBegin(); it != rooms_.constEnd(); it++) {
if (it.key() != info.id()) if (it.key() != info.id())
it.value()->setPressedState(false); it.value()->setPressedState(false);

View file

@ -30,12 +30,14 @@ void Badge::init()
{ {
x_ = 0; x_ = 0;
y_ = 0; y_ = 0;
padding_ = 10; // TODO: Make padding configurable.
padding_ = 5;
diameter_ = 24;
setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_TransparentForMouseEvents);
QFont _font(font()); QFont _font(font());
_font.setPointSizeF(10); _font.setPointSizeF(7.5);
_font.setStyleName("Bold"); _font.setStyleName("Bold");
setFont(_font); setFont(_font);
@ -54,7 +56,7 @@ QIcon Badge::icon() const
QSize Badge::sizeHint() const QSize Badge::sizeHint() const
{ {
const int d = getDiameter(); const int d = diameter();
return QSize(d + 4, d + 4); return QSize(d + 4, d + 4);
} }
@ -141,6 +143,14 @@ void Badge::setText(const QString &text)
update(); update();
} }
void Badge::setDiameter(int diameter)
{
if (diameter > 0) {
diameter_ = diameter;
update();
}
}
void Badge::paintEvent(QPaintEvent *) void Badge::paintEvent(QPaintEvent *)
{ {
QPainter painter(this); QPainter painter(this);
@ -154,13 +164,20 @@ void Badge::paintEvent(QPaintEvent *)
painter.setBrush(brush); painter.setBrush(brush);
painter.setPen(Qt::NoPen); painter.setPen(Qt::NoPen);
const int d = getDiameter(); const int d = diameter();
QRectF r(0, 0, d, d); QRectF r(0, 0, d, d);
r.translate(QPointF((width() - d), (height() - d)) / 2); r.translate(QPointF((width() - d), (height() - d)) / 2);
if (icon_.isNull()) { if (icon_.isNull()) {
QPen pen;
// TODO: Make badge width configurable.
pen.setWidth(1);
pen.setColor(textColor());
painter.setPen(pen);
painter.drawEllipse(r); painter.drawEllipse(r);
painter.setPen(textColor()); painter.setPen(textColor());
painter.setBrush(Qt::NoBrush); painter.setBrush(Qt::NoBrush);
painter.drawText(r.translated(0, -0.5), Qt::AlignCenter, text_); painter.drawText(r.translated(0, -0.5), Qt::AlignCenter, text_);
@ -176,11 +193,11 @@ void Badge::paintEvent(QPaintEvent *)
} }
} }
int Badge::getDiameter() const int Badge::diameter() const
{ {
if (icon_.isNull()) { if (icon_.isNull()) {
return qMax(size_.width(), size_.height()) + padding_; return qMax(size_.width(), size_.height()) + padding_;
} }
// FIXME: Move this to Theme.h as the default
return 24; return diameter_;
} }