From db6a72cbddb358142c824fd4f1afacfe466dc218 Mon Sep 17 00:00:00 2001 From: Jonas Kruckenberg Date: Fri, 18 Nov 2022 16:32:38 +0100 Subject: [PATCH] feat: add global_shortcut module --- Cargo.toml | 24 +++--- README.md | 2 +- src/global_shortcut.rs | 164 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 4 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 src/global_shortcut.rs diff --git a/Cargo.toml b/Cargo.toml index 475ba19..1a487c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,35 +1,35 @@ [package] +edition = "2021" name = "tauri-sys" version = "0.1.0" -edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde-wasm-bindgen = "0.4.3" -js-sys = "0.3.59" -serde = { version = "1.0.140", features = ["derive"] } -wasm-bindgen = { version = "0.2.82", features = ["serde_json"] } -wasm-bindgen-futures = "0.4.32" -url = { version = "2.3.1", optional = true, features = ["serde"] } -thiserror = "1.0.37" -semver = { version = "1.0.14", optional = true, features = ["serde"] } +js-sys = "0.3.59" log = "0.4.17" +semver = {version = "1.0.14", optional = true, features = ["serde"]} +serde = {version = "1.0.140", features = ["derive"]} +serde-wasm-bindgen = "0.4.3" +thiserror = "1.0.37" +url = {version = "2.3.1", optional = true, features = ["serde"]} +wasm-bindgen = {version = "0.2.82", features = ["serde_json"]} +wasm-bindgen-futures = "0.4.32" [dev-dependencies] +tauri-sys = {path = ".", features = ["all"]} wasm-bindgen-test = "0.3.33" -tauri-sys = { path = ".", features = ["all"] } -# tauri = "1.1.1" [package.metadata.docs.rs] all-features = true [features] -all = ["app", "clipboard", "event", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path", "updater"] +all = ["app", "clipboard", "event", "mocks", "tauri", "window", "process", "dialog", "os", "notification", "path", "updater", "global_shortcut"] app = ["dep:semver"] clipboard = [] dialog = [] event = [] +global_shortcut = [] mocks = [] tauri = ["dep:url"] window = [] diff --git a/README.md b/README.md index 319604e..5a4959b 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ These API bindings are not completely on-par with `@tauri-apps/api` yet, but her - [x] `dialog` - [x] `event` - [ ] `fs` -- [ ] `global_shortcut` +- [x] `global_shortcut` - [ ] `http` - [x] `mocks` - [x] `notification` diff --git a/src/global_shortcut.rs b/src/global_shortcut.rs new file mode 100644 index 0000000..b0c4381 --- /dev/null +++ b/src/global_shortcut.rs @@ -0,0 +1,164 @@ +//! Register global shortcuts. +//! +//! The APIs must be added to tauri.allowlist.globalShortcut in tauri.conf.json: +//! +//! ```json +//! { +//! "tauri": { +//! "allowlist": { +//! "globalShortcut": { +//! "all": true // enable all global shortcut APIs +//! } +//! } +//! } +//! } +//! ``` +//! It is recommended to allowlist only the APIs you use for optimal bundle size and security. + +use wasm_bindgen::{prelude::Closure, JsValue}; + +/// Determines whether the given shortcut is registered by this application or not. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::global_shortcut::is_registered; +/// +/// # async fn main() -> Result<(), Box> { +/// let registered = is_registered("CommandOrControl+P").await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn is_registered(shortcut: &str) -> crate::Result { + let raw = inner::isRegistered(shortcut).await?; + + Ok(serde_wasm_bindgen::from_value(raw)?) +} + +/// Register a global shortcut. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::global_shortcut::register; +/// use web_sys::console; +/// +/// # async fn main() -> Result<(), Box> { +/// register("CommandOrControl+Shift+C", |_| { +/// console::log_1(&"Shortcut triggered".into()); +/// }).await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn register(shortcut: &str, mut handler: H) -> crate::Result<()> +where + H: FnMut(&str) + 'static, +{ + let closure = Closure::::new(move |raw: JsValue| { + let raw = raw.as_string().unwrap(); + (handler)(raw.as_str()) + }); + + inner::register(shortcut, &closure).await?; + + closure.forget(); + + Ok(()) +} + +/// Register a collection of global shortcuts. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::global_shortcut::register_all; +/// +/// # async fn main() -> Result<(), Box> { +/// let registered = register_all(["CommandOrControl+Shift+C", "Ctrl+Alt+F12"], |shortcut| { +/// console::log_1(&format!("Shortcut {} triggered", shortcut).into()); +/// }).await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn register_all<'a, I, H>(shortcuts: I, mut handler: H) -> crate::Result<()> +where + I: IntoIterator, + H: FnMut(&str) + 'static, +{ + let shortcuts = shortcuts.into_iter().map(JsValue::from_str).collect(); + + let closure = Closure::::new(move |raw: JsValue| { + let raw = raw.as_string().unwrap(); + (handler)(raw.as_str()) + }); + + inner::registerAll(shortcuts, &closure).await?; + + closure.forget(); + + Ok(()) +} + +/// Unregister a global shortcut. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::global_shortcut::unregister; +/// +/// # async fn main() -> Result<(), Box> { +/// unregister("CmdOrControl+Space").await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn unregister(shortcut: &str) -> crate::Result<()> { + inner::unregister(shortcut).await?; + + Ok(()) +} + +/// Unregisters all shortcuts registered by the application. +/// +/// # Example +/// +/// ```rust,no_run +/// use tauri_sys::global_shortcut::unregister_all; +/// +/// # async fn main() -> Result<(), Box> { +/// unregister_all().await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn unregister_all() -> crate::Result<()> { + inner::unregisterAll().await?; + + Ok(()) +} + +mod inner { + use js_sys::Array; + use wasm_bindgen::{ + prelude::{wasm_bindgen, Closure}, + JsValue, + }; + + #[wasm_bindgen(module = "/src/globalShortcut.js")] + extern "C" { + #[wasm_bindgen(catch)] + pub async fn isRegistered(shortcut: &str) -> Result; + #[wasm_bindgen(catch)] + pub async fn register( + shortcut: &str, + handler: &Closure, + ) -> Result<(), JsValue>; + #[wasm_bindgen(catch)] + pub async fn registerAll( + shortcuts: Array, + handler: &Closure, + ) -> Result<(), JsValue>; + #[wasm_bindgen(catch)] + pub async fn unregister(shortcut: &str) -> Result<(), JsValue>; + #[wasm_bindgen(catch)] + pub async fn unregisterAll() -> Result<(), JsValue>; + } +} diff --git a/src/lib.rs b/src/lib.rs index 353cc22..92cb264 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ pub mod clipboard; pub mod dialog; #[cfg(feature = "event")] pub mod event; +#[cfg(feature = "global_shortcut")] +pub mod global_shortcut; #[cfg(feature = "mocks")] pub mod mocks; #[cfg(feature = "notification")]