From 36d25951dc147efc032bb0390b3b65c0c43ef129 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Mon, 5 Jun 2017 19:21:19 +0300 Subject: [PATCH 1/4] Fix scrolling flickering on backwards pagination --- include/TimelineView.h | 6 +++++- src/TimelineView.cc | 22 ++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/include/TimelineView.h b/include/TimelineView.h index 67ea28b2..b50970b9 100644 --- a/include/TimelineView.h +++ b/include/TimelineView.h @@ -111,12 +111,16 @@ private: bool isInitialized = false; bool isTimelineFinished = false; bool isInitialSync = true; + bool isPaginationScrollPending_ = false; - const int SCROLL_BAR_GAP = 300; + const int SCROLL_BAR_GAP = 400; int scroll_height_ = 0; int previous_max_height_ = 0; + int oldPosition_; + int oldHeight_; + QList pending_msgs_; QSharedPointer client_; }; diff --git a/src/TimelineView.cc b/src/TimelineView.cc index 5cd59fe5..412b9520 100644 --- a/src/TimelineView.cc +++ b/src/TimelineView.cc @@ -58,6 +58,15 @@ void TimelineView::sliderRangeChanged(int min, int max) if (max - scroll_area_->verticalScrollBar()->value() < SCROLL_BAR_GAP) scroll_area_->verticalScrollBar()->setValue(max); + + if (isPaginationScrollPending_) { + isPaginationScrollPending_ = false; + + int currentHeight = scroll_widget_->size().height(); + int diff = currentHeight - oldHeight_; + + scroll_area_->verticalScrollBar()->setValue(oldPosition_ + diff); + } } void TimelineView::scrollDown() @@ -88,17 +97,14 @@ void TimelineView::sliderMoved(int position) return; // Prevent user from moving up when there is pagination in progress. - if (isPaginationInProgress_) { - scroll_area_->verticalScrollBar()->setValue(SCROLL_BAR_GAP); + // TODO: Keep a map of the event ids to filter out duplicates. + if (isPaginationInProgress_) return; - } isPaginationInProgress_ = true; - scroll_height_ = scroll_area_->verticalScrollBar()->value(); - previous_max_height_ = scroll_area_->verticalScrollBar()->maximum(); // FIXME: Maybe move this to TimelineViewManager to remove the extra calls? - client_.data()->messages(room_id_, prev_batch_token_); + client_->messages(room_id_, prev_batch_token_); } } @@ -130,11 +136,15 @@ void TimelineView::addBackwardsEvents(const QString &room_id, const RoomMessages // 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); prev_batch_token_ = msgs.end(); isPaginationInProgress_ = false; + isPaginationScrollPending_ = true; } TimelineItem *TimelineView::parseMessageEvent(const QJsonObject &event, TimelineDirection direction) From 26dfbfd08ceb913fd91f123935696d253fca2035 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Mon, 5 Jun 2017 19:54:45 +0300 Subject: [PATCH 2/4] Lazy load initial timeline events --- include/MatrixClient.h | 2 +- src/MatrixClient.cc | 5 +++-- src/TimelineView.cc | 14 ++++++++------ src/TimelineViewManager.cc | 3 ++- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/MatrixClient.h b/include/MatrixClient.h index 2fde1c1e..7a4ac24b 100644 --- a/include/MatrixClient.h +++ b/include/MatrixClient.h @@ -44,7 +44,7 @@ public: void fetchUserAvatar(const QString &userId, const QUrl &avatarUrl); void fetchOwnAvatar(const QUrl &avatar_url); void downloadImage(const QString &event_id, const QUrl &url); - void messages(const QString &room_id, const QString &from_token) noexcept; + void messages(const QString &room_id, const QString &from_token, int limit = 20) noexcept; inline QUrl getHomeServer(); inline int transactionId(); diff --git a/src/MatrixClient.cc b/src/MatrixClient.cc index 927db541..ebecb05a 100644 --- a/src/MatrixClient.cc +++ b/src/MatrixClient.cc @@ -541,7 +541,7 @@ void MatrixClient::initialSync() noexcept }; QJsonObject filter{{"room", - QJsonObject{{"timeline", QJsonObject{{"limit", 70}}}, + QJsonObject{{"timeline", QJsonObject{{"limit", 20}}}, {"ephemeral", QJsonObject{{"limit", 0}}}}}, {"presence", QJsonObject{{"not_types", excluded_presence}}}}; @@ -677,12 +677,13 @@ void MatrixClient::fetchOwnAvatar(const QUrl &avatar_url) reply->setProperty("endpoint", static_cast(Endpoint::GetOwnAvatar)); } -void MatrixClient::messages(const QString &room_id, const QString &from_token) noexcept +void MatrixClient::messages(const QString &room_id, const QString &from_token, int limit) noexcept { QUrlQuery query; query.addQueryItem("access_token", token_); query.addQueryItem("from", from_token); query.addQueryItem("dir", "b"); + query.addQueryItem("limit", QString::number(limit)); QUrl endpoint(server_); endpoint.setPath(api_url_ + QString("/rooms/%1/messages").arg(room_id)); diff --git a/src/TimelineView.cc b/src/TimelineView.cc index 412b9520..418545a6 100644 --- a/src/TimelineView.cc +++ b/src/TimelineView.cc @@ -76,7 +76,7 @@ void TimelineView::scrollDown() // The first time we enter the room move the scroll bar to the bottom. if (!isInitialized) { - scroll_area_->ensureVisible(0, scroll_widget_->size().height(), 0, 0); + scroll_area_->verticalScrollBar()->setValue(max); isInitialized = true; return; } @@ -226,11 +226,6 @@ int TimelineView::addEvents(const Timeline &timeline) QSettings settings; QString localUser = settings.value("auth/user_id").toString(); - if (isInitialSync) { - prev_batch_token_ = timeline.previousBatch(); - isInitialSync = false; - } - for (const auto &event : timeline.events()) { TimelineItem *item = parseMessageEvent(event.toObject(), TimelineDirection::Bottom); auto sender = event.toObject().value("sender").toString(); @@ -243,6 +238,13 @@ int TimelineView::addEvents(const Timeline &timeline) } } + if (isInitialSync) { + prev_batch_token_ = timeline.previousBatch(); + isInitialSync = false; + + client_->messages(room_id_, prev_batch_token_); + } + return message_count; } diff --git a/src/TimelineViewManager.cc b/src/TimelineViewManager.cc index 008dc5dc..f55d4868 100644 --- a/src/TimelineViewManager.cc +++ b/src/TimelineViewManager.cc @@ -119,9 +119,10 @@ void TimelineViewManager::setHistoryView(const QString &room_id) active_room_ = room_id; auto widget = views_.value(room_id); - widget->scrollDown(); setCurrentWidget(widget.data()); + + widget->scrollDown(); } QMap TimelineViewManager::NICK_COLORS; From da190593c8b2739692d69718da91792f35d089e0 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Mon, 5 Jun 2017 20:19:20 +0300 Subject: [PATCH 3/4] Repaint when the room avatar is received --- include/RoomInfoListItem.h | 1 + src/RoomInfoListItem.cc | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/RoomInfoListItem.h b/include/RoomInfoListItem.h index 40a1cbb0..12d5abb1 100644 --- a/include/RoomInfoListItem.h +++ b/include/RoomInfoListItem.h @@ -104,4 +104,5 @@ inline RoomState RoomInfoListItem::state() const inline void RoomInfoListItem::setAvatar(const QImage &img) { roomAvatar_ = QPixmap::fromImage(img.scaled(IconSize, IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + update(); } diff --git a/src/RoomInfoListItem.cc b/src/RoomInfoListItem.cc index 3d4c5355..be1b4133 100644 --- a/src/RoomInfoListItem.cc +++ b/src/RoomInfoListItem.cc @@ -189,13 +189,13 @@ void RoomInfoListItem::paintEvent(QPaintEvent *event) void RoomInfoListItem::updateUnreadMessageCount(int count) { unreadMsgCount_ += count; - repaint(); + update(); } void RoomInfoListItem::clearUnreadMessageCount() { unreadMsgCount_ = 0; - repaint(); + update(); } void RoomInfoListItem::setPressedState(bool state) @@ -212,7 +212,7 @@ void RoomInfoListItem::setPressedState(bool state) void RoomInfoListItem::setState(const RoomState &new_state) { state_ = new_state; - repaint(); + update(); } void RoomInfoListItem::contextMenuEvent(QContextMenuEvent *event) From 82b48d926dd835aa3adb5fb3a8426532386df5c0 Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Tue, 6 Jun 2017 15:03:11 +0300 Subject: [PATCH 4/4] Don't collapse room list --- src/Splitter.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Splitter.cc b/src/Splitter.cc index 2564c434..a15e8d0a 100644 --- a/src/Splitter.cc +++ b/src/Splitter.cc @@ -24,6 +24,7 @@ Splitter::Splitter(QWidget *parent) : QSplitter(parent) { connect(this, &QSplitter::splitterMoved, this, &Splitter::onSplitterMoved); + setChildrenCollapsible(false); } void Splitter::onSplitterMoved(int pos, int index)