diff options
-rw-r--r-- | events/receiptevent.cpp | 6 | ||||
-rw-r--r-- | events/receiptevent.h | 2 | ||||
-rw-r--r-- | jobs/postreadmarkersjob.h | 37 | ||||
-rw-r--r-- | libqmatrixclient.pri | 3 | ||||
-rw-r--r-- | room.cpp | 87 |
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 \ @@ -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) |