aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--room.cpp73
-rw-r--r--room.h5
2 files changed, 64 insertions, 14 deletions
diff --git a/room.cpp b/room.cpp
index c2a1ce70..fa919f61 100644
--- a/room.cpp
+++ b/room.cpp
@@ -49,7 +49,7 @@ class Room::Private
Private(Connection* c, const QString& id_)
: q(nullptr), connection(c), id(id_), joinState(JoinState::Join)
- , roomMessagesJob(nullptr)
+ , unreadMessages(false), roomMessagesJob(nullptr)
{ }
Room* q;
@@ -68,6 +68,7 @@ class Room::Private
QString displayname;
QString topic;
JoinState joinState;
+ bool unreadMessages;
int highlightCount;
int notificationCount;
members_map_t membersMap;
@@ -90,6 +91,7 @@ class Room::Private
void getPreviousContent();
+ bool isEventNotable(const Event* e) const;
private:
QString calculateDisplayname() const;
QString roomNameFromMemberNames(const QList<User*>& userlist) const;
@@ -169,30 +171,46 @@ void Room::setLastReadEvent(User* user, QString eventId)
emit lastReadEventChanged(user);
}
-bool Room::promoteReadMarker(User* user, QString eventId)
+bool Room::promoteReadMarker(QString newLastReadEventId)
{
- // Check that the new read event is not before the previously set - only
- // allow the read marker to move down the timeline, not up.
- QString prevLastReadId = lastReadEvent(user);
+ User* localUser = connection()->user();
+ QString prevLastReadId = lastReadEvent(localUser);
+ int stillUnreadMessagesCount = 0;
// Older Qt doesn't provide rbegin()/rend() for Qt containers
for (auto it = messageEvents().end(); it != messageEvents().begin();)
{
--it;
+ // Check that the new read event is not before the previously set - only
+ // allow the read marker to move down the timeline, not up.
if (prevLastReadId == (*it)->id())
- return false;
- if (eventId == (*it)->id())
+ break;
+
+ // Found the message to mark as read; for the local user,
+ // if we don't have other notable events below this one, reset unreadMessages
+ if (newLastReadEventId == (*it)->id())
{
- setLastReadEvent(user, eventId);
- return true;
+ setLastReadEvent(localUser, newLastReadEventId);
+ break;
}
+
+ // Detect events "notable" for the local user so that we can properly
+ // set unreadMessages
+ stillUnreadMessagesCount += d->isEventNotable(*it);
}
- return false;
+ if( d->unreadMessages && stillUnreadMessagesCount == 0)
+ {
+ d->unreadMessages = false;
+ emit unreadMessagesChanged(this);
+ }
+ qDebug() << "Room" << displayName()
+ << ": still" << stillUnreadMessagesCount << "unread message(s)";
+ return newLastReadEventId.isEmpty() || lastReadEvent(localUser) == newLastReadEventId;
}
void Room::markMessagesAsRead(Timeline::const_iterator last)
{
QString prevLastReadId = lastReadEvent(connection()->user());
- if ( !promoteReadMarker(connection()->user(), (*last)->id()) )
+ if ( !promoteReadMarker( (*last)->id()) )
return;
// We shouldn't send read receipts for messages from the local user - so
@@ -216,6 +234,11 @@ void Room::markMessagesAsRead()
markMessagesAsRead(messageEvents().end() - 1);
}
+bool Room::hasUnreadMessages()
+{
+ return d->unreadMessages;
+}
+
QString Room::lastReadEvent(User* user)
{
return d->lastReadEvent.value(user);
@@ -441,10 +464,29 @@ void Room::addNewMessageEvents(const Events& events)
emit addedMessages();
}
+bool Room::Private::isEventNotable(const Event* e) const
+{
+ return e->senderId() != connection->userId() &&
+ e->type() == EventType::RoomMessage;
+}
+
void Room::doAddNewMessageEvents(const Events& events)
{
d->messageEvents.reserve(d->messageEvents.size() + events.size());
- std::copy(events.begin(), events.end(), std::back_inserter(d->messageEvents));
+ int newMessages = 0;
+
+ for (auto e: events)
+ {
+ d->messageEvents.push_back(e);
+ newMessages += d->isEventNotable(e);
+ }
+
+ if( !d->unreadMessages && newMessages > 0)
+ {
+ d->unreadMessages = true;
+ emit unreadMessagesChanged(this);
+ qDebug() << "Room" << displayName() << ": unread messages";
+ }
}
void Room::addHistoricalMessageEvents(const Events& events)
@@ -537,7 +579,12 @@ void Room::processEphemeralEvent(Event* event)
for( const Receipt& r: receipts )
{
if (auto m = d->member(r.userId))
- promoteReadMarker(m, eventId);
+ {
+ if (m == connection()->user())
+ promoteReadMarker(eventId);
+ else
+ setLastReadEvent(m, eventId);
+ }
}
}
}
diff --git a/room.h b/room.h
index fb3212e9..38435e95 100644
--- a/room.h
+++ b/room.h
@@ -85,6 +85,8 @@ namespace QMatrixClient
*/
Q_INVOKABLE void markMessagesAsRead();
+ Q_INVOKABLE bool hasUnreadMessages();
+
Q_INVOKABLE int notificationCount() const;
Q_INVOKABLE void resetNotificationCount();
Q_INVOKABLE int highlightCount() const;
@@ -116,6 +118,7 @@ namespace QMatrixClient
void highlightCountChanged(Room* room);
void notificationCountChanged(Room* room);
void lastReadEventChanged(User* user);
+ void unreadMessagesChanged(Room* room);
protected:
Connection* connection() const;
@@ -124,7 +127,7 @@ namespace QMatrixClient
virtual void processStateEvents(const Events& events);
virtual void processEphemeralEvent(Event* event);
- bool promoteReadMarker(User* user, QString eventId);
+ bool promoteReadMarker(QString newLastReadEventId);
private:
class Private;