mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
Merge pull request #183 from shocklateboy92/features/smooth-scroll
Improve scrolling in timeline view
This commit is contained in:
commit
19ec8d261d
4 changed files with 126 additions and 20 deletions
109
resources/qml/ScrollHelper.qml
Normal file
109
resources/qml/ScrollHelper.qml
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Michael Bohlender, <michael.bohlender@kdemail.net>
|
||||||
|
* Copyright (C) 2017 Christian Mollekopf, <mollekopf@kolabsystems.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Controls 2.12
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shamelessly stolen from:
|
||||||
|
* https://cgit.kde.org/kube.git/tree/framework/qml/ScrollHelper.qml
|
||||||
|
*
|
||||||
|
* The MouseArea + interactive: false + maximumFlickVelocity are required
|
||||||
|
* to fix scrolling for desktop systems where we don't want flicking behaviour.
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* ScrollView.qml in qtquickcontrols
|
||||||
|
* qquickwheelarea.cpp in qtquickcontrols
|
||||||
|
*/
|
||||||
|
MouseArea {
|
||||||
|
id: root
|
||||||
|
propagateComposedEvents: true
|
||||||
|
|
||||||
|
property Flickable flickable
|
||||||
|
property alias enabled: root.enabled
|
||||||
|
|
||||||
|
//Place the mouse area under the flickable
|
||||||
|
z: -1
|
||||||
|
onFlickableChanged: {
|
||||||
|
if (enabled) {
|
||||||
|
flickable.maximumFlickVelocity = 100000
|
||||||
|
flickable.boundsBehavior = Flickable.StopAtBounds
|
||||||
|
root.parent = flickable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
|
||||||
|
function calculateNewPosition(flickableItem, wheel) {
|
||||||
|
//Nothing to scroll
|
||||||
|
if (flickableItem.contentHeight < flickableItem.height) {
|
||||||
|
return flickableItem.contentY;
|
||||||
|
}
|
||||||
|
//Ignore 0 events (happens at least with Christians trackpad)
|
||||||
|
if (wheel.pixelDelta.y == 0 && wheel.angleDelta.y == 0) {
|
||||||
|
return flickableItem.contentY;
|
||||||
|
}
|
||||||
|
//pixelDelta seems to be the same as angleDelta/8
|
||||||
|
var pixelDelta = 0
|
||||||
|
//The pixelDelta is a smaller number if both are provided, so pixelDelta can be 0 while angleDelta is still something. So we check the angleDelta
|
||||||
|
if (wheel.angleDelta.y) {
|
||||||
|
var wheelScrollLines = 3 //Default value of QApplication wheelScrollLines property
|
||||||
|
var pixelPerLine = 20 //Default value in Qt, originally comes from QTextEdit
|
||||||
|
var ticks = (wheel.angleDelta.y / 8) / 15.0 //Divide by 8 gives us pixels typically come in 15pixel steps.
|
||||||
|
pixelDelta = ticks * pixelPerLine * wheelScrollLines
|
||||||
|
} else {
|
||||||
|
pixelDelta = wheel.pixelDelta.y
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pixelDelta) {
|
||||||
|
return flickableItem.contentY;
|
||||||
|
}
|
||||||
|
|
||||||
|
var minYExtent = flickableItem.originY + flickableItem.topMargin;
|
||||||
|
var maxYExtent = (flickableItem.contentHeight + flickableItem.bottomMargin + flickableItem.originY) - flickableItem.height;
|
||||||
|
|
||||||
|
if (typeof(flickableItem.headerItem) !== "undefined" && flickableItem.headerItem) {
|
||||||
|
minYExtent += flickableItem.headerItem.height
|
||||||
|
}
|
||||||
|
|
||||||
|
//Avoid overscrolling
|
||||||
|
return Math.max(minYExtent, Math.min(maxYExtent, flickableItem.contentY - pixelDelta));
|
||||||
|
}
|
||||||
|
|
||||||
|
onWheel: {
|
||||||
|
var newPos = calculateNewPosition(flickable, wheel);
|
||||||
|
// console.warn("Delta: ", wheel.pixelDelta.y);
|
||||||
|
// console.warn("Old position: ", flickable.contentY);
|
||||||
|
// console.warn("New position: ", newPos);
|
||||||
|
|
||||||
|
// Show the scrollbars
|
||||||
|
flickable.flick(0, 0);
|
||||||
|
flickable.contentY = newPos;
|
||||||
|
cancelFlickStateTimer.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: cancelFlickStateTimer
|
||||||
|
//How long the scrollbar will remain visible
|
||||||
|
interval: 500
|
||||||
|
// Hide the scrollbars
|
||||||
|
onTriggered: flickable.cancelFlick();
|
||||||
|
}
|
||||||
|
}
|
|
@ -115,21 +115,11 @@ Page {
|
||||||
model: timelineManager.timeline
|
model: timelineManager.timeline
|
||||||
|
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
pixelAligned: true
|
|
||||||
|
|
||||||
MouseArea {
|
ScrollHelper {
|
||||||
anchors.fill: parent
|
flickable: parent
|
||||||
acceptedButtons: Qt.NoButton
|
anchors.fill: parent
|
||||||
propagateComposedEvents: true
|
}
|
||||||
z: -1
|
|
||||||
onWheel: {
|
|
||||||
if (wheel.angleDelta != 0) {
|
|
||||||
chat.contentY = chat.contentY - wheel.angleDelta.y
|
|
||||||
wheel.accepted = true
|
|
||||||
chat.returnToBounds()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Shortcut {
|
Shortcut {
|
||||||
sequence: StandardKey.MoveToPreviousPage
|
sequence: StandardKey.MoveToPreviousPage
|
||||||
|
@ -218,9 +208,10 @@ Page {
|
||||||
text: chat.model.formatDateSeparator(modelData.timestamp)
|
text: chat.model.formatDateSeparator(modelData.timestamp)
|
||||||
color: colors.brightText
|
color: colors.brightText
|
||||||
|
|
||||||
height: contentHeight * 1.2
|
height: fontMetrics.height * 1.4
|
||||||
width: contentWidth * 1.2
|
width: contentWidth * 1.2
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
radius: parent.height / 2
|
radius: parent.height / 2
|
||||||
color: colors.dark
|
color: colors.dark
|
||||||
|
@ -228,7 +219,7 @@ Page {
|
||||||
}
|
}
|
||||||
Row {
|
Row {
|
||||||
height: userName.height
|
height: userName.height
|
||||||
spacing: 4
|
spacing: 4
|
||||||
Avatar {
|
Avatar {
|
||||||
width: avatarSize
|
width: avatarSize
|
||||||
height: avatarSize
|
height: avatarSize
|
||||||
|
@ -335,4 +326,8 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FontMetrics {
|
||||||
|
id: fontMetrics
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,9 @@ Label {
|
||||||
color: colors.brightText
|
color: colors.brightText
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
||||||
height: contentHeight * 1.2
|
height: fontMetrics.height * 1.4
|
||||||
width: contentWidth * 1.2
|
width: contentWidth * 1.2
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
radius: parent.height / 2
|
radius: parent.height / 2
|
||||||
color: colors.dark
|
color: colors.dark
|
||||||
|
|
|
@ -118,6 +118,7 @@
|
||||||
<file>qml/StatusIndicator.qml</file>
|
<file>qml/StatusIndicator.qml</file>
|
||||||
<file>qml/EncryptionIndicator.qml</file>
|
<file>qml/EncryptionIndicator.qml</file>
|
||||||
<file>qml/TimelineRow.qml</file>
|
<file>qml/TimelineRow.qml</file>
|
||||||
|
<file>qml/ScrollHelper.qml</file>
|
||||||
<file>qml/delegates/MessageDelegate.qml</file>
|
<file>qml/delegates/MessageDelegate.qml</file>
|
||||||
<file>qml/delegates/TextMessage.qml</file>
|
<file>qml/delegates/TextMessage.qml</file>
|
||||||
<file>qml/delegates/NoticeMessage.qml</file>
|
<file>qml/delegates/NoticeMessage.qml</file>
|
||||||
|
|
Loading…
Reference in a new issue