Files
z-bar-qt/Modules/Sidebar/NotifDock.qml
T
zach 11e7aac195
C++ / fmt (pull_request) Failing after 5s
C++ / build (pull_request) Failing after 11s
C++ / clang-tidy (pull_request) Failing after 10s
JS/TS / fmt (pull_request) Successful in 12s
JS/TS / lint (pull_request) Successful in 10s
Python / static (pull_request) Failing after 27s
Rust / build (pull_request) Successful in 54s
Python / verify (pull_request) Failing after 1m26s
Rust / fmt (pull_request) Successful in 46s
Rust / clippy (pull_request) Successful in 1m6s
feat: better notification storage and image caching + blobs
2026-11-02 19:00:43 +01:00

195 lines
3.7 KiB
QML

pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import ZShell.Components
import ZShell.Config
import qs.Components
import qs.Daemons
import qs.Modules
import qs.Services
Item {
id: root
required property ScreenState screenState
readonly property int notifCount: NotifServer.notClosed.length
anchors.fill: parent
anchors.margins: Tokens.padding.small
Component.onCompleted: NotifServer.list.forEach(n => n.dismissPopup())
Item {
id: title
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Tokens.padding.extraSmall
implicitHeight: Math.max(count.implicitHeight, titleText.implicitHeight)
CustomText {
id: count
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: root.notifCount > 0 ? 0 : -width - titleText.anchors.leftMargin
opacity: root.notifCount > 0 ? 1 : 0
text: root.notifCount
color: Colors.palette.m3outline
font: Tokens.font.label.large
Behavior on anchors.leftMargin {
Anim {}
}
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
CustomText {
id: titleText
anchors.verticalCenter: parent.verticalCenter
anchors.left: count.right
anchors.right: parent.right
anchors.leftMargin: Tokens.spacing.extraSmall
text: root.notifCount > 0 ? qsTr("notification%1").arg(root.notifCount === 1 ? "" : "s") : qsTr("Notifications")
color: Colors.palette.m3outline
font: Tokens.font.label.large
elide: Text.ElideRight
}
}
Item {
id: clipRect
anchors.left: parent.left
anchors.right: parent.right
anchors.top: title.bottom
anchors.bottom: parent.bottom
anchors.topMargin: Tokens.spacing.medium
clip: true
Loader {
asynchronous: true
anchors.centerIn: parent
active: opacity > 0
opacity: root.notifCount > 0 ? 0 : 1
sourceComponent: SnapLayout {
orientation: Qt.Vertical
spacing: Tokens.spacing.extraLarge
CustomText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("No notifications")
color: Colors.palette.m3outlineVariant
font: Tokens.font.headline.builders.small.width(90).build()
}
}
Behavior on opacity {
Anim {
type: Anim.StandardExtraLarge
}
}
}
KineticFlickable {
id: view
anchors.fill: parent
flickableDirection: Flickable.VerticalFlick
contentWidth: width
contentHeight: notifList.implicitHeight
CustomScrollBar.vertical: CustomScrollBar {
flickable: view
}
NotifDockList {
id: notifList
screenState: root.screenState
container: view
}
}
}
Timer {
id: clearTimer
repeat: true
triggeredOnStart: true
interval: Math.max(15, Math.min(80, 69.8 - 12.3 * Math.log(NotifServer.notClosed.length)))
onTriggered: {
const group = NotifServer.groups[0];
if (!group) {
stop();
return;
}
let cleared = 0;
for (const n of [...group.activeNotifs]) {
n.dismiss();
cleared++;
if (cleared > 30) {
interval = 5;
return;
}
}
}
}
Loader {
asynchronous: true
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: Tokens.padding.medium
scale: root.notifCount > 0 ? 1 : 0.5
opacity: root.notifCount > 0 ? 1 : 0
active: opacity > 0
sourceComponent: IconButton {
id: clearBtn
icon: "clear_all"
font: Tokens.font.icon.large
isRound: true
onClicked: clearTimer.start()
Elevation {
anchors.fill: parent
radius: parent.radius
z: -1
level: clearBtn.stateLayer.containsMouse ? 4 : 3
}
}
Behavior on scale {
Anim {
type: Anim.FastSpatial
}
}
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
}