Files
Notify/src/error.rs
2024-02-13 15:41:23 +01:00

51 lines
1.5 KiB
Rust

use futures::Future;
use glib::subclass::prelude::*;
use gtk::prelude::*;
use gtk::{self, glib};
use crate::widgets::NotifyWindow;
pub type Error = anyhow::Error;
pub trait ErrorBoundaryProvider {
fn error_boundary(&self) -> ErrorBoundary;
}
impl<W: IsA<gtk::Widget>> ErrorBoundaryProvider for W {
fn error_boundary(&self) -> ErrorBoundary {
let direct_ancestor: Option<adw::ToastOverlay> = self
.ancestor(adw::ToastOverlay::static_type())
.and_downcast();
let win: Option<adw::ToastOverlay> = self
.ancestor(NotifyWindow::static_type())
.and_downcast()
.map(|win: NotifyWindow| win.imp().toast_overlay.clone());
let toast_overlay = direct_ancestor.or(win);
ErrorBoundary {
source: self.clone().into(),
boundary: toast_overlay,
}
}
}
pub struct ErrorBoundary {
source: gtk::Widget,
boundary: Option<adw::ToastOverlay>,
}
impl ErrorBoundary {
pub fn spawn<T>(self, f: impl Future<Output = Result<T, Error>> + 'static) {
glib::MainContext::ref_thread_default().spawn_local_with_priority(
glib::Priority::DEFAULT_IDLE,
async move {
if let Err(e) = f.await {
if let Some(boundary) = self.boundary {
boundary.add_toast(adw::Toast::builder().title(&e.to_string()).build());
}
tracing::error!(source=?self.source.type_().name(), error=?e);
}
},
);
}
}