Notifications

This commit is contained in:
2025-02-03 18:07:00 -08:00
parent d3977958ed
commit 0fea2069f1
5 changed files with 149 additions and 1 deletions
+7
View File
@@ -0,0 +1,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
␍<g id="SVGRepo_bgCarrier" stroke-width="0"/>
␍<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
␍<g id="SVGRepo_iconCarrier"> <path d="M12.0009 5C13.4331 5 14.8066 5.50571 15.8193 6.40589C16.832 7.30606 17.4009 8.52696 17.4009 9.8C17.4009 11.7691 17.846 13.2436 18.4232 14.3279C19.1606 15.7133 19.5293 16.406 19.5088 16.5642C19.4849 16.7489 19.4544 16.7997 19.3026 16.9075C19.1725 17 18.5254 17 17.2311 17H6.77066C5.47638 17 4.82925 17 4.69916 16.9075C4.54741 16.7997 4.51692 16.7489 4.493 16.5642C4.47249 16.406 4.8412 15.7133 5.57863 14.3279C6.1558 13.2436 6.60089 11.7691 6.60089 9.8C6.60089 8.52696 7.16982 7.30606 8.18251 6.40589C9.19521 5.50571 10.5687 5 12.0009 5ZM12.0009 5V3M9.35489 20C10.0611 20.6233 10.9888 21.0016 12.0049 21.0016C13.0209 21.0016 13.9486 20.6233 14.6549 20" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="--darkreader-inline-stroke: var(--darkreader-text-ffffff, #e8e6e3);" data-darkreader-inline-stroke=""/> </g>
␍</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+34
View File
@@ -10,6 +10,9 @@ window {
> centerbox {
background: $background-1;
}
icon {
font-size: 24px;
}
}
button {
@@ -303,3 +306,34 @@ button {
border: 2px solid $highlight-3;
border-radius: 8px;
}
@keyframes notifIn {
0% {
margin-right: -352px;
}
}
@keyframes glowIn {
from {
background: white;
box-shadow: 0 0 10px 4px white;
}
}
.notifBox {
animation: notifIn cubic-bezier(0.34, 1.4, 0.64, 1) 0.4s, glowIn ease-in 0.3s;
transition: margin cubic-bezier(0.34, 1.4, 0.64, 1) 0.4s;
background: $background-3;
border-radius: 10px;
padding: 8px;
box-shadow: 0 0 10px 4px black;
min-width: 300px;
margin: 12px 12px 40px 40px;
}
.notifIcon {
min-width: 64px;
min-height: 64px;
margin: 8px;
background-size: contain;
border-radius: 10px;
}
+2
View File
@@ -8,6 +8,7 @@ import brightness from "./brightness"
import client from "./client"
import player from "./player"
import bluetooth from "./bluetooth"
import notifs from "./notif"
const time = Variable("").poll(1000, "date +'%a %b %d · %H:%M'")
@@ -40,6 +41,7 @@ export default function Bar(monitor: Hyprland.Monitor) {
label={time()}
/>
</box></button>
{notifs()}
</box>
</centerbox>
</window>
+1 -1
View File
@@ -21,7 +21,7 @@ function bluetoothItem(device: Bluetooth.Device) {
valign: Gtk.Align.CENTER,
})}>
<box>
<icon icon={device.icon} css="font-size: 32px;" />
<icon icon={device.icon ?? "bluetooth"} css="font-size: 32px;" />
<label valign={Gtk.Align.CENTER}>{device.alias ?? device.name}</label>
</box>
</overlay>
+105
View File
@@ -0,0 +1,105 @@
import { bind } from "astal"
import { Astal, Gtk, Widget } from "astal/gtk3"
import Notif from "gi://AstalNotifd"
import Pango from "gi://Pango?version=1.0"
const notifs = Notif.get_default()
const { TOP, RIGHT } = Astal.WindowAnchor
const notifPlaceholder = "/home/protoshark/.config/ags/assets/notif.svg"
let notifWindow: Widget.Window
function NewNotif(notif: Notif.Notification) {
return <box
className="notifBox"
halign={Gtk.Align.END}
valign={Gtk.Align.START} >
<box
spacing={8}>
<box
halign={Gtk.Align.CENTER}
valign={Gtk.Align.CENTER}
className="notifIcon"
css={`background-image: url("${notif.image ?? notifPlaceholder}")`}
/>
<box vertical={true} valign={Gtk.Align.CENTER} spacing={6}>
<label
halign={Gtk.Align.START}
css="font-size: 16px;"
wrap={true}
maxWidthChars={20}
wrapMode={Pango.WrapMode.WORD_CHAR}>
{notif.summary.substring(0, 80)}
</label>
<label
halign={Gtk.Align.START}
css="font-size: 14px;"
wrap={true}
maxWidthChars={22}
wrapMode={Pango.WrapMode.WORD_CHAR}>
{notif.body.substring(0, 88)}
</label>
</box>
</box></box>
}
function notify(notif: Notif.Notification) {
let thisNotif = NewNotif(notif)
if (notifWindow) {
let os = notifWindow.get_child().overlays
let top = 12
for (let i = os.length-1; i > 0; i--) {
top += thisNotif.get_preferred_height()[0] - 40
if (os[i].get_preferred_width()[0] >= 352) {
os[i].css = `margin-top: ${top}px;`
}
}
notifWindow.get_child().add_overlay(thisNotif)
notifWindow.get_child().get_child().heightRequest = os[1].get_preferred_height()[0] + thisNotif.get_preferred_height()[0]
} else {
notifWindow = <window
anchor={ TOP | RIGHT }
marginTop={36}
css="background: transparent;"
namespace="notification">
<overlay overlay={thisNotif}>
<box
halign={Gtk.Align.END}
valign={Gtk.Align.START}
widthRequest={thisNotif.get_preferred_width()[0]}
heightRequest={1200}
/>
</overlay>
</window>
}
setTimeout(() => {
let os = notifWindow.get_child().overlays
thisNotif.css = `margin-right: -352px; margin-top: ${thisNotif.get_preferred_height()[0]-thisNotif.get_child().get_preferred_height()[0]-52}px; transition: cubic-bezier(0.64, 0, 0.78, 0) 0.3s;`
setTimeout(() => {
let os = notifWindow.get_child().overlays
notifWindow.get_child().remove(thisNotif)
if (os.length < 3) {
notifWindow.destroy()
notifWindow = null
}
}, 400)
}, 3000)
}
function notifCount() {
return <label css="padding-top: 2px;">
{bind(notifs, "notifications").as(ns => ns.length)}
</label>
}
export default function notifWidget() {
return <button
onClicked={() => {}}
setup={(self) => self.hook(notifs, "notified", (_, id) => {
notify(notifs.get_notification(id))
})}>
<box>
<icon icon="notif" css="color: white;" />
{notifCount()}
</box>
</button>
}