Render messages received by `/messages` on demand

This commit is contained in:
Konstantinos Sideris 2018-01-30 12:56:01 -07:00
parent 992332adf7
commit b1f232bf86
2 changed files with 66 additions and 33 deletions

View File

@ -211,9 +211,13 @@ private:
//! Messages received by sync not added to the timeline. //! Messages received by sync not added to the timeline.
std::vector<TimelineEvent> bottomMessages_; std::vector<TimelineEvent> bottomMessages_;
//! Messages received by /messages not added to the timeline.
std::vector<TimelineEvent> topMessages_;
//! Render the given timeline events to the bottom of the timeline. //! Render the given timeline events to the bottom of the timeline.
void renderBottomEvents(const std::vector<TimelineEvent> &events); void renderBottomEvents(const std::vector<TimelineEvent> &events);
//! Render the given timeline events to the top of the timeline.
void renderTopEvents(const std::vector<TimelineEvent> &events);
//! Decide if the given timeline event can be rendered. //! Decide if the given timeline event can be rendered.
inline bool isViewable(const TimelineEvent &event) const; inline bool isViewable(const TimelineEvent &event) const;

View File

@ -163,48 +163,32 @@ TimelineView::addBackwardsEvents(const QString &room_id, const mtx::responses::M
} }
isTimelineFinished = false; isTimelineFinished = false;
QList<TimelineItem *> items;
// Reset the sender of the first message in the timeline // Queue incoming messages to be rendered later.
// cause we're about to insert a new one. for (auto const &e : msgs.chunk) {
firstSender_.clear(); if (isViewable(e))
topMessages_.emplace_back(e);
// Parse in reverse order to determine where we should not show sender's
// name.
auto ii = msgs.chunk.size();
while (ii != 0) {
--ii;
TimelineItem *item = parseMessageEvent(msgs.chunk[ii], TimelineDirection::Top);
if (item != nullptr)
items.push_back(item);
} }
// Reverse again to render them. // The RoomList message preview will be updated only if this
std::reverse(items.begin(), items.end()); // is the first batch of messages received through /messages
// i.e there are no other messages currently present.
if (!topMessages_.empty() && scroll_layout_->count() == 1)
notifyForLastEvent(topMessages_.at(0));
oldPosition_ = scroll_area_->verticalScrollBar()->value(); if (isVisible()) {
oldHeight_ = scroll_widget_->size().height(); renderTopEvents(topMessages_);
for (const auto &item : items) // Free up space for new messages.
addTimelineItem(item, TimelineDirection::Top); topMessages_.clear();
lastMessageDirection_ = TimelineDirection::Top; // Send a read receipt for the last event.
if (isActiveWindow())
QApplication::processEvents(); readLastEvent();
}
prev_batch_token_ = QString::fromStdString(msgs.end); prev_batch_token_ = QString::fromStdString(msgs.end);
isPaginationInProgress_ = false; isPaginationInProgress_ = false;
// Exclude the top stretch.
if (msgs.chunk.size() != 0 && scroll_layout_->count() > 1)
notifyForLastEvent();
// If this batch is the first being rendered (i.e the first and the last
// events originate from this batch), set the last sender.
if (lastSender_.isEmpty() && !items.isEmpty())
lastSender_ = items.constFirst()->descriptionMessage().userid;
} }
TimelineItem * TimelineItem *
@ -270,6 +254,46 @@ TimelineView::renderBottomEvents(const std::vector<TimelineEvent> &events)
QApplication::processEvents(); QApplication::processEvents();
} }
void
TimelineView::renderTopEvents(const std::vector<TimelineEvent> &events)
{
std::vector<TimelineItem *> items;
// Reset the sender of the first message in the timeline
// cause we're about to insert a new one.
firstSender_.clear();
// Parse in reverse order to determine where we should not show sender's
// name.
auto ii = events.size();
while (ii != 0) {
--ii;
TimelineItem *item = parseMessageEvent(events[ii], TimelineDirection::Top);
if (item != nullptr)
items.push_back(item);
}
// Reverse again to render them.
std::reverse(items.begin(), items.end());
oldPosition_ = scroll_area_->verticalScrollBar()->value();
oldHeight_ = scroll_widget_->size().height();
for (const auto &item : items)
addTimelineItem(item, TimelineDirection::Top);
lastMessageDirection_ = TimelineDirection::Top;
QApplication::processEvents();
// If this batch is the first being rendered (i.e the first and the last
// events originate from this batch), set the last sender.
if (lastSender_.isEmpty() && !items.empty())
lastSender_ = items.at(0)->descriptionMessage().userid;
}
int int
TimelineView::addEvents(const mtx::responses::Timeline &timeline) TimelineView::addEvents(const mtx::responses::Timeline &timeline)
{ {
@ -636,6 +660,11 @@ TimelineView::getLastEventId() const
void void
TimelineView::showEvent(QShowEvent *event) TimelineView::showEvent(QShowEvent *event)
{ {
if (!topMessages_.empty()) {
renderTopEvents(topMessages_);
topMessages_.clear();
}
if (!bottomMessages_.empty()) { if (!bottomMessages_.empty()) {
renderBottomEvents(bottomMessages_); renderBottomEvents(bottomMessages_);
bottomMessages_.clear(); bottomMessages_.clear();