feat: adjust label of autoswith depending on time of day

This commit is contained in:
Ashley Wulber 2024-03-27 17:39:26 -04:00 committed by Michael Murphy
parent bbf9eae401
commit e29d89b42f
8 changed files with 162 additions and 23 deletions

27
Cargo.lock generated
View file

@ -870,9 +870,9 @@ checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f"
[[package]]
name = "chrono"
version = "0.4.35"
version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
dependencies = [
"android-tzdata",
"iana-time-zone",
@ -1293,6 +1293,7 @@ dependencies = [
"anyhow",
"ashpd 0.7.0",
"async-channel",
"chrono",
"clap",
"color-eyre",
"cosmic-bg-config",
@ -1324,6 +1325,7 @@ dependencies = [
"serde",
"slotmap",
"static_init",
"sunrise",
"tokio",
"tracing",
"tracing-subscriber",
@ -5234,6 +5236,15 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
name = "sunrise"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3217c5830416956b1f2dc731f526150a82c144ebe83d2f0e78853c8356a22ada"
dependencies = [
"chrono",
]
[[package]]
name = "svg_fmt"
version = "0.4.2"
@ -5529,10 +5540,22 @@ dependencies = [
"pin-project-lite",
"signal-hook-registry",
"socket2 0.5.6",
"tokio-macros",
"tracing",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.55",
]
[[package]]
name = "toml"
version = "0.5.11"

View file

@ -3,6 +3,8 @@ members = ["cosmic-settings", "page", "pages/*"]
default-members = ["cosmic-settings"]
resolver = "2"
rust-version = "1.71.0"
sunrise_sunset = "1.0.1"
[workspace.dependencies.libcosmic]
git = "https://github.com/pop-os/libcosmic"

View file

@ -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" }

View file

@ -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),

View file

@ -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(

View 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."))
}

View file

@ -1,2 +1,4 @@
mod desktop_files;
pub use desktop_files::*;
mod daytime;
pub use daytime::*;

View file

@ -33,7 +33,10 @@ window-hint-accent = Active window hint color
window-hint-accent-toggle = Use theme accent color as active window hint
auto-switch = Automatically switch from Light to Dark mode
.desc = Switches to Light mode at sunrise
.sunrise = Switches to Light mode at sunrise
.sunset = Switches to Light mode at sunset
.next-sunrise = Switches to Light mode at next sunrise
.next-sunset = Switches to Light mode at next sunset
container-background = Container background
.desc-detail = Container background color is used for navigation sidebar, side drawer, dialogs and similar widgets. By default, it is automatically derived from the Application or window background.