mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-08-18 07:11:04 +02:00
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!
84 lines
2.5 KiB
Rust
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")
|
|
}
|