diff --git a/Cargo.lock b/Cargo.lock index 52d0ebcf..d69b6f46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1905,6 +1905,7 @@ name = "topgrade" version = "4.1.0" dependencies = [ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "directories 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index d0eec8dd..01b9d030 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ strum = { version = "0.17.1", features = ["derive"] } thiserror = "1.0.9" anyhow = "1.0.25" tempfile = "3.1.0" +cfg-if = "0.1.10" [target.'cfg(target_os = "macos")'.dependencies] notify-rust = "3.6.3" diff --git a/src/terminal.rs b/src/terminal.rs index 62a59a9c..09404927 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,13 +1,19 @@ +#[cfg(target_os = "linux")] +use crate::utils::which; use chrono::{Local, Timelike}; use console::{style, Term}; use lazy_static::lazy_static; +use log::debug; #[cfg(target_os = "macos")] -use notify_rust::Notification; +use notify_rust::{Notification, Timeout}; use std::cmp::{max, min}; use std::env; use std::io::{self, Write}; +#[cfg(target_os = "linux")] +use std::path::PathBuf; use std::process::Command; use std::sync::Mutex; +use std::time::Duration; #[cfg(windows)] use which_crate::which; @@ -35,6 +41,8 @@ struct Terminal { term: Term, set_title: bool, desktop_notification: bool, + #[cfg(target_os = "linux")] + notify_send: Option, } impl Terminal { @@ -48,6 +56,8 @@ impl Terminal { .unwrap_or_else(|_| String::new()), set_title: true, desktop_notification: false, + #[cfg(target_os = "linux")] + notify_send: which("notify-send"), } } @@ -59,23 +69,43 @@ impl Terminal { self.set_title = set_title } + #[allow(unused_variables)] + fn notify_desktop>(&self, message: P, timeout: Option) { + debug!("Desktop notification: {}", message.as_ref()); + cfg_if::cfg_if! { + if #[cfg(target_os = "macos")] { + let mut notification = Notification::new(); + notification.summary("Topgrade") + .body(message.as_ref()) + .appname("topgrade"); + + if let Some(timeout) = timeout { + notification.timeout(Timeout::Milliseconds(timeout.as_millis() as u32)); + } + notification.show().ok(); + } else if #[cfg(target_os = "linux")] { + if let Some(ns) = self.notify_send.as_ref() { + let mut command = Command::new(ns); + if let Some(timeout) = timeout { + command.arg("-t"); + command.arg(format!("{}", timeout.as_millis())); + command.args(&["-a", "Topgrade"]); + command.arg(message.as_ref()); + } + command.output().ok(); + } + } + } + } + fn print_separator>(&mut self, message: P) { if self.set_title { self.term .set_title(format!("{}Topgrade - {}", self.prefix, message.as_ref())); } - #[cfg(target_os = "macos")] - { - if self.desktop_notification { - Notification::new() - .summary("Topgrade") - .body(message.as_ref()) - .appname("topgrade") - .timeout(5) - .show() - .ok(); - } + if self.desktop_notification { + self.notify_desktop(message.as_ref(), Some(Duration::from_secs(5))); } let now = Local::now(); @@ -156,14 +186,7 @@ impl Terminal { self.term.set_title("Topgrade - Awaiting user"); } - #[cfg(target_os = "macos")] - Notification::new() - .summary("Topgrade") - .body(&format!("{} failed", step_name)) - .appname("topgrade") - .timeout(0) - .show() - .ok(); + self.notify_desktop(&format!("{} failed", step_name), None); self.term .write_fmt(format_args!(