mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-22 05:39:53 +03:00
refactor(tauri) execute_promise String/Serialize management (#724)
This commit is contained in:
parent
6d23b0673e
commit
6b097345ed
8
.changes/execute-promise-refactor.md
Normal file
8
.changes/execute-promise-refactor.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
"tauri-api": minor
|
||||
"tauri": minor
|
||||
---
|
||||
|
||||
The `execute_promise` and `execute_promise_sync` helpers now accepts any `tauri::Result<T>` where `T: impl Serialize`.
|
||||
This means that you do not need to serialize your response manually or deal with String quotes anymore.
|
||||
As part of this refactor, the `event::emit` function also supports `impl Serialize` instead of `String`.
|
@ -18,7 +18,7 @@ export interface HttpOptions {
|
||||
method: HttpVerb
|
||||
url: string
|
||||
headers?: Record<string, any>
|
||||
propertys?: Record<string, any>
|
||||
params?: Record<string, any>
|
||||
body?: Body
|
||||
followRedirects: boolean
|
||||
maxRedirections: boolean
|
||||
|
@ -221,7 +221,7 @@ impl HttpRequestBuilder {
|
||||
///
|
||||
/// The response will be transformed to String,
|
||||
/// If reading the response as binary, the byte array will be serialized using serde_json
|
||||
pub fn make_request(options: HttpRequestOptions) -> crate::Result<String> {
|
||||
pub fn make_request(options: HttpRequestOptions) -> crate::Result<Value> {
|
||||
let method = Method::from_bytes(options.method.to_uppercase().as_bytes())?;
|
||||
let mut builder = RequestBuilder::new(method, options.url);
|
||||
if let Some(params) = options.params {
|
||||
@ -291,12 +291,9 @@ pub fn make_request(options: HttpRequestOptions) -> crate::Result<String> {
|
||||
let response = response?;
|
||||
if response.is_success() {
|
||||
let response_data = match options.response_type.unwrap_or(ResponseType::Json) {
|
||||
ResponseType::Json => {
|
||||
let result = response.json::<Value>()?;
|
||||
serde_json::to_string(&result)?
|
||||
}
|
||||
ResponseType::Text => response.text()?,
|
||||
ResponseType::Binary => serde_json::to_string(&response.bytes()?)?,
|
||||
ResponseType::Json => response.json::<Value>()?,
|
||||
ResponseType::Text => Value::String(response.text()?),
|
||||
ResponseType::Binary => Value::String(serde_json::to_string(&response.bytes()?)?),
|
||||
};
|
||||
Ok(response_data)
|
||||
} else {
|
||||
|
@ -16,6 +16,7 @@ use std::path::MAIN_SEPARATOR;
|
||||
/// .show();
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
#[derive(Default)]
|
||||
pub struct Notification {
|
||||
/// The notification body.
|
||||
body: Option<String>,
|
||||
@ -28,11 +29,7 @@ pub struct Notification {
|
||||
impl Notification {
|
||||
/// Initializes a instance of a Notification.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
body: None,
|
||||
title: None,
|
||||
icon: None,
|
||||
}
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Sets the notification body.
|
||||
|
@ -1,12 +1,15 @@
|
||||
/// Formats a function to be evaluated as callback.
|
||||
/// If the arg is a string literal, it needs the proper quotes.
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::fmt::Display;
|
||||
|
||||
/// Formats a function name and argument to be evaluated as callback.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri_api::rpc::format_callback;
|
||||
/// // callback with a string argument
|
||||
/// // returns `window["callback-function-name"]("the string response")`
|
||||
/// format_callback("callback-function-name".to_string(), r#""the string response""#.to_string());
|
||||
/// let cb = format_callback("callback-function-name", "the string response");
|
||||
/// assert_eq!(cb, r#"window["callback-function-name"]("the string response")"#);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
@ -17,39 +20,50 @@
|
||||
/// struct MyResponse {
|
||||
/// value: String
|
||||
/// }
|
||||
/// // this returns `window["callback-function-name"]({value: "some value"})`
|
||||
/// format_callback("callback-function-name".to_string(), serde_json::to_string(&MyResponse {
|
||||
/// let cb = format_callback("callback-function-name", serde_json::to_value(&MyResponse {
|
||||
/// value: "some value".to_string()
|
||||
/// }).expect("failed to serialize type"));
|
||||
/// }).expect("failed to serialize"));
|
||||
/// assert_eq!(cb, r#"window["callback-function-name"]({"value":"some value"})"#);
|
||||
/// ```
|
||||
pub fn format_callback(function_name: String, arg: String) -> String {
|
||||
let formatted_string = &format!("window[\"{}\"]({})", function_name, arg);
|
||||
formatted_string.to_string()
|
||||
pub fn format_callback<T: Into<JsonValue>, S: AsRef<str> + Display>(
|
||||
function_name: S,
|
||||
arg: T,
|
||||
) -> String {
|
||||
format!(r#"window["{}"]({})"#, function_name, arg.into().to_string())
|
||||
}
|
||||
|
||||
/// Formats a Result type to its callback version.
|
||||
/// Formats a Result type to its Promise response.
|
||||
/// Useful for Promises handling.
|
||||
/// If the Result `is_ok()`, the callback will be the `success_callback` function name and the argument will be the Ok value.
|
||||
/// If the Result `is_err()`, the callback will be the `error_callback` function name and the argument will be the Err value.
|
||||
///
|
||||
/// If the Result is Ok, `format_callback` will be called directly.
|
||||
/// If the result is an Err, we assume the error message is a string, and quote it.
|
||||
/// * `result` the Result to check
|
||||
/// * `success_callback` the function name of the Ok callback. Usually the `resolve` of the JS Promise.
|
||||
/// * `error_callback` the function name of the Err callback. Usually the `reject` of the JS Promise.
|
||||
///
|
||||
/// Note that the callback strings are automatically generated by the `promisified` helper.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use tauri_api::rpc::format_callback_result;
|
||||
/// // returns `window["success_cb"](5)`
|
||||
/// format_callback_result(Ok("5".to_string()), "success_cb".to_string(), "error_cb".to_string());
|
||||
/// // returns `window["error_cb"]("error message here")`
|
||||
/// format_callback_result(Err("error message here".to_string()), "success_cb".to_string(), "error_cb".to_string());
|
||||
/// let res: Result<u8, &str> = Ok(5);
|
||||
/// let cb = format_callback_result(res, "success_cb".to_string(), "error_cb".to_string()).expect("failed to format");
|
||||
/// assert_eq!(cb, r#"window["success_cb"](5)"#);
|
||||
///
|
||||
/// let res: Result<&str, &str> = Err("error message here");
|
||||
/// let cb = format_callback_result(res, "success_cb".to_string(), "error_cb".to_string()).expect("failed to format");
|
||||
/// assert_eq!(cb, r#"window["error_cb"]("error message here")"#);
|
||||
/// ```
|
||||
pub fn format_callback_result(
|
||||
result: Result<String, String>,
|
||||
callback: String,
|
||||
pub fn format_callback_result<T: Serialize, E: Serialize>(
|
||||
result: Result<T, E>,
|
||||
success_callback: String,
|
||||
error_callback: String,
|
||||
) -> String {
|
||||
match result {
|
||||
Ok(res) => format_callback(callback, res),
|
||||
Err(err) => format_callback(error_callback, format!("\"{}\"", err)),
|
||||
}
|
||||
) -> crate::Result<String> {
|
||||
let rpc = match result {
|
||||
Ok(res) => format_callback(success_callback, serde_json::to_value(res)?),
|
||||
Err(err) => format_callback(error_callback, serde_json::to_value(err)?),
|
||||
};
|
||||
Ok(rpc)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -62,16 +76,9 @@ mod test {
|
||||
fn qc_formating(f: String, a: String) -> bool {
|
||||
// can not accept empty strings
|
||||
if f != "" && a != "" {
|
||||
// get length of function and argument
|
||||
let alen = &a.len();
|
||||
let flen = &f.len();
|
||||
// call format callback
|
||||
let fc = format_callback(f, a);
|
||||
// get length of the resulting string
|
||||
let fclen = fc.len();
|
||||
|
||||
// if formatted string equals the length of the argument and the function plus 12 then its correct.
|
||||
fclen == alen + flen + 12
|
||||
let fc = format_callback(f.clone(), a.clone());
|
||||
fc == format!(r#"window["{}"]({})"#, f, serde_json::Value::String(a))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@ -80,33 +87,18 @@ mod test {
|
||||
// check arbitrary strings in format_callback_result
|
||||
#[quickcheck]
|
||||
fn qc_format_res(result: Result<String, String>, c: String, ec: String) -> bool {
|
||||
// match on result to decide how to call the function.
|
||||
match result {
|
||||
// if ok, get length of result and callback strings.
|
||||
Ok(r) => {
|
||||
let rlen = r.len();
|
||||
let clen = c.len();
|
||||
let resp = format_callback_result(result.clone(), c.clone(), ec.clone())
|
||||
.expect("failed to format callback result");
|
||||
let (function, value) = match result {
|
||||
Ok(v) => (c, v),
|
||||
Err(e) => (ec, e),
|
||||
};
|
||||
|
||||
// take the ok string from result and pass it into format_callback_result as an ok.
|
||||
let resp = format_callback_result(Ok(r), c, ec);
|
||||
// get response string length
|
||||
let reslen = resp.len();
|
||||
|
||||
// if response string length equals result and callback length plus 12 characters then it is correct.
|
||||
reslen == rlen + clen + 12
|
||||
}
|
||||
// If Err, get length of Err and Error callback
|
||||
Err(err) => {
|
||||
let eclen = ec.len();
|
||||
let errlen = err.len();
|
||||
// pass err as Err into format_callback_result with callback and error callback
|
||||
let resp = format_callback_result(Err(err), c, ec);
|
||||
// get response string length
|
||||
let reslen = resp.len();
|
||||
|
||||
// if length of response string equals the error length and the error callback length plus 14 characters then its is correct.
|
||||
reslen == eclen + errlen + 14
|
||||
}
|
||||
}
|
||||
resp
|
||||
== format!(
|
||||
r#"window["{}"]({})"#,
|
||||
function,
|
||||
serde_json::Value::String(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
|
||||
callback,
|
||||
error,
|
||||
} => {
|
||||
salt::validate(webview, salt, callback, error);
|
||||
salt::validate(webview, salt, callback, error)?;
|
||||
}
|
||||
Listen {
|
||||
event,
|
||||
@ -206,7 +206,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
|
||||
error,
|
||||
} => {
|
||||
#[cfg(open_dialog)]
|
||||
dialog::open(webview, options, callback, error);
|
||||
dialog::open(webview, options, callback, error)?;
|
||||
#[cfg(not(open_dialog))]
|
||||
whitelist_error(webview, error, "title");
|
||||
}
|
||||
@ -216,7 +216,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
|
||||
error,
|
||||
} => {
|
||||
#[cfg(save_dialog)]
|
||||
dialog::save(webview, options, callback, error);
|
||||
dialog::save(webview, options, callback, error)?;
|
||||
#[cfg(not(save_dialog))]
|
||||
throw_whitelist_error(webview, "saveDialog");
|
||||
}
|
||||
@ -244,7 +244,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
|
||||
crate::execute_promise(
|
||||
webview,
|
||||
move || match crate::cli::get_matches() {
|
||||
Some(matches) => Ok(serde_json::to_string(matches)?),
|
||||
Some(matches) => Ok(matches),
|
||||
None => Err(anyhow::anyhow!(r#""failed to get matches""#)),
|
||||
},
|
||||
callback,
|
||||
@ -271,7 +271,7 @@ pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> cra
|
||||
}
|
||||
RequestNotificationPermission { callback, error } => {
|
||||
#[cfg(notification)]
|
||||
notification::request_permission(webview, callback, error);
|
||||
notification::request_permission(webview, callback, error)?;
|
||||
#[cfg(not(notification))]
|
||||
whitelist_error(webview, error, "notification");
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ pub fn load<T: 'static>(
|
||||
}
|
||||
})
|
||||
.map_err(|err| err.into())
|
||||
.map(|_| r#""Asset loaded successfully""#.to_string())
|
||||
.map(|_| "Asset loaded successfully".to_string())
|
||||
}
|
||||
},
|
||||
callback,
|
||||
|
@ -1,13 +1,14 @@
|
||||
use super::cmd::{OpenDialogOptions, SaveDialogOptions};
|
||||
use crate::api::dialog::{pick_folder, save_file, select, select_multiple, Response};
|
||||
use serde_json::Value as JsonValue;
|
||||
use web_view::WebView;
|
||||
|
||||
/// maps a dialog response to a JS value to eval
|
||||
fn map_response(response: Response) -> String {
|
||||
fn map_response(response: Response) -> JsonValue {
|
||||
match response {
|
||||
Response::Okay(path) => format!(r#""{}""#, path).replace("\\", "\\\\"),
|
||||
Response::OkayMultiple(paths) => format!("{:?}", paths),
|
||||
Response::Cancel => panic!("unexpected response type"),
|
||||
Response::Okay(path) => path.into(),
|
||||
Response::OkayMultiple(paths) => paths.into(),
|
||||
Response::Cancel => JsonValue::Null,
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +19,7 @@ pub fn open<T: 'static>(
|
||||
options: OpenDialogOptions,
|
||||
callback: String,
|
||||
error: String,
|
||||
) {
|
||||
) -> crate::Result<()> {
|
||||
crate::execute_promise_sync(
|
||||
webview,
|
||||
move || {
|
||||
@ -33,7 +34,8 @@ pub fn open<T: 'static>(
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shows a save dialog.
|
||||
@ -43,11 +45,12 @@ pub fn save<T: 'static>(
|
||||
options: SaveDialogOptions,
|
||||
callback: String,
|
||||
error: String,
|
||||
) {
|
||||
) -> crate::Result<()> {
|
||||
crate::execute_promise_sync(
|
||||
webview,
|
||||
move || save_file(options.filter, options.default_path).map(map_response),
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ pub fn read_dir<T: 'static>(
|
||||
(false, None)
|
||||
};
|
||||
dir::read_dir(resolve_path(path, dir)?, recursive)
|
||||
.and_then(|f| serde_json::to_string(&f).map_err(|err| err.into()))
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -55,9 +54,7 @@ pub fn copy_file<T: 'static>(
|
||||
),
|
||||
None => (source, destination),
|
||||
};
|
||||
fs::copy(src, dest)
|
||||
.map_err(|e| e.into())
|
||||
.map(|_| "".to_string())
|
||||
fs::copy(src, dest).map_err(|e| e.into())
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -88,7 +85,7 @@ pub fn create_dir<T: 'static>(
|
||||
fs::create_dir(resolved_path)
|
||||
};
|
||||
|
||||
response.map_err(|e| e.into()).map(|_| "".to_string())
|
||||
response.map_err(|e| e.into())
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -119,7 +116,7 @@ pub fn remove_dir<T: 'static>(
|
||||
fs::remove_dir(resolved_path)
|
||||
};
|
||||
|
||||
response.map_err(|e| e.into()).map(|_| "".to_string())
|
||||
response.map_err(|e| e.into())
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -139,9 +136,7 @@ pub fn remove_file<T: 'static>(
|
||||
webview,
|
||||
move || {
|
||||
let resolved_path = resolve_path(path, options.and_then(|o| o.dir))?;
|
||||
fs::remove_file(resolved_path)
|
||||
.map_err(|e| e.into())
|
||||
.map(|_| "".to_string())
|
||||
fs::remove_file(resolved_path).map_err(|e| e.into())
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -168,9 +163,7 @@ pub fn rename_file<T: 'static>(
|
||||
),
|
||||
None => (old_path, new_path),
|
||||
};
|
||||
fs::rename(old, new)
|
||||
.map_err(|e| e.into())
|
||||
.map(|_| "".to_string())
|
||||
fs::rename(old, new).map_err(|e| e.into())
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -192,11 +185,7 @@ pub fn write_file<T: 'static>(
|
||||
move || {
|
||||
File::create(resolve_path(file, options.and_then(|o| o.dir))?)
|
||||
.map_err(|e| e.into())
|
||||
.and_then(|mut f| {
|
||||
f.write_all(contents.as_bytes())
|
||||
.map_err(|err| err.into())
|
||||
.map(|_| "".to_string())
|
||||
})
|
||||
.and_then(|mut f| f.write_all(contents.as_bytes()).map_err(|err| err.into()))
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
@ -221,11 +210,7 @@ pub fn write_binary_file<T: 'static>(
|
||||
.and_then(|c| {
|
||||
File::create(resolve_path(file, options.and_then(|o| o.dir))?)
|
||||
.map_err(|e| e.into())
|
||||
.and_then(|mut f| {
|
||||
f.write_all(&c)
|
||||
.map_err(|err| err.into())
|
||||
.map(|_| "".to_string())
|
||||
})
|
||||
.and_then(|mut f| f.write_all(&c).map_err(|err| err.into()))
|
||||
})
|
||||
},
|
||||
callback,
|
||||
@ -244,10 +229,7 @@ pub fn read_text_file<T: 'static>(
|
||||
) {
|
||||
crate::execute_promise(
|
||||
webview,
|
||||
move || {
|
||||
file::read_string(resolve_path(path, options.and_then(|o| o.dir))?)
|
||||
.and_then(|f| serde_json::to_string(&f).map_err(|err| err.into()))
|
||||
},
|
||||
move || file::read_string(resolve_path(path, options.and_then(|o| o.dir))?),
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
@ -264,10 +246,7 @@ pub fn read_binary_file<T: 'static>(
|
||||
) {
|
||||
crate::execute_promise(
|
||||
webview,
|
||||
move || {
|
||||
file::read_binary(resolve_path(path, options.and_then(|o| o.dir))?)
|
||||
.and_then(|f| serde_json::to_string(&f).map_err(|err| err.into()))
|
||||
},
|
||||
move || file::read_binary(resolve_path(path, options.and_then(|o| o.dir))?),
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use tauri_api::http::{make_request as request, HttpRequestOptions, ResponseType};
|
||||
use tauri_api::http::{make_request as request, HttpRequestOptions};
|
||||
use web_view::WebView;
|
||||
|
||||
/// Makes an HTTP request and resolves the response to the webview
|
||||
@ -8,21 +8,5 @@ pub fn make_request<T: 'static>(
|
||||
callback: String,
|
||||
error: String,
|
||||
) {
|
||||
crate::execute_promise(
|
||||
webview,
|
||||
move || {
|
||||
let response_type = options.response_type.clone();
|
||||
request(options).map(
|
||||
|response| match response_type.unwrap_or(ResponseType::Json) {
|
||||
ResponseType::Text => format!(
|
||||
r#""{}""#,
|
||||
response.replace(r#"""#, r#"\""#).replace(r#"\\""#, r#"\""#)
|
||||
),
|
||||
_ => response,
|
||||
},
|
||||
)
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
crate::execute_promise(webview, move || request(options), callback, error);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::cmd::NotificationOptions;
|
||||
use serde_json::Value as JsonValue;
|
||||
use web_view::WebView;
|
||||
|
||||
pub fn send<T: 'static>(
|
||||
@ -18,9 +19,7 @@ pub fn send<T: 'static>(
|
||||
if let Some(icon) = options.icon {
|
||||
notification = notification.icon(icon);
|
||||
}
|
||||
notification
|
||||
.show()
|
||||
.map_err(|e| anyhow::anyhow!(r#""{}""#, e.to_string()))?;
|
||||
notification.show()?;
|
||||
Ok("".to_string())
|
||||
},
|
||||
callback,
|
||||
@ -38,9 +37,9 @@ pub fn is_permission_granted<T: 'static>(
|
||||
move || {
|
||||
let settings = crate::settings::read_settings()?;
|
||||
if let Some(allow_notification) = settings.allow_notification {
|
||||
Ok(allow_notification.to_string())
|
||||
Ok(JsonValue::String(allow_notification.to_string()))
|
||||
} else {
|
||||
Ok("null".to_string())
|
||||
Ok(JsonValue::Null)
|
||||
}
|
||||
},
|
||||
callback,
|
||||
@ -52,7 +51,7 @@ pub fn request_permission<T: 'static>(
|
||||
webview: &mut WebView<'_, T>,
|
||||
callback: String,
|
||||
error: String,
|
||||
) {
|
||||
) -> crate::Result<()> {
|
||||
crate::execute_promise_sync(
|
||||
webview,
|
||||
move || {
|
||||
@ -82,5 +81,6 @@ pub fn request_permission<T: 'static>(
|
||||
},
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -6,14 +6,13 @@ pub fn validate<T: 'static>(
|
||||
salt: String,
|
||||
callback: String,
|
||||
error: String,
|
||||
) {
|
||||
) -> crate::Result<()> {
|
||||
let response = if crate::salt::is_valid(salt) {
|
||||
Ok("'VALID'".to_string())
|
||||
} else {
|
||||
Err("'INVALID SALT'".to_string())
|
||||
};
|
||||
let callback_string = crate::api::rpc::format_callback_result(response, callback, error);
|
||||
webview
|
||||
.eval(callback_string.as_str())
|
||||
.expect("Failed to eval JS from validate()");
|
||||
let callback_string = crate::api::rpc::format_callback_result(response, callback, error)?;
|
||||
webview.eval(callback_string.as_str())?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value as JsonValue;
|
||||
use web_view::Handle;
|
||||
|
||||
/// An event handler.
|
||||
@ -55,13 +57,17 @@ pub fn listen<F: FnMut(Option<String>) + Send + 'static>(id: String, handler: F)
|
||||
}
|
||||
|
||||
/// Emits an event to JS.
|
||||
pub fn emit<T: 'static>(webview_handle: &Handle<T>, event: String, payload: Option<String>) {
|
||||
pub fn emit<T: 'static, S: Serialize>(
|
||||
webview_handle: &Handle<T>,
|
||||
event: String,
|
||||
payload: Option<S>,
|
||||
) -> crate::Result<()> {
|
||||
let salt = crate::salt::generate();
|
||||
|
||||
let js_payload = if let Some(payload_str) = payload {
|
||||
payload_str
|
||||
let js_payload = if let Some(payload_value) = payload {
|
||||
serde_json::to_value(payload_value)?
|
||||
} else {
|
||||
"void 0".to_string()
|
||||
JsonValue::Null
|
||||
};
|
||||
|
||||
webview_handle
|
||||
@ -75,6 +81,8 @@ pub fn emit<T: 'static>(webview_handle: &Handle<T>, event: String, payload: Opti
|
||||
))
|
||||
})
|
||||
.expect("Failed to dispatch JS from emit");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Triggers the given event with its payload.
|
||||
|
@ -32,17 +32,19 @@ mod endpoints;
|
||||
/// The salt helpers.
|
||||
mod salt;
|
||||
|
||||
use std::process::Stdio;
|
||||
|
||||
/// Alias for a Result with error type anyhow::Error.
|
||||
pub use anyhow::Result;
|
||||
use threadpool::ThreadPool;
|
||||
|
||||
pub use web_view::Handle;
|
||||
use web_view::WebView;
|
||||
|
||||
pub use app::*;
|
||||
pub use tauri_api as api;
|
||||
pub use web_view::Handle;
|
||||
|
||||
use std::process::Stdio;
|
||||
|
||||
use api::rpc::{format_callback, format_callback_result};
|
||||
use serde::Serialize;
|
||||
use threadpool::ThreadPool;
|
||||
use web_view::WebView;
|
||||
|
||||
thread_local!(static POOL: ThreadPool = ThreadPool::new(4));
|
||||
|
||||
/// Executes the operation in the thread pool.
|
||||
@ -56,33 +58,49 @@ pub fn spawn<F: FnOnce() -> () + Send + 'static>(task: F) {
|
||||
|
||||
/// Synchronously executes the given task
|
||||
/// and evaluates its Result to the JS promise described by the `callback` and `error` function names.
|
||||
pub fn execute_promise_sync<T: 'static, F: FnOnce() -> crate::Result<String> + Send + 'static>(
|
||||
pub fn execute_promise_sync<
|
||||
T: 'static,
|
||||
R: Serialize,
|
||||
F: FnOnce() -> crate::Result<R> + Send + 'static,
|
||||
>(
|
||||
webview: &mut WebView<'_, T>,
|
||||
task: F,
|
||||
callback: String,
|
||||
error: String,
|
||||
) {
|
||||
) -> crate::Result<()> {
|
||||
let handle = webview.handle();
|
||||
let callback_string =
|
||||
api::rpc::format_callback_result(task().map_err(|err| err.to_string()), callback, error);
|
||||
handle
|
||||
.dispatch(move |_webview| _webview.eval(callback_string.as_str()))
|
||||
.expect("Failed to dispatch promise callback");
|
||||
format_callback_result(task().map_err(|err| err.to_string()), callback, error)?;
|
||||
handle.dispatch(move |_webview| _webview.eval(callback_string.as_str()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Asynchronously executes the given task
|
||||
/// and evaluates its Result to the JS promise described by the `callback` and `error` function names.
|
||||
pub fn execute_promise<T: 'static, F: FnOnce() -> crate::Result<String> + Send + 'static>(
|
||||
/// and evaluates its Result to the JS promise described by the `success_callback` and `error_callback` function names.
|
||||
///
|
||||
/// If the Result `is_ok()`, the callback will be the `success_callback` function name and the argument will be the Ok value.
|
||||
/// If the Result `is_err()`, the callback will be the `error_callback` function name and the argument will be the Err value.
|
||||
pub fn execute_promise<
|
||||
T: 'static,
|
||||
R: Serialize,
|
||||
F: FnOnce() -> crate::Result<R> + Send + 'static,
|
||||
>(
|
||||
webview: &mut WebView<'_, T>,
|
||||
task: F,
|
||||
callback: String,
|
||||
error: String,
|
||||
success_callback: String,
|
||||
error_callback: String,
|
||||
) {
|
||||
let handle = webview.handle();
|
||||
POOL.with(|thread| {
|
||||
thread.execute(move || {
|
||||
let callback_string =
|
||||
api::rpc::format_callback_result(task().map_err(|err| err.to_string()), callback, error);
|
||||
let callback_string = match format_callback_result(
|
||||
task().map_err(|err| err.to_string()),
|
||||
success_callback,
|
||||
error_callback.clone(),
|
||||
) {
|
||||
Ok(callback_string) => callback_string,
|
||||
Err(e) => format_callback(error_callback, e.to_string()),
|
||||
};
|
||||
handle
|
||||
.dispatch(move |_webview| _webview.eval(callback_string.as_str()))
|
||||
.expect("Failed to dispatch promise callback")
|
||||
@ -100,11 +118,7 @@ pub fn call<T: 'static>(
|
||||
) {
|
||||
execute_promise(
|
||||
webview,
|
||||
|| {
|
||||
api::command::get_output(command, args, Stdio::piped())
|
||||
.map_err(|err| err)
|
||||
.map(|output| format!(r#""{}""#, output))
|
||||
},
|
||||
|| api::command::get_output(command, args, Stdio::piped()),
|
||||
callback,
|
||||
error,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user