feat: adjust label of autoswith depending on time of day
This commit is contained in:
parent
bbf9eae401
commit
e29d89b42f
8 changed files with 162 additions and 23 deletions
|
|
@ -6,6 +6,7 @@ license = "GPL-3.0"
|
|||
rust-version = "1.65.0"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.35.1", features = ["macros"] }
|
||||
async-channel = "2.1.1"
|
||||
color-eyre = "0.6.2"
|
||||
cosmic-bg-config = { workspace = true }
|
||||
|
|
@ -20,16 +21,17 @@ dirs = "5.0.1"
|
|||
generator = "=0.7.5"
|
||||
i18n-embed-fl = "0.7.0"
|
||||
itertools = "0.12.0"
|
||||
libcosmic = {workspace = true}
|
||||
libcosmic = { workspace = true }
|
||||
once_cell = "1.19.0"
|
||||
regex = "1.10.3"
|
||||
rust-embed = "8.2.0"
|
||||
slotmap = "1.0.7"
|
||||
tokio = "1.35.1"
|
||||
downcast-rs = "1.2.0"
|
||||
cosmic-comp-config = { workspace = true }
|
||||
# TODO: migrate this dependency to the pages/desktop crate.
|
||||
cosmic-panel-config = { workspace = true }
|
||||
chrono = "0.4.37"
|
||||
sunrise = "1.0.1"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
url = "2.5.0"
|
||||
|
|
@ -41,7 +43,7 @@ serde = { version = "1.0.196", features = ["derive"] }
|
|||
ashpd = { version = "0.7", default-features = false }
|
||||
ron = "0.8"
|
||||
static_init = "1.0.3"
|
||||
clap = {version = "4.4.18", features = ["derive"] }
|
||||
clap = { version = "4.4.18", features = ["derive"] }
|
||||
itoa = "1.0.10"
|
||||
futures = { package = "futures-lite", version = "2.2.0" }
|
||||
|
||||
|
|
|
|||
|
|
@ -225,6 +225,11 @@ impl cosmic::Application for SettingsApp {
|
|||
});
|
||||
|
||||
Subscription::batch(vec![
|
||||
crate::subscription::daytime().map(|daytime| {
|
||||
Message::PageMessage(pages::Message::Appearance(appearance::Message::Daytime(
|
||||
daytime,
|
||||
)))
|
||||
}),
|
||||
wayland_events,
|
||||
// Watch for changes to installed desktop entries
|
||||
desktop_files(0).map(|_| Message::DesktopInfo),
|
||||
|
|
|
|||
|
|
@ -76,8 +76,12 @@ pub struct Page {
|
|||
theme_builder_needs_update: bool,
|
||||
theme_builder_config: Option<Config>,
|
||||
|
||||
auto_switch_descs: [Cow<'static, str>; 4],
|
||||
|
||||
tk: CosmicTk,
|
||||
tk_config: Option<Config>,
|
||||
|
||||
day_time: bool,
|
||||
}
|
||||
|
||||
impl Default for Page {
|
||||
|
|
@ -192,6 +196,13 @@ impl
|
|||
theme_builder,
|
||||
tk_config,
|
||||
tk,
|
||||
day_time: true,
|
||||
auto_switch_descs: [
|
||||
fl!("auto-switch", "sunrise").into(),
|
||||
fl!("auto-switch", "sunset").into(),
|
||||
fl!("auto-switch", "next-sunrise").into(),
|
||||
fl!("auto-switch", "next-sunset").into(),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -275,6 +286,7 @@ pub enum Message {
|
|||
StartImport,
|
||||
UseDefaultWindowHint(bool),
|
||||
WindowHintSize(spin_button::Message),
|
||||
Daytime(bool),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -434,10 +446,6 @@ impl Page {
|
|||
let ret = match message {
|
||||
Message::DarkMode(enabled) => {
|
||||
if let Some(config) = self.theme_mode_config.as_ref() {
|
||||
// must disable auto switch if the user manually switches the theme
|
||||
if let Err(err) = self.theme_mode.set_auto_switch(config, false) {
|
||||
tracing::error!(?err, "Error setting auto switch");
|
||||
}
|
||||
if let Err(err) = self.theme_mode.set_is_dark(config, enabled) {
|
||||
tracing::error!(?err, "Error setting dark mode");
|
||||
}
|
||||
|
|
@ -821,6 +829,10 @@ impl Page {
|
|||
}
|
||||
Command::none()
|
||||
}
|
||||
Message::Daytime(day_time) => {
|
||||
self.day_time = day_time;
|
||||
Command::none()
|
||||
}
|
||||
};
|
||||
|
||||
if self.theme_builder_needs_update {
|
||||
|
|
@ -879,9 +891,9 @@ impl Page {
|
|||
fn reload_theme_mode(&mut self) {
|
||||
let icon_themes = std::mem::take(&mut self.icon_themes);
|
||||
let icon_theme_active = self.icon_theme_active.take();
|
||||
|
||||
let day_time = self.day_time;
|
||||
*self = Self::from((self.theme_mode_config.clone(), self.theme_mode));
|
||||
|
||||
self.day_time = day_time;
|
||||
self.icon_themes = icon_themes;
|
||||
self.icon_theme_active = icon_theme_active;
|
||||
}
|
||||
|
|
@ -1023,26 +1035,25 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
|||
.descriptions(vec![
|
||||
// 0
|
||||
fl!("auto-switch").into(),
|
||||
fl!("auto-switch", "desc").into(),
|
||||
//2
|
||||
//1
|
||||
fl!("accent-color").into(),
|
||||
//3
|
||||
//2
|
||||
fl!("app-background").into(),
|
||||
//4
|
||||
//3
|
||||
fl!("container-background").into(),
|
||||
fl!("container-background", "desc").into(),
|
||||
fl!("container-background", "desc-detail").into(),
|
||||
fl!("container-background", "reset").into(),
|
||||
// 8
|
||||
// 7
|
||||
fl!("text-tint").into(),
|
||||
fl!("text-tint", "desc").into(),
|
||||
// 10
|
||||
// 9
|
||||
fl!("control-tint").into(),
|
||||
fl!("control-tint", "desc").into(),
|
||||
// 12
|
||||
// 11
|
||||
fl!("window-hint-accent-toggle").into(),
|
||||
fl!("window-hint-accent").into(),
|
||||
// 14
|
||||
// 13
|
||||
fl!("dark").into(),
|
||||
fl!("light").into(),
|
||||
])
|
||||
|
|
@ -1067,7 +1078,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
|||
.padding([8, 0])
|
||||
.selected(page.theme_mode.is_dark)
|
||||
.on_press(Message::DarkMode(true)),
|
||||
text(&*descriptions[14])
|
||||
text(&*descriptions[13])
|
||||
]
|
||||
.spacing(8)
|
||||
.width(Length::FillPortion(1))
|
||||
|
|
@ -1082,7 +1093,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
|||
.selected(!page.theme_mode.is_dark)
|
||||
.padding([8, 0])
|
||||
.on_press(Message::DarkMode(false)),
|
||||
text(&*descriptions[15])
|
||||
text(&*descriptions[14])
|
||||
]
|
||||
.spacing(8)
|
||||
.width(Length::FillPortion(1))
|
||||
|
|
@ -1097,7 +1108,18 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
|||
)
|
||||
.add(
|
||||
settings::item::builder(&*descriptions[0])
|
||||
.description(&*descriptions[1])
|
||||
.description(
|
||||
if page.day_time && !page.theme_mode.is_dark {
|
||||
&page.auto_switch_descs[0]
|
||||
} else if !page.day_time && page.theme_mode.is_dark {
|
||||
&page.auto_switch_descs[1]
|
||||
} else if page.day_time && page.theme_mode.is_dark {
|
||||
&page.auto_switch_descs[2]
|
||||
} else {
|
||||
&page.auto_switch_descs[3]
|
||||
}
|
||||
.clone(),
|
||||
)
|
||||
.toggler(page.theme_mode.auto_switch, Message::Autoswitch),
|
||||
)
|
||||
.add(
|
||||
|
|
|
|||
80
cosmic-settings/src/subscription/daytime.rs
Normal file
80
cosmic-settings/src/subscription/daytime.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
use std::any::TypeId;
|
||||
|
||||
use ashpd::desktop::location::{Location, LocationProxy};
|
||||
use chrono::Datelike;
|
||||
use cosmic::iced::{
|
||||
self,
|
||||
futures::{channel::mpsc::Sender, future, SinkExt, StreamExt},
|
||||
};
|
||||
use sunrise::sunrise_sunset;
|
||||
use tokio::select;
|
||||
|
||||
pub fn daytime() -> cosmic::iced::Subscription<bool> {
|
||||
struct Sunset;
|
||||
iced::subscription::channel(TypeId::of::<Sunset>(), 2, |tx| async {
|
||||
if let Err(err) = inner(tx).await {
|
||||
tracing::error!("Sunset subscription error: {:?}", err);
|
||||
}
|
||||
future::pending().await
|
||||
})
|
||||
}
|
||||
|
||||
enum Event {
|
||||
Daytime,
|
||||
LocationUpdated(Location),
|
||||
}
|
||||
|
||||
async fn inner(mut tx: Sender<bool>) -> anyhow::Result<()> {
|
||||
let location_proxy = LocationProxy::new().await?;
|
||||
let mut updates = location_proxy.receive_location_updated().await?;
|
||||
|
||||
let mut next = updates.next().await.map(Event::LocationUpdated);
|
||||
let mut loc = None;
|
||||
|
||||
while let Some(e) = next {
|
||||
match e {
|
||||
Event::LocationUpdated(l) => {
|
||||
loc = Some(l);
|
||||
}
|
||||
Event::Daytime => {}
|
||||
};
|
||||
let Some(loc) = loc.as_ref() else {
|
||||
break;
|
||||
};
|
||||
let (lat, long) = (loc.latitude(), loc.longitude());
|
||||
let now = chrono::Local::now();
|
||||
let date = now.date_naive();
|
||||
let (sunrise, sunset) = sunrise_sunset(lat, long, date.year(), date.month0(), date.day0());
|
||||
let now_in_seconds = now.timestamp();
|
||||
let daytime = now_in_seconds >= sunrise && now_in_seconds <= sunset;
|
||||
tx.send(daytime).await?;
|
||||
|
||||
let sleep = if daytime {
|
||||
sunset - now_in_seconds
|
||||
} else if now_in_seconds < sunset {
|
||||
sunrise - now_in_seconds
|
||||
} else {
|
||||
let tmrw = now + chrono::Duration::days(1);
|
||||
let tmrw_date = tmrw.date_naive();
|
||||
let (tmrw_sunrise, _) = sunrise_sunset(
|
||||
lat,
|
||||
long,
|
||||
tmrw_date.year(),
|
||||
tmrw_date.month0(),
|
||||
tmrw_date.day0(),
|
||||
);
|
||||
tmrw_sunrise - now_in_seconds
|
||||
};
|
||||
next = select! {
|
||||
() = tokio::time::sleep(tokio::time::Duration::from_secs(sleep as u64)) => {
|
||||
Some(Event::Daytime)
|
||||
},
|
||||
l = updates.next() => if let Some(l) = l {
|
||||
Some(Event::LocationUpdated(l))
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(anyhow::anyhow!("Location updates ended unexpectedly."))
|
||||
}
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
mod desktop_files;
|
||||
pub use desktop_files::*;
|
||||
mod daytime;
|
||||
pub use daytime::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue