Files
z-bar-qt/Modules/NotifGroupRepeater.qml
T
2025-11-23 23:34:24 +01:00

249 lines
8.4 KiB
QML

import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Config
import qs.Daemons
import qs.Helpers
Repeater {
id: groupListView
model: ScriptModel {
id: groupModel
values: groupColumn.isExpanded || groupColumn.shouldShow ? groupColumn.notifications : groupColumn.notifications.slice( 0, 1 )
}
Rectangle {
id: groupHeader
required property int index
required property NotifServer.Notif modelData
property alias notifHeight: groupHeader.height
property bool previewHidden: !groupColumn.shouldShow && index > 0
width: parent.width
height: contentColumn.height + 15
color: Config.useDynamicColors ? DynamicColors.tPalette.m3surfaceContainer : Config.baseBgColor
border.color: "#555555"
border.width: Config.useDynamicColors ? 0 : 1
radius: 8
opacity: previewHidden ? 0 : 1
scale: previewHidden ? 0.7 : 1.0
Component.onCompleted: {
modelData.lock(this);
}
Component.onDestruction: modelData.unlock(this);
MouseArea {
anchors.fill: parent
onClicked: {
if ( groupColumn.isExpanded || groupColumn.notifications.length === 1 ) {
if ( groupHeader.modelData.actions.length === 1 ) {
groupHeader.modelData.actions[0].invoke();
}
} else {
groupColumn.isExpanded = true;
}
}
}
ParallelAnimation {
id: collapseAnim
running: groupColumn.collapseAnimRunning
Anim {
target: groupHeader
property: "opacity"
duration: 100
from: 1
to: index > 0 ? 0 : 1.0
}
Anim {
target: groupHeader
property: "scale"
duration: 100
from: 1
to: index > 0 ? 0.7 : 1.0
}
onFinished: {
groupColumn.isExpanded = false;
groupColumn.shouldShow = false;
groupColumn.collapseAnimRunning = false;
}
}
ParallelAnimation {
running: groupHeader.modelData.closed
onFinished: groupHeader.modelData.unlock(groupHeader)
Anim {
target: groupHeader
property: "opacity"
to: 0
}
Anim {
target: groupHeader
property: "x"
to: groupHeader.x >= 0 ? groupHeader.width : -groupHeader.width
}
}
Behavior on opacity {
Anim {}
}
Behavior on scale {
Anim {}
}
Behavior on x {
Anim {
duration: MaterialEasing.expressiveDefaultSpatialTime
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
}
}
Behavior on y {
Anim {
duration: MaterialEasing.expressiveDefaultSpatialTime
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
}
}
Column {
id: contentColumn
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 10
anchors.rightMargin: 10
anchors.topMargin: 5
spacing: 10
RowLayout {
id: infoRow
width: parent.width
spacing: 10
property color textColor: Config.useDynamicColors ? DynamicColors.palette.m3secondaryFixed : "#FFFFFF"
IconImage {
source: groupHeader.modelData.image === "" ? Qt.resolvedUrl(groupHeader.modelData.appIcon) : Qt.resolvedUrl(groupHeader.modelData.image)
Layout.preferredWidth: 48
Layout.preferredHeight: 48
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.topMargin: 5
visible: source !== ""
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
TextRender {
text: groupHeader.modelData.summary
color: infoRow.textColor
font.bold: true
font.pointSize: 16
elide: Text.ElideRight
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
}
TextRender {
text: groupHeader.modelData.body
color: infoRow.textColor
font.pointSize: 12
elide: Text.ElideRight
textFormat: Text.MarkdownText
wrapMode: Text.WordWrap
maximumLineCount: 5
linkColor: Config.accentColor.accents.primaryAlt
onLinkActivated: link => {
Quickshell.execDetached(["app2unit", "-O", "--", link]);
}
Layout.fillWidth: true
Layout.fillHeight: true
}
}
TextRender {
text: groupHeader.modelData.timeStr
font.pointSize: 10
color: infoRow.textColor
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
}
}
RowLayout {
id: actionRow
property NotifServer.Notif notif: groupHeader.modelData
spacing: 2
visible: groupHeader.modelData.actions.length > 1 ? true : false
height: 30
width: parent.width
Repeater {
model: [ ...actionRow.notif.actions ]
Rectangle {
id: actionButton
Layout.fillWidth: true
Layout.preferredHeight: 30
required property var modelData
required property int index
property color btnColor: Config.useDynamicColors ? ( actionButton.index === 0 ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondary ) : Config.accentColor.accents.primary
property color textColor: Config.useDynamicColors ? ( actionButton.index === 0 ? DynamicColors.palette.m3onPrimaryFixed : DynamicColors.palette.m3onSecondaryFixed ) : "white"
color: buttonArea.containsMouse ? DynamicColors.layer(btnColor, 0) : btnColor
radius: 4
TextRender {
anchors.centerIn: parent
text: actionButton.modelData.text
color: actionButton.textColor
font.pointSize: 12
}
MouseArea {
id: buttonArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
console.log( groupHeader.modelData.actions );
actionButton.modelData.invoke();
}
}
}
}
}
}
Rectangle {
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 6
anchors.topMargin: 6
width: 18
height: 18
color: closeArea.containsMouse ? "#FF6077" : "transparent"
radius: 9
TextRender {
anchors.centerIn: parent
text: "✕"
color: closeArea.containsMouse ? "white" : "#888888"
font.pointSize: 12
}
MouseArea {
id: closeArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
groupColumn.isExpanded ? groupHeader.modelData.close() : groupColumn.closeAll();
}
}
}
}
}