hooks.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use crate::manager::DefaultArgs;
  5. use crate::{
  6. api::rpc::{format_callback, format_callback_result},
  7. app::App,
  8. Params, StateManager, Window,
  9. };
  10. use serde::{Deserialize, Serialize};
  11. use serde_json::Value as JsonValue;
  12. use std::{future::Future, sync::Arc};
  13. /// A closure that is run when the Tauri application is setting up.
  14. pub type SetupHook<P> =
  15. Box<dyn Fn(&mut App<P>) -> Result<(), Box<dyn std::error::Error + Send>> + Send>;
  16. /// A closure that is run everytime Tauri receives a message it doesn't explicitly handle.
  17. pub type InvokeHandler<P> = dyn Fn(Invoke<P>) + Send + Sync + 'static;
  18. /// A closure that is run once every time a window is created and loaded.
  19. pub type OnPageLoad<P> = dyn Fn(Window<P>, PageLoadPayload) + Send + Sync + 'static;
  20. /// The payload for the [`OnPageLoad`] hook.
  21. #[derive(Debug, Clone, Deserialize)]
  22. pub struct PageLoadPayload {
  23. url: String,
  24. }
  25. impl PageLoadPayload {
  26. /// The page URL.
  27. pub fn url(&self) -> &str {
  28. &self.url
  29. }
  30. }
  31. /// The message and resolver given to a custom command.
  32. pub struct Invoke<P: Params = DefaultArgs> {
  33. /// The message passed.
  34. pub message: InvokeMessage<P>,
  35. /// The resolver of the message.
  36. pub resolver: InvokeResolver<P>,
  37. }
  38. /// Error response from an [`InvokeMessage`].
  39. #[derive(Debug)]
  40. pub struct InvokeError(JsonValue);
  41. impl InvokeError {
  42. /// Create an [`InvokeError`] as a string of the [`serde_json::Error`] message.
  43. #[inline(always)]
  44. pub fn from_serde_json(error: serde_json::Error) -> Self {
  45. Self(JsonValue::String(error.to_string()))
  46. }
  47. }
  48. impl<T: Serialize> From<T> for InvokeError {
  49. #[inline]
  50. fn from(value: T) -> Self {
  51. serde_json::to_value(value)
  52. .map(Self)
  53. .unwrap_or_else(Self::from_serde_json)
  54. }
  55. }
  56. impl From<crate::Error> for InvokeError {
  57. #[inline(always)]
  58. fn from(error: crate::Error) -> Self {
  59. Self(JsonValue::String(error.to_string()))
  60. }
  61. }
  62. /// Response from a [`InvokeMessage`] passed to the [`InvokeResolver`].
  63. #[derive(Debug)]
  64. pub enum InvokeResponse {
  65. /// Resolve the promise.
  66. Ok(JsonValue),
  67. /// Reject the promise.
  68. Err(InvokeError),
  69. }
  70. impl InvokeResponse {
  71. /// Turn a [`InvokeResponse`] back into a serializable result.
  72. #[inline(always)]
  73. pub fn into_result(self) -> Result<JsonValue, JsonValue> {
  74. match self {
  75. Self::Ok(v) => Ok(v),
  76. Self::Err(e) => Err(e.0),
  77. }
  78. }
  79. }
  80. impl<T: Serialize> From<Result<T, InvokeError>> for InvokeResponse {
  81. #[inline]
  82. fn from(result: Result<T, InvokeError>) -> Self {
  83. match result {
  84. Ok(ok) => match serde_json::to_value(ok) {
  85. Ok(value) => Self::Ok(value),
  86. Err(err) => Self::Err(InvokeError::from_serde_json(err)),
  87. },
  88. Err(err) => Self::Err(err),
  89. }
  90. }
  91. }
  92. impl From<InvokeError> for InvokeResponse {
  93. fn from(error: InvokeError) -> Self {
  94. Self::Err(error)
  95. }
  96. }
  97. /// Resolver of a invoke message.
  98. pub struct InvokeResolver<P: Params = DefaultArgs> {
  99. window: Window<P>,
  100. pub(crate) callback: String,
  101. pub(crate) error: String,
  102. }
  103. impl<P: Params> InvokeResolver<P> {
  104. pub(crate) fn new(window: Window<P>, callback: String, error: String) -> Self {
  105. Self {
  106. window,
  107. callback,
  108. error,
  109. }
  110. }
  111. /// Reply to the invoke promise with an async task.
  112. pub fn respond_async<T, F>(self, task: F)
  113. where
  114. T: Serialize,
  115. F: Future<Output = Result<T, InvokeError>> + Send + 'static,
  116. {
  117. crate::async_runtime::spawn(async move {
  118. Self::return_task(self.window, task, self.callback, self.error).await;
  119. });
  120. }
  121. /// Reply to the invoke promise with an async task which is already serialized.
  122. pub fn respond_async_serialized<F>(self, task: F)
  123. where
  124. F: Future<Output = Result<JsonValue, InvokeError>> + Send + 'static,
  125. {
  126. crate::async_runtime::spawn(async move {
  127. Self::return_result(self.window, task.await.into(), self.callback, self.error);
  128. });
  129. }
  130. /// Reply to the invoke promise with a serializable value.
  131. pub fn respond<T: Serialize>(self, value: Result<T, InvokeError>) {
  132. Self::return_result(self.window, value.into(), self.callback, self.error)
  133. }
  134. /// Reply to the invoke promise running the given closure.
  135. pub fn respond_closure<T, F>(self, f: F)
  136. where
  137. T: Serialize,
  138. F: FnOnce() -> Result<T, InvokeError>,
  139. {
  140. Self::return_closure(self.window, f, self.callback, self.error)
  141. }
  142. /// Resolve the invoke promise with a value.
  143. pub fn resolve<T: Serialize>(self, value: T) {
  144. Self::return_result(self.window, Ok(value).into(), self.callback, self.error)
  145. }
  146. /// Reject the invoke promise with a value.
  147. pub fn reject<T: Serialize>(self, value: T) {
  148. Self::return_result(
  149. self.window,
  150. Result::<(), _>::Err(value.into()).into(),
  151. self.callback,
  152. self.error,
  153. )
  154. }
  155. /// Reject the invoke promise with an [`InvokeError`].
  156. pub fn invoke_error(self, error: InvokeError) {
  157. Self::return_result(self.window, error.into(), self.callback, self.error)
  158. }
  159. /// Asynchronously executes the given task
  160. /// and evaluates its Result to the JS promise described by the `success_callback` and `error_callback` function names.
  161. ///
  162. /// If the Result `is_ok()`, the callback will be the `success_callback` function name and the argument will be the Ok value.
  163. /// If the Result `is_err()`, the callback will be the `error_callback` function name and the argument will be the Err value.
  164. pub async fn return_task<T, F>(
  165. window: Window<P>,
  166. task: F,
  167. success_callback: String,
  168. error_callback: String,
  169. ) where
  170. T: Serialize,
  171. F: Future<Output = Result<T, InvokeError>> + Send + 'static,
  172. {
  173. let result = task.await;
  174. Self::return_closure(window, || result, success_callback, error_callback)
  175. }
  176. pub(crate) fn return_closure<T: Serialize, F: FnOnce() -> Result<T, InvokeError>>(
  177. window: Window<P>,
  178. f: F,
  179. success_callback: String,
  180. error_callback: String,
  181. ) {
  182. Self::return_result(window, f().into(), success_callback, error_callback)
  183. }
  184. pub(crate) fn return_result(
  185. window: Window<P>,
  186. response: InvokeResponse,
  187. success_callback: String,
  188. error_callback: String,
  189. ) {
  190. let callback_string = match format_callback_result(
  191. response.into_result(),
  192. success_callback,
  193. error_callback.clone(),
  194. ) {
  195. Ok(callback_string) => callback_string,
  196. Err(e) => format_callback(error_callback, &e.to_string())
  197. .expect("unable to serialize shortcut string to json"),
  198. };
  199. let _ = window.eval(&callback_string);
  200. }
  201. }
  202. /// An invoke message.
  203. pub struct InvokeMessage<P: Params = DefaultArgs> {
  204. /// The window that received the invoke message.
  205. pub(crate) window: Window<P>,
  206. /// Application managed state.
  207. pub(crate) state: Arc<StateManager>,
  208. /// The RPC command.
  209. pub(crate) command: String,
  210. /// The JSON argument passed on the invoke message.
  211. pub(crate) payload: JsonValue,
  212. }
  213. impl<P: Params> InvokeMessage<P> {
  214. /// Create an new [`InvokeMessage`] from a payload send to a window.
  215. pub(crate) fn new(
  216. window: Window<P>,
  217. state: Arc<StateManager>,
  218. command: String,
  219. payload: JsonValue,
  220. ) -> Self {
  221. Self {
  222. window,
  223. state,
  224. command,
  225. payload,
  226. }
  227. }
  228. /// The invoke command.
  229. #[inline(always)]
  230. pub fn command(&self) -> &str {
  231. &self.command
  232. }
  233. /// The window that received the invoke.
  234. #[inline(always)]
  235. pub fn window(&self) -> Window<P> {
  236. self.window.clone()
  237. }
  238. /// A reference to window that received the invoke.
  239. #[inline(always)]
  240. pub fn window_ref(&self) -> &Window<P> {
  241. &self.window
  242. }
  243. /// A reference to the payload the invoke received.
  244. #[inline(always)]
  245. pub fn payload(&self) -> &JsonValue {
  246. &self.payload
  247. }
  248. /// The state manager associated with the application
  249. #[inline(always)]
  250. pub fn state(&self) -> Arc<StateManager> {
  251. self.state.clone()
  252. }
  253. /// A reference to the state manager associated with application.
  254. #[inline(always)]
  255. pub fn state_ref(&self) -> &StateManager {
  256. &self.state
  257. }
  258. }