172 lines
5.7 KiB
QML
Raw Normal View History

pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Wayland
2025-12-27 20:47:50 +01:00
import Quickshell.Hyprland
import "."
import "../../"
import QtQuick.Layouts
2025-12-28 17:36:11 +01:00
import Quickshell.Widgets
import "../settings/"
WlrLayershell {
id: root
screen: {
2025-12-27 20:47:50 +01:00
// Iterate through all connected Quickshell screens
for (let i = 0; i < Quickshell.screens.length; i++) {
let screenCandidate = Quickshell.screens[i];
2025-12-27 20:47:50 +01:00
// Ask: "Is this screen the one Hyprland is currently focusing?"
if (Hyprland.monitorFor(screenCandidate) === Hyprland.focusedMonitor) {
return screenCandidate;
}
}
return null; // Fallback (should rarely happen)
}
// 1. Position: Top Right Corner, covering the full height
// We make it a fixed width (e.g., 400px) so it doesn't block the whole screen
anchors {
top: true
right: true
}
margins {
top: 36
right: 00
}
implicitWidth: 300
implicitHeight: notifList.contentHeight + 20
Behavior on implicitHeight {
NumberAnimation {
duration: 300
easing.type: Easing.OutQuad
}
}
// 2. Layer: Put it ABOVE normal windows
layer: WlrLayer.Overlay
exclusionMode: ExclusionMode.Ignore
// 3. CRITICAL: Make the window itself invisible!
// We only want to see the
// notifications, not the container.
color: "transparent"
// 4. Input: Let clicks pass through empty areas
// (This is default behavior if the background is transparent in some compositors,
// but usually you need to be careful with handling mouse events here)
// THE SPAWNER
ListView {
id: notifList
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
2025-12-28 17:36:11 +01:00
anchors.margins: 0
// Use 'spacing' to put gaps between notifications
spacing: 00
height: contentHeight
2025-12-24 15:41:03 +01:00
model: NotifServer.trackedNotifications
delegate: Item {
id: notifyItem
required property var index
readonly property bool isLast: index === (ListView.view.count - 1)
implicitWidth: ListView.view.width
2025-12-28 17:36:11 +01:00
implicitHeight: 85 // Fixed height is usually better for icon layouts
height: implicitHeight
required property var modelData
2025-12-24 15:41:03 +01:00
Timer {
id: timout
2025-12-28 17:36:11 +01:00
interval: 3000
2025-12-24 15:41:03 +01:00
running: true
onTriggered: notifyItem.modelData.dismiss()
2025-12-24 15:41:03 +01:00
}
Rectangle {
anchors.fill: parent
color: Colors.background
bottomLeftRadius: notifyItem.isLast ? 20 : 0
border.color: Colors.color5
border.width: 0
// 2. Use RowLayout to put Image | Text side-by-side
RowLayout {
id: fullLayout
anchors.margins: 10
2025-12-26 00:37:39 +01:00
anchors.fill: parent
2025-12-28 17:36:11 +01:00
spacing: 10
// 🖼️ THE IMAGE ON THE LEFT
2025-12-28 17:36:11 +01:00
ClippingWrapperRectangle {
radius: 10
implicitWidth: 64
implicitHeight: 64
visible: notifyItem.modelData.image !== ""
IconImage {
2025-12-26 00:37:39 +01:00
2025-12-28 17:36:11 +01:00
// Use the image if available, otherwise hide this space?
// Or you could use an icon fallback.
source: notifyItem.modelData.image
2025-12-28 17:36:11 +01:00
// Hide if no image exists so text takes full width
visible: notifyItem.modelData.image !== ""
2025-12-28 17:36:11 +01:00
// Fixed size for consistency
implicitSize: 30
2025-12-28 17:36:11 +01:00
// Crop it nicely so it doesn't stretch
2025-12-28 17:36:11 +01:00
// Optional: Cache it for performance
asynchronous: true
}
}
// 📝 THE TEXT ON THE RIGHT
ColumnLayout {
id: textLayout
// Take up all remaining width
Layout.fillWidth: true
2025-12-28 17:36:11 +01:00
Layout.alignment: Qt.AlignVCenter // Center vertically
spacing: 2
Text {
text: notifyItem.modelData.summary
color: Colors.foreground
2025-12-28 17:36:11 +01:00
font.family: Settings.font
font.pixelSize: Settings.fontSize
font.bold: true
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: notifyItem.modelData.body
color: Colors.foreground
// Limit to 2 lines
2025-12-28 17:36:11 +01:00
font.family: Settings.font
font.pixelSize: Settings.fontSize - 2
maximumLineCount: 3
wrapMode: Text.WordWrap
elide: Text.ElideRight
Layout.fillWidth: true
}
}
}
// (Your MouseArea for closing can still go here covering the whole thing)
MouseArea {
anchors.fill: parent
2025-12-26 00:37:39 +01:00
Layout.fillWidth: true
Layout.fillHeight: true
acceptedButtons: Qt.LeftButton
onClicked: notifyItem.modelData.dismiss()
}
}
}
}
}