1
0
Fork 0
mirror of https://github.com/Zedfrigg/ironbar.git synced 2025-08-18 07:11:04 +02:00
ironbar/src/dynamic_value/dynamic_bool.rs
Jake Stanger 9d18ce52f5
refactor: recv_glib dependency arrays
Adds a dependency array system to `recv_glib` which internally clones the passed deps and then passes by reference to the callback.

This cleans up a lot of the big `{}` blocks full of `widget.clone()` and removes a lot of boilerplate. Yay!
2025-05-26 22:46:25 +01:00

84 lines
2.5 KiB
Rust

#[cfg(feature = "ipc")]
use crate::Ironbar;
use crate::channels::{AsyncSenderExt, Dependency, MpscReceiverExt};
use crate::script::Script;
use crate::spawn;
use cfg_if::cfg_if;
use serde::Deserialize;
use tokio::sync::mpsc;
#[derive(Debug, Deserialize, Clone)]
#[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum DynamicBool {
/// Either a script or variable, to be determined.
Unknown(String),
Script(Script),
#[cfg(feature = "ipc")]
Variable(Box<str>),
}
impl DynamicBool {
pub fn subscribe<D, F>(self, deps: D, f: F)
where
D: Dependency,
D::Target: Clone + 'static,
F: FnMut(&D::Target, bool) + 'static,
{
let value = match self {
Self::Unknown(input) => {
if input.starts_with('#') {
cfg_if! {
if #[cfg(feature = "ipc")] {
Self::Variable(input.into())
} else {
Self::Unknown(input)
}
}
} else {
let script = Script::from(input.as_str());
Self::Script(script)
}
}
_ => self,
};
let (tx, rx) = mpsc::channel(32);
rx.recv_glib(deps, f);
spawn(async move {
match value {
DynamicBool::Script(script) => {
script
.run(None, |_, success| {
tx.send_spawn(success);
})
.await;
}
#[cfg(feature = "ipc")]
DynamicBool::Variable(variable) => {
let variable_manager = Ironbar::variable_manager();
let variable_name = variable[1..].into(); // remove hash
let mut rx = variable_manager.subscribe(variable_name);
while let Ok(value) = rx.recv().await {
let has_value = value.is_some_and(|s| is_truthy(&s));
tx.send_expect(has_value).await;
}
}
DynamicBool::Unknown(_) => unreachable!(),
}
});
}
}
/// Check if a string ironvar is 'truthy',
/// i.e should be evaluated to true.
///
/// This loosely follows the common JavaScript cases.
#[cfg(feature = "ipc")]
fn is_truthy(string: &str) -> bool {
!(string.is_empty() || string == "0" || string == "false")
}