From 410569689cfd2f1e0f94724b6d0bcfe3129e79b0 Mon Sep 17 00:00:00 2001 From: ranfdev Date: Thu, 1 Feb 2024 14:48:15 +0100 Subject: [PATCH] remove deprecated MainContext channel --- src/application.rs | 48 +++++++++++++------------ src/async_utils.rs | 32 ++++++++--------- src/widgets/add_subscription_dialog.rs | 41 +++++++++++---------- src/widgets/message_row.rs | 23 ++++++------ src/widgets/subscription_info_dialog.rs | 16 ++++----- 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/src/application.rs b/src/application.rs index bcb0cf0..9f0b341 100644 --- a/src/application.rs +++ b/src/application.rs @@ -265,38 +265,40 @@ impl NotifyApplication { // `Invalid client serial` and it's broken. // Until https://github.com/flatpak/xdg-dbus-proxy/issues/46 is solved, I have to handle these things // in the main thread. Uff. - let (tx, rx) = glib::MainContext::channel(Default::default()); + + let (s, r) = async_channel::unbounded::(); + let app = self.clone(); - rx.attach(None, move |n: models::Notification| { - let gio_notif = gio::Notification::new(&n.title); - gio_notif.set_body(Some(&n.body)); + glib::MainContext::ref_thread_default().spawn_local(async move { + while let Ok(n) = r.recv().await { + let gio_notif = gio::Notification::new(&n.title); + gio_notif.set_body(Some(&n.body)); - let action_name = |a| { - let json = serde_json::to_string(a).unwrap(); - gio::Action::print_detailed_name("app.message-action", Some(&json.into())) - }; - for a in n.actions.iter() { - match a { - models::Action::View { label, .. } => { - gio_notif.add_button(&label, &action_name(a)) + let action_name = |a| { + let json = serde_json::to_string(a).unwrap(); + gio::Action::print_detailed_name("app.message-action", Some(&json.into())) + }; + for a in n.actions.iter() { + match a { + models::Action::View { label, .. } => { + gio_notif.add_button(&label, &action_name(a)) + } + models::Action::Http { label, .. } => { + gio_notif.add_button(&label, &action_name(a)) + } + _ => {} } - models::Action::Http { label, .. } => { - gio_notif.add_button(&label, &action_name(a)) - } - _ => {} } + + app.send_notification(None, &gio_notif); } - - app.send_notification(None, &gio_notif); - glib::ControlFlow::Continue }); - struct Proxies { - notification: glib::Sender, + notification: async_channel::Sender, } impl models::NotificationProxy for Proxies { fn send(&self, n: models::Notification) -> anyhow::Result<()> { - self.notification.send(n)?; + self.notification.send_blocking(n)?; Ok(()) } } @@ -317,7 +319,7 @@ impl NotifyApplication { Box::pin(rx) } } - let proxies = std::sync::Arc::new(Proxies { notification: tx }); + let proxies = std::sync::Arc::new(Proxies { notification: s }); ntfy_daemon::system_client::start( socket_path.to_owned(), dbpath.to_str().unwrap(), diff --git a/src/async_utils.rs b/src/async_utils.rs index 6c50d3b..166e1b3 100644 --- a/src/async_utils.rs +++ b/src/async_utils.rs @@ -1,28 +1,28 @@ use std::cell::Cell; use std::rc::Rc; -use glib::Receiver; use glib::SourceId; use gtk::glib; -pub fn debounce_channel( - duration: std::time::Duration, - source: Receiver, -) -> Receiver { - let (tx, rx) = glib::MainContext::channel(Default::default()); - let scheduled = Rc::new(Cell::new(None::)); - source.attach(None, move |data| { - if let Some(scheduled) = scheduled.take() { +#[derive(Clone)] +pub struct Debouncer { + scheduled: Rc>>, +} +impl Debouncer { + pub fn new() -> Self { + Self { + scheduled: Default::default(), + } + } + pub fn call(&self, duration: std::time::Duration, f: impl Fn() -> () + 'static) { + if let Some(scheduled) = self.scheduled.take() { scheduled.remove(); } - let tx = tx.clone(); - let scheduled_clone = scheduled.clone(); + let scheduled_clone = self.scheduled.clone(); let source_id = glib::source::timeout_add_local_once(duration, move || { - tx.send(data).unwrap(); + f(); scheduled_clone.take(); }); - scheduled.set(Some(source_id)); - glib::ControlFlow::Continue - }); - rx + self.scheduled.set(Some(source_id)); + } } diff --git a/src/widgets/add_subscription_dialog.rs b/src/widgets/add_subscription_dialog.rs index 509f74e..518e3c6 100644 --- a/src/widgets/add_subscription_dialog.rs +++ b/src/widgets/add_subscription_dialog.rs @@ -145,24 +145,29 @@ impl AddSubscriptionDialog { }, } - let (tx, rx) = glib::MainContext::channel(Default::default()); - let txc = tx.clone(); - topic_entry.delegate().unwrap().connect_changed(move |_| { - txc.send(()).unwrap(); - }); - let txc = tx.clone(); - server_entry.delegate().unwrap().connect_changed(move |_| { - txc.send(()).unwrap(); - }); - server_expander.connect_enable_expansion_notify(move |_| { - tx.send(()).unwrap(); - }); - let rx = crate::async_utils::debounce_channel(std::time::Duration::from_millis(500), rx); - let objc = obj.clone(); - rx.attach(None, move |_| { - objc.check_errors(); - glib::ControlFlow::Continue - }); + let debounced_error_check = { + let db = crate::async_utils::Debouncer::new(); + let objc = obj.clone(); + move || { + db.call(std::time::Duration::from_millis(500), move || { + objc.check_errors() + }); + } + }; + + let f = debounced_error_check.clone(); + topic_entry + .delegate() + .unwrap() + .connect_changed(move |_| f.clone()()); + let f = debounced_error_check.clone(); + server_entry + .delegate() + .unwrap() + .connect_changed(move |_| f.clone()()); + let f = debounced_error_check.clone(); + server_expander.connect_enable_expansion_notify(move |_| f.clone()()); + imp.widgets.replace(Widgets { topic_entry, server_expander, diff --git a/src/widgets/message_row.rs b/src/widgets/message_row.rs index 2b3371d..ef70b4f 100644 --- a/src/widgets/message_row.rs +++ b/src/widgets/message_row.rs @@ -9,6 +9,8 @@ use gtk::{gdk, gio, glib}; use ntfy_daemon::models; use tracing::error; +use crate::widgets::window::SpawnWithToast; + mod imp { use super::*; @@ -161,10 +163,10 @@ impl MessageRow { Ok(bytes) } fn build_image(&self, url: String) -> gtk::Picture { - let (tx, rx) = glib::MainContext::channel(Default::default()); + let (s, r) = async_channel::unbounded(); gio::spawn_blocking(move || { - if let Err(e) = - Self::fetch_image_bytes(&url).map(|bytes| tx.send(glib::Bytes::from_owned(bytes))) + if let Err(e) = Self::fetch_image_bytes(&url) + .map(|bytes| s.send_blocking(glib::Bytes::from_owned(bytes))) { error!(error = %e) } @@ -174,18 +176,15 @@ impl MessageRow { picture.set_can_shrink(true); picture.set_height_request(350); let picturec = picture.clone(); - rx.attach(Default::default(), move |b| { + + self.spawn_with_near_toast(async move { + let b = r.recv().await?; let stream = gio::MemoryInputStream::from_bytes(&b); - let pixbuf = match Pixbuf::from_stream(&stream, gio::Cancellable::NONE) { - Ok(res) => res, - Err(e) => { - error!(error = %e, "parsing image contents"); - return glib::ControlFlow::Break; - } - }; + let pixbuf = Pixbuf::from_stream(&stream, gio::Cancellable::NONE)?; picturec.set_paintable(Some(&gdk::Texture::for_pixbuf(&pixbuf))); - glib::ControlFlow::Break + Ok::<(), anyhow::Error>(()) }); + picture } fn build_action_btn(&self, action: models::Action) -> gtk::Button { diff --git a/src/widgets/subscription_info_dialog.rs b/src/widgets/subscription_info_dialog.rs index 19eed2f..fa46779 100644 --- a/src/widgets/subscription_info_dialog.rs +++ b/src/widgets/subscription_info_dialog.rs @@ -49,23 +49,19 @@ mod imp { self.parent_constructed(); let this = self.obj().clone(); - let (tx, rx) = glib::MainContext::channel(glib::Priority::default()); - let rx = - crate::async_utils::debounce_channel(std::time::Duration::from_millis(500), rx); - rx.attach(None, move |entry| { - this.update_display_name(&entry); - glib::ControlFlow::Continue - }); - - let this = self.obj().clone(); self.display_name_entry .set_text(&this.subscription().unwrap().display_name()); self.muted_switch_row .set_active(this.subscription().unwrap().muted()); + let debouncer = crate::async_utils::Debouncer::new(); self.display_name_entry.connect_changed({ move |entry| { - tx.send(entry.clone()).unwrap(); + let entry = entry.clone(); + let this = this.clone(); + debouncer.call(std::time::Duration::from_millis(500), move || { + this.update_display_name(&entry); + }) } }); let this = self.obj().clone();