diff --git a/src/bundle.rs b/src/bundle.rs index 16a3295..6c17c3f 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -2,9 +2,32 @@ mod menu; mod server; pub use menu::Tray; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use std::process::Command; use tokio::sync::mpsc::UnboundedSender; +fn get_config_watchers(config_path: &Path) -> Option> { + let mut config_path = config_path.parent()?.to_path_buf(); + config_path.push("bundle-config.toml"); + debug!("Reading bundle config at {}", config_path.display()); + + let config_content = std::fs::read_to_string(&config_path).ok()?; + let toml_content: toml::Value = toml::from_str(&config_content).ok()?; + + trace!("Bundle config: {toml_content:?}"); + + Some( + toml_content + .get("watchers")? + .get("autostart")? + .as_array()? + .iter() + .filter_map(|value| value.as_str()) + .map(std::string::ToString::to_string) + .collect(), + ) +} + pub async fn run( host: String, port: u32, @@ -12,13 +35,22 @@ pub async fn run( no_tray: bool, shutdown_sender: UnboundedSender<()>, ) { + let watchers: Vec = + get_config_watchers(config_file.parent().unwrap()).unwrap_or_default(); + + for watcher in &watchers { + debug!("Starting an external watcher {}", watcher); + let _ = Command::new(watcher).spawn(); + } + if !no_tray { - let service = ksni::TrayService::new(Tray { - server_host: host, - server_port: port, + let service = ksni::TrayService::new(Tray::new( + host, + port, config_file, shutdown_sender, - }); + watchers, + )); service.spawn(); } diff --git a/src/bundle/menu.rs b/src/bundle/menu.rs index 4892f8a..b7c1c91 100644 --- a/src/bundle/menu.rs +++ b/src/bundle/menu.rs @@ -4,10 +4,29 @@ use tokio::sync::mpsc::UnboundedSender; #[derive(Debug)] pub struct Tray { - pub server_host: String, - pub server_port: u32, - pub config_file: PathBuf, - pub shutdown_sender: UnboundedSender<()>, + server_host: String, + server_port: u32, + config_file: PathBuf, + shutdown_sender: UnboundedSender<()>, + watchers: Vec, +} + +impl Tray { + pub fn new( + server_host: String, + server_port: u32, + config_file: PathBuf, + shutdown_sender: UnboundedSender<()>, + watchers: Vec, + ) -> Self { + Self { + server_host, + server_port, + config_file, + shutdown_sender, + watchers, + } + } } impl ksni::Tray for Tray { @@ -23,6 +42,35 @@ impl ksni::Tray for Tray { "Awatcher".into() } fn menu(&self) -> Vec> { + let mut watchers_submenu: Vec> = vec![ + ksni::menu::CheckmarkItem { + label: "Idle".into(), + enabled: false, + checked: true, + activate: Box::new(|_this: &mut Self| {}), + ..Default::default() + } + .into(), + ksni::menu::CheckmarkItem { + label: "Window".into(), + enabled: false, + checked: true, + ..Default::default() + } + .into(), + ]; + for watcher in &self.watchers { + watchers_submenu.push( + ksni::menu::CheckmarkItem { + label: watcher.clone(), + enabled: false, + checked: true, + ..Default::default() + } + .into(), + ); + } + vec![ ksni::menu::StandardItem { label: "ActivityWatch".into(), @@ -38,6 +86,12 @@ impl ksni::Tray for Tray { ..Default::default() } .into(), + ksni::menu::SubMenu { + label: "Watchers".into(), + submenu: watchers_submenu, + ..Default::default() + } + .into(), ksni::menu::StandardItem { label: "Configuration".into(), icon_name: "preferences-other".into(),