aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--events/receiptevent.cpp6
-rw-r--r--events/receiptevent.h2
-rw-r--r--jobs/postreadmarkersjob.h37
-rw-r--r--libqmatrixclient.pri3
-rw-r--r--room.cpp87
5 files changed, 86 insertions, 49 deletions
diff --git a/events/receiptevent.cpp b/events/receiptevent.cpp
index 3c4d34ee..7555db82 100644
--- a/events/receiptevent.cpp
+++ b/events/receiptevent.cpp
@@ -66,11 +66,5 @@ ReceiptEvent::ReceiptEvent(const QJsonObject& obj)
}
_eventsWithReceipts.push_back({eventIt.key(), std::move(receipts)});
}
- static const auto UnreadMsgsKey =
- QStringLiteral("x-qmatrixclient.unread_messages");
- if (contents.contains(UnreadMsgsKey))
- _unreadMessages = contents["x-qmatrixclient.unread_messages"].toBool();
- else
- _unreadMessages = obj["x-qmatrixclient.unread_messages"].toBool();
}
diff --git a/events/receiptevent.h b/events/receiptevent.h
index 92dace82..5b99ae3f 100644
--- a/events/receiptevent.h
+++ b/events/receiptevent.h
@@ -41,12 +41,10 @@ namespace QMatrixClient
EventsWithReceipts eventsWithReceipts() const
{ return _eventsWithReceipts; }
- bool unreadMessages() const { return _unreadMessages; }
static constexpr const char* const TypeId = "m.receipt";
private:
EventsWithReceipts _eventsWithReceipts;
- bool _unreadMessages; // Spec extension for caching purposes
};
} // namespace QMatrixClient
diff --git a/jobs/postreadmarkersjob.h b/jobs/postreadmarkersjob.h
new file mode 100644
index 00000000..d0198821
--- /dev/null
+++ b/jobs/postreadmarkersjob.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (C) 2017 Kitsune Ral <kitsune-ral@users.sf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "basejob.h"
+
+using namespace QMatrixClient;
+
+class PostReadMarkersJob : public BaseJob
+{
+ public:
+ explicit PostReadMarkersJob(const QString& roomId,
+ const QString& readUpToEventId)
+ : BaseJob(HttpVerb::Post, "PostReadMarkersJob",
+ QStringLiteral("_matrix/client/r0/rooms/%1/read_markers")
+ .arg(roomId))
+ {
+ setRequestData(QJsonObject {{
+ QStringLiteral("m.fully_read"), readUpToEventId }});
+ }
+};
diff --git a/libqmatrixclient.pri b/libqmatrixclient.pri
index c7b95617..74e9d8c7 100644
--- a/libqmatrixclient.pri
+++ b/libqmatrixclient.pri
@@ -42,7 +42,8 @@ HEADERS += \
$$PWD/settings.h \
$$PWD/networksettings.h \
$$PWD/networkaccessmanager.h \
- $$PWD/jobs/downloadfilejob.h
+ $$PWD/jobs/downloadfilejob.h \
+ $$PWD/jobs/postreadmarkersjob.h
SOURCES += \
$$PWD/connectiondata.cpp \
diff --git a/room.cpp b/room.cpp
index 4f818473..beeca6e3 100644
--- a/room.cpp
+++ b/room.cpp
@@ -36,6 +36,7 @@
#include "jobs/roommessagesjob.h"
#include "jobs/mediathumbnailjob.h"
#include "jobs/downloadfilejob.h"
+#include "jobs/postreadmarkersjob.h"
#include "avatar.h"
#include "connection.h"
#include "user.h"
@@ -105,6 +106,7 @@ class Room::Private
QString firstDisplayedEventId;
QString lastDisplayedEventId;
QHash<const User*, QString> lastReadEventIds;
+ QString serverReadMarker;
TagsMap tags;
QHash<QString, QVariantHash> accountData;
QString prevBatch;
@@ -202,11 +204,12 @@ class Room::Private
*/
void processRedaction(RoomEventPtr redactionEvent);
- template <typename EvT>
- SetAccountDataPerRoomJob* setAccountData(const EvT& event)
+ void broadcastTagUpdates()
{
- return connection->callApi<SetAccountDataPerRoomJob>(
- connection->userId(), id, EvT::typeId(), event.toJson());
+ connection->callApi<SetAccountDataPerRoomJob>(
+ connection->userId(), id, TagEvent::typeId(),
+ TagEvent(tags).toJson());
+ emit q->tagsChanged();
}
QJsonObject toJson() const;
@@ -347,7 +350,11 @@ void Room::Private::setLastReadEvent(User* u, const QString& eventId)
storedId = eventId;
emit q->lastReadEventChanged(u);
if (isLocalUser(u))
+ {
+ if (eventId != serverReadMarker)
+ connection->callApi<PostReadMarkersJob>(id, eventId);
emit q->readMarkerMoved();
+ }
}
Room::Private::rev_iter_pair_t
@@ -402,9 +409,8 @@ void Room::Private::markMessagesAsRead(Room::rev_iter_t upToMarker)
{
if ((*markers.second)->senderId() != q->localUser()->id())
{
- auto eventId = (*markers.second)->id();
- connection->callApi<PostReceiptJob>(id, "m.read", eventId);
- setAccountData(ReadMarkerEvent(eventId));
+ connection->callApi<PostReceiptJob>(id, "m.read",
+ (*markers.second)->id());
break;
}
}
@@ -593,8 +599,7 @@ void Room::addTag(const QString& name, const TagRecord& record)
return;
d->tags.insert(name, record);
- d->setAccountData(TagEvent(d->tags));
- emit tagsChanged();
+ d->broadcastTagUpdates();
}
void Room::removeTag(const QString& name)
@@ -603,8 +608,7 @@ void Room::removeTag(const QString& name)
return;
d->tags.remove(name);
- d->setAccountData(TagEvent(d->tags));
- emit tagsChanged();
+ d->broadcastTagUpdates();
}
void Room::setTags(const TagsMap& newTags)
@@ -612,8 +616,7 @@ void Room::setTags(const TagsMap& newTags)
if (newTags == d->tags)
return;
d->tags = newTags;
- d->setAccountData(TagEvent(d->tags));
- emit tagsChanged();
+ d->broadcastTagUpdates();
}
bool Room::isFavourite() const
@@ -915,10 +918,13 @@ void Room::updateData(SyncRoomData&& data)
d->prevBatch = data.timelinePrevBatch;
setJoinState(data.joinState);
- QElapsedTimer et;
+ QElapsedTimer et; et.start();
+ for (auto&& event: data.accountData)
+ processAccountDataEvent(move(event));
+
if (!data.state.empty())
{
- et.start();
+ et.restart();
processStateEvents(data.state);
qCDebug(PROFILER) << "*** Room::processStateEvents(state):"
<< data.state.size() << "event(s)," << et;
@@ -938,9 +944,6 @@ void Room::updateData(SyncRoomData&& data)
for( auto&& ephemeralEvent: data.ephemeral )
processEphemeralEvent(move(ephemeralEvent));
- for (auto&& event: data.accountData)
- processAccountDataEvent(move(event));
-
if( data.highlightCount != d->highlightCount )
{
d->highlightCount = data.highlightCount;
@@ -1499,8 +1502,6 @@ void Room::processEphemeralEvent(EventPtr event)
qCDebug(PROFILER) << "*** Room::processEphemeralEvent(receipts):"
<< receiptEvent->eventsWithReceipts().size()
<< "events with receipts," << et;
- if (receiptEvent->unreadMessages())
- d->unreadMessages = true;
break;
}
default:
@@ -1524,6 +1525,20 @@ void Room::processAccountDataEvent(EventPtr event)
emit tagsChanged();
break;
}
+ case EventType::ReadMarker:
+ {
+ const auto* rmEvent = static_cast<ReadMarkerEvent*>(event.get());
+ const auto& readEventId = rmEvent->event_id();
+ qCDebug(MAIN) << "Server-side read marker at " << readEventId;
+ static const auto UnreadMsgsKey =
+ QStringLiteral("x-qmatrixclient.unread_messages");
+ if (rmEvent->contentJson().contains(UnreadMsgsKey))
+ d->unreadMessages =
+ rmEvent->contentJson().value(UnreadMsgsKey).toBool();
+ d->serverReadMarker = readEventId;
+ markMessagesAsRead(readEventId);
+ break;
+ }
default:
d->accountData[event->jsonType()] =
event->contentJson().toVariantHash();
@@ -1659,32 +1674,24 @@ QJsonObject Room::Private::toJson() const
QJsonObject {{ QStringLiteral("events"), stateEvents }});
}
- if (!q->readMarkerEventId().isEmpty())
- {
- result.insert(QStringLiteral("ephemeral"),
- QJsonObject {{ QStringLiteral("events"),
- QJsonArray { QJsonObject(
- { { QStringLiteral("type"), QStringLiteral("m.receipt") }
- , { QStringLiteral("content"), QJsonObject(
- { { q->readMarkerEventId(),
- QJsonObject {{ QStringLiteral("m.read"),
- QJsonObject {{ connection->userId(), {} }} }}
- }
- , { QStringLiteral("x-qmatrixclient.unread_messages"),
- unreadMessages }
- }) }
- }
- ) }
- }});
- }
-
QJsonArray accountDataEvents;
if (!tags.empty())
accountDataEvents.append(QJsonObject(
- { { QStringLiteral("type"), QStringLiteral("m.tag") }
+ { { QStringLiteral("type"), TagEvent::typeId() }
, { QStringLiteral("content"), TagEvent(tags).toJson() }
}));
+ if (!serverReadMarker.isEmpty())
+ {
+ auto contentJson = ReadMarkerEvent(serverReadMarker).toJson();
+ contentJson.insert(QStringLiteral("x-qmatrixclient.unread_messages"),
+ unreadMessages);
+ accountDataEvents.append(QJsonObject(
+ { { QStringLiteral("type"), ReadMarkerEvent::typeId() }
+ , { QStringLiteral("content"), contentJson }
+ }));
+ }
+
if (!accountData.empty())
{
for (auto it = accountData.begin(); it != accountData.end(); ++it)