From efe4ce2f5b514e4d553ab82c0c873dca7585c028 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Thu, 18 Jan 2024 19:01:11 -0500 Subject: [PATCH] refactor: config improvements --- cosmic-config/src/dbus.rs | 11 ++----- cosmic-config/src/lib.rs | 12 ++++++-- cosmic-config/src/subscription.rs | 35 ++++++++++++++-------- examples/applet/src/window.rs | 1 - src/app/core.rs | 34 +++++++++++++-------- src/app/cosmic.rs | 49 +++++-------------------------- src/theme/mod.rs | 13 ++++---- 7 files changed, 69 insertions(+), 86 deletions(-) diff --git a/cosmic-config/src/dbus.rs b/cosmic-config/src/dbus.rs index a2c4f5af..4977672b 100644 --- a/cosmic-config/src/dbus.rs +++ b/cosmic-config/src/dbus.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use crate::CosmicConfigEntry; +use crate::{CosmicConfigEntry, Update}; use cosmic_settings_daemon::{ConfigProxy, CosmicSettingsDaemonProxy}; use futures_util::SinkExt; use iced_futures::futures::{future::pending, StreamExt}; @@ -51,13 +51,6 @@ impl Watcher { } } -#[derive(Debug)] -pub struct Update { - pub errors: Vec, - pub keys: Vec<&'static str>, - pub config: T, -} - pub fn watcher_subscription( settings_daemon: CosmicSettingsDaemonProxy<'static>, config_id: &'static str, @@ -79,7 +72,7 @@ pub fn watcher_subscription config, Err((errors, default)) => { if !errors.is_empty() { - eprintln!("Failed to get config: {errors:?}"); + eprintln!("Error getting config: {config_id} {errors:?}"); } default } diff --git a/cosmic-config/src/lib.rs b/cosmic-config/src/lib.rs index 6a0d8b67..d6a4072b 100644 --- a/cosmic-config/src/lib.rs +++ b/cosmic-config/src/lib.rs @@ -32,6 +32,7 @@ pub enum Error { Notify(notify::Error), Ron(ron::Error), RonSpanned(ron::error::SpannedError), + GetKey(String, std::io::Error), } impl fmt::Display for Error { @@ -44,6 +45,7 @@ impl fmt::Display for Error { Self::Notify(err) => err.fmt(f), Self::Ron(err) => err.fmt(f), Self::RonSpanned(err) => err.fmt(f), + Self::GetKey(key, err) => write!(f, "failed to get key '{}': {}", key, err), } } } @@ -264,11 +266,11 @@ impl ConfigGet for Config { let key_path = self.key_path(key)?; let data = if key_path.is_file() { // Load user override - fs::read_to_string(key_path)? + fs::read_to_string(key_path).map_err(|err| Error::GetKey(key.to_string(), err))? } else { // Load system default let default_path = self.default_path(key)?; - fs::read_to_string(default_path)? + fs::read_to_string(default_path).map_err(|err| Error::GetKey(key.to_string(), err))? }; let t = ron::from_str(&data)?; Ok(t) @@ -339,3 +341,9 @@ where changed_keys: &[T], ) -> (Vec, Vec<&'static str>); } + +pub struct Update { + pub errors: Vec, + pub keys: Vec<&'static str>, + pub config: T, +} diff --git a/cosmic-config/src/subscription.rs b/cosmic-config/src/subscription.rs index 8c4f3c6d..e1e4f7ac 100644 --- a/cosmic-config/src/subscription.rs +++ b/cosmic-config/src/subscription.rs @@ -12,8 +12,7 @@ pub enum ConfigState { } pub enum ConfigUpdate { - Update(T), - UpdateError(T, Vec), + Update(crate::Update), Failed, } @@ -24,7 +23,7 @@ pub fn config_subscription< id: I, config_id: Cow<'static, str>, config_version: u64, -) -> iced_futures::Subscription<(I, Result, T)>)> { +) -> iced_futures::Subscription> { subscription::channel(id, 100, move |mut output| { let config_id = config_id.clone(); async move { @@ -45,7 +44,7 @@ pub fn config_state_subscription< id: I, config_id: Cow<'static, str>, config_version: u64, -) -> iced_futures::Subscription<(I, Result, T)>)> { +) -> iced_futures::Subscription> { subscription::channel(id, 100, move |mut output| { let config_id = config_id.clone(); async move { @@ -64,7 +63,7 @@ async fn start_listening< T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry, >( state: ConfigState, - output: &mut mpsc::Sender<(I, Result, T)>)>, + output: &mut mpsc::Sender>, id: I, ) -> ConfigState { use iced_futures::futures::{future::pending, StreamExt}; @@ -90,11 +89,21 @@ async fn start_listening< match T::get_entry(&config) { Ok(t) => { - _ = output.send((id, Ok(t.clone()))).await; + let update = crate::Update { + errors: Vec::new(), + keys: Vec::new(), + config: t.clone(), + }; + _ = output.send(update).await; ConfigState::Waiting(t, watcher, rx, config) } Err((errors, t)) => { - _ = output.send((id, Err((errors, t.clone())))).await; + let update = crate::Update { + errors: errors, + keys: Vec::new(), + config: t.clone(), + }; + _ = output.send(update).await; ConfigState::Waiting(t, watcher, rx, config) } } @@ -104,11 +113,13 @@ async fn start_listening< let (errors, changed) = conf_data.update_keys(&config, &keys); if !changed.is_empty() { - if errors.is_empty() { - _ = output.send((id, Ok(conf_data.clone()))).await; - } else { - _ = output.send((id, Err((errors, conf_data.clone())))).await; - } + _ = output + .send(crate::Update { + errors: errors, + keys: changed, + config: conf_data.clone(), + }) + .await; } ConfigState::Waiting(conf_data, watcher, rx, config) } diff --git a/examples/applet/src/window.rs b/examples/applet/src/window.rs index 45cd165f..c1706c65 100644 --- a/examples/applet/src/window.rs +++ b/examples/applet/src/window.rs @@ -13,7 +13,6 @@ const ID: &str = "com.system76.CosmicAppletExample"; pub struct Window { core: Core, popup: Option, - id_ctr: u128, example_row: bool, } diff --git a/src/app/core.rs b/src/app/core.rs index 764063d8..3ae740b6 100644 --- a/src/app/core.rs +++ b/src/app/core.rs @@ -214,27 +214,37 @@ impl Core { self.system_theme_mode } - #[cfg(feature = "dbus-config")] - pub fn watch_config( + pub fn watch_config< + T: CosmicConfigEntry + Send + Sync + Default + 'static + Clone + PartialEq, + >( &self, config_id: &'static str, - ) -> iced::Subscription> { + ) -> iced::Subscription> { + #[cfg(feature = "dbus-config")] if let Some(settings_daemon) = self.settings_daemon.clone() { - cosmic_config::dbus::watcher_subscription(settings_daemon, config_id, false) - } else { - iced::Subscription::none() + return cosmic_config::dbus::watcher_subscription(settings_daemon, config_id, false); } + cosmic_config::config_subscription( + std::any::TypeId::of::(), + std::borrow::Cow::Borrowed(config_id), + T::VERSION, + ) } - #[cfg(feature = "dbus-config")] - pub fn watch_state( + pub fn watch_state< + T: CosmicConfigEntry + Send + Sync + Default + 'static + Clone + PartialEq, + >( &self, state_id: &'static str, - ) -> iced::Subscription> { + ) -> iced::Subscription> { + #[cfg(feature = "dbus-config")] if let Some(settings_daemon) = self.settings_daemon.clone() { - cosmic_config::dbus::watcher_subscription(settings_daemon, state_id, true) - } else { - iced::Subscription::none() + return cosmic_config::dbus::watcher_subscription(settings_daemon, state_id, true); } + cosmic_config::config_subscription( + std::any::TypeId::of::(), + std::borrow::Cow::Borrowed(state_id), + T::VERSION, + ) } } diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index 45ebed2c..471db012 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -22,6 +22,7 @@ use iced::window; #[cfg(not(any(feature = "multi-window", feature = "wayland")))] use iced::Application as IcedApplication; use iced_futures::event::listen_raw; +use iced_futures::futures::executor::block_on; #[cfg(not(feature = "wayland"))] use iced_runtime::command::Action; #[cfg(not(feature = "wayland"))] @@ -66,9 +67,6 @@ pub enum Message { WmCapabilities(window::Id, WindowManagerCapabilities), /// Activate the application Activate(String), - #[cfg(feature = "dbus-config")] - /// dbus settings daemon setup - SettingsDaemon(zbus::Result>), } #[derive(Default)] @@ -85,16 +83,14 @@ where type Message = super::Message; type Theme = Theme; - fn new((core, flags): Self::Flags) -> (Self, iced::Command) { + fn new((mut core, flags): Self::Flags) -> (Self, iced::Command) { + #[cfg(feature = "dbus-config")] + { + core.settings_daemon = block_on(cosmic_config::dbus::settings_daemon_proxy()).ok(); + } + let (model, command) = T::init(core, flags); - #[cfg(feature = "dbus-config")] - let command = iced::Command::batch(vec![ - command, - iced::Command::perform(cosmic_config::dbus::settings_daemon_proxy(), |p| { - super::Message::Cosmic(super::cosmic::Message::SettingsDaemon(p)) - }), - ]); (Self::new(model), command) } @@ -176,7 +172,6 @@ where keyboard_nav::subscription() .map(Message::KeyboardNav) .map(super::Message::Cosmic), - #[cfg(feature = "dbus-config")] self.app .core() .watch_config::(if self.app.core().system_theme_mode.is_dark { @@ -191,27 +186,6 @@ where Message::SystemThemeChange(crate::theme::Theme::system(Arc::new(update.config))) }) .map(super::Message::Cosmic), - #[cfg(not(feature = "dbus-config"))] - theme::subscription(self.app.core().system_theme_mode.is_dark) - .map(Message::SystemThemeChange) - .map(super::Message::Cosmic), - #[cfg(not(feature = "dbus-config"))] - cosmic_config::config_subscription::<_, cosmic_theme::ThemeMode>( - 0, - cosmic_theme::THEME_MODE_ID.into(), - cosmic_theme::ThemeMode::version(), - ) - .map(|(_, u)| match u { - Ok(t) => Message::SystemThemeModeChange(t), - Err((errors, t)) => { - for e in errors { - tracing::error!("{e}"); - } - Message::SystemThemeModeChange(t) - } - }) - .map(super::Message::Cosmic), - #[cfg(feature = "dbus-config")] self.app .core() .watch_config::(cosmic_theme::THEME_MODE_ID) @@ -422,15 +396,6 @@ impl Cosmic { _token, ); } - #[cfg(feature = "dbus-config")] - Message::SettingsDaemon(p) => match p { - Ok(p) => { - self.app.core_mut().settings_daemon = Some(p); - } - Err(e) => { - tracing::error!("Failed to connect to settings daemon: {e}"); - } - }, } iced::Command::none() diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 42a344ac..ebc90d99 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -85,15 +85,12 @@ pub fn subscription(is_dark: bool) -> Subscription { .into(), crate::cosmic_theme::Theme::version(), ) - .map(|(_, res)| { - let theme = res.unwrap_or_else(|(errors, theme)| { - for err in errors { - tracing::error!("{:?}", err); - } - theme - }); + .map(|res| { + for err in res.errors { + tracing::error!("{:?}", err); + } - Theme::system(Arc::new(theme)) + Theme::system(Arc::new(res.config)) }) }