From d1fffd66170d7548926b205dda7d8de81bef3384 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 18 Sep 2019 20:34:30 +0200 Subject: [PATCH] Implement simple scroll state handling --- resources/qml/TimelineView.qml | 47 ++++++++++++++++++++++++++- src/timeline2/TimelineModel.cpp | 19 +++++++++++ src/timeline2/TimelineModel.h | 12 +++++++ src/timeline2/TimelineViewManager.cpp | 1 - 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 4f10f352..e1aa2738 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -2,6 +2,7 @@ import QtQuick 2.6 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.5 import QtGraphicalEffects 1.0 +import QtQuick.Window 2.2 import com.github.nheko 1.0 @@ -28,14 +29,51 @@ Rectangle { visible: timelineManager.timeline != null anchors.fill: parent + model: timelineManager.timeline + + onModelChanged: { + if (model) { + currentIndex = model.currentIndex + if (model.currentIndex == count - 1) { + positionViewAtEnd() + } else { + positionViewAtIndex(model.currentIndex, ListView.End) + } + } + } + ScrollBar.vertical: ScrollBar { id: scrollbar anchors.top: parent.top anchors.right: parent.right anchors.bottom: parent.bottom + onPressedChanged: if (!pressed) chat.updatePosition() } - model: timelineManager.timeline + property bool atBottom: false + onCountChanged: { + if (atBottom && Window.active) { + var newIndex = count - 1 // last index + positionViewAtEnd() + currentIndex = newIndex + model.currentIndex = newIndex + } + } + + function updatePosition() { + for (var y = chat.contentY + chat.height; y > chat.height; y -= 5) { + var i = chat.itemAt(100, y); + if (!i) continue; + if (!i.isFullyVisible()) continue; + chat.model.currentIndex = i.getIndex(); + chat.currentIndex = i.getIndex() + atBottom = i.getIndex() == count - 1; + console.log("bottom:" + atBottom) + break; + } + } + onMovementEnded: updatePosition() + spacing: 4 delegate: RowLayout { anchors.leftMargin: 52 @@ -43,6 +81,13 @@ Rectangle { anchors.right: parent.right anchors.rightMargin: scrollbar.width + function isFullyVisible() { + return (y - chat.contentY - 1) + height < chat.height + } + function getIndex() { + return index; + } + Loader { id: loader Layout.fillWidth: true diff --git a/src/timeline2/TimelineModel.cpp b/src/timeline2/TimelineModel.cpp index 46a33add..7a2edda4 100644 --- a/src/timeline2/TimelineModel.cpp +++ b/src/timeline2/TimelineModel.cpp @@ -625,3 +625,22 @@ TimelineModel::replyAction(QString id) emit ChatPage::instance()->messageReply(related); } + +int +TimelineModel::idToIndex(QString id) const +{ + if (id.isEmpty()) + return -1; + for (int i = 0; i < (int)eventOrder.size(); i++) + if (id == eventOrder[i]) + return i; + return -1; +} + +QString +TimelineModel::indexToId(int index) const +{ + if (index < 0 || index >= (int)eventOrder.size()) + return ""; + return eventOrder[index]; +} diff --git a/src/timeline2/TimelineModel.h b/src/timeline2/TimelineModel.h index b2481668..17f83323 100644 --- a/src/timeline2/TimelineModel.h +++ b/src/timeline2/TimelineModel.h @@ -81,6 +81,8 @@ struct DecryptionResult class TimelineModel : public QAbstractListModel { Q_OBJECT + Q_PROPERTY( + int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) public: explicit TimelineModel(QString room_id, QObject *parent = 0); @@ -112,6 +114,8 @@ public: Q_INVOKABLE QString escapeEmoji(QString str) const; Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void replyAction(QString id); + Q_INVOKABLE int idToIndex(QString id) const; + Q_INVOKABLE QString indexToId(int index) const; void addEvents(const mtx::responses::Timeline &events); template @@ -119,6 +123,12 @@ public: public slots: void fetchHistory(); + void setCurrentIndex(int index) + { + currentId = indexToId(index); + emit currentIndexChanged(index); + } + int currentIndex() const { return idToIndex(currentId); } private slots: // Add old events at the top of the timeline. @@ -129,6 +139,7 @@ signals: void oldMessagesRetrieved(const mtx::responses::Messages &res); void messageFailed(const std::string txn_id); void messageSent(const std::string txn_id, std::string event_id); + void currentIndexChanged(int index); private: DecryptionResult decryptEvent( @@ -146,6 +157,7 @@ private: bool paginationInProgress = false; QHash userColors; + QString currentId; }; template diff --git a/src/timeline2/TimelineViewManager.cpp b/src/timeline2/TimelineViewManager.cpp index 93a42543..8233d33e 100644 --- a/src/timeline2/TimelineViewManager.cpp +++ b/src/timeline2/TimelineViewManager.cpp @@ -14,7 +14,6 @@ TimelineViewManager::TimelineViewManager(QWidget *parent) 0, "MtxEvent", "Can't instantiate enum!"); - view = new QQuickView(); container = QWidget::createWindowContainer(view, parent); container->setMinimumSize(200, 200);