From 3462bcc46ecf74f576ea4397f16492c16bd75b10 Mon Sep 17 00:00:00 2001 From: Nippy Date: Fri, 8 May 2026 19:50:49 +0200 Subject: raveos update --- .../theme-data/dms/Widgets/DankListView.qml | 213 +++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 raveos-hyprland-theme/theme-data/dms/Widgets/DankListView.qml (limited to 'raveos-hyprland-theme/theme-data/dms/Widgets/DankListView.qml') diff --git a/raveos-hyprland-theme/theme-data/dms/Widgets/DankListView.qml b/raveos-hyprland-theme/theme-data/dms/Widgets/DankListView.qml new file mode 100644 index 0000000..41bdc9b --- /dev/null +++ b/raveos-hyprland-theme/theme-data/dms/Widgets/DankListView.qml @@ -0,0 +1,213 @@ +import QtQuick +import QtQuick.Controls +import qs.Common +import qs.Widgets +import "ScrollConstants.js" as Scroll + +ListView { + id: listView + + property real scrollBarTopMargin: 0 + property real mouseWheelSpeed: Scroll.mouseWheelSpeed + property real savedY: 0 + property bool justChanged: false + property bool isUserScrolling: false + property real momentumVelocity: 0 + property bool isMomentumActive: false + property real friction: Scroll.friction + + flickDeceleration: Scroll.flickDeceleration + maximumFlickVelocity: Scroll.maximumFlickVelocity + boundsBehavior: Flickable.StopAtBounds + boundsMovement: Flickable.FollowBoundsBehavior + pressDelay: 0 + flickableDirection: Flickable.VerticalFlick + + add: ListViewTransitions.add + remove: ListViewTransitions.remove + displaced: ListViewTransitions.displaced + move: ListViewTransitions.move + + onMovementStarted: { + isUserScrolling = true; + vbar._scrollBarActive = true; + vbar.hideTimer.stop(); + } + onMovementEnded: { + isUserScrolling = false; + vbar.hideTimer.restart(); + } + + onContentYChanged: { + if (!justChanged && isUserScrolling) { + savedY = contentY; + } + justChanged = false; + } + + onModelChanged: { + justChanged = true; + contentY = savedY; + } + + WheelHandler { + id: wheelHandler + property real touchpadSpeed: Scroll.touchpadSpeed + property real lastWheelTime: 0 + property real momentum: 0 + property var velocitySamples: [] + property bool sessionUsedMouseWheel: false + + function startMomentum() { + isMomentumActive = true; + momentumAnim.running = true; + } + + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + + onWheel: event => { + isUserScrolling = true; + vbar._scrollBarActive = true; + vbar.hideTimer.restart(); + + const currentTime = Date.now(); + const timeDelta = currentTime - lastWheelTime; + lastWheelTime = currentTime; + + const hasPixel = event.pixelDelta && event.pixelDelta.y !== 0; + const deltaY = event.angleDelta.y; + const isTraditionalMouse = !hasPixel && Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0; + const isHighDpiMouse = !hasPixel && !isTraditionalMouse && deltaY !== 0; + const isTouchpad = hasPixel; + + if (isTraditionalMouse) { + sessionUsedMouseWheel = true; + momentumAnim.running = false; + isMomentumActive = false; + velocitySamples = []; + momentum = 0; + momentumVelocity = 0; + + const lines = Math.round(Math.abs(deltaY) / 120); + const scrollAmount = (deltaY > 0 ? -lines : lines) * mouseWheelSpeed; + let newY = listView.contentY + scrollAmount; + const maxY = Math.max(0, listView.contentHeight - listView.height + listView.originY); + newY = Math.max(listView.originY, Math.min(maxY, newY)); + + if (listView.flicking) { + listView.cancelFlick(); + } + + listView.contentY = newY; + savedY = newY; + } else if (isHighDpiMouse) { + sessionUsedMouseWheel = true; + momentumAnim.running = false; + isMomentumActive = false; + velocitySamples = []; + momentum = 0; + momentumVelocity = 0; + + let delta = deltaY / 8 * touchpadSpeed; + let newY = listView.contentY - delta; + const maxY = Math.max(0, listView.contentHeight - listView.height + listView.originY); + newY = Math.max(listView.originY, Math.min(maxY, newY)); + + if (listView.flicking) { + listView.cancelFlick(); + } + + listView.contentY = newY; + savedY = newY; + } else if (isTouchpad) { + sessionUsedMouseWheel = false; + momentumAnim.running = false; + isMomentumActive = false; + + let delta = event.pixelDelta.y * touchpadSpeed; + + velocitySamples.push({ + "delta": delta, + "time": currentTime + }); + velocitySamples = velocitySamples.filter(s => currentTime - s.time < Scroll.velocitySampleWindowMs); + + if (velocitySamples.length > 1) { + const totalDelta = velocitySamples.reduce((sum, s) => sum + s.delta, 0); + const timeSpan = currentTime - velocitySamples[0].time; + if (timeSpan > 0) { + momentumVelocity = Math.max(-Scroll.maxMomentumVelocity, Math.min(Scroll.maxMomentumVelocity, totalDelta / timeSpan * 1000)); + } + } + + if (timeDelta < Scroll.momentumTimeThreshold) { + momentum = momentum * Scroll.momentumRetention + delta * Scroll.momentumDeltaFactor; + delta += momentum; + } else { + momentum = 0; + } + + let newY = listView.contentY - delta; + const maxY = Math.max(0, listView.contentHeight - listView.height + listView.originY); + newY = Math.max(listView.originY, Math.min(maxY, newY)); + + if (listView.flicking) { + listView.cancelFlick(); + } + + listView.contentY = newY; + savedY = newY; + } + + event.accepted = true; + } + + onActiveChanged: { + if (!active) { + isUserScrolling = false; + if (!sessionUsedMouseWheel && Math.abs(momentumVelocity) >= Scroll.minMomentumVelocity) { + startMomentum(); + } else { + velocitySamples = []; + momentumVelocity = 0; + } + } + } + } + + FrameAnimation { + id: momentumAnim + running: false + + onTriggered: { + const dt = frameTime; + const newY = contentY - momentumVelocity * dt; + const maxY = Math.max(0, contentHeight - height + originY); + const minY = originY; + + if (newY < minY || newY > maxY) { + contentY = newY < minY ? minY : maxY; + savedY = contentY; + running = false; + isMomentumActive = false; + momentumVelocity = 0; + return; + } + + contentY = newY; + savedY = newY; + momentumVelocity *= Math.pow(friction, dt / 0.016); + + if (Math.abs(momentumVelocity) < Scroll.momentumStopThreshold) { + running = false; + isMomentumActive = false; + momentumVelocity = 0; + } + } + } + + ScrollBar.vertical: DankScrollbar { + id: vbar + topPadding: listView.scrollBarTopMargin + } +} -- cgit v1.3