Notifications
This commit is contained in:
7
assets/notif.svg
Normal file
7
assets/notif.svg
Normal 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"/>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
34
style.scss
34
style.scss
@@ -10,6 +10,9 @@ window {
|
|||||||
> centerbox {
|
> centerbox {
|
||||||
background: $background-1;
|
background: $background-1;
|
||||||
}
|
}
|
||||||
|
icon {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -303,3 +306,34 @@ button {
|
|||||||
border: 2px solid $highlight-3;
|
border: 2px solid $highlight-3;
|
||||||
border-radius: 8px;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import brightness from "./brightness"
|
|||||||
import client from "./client"
|
import client from "./client"
|
||||||
import player from "./player"
|
import player from "./player"
|
||||||
import bluetooth from "./bluetooth"
|
import bluetooth from "./bluetooth"
|
||||||
|
import notifs from "./notif"
|
||||||
|
|
||||||
const time = Variable("").poll(1000, "date +'%a %b %d · %H:%M'")
|
const time = Variable("").poll(1000, "date +'%a %b %d · %H:%M'")
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ export default function Bar(monitor: Hyprland.Monitor) {
|
|||||||
label={time()}
|
label={time()}
|
||||||
/>
|
/>
|
||||||
</box></button>
|
</box></button>
|
||||||
|
{notifs()}
|
||||||
</box>
|
</box>
|
||||||
</centerbox>
|
</centerbox>
|
||||||
</window>
|
</window>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function bluetoothItem(device: Bluetooth.Device) {
|
|||||||
valign: Gtk.Align.CENTER,
|
valign: Gtk.Align.CENTER,
|
||||||
})}>
|
})}>
|
||||||
<box>
|
<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>
|
<label valign={Gtk.Align.CENTER}>{device.alias ?? device.name}</label>
|
||||||
</box>
|
</box>
|
||||||
</overlay>
|
</overlay>
|
||||||
|
|||||||
105
widget/notif.tsx
Normal file
105
widget/notif.tsx
Normal 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>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user