Files

172 lines
3.6 KiB
QML

pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Widgets
import QtQuick
import qs.Components
import ZShell.Config
import qs.Daemons
import qs.Helpers
Item {
id: root
readonly property int padding: Tokens.padding.smaller
required property Item panels
required property PersistentProperties visibilities
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.top: parent.top
implicitHeight: {
const count = list.count;
if (count === 0)
return 0;
let height = (count - 1) * Tokens.spacing.small;
for (let i = 0; i < count; i++)
height += (list.itemAtIndex(i) as NotifWrapper)?.nonAnimHeight ?? 0;
if (panels.popouts.hasCurrent && (panels.popouts.currentCenter + (panels.popouts.current?.width / 2)) > panels.notifications.x || visibilities.dashboard)
return 0;
if (visibilities.osd) {
const h = panels.osd.y - Tokens.spacing.small * 2 - padding * 2;
if (height > h)
height = h;
}
if (visibilities.session) {
const h = panels.session.y - Tokens.spacing.small * 2 - padding * 2;
if (height > h)
height = h;
}
return Math.min(((QsWindow.window as QsWindow)?.screen?.height ?? 0) - 1 * 2, height + padding * 2);
}
implicitWidth: Config.notifs.sizes.width + padding * 2
Behavior on implicitHeight {
Anim {
}
}
ClippingWrapperRectangle {
anchors.fill: parent
anchors.margins: root.padding
color: "transparent"
radius: Tokens.rounding.normal - root.padding
CustomListView {
id: list
anchors.fill: parent
cacheBuffer: (QsWindow.window as QsWindow)?.screen.height ?? 0
orientation: Qt.Vertical
spacing: 0
delegate: NotifWrapper {
}
displaced: Transition {
Anim {
property: "y"
}
}
model: ScriptModel {
values: {
const popups = NotifServer.popups.filter(n => !n.closed);
if (!Config.notifs.showInFullscreen) {
if (Hypr.monitorFor(root.panels.screen).activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1) ?? false)
return [];
}
return popups;
}
}
move: Transition {
Anim {
property: "y"
}
}
}
}
component Anim: NumberAnimation {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
component NotifWrapper: Item {
id: wrapper
property int idx
required property int index
required property NotifServer.Notif modelData
readonly property alias nonAnimHeight: notif.nonAnimHeight
implicitHeight: notif.implicitHeight + (idx === 0 ? 0 : Tokens.spacing.small)
implicitWidth: notif.implicitWidth
ListView.onRemove: removeAnim.start()
onIndexChanged: {
if (index !== -1)
idx = index;
}
SequentialAnimation {
id: removeAnim
PropertyAction {
property: "ListView.delayRemove"
target: wrapper
value: true
}
PropertyAction {
property: "enabled"
target: wrapper
value: false
}
PropertyAction {
property: "implicitHeight"
target: wrapper
value: 0
}
PropertyAction {
property: "z"
target: wrapper
value: 1
}
Anim {
property: "x"
target: notif
to: (notif.x >= 0 ? Config.notifs.sizes.width : -Config.notifs.sizes.width) * 2
}
PropertyAction {
property: "ListView.delayRemove"
target: wrapper
value: false
}
}
ClippingRectangle {
anchors.top: parent.top
anchors.topMargin: wrapper.idx === 0 ? 0 : 8
color: "transparent"
implicitHeight: notif.implicitHeight
implicitWidth: notif.implicitWidth
radius: Tokens.rounding.small
Notification {
id: notif
implicitWidth: root.implicitWidth - root.padding * 2
modelData: wrapper.modelData
}
}
}
}