Add button to close notification

This commit is contained in:
Ian Douglas Scott 2021-09-13 13:48:17 -07:00
parent e0d1224173
commit a82c0a5577
4 changed files with 67 additions and 15 deletions

View file

@ -64,6 +64,9 @@ impl NotificationList {
notifications.connect_notification_recieved(clone!(@weak obj => move |notification| { notifications.connect_notification_recieved(clone!(@weak obj => move |notification| {
obj.handle_notification(&notification); obj.handle_notification(&notification);
})); }));
notifications.connect_notification_closed(clone!(@weak obj => move |id| {
obj.remove_notification(id);
}));
obj obj
} }
@ -74,7 +77,7 @@ impl NotificationList {
fn handle_notification(&self, notification: &Notification) { fn handle_notification(&self, notification: &Notification) {
let notification_widget = cascade! { let notification_widget = cascade! {
NotificationWidget::new(); NotificationWidget::new(&*self.inner().notifications);
..set_notification(notification); ..set_notification(notification);
}; };
@ -88,6 +91,12 @@ impl NotificationList {
self.inner().rows.borrow_mut().insert(notification.id, row); self.inner().rows.borrow_mut().insert(notification.id, row);
} }
fn remove_notification(&self, id: NotificationId) {
if let Some(row) = self.inner().rows.borrow_mut().remove(&id) {
self.inner().listbox.remove(&row);
}
}
fn id_for_row(&self, row: &gtk4::ListBoxRow) -> Option<NotificationId> { fn id_for_row(&self, row: &gtk4::ListBoxRow) -> Option<NotificationId> {
let rows = self.inner().rows.borrow(); let rows = self.inner().rows.borrow();
Some(*rows.iter().find(|(_, i)| i == &row)?.0) Some(*rows.iter().find(|(_, i)| i == &row)?.0)

View file

@ -31,19 +31,12 @@ impl ObjectImpl for NotificationPopoverInner {
})); }));
}); });
let notification_widget = cascade! {
NotificationWidget::new();
};
cascade! { cascade! {
obj; obj;
..set_autohide(false); ..set_autohide(false);
..set_has_arrow(false); ..set_has_arrow(false);
..set_offset(0, 12); ..set_offset(0, 12);
..set_child(Some(&notification_widget));
}; };
self.notification_widget.set(notification_widget);
} }
} }
@ -59,6 +52,12 @@ impl NotificationPopover {
pub fn new(notifications: &Notifications) -> Self { pub fn new(notifications: &Notifications) -> Self {
let obj = glib::Object::new::<Self>(&[]).unwrap(); let obj = glib::Object::new::<Self>(&[]).unwrap();
let notification_widget = cascade! {
NotificationWidget::new(notifications);
};
obj.set_child(Some(&notification_widget));
obj.inner().notification_widget.set(notification_widget);
// XXX disconnect? // XXX disconnect?
obj.inner().notifications.set(notifications.clone()); obj.inner().notifications.set(notifications.clone());
notifications.connect_notification_recieved(clone!(@weak obj => move |notification| { notifications.connect_notification_recieved(clone!(@weak obj => move |notification| {

View file

@ -1,14 +1,22 @@
use cascade::cascade; use cascade::cascade;
use gtk4::{glib, pango, prelude::*, subclass::prelude::*}; use gtk4::{
glib::{self, clone},
pango,
prelude::*,
subclass::prelude::*,
};
use std::cell::Cell;
use crate::deref_cell::DerefCell; use crate::deref_cell::DerefCell;
use crate::notifications::Notification; use crate::notifications::{Notification, NotificationId, Notifications};
#[derive(Default)] #[derive(Default)]
pub struct NotificationWidgetInner { pub struct NotificationWidgetInner {
box_: DerefCell<gtk4::Box>, box_: DerefCell<gtk4::Box>,
summary_label: DerefCell<gtk4::Label>, summary_label: DerefCell<gtk4::Label>,
body_label: DerefCell<gtk4::Label>, body_label: DerefCell<gtk4::Label>,
notifications: DerefCell<Notifications>,
id: Cell<Option<NotificationId>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
@ -37,10 +45,25 @@ impl ObjectImpl for NotificationWidgetInner {
}; };
let box_ = cascade! { let box_ = cascade! {
gtk4::Box::new(gtk4::Orientation::Vertical, 0); gtk4::Box::new(gtk4::Orientation::Horizontal, 0);
..set_parent(obj); ..set_parent(obj);
..append(&summary_label); ..append(&cascade! {
..append(&body_label); gtk4::Box::new(gtk4::Orientation::Vertical, 0);
..append(&summary_label);
..append(&body_label);
});
..append(&cascade! {
gtk4::Button::new();
..set_valign(gtk4::Align::Start);
..set_child(Some(&cascade! {
gtk4::Image::from_icon_name(Some("window-close-symbolic"));
}));
..connect_clicked(clone!(@weak obj => move |_| {
if let Some(id) = obj.inner().id.get() {
obj.inner().notifications.dismiss(id);
}
}));
});
}; };
self.box_.set(box_); self.box_.set(box_);
@ -61,8 +84,10 @@ glib::wrapper! {
} }
impl NotificationWidget { impl NotificationWidget {
pub fn new() -> Self { pub fn new(notifications: &Notifications) -> Self {
glib::Object::new(&[]).unwrap() let obj = glib::Object::new::<Self>(&[]).unwrap();
obj.inner().notifications.set(notifications.clone());
obj
} }
fn inner(&self) -> &NotificationWidgetInner { fn inner(&self) -> &NotificationWidgetInner {
@ -72,5 +97,6 @@ impl NotificationWidget {
pub fn set_notification(&self, notification: &Notification) { pub fn set_notification(&self, notification: &Notification) {
self.inner().summary_label.set_label(&notification.summary); self.inner().summary_label.set_label(&notification.summary);
self.inner().body_label.set_label(&notification.body); self.inner().body_label.set_label(&notification.body);
self.inner().id.set(Some(notification.id));
} }
} }

View file

@ -297,6 +297,8 @@ impl Notifications {
} }
fn close_notification(&self, id: NotificationId, reason: CloseReason) { fn close_notification(&self, id: NotificationId, reason: CloseReason) {
self.inner().notifications.borrow_mut().remove(&id);
self.emit_by_name("notification-closed", &[&id]).unwrap(); self.emit_by_name("notification-closed", &[&id]).unwrap();
if let Some(connection) = self.inner().connection.borrow().as_ref() { if let Some(connection) = self.inner().connection.borrow().as_ref() {
@ -312,6 +314,10 @@ impl Notifications {
} }
} }
pub fn dismiss(&self, id: NotificationId) {
self.close_notification(id, CloseReason::Dismiss);
}
fn bus_acquired(&self, connection: gio::DBusConnection, _name: &str) { fn bus_acquired(&self, connection: gio::DBusConnection, _name: &str) {
*self.inner().connection.borrow_mut() = Some(connection); *self.inner().connection.borrow_mut() = Some(connection);
} }
@ -396,4 +402,16 @@ impl Notifications {
}) })
.unwrap() .unwrap()
} }
pub fn connect_notification_closed<F: Fn(NotificationId) + 'static>(
&self,
cb: F,
) -> SignalHandlerId {
self.connect_local("notification-closed", false, move |values| {
let id = values[1].get().unwrap();
cb(id);
None
})
.unwrap()
}
} }