**animations**
oops
This commit is contained in:
@@ -17,6 +17,10 @@ Scope {
|
||||
screen: modelData
|
||||
property var root: Quickshell.shellDir
|
||||
|
||||
NotificationCenter {
|
||||
bar: bar
|
||||
}
|
||||
|
||||
Process {
|
||||
id: ncProcess
|
||||
command: ["sh", "-c", `qs -p ${bar.root}/shell.qml ipc call root showCenter`]
|
||||
|
||||
@@ -237,13 +237,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notificationPopup
|
||||
TrackedNotification {
|
||||
centerX: NotificationCenter.posX
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notifComp
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property alias centerX: notifCenterSpacing.centerX
|
||||
|
||||
JsonAdapter {
|
||||
id: notifCenterSpacing
|
||||
|
||||
property int centerX
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls.FluentWinUI3
|
||||
import QtQuick.Effects
|
||||
@@ -20,9 +21,11 @@ PanelWindow {
|
||||
left: true
|
||||
bottom: true
|
||||
}
|
||||
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
required property PanelWindow bar
|
||||
property bool centerShown: false
|
||||
property alias posX: backgroundRect.x
|
||||
property alias doNotDisturb: dndSwitch.checked
|
||||
visible: false
|
||||
|
||||
mask: Region { item: backgroundRect }
|
||||
@@ -61,10 +64,10 @@ PanelWindow {
|
||||
id: showAnimation
|
||||
target: backgroundRect
|
||||
property: "x"
|
||||
from: Screen.width
|
||||
to: Screen.width - backgroundRect.implicitWidth - 10
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
to: root.bar.screen.width - backgroundRect.implicitWidth - 10
|
||||
from: root.bar.screen.width
|
||||
duration: MaterialEasing.expressiveEffectsTime
|
||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||
onStopped: {
|
||||
focusGrab.active = true;
|
||||
}
|
||||
@@ -74,10 +77,10 @@ PanelWindow {
|
||||
id: closeAnimation
|
||||
target: backgroundRect
|
||||
property: "x"
|
||||
from: Screen.width - backgroundRect.implicitWidth - 10
|
||||
to: Screen.width
|
||||
duration: 300
|
||||
easing.type: Easing.OutCubic
|
||||
from: root.bar.screen.width - backgroundRect.implicitWidth - 10
|
||||
to: root.bar.screen.width
|
||||
duration: MaterialEasing.expressiveEffectsTime
|
||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||
}
|
||||
|
||||
HyprlandFocusGrab {
|
||||
@@ -89,10 +92,16 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
TrackedNotification {
|
||||
centerShown: root.centerShown
|
||||
bar: root.bar
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: backgroundRect
|
||||
y: 10
|
||||
x: Screen.width
|
||||
z: 1
|
||||
implicitWidth: 400
|
||||
implicitHeight: root.height - 20
|
||||
color: Config.baseBgColor
|
||||
@@ -114,6 +123,9 @@ PanelWindow {
|
||||
focus: false
|
||||
activeFocusOnTab: false
|
||||
focusPolicy: Qt.NoFocus
|
||||
onCheckedChanged: {
|
||||
NotifServer.dnd = dndSwitch.checked;
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
@@ -176,7 +188,7 @@ PanelWindow {
|
||||
|
||||
move: Transition {
|
||||
NumberAnimation {
|
||||
properties: "y,x";
|
||||
properties: "x";
|
||||
duration: 200;
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
@@ -215,31 +227,45 @@ PanelWindow {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
// add: Transition {
|
||||
// id: addTrans
|
||||
// SequentialAnimation {
|
||||
// PauseAnimation {
|
||||
// duration: ( addTrans.ViewTransition.index - addTrans.ViewTransition.targetIndexes[ 0 ]) * 50
|
||||
// }
|
||||
// ParallelAnimation {
|
||||
// NumberAnimation {
|
||||
// properties: "y";
|
||||
// from: addTrans.ViewTransition.destination.y - (height / 2);
|
||||
// to: addTrans.ViewTransition.destination.y;
|
||||
// duration: 100;
|
||||
// easing.type: Easing.OutCubic
|
||||
// }
|
||||
// NumberAnimation {
|
||||
// properties: "opacity";
|
||||
// from: 0;
|
||||
// to: 1;
|
||||
// duration: 100;
|
||||
// easing.type: Easing.OutCubic
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
Behavior on y {
|
||||
Anim {
|
||||
duration: MaterialEasing.expressiveEffectsTime
|
||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||
}
|
||||
}
|
||||
|
||||
add: Transition {
|
||||
id: addTrans
|
||||
SequentialAnimation {
|
||||
PauseAnimation {
|
||||
duration: ( addTrans.ViewTransition.index - addTrans.ViewTransition.targetIndexes[ 0 ]) * 50
|
||||
}
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
properties: "y";
|
||||
from: addTrans.ViewTransition.destination.y - (height / 2);
|
||||
to: addTrans.ViewTransition.destination.y;
|
||||
duration: 100;
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "opacity";
|
||||
from: 0;
|
||||
to: 1;
|
||||
duration: 100;
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "scale";
|
||||
from: 0.7;
|
||||
to: 1.0;
|
||||
duration: 100
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
move: Transition {
|
||||
id: moveTrans
|
||||
NumberAnimation {
|
||||
@@ -281,79 +307,35 @@ PanelWindow {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
groupColumn.isExpanded = false;
|
||||
groupColumn.shouldShow = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
Repeater {
|
||||
id: groupListView
|
||||
model: ScriptModel {
|
||||
id: groupModel
|
||||
values: groupColumn.isExpanded ? groupColumn.notifications : groupColumn.notifications.slice( 0, 1 )
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
spacing: 10
|
||||
height: contentHeight
|
||||
contentHeight: childrenRect.height
|
||||
clip: false
|
||||
|
||||
pixelAligned: true
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
displayMarginBeginning: 0
|
||||
displayMarginEnd: 5000
|
||||
|
||||
Behavior on height {
|
||||
Anim {
|
||||
duration: 20;
|
||||
}
|
||||
}
|
||||
|
||||
add: Transition {
|
||||
id: add
|
||||
NumberAnimation {
|
||||
properties: "y,opacity";
|
||||
duration: 100 * ( add.ViewTransition.targetIndexes.length / ( add.ViewTransition.targetIndexes.length < 3 ? 1 : 3 ));
|
||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
NumberAnimation {
|
||||
properties: "opacity";
|
||||
from: 1;
|
||||
to: 0;
|
||||
duration: 300;
|
||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
properties: "y";
|
||||
duration: 200;
|
||||
easing.bezierCurve: MaterialEasing.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Rectangle {
|
||||
Rectangle {
|
||||
id: groupHeader
|
||||
required property int index
|
||||
required property NotifServer.Notif modelData
|
||||
property alias notifHeight: groupHeader.height
|
||||
|
||||
property bool previewHidden: !groupColumn.isExpanded && index > 0
|
||||
property bool previewHidden: groupColumn.shouldShow && index > 0
|
||||
|
||||
width: groupListView.width
|
||||
width: parent.width
|
||||
height: contentColumn.height + 20
|
||||
color: Config.baseBgColor
|
||||
border.color: "#555555"
|
||||
border.width: 1
|
||||
radius: 8
|
||||
opacity: 1
|
||||
scale: 1.0
|
||||
opacity: previewHidden ? 0 : 1.0
|
||||
scale: previewHidden ? 0.7 : 1.0
|
||||
|
||||
Component.onCompleted: modelData.lock(this);
|
||||
Component.onDestruction: modelData.unlock(this);
|
||||
@@ -366,11 +348,35 @@ PanelWindow {
|
||||
groupHeader.modelData.actions[0].invoke();
|
||||
}
|
||||
} else {
|
||||
groupColumn.shouldShow = true;
|
||||
groupColumn.isExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: collapseAnim
|
||||
running: !groupColumn.shouldShow && index > 0
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
running: groupHeader.modelData.closed
|
||||
onFinished: groupHeader.modelData.unlock(groupHeader)
|
||||
|
||||
+162
-125
@@ -1,167 +1,204 @@
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Hyprland
|
||||
import QtQuick.Layouts
|
||||
import QtQuick
|
||||
import Quickshell.Services.Notifications
|
||||
import qs.Config
|
||||
import qs.Daemons
|
||||
import qs.Helpers
|
||||
|
||||
PanelWindow {
|
||||
id: root
|
||||
color: "transparent"
|
||||
screen: root.bar.screen
|
||||
anchors {
|
||||
top: true
|
||||
right: true
|
||||
left: true
|
||||
bottom: true
|
||||
}
|
||||
mask: Region { item: backgroundRect }
|
||||
mask: Region { regions: root.notifRegions }
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.layer: WlrLayer.Overlay
|
||||
required property Notification notif
|
||||
required property int centerX
|
||||
required property list<int> notifIndex
|
||||
property int index: notifIndex.indexOf(notif.id)
|
||||
property alias y: backgroundRect.y
|
||||
property alias notifHeight: backgroundRect.implicitHeight
|
||||
signal notifDestroy()
|
||||
property list<Region> notifRegions: []
|
||||
required property bool centerShown
|
||||
required property PanelWindow bar
|
||||
visible: Hyprland.monitorFor(screen).focused
|
||||
|
||||
Component.onCompleted: {
|
||||
openAnim.start();
|
||||
console.log(root.index);
|
||||
console.log(NotifServer.list.filter( n => n.popup ).length + " notification popups loaded.");
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timeout
|
||||
interval: 5000
|
||||
onTriggered: {
|
||||
closeAnim.start();
|
||||
ListView {
|
||||
id: notifListView
|
||||
model: ScriptModel {
|
||||
values: NotifServer.list.filter( n => n.popup )
|
||||
}
|
||||
}
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
x: root.centerShown ? root.bar.width - width - 420 : root.bar.width - width - 20
|
||||
z: 0
|
||||
anchors.topMargin: 54
|
||||
width: 400
|
||||
spacing: 10
|
||||
|
||||
NumberAnimation {
|
||||
id: openAnim
|
||||
target: backgroundRect
|
||||
property: "x"
|
||||
from: root.centerX
|
||||
to: root.centerX - backgroundRect.implicitWidth - 20
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuad
|
||||
onStopped: { timeout.start(); }
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: closeAnim
|
||||
target: backgroundRect
|
||||
property: "x"
|
||||
from: root.centerX - backgroundRect.implicitWidth - 20
|
||||
to: root.centerX
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuad
|
||||
onStopped: {
|
||||
root.destroy();
|
||||
root.notifDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: backgroundRect
|
||||
implicitWidth: 400
|
||||
implicitHeight: contentLayout.childrenRect.height + 16
|
||||
x: root.centerX - implicitWidth - 20
|
||||
y: !root.notifList[ root.index - 1 ] ? 34 + 20 : root.notifList[ root.index - 1 ].y + root.notifList[ root.index - 1 ].notifHeight + 10
|
||||
color: Config.baseBgColor
|
||||
border.color: "#555555"
|
||||
radius: 8
|
||||
|
||||
Behavior on y {
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
duration: MaterialEasing.expressiveEffectsTime
|
||||
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||
}
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
duration: 100
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: contentLayout
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: 10
|
||||
spacing: 8
|
||||
RowLayout {
|
||||
spacing: 12
|
||||
IconImage {
|
||||
source: root.notif.image
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignLeft
|
||||
visible: root.notif.image !== ""
|
||||
remove: Transition {
|
||||
id: hideTransition
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 1
|
||||
to: 0
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 0
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
|
||||
Text {
|
||||
text: root.notif.appName
|
||||
color: "white"
|
||||
font.bold: true
|
||||
font.pointSize: 14
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.notif.summary
|
||||
color: "white"
|
||||
font.pointSize: 12
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
property: "x"
|
||||
to: hideTransition.ViewTransition.destination.x + 200
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: root.notif.body
|
||||
color: "#dddddd"
|
||||
font.pointSize: 14
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.WordWrap
|
||||
maximumLineCount: 4
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
add: Transition {
|
||||
id: showTransition
|
||||
ParallelAnimation {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0
|
||||
to: 1
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "✕"
|
||||
color: closeArea.containsMouse ? "white" : "#888888"
|
||||
font.pointSize: 12
|
||||
NumberAnimation {
|
||||
property: "x"
|
||||
from: showTransition.ViewTransition.destination.x + 200
|
||||
to: showTransition.ViewTransition.destination.x
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component NotifRegion: Region { }
|
||||
|
||||
Component {
|
||||
id: notifRegion
|
||||
NotifRegion {}
|
||||
}
|
||||
|
||||
delegate: Rectangle {
|
||||
id: backgroundRect
|
||||
required property NotifServer.Notif modelData
|
||||
implicitWidth: 400
|
||||
implicitHeight: contentLayout.childrenRect.height + 16
|
||||
color: Config.baseBgColor
|
||||
border.color: "#555555"
|
||||
radius: 8
|
||||
|
||||
Component.onCompleted: {
|
||||
root.notifRegions.push( notifRegion.createObject(root, { item: backgroundRect }));
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
root.notif.dismiss();
|
||||
root.visible = false;
|
||||
Column {
|
||||
id: contentLayout
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: 10
|
||||
spacing: 8
|
||||
RowLayout {
|
||||
spacing: 12
|
||||
IconImage {
|
||||
source: backgroundRect.modelData.image
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignLeft
|
||||
visible: backgroundRect.modelData.image !== ""
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 0
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
|
||||
Text {
|
||||
text: backgroundRect.modelData.appName
|
||||
color: "white"
|
||||
font.bold: true
|
||||
font.pointSize: 14
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: backgroundRect.modelData.summary
|
||||
color: "white"
|
||||
font.pointSize: 12
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: backgroundRect.modelData.body
|
||||
color: "#dddddd"
|
||||
font.pointSize: 14
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.WordWrap
|
||||
maximumLineCount: 4
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "✕"
|
||||
color: closeArea.containsMouse ? "white" : "#888888"
|
||||
font.pointSize: 12
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
backgroundRect.modelData.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user