aboutsummaryrefslogtreecommitdiff
path: root/lib/room.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/room.cpp')
-rw-r--r--lib/room.cpp259
1 files changed, 137 insertions, 122 deletions
diff --git a/lib/room.cpp b/lib/room.cpp
index a4cfadb4..5f2e3088 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -18,14 +18,15 @@
#include "room.h"
-#include "jobs/generated/kicking.h"
-#include "jobs/generated/inviting.h"
-#include "jobs/generated/banning.h"
-#include "jobs/generated/leaving.h"
-#include "jobs/generated/receipts.h"
-#include "jobs/generated/redaction.h"
-#include "jobs/generated/account-data.h"
-#include "jobs/setroomstatejob.h"
+#include "csapi/kicking.h"
+#include "csapi/inviting.h"
+#include "csapi/banning.h"
+#include "csapi/leaving.h"
+#include "csapi/receipts.h"
+#include "csapi/redaction.h"
+#include "csapi/account-data.h"
+#include "csapi/message_pagination.h"
+#include "csapi/room_state.h"
#include "events/simplestateevents.h"
#include "events/roomavatarevent.h"
#include "events/roommemberevent.h"
@@ -33,7 +34,6 @@
#include "events/receiptevent.h"
#include "events/redactionevent.h"
#include "jobs/sendeventjob.h"
-#include "jobs/roommessagesjob.h"
#include "jobs/mediathumbnailjob.h"
#include "jobs/downloadfilejob.h"
#include "jobs/postreadmarkersjob.h"
@@ -112,7 +112,7 @@ class Room::Private
TagsMap tags;
QHash<QString, AccountDataMap> accountData;
QString prevBatch;
- QPointer<RoomMessagesJob> roomMessagesJob;
+ QPointer<GetRoomEventsJob> eventsHistoryJob;
struct FileTransferPrivateInfo
{
@@ -199,13 +199,27 @@ class Room::Private
void markMessagesAsRead(rev_iter_t upToMarker);
+ template <typename EvT>
+ auto requestSetState(const QString& stateKey, const EvT& event)
+ {
+ return connection->callApi<SetRoomStateWithKeyJob>(
+ id, EvT::typeId(), stateKey, event.toJson());
+ }
+
+ template <typename EvT>
+ auto requestSetState(const EvT& event)
+ {
+ return connection->callApi<SetRoomStateJob>(
+ id, EvT::typeId(), event.toJson());
+ }
+
/**
* @brief Apply redaction to the timeline
*
* Tries to find an event in the timeline and redact it; deletes the
* redaction event whether the redacted event was found or not.
*/
- void processRedaction(RoomEventPtr&& redactionEvent);
+ void processRedaction(event_ptr_tt<RedactionEvent>&& redaction);
void broadcastTagUpdates()
{
@@ -1036,21 +1050,31 @@ void Room::updateData(SyncRoomData&& data)
for (auto&& event: data.accountData)
processAccountDataEvent(move(event));
+ bool emitNamesChanged = false;
if (!data.state.empty())
{
et.restart();
- processStateEvents(data.state);
- qCDebug(PROFILER) << "*** Room::processStateEvents(state):"
+ for (const auto& e: data.state)
+ emitNamesChanged |= processStateEvent(*e);
+
+ qCDebug(PROFILER) << "*** Room::processStateEvents():"
<< data.state.size() << "event(s)," << et;
}
if (!data.timeline.empty())
{
et.restart();
// State changes can arrive in a timeline event; so check those.
- processStateEvents(data.timeline);
+ for (const auto& e: data.timeline)
+ emitNamesChanged |= processStateEvent(*e);
qCDebug(PROFILER) << "*** Room::processStateEvents(timeline):"
<< data.timeline.size() << "event(s)," << et;
+ }
+ if (emitNamesChanged)
+ emit namesChanged(this);
+ d->updateDisplayname();
+ if (!data.timeline.empty())
+ {
et.restart();
d->addNewMessageEvents(move(data.timeline));
qCDebug(PROFILER) << "*** Room::addNewMessageEvents():" << et;
@@ -1100,19 +1124,17 @@ void Room::postMessage(const RoomMessageEvent& event)
void Room::setName(const QString& newName)
{
- connection()->callApi<SetRoomStateJob>(id(), RoomNameEvent(newName));
+ d->requestSetState(RoomNameEvent(newName));
}
void Room::setCanonicalAlias(const QString& newAlias)
{
- connection()->callApi<SetRoomStateJob>(id(),
- RoomCanonicalAliasEvent(newAlias));
+ d->requestSetState(RoomCanonicalAliasEvent(newAlias));
}
void Room::setTopic(const QString& newTopic)
{
- RoomTopicEvent evt(newTopic);
- connection()->callApi<SetRoomStateJob>(id(), evt);
+ d->requestSetState(RoomTopicEvent(newTopic));
}
void Room::getPreviousContent(int limit)
@@ -1122,13 +1144,13 @@ void Room::getPreviousContent(int limit)
void Room::Private::getPreviousContent(int limit)
{
- if( !isJobRunning(roomMessagesJob) )
+ if( !isJobRunning(eventsHistoryJob) )
{
- roomMessagesJob =
- connection->callApi<RoomMessagesJob>(id, prevBatch, limit);
- connect( roomMessagesJob, &RoomMessagesJob::success, [=] {
- prevBatch = roomMessagesJob->end();
- addHistoricalMessageEvents(roomMessagesJob->releaseEvents());
+ eventsHistoryJob =
+ connection->callApi<GetRoomEventsJob>(id, prevBatch, "b", "", limit);
+ connect( eventsHistoryJob, &BaseJob::success, q, [=] {
+ prevBatch = eventsHistoryJob->end();
+ addHistoricalMessageEvents(eventsHistoryJob->chunk());
});
}
}
@@ -1143,6 +1165,11 @@ LeaveRoomJob* Room::leaveRoom()
return connection()->callApi<LeaveRoomJob>(id());
}
+SetRoomStateWithKeyJob*Room::setMemberState(const QString& memberId, const RoomMemberEvent& event) const
+{
+ return d->requestSetState(memberId, event);
+}
+
void Room::kickMember(const QString& memberId, const QString& reason)
{
connection()->callApi<KickJob>(id(), memberId, reason);
@@ -1287,11 +1314,8 @@ inline bool isRedaction(const RoomEventPtr& e)
return e->type() == EventType::Redaction;
}
-void Room::Private::processRedaction(RoomEventPtr&& redactionEvent)
+void Room::Private::processRedaction(event_ptr_tt<RedactionEvent>&& redaction)
{
- Q_ASSERT(redactionEvent && isRedaction(redactionEvent));
- const auto& redaction = ptrCast<RedactionEvent>(move(redactionEvent));
-
const auto pIdx = eventsIndex.find(redaction->redactedEvent());
if (pIdx == eventsIndex.end())
{
@@ -1385,7 +1409,7 @@ void Room::Private::addNewMessageEvents(RoomEvents&& events)
const auto normalsBegin =
stable_partition(events.begin(), events.end(), isRedaction);
RoomEventsRange redactions { events.begin(), normalsBegin },
- normalEvents { normalsBegin, events.end() };
+ normalEvents { normalsBegin, events.end() };
if (!normalEvents.empty())
emit q->aboutToAddNewMessages(normalEvents);
@@ -1399,7 +1423,10 @@ void Room::Private::addNewMessageEvents(RoomEvents&& events)
q->onAddNewTimelineEvents(from);
}
for (auto&& r: redactions)
- processRedaction(move(r));
+ {
+ Q_ASSERT(isRedaction(r));
+ processRedaction(ptrCast<RedactionEvent>(move(r)));
+ }
if (insertedSize > 0)
{
emit q->addedMessages();
@@ -1450,107 +1477,95 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events)
Q_ASSERT(timeline.size() == timelineSize + insertedSize);
}
-void Room::processStateEvents(const RoomEvents& events)
+bool Room::processStateEvent(const RoomEvent& e)
{
- bool emitNamesChanged = false;
- for (const auto& e: events)
+ switch (e.type())
{
- switch (e->type())
- {
- case EventType::RoomName: {
- auto* nameEvent = weakPtr<const RoomNameEvent>(e);
- d->name = nameEvent->name();
- qCDebug(MAIN) << "Room name updated:" << d->name;
- emitNamesChanged = true;
- break;
- }
- case EventType::RoomAliases: {
- auto* aliasesEvent = weakPtr<const RoomAliasesEvent>(e);
- d->aliases = aliasesEvent->aliases();
- qCDebug(MAIN) << "Room aliases updated:" << d->aliases;
- emitNamesChanged = true;
- break;
- }
- case EventType::RoomCanonicalAlias: {
- auto* aliasEvent = weakPtr<const RoomCanonicalAliasEvent>(e);
- d->canonicalAlias = aliasEvent->alias();
- setObjectName(d->canonicalAlias);
- qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias;
- emitNamesChanged = true;
- break;
- }
- case EventType::RoomTopic: {
- auto* topicEvent = weakPtr<const RoomTopicEvent>(e);
- d->topic = topicEvent->topic();
- qCDebug(MAIN) << "Room topic updated:" << d->topic;
- emit topicChanged();
- break;
+ case EventType::RoomName: {
+ d->name = static_cast<const RoomNameEvent&>(e).name();
+ qCDebug(MAIN) << "Room name updated:" << d->name;
+ return true;
+ }
+ case EventType::RoomAliases: {
+ d->aliases = static_cast<const RoomAliasesEvent&>(e).aliases();
+ qCDebug(MAIN) << "Room aliases updated:" << d->aliases;
+ return true;
+ }
+ case EventType::RoomCanonicalAlias: {
+ d->canonicalAlias =
+ static_cast<const RoomCanonicalAliasEvent&>(e).alias();
+ setObjectName(d->canonicalAlias);
+ qCDebug(MAIN) << "Room canonical alias updated:" << d->canonicalAlias;
+ return true;
+ }
+ case EventType::RoomTopic: {
+ d->topic = static_cast<const RoomTopicEvent&>(e).topic();
+ qCDebug(MAIN) << "Room topic updated:" << d->topic;
+ emit topicChanged();
+ return false;
+ }
+ case EventType::RoomAvatar: {
+ const auto& avatarEventContent =
+ static_cast<const RoomAvatarEvent&>(e).content();
+ if (d->avatar.updateUrl(avatarEventContent.url))
+ {
+ qCDebug(MAIN) << "Room avatar URL updated:"
+ << avatarEventContent.url.toString();
+ emit avatarChanged();
}
- case EventType::RoomAvatar: {
- const auto& avatarEventContent =
- weakPtr<const RoomAvatarEvent>(e)->content();
- if (d->avatar.updateUrl(avatarEventContent.url))
+ return false;
+ }
+ case EventType::RoomMember: {
+ const auto& memberEvent = static_cast<const RoomMemberEvent&>(e);
+ auto* u = user(memberEvent.userId());
+ u->processEvent(memberEvent, this);
+ if (u == localUser() && memberJoinState(u) == JoinState::Invite
+ && memberEvent.isDirect())
+ connection()->addToDirectChats(this,
+ user(memberEvent.senderId()));
+
+ if( memberEvent.membership() == MembershipType::Join )
+ {
+ if (memberJoinState(u) != JoinState::Join)
{
- qCDebug(MAIN) << "Room avatar URL updated:"
- << avatarEventContent.url.toString();
- emit avatarChanged();
+ d->insertMemberIntoMap(u);
+ connect(u, &User::nameAboutToChange, this,
+ [=] (QString newName, QString, const Room* context) {
+ if (context == this)
+ emit memberAboutToRename(u, newName);
+ });
+ connect(u, &User::nameChanged, this,
+ [=] (QString, QString oldName, const Room* context) {
+ if (context == this)
+ d->renameMember(u, oldName);
+ });
+ emit userAdded(u);
}
- break;
}
- case EventType::RoomMember: {
- auto* memberEvent = weakPtr<const RoomMemberEvent>(e);
- auto u = user(memberEvent->userId());
- u->processEvent(memberEvent, this);
- if (u == localUser() && memberJoinState(u) == JoinState::Invite
- && memberEvent->isDirect())
- connection()->addToDirectChats(this,
- user(memberEvent->senderId()));
-
- if( memberEvent->membership() == MembershipType::Join )
- {
- if (memberJoinState(u) != JoinState::Join)
- {
- d->insertMemberIntoMap(u);
- connect(u, &User::nameAboutToChange, this,
- [=] (QString newName, QString, const Room* context) {
- if (context == this)
- emit memberAboutToRename(u, newName);
- });
- connect(u, &User::nameChanged, this,
- [=] (QString, QString oldName, const Room* context) {
- if (context == this)
- d->renameMember(u, oldName);
- });
- emit userAdded(u);
- }
- }
- else if( memberEvent->membership() == MembershipType::Leave )
+ else if( memberEvent.membership() == MembershipType::Leave )
+ {
+ if (memberJoinState(u) == JoinState::Join)
{
- if (memberJoinState(u) == JoinState::Join)
- {
- if (!d->membersLeft.contains(u))
- d->membersLeft.append(u);
- d->removeMemberFromMap(u->name(this), u);
- emit userRemoved(u);
- }
+ if (!d->membersLeft.contains(u))
+ d->membersLeft.append(u);
+ d->removeMemberFromMap(u->name(this), u);
+ emit userRemoved(u);
}
- break;
- }
- case EventType::RoomEncryption:
- {
- d->encryptionAlgorithm =
- weakPtr<const EncryptionEvent>(e)->algorithm();
- qCDebug(MAIN) << "Encryption switched on in" << displayName();
- emit encryption();
- break;
}
- default: /* Ignore events of other types */;
+ return false;
}
+ case EventType::RoomEncryption:
+ {
+ d->encryptionAlgorithm =
+ static_cast<const EncryptionEvent&>(e).algorithm();
+ qCDebug(MAIN) << "Encryption switched on in" << displayName();
+ emit encryption();
+ return false;
+ }
+ default:
+ /* Ignore events of other types */
+ return false;
}
- if (emitNamesChanged) {
- emit namesChanged(this);
- }
- d->updateDisplayname();
}
void Room::processEphemeralEvent(EventPtr&& event)
@@ -1776,7 +1791,7 @@ void appendEvent(QJsonArray& events, const QString& type,
template <typename EvtT>
void appendEvent(QJsonArray& events, const EvtT& event)
{
- appendEvent(events, EvtT::TypeId, event.toJson());
+ appendEvent(events, EvtT::typeId(), event.toJson());
}
QJsonObject Room::Private::toJson() const