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
27
Cargo.lock
generated
27
Cargo.lock
generated
|
|
@ -870,9 +870,9 @@ checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.35"
|
version = "0.4.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
|
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
|
@ -1293,6 +1293,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ashpd 0.7.0",
|
"ashpd 0.7.0",
|
||||||
"async-channel",
|
"async-channel",
|
||||||
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"cosmic-bg-config",
|
"cosmic-bg-config",
|
||||||
|
|
@ -1324,6 +1325,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"static_init",
|
"static_init",
|
||||||
|
"sunrise",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
|
@ -5234,6 +5236,15 @@ version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sunrise"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3217c5830416956b1f2dc731f526150a82c144ebe83d2f0e78853c8356a22ada"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "svg_fmt"
|
name = "svg_fmt"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -5529,10 +5540,22 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2 0.5.6",
|
"socket2 0.5.6",
|
||||||
|
"tokio-macros",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.48.0",
|
"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]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ members = ["cosmic-settings", "page", "pages/*"]
|
||||||
default-members = ["cosmic-settings"]
|
default-members = ["cosmic-settings"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
rust-version = "1.71.0"
|
rust-version = "1.71.0"
|
||||||
|
sunrise_sunset = "1.0.1"
|
||||||
|
|
||||||
|
|
||||||
[workspace.dependencies.libcosmic]
|
[workspace.dependencies.libcosmic]
|
||||||
git = "https://github.com/pop-os/libcosmic"
|
git = "https://github.com/pop-os/libcosmic"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ license = "GPL-3.0"
|
||||||
rust-version = "1.65.0"
|
rust-version = "1.65.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tokio = { version = "1.35.1", features = ["macros"] }
|
||||||
async-channel = "2.1.1"
|
async-channel = "2.1.1"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
cosmic-bg-config = { workspace = true }
|
cosmic-bg-config = { workspace = true }
|
||||||
|
|
@ -20,16 +21,17 @@ dirs = "5.0.1"
|
||||||
generator = "=0.7.5"
|
generator = "=0.7.5"
|
||||||
i18n-embed-fl = "0.7.0"
|
i18n-embed-fl = "0.7.0"
|
||||||
itertools = "0.12.0"
|
itertools = "0.12.0"
|
||||||
libcosmic = {workspace = true}
|
libcosmic = { workspace = true }
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
regex = "1.10.3"
|
regex = "1.10.3"
|
||||||
rust-embed = "8.2.0"
|
rust-embed = "8.2.0"
|
||||||
slotmap = "1.0.7"
|
slotmap = "1.0.7"
|
||||||
tokio = "1.35.1"
|
|
||||||
downcast-rs = "1.2.0"
|
downcast-rs = "1.2.0"
|
||||||
cosmic-comp-config = { workspace = true }
|
cosmic-comp-config = { workspace = true }
|
||||||
# TODO: migrate this dependency to the pages/desktop crate.
|
# TODO: migrate this dependency to the pages/desktop crate.
|
||||||
cosmic-panel-config = { workspace = true }
|
cosmic-panel-config = { workspace = true }
|
||||||
|
chrono = "0.4.37"
|
||||||
|
sunrise = "1.0.1"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
|
|
@ -41,7 +43,7 @@ serde = { version = "1.0.196", features = ["derive"] }
|
||||||
ashpd = { version = "0.7", default-features = false }
|
ashpd = { version = "0.7", default-features = false }
|
||||||
ron = "0.8"
|
ron = "0.8"
|
||||||
static_init = "1.0.3"
|
static_init = "1.0.3"
|
||||||
clap = {version = "4.4.18", features = ["derive"] }
|
clap = { version = "4.4.18", features = ["derive"] }
|
||||||
itoa = "1.0.10"
|
itoa = "1.0.10"
|
||||||
futures = { package = "futures-lite", version = "2.2.0" }
|
futures = { package = "futures-lite", version = "2.2.0" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,11 @@ impl cosmic::Application for SettingsApp {
|
||||||
});
|
});
|
||||||
|
|
||||||
Subscription::batch(vec![
|
Subscription::batch(vec![
|
||||||
|
crate::subscription::daytime().map(|daytime| {
|
||||||
|
Message::PageMessage(pages::Message::Appearance(appearance::Message::Daytime(
|
||||||
|
daytime,
|
||||||
|
)))
|
||||||
|
}),
|
||||||
wayland_events,
|
wayland_events,
|
||||||
// Watch for changes to installed desktop entries
|
// Watch for changes to installed desktop entries
|
||||||
desktop_files(0).map(|_| Message::DesktopInfo),
|
desktop_files(0).map(|_| Message::DesktopInfo),
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,12 @@ pub struct Page {
|
||||||
theme_builder_needs_update: bool,
|
theme_builder_needs_update: bool,
|
||||||
theme_builder_config: Option<Config>,
|
theme_builder_config: Option<Config>,
|
||||||
|
|
||||||
|
auto_switch_descs: [Cow<'static, str>; 4],
|
||||||
|
|
||||||
tk: CosmicTk,
|
tk: CosmicTk,
|
||||||
tk_config: Option<Config>,
|
tk_config: Option<Config>,
|
||||||
|
|
||||||
|
day_time: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Page {
|
impl Default for Page {
|
||||||
|
|
@ -192,6 +196,13 @@ impl
|
||||||
theme_builder,
|
theme_builder,
|
||||||
tk_config,
|
tk_config,
|
||||||
tk,
|
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,
|
StartImport,
|
||||||
UseDefaultWindowHint(bool),
|
UseDefaultWindowHint(bool),
|
||||||
WindowHintSize(spin_button::Message),
|
WindowHintSize(spin_button::Message),
|
||||||
|
Daytime(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
@ -434,10 +446,6 @@ impl Page {
|
||||||
let ret = match message {
|
let ret = match message {
|
||||||
Message::DarkMode(enabled) => {
|
Message::DarkMode(enabled) => {
|
||||||
if let Some(config) = self.theme_mode_config.as_ref() {
|
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) {
|
if let Err(err) = self.theme_mode.set_is_dark(config, enabled) {
|
||||||
tracing::error!(?err, "Error setting dark mode");
|
tracing::error!(?err, "Error setting dark mode");
|
||||||
}
|
}
|
||||||
|
|
@ -821,6 +829,10 @@ impl Page {
|
||||||
}
|
}
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
Message::Daytime(day_time) => {
|
||||||
|
self.day_time = day_time;
|
||||||
|
Command::none()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.theme_builder_needs_update {
|
if self.theme_builder_needs_update {
|
||||||
|
|
@ -879,9 +891,9 @@ impl Page {
|
||||||
fn reload_theme_mode(&mut self) {
|
fn reload_theme_mode(&mut self) {
|
||||||
let icon_themes = std::mem::take(&mut self.icon_themes);
|
let icon_themes = std::mem::take(&mut self.icon_themes);
|
||||||
let icon_theme_active = self.icon_theme_active.take();
|
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 = Self::from((self.theme_mode_config.clone(), self.theme_mode));
|
||||||
|
self.day_time = day_time;
|
||||||
self.icon_themes = icon_themes;
|
self.icon_themes = icon_themes;
|
||||||
self.icon_theme_active = icon_theme_active;
|
self.icon_theme_active = icon_theme_active;
|
||||||
}
|
}
|
||||||
|
|
@ -1023,26 +1035,25 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
||||||
.descriptions(vec![
|
.descriptions(vec![
|
||||||
// 0
|
// 0
|
||||||
fl!("auto-switch").into(),
|
fl!("auto-switch").into(),
|
||||||
fl!("auto-switch", "desc").into(),
|
//1
|
||||||
//2
|
|
||||||
fl!("accent-color").into(),
|
fl!("accent-color").into(),
|
||||||
//3
|
//2
|
||||||
fl!("app-background").into(),
|
fl!("app-background").into(),
|
||||||
//4
|
//3
|
||||||
fl!("container-background").into(),
|
fl!("container-background").into(),
|
||||||
fl!("container-background", "desc").into(),
|
fl!("container-background", "desc").into(),
|
||||||
fl!("container-background", "desc-detail").into(),
|
fl!("container-background", "desc-detail").into(),
|
||||||
fl!("container-background", "reset").into(),
|
fl!("container-background", "reset").into(),
|
||||||
// 8
|
// 7
|
||||||
fl!("text-tint").into(),
|
fl!("text-tint").into(),
|
||||||
fl!("text-tint", "desc").into(),
|
fl!("text-tint", "desc").into(),
|
||||||
// 10
|
// 9
|
||||||
fl!("control-tint").into(),
|
fl!("control-tint").into(),
|
||||||
fl!("control-tint", "desc").into(),
|
fl!("control-tint", "desc").into(),
|
||||||
// 12
|
// 11
|
||||||
fl!("window-hint-accent-toggle").into(),
|
fl!("window-hint-accent-toggle").into(),
|
||||||
fl!("window-hint-accent").into(),
|
fl!("window-hint-accent").into(),
|
||||||
// 14
|
// 13
|
||||||
fl!("dark").into(),
|
fl!("dark").into(),
|
||||||
fl!("light").into(),
|
fl!("light").into(),
|
||||||
])
|
])
|
||||||
|
|
@ -1067,7 +1078,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
||||||
.padding([8, 0])
|
.padding([8, 0])
|
||||||
.selected(page.theme_mode.is_dark)
|
.selected(page.theme_mode.is_dark)
|
||||||
.on_press(Message::DarkMode(true)),
|
.on_press(Message::DarkMode(true)),
|
||||||
text(&*descriptions[14])
|
text(&*descriptions[13])
|
||||||
]
|
]
|
||||||
.spacing(8)
|
.spacing(8)
|
||||||
.width(Length::FillPortion(1))
|
.width(Length::FillPortion(1))
|
||||||
|
|
@ -1082,7 +1093,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
||||||
.selected(!page.theme_mode.is_dark)
|
.selected(!page.theme_mode.is_dark)
|
||||||
.padding([8, 0])
|
.padding([8, 0])
|
||||||
.on_press(Message::DarkMode(false)),
|
.on_press(Message::DarkMode(false)),
|
||||||
text(&*descriptions[15])
|
text(&*descriptions[14])
|
||||||
]
|
]
|
||||||
.spacing(8)
|
.spacing(8)
|
||||||
.width(Length::FillPortion(1))
|
.width(Length::FillPortion(1))
|
||||||
|
|
@ -1097,7 +1108,18 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
|
||||||
)
|
)
|
||||||
.add(
|
.add(
|
||||||
settings::item::builder(&*descriptions[0])
|
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),
|
.toggler(page.theme_mode.auto_switch, Message::Autoswitch),
|
||||||
)
|
)
|
||||||
.add(
|
.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;
|
mod desktop_files;
|
||||||
pub use desktop_files::*;
|
pub use desktop_files::*;
|
||||||
|
mod daytime;
|
||||||
|
pub use daytime::*;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@ window-hint-accent = Active window hint color
|
||||||
window-hint-accent-toggle = Use theme accent color as active window hint
|
window-hint-accent-toggle = Use theme accent color as active window hint
|
||||||
|
|
||||||
auto-switch = Automatically switch from Light to Dark mode
|
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
|
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.
|
.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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue