Implement simple scroll state handling

This commit is contained in:
Nicolas Werner 2019-09-18 20:34:30 +02:00
parent 691c854201
commit d1fffd6617
4 changed files with 77 additions and 2 deletions

View file

@ -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

View file

@ -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];
}

View file

@ -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<class T>
@ -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<QString, QColor> userColors;
QString currentId;
};
template<class T>

View file

@ -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);