From b82995dd9df451f8647cc945088ef224ab019282 Mon Sep 17 00:00:00 2001
From: Nydragon <contact@ccnlc.eu>
Date: Sun, 29 Sep 2024 00:05:31 +0200
Subject: [PATCH] feat: add notification popups

---
 src/Bar.qml                                   |  5 +-
 src/provider/Notifications.qml                | 16 +++++
 .../notificationtoast/NotificationToasts.qml  | 66 +++++++++++++++++++
 src/windows/notificationtoast/Toast.qml       | 57 ++++++++++++++++
 4 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 src/provider/Notifications.qml
 create mode 100644 src/windows/notificationtoast/NotificationToasts.qml
 create mode 100644 src/windows/notificationtoast/Toast.qml

diff --git a/src/Bar.qml b/src/Bar.qml
index fc88acf..d8251ff 100644
--- a/src/Bar.qml
+++ b/src/Bar.qml
@@ -8,6 +8,7 @@ import "widgets/battery"
 import "widgets/network"
 import "widgets/notifcenter"
 import "widgets/caffeine"
+import "windows/notificationtoast"
 
 Scope {
     Variants {
@@ -29,7 +30,9 @@ Scope {
 
             width: 30
             color: "transparent"
-
+            NotificationToasts {
+                win: lbar
+            }
             ColumnLayout {
                 anchors.fill: parent
 
diff --git a/src/provider/Notifications.qml b/src/provider/Notifications.qml
new file mode 100644
index 0000000..8baa0ef
--- /dev/null
+++ b/src/provider/Notifications.qml
@@ -0,0 +1,16 @@
+pragma Singleton
+
+import Quickshell.Services.Notifications
+import Quickshell
+
+Singleton {
+    property var d: NotificationServer {
+        actionIconsSupported: true
+        actionsSupported: true
+        bodyHyperlinksSupported: true
+        bodyImagesSupported: true
+        bodyMarkupSupported: false
+        bodySupported: true
+        imageSupported: true
+    }
+}
diff --git a/src/windows/notificationtoast/NotificationToasts.qml b/src/windows/notificationtoast/NotificationToasts.qml
new file mode 100644
index 0000000..522f045
--- /dev/null
+++ b/src/windows/notificationtoast/NotificationToasts.qml
@@ -0,0 +1,66 @@
+import QtQuick
+import Quickshell
+import QtQuick.Controls
+import "root:provider"
+import "root:base"
+
+PopupWindow {
+    id: popups
+    required property var win
+    anchor {
+        rect.x: lbar.width * 1.2
+        window: popups.win
+    }
+    mask: Region {
+        item: popupcol
+        intersection: Intersection.Xor
+    }
+    visible: true
+    color: "transparent"
+    height: 500
+    width: 400
+    ListView {
+        id: popupcol
+        anchors.margins: lbar.width * 0.2
+        anchors.fill: parent
+        model: ListModel {
+            id: data
+            Component.onCompleted: () => {
+                Notifications.d.notification.connect(e => {
+                    data.insert(0, e);
+                    //data.append(e);
+                });
+            }
+        }
+        addDisplaced: Transition {
+            NumberAnimation {
+                properties: "x,y"
+                duration: 100
+            }
+        }
+        add: Transition {
+            NumberAnimation {
+                properties: "y"
+                from: -50
+                duration: 1000
+            }
+        }
+        remove: Transition {
+            ParallelAnimation {
+                NumberAnimation {
+                    property: "opacity"
+                    to: 0
+                    duration: 300
+                }
+                NumberAnimation {
+                    properties: "y"
+                    to: 100
+                    duration: 300
+                }
+            }
+        }
+
+        spacing: 10
+        delegate: Toast {}
+    }
+}
diff --git a/src/windows/notificationtoast/Toast.qml b/src/windows/notificationtoast/Toast.qml
new file mode 100644
index 0000000..e785a00
--- /dev/null
+++ b/src/windows/notificationtoast/Toast.qml
@@ -0,0 +1,57 @@
+import QtQuick
+import QtQuick.Controls
+import Quickshell
+import "root:base"
+
+BRectangle {
+    id: toast
+    color: "#BD93f910"
+    height: 50
+    width: 200
+    property int lifetime: 10000
+    property int countdownTime: lifetime
+
+    required property string appName
+    required property string summary
+    required property int index
+    MouseArea {
+
+        anchors.margins: 10
+        anchors.fill: parent
+        Text {
+            text: toast.appName + ": " + toast.summary
+        }
+
+        onEntered: () => {
+            timer.repeat = false;
+        }
+        onExited: () => {
+            timer.repeat = true;
+        }
+    }
+
+    Rectangle {
+        anchors.margins: 2
+        anchors.bottom: toast.bottom
+        anchors.right: toast.right
+        width: (toast.width - toast.border.width - anchors.margins) * (toast.countdownTime / toast.lifetime)
+        height: 2
+        bottomLeftRadius: toast.radius
+        bottomRightRadius: toast.radius
+    }
+
+    Timer {
+        id: timer
+        interval: 10
+        repeat: true
+        onTriggered: () => {
+            toast.countdownTime -= timer.interval;
+            if (toast.countdownTime <= 0) {
+                toast.parent.parent.model.remove(toast.index, 1);
+                timer.repeat = false;
+                timer.running = false;
+            }
+        }
+        running: true
+    }
+}