Notification backend usable
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
.qmlls.ini
|
.qmlls.ini
|
||||||
|
scripts/
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ WrapperRectangle {
|
|||||||
item.monitor = barArea.monitor;
|
item.monitor = barArea.monitor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ Item {
|
|||||||
running: true
|
running: true
|
||||||
command: ["cal", "-S3"]
|
command: ["cal", "-S3"]
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {clock.calendar=this.text}
|
onStreamFinished: {
|
||||||
|
clock.calendar = this.text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,15 +48,12 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
cal.running = true
|
cal.running = true;
|
||||||
PopUpHover.start(clock,"time")
|
PopUpHover.start(clock, "time");
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
PopUpHover.exit()
|
PopUpHover.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ Item {
|
|||||||
leftMargin: Theme.gaps
|
leftMargin: Theme.gaps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
target: root
|
||||||
|
property: "createWindow"
|
||||||
|
value: NotificationService.notificationsNumber > 0 && root.createWindow
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: Theme.backgroudColor
|
color: Theme.backgroudColor
|
||||||
implicitWidth: clockText.implicitWidth * 1.6
|
implicitWidth: clockText.implicitWidth * 1.6
|
||||||
@@ -39,18 +45,15 @@ Item {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log(NotificationService.currentNotification.image);
|
root.createWindow = !root.createWindow;
|
||||||
root.createWindow = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
id: windowLoader
|
id: windowLoader
|
||||||
|
|
||||||
active: root.createWindow
|
active: NotificationService.notificationsNumber ? createWindow : false
|
||||||
|
|
||||||
component: NotificationWindow {
|
component: NotificationWindow {}
|
||||||
anchor.item:root
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,70 +10,68 @@ Singleton {
|
|||||||
|
|
||||||
property var sortedTopLevels: {
|
property var sortedTopLevels: {
|
||||||
if (!ToplevelManager.toplevels || !ToplevelManager.toplevels.values) {
|
if (!ToplevelManager.toplevels || !ToplevelManager.toplevels.values) {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const topLevels = Array.from(Hyprland.toplevels.values)
|
const topLevels = Array.from(Hyprland.toplevels.values);
|
||||||
const sortedHyprland = topLevels.sort((a, b) => {
|
const sortedHyprland = topLevels.sort((a, b) => {
|
||||||
if (a.monitor && b.monitor) {
|
if (a.monitor && b.monitor) {
|
||||||
const monitorCompare = a.monitor.name.localeCompare(b.monitor.name)
|
const monitorCompare = a.monitor.name.localeCompare(b.monitor.name);
|
||||||
if (monitorCompare !== 0) {
|
if (monitorCompare !== 0) {
|
||||||
return monitorCompare
|
return monitorCompare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.workspace && b.workspace) {
|
if (a.workspace && b.workspace) {
|
||||||
const workspaceCompare = a.workspace.id - b.workspace.id
|
const workspaceCompare = a.workspace.id - b.workspace.id;
|
||||||
if (workspaceCompare !== 0) {
|
if (workspaceCompare !== 0) {
|
||||||
return workspaceCompare
|
return workspaceCompare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.lastIpcObject && b.lastIpcObject && a.lastIpcObject.at && b.lastIpcObject.at) {
|
if (a.lastIpcObject && b.lastIpcObject && a.lastIpcObject.at && b.lastIpcObject.at) {
|
||||||
const aX = a.lastIpcObject.at[0]
|
const aX = a.lastIpcObject.at[0];
|
||||||
const bX = b.lastIpcObject.at[0]
|
const bX = b.lastIpcObject.at[0];
|
||||||
const aY = a.lastIpcObject.at[1]
|
const aY = a.lastIpcObject.at[1];
|
||||||
const bY = b.lastIpcObject.at[1]
|
const bY = b.lastIpcObject.at[1];
|
||||||
|
|
||||||
const xCompare = aX - bX
|
const xCompare = aX - bX;
|
||||||
if (Math.abs(xCompare) > 10) {
|
if (Math.abs(xCompare) > 10) {
|
||||||
return xCompare
|
return xCompare;
|
||||||
}
|
}
|
||||||
return aY - bY
|
return aY - bY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.lastIpcObject && !b.lastIpcObject) {
|
if (a.lastIpcObject && !b.lastIpcObject) {
|
||||||
return -1
|
return -1;
|
||||||
}
|
}
|
||||||
if (!a.lastIpcObject && b.lastIpcObject) {
|
if (!a.lastIpcObject && b.lastIpcObject) {
|
||||||
return 1
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.title && b.title) {
|
if (a.title && b.title) {
|
||||||
return a.title.localeCompare(b.title)
|
return a.title.localeCompare(b.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0;
|
||||||
})
|
});
|
||||||
return sortedHyprland.filter(tl => tl.wayland !== null)
|
return sortedHyprland.filter(tl => tl.wayland !== null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
property var topLevelWorkspaces: {
|
property var topLevelWorkspaces: {
|
||||||
return sortedTopLevels.map(topLevel => topLevel.workspace)
|
return sortedTopLevels.map(topLevel => topLevel.workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
property var sortedDesktopApplications: {
|
property var sortedDesktopApplications: {
|
||||||
const sortedWayland = sortedTopLevels.map(topLevel => topLevel.wayland).filter(wayland=> wayland !== null)
|
const sortedWayland = sortedTopLevels.map(topLevel => topLevel.wayland).filter(wayland => wayland !== null);
|
||||||
|
|
||||||
const desktopEntries = sortedWayland.map(topLevel => {
|
const desktopEntries = sortedWayland.map(topLevel => {
|
||||||
return DesktopEntries.heuristicLookup(topLevel.appId)
|
return DesktopEntries.heuristicLookup(topLevel.appId);
|
||||||
})
|
});
|
||||||
const workspace = sortedTopLevels.map(topLevel => {
|
const workspace = sortedTopLevels.map(topLevel => {
|
||||||
return topLevel.workspace.id
|
return topLevel.workspace.id;
|
||||||
})
|
});
|
||||||
const workspaceDesktopEntries = new Map()
|
const workspaceDesktopEntries = new Map();
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < workspace.length; i++) {
|
for (let i = 0; i < workspace.length; i++) {
|
||||||
const key = workspace[i];
|
const key = workspace[i];
|
||||||
@@ -85,8 +83,6 @@ Singleton {
|
|||||||
workspaceDesktopEntries.set(key, [value]);
|
workspaceDesktopEntries.set(key, [value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return workspaceDesktopEntries
|
return workspaceDesktopEntries;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,16 +2,13 @@ pragma Singleton
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: notificationRoot
|
id: notificationRoot
|
||||||
|
|
||||||
|
|
||||||
readonly property var notificationServer: notificationServer
|
readonly property var notificationServer: notificationServer
|
||||||
readonly property var trackedNotifications: notificationServer.trackedNotifications
|
readonly property var trackedNotifications: notificationServer.trackedNotifications
|
||||||
readonly property var notificationsNumber: notificationServer.trackedNotifications.values.length
|
readonly property var notificationsNumber: notificationServer.trackedNotifications.values.length
|
||||||
@@ -29,6 +26,9 @@ Singleton {
|
|||||||
notif.dismiss();
|
notif.dismiss();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (notif.traked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
notif.tracked = true;
|
notif.tracked = true;
|
||||||
notificationRoot.currentNotification = notif;
|
notificationRoot.currentNotification = notif;
|
||||||
notificationRoot.shouldShowOsd = true;
|
notificationRoot.shouldShowOsd = true;
|
||||||
@@ -47,19 +47,33 @@ Singleton {
|
|||||||
|
|
||||||
LazyLoader {
|
LazyLoader {
|
||||||
id: popupLoader
|
id: popupLoader
|
||||||
active: currentNotification && shouldShowOsd
|
active: notificationRoot.currentNotification && notificationRoot.shouldShowOsd
|
||||||
|
|
||||||
component: NotificationPopup {
|
component: PanelWindow {
|
||||||
notification: currentNotification
|
id: notificationWindow
|
||||||
// No signal handler here!
|
|
||||||
}
|
|
||||||
|
|
||||||
onItemChanged: {
|
anchors.top: true
|
||||||
if (item) {
|
margins.top: screen.height / 100
|
||||||
item.dismissed.connect(function() {
|
exclusiveZone: 0
|
||||||
notificationRoot.shouldShowOsd = false
|
|
||||||
currentNotification.dismiss()
|
implicitWidth: 400
|
||||||
})
|
implicitHeight: 905
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
NotificationWrapper {
|
||||||
|
id: notificationWrapper
|
||||||
|
|
||||||
|
notification: notificationRoot.currentNotification
|
||||||
|
implicitWidth: notificationWindow.implicitWidth
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
console.log(notificationWrapper.height);
|
||||||
|
popupLoader.implicitHeight = notificationWrapper.implicitHeight;
|
||||||
|
}
|
||||||
|
onDismissed: {
|
||||||
|
notificationRoot.shouldShowOsd = false;
|
||||||
|
notificationRoot.currentNotification.dismiss();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,19 +8,18 @@ import Quickshell.Widgets
|
|||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
|
|
||||||
function start(component, type) {
|
function start(component, type) {
|
||||||
HoverMediator.component = component
|
HoverMediator.component = component;
|
||||||
HoverMediator.type = type
|
HoverMediator.type = type;
|
||||||
hoverPopUp.anchor.updateAnchor()
|
hoverPopUp.anchor.updateAnchor();
|
||||||
hoverTimer.start()
|
hoverTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
function exit() {
|
function exit() {
|
||||||
hoverTimer.stop()
|
hoverTimer.stop();
|
||||||
hoverPopUp.visible = false
|
hoverPopUp.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupWindow {
|
PopupWindow {
|
||||||
@@ -50,10 +49,14 @@ Singleton {
|
|||||||
id: systray
|
id: systray
|
||||||
Text {
|
Text {
|
||||||
text: {
|
text: {
|
||||||
if (!HoverMediator.component.model) return ""
|
if (!HoverMediator.component.model)
|
||||||
if (HoverMediator.component.model.tooltipTitle) return HoverMediator.component.model.tooltipTitle
|
return "";
|
||||||
if (HoverMediator.component.model.title) return HoverMediator.component.model.title
|
if (HoverMediator.component.model.tooltipTitle)
|
||||||
else return ""
|
return HoverMediator.component.model.tooltipTitle;
|
||||||
|
if (HoverMediator.component.model.title)
|
||||||
|
return HoverMediator.component.model.title;
|
||||||
|
else
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: Theme.pixelSize
|
font.pixelSize: Theme.pixelSize
|
||||||
@@ -104,7 +107,8 @@ Singleton {
|
|||||||
|
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
||||||
width:30; height:30
|
width: 30
|
||||||
|
height: 30
|
||||||
source: (modelData && modelData.icon) ? Quickshell.iconPath(modelData.icon, 1) : ""
|
source: (modelData && modelData.icon) ? Quickshell.iconPath(modelData.icon, 1) : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,21 +126,28 @@ Singleton {
|
|||||||
radius: 25
|
radius: 25
|
||||||
opacity: 1
|
opacity: 1
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
NumberAnimation { property: "opacity"; duration: Theme.animationDuration}
|
NumberAnimation {
|
||||||
|
property: "opacity"
|
||||||
|
duration: Theme.animationDuration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: hoverLoader
|
id: hoverLoader
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
if(!HoverMediator.type) return stub
|
if (!HoverMediator.type)
|
||||||
if(HoverMediator.type === "workspace") return workspaceComponent
|
return stub;
|
||||||
if(HoverMediator.type === "audio") return audio
|
if (HoverMediator.type === "workspace")
|
||||||
if(HoverMediator.type === "time") return time
|
return workspaceComponent;
|
||||||
if(HoverMediator.type === "systray") return systray
|
if (HoverMediator.type === "audio")
|
||||||
|
return audio;
|
||||||
|
if (HoverMediator.type === "time")
|
||||||
|
return time;
|
||||||
|
if (HoverMediator.type === "systray")
|
||||||
|
return systray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -145,7 +156,7 @@ Singleton {
|
|||||||
interval: 300
|
interval: 300
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
// wsPopUp.opacity = 1
|
// wsPopUp.opacity = 1
|
||||||
hoverPopUp.visible = true
|
hoverPopUp.visible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,4 @@ Singleton {
|
|||||||
|
|
||||||
precision: SystemClock.Seconds
|
precision: SystemClock.Seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -57,7 +56,8 @@ WrapperRectangle {
|
|||||||
IconImage {
|
IconImage {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width:25; height:25
|
width: 25
|
||||||
|
height: 25
|
||||||
source: systrayItem.iconSource
|
source: systrayItem.iconSource
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,30 +66,23 @@ WrapperRectangle {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
PopUpHover.start(systrayItem,"systray")
|
PopUpHover.start(systrayItem, "systray");
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
PopUpHover.exit()
|
PopUpHover.exit();
|
||||||
}
|
}
|
||||||
onClicked: (mouse) => {
|
onClicked: mouse => {
|
||||||
if (mouse.button === Qt.RightButton) {
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
|
||||||
menuAnchor.menu = systrayItem.model.menu;
|
menuAnchor.menu = systrayItem.model.menu;
|
||||||
menuAnchor.anchor.item = systrayItem;
|
menuAnchor.anchor.item = systrayItem;
|
||||||
menuAnchor.anchor.rect = Qt.rect(
|
menuAnchor.anchor.rect = Qt.rect(0, systrayItem.implicitHeight, 0, 0);
|
||||||
0,
|
|
||||||
systrayItem.implicitHeight,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
menuAnchor.open();
|
menuAnchor.open();
|
||||||
|
} else if (mouse.button === Qt.LeftButton)
|
||||||
} else if (mouse.button === Qt.LeftButton) {
|
|
||||||
// systrayItem.model.activate()
|
// systrayItem.model.activate()
|
||||||
}
|
{}
|
||||||
}
|
}
|
||||||
onDoubleClicked: {
|
onDoubleClicked: {
|
||||||
systrayItem.model.activate()
|
systrayItem.model.activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,6 +91,5 @@ WrapperRectangle {
|
|||||||
|
|
||||||
QsMenuAnchor {
|
QsMenuAnchor {
|
||||||
id: menuAnchor
|
id: menuAnchor
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Services.Notifications
|
|
||||||
import Quickshell.Widgets
|
|
||||||
|
|
||||||
PanelWindow {
|
|
||||||
id: notificationRoot
|
|
||||||
|
|
||||||
// Since the panel's screen is unset, it will be picked by the compositor
|
|
||||||
// when the window is created. Most compositors pick the current active monitor.
|
|
||||||
|
|
||||||
property bool hasImage: notification?.image ? true : false
|
|
||||||
|
|
||||||
property string image: {
|
|
||||||
if (hasImage) {
|
|
||||||
return notification.image;
|
|
||||||
}
|
|
||||||
if (notification?.appIcon === "") {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return Quickshell.iconPath(notification?.appIcon);
|
|
||||||
}
|
|
||||||
property var notification: null
|
|
||||||
|
|
||||||
signal dismissed()
|
|
||||||
|
|
||||||
anchors.top: true
|
|
||||||
margins.top: screen.height / 100
|
|
||||||
exclusiveZone: 0
|
|
||||||
|
|
||||||
implicitWidth: 400
|
|
||||||
implicitHeight: 100
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
// An empty click mask prevents the window from blocking mouse events.
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
topLeftRadius: 100
|
|
||||||
bottomLeftRadius: 100
|
|
||||||
topRightRadius: 20
|
|
||||||
bottomRightRadius: 20
|
|
||||||
color: "#80000000"
|
|
||||||
|
|
||||||
MouseArea{
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
notificationRoot.dismissed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
anchors {
|
|
||||||
fill: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
ClippingRectangle {
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
|
||||||
|
|
||||||
implicitWidth: 100
|
|
||||||
implicitHeight: 100
|
|
||||||
visible: image? true : false
|
|
||||||
|
|
||||||
color: "grey"
|
|
||||||
|
|
||||||
radius: 100
|
|
||||||
|
|
||||||
IconImage {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
implicitSize: 100
|
|
||||||
source: notificationRoot.image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
|
|
||||||
Layout.leftMargin: 10
|
|
||||||
Layout.rightMargin: 10
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
implicitHeight: 30
|
|
||||||
radius: 20
|
|
||||||
color: "#50ffffff"
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
top: parent.top
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitWidth: parent.width
|
|
||||||
radius: parent.radius
|
|
||||||
color: "white"
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.fill: parent
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
fontSizeMode: Text.Fit
|
|
||||||
|
|
||||||
text: notificationRoot.notification.summary
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
implicitHeight: 55
|
|
||||||
radius: 20
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
top: parent.top
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitWidth: parent.width
|
|
||||||
radius: parent.radius
|
|
||||||
color: "white"
|
|
||||||
|
|
||||||
Text {
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
font.pixelSize: 24
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
fontSizeMode: Text.Fit
|
|
||||||
minimumPixelSize: 10
|
|
||||||
elide: Text.ElideRight
|
|
||||||
|
|
||||||
text: notificationRoot.notification.body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +1,41 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
import QtQuick.Window
|
||||||
|
|
||||||
PopupWindow {
|
PopupWindow {
|
||||||
|
id: notificationRoot
|
||||||
|
|
||||||
anchor.item: root
|
anchor.item: root
|
||||||
anchor.rect.y: parentWindow.height
|
anchor.rect.y: parentWindow?.height
|
||||||
implicitWidth: 400
|
implicitWidth: 400
|
||||||
implicitHeight: 1000
|
implicitHeight: Math.min(listView.contentHeight, 900)
|
||||||
color: "white"
|
color: "white"
|
||||||
visible: true
|
visible: true
|
||||||
|
|
||||||
id: notificationRoot
|
|
||||||
|
|
||||||
// Since the panel's screen is unset, it will be picked by the compositor
|
|
||||||
// when the window is created. Most compositors pick the current active monitor.
|
|
||||||
|
|
||||||
|
|
||||||
// An empty click mask prevents the window from blocking mouse events.
|
|
||||||
Component {
|
|
||||||
id: contactDelegate
|
|
||||||
NotificationPopup {
|
|
||||||
id: myItem
|
|
||||||
required property string notification
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
|
id: listView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
model: NotificationService.trackedNotifications.values
|
model: NotificationService.trackedNotifications.values
|
||||||
delegate: contactDelegate
|
orientation: ListView.Vertical
|
||||||
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
focus: true
|
clip: true
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
delegate: NotificationWrapper {
|
||||||
|
required property var modelData
|
||||||
|
notification: modelData
|
||||||
|
width: ListView.width
|
||||||
|
onDismissed: {
|
||||||
|
if (notification && typeof notification.dismiss === "function") {
|
||||||
|
notification.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onCompleted: positionViewAtEnd()
|
||||||
|
onModelChanged: positionViewAtEnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
138
Widgets/NotificationWrapper.qml
Normal file
138
Widgets/NotificationWrapper.qml
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell.Widgets
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: notificationWrapper
|
||||||
|
|
||||||
|
signal dismissed
|
||||||
|
|
||||||
|
property bool hasImage: notification?.image ? true : false
|
||||||
|
property var notification: null
|
||||||
|
|
||||||
|
property string image: {
|
||||||
|
if (hasImage) {
|
||||||
|
return notification.image;
|
||||||
|
}
|
||||||
|
if (notification?.appIcon === "") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return Quickshell.iconPath(notification?.appIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: 400
|
||||||
|
implicitHeight: notifLayout.implicitHeight
|
||||||
|
topLeftRadius: image ? 100 : 20
|
||||||
|
bottomLeftRadius: image ? 100 : 20
|
||||||
|
topRightRadius: 20
|
||||||
|
bottomRightRadius: 20
|
||||||
|
color: "#80000000"
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
notificationWrapper.dismissed();
|
||||||
|
console.log("opa");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: notifLayout
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
ClippingRectangle {
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
|
||||||
|
implicitWidth: 100
|
||||||
|
implicitHeight: 100
|
||||||
|
visible: notificationWrapper.image ? true : false
|
||||||
|
|
||||||
|
color: "grey"
|
||||||
|
|
||||||
|
radius: 100
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
implicitSize: 100
|
||||||
|
source: notificationWrapper.image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
Layout.rightMargin: 10
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
implicitHeight: summaryText.implicitHeight + 10
|
||||||
|
radius: 20
|
||||||
|
color: "#50ffffff"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: parent.width
|
||||||
|
radius: parent.radius
|
||||||
|
color: "white"
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: summaryText
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font.pixelSize: 12
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
textFormat: Text.MarkdownText
|
||||||
|
|
||||||
|
text: notificationWrapper.notification.summary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
implicitHeight: bodyText.implicitHeight + 10
|
||||||
|
radius: 20
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
top: parent.top
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: parent.width
|
||||||
|
radius: parent.radius
|
||||||
|
color: "white"
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: bodyText
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font.pixelSize: 14
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
textFormat: Text.MarkdownText
|
||||||
|
|
||||||
|
text: notificationWrapper.notification.body
|
||||||
|
onLinkActivated: link => Qt.openUrlExternally(link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ WrapperMouseArea {
|
|||||||
|
|
||||||
property var monitor: "black"
|
property var monitor: "black"
|
||||||
|
|
||||||
onWheel: (wheel) => {
|
onWheel: wheel => {
|
||||||
if (wheel.angleDelta.y > 0) {
|
if (wheel.angleDelta.y > 0) {
|
||||||
if ((Hyprland.focusedWorkspace.id) % 5 === 0)
|
if ((Hyprland.focusedWorkspace.id) % 5 === 0)
|
||||||
return;
|
return;
|
||||||
@@ -63,17 +63,32 @@ WrapperMouseArea {
|
|||||||
State {
|
State {
|
||||||
name: "Active"
|
name: "Active"
|
||||||
when: workspacesRectangle.workspaceActive
|
when: workspacesRectangle.workspaceActive
|
||||||
PropertyChanges { workspacesRectangle{ color: Theme.color6; implicitWidth: Theme.barSize*1.5}}
|
PropertyChanges {
|
||||||
|
workspacesRectangle {
|
||||||
|
color: Theme.color6
|
||||||
|
implicitWidth: Theme.barSize * 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
name: "Filled"
|
name: "Filled"
|
||||||
when: !workspacesRectangle.workspaceActive && workspacesRectangle.hasTopLevel
|
when: !workspacesRectangle.workspaceActive && workspacesRectangle.hasTopLevel
|
||||||
PropertyChanges { workspacesRectangle{ color: Theme.backgroudColorBright; implicitWidth: Theme.barSize}}
|
PropertyChanges {
|
||||||
|
workspacesRectangle {
|
||||||
|
color: Theme.backgroudColorBright
|
||||||
|
implicitWidth: Theme.barSize
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
name: "Empty"
|
name: "Empty"
|
||||||
when: !workspacesRectangle.workspaceActive && !workspacesRectangle.hasTopLevel
|
when: !workspacesRectangle.workspaceActive && !workspacesRectangle.hasTopLevel
|
||||||
PropertyChanges { workspacesRectangle{ color: Theme.backgroudColor;implicitWidth: Theme.barSize}}
|
PropertyChanges {
|
||||||
|
workspacesRectangle {
|
||||||
|
color: Theme.backgroudColor
|
||||||
|
implicitWidth: Theme.barSize
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -106,23 +121,21 @@ WrapperMouseArea {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (parent.hasTopLevel && !parent.workspaceActive) {
|
if (parent.hasTopLevel && !parent.workspaceActive) {
|
||||||
PopUpHover.start(workspacesRectangle, "workspace")
|
PopUpHover.start(workspacesRectangle, "workspace");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
PopUpHover.exit()
|
PopUpHover.exit();
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if(workspacesRectangle.workspace.id === Hyprland.focusedWorkspace.id) {return} ;
|
if (workspacesRectangle.workspace.id === Hyprland.focusedWorkspace.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
;
|
||||||
Hyprland.dispatch("workspace " + workspacesRectangle.workspace.id);
|
Hyprland.dispatch("workspace " + workspacesRectangle.workspace.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user