From caaddebae6acf1a1c5281a5beba43782a8c899fc Mon Sep 17 00:00:00 2001
From: Kitsune Ral <Kitsune-Ral@users.sf.net>
Date: Sun, 23 Oct 2016 19:08:41 +0900
Subject: Room: Don't let the read marker (of any user) get back, only forward

---
 room.cpp | 25 +++++++++++++++++++++++--
 room.h   |  4 +++-
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/room.cpp b/room.cpp
index df230e38..c2a1ce70 100644
--- a/room.cpp
+++ b/room.cpp
@@ -169,10 +169,31 @@ void Room::setLastReadEvent(User* user, QString 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());
-    setLastReadEvent(connection()->user(), (*last)->id());
+    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
@@ -516,7 +537,7 @@ void Room::processEphemeralEvent(Event* event)
             for( const Receipt& r: receipts )
             {
                 if (auto m = d->member(r.userId))
-                    setLastReadEvent(m, eventId);
+                    promoteReadMarker(m, eventId);
             }
         }
     }
diff --git a/room.h b/room.h
index 9c745199..fb3212e9 100644
--- a/room.h
+++ b/room.h
@@ -124,7 +124,7 @@ namespace QMatrixClient
             virtual void processStateEvents(const Events& events);
             virtual void processEphemeralEvent(Event* event);
 
-            void setLastReadEvent(User* user, QString eventId);
+            bool promoteReadMarker(User* user, QString eventId);
 
         private:
             class Private;
@@ -132,6 +132,8 @@ namespace QMatrixClient
 
             void addNewMessageEvents(const Events& events);
             void addHistoricalMessageEvents(const Events& events);
+
+            void setLastReadEvent(User* user, QString eventId);
     };
 }
 
-- 
cgit v1.2.3