137 lines
4.0 KiB
Python
137 lines
4.0 KiB
Python
from fabric.notifications import Notification
|
|
from fabric.utils import invoke_repeater
|
|
from fabric.widgets.box import Box
|
|
from fabric.widgets.button import Button
|
|
from fabric.widgets.image import Image
|
|
from fabric.widgets.label import Label
|
|
from gi.repository import GdkPixbuf
|
|
|
|
from sims.utils.markup import render_body_markup
|
|
|
|
NOTIFICATION_IMAGE_SIZE = 64
|
|
|
|
|
|
class NotificationWidget(Box):
|
|
def __init__(
|
|
self,
|
|
notification: Notification,
|
|
width: int = 360,
|
|
timeout_ms: int = 10_000,
|
|
**kwargs,
|
|
):
|
|
super().__init__(
|
|
size=(width, -1),
|
|
name="notification",
|
|
spacing=8,
|
|
orientation="v",
|
|
**kwargs,
|
|
)
|
|
|
|
self._notification = notification
|
|
|
|
urgency_class = {0: "urgency-low", 1: "urgency-normal", 2: "urgency-critical"}.get(
|
|
notification.urgency, "urgency-normal"
|
|
)
|
|
self.get_style_context().add_class(urgency_class)
|
|
|
|
body_container = Box(spacing=4, orientation="h")
|
|
|
|
if image_pixbuf := self._notification.image_pixbuf:
|
|
body_container.add(
|
|
Image(
|
|
pixbuf=image_pixbuf.scale_simple(
|
|
NOTIFICATION_IMAGE_SIZE,
|
|
NOTIFICATION_IMAGE_SIZE,
|
|
GdkPixbuf.InterpType.BILINEAR,
|
|
)
|
|
)
|
|
)
|
|
|
|
text_children = []
|
|
summary = self._notification.summary or ""
|
|
body = self._notification.body or ""
|
|
|
|
text_children.append(
|
|
Box(
|
|
orientation="h",
|
|
children=[
|
|
Label(label=summary, ellipsization="middle")
|
|
.build()
|
|
.add_style_class("summary")
|
|
.unwrap(),
|
|
],
|
|
h_expand=True,
|
|
v_expand=True,
|
|
).build(
|
|
lambda box, _: box.pack_end(
|
|
Button(
|
|
image=Image(icon_name="window-close-symbolic", icon_size=18),
|
|
v_align="center",
|
|
h_align="end",
|
|
on_clicked=lambda *_: self._notification.close(),
|
|
),
|
|
False,
|
|
False,
|
|
0,
|
|
)
|
|
)
|
|
)
|
|
|
|
if body:
|
|
body_text, body_is_markup = render_body_markup(body)
|
|
body_kwargs = {"markup": body_text} if body_is_markup else {"label": body_text}
|
|
text_children.append(
|
|
Label(
|
|
**body_kwargs,
|
|
line_wrap="word-char",
|
|
v_align="start",
|
|
h_align="start",
|
|
)
|
|
.build()
|
|
.add_style_class("body")
|
|
.unwrap()
|
|
)
|
|
|
|
body_container.add(
|
|
Box(
|
|
spacing=4,
|
|
orientation="v",
|
|
children=text_children,
|
|
h_expand=True,
|
|
v_expand=True,
|
|
)
|
|
)
|
|
|
|
self.add(body_container)
|
|
|
|
if actions := self._notification.actions:
|
|
self.add(
|
|
Box(
|
|
spacing=4,
|
|
orientation="h",
|
|
children=[
|
|
Button(
|
|
h_expand=True,
|
|
v_expand=True,
|
|
label=action.label,
|
|
on_clicked=lambda *_, action=action: action.invoke(),
|
|
)
|
|
for action in actions
|
|
],
|
|
)
|
|
)
|
|
|
|
self._notification.connect(
|
|
"closed",
|
|
lambda *_: (
|
|
parent.remove(self) if (parent := self.get_parent()) else None, # type: ignore
|
|
self.destroy(),
|
|
),
|
|
)
|
|
|
|
invoke_repeater(
|
|
timeout_ms,
|
|
lambda: self._notification.close("expired"),
|
|
initial_call=False,
|
|
)
|