Files
monoshell/Panes/NotificationCenter.qml

234 lines
8.9 KiB
QML

import QtQuick
import QtQuick.Shapes
import Quickshell
import Quickshell.Widgets
import Quickshell.Services.Mpris
import Quickshell.Services.Notifications
import "../Widgets" as Widgets
Item {
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
width: childrenRect.width + 12
height: childrenRect.height + 12
Row {
spacing: 6
x: 6
y: 6
Rectangle {
width: 400
height: 300
color: "#111"
radius: 10
Column {
anchors.centerIn: parent
spacing: 2
opacity: !notifServer.trackedNotifications.values.length
Behavior on opacity {NumberAnimation {duration: 150}}
Image {
anchors.horizontalCenter: parent.horizontalCenter
source: Quickshell.shellPath("assets/notif.svg")
width: 24
height: 24
sourceSize {width: width; height: height}
opacity: 0.5
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
color: "#888"
text: "No notifications"
}
}
ListView {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: anchors.leftMargin
clip: true
spacing: 4
add: Transition {NumberAnimation {
property: "opacity"
from: 0
to: 1
duration: 150
}}
remove: Transition {NumberAnimation {
property: "opacity"
from: 1
to: 0
duration: 150
}}
displaced: Transition {NumberAnimation {
property: "y"
duration: 300
}}
header: Item {height: 4; width: 1}
model: Array.from(notifServer.trackedNotifications.values)
delegate: Widgets.Notification {
color: "#181818"
}
}
}
Item {
id: player
property var modelData: Mpris.players.values[0]
height: 300
width: 250
Column {
anchors.centerIn: parent
spacing: 2
opacity: !Mpris.players.values.length
Behavior on opacity {NumberAnimation {duration: 150}}
Image {
anchors.horizontalCenter: parent.horizontalCenter
source: Quickshell.shellPath("assets/player-symbolic.svg")
width: 24
height: 24
sourceSize {width: width; height: height}
opacity: 0.5
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
color: "#888"
text: "Nothing playing"
}
}
Column {
anchors {
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
margins: 6
}
opacity: Mpris.players.values.length
Behavior on opacity {NumberAnimation {duration: 150}}
Shape {
id: progressShape
anchors.horizontalCenter: parent.horizontalCenter
width: 160
height: width
property var strokeWidth: 6
preferredRendererType: Shape.CurveRenderer
ShapePath {
capStyle: ShapePath.RoundCap
strokeColor: "#444"
fillColor: "transparent"
strokeWidth: progressShape.strokeWidth
PathAngleArc {
moveToStart: true
radiusX: (progressShape.width-progressShape.strokeWidth)/2
radiusY: (progressShape.height-progressShape.strokeWidth)/2
centerX: progressShape.width/2
centerY: progressShape.height/2
startAngle: 90 + 20
sweepAngle: 360 - 40
}
}
ShapePath {
capStyle: ShapePath.RoundCap
strokeColor: "white"
fillColor: "transparent"
strokeWidth: 6
PathAngleArc {
moveToStart: true
radiusX: (progressShape.width-progressShape.strokeWidth)/2
radiusY: (progressShape.height-progressShape.strokeWidth)/2
centerX: progressShape.width/2
centerY: progressShape.height/2
startAngle: 90 + 20
sweepAngle: (player.modelData?.position/player.modelData.length) * (360 - 40)
}
}
ClippingRectangle {
color: "transparent"
radius: height/2
anchors.fill: parent
anchors.margins: progressShape.strokeWidth*2
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
mipmap: true
smooth: true
source: player.modelData?.trackArtUrl ?? source
}
NumberAnimation on rotation {
id: spin
paused: !player.modelData?.isPlaying || !root.up || background.index !== 3
duration: 60000
loops: Animation.Infinite
from: 0
to: 360
}
layer.enabled: true
layer.smooth: true
}
}
Item {width: 1; height: 10}
Text {
anchors {
left: parent.left
right: parent.right
}
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
color: "white"
text: player.modelData?.trackTitle ?? ""
font.pixelSize: 16
}
Text {
anchors {
left: parent.left
right: parent.right
}
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
color: "white"
text: player.modelData?.trackArtist ?? ""
font.pixelSize: 12
}
Item {width: 1; height: 8}
Row {
height: childrenRect.height
anchors.horizontalCenter: parent.horizontalCenter
component Button: Rectangle {
id: button
property var action
property var clicked
radius: 12
color: hover.hovered ? "#11ffffff" : "#00ffffff"
property var hover: HoverHandler {}
width: 40
height: width
Image {
anchors.fill: parent
anchors.margins: 8
sourceSize {width: width; height: height}
source: Quickshell.shellPath(`assets/lazer-${action}-symbolic.svg`)
}
TapHandler {onTapped: button.clicked()}
}
Button {
action: "previous"
clicked: player.modelData?.previous
}
Button {
action: player.modelData?.isPlaying ? "pause" : "play"
clicked: player.modelData?.togglePlaying
}
Button {
action: "next"
clicked: player.modelData?.next
}
}
FrameAnimation {
running: background.index === 3
onTriggered: player.modelData.positionChanged()
}
}
}
}
}