From b443dd5b53897642e78d6b4d5109fc5300aecf19 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Wed, 8 May 2024 12:59:35 +0200 Subject: [PATCH] improv: create subscription channel for pages to send messages to --- Cargo.lock | 1 + Cargo.toml | 2 + cosmic-settings/Cargo.toml | 2 +- cosmic-settings/src/app.rs | 65 +++++++++++++++---- .../src/pages/desktop/appearance.rs | 6 +- .../src/pages/desktop/wallpaper/mod.rs | 6 +- cosmic-settings/src/pages/display/mod.rs | 18 +++-- .../src/pages/input/keyboard/mod.rs | 6 +- cosmic-settings/src/pages/system/about.rs | 6 +- page/Cargo.toml | 3 +- page/src/binder.rs | 8 ++- page/src/lib.rs | 7 +- 12 files changed, 104 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d725ecd..2bfa65e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1349,6 +1349,7 @@ dependencies = [ "once_cell", "regex", "slotmap", + "tokio", "url", ] diff --git a/Cargo.toml b/Cargo.toml index 3dc9ede..1acba77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,8 @@ resolver = "2" rust-version = "1.71.0" sunrise_sunset = "1.0.1" +[workspace.dependencies] +tokio = { version = "1.37.0", features = ["macros"] } [workspace.dependencies.libcosmic] git = "https://github.com/pop-os/libcosmic" diff --git a/cosmic-settings/Cargo.toml b/cosmic-settings/Cargo.toml index 5efcc41..d837107 100644 --- a/cosmic-settings/Cargo.toml +++ b/cosmic-settings/Cargo.toml @@ -6,7 +6,7 @@ license = "GPL-3.0" rust-version = "1.65.0" [dependencies] -tokio = { version = "1.35.1", features = ["macros"] } +tokio.workspace = true async-channel = "2.1.1" color-eyre = "0.6.2" cosmic-bg-config = { workspace = true } diff --git a/cosmic-settings/src/app.rs b/cosmic-settings/src/app.rs index 1e88c7c..2394fcb 100644 --- a/cosmic-settings/src/app.rs +++ b/cosmic-settings/src/app.rs @@ -6,16 +6,17 @@ use crate::pages::desktop::{ self, appearance, dock, panel::{ self, - applets_inner::{self, AppletsPage, APPLET_DND_ICON_ID}, + applets_inner::{self, APPLET_DND_ICON_ID}, inner as _panel, }, }; -use crate::pages::input::{self, keyboard}; -use crate::pages::{self, display, networking, sound, system, time}; +use crate::pages::input::{self}; +use crate::pages::{self, display, sound, system, time}; use crate::subscription::desktop_files; use crate::widget::{page_title, search_header}; use crate::PageCommands; use cosmic::app::DbusActivationMessage; +use cosmic::iced::futures::SinkExt; use cosmic::iced::Subscription; use cosmic::widget::{button, row, text_input}; use cosmic::{ @@ -42,6 +43,7 @@ pub struct SettingsApp { config: Config, core: Core, nav_model: nav_bar::Model, + page_sender: Option>, pages: page::Binder, search_active: bool, search_id: cosmic::widget::Id, @@ -77,19 +79,21 @@ impl SettingsApp { #[derive(Clone, Debug)] pub enum Message { + CloseContextDrawer, + DelayedInit(page::Entity), DesktopInfo, Error(String), + OpenContextDrawer(Cow<'static, str>), Page(page::Entity), PageMessage(crate::pages::Message), PanelConfig(CosmicPanelConfig), + RegisterSubscriptionSender(tokio::sync::mpsc::Sender), SearchActivate, SearchChanged(String), SearchClear, SearchSubmit, - SetWindowTitle, - OpenContextDrawer(Cow<'static, str>), - CloseContextDrawer, SetTheme(cosmic::theme::Theme), + SetWindowTitle, } impl cosmic::Application for SettingsApp { @@ -113,6 +117,7 @@ impl cosmic::Application for SettingsApp { config: Config::new(), core, nav_model: nav_bar::Model::default(), + page_sender: None, pages: page::Binder::default(), search_active: false, search_id: cosmic::widget::Id::unique(), @@ -136,9 +141,10 @@ impl cosmic::Application for SettingsApp { } .unwrap_or(desktop_id); - let command = app.activate_page(active_id); - - (app, command) + ( + app, + cosmic::command::message(cosmic::app::message::app(Message::DelayedInit(active_id))), + ) } fn nav_model(&self) -> Option<&nav_bar::Model> { @@ -208,6 +214,23 @@ impl cosmic::Application for SettingsApp { }); Subscription::batch(vec![ + // Creates a channel that listens to messages from pages. + // The sender is given back to the application so that it may pass it on. + cosmic::iced::subscription::channel( + std::any::TypeId::of::(), + 4, + move |mut output| async move { + let (tx, mut rx) = tokio::sync::mpsc::channel::(4); + + let _res = output.send(Message::RegisterSubscriptionSender(tx)).await; + + while let Some(event) = rx.recv().await { + let _res = output.send(Message::PageMessage(event)).await; + } + + futures::future::pending().await + }, + ), crate::subscription::daytime().map(|daytime| { Message::PageMessage(pages::Message::Appearance(appearance::Message::Daytime( daytime, @@ -409,6 +432,21 @@ impl cosmic::Application for SettingsApp { Message::Error(error) => { tracing::error!(error, "error occurred"); } + + Message::RegisterSubscriptionSender(sender) => { + self.page_sender = Some(sender); + } + + // It is necessary to delay init to allow time for the page sender to be initialized + Message::DelayedInit(active_id) => { + if self.page_sender.is_none() { + return cosmic::command::message(cosmic::app::message::app( + Message::DelayedInit(active_id), + )); + } + + return self.activate_page(active_id); + } } Command::none() @@ -438,7 +476,7 @@ impl cosmic::Application for SettingsApp { } else if let Some(sub_pages) = self.pages.sub_pages(self.active_page) { self.sub_page_view(sub_pages) } else { - panic!("page without sub-pages or content"); + return row::row().into(); }; let padding = if self.core.is_condensed() { @@ -518,9 +556,14 @@ impl SettingsApp { self.search_active = false; self.activate_navbar(page); + let sender = self + .page_sender + .clone() + .expect("sender should be available"); + let page_command = self .pages - .page_reload(page) + .on_enter(page, sender) .map(Message::PageMessage) .map(cosmic::app::Message::App); diff --git a/cosmic-settings/src/pages/desktop/appearance.rs b/cosmic-settings/src/pages/desktop/appearance.rs index 4f9dc72..bbd2703 100644 --- a/cosmic-settings/src/pages/desktop/appearance.rs +++ b/cosmic-settings/src/pages/desktop/appearance.rs @@ -1087,7 +1087,11 @@ impl page::Page for Page { .description(fl!("appearance", "desc")) } - fn reload(&mut self, _: page::Entity) -> Command { + fn on_enter( + &mut self, + _: page::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { command::future(fetch_icon_themes()).map(crate::pages::Message::Appearance) } diff --git a/cosmic-settings/src/pages/desktop/wallpaper/mod.rs b/cosmic-settings/src/pages/desktop/wallpaper/mod.rs index b65e6f0..c9d0718 100644 --- a/cosmic-settings/src/pages/desktop/wallpaper/mod.rs +++ b/cosmic-settings/src/pages/desktop/wallpaper/mod.rs @@ -207,7 +207,11 @@ impl page::Page for Page { .description(fl!("wallpaper", "desc")) } - fn reload(&mut self, _page: page::Entity) -> Command { + fn on_enter( + &mut self, + _page: page::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { let current_folder = self.config.current_folder().to_owned(); let recurse = self.categories.selected == Some(Category::Wallpapers); diff --git a/cosmic-settings/src/pages/display/mod.rs b/cosmic-settings/src/pages/display/mod.rs index ea4c2e9..93a724e 100644 --- a/cosmic-settings/src/pages/display/mod.rs +++ b/cosmic-settings/src/pages/display/mod.rs @@ -219,12 +219,20 @@ impl page::Page for Page { } #[cfg(not(feature = "test"))] - fn reload(&mut self, _page: page::Entity) -> Command { - command::future(reload()) + fn on_enter( + &mut self, + _page: page::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { + command::future(on_enter()) } #[cfg(feature = "test")] - fn reload(&mut self, _page: page::Entity) -> Command { + fn on_enter( + &mut self, + _page: page::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { command::future(async move { let mut randr = List::default(); @@ -287,7 +295,7 @@ impl Page { } return cosmic::command::future(async { - crate::Message::PageMessage(reload().await) + crate::Message::PageMessage(on_enter().await) }); } @@ -805,7 +813,7 @@ fn cache_rates(cached_rates: &mut Vec, rates: &[u32]) { .collect(); } -pub async fn reload() -> crate::pages::Message { +pub async fn on_enter() -> crate::pages::Message { let graphics_fut = graphics::fetch(); let randr_fut = cosmic_randr_shell::list(); let (graphics, randr) = futures::future::zip(graphics_fut, randr_fut).await; diff --git a/cosmic-settings/src/pages/input/keyboard/mod.rs b/cosmic-settings/src/pages/input/keyboard/mod.rs index 361ce1d..eb9fdb6 100644 --- a/cosmic-settings/src/pages/input/keyboard/mod.rs +++ b/cosmic-settings/src/pages/input/keyboard/mod.rs @@ -250,7 +250,11 @@ impl page::Page for Page { } } - fn reload(&mut self, _page: page::Entity) -> Command { + fn on_enter( + &mut self, + _page: page::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { self.xkb = super::get_config(&self.config, "xkb_config"); match xkb_data::keyboard_layouts() { Ok(keyboard_layouts) => { diff --git a/cosmic-settings/src/pages/system/about.rs b/cosmic-settings/src/pages/system/about.rs index a809433..e684135 100644 --- a/cosmic-settings/src/pages/system/about.rs +++ b/cosmic-settings/src/pages/system/about.rs @@ -43,7 +43,11 @@ impl page::Page for Page { .description(fl!("about", "desc")) } - fn reload(&mut self, _page: page::Entity) -> Command { + fn on_enter( + &mut self, + _page: page::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { command::future(async move { crate::pages::Message::About(Message::Info(Box::new(Info::load()))) }) diff --git a/page/Cargo.toml b/page/Cargo.toml index ca0b78a..da4f2fc 100644 --- a/page/Cargo.toml +++ b/page/Cargo.toml @@ -11,4 +11,5 @@ libcosmic = { workspace = true } generator = "0.7.5" downcast-rs = "1.2.0" once_cell = "1.19.0" -url = "2.5.0" +tokio.workspace = true +url = "2.5.0" \ No newline at end of file diff --git a/page/src/binder.rs b/page/src/binder.rs index 309eb0e..f256d7e 100644 --- a/page/src/binder.rs +++ b/page/src/binder.rs @@ -166,9 +166,13 @@ impl Binder { } /// Calls a page's load function to refresh its data. - pub fn page_reload(&mut self, id: crate::Entity) -> Command { + pub fn on_enter( + &mut self, + id: crate::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { if let Some(page) = self.page.get_mut(id) { - return page.reload(id); + return page.on_enter(id, sender); } Command::none() diff --git a/page/src/lib.rs b/page/src/lib.rs index 7df1d3d..00ea19a 100644 --- a/page/src/lib.rs +++ b/page/src/lib.rs @@ -59,9 +59,12 @@ pub trait Page: Downcast { } /// Reload page metadata via a Command. - #[must_use] #[allow(unused)] - fn reload(&mut self, page: crate::Entity) -> Command { + fn on_enter( + &mut self, + page: crate::Entity, + sender: tokio::sync::mpsc::Sender, + ) -> Command { Command::none() }