aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--events/event.h25
-rw-r--r--room.cpp124
-rw-r--r--room.h20
3 files changed, 83 insertions, 86 deletions
diff --git a/events/event.h b/events/event.h
index bb80cde8..2e5e5da1 100644
--- a/events/event.h
+++ b/events/event.h
@@ -35,7 +35,7 @@ namespace QMatrixClient
RoomMessage, RoomName, RoomAliases, RoomCanonicalAlias,
RoomMember, RoomTopic, Typing, Receipt, Unknown
};
-
+
class Event
{
public:
@@ -62,28 +62,7 @@ namespace QMatrixClient
};
using Events = QVector<Event*>;
- Events eventsFromJson(const QJsonArray& contents);
-
- /**
- * Finds a place in the timeline where a new event/message could be inserted.
- * @return an iterator to an item with the earliest timestamp after
- * the one of 'item'; or timeline.end(), if all events are earlier
- */
- template <class ItemT, class ContT>
- typename ContT::iterator
- findInsertionPos(ContT & timeline, const ItemT *item)
- {
- return std::lower_bound (timeline.begin(), timeline.end(), item,
- [](const typename ContT::value_type a, const ItemT * b) {
- // FIXME: We should not order the message list by origin timestamp.
- // Rather, an order of receiving should be used (which actually
- // poses a question on whether this method is needed at all -
- // or we'd just prepend and append, depending on whether we
- // received something from /sync or from /messages.
- return a->timestamp() < b->timestamp();
- }
- );
- }
+ Events eventsFromJson(const QJsonArray& json);
/**
* @brief Lookup a value by a key in a varargs list
diff --git a/room.cpp b/room.cpp
index 3683781b..e08b45e8 100644
--- a/room.cpp
+++ b/room.cpp
@@ -46,7 +46,7 @@ class Room::Private
public:
/** Map of user names to users. User names potentially duplicate, hence a multi-hashmap. */
typedef QMultiHash<QString, User*> members_map_t;
-
+
Private(Connection* c, const QString& id_)
: q(nullptr), connection(c), id(id_), joinState(JoinState::Join)
, roomMessagesJob(nullptr)
@@ -76,7 +76,7 @@ class Room::Private
QHash<User*, QString> lastReadEvent;
QString prevBatch;
RoomMessagesJob* roomMessagesJob;
-
+
// Convenience methods to work with the membersMap and usersLeft.
// addMember() and removeMember() emit respective Room:: signals
// after a succesful operation.
@@ -335,18 +335,13 @@ void Room::updateData(const SyncRoomData& data)
d->prevBatch = data.timelinePrevBatch;
setJoinState(data.joinState);
- for( Event* stateEvent: data.state )
- {
- processStateEvent(stateEvent);
- }
+ processStateEvents(data.state);
- for( Event* timelineEvent: data.timeline )
+ if (!data.timeline.empty())
{
-
- processMessageEvent(timelineEvent);
- emit newMessage(timelineEvent);
- // State changes can arrive in a timeline event - try to check those.
- processStateEvent(timelineEvent);
+ // State changes can arrive in a timeline event; so check those.
+ processStateEvents(data.timeline);
+ addNewMessageEvents(data.timeline);
}
for( Event* ephemeralEvent: data.ephemeral )
@@ -379,11 +374,7 @@ void Room::Private::getPreviousContent()
connect( roomMessagesJob, &RoomMessagesJob::result, [=]() {
if( !roomMessagesJob->error() )
{
- for( Event* event: roomMessagesJob->events() )
- {
- q->processMessageEvent(event);
- emit q->newMessage(event);
- }
+ q->addHistoricalMessageEvents(roomMessagesJob->events());
prevBatch = roomMessagesJob->end();
}
roomMessagesJob = nullptr;
@@ -396,61 +387,80 @@ Connection* Room::connection() const
return d->connection;
}
-void Room::processMessageEvent(Event* event)
+void Room::addNewMessageEvents(const Events& events)
+{
+ emit aboutToAddNewMessages(events);
+ doAddNewMessageEvents(events);
+ emit addedMessages();
+}
+
+void Room::doAddNewMessageEvents(const Events& events)
{
- d->messageEvents.insert(findInsertionPos(d->messageEvents, event), event);
+ d->messageEvents.reserve(d->messageEvents.size() + events.size());
+ std::copy(events.begin(), events.end(), std::back_inserter(d->messageEvents));
}
-void Room::processStateEvent(Event* event)
+void Room::addHistoricalMessageEvents(const Events& events)
{
- if( event->type() == EventType::RoomName )
+ emit aboutToAddHistoricalMessages(events);
+ doAddHistoricalMessageEvents(events);
+ emit addedMessages();
+}
+
+void Room::doAddHistoricalMessageEvents(const Events& events)
+{
+ // Historical messages arrive in newest-to-oldest order
+ d->messageEvents.reserve(d->messageEvents.size() + events.size());
+ std::copy(events.begin(), events.end(), std::front_inserter(d->messageEvents));
+}
+
+void Room::processStateEvents(const Events& events)
+{
+ for (auto event: events)
{
- if (RoomNameEvent* nameEvent = static_cast<RoomNameEvent*>(event))
+ if( event->type() == EventType::RoomName )
{
+ RoomNameEvent* nameEvent = static_cast<RoomNameEvent*>(event);
d->name = nameEvent->name();
qDebug() << "room name:" << d->name;
d->updateDisplayname();
emit namesChanged(this);
- } else
+ }
+ if( event->type() == EventType::RoomAliases )
+ {
+ RoomAliasesEvent* aliasesEvent = static_cast<RoomAliasesEvent*>(event);
+ d->aliases = aliasesEvent->aliases();
+ qDebug() << "room aliases:" << d->aliases;
+ // No displayname update - aliases are not used to render a displayname
+ emit namesChanged(this);
+ }
+ if( event->type() == EventType::RoomCanonicalAlias )
{
- qDebug() <<
- "!!! event type is RoomName but the event is not RoomNameEvent";
+ RoomCanonicalAliasEvent* aliasEvent = static_cast<RoomCanonicalAliasEvent*>(event);
+ d->canonicalAlias = aliasEvent->alias();
+ qDebug() << "room canonical alias:" << d->canonicalAlias;
+ d->updateDisplayname();
+ emit namesChanged(this);
}
- }
- if( event->type() == EventType::RoomAliases )
- {
- RoomAliasesEvent* aliasesEvent = static_cast<RoomAliasesEvent*>(event);
- d->aliases = aliasesEvent->aliases();
- qDebug() << "room aliases:" << d->aliases;
- // No displayname update - aliases are not used to render a displayname
- emit namesChanged(this);
- }
- if( event->type() == EventType::RoomCanonicalAlias )
- {
- RoomCanonicalAliasEvent* aliasEvent = static_cast<RoomCanonicalAliasEvent*>(event);
- d->canonicalAlias = aliasEvent->alias();
- qDebug() << "room canonical alias:" << d->canonicalAlias;
- d->updateDisplayname();
- emit namesChanged(this);
- }
- if( event->type() == EventType::RoomTopic )
- {
- RoomTopicEvent* topicEvent = static_cast<RoomTopicEvent*>(event);
- d->topic = topicEvent->topic();
- emit topicChanged();
- }
- if( event->type() == EventType::RoomMember )
- {
- RoomMemberEvent* memberEvent = static_cast<RoomMemberEvent*>(event);
- User* u = d->connection->user(memberEvent->userId());
- u->processEvent(event);
- if( memberEvent->membership() == MembershipType::Join )
+ if( event->type() == EventType::RoomTopic )
{
- d->addMember(u);
+ RoomTopicEvent* topicEvent = static_cast<RoomTopicEvent*>(event);
+ d->topic = topicEvent->topic();
+ emit topicChanged();
}
- else if( memberEvent->membership() == MembershipType::Leave )
+ if( event->type() == EventType::RoomMember )
{
- d->removeMember(u);
+ RoomMemberEvent* memberEvent = static_cast<RoomMemberEvent*>(event);
+ User* u = d->connection->user(memberEvent->userId());
+ u->processEvent(event);
+ if( memberEvent->membership() == MembershipType::Join )
+ {
+ d->addMember(u);
+ }
+ else if( memberEvent->membership() == MembershipType::Leave )
+ {
+ d->removeMember(u);
+ }
}
}
}
diff --git a/room.h b/room.h
index 8f6a65a6..1c29aa01 100644
--- a/room.h
+++ b/room.h
@@ -82,13 +82,17 @@ namespace QMatrixClient
void userRenamed(User* user, QString oldName);
signals:
- void newMessage(Event* event);
+ void aboutToAddHistoricalMessages(const Events& events);
+ void aboutToAddNewMessages(const Events& events);
+ void addedMessages();
+
/**
- * Triggered when the room name, canonical alias or other aliases
- * change. Not triggered when displayname changes.
+ * @brief The room name, the canonical alias or other aliases changed
+ *
+ * Not triggered when displayname changes.
*/
void namesChanged(Room* room);
- /** Triggered only for changes in the room displayname. */
+ /** @brief The room displayname changed */
void displaynameChanged(Room* room);
void topicChanged();
void userAdded(User* user);
@@ -101,13 +105,17 @@ namespace QMatrixClient
protected:
Connection* connection() const;
- virtual void processMessageEvent(Event* event);
- virtual void processStateEvent(Event* event);
+ virtual void doAddNewMessageEvents(const Events& events);
+ virtual void doAddHistoricalMessageEvents(const Events& events);
+ virtual void processStateEvents(const Events& events);
virtual void processEphemeralEvent(Event* event);
private:
class Private;
Private* d;
+
+ void addNewMessageEvents(const Events& events);
+ void addHistoricalMessageEvents(const Events& events);
};
}