102 lines
3.2 KiB
Rust
102 lines
3.2 KiB
Rust
/*
|
|
* This file is part of espanso.
|
|
*
|
|
* Copyright (C) 2019-2021 Federico Terzi
|
|
*
|
|
* espanso is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* espanso is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
use std::{path::{PathBuf}, sync::{Arc, Mutex, mpsc::{Sender, channel}}};
|
|
|
|
use anyhow::{Result, anyhow, bail};
|
|
use lazy_static::lazy_static;
|
|
use log::{error, warn};
|
|
use std::process::Command;
|
|
use winrt_notification::{IconCrop, Toast};
|
|
use std::os::windows::process::CommandExt;
|
|
|
|
const ESPANSO_APP_USER_MODEL_ID: &str = "{5E3B6C0F-1A4D-45C4-8872-D8174702101A}";
|
|
|
|
lazy_static! {
|
|
static ref SEND_CHANNEL: Arc<Mutex<Option<Sender<String>>>> = Arc::new(Mutex::new(None));
|
|
}
|
|
|
|
pub fn initialize_notification_thread(notification_icon_path: PathBuf) -> Result<()> {
|
|
let (sender, receiver) = channel::<String>();
|
|
|
|
{
|
|
let mut lock = SEND_CHANNEL.lock().map_err(|e| anyhow!("failed to define shared notification sender: {}", e))?;
|
|
*lock = Some(sender);
|
|
}
|
|
|
|
std::thread::Builder::new().name("notification-thread".to_string()).spawn(move || {
|
|
// First determine which AppUserModelID we can use
|
|
lazy_static! {
|
|
static ref APP_USER_MODEL_ID: &'static str = if is_espanso_app_user_model_id_set() {
|
|
ESPANSO_APP_USER_MODEL_ID
|
|
} else {
|
|
warn!("unable to find espanso AppUserModelID in the list of registered ones, falling back to Powershell");
|
|
Toast::POWERSHELL_APP_ID
|
|
};
|
|
}
|
|
|
|
while let Ok(message) = receiver.recv() {
|
|
if let Err(err) = Toast::new(&APP_USER_MODEL_ID)
|
|
.icon(¬ification_icon_path, IconCrop::Square, "Espanso")
|
|
.title("Espanso")
|
|
.text1(&message)
|
|
.sound(None)
|
|
.show()
|
|
.map_err(|e| anyhow!("failed to show notification: {}", e)) {
|
|
error!("unable to show notification: {}", err);
|
|
}
|
|
}
|
|
})?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn show_notification(msg: &str) -> Result<()> {
|
|
let mut lock = SEND_CHANNEL.lock().map_err(|e| anyhow!("unable to acquire notification send channel: {}", e))?;
|
|
match &mut *lock {
|
|
Some(sender) => {
|
|
sender.send(msg.to_string())?;
|
|
Ok(())
|
|
},
|
|
None => bail!("notification sender not available"),
|
|
}
|
|
}
|
|
|
|
fn is_espanso_app_user_model_id_set() -> bool {
|
|
match Command::new("powershell")
|
|
.args(&["-c", "get-startapps"])
|
|
.creation_flags(0x08000000)
|
|
.output()
|
|
{
|
|
Ok(output) => {
|
|
let output_str = String::from_utf8_lossy(&output.stdout);
|
|
// Check if espanso is present
|
|
output_str
|
|
.lines()
|
|
.any(|line| line.contains(ESPANSO_APP_USER_MODEL_ID))
|
|
}
|
|
Err(err) => {
|
|
error!(
|
|
"unable to determine if AppUserModelID was registered: {}",
|
|
err
|
|
);
|
|
false
|
|
}
|
|
}
|
|
} |