[desktop] support for windows notifications
This commit is contained in:
@@ -3,9 +3,7 @@ use crate::portapi::message::*;
|
||||
use crate::portapi::models::notification::*;
|
||||
use crate::portapi::types::*;
|
||||
use log::error;
|
||||
use notify_rust;
|
||||
use serde_json::json;
|
||||
#[allow(unused_imports)]
|
||||
use tauri::async_runtime;
|
||||
|
||||
pub async fn notification_handler(cli: PortAPI) {
|
||||
@@ -34,59 +32,7 @@ pub async fn notification_handler(cli: PortAPI) {
|
||||
if n.selected_action_id != "" {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(ppacher): keep a reference of open notifications and close them
|
||||
// if the user reacted inside the UI:
|
||||
|
||||
let mut notif = notify_rust::Notification::new();
|
||||
notif.body(&n.message);
|
||||
notif.timeout(notify_rust::Timeout::Never); // TODO(ppacher): use n.expires to calculate the timeout.
|
||||
notif.summary(&n.title);
|
||||
notif.icon("portmaster");
|
||||
|
||||
for action in n.actions {
|
||||
notif.action(&action.id, &action.text);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let cli_clone = cli.clone();
|
||||
async_runtime::spawn(async move {
|
||||
let res = notif.show();
|
||||
match res {
|
||||
Ok(handle) => {
|
||||
handle.wait_for_action(|action| {
|
||||
match action {
|
||||
"__closed" => {
|
||||
// timeout
|
||||
}
|
||||
|
||||
value => {
|
||||
let value = value.to_string().clone();
|
||||
|
||||
async_runtime::spawn(async move {
|
||||
let _ = cli_clone
|
||||
.request(Request::Update(
|
||||
key,
|
||||
Payload::JSON(
|
||||
json!({
|
||||
"SelectedActionID": value
|
||||
})
|
||||
.to_string(),
|
||||
),
|
||||
))
|
||||
.await;
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Err(err) => {
|
||||
error!("failed to display notification: {}", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
show_notification(&cli, key, n).await;
|
||||
}
|
||||
Err(err) => match err {
|
||||
ParseError::JSON(err) => {
|
||||
@@ -101,3 +47,99 @@ pub async fn notification_handler(cli: PortAPI) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn show_notification(cli: &PortAPI, key: String, n: Notification) {
|
||||
let mut notif = notify_rust::Notification::new();
|
||||
notif.body(&n.message);
|
||||
notif.timeout(notify_rust::Timeout::Never); // TODO(ppacher): use n.expires to calculate the timeout.
|
||||
notif.summary(&n.title);
|
||||
notif.icon("portmaster");
|
||||
|
||||
for action in n.actions {
|
||||
notif.action(&action.id, &action.text);
|
||||
}
|
||||
|
||||
{
|
||||
let cli_clone = cli.clone();
|
||||
async_runtime::spawn(async move {
|
||||
let res = notif.show();
|
||||
// TODO(ppacher): keep a reference of open notifications and close them
|
||||
// if the user reacted inside the UI:
|
||||
match res {
|
||||
Ok(handle) => {
|
||||
handle.wait_for_action(|action| {
|
||||
match action {
|
||||
"__closed" => {
|
||||
// timeout
|
||||
}
|
||||
|
||||
value => {
|
||||
let value = value.to_string().clone();
|
||||
|
||||
async_runtime::spawn(async move {
|
||||
let _ = cli_clone
|
||||
.request(Request::Update(
|
||||
key,
|
||||
Payload::JSON(
|
||||
json!({
|
||||
"SelectedActionID": value
|
||||
})
|
||||
.to_string(),
|
||||
),
|
||||
))
|
||||
.await;
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Err(err) => {
|
||||
error!("failed to display notification: {}", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub async fn show_notification(cli: &PortAPI, key: String, n: Notification) {
|
||||
use tauri_winrt_notification::{Duration, Sound, Toast};
|
||||
|
||||
let mut toast = Toast::new("io.safing.portmaster")
|
||||
.title(&n.title)
|
||||
.text1(&n.message)
|
||||
.sound(Some(Sound::Default))
|
||||
.duration(Duration::Long);
|
||||
|
||||
for action in n.actions {
|
||||
toast = toast.add_button(&action.text, &action.id);
|
||||
}
|
||||
{
|
||||
let cli = cli.clone();
|
||||
toast = toast.on_activated(move |action| -> windows::core::Result<()> {
|
||||
if let Some(value) = action {
|
||||
let cli = cli.clone();
|
||||
let key = key.clone();
|
||||
async_runtime::spawn(async move {
|
||||
let _ = cli
|
||||
.request(Request::Update(
|
||||
key,
|
||||
Payload::JSON(
|
||||
json!({
|
||||
"SelectedActionID": value
|
||||
})
|
||||
.to_string(),
|
||||
),
|
||||
))
|
||||
.await;
|
||||
});
|
||||
}
|
||||
// TODO(vladimir): If Action is None, the user clicked on the notification. Focus on the UI.
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
toast.show().expect("unable to send notification");
|
||||
// TODO(vladimir): keep a reference of open notifications and close them
|
||||
// if the user reacted inside the UI:
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user