diff options
author | KitsuneRal <Kitsune-Ral@users.sf.net> | 2016-10-24 09:04:35 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-24 09:04:35 +0900 |
commit | 9a1270dbf8cf6c2dc9337c33a3c59b437676548c (patch) | |
tree | 8c77a5ebf5d7660bf78add62498a1e57298f84ab | |
parent | a5962ee1fb1ccfa641217778e6bf7f4e9c53dff1 (diff) | |
parent | caaddebae6acf1a1c5281a5beba43782a8c899fc (diff) | |
download | libquotient-9a1270dbf8cf6c2dc9337c33a3c59b437676548c.tar.gz libquotient-9a1270dbf8cf6c2dc9337c33a3c59b437676548c.zip |
Merge pull request #44 from Fxrh/kitsune-read-receipts
Room: added setLastReadEvent accessor and a signal for it; don't post receipts for own messages to the server
-rw-r--r-- | room.cpp | 54 | ||||
-rw-r--r-- | room.h | 20 |
2 files changed, 70 insertions, 4 deletions
@@ -163,9 +163,57 @@ void Room::setJoinState(JoinState state) emit joinStateChanged(oldState, state); } -void Room::markMessageAsRead(Event* event) +void Room::setLastReadEvent(User* user, QString eventId) { - d->connection->postReceipt(this, event); + d->lastReadEvent.insert(user, eventId); + emit lastReadEventChanged(user); +} + +bool Room::promoteReadMarker(User* user, QString eventId) +{ + // 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); + // Older Qt doesn't provide rbegin()/rend() for Qt containers + for (auto it = messageEvents().end(); it != messageEvents().begin();) + { + --it; + if (prevLastReadId == (*it)->id()) + return false; + if (eventId == (*it)->id()) + { + setLastReadEvent(user, eventId); + return true; + } + } + return false; +} + +void Room::markMessagesAsRead(Timeline::const_iterator last) +{ + QString prevLastReadId = lastReadEvent(connection()->user()); + if ( !promoteReadMarker(connection()->user(), (*last)->id()) ) + return; + + // 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. + for (; (*last)->id() != prevLastReadId; --last) + { + if ((*last)->senderId() != connection()->userId()) + { + d->connection->postReceipt(this, (*last)); + break; + } + if (last == messageEvents().begin()) + break; + } +} + +void Room::markMessagesAsRead() +{ + if (!messageEvents().empty()) + markMessagesAsRead(messageEvents().end() - 1); } QString Room::lastReadEvent(User* user) @@ -489,7 +537,7 @@ void Room::processEphemeralEvent(Event* event) for( const Receipt& r: receipts ) { if (auto m = d->member(r.userId)) - d->lastReadEvent.insert(m, eventId); + promoteReadMarker(m, eventId); } } } @@ -69,8 +69,21 @@ namespace QMatrixClient Q_INVOKABLE void updateData(SyncRoomData& data ); Q_INVOKABLE void setJoinState( JoinState state ); - Q_INVOKABLE void markMessageAsRead( Event* event ); Q_INVOKABLE QString lastReadEvent(User* user); + /** + * @brief Mark the message at the iterator 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. + */ + Q_INVOKABLE void markMessagesAsRead(Timeline::const_iterator last); + /** + * @brief Mark the most recent message in the timeline as read + * + * This effectively marks everything in the room as read. + */ + Q_INVOKABLE void markMessagesAsRead(); Q_INVOKABLE int notificationCount() const; Q_INVOKABLE void resetNotificationCount(); @@ -102,6 +115,7 @@ namespace QMatrixClient void typingChanged(); void highlightCountChanged(Room* room); void notificationCountChanged(Room* room); + void lastReadEventChanged(User* user); protected: Connection* connection() const; @@ -110,12 +124,16 @@ namespace QMatrixClient virtual void processStateEvents(const Events& events); virtual void processEphemeralEvent(Event* event); + bool promoteReadMarker(User* user, QString eventId); + private: class Private; Private* d; void addNewMessageEvents(const Events& events); void addHistoricalMessageEvents(const Events& events); + + void setLastReadEvent(User* user, QString eventId); }; } |