Hello community,

here is the log from the commit of package libqmatrixclient for 
openSUSE:Factory checked in at 2018-12-18 14:58:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libqmatrixclient (Old)
 and      /work/SRC/openSUSE:Factory/.libqmatrixclient.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libqmatrixclient"

Tue Dec 18 14:58:17 2018 rev:2 rq:658761 version:0.4.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/libqmatrixclient/libqmatrixclient.changes        
2018-11-12 09:42:52.505061118 +0100
+++ 
/work/SRC/openSUSE:Factory/.libqmatrixclient.new.28833/libqmatrixclient.changes 
    2018-12-18 14:59:54.394114358 +0100
@@ -1,0 +2,10 @@
+Sun Dec 16 03:06:40 UTC 2018 - Michael Vetter <mvet...@suse.com>
+
+- Update to 0.4.1
+  * Fix pending events (aka local echo) not being cleaned up 
+    properly
+  * Fix rooms not being correctly sorted according to their
+    position under tag if using Connection::roomsByTags()
+  * Fix incorrect SOVERSION
+
+-------------------------------------------------------------------

Old:
----
  v0.4.0.tar.gz

New:
----
  v0.4.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libqmatrixclient.spec ++++++
--- /var/tmp/diff_new_pack.j2Dhyf/_old  2018-12-18 14:59:55.222113113 +0100
+++ /var/tmp/diff_new_pack.j2Dhyf/_new  2018-12-18 14:59:55.226113106 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package libqmatrixclient
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,16 +12,19 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
+#
+
+
 #
 %define soname libQMatrixClient
-%define soversion 0
+%define soversion 0_4
 
 Name:           libqmatrixclient
-Version:        0.4.0
+Version:        0.4.1
 Release:        0
 Summary:        Library for Qt Matrix Clients
-License:        LGPL-2.1
+License:        LGPL-2.1-only
 Group:          Development/Libraries/C and C++
 Url:            https://github.com/QMatrixClient/libqmatrixclient
 Source0:        
https://github.com/QMatrixClient/libqmatrixclient/archive/v%{version}.tar.gz
@@ -33,8 +36,8 @@
 %endif
 BuildRequires:  pkgconfig
 BuildRequires:  pkgconfig(Qt5Core) >= 5.6
-BuildRequires:  pkgconfig(Qt5Network)
 BuildRequires:  pkgconfig(Qt5Gui)
+BuildRequires:  pkgconfig(Qt5Network)
 
 %description
 Library for Qt-based Matrix chat clients. It is required by

++++++ v0.4.0.tar.gz -> v0.4.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/CMakeLists.txt 
new/libqmatrixclient-0.4.1/CMakeLists.txt
--- old/libqmatrixclient-0.4.0/CMakeLists.txt   2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/CMakeLists.txt   2018-12-06 13:01:06.000000000 
+0100
@@ -141,7 +141,7 @@
             ${libqmatrixclient_asdef_SRCS} ${libqmatrixclient_isdef_SRCS})
 set(API_VERSION "0.4")
 set_property(TARGET QMatrixClient PROPERTY VERSION "${API_VERSION}.0")
-set_property(TARGET QMatrixClient PROPERTY SOVERSION 0 )
+set_property(TARGET QMatrixClient PROPERTY SOVERSION ${API_VERSION} )
 set_property(TARGET QMatrixClient PROPERTY
              INTERFACE_QMatrixClient_MAJOR_VERSION ${API_VERSION})
 set_property(TARGET QMatrixClient APPEND PROPERTY
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/CONTRIBUTING.md 
new/libqmatrixclient-0.4.1/CONTRIBUTING.md
--- old/libqmatrixclient-0.4.0/CONTRIBUTING.md  2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/CONTRIBUTING.md  2018-12-06 13:01:06.000000000 
+0100
@@ -237,6 +237,14 @@
 
 Having said that, there's always a trade-off between various attributes; in 
particular, readability and maintainability of the code is more important than 
squeezing every bit out of that clumsy algorithm. Beware of premature 
optimization and have profiling data around before going into some hardcore 
optimization.
 
+Speaking of profiling logs (see README.md on how to turn them on) - in order
+to reduce small timespan logging spam, there's a default limit of at least
+200 microseconds to log most operations with the PROFILER
+(aka libqmatrixclient.profile.debug) logging category. You can override this
+limit by passing the new value (in microseconds) in PROFILER_LOG_USECS to
+the compiler. In the future, this parameter will be made changeable at runtime
+_if_ needed.
+
 ## How to check proposed changes before submitting them
 
 Checking the code on at least one configuration is essential; if you only have
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/QMatrixClient.pc.in 
new/libqmatrixclient-0.4.1/QMatrixClient.pc.in
--- old/libqmatrixclient-0.4.0/QMatrixClient.pc.in      2018-10-12 
08:14:05.000000000 +0200
+++ new/libqmatrixclient-0.4.1/QMatrixClient.pc.in      2018-12-06 
13:01:06.000000000 +0100
@@ -1,7 +1,7 @@
 prefix=@CMAKE_INSTALL_PREFIX@
 exec_prefix=${prefix}
-includedir=${prefix}/include
-libdir=${prefix}/lib
+includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
+libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
 
 Name: QMatrixClient
 Description: A Qt5 library to write cross-platfrom clients for Matrix
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/connection.cpp 
new/libqmatrixclient-0.4.1/lib/connection.cpp
--- old/libqmatrixclient-0.4.0/lib/connection.cpp       2018-10-12 
08:14:05.000000000 +0200
+++ new/libqmatrixclient-0.4.1/lib/connection.cpp       2018-12-06 
13:01:06.000000000 +0100
@@ -422,9 +422,10 @@
     return callApi<PostReceiptJob>(room->id(), "m.read", event->id());
 }
 
-JoinRoomJob* Connection::joinRoom(const QString& roomAlias)
+JoinRoomJob* Connection::joinRoom(const QString& roomAlias,
+                                  const QStringList& serverNames)
 {
-    auto job = callApi<JoinRoomJob>(roomAlias);
+    auto job = callApi<JoinRoomJob>(roomAlias, serverNames);
     connect(job, &JoinRoomJob::success,
             this, [this, job] { provideRoom(job->roomId(), JoinState::Join); 
});
     return job;
@@ -830,7 +831,7 @@
     for (auto it = result.begin(); it != result.end(); ++it)
         std::sort(it->begin(), it->end(),
             [t=it.key()] (Room* r1, Room* r2) {
-                return r1->tags().value(t).order < r2->tags().value(t).order;
+                return r1->tags().value(t) < r2->tags().value(t);
             });
     return result;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/connection.h 
new/libqmatrixclient-0.4.1/lib/connection.h
--- old/libqmatrixclient-0.4.0/lib/connection.h 2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/lib/connection.h 2018-12-06 13:01:06.000000000 
+0100
@@ -461,7 +461,8 @@
             CreateRoomJob* createDirectChat(const QString& userId,
                 const QString& topic = {}, const QString& name = {});
 
-            virtual JoinRoomJob* joinRoom(const QString& roomAlias);
+            virtual JoinRoomJob* joinRoom(const QString& roomAlias,
+                                          const QStringList& serverNames = {});
 
             /** Sends /forget to the server and also deletes room locally.
              * This method is in Connection, not in Room, since it's a
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/converters.h 
new/libqmatrixclient-0.4.1/lib/converters.h
--- old/libqmatrixclient-0.4.0/lib/converters.h 2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/lib/converters.h 2018-12-06 13:01:06.000000000 
+0100
@@ -61,7 +61,7 @@
     inline auto toJson(const QJsonValue& val) { return val; }
     inline auto toJson(const QJsonObject& o) { return o; }
     inline auto toJson(const QJsonArray& arr) { return arr; }
-    // Special-case QStrings and bools to avoid ambiguity between QJsonValue
+    // Special-case QString to avoid ambiguity between QJsonValue
     // and QVariant (also, QString.isEmpty() is used in _impl::AddNode<> below)
     inline auto toJson(const QString& s) { return s; }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/events/event.h 
new/libqmatrixclient-0.4.1/lib/events/event.h
--- old/libqmatrixclient-0.4.0/lib/events/event.h       2018-10-12 
08:14:05.000000000 +0200
+++ new/libqmatrixclient-0.4.1/lib/events/event.h       2018-12-06 
13:01:06.000000000 +0100
@@ -209,7 +209,7 @@
     inline auto registerEventType()
     {
         static const auto _ = setupFactory<EventT>();
-        return _;
+        return _; // Only to facilitate usage in static initialisation
     }
 
     // === Event ===
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libqmatrixclient-0.4.0/lib/jobs/mediathumbnailjob.cpp 
new/libqmatrixclient-0.4.1/lib/jobs/mediathumbnailjob.cpp
--- old/libqmatrixclient-0.4.0/lib/jobs/mediathumbnailjob.cpp   2018-10-12 
08:14:05.000000000 +0200
+++ new/libqmatrixclient-0.4.1/lib/jobs/mediathumbnailjob.cpp   2018-12-06 
13:01:06.000000000 +0100
@@ -23,7 +23,8 @@
 QUrl MediaThumbnailJob::makeRequestUrl(QUrl baseUrl,
                                        const QUrl& mxcUri, QSize requestedSize)
 {
-    return makeRequestUrl(baseUrl, mxcUri.authority(), mxcUri.path().mid(1),
+    return makeRequestUrl(std::move(baseUrl),
+                          mxcUri.authority(), mxcUri.path().mid(1),
                           requestedSize.width(), requestedSize.height());
 }
 
@@ -34,9 +35,8 @@
 { }
 
 MediaThumbnailJob::MediaThumbnailJob(const QUrl& mxcUri, QSize requestedSize)
-    : GetContentThumbnailJob(mxcUri.authority(),
-                             mxcUri.path().mid(1), // sans leading '/'
-                             requestedSize.width(), requestedSize.height())
+    : MediaThumbnailJob(mxcUri.authority(), mxcUri.path().mid(1), // sans 
leading '/'
+                        requestedSize)
 { }
 
 QImage MediaThumbnailJob::thumbnail() const
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/jobs/syncjob.cpp 
new/libqmatrixclient-0.4.1/lib/jobs/syncjob.cpp
--- old/libqmatrixclient-0.4.0/lib/jobs/syncjob.cpp     2018-10-12 
08:14:05.000000000 +0200
+++ new/libqmatrixclient-0.4.1/lib/jobs/syncjob.cpp     2018-12-06 
13:01:06.000000000 +0100
@@ -109,11 +109,12 @@
             totalEvents += r.state.size() + r.ephemeral.size() +
                            r.accountData.size() + r.timeline.size();
         }
-        totalRooms += roomData.size();
+        totalRooms += rs.size();
     }
-    qCDebug(PROFILER) << "*** SyncData::parseJson(): batch with"
-                      << totalRooms << "room(s),"
-                      << totalEvents << "event(s) in" << et;
+    if (totalRooms > 9 || et.nsecsElapsed() >= profilerMinNsecs())
+        qCDebug(PROFILER) << "*** SyncData::parseJson(): batch with"
+                          << totalRooms << "room(s),"
+                          << totalEvents << "event(s) in" << et;
     return BaseJob::Success;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/logging.h 
new/libqmatrixclient-0.4.1/lib/logging.h
--- old/libqmatrixclient-0.4.0/lib/logging.h    2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/lib/logging.h    2018-12-06 13:01:06.000000000 
+0100
@@ -65,6 +65,17 @@
     {
         return qdm(debug_object);
     }
+
+    inline qint64 profilerMinNsecs()
+    {
+        return
+#ifdef PROFILER_LOG_USECS
+            PROFILER_LOG_USECS
+#else
+            200
+#endif
+        * 1000;
+    }
 }
 
 inline QDebug operator<< (QDebug debug_object, const QElapsedTimer& et)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/room.cpp 
new/libqmatrixclient-0.4.1/lib/room.cpp
--- old/libqmatrixclient-0.4.0/lib/room.cpp     2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/lib/room.cpp     2018-12-06 13:01:06.000000000 
+0100
@@ -157,8 +157,8 @@
             fileTransfers[tid].status = FileTransferInfo::Failed;
             emit q->fileTransferFailed(tid, errorMessage);
         }
-        // A map from event/txn ids to information about the long operation;
-        // used for both download and upload operations
+        /// A map from event/txn ids to information about the long operation;
+        /// used for both download and upload operations
         QHash<QString, FileTransferPrivateInfo> fileTransfers;
 
         const RoomMessageEvent* getEventWithFile(const QString& eventId) const;
@@ -215,6 +215,8 @@
 
         QString doSendEvent(const RoomEvent* pEvent);
         PendingEvents::iterator findAsPending(const RoomEvent* rawEvtPtr);
+        void onEventSendingFailure(const RoomEvent* pEvent,
+                const QString& txnId, BaseJob* call = nullptr);
 
         template <typename EvT>
         auto requestSetState(const QString& stateKey, const EvT& event)
@@ -408,7 +410,7 @@
     QElapsedTimer et; et.start();
     const auto newUnreadMessages = count_if(from, to,
             std::bind(&Room::Private::isEventNotable, this, _1));
-    if (et.nsecsElapsed() > 10000)
+    if (et.nsecsElapsed() > profilerMinNsecs() / 10)
         qCDebug(PROFILER) << "Counting gained unread messages took" << et;
 
     if(newUnreadMessages > 0)
@@ -418,7 +420,7 @@
             unreadMessages = 0;
 
         unreadMessages += newUnreadMessages;
-        qCDebug(MAIN) << "Room" << displayname << "has gained"
+        qCDebug(MAIN) << "Room" << q->objectName() << "has gained"
             << newUnreadMessages << "unread message(s),"
             << (q->readMarker() == timeline.crend() ?
                     "in total at least" : "in total")
@@ -450,7 +452,7 @@
         QElapsedTimer et; et.start();
         unreadMessages = count_if(eagerMarker, timeline.cend(),
                     std::bind(&Room::Private::isEventNotable, this, _1));
-        if (et.nsecsElapsed() > 10000)
+        if (et.nsecsElapsed() > profilerMinNsecs() / 10)
             qCDebug(PROFILER) << "Recounting unread messages took" << et;
 
         // See 
https://github.com/QMatrixClient/libqmatrixclient/wiki/unread_count
@@ -1091,8 +1093,9 @@
         for (const auto& e: data.state)
             emitNamesChanged |= processStateEvent(*e);
 
-        qCDebug(PROFILER) << "*** Room::processStateEvents():"
-                          << data.state.size() << "event(s)," << et;
+        if (data.state.size() > 9 || et.nsecsElapsed() >= profilerMinNsecs())
+            qCDebug(PROFILER) << "*** Room::processStateEvents():"
+                              << data.state.size() << "event(s)," << et;
     }
     if (!data.timeline.empty())
     {
@@ -1100,8 +1103,9 @@
         // State changes can arrive in a timeline event; so check those.
         for (const auto& e: data.timeline)
             emitNamesChanged |= processStateEvent(*e);
-        qCDebug(PROFILER) << "*** Room::processStateEvents(timeline):"
-                          << data.timeline.size() << "event(s)," << et;
+        if (data.timeline.size() > 9 || et.nsecsElapsed() >= 
profilerMinNsecs())
+            qCDebug(PROFILER) << "*** Room::processStateEvents(timeline):"
+                              << data.timeline.size() << "event(s)," << et;
     }
     if (emitNamesChanged)
         emit namesChanged(this);
@@ -1111,7 +1115,8 @@
     {
         et.restart();
         d->addNewMessageEvents(move(data.timeline));
-        qCDebug(PROFILER) << "*** Room::addNewMessageEvents():" << et;
+        if (data.timeline.size() > 9 || et.nsecsElapsed() >= 
profilerMinNsecs())
+            qCDebug(PROFILER) << "*** Room::addNewMessageEvents():" << et;
     }
     for( auto&& ephemeralEvent: data.ephemeral )
         processEphemeralEvent(move(ephemeralEvent));
@@ -1150,50 +1155,42 @@
 QString Room::Private::doSendEvent(const RoomEvent* pEvent)
 {
     auto txnId = pEvent->transactionId();
-    // TODO: Enqueue the job rather than immediately trigger it
-    auto call = connection->callApi<SendMessageJob>(BackgroundRequest,
-                    id, pEvent->matrixType(), txnId, pEvent->contentJson());
-    Room::connect(call, &BaseJob::started, q,
-        [this,pEvent,txnId] {
-            auto it = findAsPending(pEvent);
-            if (it == unsyncedEvents.end())
-            {
-                qWarning(EVENTS) << "Pending event for transaction" << txnId
-                                 << "not found - got synced so soon?";
-                return;
-            }
-            it->setDeparted();
-            emit q->pendingEventChanged(it - unsyncedEvents.begin());
-        });
-    Room::connect(call, &BaseJob::failure, q,
-        [this,pEvent,txnId,call] {
-            auto it = findAsPending(pEvent);
-            if (it == unsyncedEvents.end())
-            {
-                qCritical(EVENTS) << "Pending event for transaction" << txnId
-                                  << "got lost without successful sending";
-                return;
-            }
-            it->setSendingFailed(
-                        call->statusCaption() % ": " % call->errorString());
-            emit q->pendingEventChanged(it - unsyncedEvents.begin());
-
-        });
-    Room::connect(call, &BaseJob::success, q,
-        [this,call,pEvent,txnId] {
-            // Find an event by the pointer saved in the lambda (the pointer
-            // may be dangling by now but we can still search by it).
-            auto it = findAsPending(pEvent);
-            if (it == unsyncedEvents.end())
-            {
-                qDebug(EVENTS) << "Pending event for transaction" << txnId
-                               << "already merged";
-                return;
-            }
+    // TODO, #133: Enqueue the job rather than immediately trigger it.
+    if (auto call = connection->callApi<SendMessageJob>(BackgroundRequest,
+                        id, pEvent->matrixType(), txnId, 
pEvent->contentJson()))
+    {
+        Room::connect(call, &BaseJob::started, q,
+            [this,pEvent,txnId] {
+                auto it = findAsPending(pEvent);
+                if (it == unsyncedEvents.end())
+                {
+                    qWarning(EVENTS) << "Pending event for transaction" << 
txnId
+                                     << "not found - got synced so soon?";
+                    return;
+                }
+                it->setDeparted();
+                emit q->pendingEventChanged(it - unsyncedEvents.begin());
+            });
+        Room::connect(call, &BaseJob::failure, q,
+            std::bind(&Room::Private::onEventSendingFailure,
+                      this, pEvent, txnId, call));
+        Room::connect(call, &BaseJob::success, q,
+            [this,call,pEvent,txnId] {
+                // Find an event by the pointer saved in the lambda (the 
pointer
+                // may be dangling by now but we can still search by it).
+                auto it = findAsPending(pEvent);
+                if (it == unsyncedEvents.end())
+                {
+                    qDebug(EVENTS) << "Pending event for transaction" << txnId
+                                   << "already merged";
+                    return;
+                }
 
-            it->setReachedServer(call->eventId());
-            emit q->pendingEventChanged(it - unsyncedEvents.begin());
-        });
+                it->setReachedServer(call->eventId());
+                emit q->pendingEventChanged(it - unsyncedEvents.begin());
+            });
+    } else
+        onEventSendingFailure(pEvent, txnId);
     return txnId;
 }
 
@@ -1206,6 +1203,22 @@
     return std::find_if(unsyncedEvents.begin(), unsyncedEvents.end(), comp);
 }
 
+void Room::Private::onEventSendingFailure(const RoomEvent* pEvent,
+        const QString& txnId, BaseJob* call)
+{
+    auto it = findAsPending(pEvent);
+    if (it == unsyncedEvents.end())
+    {
+        qCritical(EVENTS) << "Pending event for transaction" << txnId
+                          << "could not be sent";
+        return;
+    }
+    it->setSendingFailed(call
+        ? call->statusCaption() % ": " % call->errorString()
+        : tr("The call could not be started"));
+    emit q->pendingEventChanged(it - unsyncedEvents.begin());
+}
+
 QString Room::retryMessage(const QString& txnId)
 {
     auto it = std::find_if(d->unsyncedEvents.begin(), d->unsyncedEvents.end(),
@@ -1285,15 +1298,15 @@
     if (le->type() != re->type())
         return false;
 
-    if (!le->id().isEmpty())
+    if (!re->id().isEmpty())
         return le->id() == re->id();
-    if (!le->transactionId().isEmpty())
+    if (!re->transactionId().isEmpty())
         return le->transactionId() == re->transactionId();
 
     // This one is not reliable (there can be two unsynced
     // events with the same type, sender and state key) but
     // it's the best we have for state events.
-    if (le->isStateEvent())
+    if (re->isStateEvent())
         return le->stateKey() == re->stateKey();
 
     // Empty id and no state key, hmm... (shrug)
@@ -1616,45 +1629,37 @@
 void Room::Private::addNewMessageEvents(RoomEvents&& events)
 {
     dropDuplicateEvents(events);
+    if (events.empty())
+        return;
 
     // Pre-process redactions so that events that get redacted in the same
     // batch landed in the timeline already redacted.
-    // XXX: The code below is written (and commented) so that it could be
-    // quickly converted to not-saving redaction events in the timeline.
-    // See #220 for details.
-    auto newEnd = std::find_if(events.begin(), events.end(), isRedaction);
-    // Either process the redaction, or shift the non-redaction event
-    // overwriting redactions in a remove_if fashion.
-    for(const auto& eptr: RoomEventsRange(newEnd, events.end()))
+    // NB: We have to store redaction events to the timeline too - see #220.
+    auto redactionIt = std::find_if(events.begin(), events.end(), isRedaction);
+    for(const auto& eptr: RoomEventsRange(redactionIt, events.end()))
         if (auto* r = eventCast<RedactionEvent>(eptr))
         {
             // Try to find the target in the timeline, then in the batch.
             if (processRedaction(*r))
                 continue;
-            auto targetIt = std::find_if(events.begin(), newEnd,
+            auto targetIt = std::find_if(events.begin(), redactionIt,
                 [id=r->redactedEvent()] (const RoomEventPtr& ep) {
                     return ep->id() == id;
                 });
-            if (targetIt != newEnd)
+            if (targetIt != redactionIt)
                 *targetIt = makeRedacted(**targetIt, *r);
             else
                 qCDebug(MAIN) << "Redaction" << r->id()
                               << "ignored: target event" << r->redactedEvent()
                               << "is not found";
-            // If the target events comes later, it comes already redacted.
+            // If the target event comes later, it comes already redacted.
         }
-//        else // This should be uncommented once we stop adding redactions to 
the timeline
-//            *newEnd++ = std::move(eptr);
-    newEnd = events.end(); // This line should go if/when we stop adding 
redactions to the timeline
-
-    if (events.begin() == newEnd)
-        return;
 
     auto timelineSize = timeline.size();
     auto totalInserted = 0;
-    for (auto it = events.begin(); it != newEnd;)
+    for (auto it = events.begin(); it != events.end();)
     {
-        auto nextPendingPair = findFirstOf(it, newEnd,
+        auto nextPendingPair = findFirstOf(it, events.end(),
                     unsyncedEvents.begin(), unsyncedEvents.end(), isEchoEvent);
         auto nextPending = nextPendingPair.first;
 
@@ -1668,7 +1673,7 @@
             q->onAddNewTimelineEvents(firstInserted);
             emit q->addedMessages(firstInserted->index(), 
timeline.back().index());
         }
-        if (nextPending == newEnd)
+        if (nextPending == events.end())
             break;
 
         it = nextPending + 1;
@@ -1696,7 +1701,7 @@
     if (totalInserted > 0)
     {
         qCDebug(MAIN)
-                << "Room" << displayname << "received" << totalInserted
+                << "Room" << q->objectName() << "received" << totalInserted
                 << "new events; the last event is now" << timeline.back();
 
         // The first event in the just-added batch (referred to by `from`)
@@ -1721,6 +1726,7 @@
 
 void Room::Private::addHistoricalMessageEvents(RoomEvents&& events)
 {
+    QElapsedTimer et; et.start();
     const auto timelineSize = timeline.size();
 
     dropDuplicateEvents(events);
@@ -1743,6 +1749,9 @@
         updateUnreadCount(from, timeline.crend());
 
     Q_ASSERT(timeline.size() == timelineSize + insertedSize);
+    if (insertedSize > 9 || et.nsecsElapsed() >= profilerMinNsecs())
+        qCDebug(PROFILER) << "*** Room::addHistoricalMessageEvents():"
+                          << insertedSize << "event(s)," << et;
 }
 
 bool Room::processStateEvent(const RoomEvent& e)
@@ -1786,8 +1795,7 @@
             u->processEvent(evt, this);
             if (u == localUser() && memberJoinState(u) == JoinState::Invite
                     && evt.isDirect())
-                connection()->addToDirectChats(this,
-                                user(evt.senderId()));
+                connection()->addToDirectChats(this, user(evt.senderId()));
 
             if( evt.membership() == MembershipType::Join )
             {
@@ -1841,15 +1849,17 @@
             if (memberJoinState(u) == JoinState::Join)
                 d->usersTyping.append(u);
         }
-        if (!evt->users().isEmpty())
+        if (evt->users().size() > 3 || et.nsecsElapsed() >= profilerMinNsecs())
             qCDebug(PROFILER) << "*** Room::processEphemeralEvent(typing):"
                 << evt->users().size() << "users," << et;
         emit typingChanged();
     }
     if (auto* evt = eventCast<ReceiptEvent>(event))
     {
+        int totalReceipts = 0;
         for( const auto &p: qAsConst(evt->eventsWithReceipts()) )
         {
+            totalReceipts += p.receipts.size();
             {
                 if (p.receipts.size() == 1)
                     qCDebug(EPHEMERAL) << "Marking" << p.evtId
@@ -1888,10 +1898,11 @@
                 }
             }
         }
-        if (!evt->eventsWithReceipts().isEmpty())
+        if (evt->eventsWithReceipts().size() > 3 || totalReceipts > 10 ||
+                et.nsecsElapsed() >= profilerMinNsecs())
             qCDebug(PROFILER) << "*** Room::processEphemeralEvent(receipts):"
                 << evt->eventsWithReceipts().size()
-                << "events with receipts," << et;
+                << "event(s) with" << totalReceipts << "receipt(s)," << et;
     }
 }
 
@@ -1963,9 +1974,8 @@
 
     // iii. More users.
     if (userlist.size() > 3)
-        return tr("%1 and %L2 others")
-                .arg(q->roomMembername(first_two[0]))
-                .arg(userlist.size() - 3);
+        return tr("%1 and %Ln other(s)", "", userlist.size() - 3)
+                .arg(q->roomMembername(first_two[0]));
 
     // userlist.size() < 2 - apparently, there's only current user in the room
     return QString();
@@ -2094,7 +2104,7 @@
 
     result.insert(QStringLiteral("unread_notifications"), unreadNotifObj);
 
-    if (et.elapsed() > 50)
+    if (et.elapsed() > 30)
         qCDebug(PROFILER) << "Room::toJson() for" << displayname << "took" << 
et;
 
     return result;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/room.h 
new/libqmatrixclient-0.4.1/lib/room.h
--- old/libqmatrixclient-0.4.0/lib/room.h       2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/lib/room.h       2018-12-06 13:01:06.000000000 
+0100
@@ -323,6 +323,7 @@
              *
              * Takes ownership of the event, deleting it once the matching one
              * arrives with the sync
+             * \return transaction id associated with the event.
              */
             QString postEvent(RoomEvent* event);
             QString postJson(const QString& matrixType,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libqmatrixclient-0.4.0/lib/user.cpp 
new/libqmatrixclient-0.4.1/lib/user.cpp
--- old/libqmatrixclient-0.4.0/lib/user.cpp     2018-10-12 08:14:05.000000000 
+0200
+++ new/libqmatrixclient-0.4.1/lib/user.cpp     2018-12-06 13:01:06.000000000 
+0100
@@ -321,14 +321,16 @@
 
 QString User::displayname(const Room* room) const
 {
-    auto name = d->nameForRoom(room);
-    return name.isEmpty() ? d->userId :
-           room ? room->roomMembername(this) : name;
+    if (room)
+        return room->roomMembername(this);
+
+    const auto name = d->nameForRoom(nullptr);
+    return name.isEmpty() ? d->userId : name;
 }
 
 QString User::fullName(const Room* room) const
 {
-    auto name = d->nameForRoom(room);
+    const auto name = d->nameForRoom(room);
     return name.isEmpty() ? d->userId : name % " (" % d->userId % ')';
 }
 


Reply via email to