Files
z-bar-qt/Modules/Notifications/Sidebar/NotifDockList.qml
T
2026-04-12 19:41:10 +02:00

158 lines
3.8 KiB
QML

pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import ZShell.Components
import qs.Components
import qs.Config
import qs.Modules
import qs.Daemons
LazyListView {
id: root
required property Flickable container
required property Props props
required property PersistentProperties visibilities
anchors.left: parent?.left
anchors.right: parent?.right
asynchronous: true
cacheBuffer: 400
implicitHeight: contentHeight
readyDelay: 1
removeDuration: Appearance.anim.durations.normal
spacing: Appearance.spacing.small
useCustomViewport: true
viewport: Qt.rect(0, container.contentY, width, container.height)
delegate: Component {
MouseArea {
id: notif
readonly property bool closed: notifInner.notifCount === 0
required property int index
required property string modelData
property int startY
function closeAll(): void {
clearTimer.start();
}
LazyListView.preferredHeight: closed ? 0 : notifInner.nonAnimHeight
LazyListView.trackViewport: !notifInner.expanded && notifInner.nonAnimHeight < notifInner.implicitHeight
LazyListView.visibleHeight: notifInner.implicitHeight
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
cursorShape: pressed ? Qt.ClosedHandCursor : undefined
drag.axis: Drag.XAxis
drag.target: this
enabled: !closed
hoverEnabled: true
implicitHeight: notifInner.implicitHeight
opacity: LazyListView.removing || closed || LazyListView.adding ? 0 : 1
preventStealing: true
scale: LazyListView.removing || closed ? 0.6 : LazyListView.adding ? 0 : 1
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on x {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on y {
enabled: notif.LazyListView.ready
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
onPositionChanged: event => {
if (pressed) {
const diffY = event.y - startY;
if (Math.abs(diffY) > Config.notifs.expandThreshold)
notifInner.toggleExpand(diffY > 0);
}
}
onPressed: event => {
startY = event.y;
if (event.button === Qt.RightButton)
notifInner.toggleExpand(!notifInner.expanded);
else if (event.button === Qt.MiddleButton)
closeAll();
}
onReleased: event => {
if (Math.abs(x) < width * Config.notifs.clearThreshold)
x = 0;
else
closeAll();
}
Timer {
id: clearTimer
interval: 15
repeat: true
triggeredOnStart: true
onTriggered: {
const notifs = NotifServer.notClosed.filter(n => n.appName === notif.modelData);
if (notifs.length === 0) {
stop();
return;
}
for (const n of notifs.slice(0, 30))
n.close();
}
}
NotifGroup {
id: notifInner
container: root.container
modelData: notif.modelData
props: root.props
visibilities: root.visibilities
}
}
}
model: ScriptModel {
values: {
const map = new Map();
for (const n of NotifServer.notClosed)
map.set(n.appName, null);
for (const n of NotifServer.list)
map.set(n.appName, null);
return [...map.keys()];
}
}
onViewportAdjustNeeded: d => {
if (contentYAnim.running)
contentYAnim.complete();
contentYAnim.to = Math.max(0, container.contentY + d);
contentYAnim.start();
}
Anim {
id: contentYAnim
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "contentY"
target: root.container
}
}