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<MatrixClient> 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<Event> &events)
+int HistoryView::addEvents(const QList<Event> &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<Event> &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_;
}
|