diff options
-rw-r--r-- | room.cpp | 31 | ||||
-rw-r--r-- | room.h | 22 |
2 files changed, 32 insertions, 21 deletions
@@ -170,13 +170,14 @@ void Room::setLastReadEvent(User* user, QString eventId) emit lastReadEventChanged(user); } -bool Room::promoteReadMarker(QString newLastReadEventId) +Room::Timeline::const_iterator Room::promoteReadMarker(QString eventId) { User* localUser = connection()->user(); QString prevLastReadId = lastReadEvent(localUser); int stillUnreadMessagesCount = 0; + auto it = d->messageEvents.end(); // Older Qt doesn't provide rbegin()/rend() for Qt containers - for (auto it = messageEvents().end(); it != messageEvents().begin();) + while (it != d->messageEvents.begin()) { --it; // Check that the new read event is not before the previously set - only @@ -186,9 +187,10 @@ bool Room::promoteReadMarker(QString newLastReadEventId) // 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()) + if (eventId == (*it)->id()) { - setLastReadEvent(localUser, newLastReadEventId); + setLastReadEvent(localUser, eventId); + emit readMarkerPromoted(); break; } @@ -205,15 +207,17 @@ bool Room::promoteReadMarker(QString newLastReadEventId) if (stillUnreadMessagesCount > 0) qDebug() << "Room" << displayName() << ": still" << stillUnreadMessagesCount << "unread message(s)"; - return newLastReadEventId.isEmpty() || lastReadEvent(localUser) == newLastReadEventId; + return it; } -void Room::markMessagesAsRead(Timeline::const_iterator last) +void Room::markMessagesAsRead(QString uptoEventId) { - QString prevLastReadId = lastReadEvent(connection()->user()); - if ( !promoteReadMarker( (*last)->id()) ) + if (d->messageEvents.empty()) return; + QString prevLastReadId = lastReadEvent(connection()->user()); + auto last = promoteReadMarker(uptoEventId); + // We shouldn't send read receipts for messages from the local user - so // shift back (if necessary) to the nearest message not from the local user // or the so far last read message, whichever comes first. @@ -221,7 +225,7 @@ void Room::markMessagesAsRead(Timeline::const_iterator last) { if ((*last)->senderId() != connection()->userId()) { - d->connection->postReceipt(this, (*last)); + d->connection->postReceipt(this, *last); break; } if (last == messageEvents().begin()) @@ -232,7 +236,7 @@ void Room::markMessagesAsRead(Timeline::const_iterator last) void Room::markMessagesAsRead() { if (!messageEvents().empty()) - markMessagesAsRead(messageEvents().end() - 1); + markMessagesAsRead(messageEvents().back()->id()); } bool Room::hasUnreadMessages() @@ -240,11 +244,16 @@ bool Room::hasUnreadMessages() return d->unreadMessages; } -QString Room::lastReadEvent(User* user) +QString Room::lastReadEvent(User* user) const { return d->lastReadEvent.value(user); } +QString Room::readMarkerEventId() const +{ + return lastReadEvent(d->connection->user()); +} + int Room::notificationCount() const { return d->notificationCount; @@ -37,6 +37,7 @@ namespace QMatrixClient class Room: public QObject { Q_OBJECT + Q_PROPERTY(QString readMarkerEventId READ readMarkerEventId WRITE markMessagesAsRead NOTIFY readMarkerPromoted) public: using Timeline = Owning<Events>; @@ -70,19 +71,19 @@ namespace QMatrixClient Q_INVOKABLE void updateData(SyncRoomData& data ); Q_INVOKABLE void setJoinState( JoinState state ); - Q_INVOKABLE QString lastReadEvent(User* user); + Q_INVOKABLE QString lastReadEvent(User* user) const; + QString readMarkerEventId() const; /** - * @brief Mark the message at the iterator as read + * @brief Mark the event with uptoEventId as read * - * Marks the message at the iterator as read; also posts a read - * receipt to the server either for this message or, if it's from - * the local user, for the nearest non-local message before. + * Finds in the timeline and marks as read the event with + * the specified id; also posts a read receipt to the server either + * for this message or, if it's from the local user, for + * the nearest non-local message before. */ - Q_INVOKABLE void markMessagesAsRead(Timeline::const_iterator last); + Q_INVOKABLE void markMessagesAsRead(QString uptoEventId); /** - * @brief Mark the most recent message in the timeline as read - * - * This effectively marks everything in the room as read. + * @brief Mark the whole room timeline as read */ Q_INVOKABLE void markMessagesAsRead(); @@ -121,6 +122,7 @@ namespace QMatrixClient void highlightCountChanged(Room* room); void notificationCountChanged(Room* room); void lastReadEventChanged(User* user); + void readMarkerPromoted(); void unreadMessagesChanged(Room* room); protected: @@ -130,7 +132,7 @@ namespace QMatrixClient virtual void processStateEvents(const Events& events); virtual void processEphemeralEvent(Event* event); - bool promoteReadMarker(QString newLastReadEventId); + Timeline::const_iterator promoteReadMarker(QString eventId); private: class Private; |