From 428dafe37cced00cab0afa00ddc5f6c8ebccd428 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Wed, 22 May 2024 13:21:01 -0400 Subject: [PATCH] fix: retry portal when it fails, and only apply theme changes when there is a relevant change --- src/app/cosmic.rs | 9 ++++ src/theme/portal.rs | 120 +++++++++++++++++++++++++------------------- 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index 1560c56f..bdec9233 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -156,6 +156,7 @@ where } } + #[allow(clippy::too_many_lines)] fn subscription(&self) -> Subscription { let window_events = listen_with(|event, _| { match event { @@ -429,6 +430,11 @@ impl Cosmic { } Message::SystemThemeChange(keys, theme) => { + let cur_is_dark = THEME.with(|t| t.borrow().theme_type.is_dark()); + // Ignore updates if the current theme mode does not match. + if cur_is_dark != theme.cosmic().is_dark { + return iced::Command::none(); + } let cmd = self.app.system_theme_update(&keys, theme.cosmic()); // Record the last-known system theme in event that the current theme is custom. self.app.core_mut().system_theme = theme.clone(); @@ -472,6 +478,9 @@ impl Cosmic { }; } Message::SystemThemeModeChange(keys, mode) => { + if !keys.contains(&"is_dark") { + return iced::Command::none(); + } if THEME.with(|t| match t.borrow().theme_type { ThemeType::System { theme: _, diff --git a/src/theme/portal.rs b/src/theme/portal.rs index 277abd7b..b0fc5f84 100644 --- a/src/theme/portal.rs +++ b/src/theme/portal.rs @@ -1,7 +1,6 @@ use ashpd::desktop::settings::{ColorScheme, Contrast}; use ashpd::desktop::Color; use iced::futures::{self, select, FutureExt, SinkExt, StreamExt}; -use iced::Subscription; use iced_futures::subscription; use tracing::error; @@ -15,68 +14,83 @@ pub enum Desktop { pub fn desktop_settings() -> iced_futures::Subscription { subscription::channel(std::any::TypeId::of::(), 10, |mut tx| { async move { - let Ok(settings) = ashpd::desktop::settings::Settings::new().await else { - // wait forever - error!("Failed to create the settings proxy"); - futures::future::pending::<()>().await; - unreachable!() - }; - - match settings.color_scheme().await { - Ok(color_scheme) => { - let _ = tx.send(Desktop::ColorScheme(color_scheme)).await; - } - Err(err) => error!("Failed to get the color scheme {err:?}"), - }; - match settings.contrast().await { - Ok(contrast) => { - let _ = tx.send(Desktop::Contrast(contrast)).await; - } - Err(err) => error!("Failed to get the contrast {err:?}"), - }; - - let mut color_scheme_stream = settings.receive_color_scheme_changed().await.ok(); - if color_scheme_stream.is_none() { - error!("Failed to receive color scheme changes"); - } - - let mut contrast_stream = settings.receive_contrast_changed().await.ok(); - if contrast_stream.is_none() { - error!("Failed to receive contrast changes"); - } - + let mut attempts = 0; loop { - let next_color_scheme = async { - if let Some(s) = color_scheme_stream.as_mut() { - return s.next().await; + let Ok(settings) = ashpd::desktop::settings::Settings::new().await else { + error!("Failed to create the settings proxy"); + #[cfg(feature = "tokio")] + ::tokio::time::sleep(::tokio::time::Duration::from_secs(2_u64.pow(attempts))) + .await; + #[cfg(not(feature = "tokio"))] + { + pending::<()>().await; + unreachable!(); } - futures::future::pending().await + attempts += 1; + continue; }; - let next_contrast = async { - if let Some(s) = contrast_stream.as_mut() { - return s.next().await; + match settings.color_scheme().await { + Ok(color_scheme) => { + let _ = tx.send(Desktop::ColorScheme(color_scheme)).await; } - futures::future::pending().await + Err(err) => error!("Failed to get the color scheme {err:?}"), + }; + match settings.contrast().await { + Ok(contrast) => { + let _ = tx.send(Desktop::Contrast(contrast)).await; + } + Err(err) => error!("Failed to get the contrast {err:?}"), }; - select! { - s = next_color_scheme.fuse() => { - if let Some(s) = s { - _ = tx.send(Desktop::ColorScheme(s)).await; - } else { - color_scheme_stream = None; + let mut color_scheme_stream = settings.receive_color_scheme_changed().await.ok(); + if color_scheme_stream.is_none() { + error!("Failed to receive color scheme changes"); + } + + let mut contrast_stream = settings.receive_contrast_changed().await.ok(); + if contrast_stream.is_none() { + error!("Failed to receive contrast changes"); + } + + loop { + if color_scheme_stream.is_none() && contrast_stream.is_none() { + break; + } + let next_color_scheme = async { + if let Some(s) = color_scheme_stream.as_mut() { + return s.next().await; } - }, + futures::future::pending().await + }; - c = next_contrast.fuse() => { - if let Some(c) = c { - _ = tx.send(Desktop::Contrast(c)).await; - } else { - contrast_stream = None; + let next_contrast = async { + if let Some(s) = contrast_stream.as_mut() { + return s.next().await; } - } - }; + futures::future::pending().await + }; + + select! { + s = next_color_scheme.fuse() => { + if let Some(s) = s { + _ = tx.send(Desktop::ColorScheme(s)).await; + } else { + color_scheme_stream = None; + } + }, + + c = next_contrast.fuse() => { + if let Some(c) = c { + _ = tx.send(Desktop::Contrast(c)).await; + } else { + contrast_stream = None; + } + } + }; + // Reset the attempts counter if we successfully received a change + attempts = 0; + } } } })