From 3b0ff1a4cdd0c7eb3ed06eec2e70ee2722b7c4e5 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Sat, 15 Apr 2017 02:56:04 +0300 Subject: [PATCH] Add initial support for unread message count - Add border width on Badge --- include/HistoryView.h | 2 +- include/HistoryViewManager.h | 3 +++ include/RoomInfoListItem.h | 7 +++++++ include/RoomList.h | 1 + include/ui/Badge.h | 5 ++++- src/ChatPage.cc | 5 +++++ src/HistoryView.cc | 8 +++++++- src/HistoryViewManager.cc | 6 +++++- src/RoomInfoListItem.cc | 25 +++++++++++++++++++++++++ src/RoomList.cc | 20 ++++++++++++++++++++ src/ui/Badge.cc | 31 ++++++++++++++++++++++++------- 11 files changed, 102 insertions(+), 11 deletions(-) diff --git a/include/HistoryView.h b/include/HistoryView.h index 09f8bdce..9ca0a156 100644 --- a/include/HistoryView.h +++ b/include/HistoryView.h @@ -54,7 +54,7 @@ public: ~HistoryView(); void addHistoryItem(const Event &event, const QString &color, bool with_sender); - void addEvents(const QList &events); + int addEvents(const QList &events); void addUserTextMessage(const QString &msg, int txn_id); void updatePendingMessage(int txn_id, QString event_id); void clear(); diff --git a/include/HistoryViewManager.h b/include/HistoryViewManager.h index 99ab7384..71700035 100644 --- a/include/HistoryViewManager.h +++ b/include/HistoryViewManager.h @@ -44,6 +44,9 @@ public: static QString getUserColor(const QString &userid); static QMap NICK_COLORS; +signals: + void unreadMessages(QString roomid, int count); + public slots: void setHistoryView(const RoomInfo &info); void sendTextMessage(const QString &msg); diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h index 8e19abc1..24e84bd3 100644 --- a/include/RoomInfoListItem.h +++ b/include/RoomInfoListItem.h @@ -24,6 +24,7 @@ #include #include "Avatar.h" +#include "Badge.h" #include "RippleOverlay.h" #include "RoomInfo.h" @@ -35,6 +36,9 @@ public: RoomInfoListItem(RoomInfo info, QWidget *parent = 0); ~RoomInfoListItem(); + void updateUnreadMessageCount(int count); + void clearUnreadMessageCount(); + inline bool isPressed(); inline RoomInfo info(); inline void setAvatar(const QImage &avatar_image); @@ -67,12 +71,15 @@ private: QLabel *roomTopic_; Avatar *roomAvatar_; + Badge *unreadMessagesBadge_; QString pressed_style_; QString normal_style_; bool is_pressed_; + int max_height_; + int unread_msg_count_; }; inline bool RoomInfoListItem::isPressed() diff --git a/include/RoomList.h b/include/RoomList.h index 42ded171..d6066166 100644 --- a/include/RoomList.h +++ b/include/RoomList.h @@ -52,6 +52,7 @@ signals: public slots: void updateRoomAvatar(const QString &roomid, const QPixmap &img); void highlightSelectedRoom(const RoomInfo &info); + void updateUnreadMessageCount(const QString &roomid, int count); private: Ui::RoomList *ui; diff --git a/include/ui/Badge.h b/include/ui/Badge.h index 774b03ad..d84dd7ef 100644 --- a/include/ui/Badge.h +++ b/include/ui/Badge.h @@ -30,6 +30,7 @@ public: void setRelativeXPosition(qreal x); void setRelativeYPosition(qreal y); void setText(const QString &text); + void setDiameter(int diameter); QIcon icon() const; QString text() const; @@ -40,9 +41,10 @@ public: qreal relativeXPosition() const; qreal relativeYPosition() const; + int diameter() const; + protected: void paintEvent(QPaintEvent *event) override; - int getDiameter() const; private: void init(); @@ -55,6 +57,7 @@ private: QString text_; int padding_; + int diameter_; qreal x_; qreal y_; diff --git a/src/ChatPage.cc b/src/ChatPage.cc index dfe1505e..33cacb3e 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -64,6 +64,11 @@ ChatPage::ChatPage(QSharedPointer client, QWidget *parent) view_manager_, SLOT(setHistoryView(const RoomInfo &))); + connect(view_manager_, + SIGNAL(unreadMessages(const QString &, int)), + room_list_, + SLOT(updateUnreadMessageCount(const QString &, int))); + connect(text_input_, SIGNAL(sendTextMessage(const QString &)), view_manager_, diff --git a/src/HistoryView.cc b/src/HistoryView.cc index 374fe133..2d54caca 100644 --- a/src/HistoryView.cc +++ b/src/HistoryView.cc @@ -50,11 +50,13 @@ void HistoryView::sliderRangeChanged(int min, int max) scroll_area_->verticalScrollBar()->setValue(max); } -void HistoryView::addEvents(const QList &events) +int HistoryView::addEvents(const QList &events) { QSettings settings; auto local_user = settings.value("auth/user_id").toString(); + int message_count = 0; + for (const auto &event : events) { if (event.type() == "m.room.message") { auto msg_type = event.content().value("msgtype").toString(); @@ -70,9 +72,13 @@ void HistoryView::addEvents(const QList &events) addHistoryItem(event, color, with_sender); last_sender_ = event.sender(); + + message_count += 1; } } } + + return message_count; } void HistoryView::init() diff --git a/src/HistoryViewManager.cc b/src/HistoryViewManager.cc index 20a42f3b..1b1244f4 100644 --- a/src/HistoryViewManager.cc +++ b/src/HistoryViewManager.cc @@ -106,7 +106,11 @@ void HistoryViewManager::sync(const Rooms &rooms) auto view = views_.value(roomid); 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); } } diff --git a/src/RoomInfoListItem.cc b/src/RoomInfoListItem.cc index ddb3ba55..41593a42 100644 --- a/src/RoomInfoListItem.cc +++ b/src/RoomInfoListItem.cc @@ -27,6 +27,7 @@ RoomInfoListItem::RoomInfoListItem(RoomInfo info, QWidget *parent) , info_(info) , is_pressed_(false) , max_height_(60) + , unread_msg_count_(0) { normal_style_ = "QWidget { color: black; background-color: #f8fbfe}" @@ -63,6 +64,16 @@ RoomInfoListItem::RoomInfoListItem(RoomInfo info, QWidget *parent) roomAvatar_->setSize(max_height_ - 20); roomAvatar_->setTextColor("#555459"); 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_); roomName_ = new QLabel(info_.name(), textWidget_); @@ -94,6 +105,20 @@ RoomInfoListItem::RoomInfoListItem(RoomInfo info, QWidget *parent) 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) { if (!is_pressed_ && state) { diff --git a/src/RoomList.cc b/src/RoomList.cc index f483a798..b1186d39 100644 --- a/src/RoomList.cc +++ b/src/RoomList.cc @@ -81,6 +81,16 @@ RoomInfo RoomList::extractRoomInfo(const State &room_state) 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) { rooms_.clear(); @@ -117,6 +127,16 @@ void RoomList::highlightSelectedRoom(const RoomInfo &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++) { if (it.key() != info.id()) it.value()->setPressedState(false); diff --git a/src/ui/Badge.cc b/src/ui/Badge.cc index 05531f6c..c799dbf2 100644 --- a/src/ui/Badge.cc +++ b/src/ui/Badge.cc @@ -30,12 +30,14 @@ void Badge::init() { x_ = 0; y_ = 0; - padding_ = 10; + // TODO: Make padding configurable. + padding_ = 5; + diameter_ = 24; setAttribute(Qt::WA_TransparentForMouseEvents); QFont _font(font()); - _font.setPointSizeF(10); + _font.setPointSizeF(7.5); _font.setStyleName("Bold"); setFont(_font); @@ -54,7 +56,7 @@ QIcon Badge::icon() const QSize Badge::sizeHint() const { - const int d = getDiameter(); + const int d = diameter(); return QSize(d + 4, d + 4); } @@ -141,6 +143,14 @@ void Badge::setText(const QString &text) update(); } +void Badge::setDiameter(int diameter) +{ + if (diameter > 0) { + diameter_ = diameter; + update(); + } +} + void Badge::paintEvent(QPaintEvent *) { QPainter painter(this); @@ -154,13 +164,20 @@ void Badge::paintEvent(QPaintEvent *) painter.setBrush(brush); painter.setPen(Qt::NoPen); - const int d = getDiameter(); + const int d = diameter(); QRectF r(0, 0, d, d); r.translate(QPointF((width() - d), (height() - d)) / 2); if (icon_.isNull()) { + QPen pen; + // TODO: Make badge width configurable. + pen.setWidth(1); + pen.setColor(textColor()); + + painter.setPen(pen); painter.drawEllipse(r); + painter.setPen(textColor()); painter.setBrush(Qt::NoBrush); 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()) { return qMax(size_.width(), size_.height()) + padding_; } - // FIXME: Move this to Theme.h as the default - return 24; + + return diameter_; }