diff --git a/src/app/qml/RoomPage.qml b/src/app/qml/RoomPage.qml index a4816559d..389745b13 100644 --- a/src/app/qml/RoomPage.qml +++ b/src/app/qml/RoomPage.qml @@ -75,6 +75,12 @@ Kirigami.Page { focus: true padding: 0 + onHeightChanged: { + // HACK: See TimelineView for the hack details. + // We get the height change here *first* so we are informed this is because of a window resize and not due to the pinned message. + (timelineViewLoader.item as TimelineView).resetViewSettling(); + } + actions: [ Kirigami.Action { id: jitsiMeetingAction diff --git a/src/timeline/TimelineView.qml b/src/timeline/TimelineView.qml index 5f74fdcce..6c3eb3929 100644 --- a/src/timeline/TimelineView.qml +++ b/src/timeline/TimelineView.qml @@ -80,12 +80,30 @@ QQC2.ScrollView { QQC2.ScrollBar.vertical.interactive: false + /** + * @brief Tell the view to resettle again as needed. + */ + function resetViewSettling() { + _private.viewHasSettled = false; + } + ListView { id: messageListView // HACK: Use this instead of atYEnd to handle cases like -643.2 at height of 643 not being counted as "at the beginning" readonly property bool closeToYEnd: -Math.round(contentY) >= height + onHeightChanged: { + // HACK: Fix a bug where Qt doesn't resettle the view properly when the pinned messages changes our height + // We basically want to resettle back at the start if: + // * The user hasn't scrolled before (obviously) *and* that scroll is actually somewhere other than the beginning + // * This is the first height change + if (!_private.viewHasSettled && (!_private.hasScrolledUpBefore || closeToYEnd)) { + positionViewAtBeginning(); + _private.viewHasSettled = true; + } + } + /** * @brief Whether all unread messages in the timeline are visible. */ @@ -141,19 +159,13 @@ QQC2.ScrollView { } } - Component.onCompleted: { - positionViewAtBeginning(); - } Connections { target: messageListView.model.sourceModel.timelineMessageModel function onModelAboutToBeReset() { (root.QQC2.ApplicationWindow.window as Main).hoverLinkIndicator.text = ""; _private.hasScrolledUpBefore = false; - } - - function onModelResetComplete() { - messageListView.positionViewAtBeginning(); + _private.viewHasSettled = false; } function onReadMarkerAdded() { @@ -182,13 +194,20 @@ QQC2.ScrollView { } } - onCloseToYEndChanged: if (closeToYEnd && _private.hasScrolledUpBefore) { - if (QQC2.ApplicationWindow.window && (QQC2.ApplicationWindow.window.visibility !== QQC2.ApplicationWindow.Hidden)) { - _private.room.markAllMessagesAsRead(); + onAtYEndChanged: { + // Don't care about this until the view has settled first. + if (!_private.viewHasSettled) { + return; + } + + if (closeToYEnd && _private.hasScrolledUpBefore) { + if (QQC2.ApplicationWindow.window && (QQC2.ApplicationWindow.window.visibility !== QQC2.ApplicationWindow.Hidden)) { + _private.room.markAllMessagesAsRead(); + } + _private.hasScrolledUpBefore = false; + } else if (!closeToYEnd) { + _private.hasScrolledUpBefore = true; } - _private.hasScrolledUpBefore = false; - } else if (!closeToYEnd) { - _private.hasScrolledUpBefore = true; } model: root.messageFilterModel @@ -371,5 +390,8 @@ QQC2.ScrollView { // Used to determine if scrolling to the bottom should mark the message as unread property bool hasScrolledUpBefore: false + + // Used to determine if the view has settled and should stop moving + property bool viewHasSettled: false } }