2023-06-22 23:07:40 +01:00
|
|
|
use crate::script::Script;
|
2023-12-17 23:51:43 +00:00
|
|
|
use crate::{glib_recv_mpsc, spawn, try_send};
|
2023-12-08 22:39:27 +00:00
|
|
|
#[cfg(feature = "ipc")]
|
2023-12-17 23:51:43 +00:00
|
|
|
use crate::{send_async, Ironbar};
|
2023-06-22 23:07:40 +01:00
|
|
|
use cfg_if::cfg_if;
|
|
|
|
use serde::Deserialize;
|
2023-12-17 23:51:43 +00:00
|
|
|
use tokio::sync::mpsc;
|
2023-06-22 23:07:40 +01:00
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
pub enum DynamicBool {
|
|
|
|
/// Either a script or variable, to be determined.
|
|
|
|
Unknown(String),
|
|
|
|
Script(Script),
|
|
|
|
#[cfg(feature = "ipc")]
|
|
|
|
Variable(Box<str>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DynamicBool {
|
2023-12-17 23:51:43 +00:00
|
|
|
pub fn subscribe<F>(self, mut f: F)
|
2023-06-22 23:07:40 +01:00
|
|
|
where
|
2023-12-17 23:51:43 +00:00
|
|
|
F: FnMut(bool) + 'static,
|
2023-06-22 23:07:40 +01:00
|
|
|
{
|
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
2023-12-17 23:51:43 +00:00
|
|
|
let (tx, mut rx) = mpsc::channel(32);
|
2023-06-22 23:07:40 +01:00
|
|
|
|
2023-12-17 23:51:43 +00:00
|
|
|
glib_recv_mpsc!(rx, val => f(val));
|
2023-06-22 23:07:40 +01:00
|
|
|
|
|
|
|
spawn(async move {
|
|
|
|
match value {
|
|
|
|
DynamicBool::Script(script) => {
|
|
|
|
script
|
|
|
|
.run(None, |_, success| {
|
2023-12-17 23:51:43 +00:00
|
|
|
try_send!(tx, success);
|
2023-06-22 23:07:40 +01:00
|
|
|
})
|
|
|
|
.await;
|
|
|
|
}
|
|
|
|
#[cfg(feature = "ipc")]
|
|
|
|
DynamicBool::Variable(variable) => {
|
2023-12-08 22:39:27 +00:00
|
|
|
let variable_manager = Ironbar::variable_manager();
|
2023-06-22 23:07:40 +01:00
|
|
|
|
|
|
|
let variable_name = variable[1..].into(); // remove hash
|
|
|
|
let mut rx = crate::write_lock!(variable_manager).subscribe(variable_name);
|
|
|
|
|
|
|
|
while let Ok(value) = rx.recv().await {
|
|
|
|
let has_value = value.map(|s| is_truthy(&s)).unwrap_or_default();
|
2023-12-17 23:51:43 +00:00
|
|
|
send_async!(tx, has_value);
|
2023-06-22 23:07:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
DynamicBool::Unknown(_) => unreachable!(),
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-17 23:51:43 +00:00
|
|
|
/// Check if a string ironvar is 'truthy',
|
|
|
|
/// i.e should be evaluated to true.
|
|
|
|
///
|
|
|
|
/// This loosely follows the common JavaScript cases.
|
2023-06-22 23:07:40 +01:00
|
|
|
#[cfg(feature = "ipc")]
|
|
|
|
fn is_truthy(string: &str) -> bool {
|
|
|
|
!(string.is_empty() || string == "0" || string == "false")
|
|
|
|
}
|