Something went wrong. Try again.
Small, cross-platform Rust crate for sending system notifications
Something went wrong. Try again.
5.6 kB · 218 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219//! Small, cross-platform Rust crate for sending system notifications//!//! ## Examples//!//! ```rust//! notifica::notify("Hello", "World! 🌍");//! ```
#[cfg(target_os = "macos")]extern crate mac_notification_sys;
#[cfg(target_os = "macos")]use mac_notification_sys::error::{ApplicationError, NotificationError};
#[cfg(target_os = "linux")]extern crate notify_rust;
#[cfg(target_os = "linux")]use notify_rust::error::Error as LError;
#[cfg(target_os = "windows")]use winrt::Error as WError;
use std::{ error::Error as StdError, fmt::{self, Display, Formatter},};
trait Platform { fn setup() -> Self; fn notify(msg_title: &str, msg_body: &str) -> Result<(), ErrorRepr>;}
#[derive(Debug)]pub struct Error(ErrorRepr);
#[derive(Debug)]enum ErrorRepr { #[cfg(target_os = "linux")] Linux(LError), #[cfg(target_os = "macos")] MacOs(MacOsError), #[cfg(target_os = "windows")] Windows(WError),}
impl StdError for Error {}impl StdError for ErrorRepr {}
#[cfg(target_os = "macos")]#[derive(Debug)]enum MacOsError { AppErr(ApplicationError), NotErr(NotificationError),}
#[cfg(target_os = "macos")]impl Display for MacOsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { MacOsError::AppErr(e) => Display::fmt(e, f), MacOsError::NotErr(e) => Display::fmt(e, f), } }}
impl Display for Error { fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { self.0.fmt(fmt) }}
impl Display for ErrorRepr { fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { match self { #[cfg(target_os = "linux")] ErrorRepr::Linux(e) => write!(fmt, "{}", e), #[cfg(target_os = "macos")] ErrorRepr::MacOs(e) => write!(fmt, "{}", e), #[cfg(target_os = "windows")] ErrorRepr::Windows(e) => write!(fmt, "{:?}", e), } }}
#[cfg(target_os = "macos")]impl From<ApplicationError> for MacOsError { fn from(err: ApplicationError) -> Self { MacOsError::AppErr(err) }}
#[cfg(target_os = "macos")]impl From<ApplicationError> for ErrorRepr { fn from(err: ApplicationError) -> Self { ErrorRepr::MacOs(err.into()) }}
#[cfg(target_os = "macos")]impl From<NotificationError> for MacOsError { fn from(err: NotificationError) -> Self { MacOsError::NotErr(err) }}
#[cfg(target_os = "macos")]impl From<NotificationError> for ErrorRepr { fn from(err: NotificationError) -> Self { ErrorRepr::MacOs(err.into()) }}
#[cfg(target_os = "linux")]impl From<LError> for ErrorRepr { fn from(err: LError) -> Self { ErrorRepr::Linux(err) }}
#[cfg(target_os = "windows")]impl From<WError> for ErrorRepr { fn from(err: WError) -> Self { ErrorRepr::Windows(err) }}
#[cfg(target_os = "windows")]struct Windows;
#[cfg(target_os = "windows")]impl Platform for Windows { fn setup() -> Self { Windows }
fn notify(msg_title: &str, msg_body: &str) -> Result<(), ErrorRepr> { use winrt::windows::data::xml::dom::*; use winrt::windows::ui::notifications::*; use winrt::*; let toast_xml = ToastNotificationManager::get_template_content(ToastTemplateType::ToastText02)?.unwrap(); let toast_text_elements = toast_xml.get_elements_by_tag_name(&FastHString::new("text"))?.unwrap();
toast_text_elements.item(0)?.unwrap().append_child( &*toast_xml .create_text_node(&FastHString::from(msg_title))?.unwrap() .query_interface::<IXmlNode>().unwrap(), )?; toast_text_elements.item(1)?.unwrap().append_child( &*toast_xml .create_text_node(&FastHString::from(msg_body))?.unwrap() .query_interface::<IXmlNode>().unwrap(), )?;
let toast = ToastNotification::create_toast_notification(&*toast_xml)?; ToastNotificationManager::create_toast_notifier_with_id(&FastHString::new( "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe", ))?.unwrap() .show(&*toast)?; Ok(()) }}
#[cfg(target_os = "macos")]static APP_SET: std::sync::Once = std::sync::Once::new();
#[cfg(target_os = "macos")]struct MacOs;
#[cfg(target_os = "macos")]impl Platform for MacOs { fn setup() -> Self { APP_SET.call_once(|| { let bundle = mac_notification_sys::get_bundle_identifier("Script Editor").unwrap(); mac_notification_sys::set_application(&bundle).unwrap(); }); MacOs }
fn notify(msg_title: &str, msg_body: &str) -> Result<(), ErrorRepr> { mac_notification_sys::send_notification(msg_title, &None, msg_body, &None).unwrap(); Ok(()) }}
#[cfg(target_os = "linux")]struct Linux;
#[cfg(target_os = "linux")]impl Platform for Linux { fn setup() -> Self { Linux }
fn notify(msg_title: &str, msg_body: &str) -> Result<(), ErrorRepr> { notify_rust::Notification::new() .summary(msg_title) .body(msg_body) .show()?; Ok(()) }}
#[cfg(target_os = "windows")]type CurrPlatform = Windows;#[cfg(target_os = "macos")]type CurrPlatform = MacOs;#[cfg(target_os = "linux")]type CurrPlatform = Linux;
pub fn notify(msg_title: &str, msg_body: &str) -> Result<(), Error> { CurrPlatform::setup(); CurrPlatform::notify(msg_title, msg_body).map_err(Error)?; Ok(())}