add alert for macos

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2023-02-19 11:40:59 +08:00
parent b733ad9379
commit a333a261fd
7 changed files with 145 additions and 42 deletions

12
Cargo.lock generated
View File

@ -2612,6 +2612,7 @@ dependencies = [
"log", "log",
"mac_address", "mac_address",
"machine-uid", "machine-uid",
"osascript",
"protobuf", "protobuf",
"protobuf-codegen", "protobuf-codegen",
"quinn", "quinn",
@ -3926,6 +3927,17 @@ version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "osascript"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38731fa859ef679f1aec66ca9562165926b442f298467f76f5990f431efe87dc"
dependencies = [
"serde 1.0.149",
"serde_derive",
"serde_json 1.0.89",
]
[[package]] [[package]]
name = "pango" name = "pango"
version = "0.16.5" version = "0.16.5"

View File

@ -48,6 +48,9 @@ protobuf-codegen = { version = "3.1" }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["winuser"] } winapi = { version = "0.3", features = ["winuser"] }
[target.'cfg(target_os = "macos")'.dependencies]
osascript = "0.3.0"
[dev-dependencies] [dev-dependencies]
toml = "0.5" toml = "0.5"
serde_json = "1.0" serde_json = "1.0"

View File

@ -0,0 +1,15 @@
extern crate hbb_common;
fn main() {
#[cfg(target_os = "linux")]
linux::system_message("test title", "test message", true).ok();
#[cfg(target_os = "macos")]
macos::alert(
"RustDesk".to_owned(),
"critical".to_owned(),
"test title".to_owned(),
"test message".to_owned(),
["Ok".to_owned()].to_vec(),
)
.ok();
}

View File

@ -1,4 +1,5 @@
use crate::ResultType; use crate::ResultType;
use std::{collections::HashMap, process::Command};
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref DISTRO: Distro = Distro::new(); pub static ref DISTRO: Distro = Distro::new();
@ -155,3 +156,42 @@ fn run_loginctl(args: Option<Vec<&str>>) -> std::io::Result<std::process::Output
.args(vec![String::from("--host"), l_args]) .args(vec![String::from("--host"), l_args])
.output() .output()
} }
/// forever: may not work
#[cfg(target_os = "linux")]
pub fn system_message(title: &str, msg: &str, forever: bool) -> ResultType<()> {
let cmds: HashMap<&str, Vec<&str>> = HashMap::from([
("notify-send", [title, msg].to_vec()),
(
"zenity",
[
"--info",
"--timeout",
if forever { "0" } else { "3" },
"--title",
title,
"--text",
msg,
]
.to_vec(),
),
("kdialog", ["--title", title, "--msgbox", msg].to_vec()),
(
"xmessage",
[
"-center",
"-timeout",
if forever { "0" } else { "3" },
title,
msg,
]
.to_vec(),
),
]);
for (k, v) in cmds {
if Command::new(k).args(v).spawn().is_ok() {
return Ok(());
}
}
crate::bail!("failed to post system message");
}

View File

@ -0,0 +1,55 @@
use osascript;
use serde_derive;
#[derive(Serialize)]
struct AlertParams {
title: String,
message: String,
alert_type: String,
buttons: Vec<String>,
}
#[derive(Deserialize)]
struct AlertResult {
#[serde(rename = "buttonReturned")]
button: String,
}
/// Alert dialog, return the clicked button value.
///
/// # Arguments
///
/// * `app` - The app to execute the script.
/// * `alert_type` - Alert type. critical
/// * `title` - The alert title.
/// * `message` - The alert message.
/// * `buttons` - The buttons to show.
pub fn alert(
app: &str,
alert_type: &str,
title: &str,
message: String,
buttons: Vec<String>,
) -> ResultType<String> {
let script = osascript::JavaScript::new(format!(
"
var App = Application('{}');
App.includeStandardAdditions = true;
return App.displayAlert($params.title, {
message: $params.message,
'as': $params.alert_type,
buttons: $params.buttons,
});
",
app
));
script
.execute_with_params(AlertParams {
title,
message,
alert_type,
buttons,
})?
.button
}

View File

@ -1,8 +1,11 @@
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub mod linux; pub mod linux;
use crate::{log, config::Config, ResultType}; #[cfg(target_os = "macos")]
use std::{collections::HashMap, process::{Command, exit}}; pub mod macos;
use crate::{config::Config, log};
use std::process::exit;
extern "C" fn breakdown_signal_handler(sig: i32) { extern "C" fn breakdown_signal_handler(sig: i32) {
let mut stack = vec![]; let mut stack = vec![];
@ -30,54 +33,26 @@ extern "C" fn breakdown_signal_handler(sig: i32) {
stack.join("\n").to_string() stack.join("\n").to_string()
); );
if !info.is_empty() { if !info.is_empty() {
system_message( #[cfg(target_os = "linux")]
linux::system_message(
"RustDesk", "RustDesk",
&format!("Got signal {} and exit.{}", sig, info), &format!("Got signal {} and exit.{}", sig, info),
true, true,
) )
.ok(); .ok();
#[cfg(target_os = "macos")]
macos::alert(
"RustDesk".to_owned(),
"critical".to_owned(),
"Crashed".to_owned(),
format!("Got signal {} and exit.{}", sig, info),
["Ok".to_owned()].to_vec(),
)
.ok();
} }
exit(0); exit(0);
} }
/// forever: may not work
pub fn system_message(title: &str, msg: &str, forever: bool) -> ResultType<()> {
let cmds: HashMap<&str, Vec<&str>> = HashMap::from([
("notify-send", [title, msg].to_vec()),
(
"zenity",
[
"--info",
"--timeout",
if forever { "0" } else { "3" },
"--title",
title,
"--text",
msg,
]
.to_vec(),
),
("kdialog", ["--title", title, "--msgbox", msg].to_vec()),
(
"xmessage",
[
"-center",
"-timeout",
if forever { "0" } else { "3" },
title,
msg,
]
.to_vec(),
),
]);
for (k, v) in cmds {
if Command::new(k).args(v).spawn().is_ok() {
return Ok(());
}
}
crate::bail!("failed to post system message");
}
pub fn register_breakdown_handler() { pub fn register_breakdown_handler() {
unsafe { unsafe {
libc::signal(libc::SIGSEGV, breakdown_signal_handler as _); libc::signal(libc::SIGSEGV, breakdown_signal_handler as _);

View File

@ -1,4 +1,6 @@
use hbb_common::{log, platform::register_breakdown_handler}; use hbb_common::log;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
use hbb_common::platform::register_breakdown_handler;
/// shared by flutter and sciter main function /// shared by flutter and sciter main function
/// ///
@ -38,6 +40,7 @@ pub fn core_main() -> Option<Vec<String>> {
} }
i += 1; i += 1;
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))]
register_breakdown_handler(); register_breakdown_handler();
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
#[cfg(feature = "flutter")] #[cfg(feature = "flutter")]