This commit is contained in:
2026-02-09 00:09:29 -08:00
parent add0b3d66f
commit 925b01939c
7 changed files with 270 additions and 125 deletions

View File

@@ -13,9 +13,7 @@ PanelWindow {
id: launcher id: launcher
function close() { function close() {
visible = false exitAnim.start();
list.visible = false
searchInput.text = ""
} }
function open() { function open() {
visible = true visible = true
@@ -358,6 +356,45 @@ PanelWindow {
width: 24 width: 24
height: 24 height: 24
} }
property var progress
}
transform: Translate {
NumberAnimation on x {
running: launcher.visible
duration: 200
from: launcher.implicitWidth/6
to: 0
easing.type: Easing.OutQuart
}
NumberAnimation on x {
running: exitAnim.running
duration: 200
from: 0
to: launcher.implicitWidth/6
easing.type: Easing.InCubic
}
}
NumberAnimation on opacity {
running: launcher.visible
from: 0
to: 1
duration: 150
}
SequentialAnimation on opacity {
id: exitAnim
running: false
PauseAnimation { duration: 50 }
NumberAnimation {
from: 1
to: 0
duration: 150
}
onFinished: {
launcher.visible = false
list.visible = false
searchInput.text = ""
}
} }
} }
} }

View File

@@ -2,6 +2,7 @@ import Quickshell
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import "NotificationBox.qml"
PanelWindow { PanelWindow {
id: root id: root
@@ -11,7 +12,7 @@ PanelWindow {
bottom: true bottom: true
} }
visible: false visible: false
exclusiveZone: 1 exclusionMode: ExclusionMode.Normal
implicitWidth: 500 implicitWidth: 500
color: "transparent" color: "transparent"
@@ -58,7 +59,6 @@ PanelWindow {
anchors { anchors {
right: parent.right right: parent.right
top: parent.top top: parent.top
bottom: parent.bottom
topMargin: 14 topMargin: 14
rightMargin: 16 rightMargin: 16
} }
@@ -91,69 +91,49 @@ PanelWindow {
fill: parent fill: parent
topMargin: 48 topMargin: 48
} }
model: root.tracked
spacing: 10 spacing: 10
add: Transition { NumberAnimation {
property: "translateX"
from: root.width
to: 0
duration: 300
easing.type: Easing.OutBack
easing.overshoot: 0.7
}}
remove: Transition { NumberAnimation {
property: "translateX"
from: 0
to: root.width
duration: 150
easing.type: Easing.InQuint
}}
displaced: Transition { NumberAnimation {
property: "y"
duration: 300
easing.type: Easing.InOutCubic
}}
model: root.tracked
delegate: Button { delegate: Button {
anchors { anchors {
left: parent.left left: parent.left
right: parent.right right: parent.right
margins: 12
} }
height: notifContent.childrenRect.height + 32 height: notifBox.height
Image { background: NotificationBox {
id: notifIcon id: notifBox
anchors { notification: modelData
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 12
}
width: 40
height: 40
source: Quickshell.iconPath(modelData.appIcon, true)
}
Column {
id: notifContent
anchors { anchors {
left: parent.left left: parent.left
right: parent.right right: parent.right
top: parent.top leftMargin: 12
topMargin: 16 rightMargin: 12
leftMargin: 16 + (notifIcon.source == "" ? 0 : 44)
rightMargin: 16
} }
spacing: 6
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 16
text: modelData.summary
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
}
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 12
text: modelData.body
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 4
}
}
background: Rectangle {
color: "#333"
radius: 12
} }
onClicked: modelData.tracked = false onClicked: modelData.tracked = false
property real translateX: 0
transform: Translate { x: translateX }
} }
} }
transform: Translate { transform: Translate {

View File

@@ -2,6 +2,7 @@ import Quickshell
import Quickshell.Services.Notifications import Quickshell.Services.Notifications
import QtQuick import QtQuick
import QtQuick.Effects import QtQuick.Effects
import "./NotificationBox.qml"
PanelWindow { PanelWindow {
id: root id: root
@@ -20,10 +21,8 @@ PanelWindow {
Component { Component {
id: notifPopup id: notifPopup
Rectangle { NotificationBox {
id: notifRect id: notifBox
required property var modelData
y: { y: {
let res = 0; let res = 0;
for (let i = 0; notifsList.children[i] && notifsList.children[i] != this; i++) { for (let i = 0; notifsList.children[i] && notifsList.children[i] != this; i++) {
@@ -35,67 +34,12 @@ PanelWindow {
duration: 300 duration: 300
easing.type: Easing.InOutCubic easing.type: Easing.InOutCubic
}} }}
property bool exiting: false
width: parent?.width ?? 0
height: notifContent.childrenRect.height + 32
radius: 20
color: "#181818"
RectangularShadow { RectangularShadow {
z: -1 z: -1
anchors.fill: parent anchors.fill: parent
blur: 12 blur: 12
radius: parent.radius radius: parent.radius
} }
Image {
id: notifIcon
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 12
}
width: 40
height: 40
source: Quickshell.iconPath(modelData.appIcon, true)
}
Column {
id: notifContent
anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: 16
leftMargin: 16 + (notifIcon.source == "" ? 0 : 44)
rightMargin: 16
}
spacing: 6
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 16
text: modelData.summary
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
}
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 12
text: modelData.body
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 4
}
}
NumberAnimation on x { NumberAnimation on x {
running: root.visible running: root.visible
from: root.width from: root.width
@@ -116,7 +60,7 @@ PanelWindow {
root.visible = false root.visible = false
root.implicitHeight = 200; root.implicitHeight = 200;
} }
notifRect.destroy(); notifBox.destroy();
} }
} }
Timer { Timer {
@@ -147,6 +91,6 @@ PanelWindow {
function notify(notif) { function notify(notif) {
if (notif.lastGeneration) return if (notif.lastGeneration) return
root.visible = true; root.visible = true;
notifPopup.createObject(notifsList, {modelData: notif}); notifPopup.createObject(notifsList, {notification: notif});
} }
} }

91
NotificationBox.qml Normal file
View File

@@ -0,0 +1,91 @@
import Quickshell
import Quickshell.Services.Notifications
import QtQuick
import QtQuick.Controls
import QtQuick.Effects
Rectangle {
id: notifRect
required property var notification
property bool exiting: false
width: parent?.width ?? 0
height: notifContent.childrenRect.height + 32
radius: 20
color: "#181818"
Image {
id: notifIcon
visible: false
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 12
}
width: 40
height: 40
source: notification?.image ?? source
layer.enabled: true
}
Rectangle {
id: iconMask
antialiasing: true
layer.enabled: true
visible: false
anchors.fill: notifIcon
layer.smooth: true
radius: 8
}
MultiEffect {
anchors.fill: notifIcon
source: notifIcon
maskEnabled: true
maskSource: iconMask
maskThresholdMin: 0.5
maskSpreadAtMin: 1
}
Column {
id: notifContent
anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: 16
leftMargin: 16 + (notifIcon.source == "" ? 0 : 44)
rightMargin: 16
}
spacing: 6
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 16
text: notification?.summary ?? text
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
}
Text {
anchors {
left: parent.left
right: parent.right
}
color: "white"
font.family: "Comfortaa"
font.pixelSize: 12
text: notification?.body ?? text
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 4
}
}
Timer {
running: notification?.expireTimeout > 0
interval: (notification?.expireTimeout > 0) ? notification?.expireTimeout : 0
onTriggered: notification.tracked = false
}
}

89
Wall.qml Normal file
View File

@@ -0,0 +1,89 @@
import Quickshell
import Quickshell.Io
import QtQuick
import QtQuick.Effects
Variants {
model: Quickshell.screens
PanelWindow {
anchors {
top: true
right: true
bottom: true
left: true
}
aboveWindows: false
property var modelData
screen: modelData
color: "#222222"
RectangularShadow {
anchors.fill: imageWrapper
transform: imageWrapper.transform
radius: roundMask.radius
blur: 30
spread: 10
color: "#000000"
}
Item {
id: imageWrapper
anchors.fill: parent
layer.enabled: true
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: {
const _source = path.text()
return _source.substring(0, _source.length - 1)
}
}
transform: [Scale {
origin {x: width/2; y: height/2}
xScale: 0.8
yScale: xScale
NumberAnimation on xScale {
id: scaleAnim
running: false
to: 1
duration: 800
easing.type: Easing.InOutCubic
}
}, Translate {
NumberAnimation on y {
from: 100
to: 0
duration: 500
easing.type: Easing.OutQuint
onFinished: scaleAnim.start()
}
}]
layer.effect: MultiEffect {
maskSource: roundMask
maskEnabled: true
}
NumberAnimation on opacity {
from: 0
to: 1
duration: 250
}
}
Rectangle {
id: roundMask
visible: false
antialiasing: true
anchors.fill: imageWrapper
radius: 40
layer.enabled: true
NumberAnimation on radius {
running: scaleAnim.running
to: 0
duration: 800
}
}
FileView {
id: path
path: Qt.resolvedUrl("wall.txt")
}
}
}

View File

@@ -6,13 +6,6 @@ import Quickshell.Services.Notifications
ShellRoot { ShellRoot {
id: root id: root
NotificationServer {
id: notificationServer
onNotification: (notif) => {
notif.tracked = true
notifPopup.notify(notif)
}
}
readonly property var font: { readonly property var font: {
family: "comfortaa" family: "comfortaa"
} }
@@ -27,8 +20,18 @@ ShellRoot {
Osu.IpcToggle { Osu.IpcToggle {
target: "notifications" target: "notifications"
item: Osu.NotifCenter { item: Osu.NotifCenter {
id: notifCenter
tracked: notificationServer.trackedNotifications tracked: notificationServer.trackedNotifications
} }
} }
Osu.Notifs { id: notifPopup } Osu.Wall {}
Osu.NotifPopup { id: notifPopup }
NotificationServer {
id: notificationServer
imageSupported: true
onNotification: (notif) => {
notif.tracked = true
if (!notifCenter.visible) notifPopup.notify(notif)
}
}
} }

1
wall.txt Normal file
View File

@@ -0,0 +1 @@
/home/spingus/Pictures/Wallpapers/osu-light-2.jpg